3

Our long running git branches are Master, UAT, and Prod such that new functionality is worked on and committed initially to Master, promoted to UAT (when ready for UAT) then promoted to Prod (when ready for Production). We now need the ability to create hotfixes in production. We are planning to create a Hotfix branch that links up with the Prod branch. In addition to being long running, these branches are separate from each other in that merges are done using "non-fast-forward" merges to keep the branches separate (so that we can see easily what activity has happened on each branch, e.g. a code promotion from Master to UAT, etc).

The following shows the flow of commits for one regular development release which ended up needing a hotfix. Master has the majority of commits as development is happening all the time. UAT and Prod only have commits that represent code promotions. When a hotfix is needed, we merge from prod to hotfix, make the change on the hotfix branch, test it in a hotfix environment, then merge it into prod.

hotfix ----------------------o-o----------   [1 commit for the merge prod->hotfix to get the latest state of prod into the hotfix environment, 1 commit of a bugfix to the hotfix environment]
prod   --------------------o-----o--------   [1 commit for the promotion uat-> prod to get the latest uat-tested code into prod, 1 commit for the promotion of the bugfix hotfix->prod]
uat    -----------------o-----------------   [1 commit for the promotion of master->uat of 4 master commits]
master --o---o---o---o----o-o--o---o-o--o-   [10 commits of new functionality]

Note after a hotfix, the hotfix change is manually incorporated into the master branch. This is because depending on the time the hotfix went out and the state of the current development line (it could be months later), the code could be too divergent between Master and Hotfix, and an automatic merge from Hotfix to Master may not make sense. Because of this, for the merge from UAT to PROD, from PROD to HOTFIX, and from HOTFIX to PROD, we will be NOT be doing a regular git merge, but will instead use the git merge -s theirs strategy as documented here: git command for making one branch like another (We will specifically be doing simulation #3).

What this strategy does is say "please merge in all changes from upstream into downstream and wipe out the state of downstream and replace it with exactly what is coming from the upstream". So when we go from UAT to PROD using this strategy we basically say "make PROD look EXACTLY like UAT". This ensures that what gets into Production is exactly the state of the code that was in UAT.

Is the git merge -s theirs strategy the right way to do this sort of a merge strategy when you have two branches bringing in changes into production (one for regular releases and one for hotfixes) like this?

If we had no hotfix branch, we would simply do a regular (non-fast-forward) merge from master to uat to prod and not use the git merge -s theirs strategy, as it would not be needed.

Community
  • 1
  • 1
BestPractices
  • 12,738
  • 29
  • 96
  • 140

2 Answers2

1

You have three options:

  • either you just reset your branch to the new version. (Which seems to be no option in your case.)
  • you use your "theirs strategy" to tell git "throw away the old version and replace it with the new one" (but git does not support this easily)
  • or you "invalidate" the hotfix change for master by merging PROD to master with the --ours option.

If a regular merge from PROD to master is possible, do it. Otherwise merge with --ours and manually do the corresponding changes on master.

michas
  • 25,361
  • 15
  • 76
  • 121
  • Our long running branches need to be kept separate -- we dont want the branches to actually merge (point at the same commits). We are following a strategy for git branching like the one here: http://nvie.com/posts/a-successful-git-branching-model/ that leverages the --no-ff merge option to keep branches separate. So while we want to make PROD look exactly like UAT, we dont want to make PROD point at the same branch line as UAT. – BestPractices Mar 02 '13 at 19:35
  • Also note that we can't be assured that the hotfix as introduced through the HOTFIX branch then PROD is the same version/form as the fix that is needed on the MASTER branch. The new development on MASTER might have drastically altered the code in such a way that the fix as introduced on HOTFIX could be completely wrong when merged with the MASTER code line. So we dont want anything from HOTFIX that got promoted to PROD to be merged with something coming from MASTER (through UAT). – BestPractices Mar 02 '13 at 19:37
  • you fix a defect both in hotfix and in master. if you merge both branches (by merging both to prod) you get both fixes at the same time. This is pretty much not what you want. - you probably should merge `prod` to `master` after merging `hotfix` to `prod`. in this case you can solve the conflict on `master` and the merge from `master` (via `uat`) to `prod` is a ff and therefore no problem any longer. – michas Mar 02 '13 at 19:49
  • I would agree if we were doing hotfixes soon after a release. we might do a hotfix months later where master is quite divergent from prod and hotfix (files have been deleted, moved etc). please correct me if i'm wrong, but i'm thinking my approach is the safest approach when dealing with this situation. i could see trying the traditional merge approach having the risk that someone needs to validate the merge from prod to master and they could miss seeing something that got merged incorrectly because prod and master had significantly diverged. – BestPractices Mar 02 '13 at 20:10
  • Either you do a reset, or you have to do a merge at some point. - If you go for the merge, you can do the merge on master or on prod. Doing it a master is probably much safer than doing it on prod. - But I still would suggest the reset approach. If you have a branch with only one commit every few month and commits from both directions, you will get in trouble. - You really have to choose a merging strategy which fits you way of working. – michas Mar 02 '13 at 20:18
  • I think the complexity (difference) comes in the fact that we have this long running hotfix branch. If we were constructing this hotfix branch off of prod every time we did a hotfix, I could see doing what you are suggesting. However, because hotfix is a long running branch (it has its own series of commits and is only tied to prod through non-fast-forward merge commits), we must do this git merge -theirs strategy to ensure that hotfix matches prod exactly when we go to make our hotfix. – BestPractices Mar 02 '13 at 20:25
  • You could also do an "ours strategy" for merging from prod to master. But be aware that both strategies do *not* ensure that branches match exactly! – michas Mar 02 '13 at 20:36
  • Funny, I just came to that same alternative -- doing an ours strategy from prod to master. Can you elaborate on why neither strategy would ensure that the branches match exactly? It seems like your suggestion of the ours strategy gets me what I need. lets say that i did master->uat->prod, a month goes by so lots of commits to master, then prod->hotfix, then hotfix to prod (introduced a fix), then prod to master (ours strategy), then manually introduce the hotfix on master, then a new release from master to uat to prod. that's basically what i want. does that sound right to you? – BestPractices Mar 02 '13 at 20:40
  • sounds ok. but this ours/theirs strategy only works for any conflicts noticed by git. If git is able to incorporate a change without a conflict it will do so. - independent of the strategy. Therefore such a merge will usually change your code. (and for such old branches probably in a intended way.) That's why this kind of merges are dangerous. (But discussion gets long, let's switch to chat for more...) – michas Mar 02 '13 at 20:51
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/25435/discussion-between-bestpractices-and-michas) – BestPractices Mar 02 '13 at 20:54
0

Please think about your branching strategy. A strategy which is perfect for one kind of project might be a real burden for another project.

In your case I would suggest one development branch (e.g. master) with the normal develpment and for each release a separate branch (name based on the release).

The release branch starts at master and enters UAT. There minor fixes can be applied for issues found at this phase. Afterward it enters production, where any hotfixes can be applied directly.

There is really no good reason to link commits of two different releases in your case.

michas
  • 25,361
  • 15
  • 76
  • 121