GIT Merge & Squash

Over the course of my career I’ve encountered many source code control systems as I’m sure many of you have. It seems softwarekind has reached the point where we have whittled all of the contenders down to just a few with git becoming the most popular (at least that’s my understanding). One of git’s virtues is its ability to do branching - where you make a copy of your work, make changes, and either toss it away if its crap (and return to your previous revision) or keep your changes and move on to the next task.

The focus of this article is about one of my favorite features of git. If you are a seasoned git user you can skip this but if you are starting out and want a couple of pointers, then please join me. There are a lot of git commands and each has a myriad options. I am only discussing the git merge command and its squash option. And even with that I’m not going into high detail, mostly because I don’t think it’s necessary to be productive.

Each company’s development environment is different and each has its own rules and workflow. You may find what I write in this article to not fit with your company’s culture, which is fine of course. I think this process that I use is simple and straightforward. It follows closely the standard “git flow” process which is just a series of steps to follow when developing code and using git on a daily basis.

Let’s assume you have a working directory with your source files in it and are on a develop branch. This would be the code that, when built, runs your application with all of the latest features. At this moment in time you are in sync with everyone else on the project.

This is where things can be different from your company. Some places work directly on the master branch, others work on a release number branch, others work on a shared develop branch, which is what I am assuming.

You are tasked to do some new work - some sort of feature. To do this you create a branch. The naming of your branch is, again, a company culture thing. If your company wants you to always push your branch to the remote repository, then its wise to name your feature with a directory so use git checkout -b features/new_search and that is the name I will use.

If you do git status it should show that you have a clean working directory (no changes) and you are on the features/new_search branch. Terrific. So now you can make your changes.

You make some changes over the course of the next few hours, running the code, making sure it works. But the feature isn’t complete; it might take a few more days. You could just walk away for the day, but I recommend that, if you are at a point where you are happy with the code, you commit it to your branch. This way your next changes can be discarded if you go down the wrong path and you won’t need to worry about corrupting something you have working. I believe this is essential and the safest thing you can do. There is nothing more frustrating to have some nicely working code, then spend another hour on the next step and screw it up. If you do commit your code, you can just discard your changes and start over.

This process of moving forward, doing a commit, making more changes, a commit, continues until you have the new_search feature working and tested. You may have made just a single commit or maybe a dozen commits.

At this point you are done with the feature and now its time to merge your changes into the develop branch. This is what I do:

  1. I make sure all of my changes are committed to my branch (features/new_search).

  2. I git checkout develop which replaces my working directory (and feature code) with the version of the application I had a few days ago. This may not be the latest version of the develop branch.

  3. To bring my feature into the develop branch, I do: git merge features/new_search —squash. Remember that you might have many commits on your feature branch. The -squash option removes all of your commits on your branch and reduces all of your changes to a single change (per file). For example, let’s say you have File A and you made changes: ‘apple’ (commit) ‘orange’ (commit) ‘banana’ (commit). The -squash reduces this to ‘apple’ -> ‘banana’. Without the -squash the develop branch would have all of your commits listed; with -squash the develop branch will just have a single commit, which is the next step.

  4. I commit my changes to the develop branch using git commit -m “Added the New Search feature”. When you look at the commits to develop you will see just one commit for your feature.

  5. I do two last things to finish up: I git push my develop branch to the remote repository and git branch -d features/new_search which deletes the branch locally. I do not keep extraneous branches around as I find it confusing later on.

Using -squash is something some companies may frown upon because it removes all of the history of the changes. But without it, your repository is full of minor commits. How many times have you gone through your code, think its fine, do the commit, then realize you forgot to remove some comments or print statements and have to make another commit? If those minor commits are on your branch and you -squash your merge, you do not carry those over. It is a matter of taste, but think by and large, keeping your repository free from miscellaneous changes makes a better repository.

Just a quick jump back to step 2 above. If you are working in a team, there is a good chance that while you have been working on your feature branch, other people have also been working on their features. So before you merge your feature branch into the develop branch, you should pull down any new changes with git pull. Then merge and squash your changes.

The merge and squash after doing a pull should be clean unless your changes also touch files someone else changed. In that case the merge will fail and you have to fix the changes yourself. There are many resources on how best to that along with many programs to help you. Basically you resolve whether to keep your changes or keep the others’ (aka “theirs”) changes.

Be sure to follow your company’s policy on this. Some places will require you to run a bunch of tests before pushing your develop branch; other places have automated this and run tests when a push happens.

I hope you find this light and easy explanation of get merge —squash helpful. I find keeping my repository neat and tidy is very rewarding.

Previous
Previous

Custom Binding with SwiftUI

Next
Next

A Year of SwiftUI