Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save TheBestPessimist/ebe881003cb895d8579555bf66e4603d to your computer and use it in GitHub Desktop.
Save TheBestPessimist/ebe881003cb895d8579555bf66e4603d to your computer and use it in GitHub Desktop.
Git branching workflow when you have big and interdependent branches

The key for our workflow now is (imo) the following settings in gitlab/repository/settings/Merge Requests:

  • Merge method: Merge commit with semi-linear history.
    You want to use this one because it forces you that before a merge into master, your branch contains the latest master commit. This helps with ordering the commit history in intellij :).
  • Squash commits when merging: Allow
    Some branches dont need to have the history of all the commits, so the branch developer may chose this option in the merge request. It is unchecked by default, but the dev has the option to use it. Use your judgement.
  • Merge commit message template:
Merge branch '%{source_branch}' into '%{target_branch}'

%{title}

%{description}

%{issues}

See merge request %{url}

I like this template and it helps a lot when you need to track why a change happened. You have title of the MR, description, in which you can give as many details as needed, the jira issues and also the FULL url to the MR. This makes accessing the MR from intellij a click away (in case you want to check the review comments, or whatever).

Now for an example:

Note: this example is about big and interdependent branches where rebasing is a PITA. Smaller branches (in terms of development time, number of commits or number of changes) can do whatever they want.

say you have B1, B2, B3 and master with their dependencies:

  • B1 depends on master
  • B2 depends on B1
  • B3 depends on B2

during development, of your branches, always use merge and not rebase:

  • merge master into B1 afterwards (or as needed)
  • merge B1 into B2 afterwards (or as needed)
  • merge B2 into B3

this makes your updates (to your upstream branch) much easier than rebasing because all the existing commits are already there the next time you merge. i cannot stress it enough how much easier!

When your branch (say B1) is ready for review, do the review, do all the fixes, merge master just like before (if needed), then finally merge your MR into master without squashing.
It is important to not squash, because B2 and B3 already have almost all the commits from B1 (and master), so next time you merge master into B2, then B2 into B3 you will have much less conflicts to solve (ie. much less friction)

Now continue working on B2 and B3, merging them into each other as needed.

Key with big branches is:

  • use merge
  • do not rebase
  • do not squash your commits
  • do not rewrite your commit hashes

Obviously, if you force push B1 after you already merged B1 into B2, then you'll have rewritten history, so some conflicts will appear. On the other hand, if you didnt yet merge the "force pushed" changes into B2, then you're free to do whatever.

It is true the by using merge, you won't have such a nice history, as you'll have all the noise from all the master/BX merges, but it makes your development time so much easier.
It remains for you to decide what is more important:

  • the rebase approach: having an easy to follow -linear- git history after the merge, or
  • the merge approach: having a potentially harder (but not very hard because we're enforcing the Merge method) -non-linear- git history but with a much easier time during development.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment