Using Git Interactive Rebase With Feature Branches

The next GIT topic to cover is branching and using interactive rebase before merging the branch back into master. This article will cover a workflow strategy where you create a local branch for a new feature where you can make many small commits. Then before merging and committing to master, use interactive rebase to squash some (or all) of the less meaningful commits, keeping the commits to master more concise and feature focused.

Getting ready

For the examples today, assume you are working on your local branch master and a remote branch origin/master. The origin/master branch is collaborative and frequently committed to by multiple team members. You want to start working on a new feature (MyFeature), so to begin, make sure you have the most up-to-date code:

git fetch origin
git rebase origin/master

How do it…

Create a new feature branch for MyFeature:

git checkout -b MyFeature

GIT should report the following:

Switched to a new branch 'MyFeature'

Work as long as necessary on the branch and make frequent small commits, so rolling back is easy. Also, remember to rebase with master at least once a day:

git fetch origin master
git rebase origin/master

When the feature is complete and ready to be merged into master:

git rebase -i origin/master

An editor will open and all the commits on the branch will be listed. It should look something like:

pick 704c166 adding new file
pick df1ece0 adding another file
pick 226433d making a change
pick d04306a making another change
pick b0c7604 final commit for new feature

Squash all but one commit (unless you want several to be merged into master) and save:

pick 704c166 adding new file
pick df1ece0 adding another file
pick 226433d making a change
pick d04306a making another change
pick b0c7604 final commit for new feature

You will then be prompted to enter a new commit messages for each non-squashed commit (I added the first line to this message, the rest are auto-generated by GIT):

Wiring up and testing MyFeature

# This is a combination of 5 commits.
# The first commit message is:
adding new file

# This is the 2nd commit message:

adding another file

# This is the 3rd commit message:

making a change

# This is the 4th commit message:

making another change

# This is the 5th commit message:

final commit for new feature

Next, go back to master and merge the MyFeature branch:

git checkout master
git rebase origin/master
git merge MyFeature

Lastly, push your changes to the upstream:

git push origin master

How it works…

The strategy here is to do feature work, especially those that will take more than a few hours, in a branch. This keeps the master branch clean, so you can easily switch context to deal with bug fixes. While making many small commits on the branch for easy rollback, be sure to regularly rebase with master. You should not go more than a day without rebasing. This keeps commits on the branch always after those on master (making merging branches back into master trivial).

For example, if MyFeature is branched at commit C3, and work was done on master, while working on the MyFeature branch, the commit tree might look like:

- C1 - C2 - C3 - C4 - C5 - C6 (master)
             \
              C4` - C5` - C6` (MyFeature)

When rebasing to master, the tree changes to:

- C1 - C2 - C3 - C4 - C5 - C6 (master)
                            \
                            C4` - C5` - C6` (MyFeature)

This can be done as many times and necessary. You may have to handle conflicts while rebasing, but these usually only need to be dealt with once. The final interactive rebase will squash all your commits into a single *new* commit, making it look like:

- C1 - C2 - C3 - C4 - C5 - C6 (master)
                            \
                            C7 (MyFeature)

Then when you merge back into master:

- C1 - C2 - C3 - C4 - C5 - C6 - C7 (master)

As far as master is concerned there was only one commit, the one created during the interactive rebase. That said, you do not need to squash all your commits, only the ones that are small and more for ease of development. So, you could merge several commits back into master, even after the interactive rebase. It just depends on your workflow.

Also, rebasing with master in a branch doesn’t work well when you are pushing changes to a remote branch. Each time you rebase your commits get a new hash, which causes your local branch to get out of sync with the remote branch. If multiple users are committing remotely on the branch, you will need to pull from master instead.

There’s more…

A lot of the ideas in this article originated from A Git Workflow for Agile Teams. Check it out for more details on a using GIT in agile teams.