Using Git Rebase to Combine Commits (GitHub for Windows)

Let’s say you have been working in a branch of code for a week, and have checked in your changes several times.  You are now satisfied with the changes, are ready to merge everything back into the main branch.  However, you do not want to maintain all of the interim check-ins that were done during the week.  You only want the cumulative changes to be merged back into the main branch.

Here is how to use Git’s rebase functionality to “squash” all of the commits on your branch into a single commit that can then be merged back into the main branch.  This assumes the use of the tools provided with the GitHub for Windows package, but it should work similarly on other operating systems.

1) Open the Git Shell included with the GitHub for Windows tools.

2) Navigate to your git repository.

3) Use “git status” to make sure you are working on the branch of code that includes the commits that you want to combine.

3) Use “git log master..” to view the commits on the current branch.  (This command assumes you are working on a branch separate from “master”).  Either way, the goal of this is to determine how many commits are going to be squashed together.

4) “git rebase -i HEAD~N”, where N is the number of commits to include in the rebase/squash operation.

5) This will open Notepad with a list of the commits.  Example:

pick fd8adcc Initial check-in of new feature
pick ece5003 Updates to the new feature
pick 7d828d2 Finalized the new feature
# Rebase d96b13b..7d828d2 onto d96b13b
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like “squash”, but discard this commit’s log message
#  x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

6) Assuming you want to collapse all of these commits into a single commit, change the “pick” command in front of every line AFTER THE FIRST LINE to “s” or “squash”.  Each line that has “s” in front of it will be squashed into the line above it.  Notice the comments at the bottom of the file… use them to guide your actions.  Save the file and exit when you are done.  Here is an example file after editing:

pick fd8adcc Initial check-in of new feature
s ece5003 Updates to the new feature
s 7d828d2 Finalized the new feature
# Rebase d96b13b..7d828d2 onto d96b13b
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like “squash”, but discard this commit’s log message
#  x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

7) Git will proceed to implement the squashing of commits.  You’ll see it working with a prompt that looks like “Rebasing (2/3)”.  When done, a new file containing the combined list of files and comments will be opened in Notepad.  Here is an example:

# This is a combination of 3 commits.
# The first commit’s message is:
Initial check-in of new feature
# This is the 2nd commit message:
Updates to the new feature
# This is the 3rd commit message:
Finalized the new feature
# Please enter the commit message for your changes. Lines starting
# with ‘#’ will be ignored, and an empty message aborts the commit.
# rebase in progress; onto d96b13b
# You are currently editing a commit while rebasing branch ‘feature’ on ‘d96b13b’.
#
# Changes to be committed:
#     new file:   project.csproj
#     new file:   parms.cs
#     new file:   processor.cs
#     new file:   program.cs
#     modified:   solution.sln
#

8) Edit this file to contain a new comment for the combined commit (or if you prefer, keep all of the existing comments).  As before, the comments at the bottom of the file can be used as a guide.  Save and exit when you are done.  Here is an example file after editing:

Added the new feature to the solution.
# Please enter the commit message for your changes. Lines starting
# with ‘#’ will be ignored, and an empty message aborts the commit.
# rebase in progress; onto d96b13b
# You are currently editing a commit while rebasing branch ‘feature on ‘d96b13b’.
#
# Changes to be committed:

#     new file:   project.csproj
#     new file:   parms.cs
#     new file:   processor.cs
#     new file:   program.cs
#     modified:   solution.sln
#

9) Rerun “git log master..” to view the new list of commits on the current branch.  If you collapsed everything into a single commit, you should now only see that one commit.

NOTE:  Consider creating a separate “rebase” branch to try this process out the first time you do it.  If you do this, you can use “git diff <branch> <rebase-branch>” to compare the original set of commits to the newly squashed commit and verify that the two branches match.

More information

https://help.github.com/articles/interactive-rebase
http://stackoverflow.com/questions/16974204/git-how-to-get-commit-history-for-just-one-branch
http://www.youtube.com/watch?v=msuJGG2iWjs
http://davidwalsh.name/squash-commits-git

Advertisements

2 Responses to Using Git Rebase to Combine Commits (GitHub for Windows)

  1. Kem Jones says:

    Good information. One slight typo: In step 4, it states:
    4) “git rebase -i HEAD~N”, where N is the number of branches to include in the rebase/squash operation.
    it *should* state:
    4) “git rebase -i HEAD~N”, where N is the number of *commits* to include in the rebase/squash operation.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: