You've been working on your great new feature for a few days, and the feature branch is finally ready to be merged in to the master branch! However, you've made dozens of commits while making the feature, which would make it tricky to unmerge if something goes wrong, or to track down exactly where a bug was added. Alternatively, if this is a hot fix to be merged straight in to master, then a single commit is much easier to cherry-pick.
A good way to get around this is to squash all the commits in your feature branch into one commit before you merge; this is (fairly) simple to do in Git.
On your feature branch, run git rebase -i HEAD~5
, where 5 is the number of commits in your branch which you'd like to squash down. Note: the -i
flag is important!
This will then show you a list of the last commits going back to the number you specified (eg the last 5 commits). This will usually be opened in Vim (depending on your OS), which has it's own unique commands, where you can choose what to do with the list of commits.
pick dd897aa Setting up unit tests pick 92f6eac Adding tests for powerups pick 1ccedc4 Draw lightning pick 9372180 Glow filter pick 7f87a67 Lightning ooOOoo # Rebase c49dc2a..7f87a67 onto c49dc2a (5 command(s)) # # 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
You'll see a screen like the one above, which lists out the commit SHA hashes along with the commit message (this screen is from commits to my runner game), and also shows you commands to run on the commits.
Generally, I like to use the first commit as the base, so I leave that as pick
, then change the rest to fixup
(f): this keeps all the commits, but only shows one commit in the log, with the message from the first commit (with pick
). If you want to rewrite the message, use reword
(r). If you don't want the commit to be used at all in this squashing (if you've included too many commits from the history), then delete the entire line.
r dd897aa Adding lightning powerup f 92f6eac Adding tests for powerups f 1ccedc4 Draw lightning f 9372180 Glow filter f 7f87a67 Lightning ooOOoo
Once you're happy with your commits, save and exit (Vim: Esc, :wq
) and the commits will be squashed down. You'll then need to force push your branch, since you've rewritten Git's history for this branch. Once that's done, you can easily merge your squashed feature branch into the master branch, where only one commit will appear.