Git Rebase Cleanup Commits

One of the best ways to incorporate rebasing into your workflow is to clean up local, in-progress features. By periodically performing an interactive rebase, you can make sure each commit in your feature is focused and meaningful. This lets you write your code without worrying about breaking it up into isolated commits

Example

Suppose the following branch structure

c0->c4->5 <--master
  ->c1(update1)->c2(update2)->c3(update3) <--feature

To squash c1, c2, c3 into a single new commit with c0 as base, you can do the following

git checkout feature
git rebase -i HEAD~3

In the rebase edit page, you would probably see the following

pick 56ac2b6 update1
pick 4a1c4d9 update2
pick 039bcd2 update3

Change the above to the following

pick 56ac2b6 update1
squash 4a1c4d9 update2
squash 039bcd2 update3

This means: squash c3 (update3) and c2 (update2) into c1 (update1), pick the squashed commit and rebase to c0

Give this new commit a meaningful message (e.g. update1; update2; update3), the graph becomes

c0->c4->c5 <--master
  ->c6(update1; update2; update3) <--feature

Now if the feature branch has already been pushed to remote, you can update the remote branch by doing:

git push origin <branch_name> -f
# or
git push origin +<branch_name>

Another example to demonstrate rebasing only on some commits of the same branch

  1. consider the following, our goal is to merge c1 and c2 into a single commit
c0->c1->c2
  1. git rebase -i c2 will show noop, meaning nothing to be rebased because c2 is already the latest commit
  2. git rebase -i c0, on the other hand, will let you base c1 and c2 into c0
pick c1
pick c2

Example (if you want to re-write the entire feature)

  1. get the current branch name
CURRENT_BRANCH=$(git branch --show-current)
  1. use git merge-base command to find the original base of current branch. The following returns the commit ID of the original base, which you can then pass to git rebase
BASE_COMMIT=$(git merge-base $CURRENT_BRANCH master)
  1. then you can rebase the entire branch into a single commit
git rebase -i $BASE_COMMIT