Git branches — rewriting history and avoiding nightmares (Part 1)

Three tips to make using branches less painful and 100% more effective

Claudia Minardi
NEXT Engineering
3 min readJul 3, 2017

--

Branches are an incredibly useful tool when developing new features or refactoring existing modules, but one cannot deny the feeling of dread that rises at the moment of merging a branch into master. What about conflicts? Is the branch good enough to be merged in?

No more! Here are three best practices we use to avoid headaches and conflict nightmares.

1. Small and fast

While working on a branch we produce small commits, much smaller than the ones that would be considered “good” on master. This allows us to exploit interactive rebase (as we’ll explore in a minute).

What can be considered a small commit? Anything from fixing a typo, reordering imports, refactoring a function. We think of the commit we do at this point to be LEGO® blocks for the commit you’ll see on master once this branch is ready to be merged in.

We push the code often, especially when we want the automatic builds to run and deploy the code in our test environment— let them do the hard work.

2. Interactive rebase is the secret

Roughly once per day, we do a couple of interactive rebase sessions, with git rebase -i. Here we update the branch to master, and we can do a few things to make our life easier:

  1. Reorder the commits, so that the “independent cleanups” end up at the end of our commit list — far away from HEAD — and are easier to separate from the rest. For example typo fixes, sun-dry refactorings that have nothing to do with the branch, and so on…
  2. Optionally, we can merge the commits above onto master already, reducing the size of our branch.
  3. Squash or fixup commits that belong together, or need to be attached to a self-standing commit.

For example (considering older commits at the top of the list):

6698a1e Add button to the homepage
4e95b8a Make button red
f4ca895 Add missing unit tests for completely unrelated module
fe6b896 Fix typo in button text

Applying the tips above, this becomes:

f4ca895 Add missing unit tests for completely unrelated module
6698a1e Add red button to the homepage

Now that our branch looks ordered and clean, the changes are force-pushed to Github.

Note: you might want to consider doing git rebase -i origin/master as it avoids the need to update the local master as well, and it reduces the risk of having conflicts once you have to merge.

3. More rebase before you merge — nightmare free!

Before merging to master we do more interactive rebasing, and aggressively try to reduce the amount of self-standing commits to ones that really make sense even in a couple of weeks. If you’ve been keeping up with your daily rebases, this should be a matter of a few minutes!

Using git rebase -i origin/master is necessary at this point, as you need to make sure we are ready to merge our branch on top of the latest from remote.

When the time comes to make the branch a part of the main product, we explicitly fast-forward merge the branch onto master.

Summing it up, from your branch my-awesome-branch:

$ git rebase -i origin/master
$ git checkout master
$ git pull
$ git merge --ff-only my-awesome-branch

Extra: don’t get maimed by your colleagues

When working with other people on the same branch we usually do less rebases, unless we can guarantee that the forced-push will be picked up by other people working on the branch easily. In the worst case this might mean the rebasing will happen only just before merging — less enjoyable than rebasing step by step, but not less effective.

That’s all! You’re ready to start branching like a pro.

Stay tuned for the next part — we have some interactive rebase secrets that you definitely want to hear about.

Happy coding!

Want to learn more about coding? Have a look to our other articles.

--

--