Long-lived git branches survival guide

Peter Hozák
3 min readMay 21, 2020

--

Chances are that your team is using Trunk Based Development,
or GitHub flow with only one long-lived branch (master). Your life is simple.

Then again, one day, you might find yourself supporting multiple versions of a product. Each version living in a different branch of your git repository (or even in multiple forks). And there are four(-tien) other developers who also contribute daily.

So you already learned all about Merging vs. Rebasing, either just in case™️ or out of necessity.

This article is not about such simple matters.

Following tips are here to keep you sane in your darkest hours, when you burned yourself by a 3-line git command and it still didn’t do what you wanted. Tips to prevent the next time. Tips to survive.

1. Unless you HAVE to, don’t use long-lived branches

It should go without saying, but unless you want to develop 2 independent things, then stick to one master branch and merge your short-lived feature branches ASAP (e.g. daily, after code review). And if you cannot merge the feature branch every day, then at least rebase it to the latest master every morning, to keep it up to date.

Create a new branch for a release only after you need to maintain 2 different versions. Use git tags for release candidates if you need to keep a good track of what is deployed in test environments. Keep in mind that a branch can be created from any commit, not just from HEAD.

2. Don’t mix branches

If you need to create a short-lived branch for a pull request, start it from the correct long-lived branch. Any changes to release/01 should be started from release/01 and not from the newest master (you don’t want to include all changes from master, that’s why you have multiple branches, right? ಠ_ಠ).

If you already made a fix in a branch started from master, then create a new branch from release/01 and cherry pick 🍒 that one commit into the correct branch. Then double check everything in the diff — cherry pick is not a magical operation that will do what you want. Think about it as the +1 part of 3 + 1 vs 2 + 1

3. Fake merge

Sometimes you end up in a situation when you want to synchronize 2 branches without modifying any files, after you manually solved the merge conflicts outside of a git merge command. You might be tempted by -Xtheirs or -Xours merge options, but those would perform a normal merge while skipping conflicts, and we don’t want any change to any file right now.

Our strategy is -s ours.

An example of fake merge of release into master (without changing any file):

git checkout master
git merge -s ours release/01

While you could fake-merge master into release, stop and think again what you were about to do next— do you really want to get into more trouble?

4. The Prime Directive

Finally, remember that this is one of the rare occasions when the end justifies the means —your build process cares only about the current version of the code, not about git history.

Only the code matters, not the journey.

If all else fails, just start over. Make a backup, hard reset everything that is not released yet, and make one good commit at a time until you end up with the desired code in each branch.

Git history is important for the future archeologists (a.k.a. git blame, bisect, …), but not as important as shipping the correct code ¯\_(ツ)_/¯

I am Peter, a software engineer. Everything without a link is just my opinion. https://peter.hozak.info/

--

--