If you’re writing code in 2019, then chances are, you’re also using Git. Git is the most famous version control system in-use today. It was developed in 2005 by Linus Torvalds, inventor of the Linux operating system, and is widely-used by developers in order to properly maintain source code. By using Git, developers keep a history of changes made to code throughout the development lifecycle and can revert to previous versions, if needed.
One of the most common mantras you are introduced to when beginning to use git is: Commit early and commit often. By committing often, you effectively save a working version of the source code, or application, after each substantial change. This is good practice, as you capture a snapshot of the code at each point and can safely revert to a previous working version if things go haywire. For complex changes, committing often means that the project’s git log (a log of all commits performed) may be littered with many commits. This isn’t a functional problem, as the number of commits associated with a pull request (PR) does not affect how the code will end up working. It can be summed up as a matter of aesthetics and efficiency. The git log is available to all developers working on the project, and can be used to obtain a brief summary of all major changes over time. As a result, if there are too many commits to review, the log can grow to an unreasonably large size and not be a true representation of the major changes made to the application. For instance, a developer tasked with adding email functionality to an application might make x-number of commits during development. They might commit after having added the initial function, commit again after some unit-testing, and commit again after final code cleanup. Those 3 commits can, instead, be summed up as 1, with a single meaningful message like, “add email functionality to application”. Another reason for this is also that the person reviewing the PR does not concern themselves with how many changes you needed to make before you got it working, they are only concerned with the task at hand, which, in this case, was to add email functionality.
In this scenario, in order to revise the git log before merging the PR, the developer can squash the all the commits associated with the change into a single commit. By squashing, you keep all the changes but instead of having multiple commits, they are compressed into a single commit with one meaningful message, which is what we are trying to achieve.
Consider this — the developer has created 3 commits on a local branch but needs to squash those three commits into 1. Here’s how they would do so:
- While on the local branch, in the console window, enter the following command (replacing the number “3” with the total number of commits you wish to squash into 1):
git rebase -i HEAD~3
2. This would open a VIM window showing the last three commits. In this window, press i to begin editing. Now that you can edit, you want to change two of the commits to “squash” and only “pick” one. Normally, we would choose to “pick”, or keep, the first commit, and “squash” the last two changes into this commit. To do so, go to the line of each of the more recent commits and change the command at the beginning of the line to “squash” or “s”. In order to save these changes, press Enter, then ESC and enter :wq. Your changes should look as follows:
3. You will now be presented with a new screen where you can edit the commit messages to keep associated with the newly-squashed commit. Similarly, press i to edit the messages. Normally, only one of the commit messages (the first one) would be kept. It should also be a meaningful message that fully describes the change in its entirety. Save the changes (Enter->ESC->:wq) and you should now be back in the console.
4. Finally, in order to push the newly-squashed commit to GitHub (if you are using it), you will need to force the push. In order to do so, use:
git push -u origin <your branch> -f
Now, you should only see a single commit associated with your PR. You will have effectively squashed all commits into a single, meaningful commit with a single message to describe the change being made.
Important to note is that when contributing to Open Source applications, many (or most) of the application’s admins will not accept your changes if commits are not properly squashed, as they would risk littering the project’s history with a multitude of redundant commit messages. This might not seem like a very important task when working with smaller, in-house, projects, but imagine how large a git log can get if every contributor to the project provides more commits than needed. It would surely become unreadable and lose its value.
I hope you found this helpful! Take Care!