Learning to make appropriate use of
git rebase can help you ensure your git commit log makes sense and is easy to follow. It is also important if you want to use commands like
I recently had to make 47 commits in order to debug an issue. I could only test my changes inside a Heroku private space due to IP whitelisting. So commit after commit was pushed to Heroku, but I never pushed any of those commits to GitHub. Forcing a push to Heroku is necessary from time to time, but it is rarely permissible to do the same to GitHub or wherever your repository is stored.
Today I was able to go in and do an interactive rebase to take those 47 commits and combine them into a single commit with a nice log message and push that up to GitHub. One small thing I did that was very helpful was to consistently start the commit message for every one of those debugging commits with
[DEBUG]. When I was rebasing I was able to clearly see where my debugging work started and didn’t have to worry about how I named my commits. Below I’ll take you through a simple example showing how I rebased things.
Let us suppose you had a situation like mine and were debugging issues on Heroku and had to keep pushing commits. You had better luck with your debugging and only made 10 commits, but you don’t really need everyone to see each step you went through in debugging.
To start with our commit log looks like this:
> git log --oneline b481c12 (HEAD -> feature-cool-stuff, heroku/master) [DEBUG] Remove debugging code b47a33f [DEBUG] Lock package2 version fdf7e4f [DEBUG] Downgrade package2, Upgrade package1 c8a3a97 [DEBUG] Downgrade package1 ccdcda3 [DEBUG] Tweak even more 723e090 [DEBUG] Tweak complex function 23f4f6e [DEBUG] Moar logging! 39c00f8 [DEBUG] console.log not console.olg 749df59 [DEBUG] Add even more log output 2a16981 [DEBUG] Add console debugging statements e2399fe (origin/feature-cool-stuff) Upgrade packages ....
Next we will run
git rebase -i to begin an interactive rebase on our current branch. That will display this in an editor:
pick e2399fe Upgrade packages pick 2a16981 [DEBUG] Add console debugging statements pick 749df59 [DEBUG] Add even more log output pick 39c00f8 [DEBUG] console.log not console.olg pick 23f4f6e [DEBUG] Moar logging! pick 723e090 [DEBUG] Tweak complex function pick ccdcda3 [DEBUG] Tweak even more pick c8a3a97 [DEBUG] Downgrade package1 pick fdf7e4f [DEBUG] Downgrade package2, Upgrade package1 pick b47a33f [DEBUG] Lock package2 version pick b481c12 [DEBUG] Remove debugging code # Rebase e2399fe.. b481c12 onto e2399fe (11 commands) # # Commands: # p, pick <commit> = use commit # r, reword <commit> = use commit, but edit the commit message # e, edit <commit> = use commit, but stop for amending # s, squash <commit> = use commit, but meld into previous commit # f, fixup <commit> = like "squash", but discard this commit's log message # x, exec <command> = run command (the rest of the line) using shell # d, drop <commit> = remove commit # l, label <label> = label current HEAD with a name # t, reset <label> = reset HEAD to a label # m, merge [-C <commit> | -c <commit>] <label> [# <oneline>] # . create a merge commit using the original merge commit's # . message (or the oneline, if no original merge commit was # . specified). Use -c <commit> to reword the commit message. # # 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
The command for the first debug commit should be
reword. All the rest should be changed to have the
fixup command. This combines all the debug commits into one, ignoring their original commit messages, and allow me to set the end message.
pick e2399fe Upgrade packages reword 2a16981 [DEBUG] Add console debugging statements fixup 749df59 [DEBUG] Add even more log output fixup 39c00f8 [DEBUG] console.log not console.olg fixup 23f4f6e [DEBUG] Moar logging! fixup 723e090 [DEBUG] Tweak complex function fixup ccdcda3 [DEBUG] Tweak even more fixup c8a3a97 [DEBUG] Downgrade package1 fixup fdf7e4f [DEBUG] Downgrade package2, Upgrade package1 fixup b47a33f [DEBUG] Lock package2 version fixup b481c12 [DEBUG] Remove debugging code
After saving and exiting the editor I was presented with a commit message that I changed to reflect what the resulting commit actually contained. After saving and exiting that the rebase continued to execute until I was left with a much simpler commit log.
> git log --oneline b4fac12 (HEAD -> feature-cool-stuff) Fix bugs caused by package upgrade e2399fe (origin/feature-cool-stuff) Upgrade packages ....
Rebasing can be a dangerous task if you are careless or don’t understand what you are doing, but with a bit of time and knowledge, you can make use of this powerful feature.