Let’s paint a scenario. Our website has one main repo. Ok, ok, Git is a dCVS, we get it, just go with me on this:
- One main repo.
- We want to create a new feature on our website.
- We don’t want a million trivial commits in our tree on the master branch because we want master to be tidy.
- We also want to keep our repo compact and useful, at least in terms of re-usability.
So, first we need to create a new branch to work on our feature. My local repo is on the master branch. Obviously, you can create a local branch if you like. For me, master is fine and these changes are all happening on the server side.
$ git checkout -b new_feature
Ok, that will create a new branch called new_feature and check it out, so that we are now working on the new branch. You can always see what branch you’re on with the following command:
$ git branch
The branch with a * on the left is your current branch. So, we made a new branch and we have checked it out. Now we can develop our feature and push as many commits to this branch as we like. Obviously, sensibility is called for! 20 commits an hour equals bad.
Because I’m working on my master branch locally, I certainly don’t want to muddy the tree by adding tons of tiny commits. If you work like that, make a new branch locally! Otherwise, the whole reason for this article becomes null and void!
Now, it’s 3 days later and we have created 50 new commits. Our feature is complete and now we want to merge our changes into the master branch and continue on with our lives. However, we don’t want all the tiny commits and certainly not the commit messages muddying up the tree. I know, we’ll use a squash merge!
First, switch to the master branch because we are merging our changes from the new_feature branch into the master branch.
$ git checkout master
$ git merge --squash new_feature
$ git commit -v
What is going on here is really simple:
- We switched to (checked out) master branch. Duh!
- We merged our whole new_feature branch into master.
- Using the –squash operator, we basically told Git to consider this as if it were a single commit. So all the tiny in-betweens will be discarded and we pull in a large chunk of code from the head of the branch as a single change in time.
- We commit all the new changes to the master branch.
Take the time to write a valuable, detailed commit message. Maybe you know what went on, but future colleagues have only these messages and your bad reputation to decipher.
Note that this will merge your changes into the master branch, but it will not delete the new_feature branch. You will need to do that once you are ready.
If the –squash option seems like hitting a pin with a sledgehammer, it kinda is, but it’s very useful for feature changes where there will be a lot of small commits. Bear in mind that this technique will mean your history will contain master branch, pre-new_feature branch, and then straight to master branch, post-new_feature… a single step only.
All the more reason to take time writing a meaningful commit message!