-1

We have been trying git flow in our team. We create release branch base off of develop branch. Then we merge release branch to develop and master after release. We have made several releases so far without hotfix.

Now, we just had an incident that needed a hotfix (first hotfix). so we created hotfix branch based off of master. We merged hotfix branch to master, it was all good. Then we tried to merge hotfix branch to develop, and diff shows old changes being reintroduced to develop. For example, there are files that should have been deleted but were re-added into develop after merge. Prior to merging, both staging and master are the same (no diff whatsoever).

Any idea what is causing this? I wanted to show sample history/graph but our history is very cluttered due to merges.

  • Update: it turns out there are differences between develop and master when I do `git diff develop master`. Also when I compare branches master -> develop in Gitlab, it shows differences, but when comparing develop -> master, no diff. Very odd. – Jerome Ortega May 04 '21 at 14:54

1 Answers1

1

Any idea what is causing this?

The choice of merge base commit, of course. This choice is not yours: Git makes it automatically, based on the commit graph. That's why this step:

so we created hotfix branch based off of master

was probably the founding error (or "root cause", if you prefer).

You can see which commits Git considers to be the merge base(s) for develop and master using:

git merge-base --all develop master

This will print out one or more commit hash IDs.1 If it prints just one hash ID—which is the usual case—then that one hash ID is the hash ID of the merge base commit. If it prints two or more, Git will construct a merge base (for git-merge-recursive anyway) by merging the listed commits; these situations are tricky.

Remember that git merge is all about combining changes, yet Git does not store changes at all. Git stores snapshots: each commit holds a full snapshot of every file, as a sort of frozen-in-time archive, saying that this is how the project is at this (snapshot) time. The only way to turn snapshots into changes is to take at least two snapshots and compare them, as if playing a game of Spot the Difference.

Spotting the differences between the two branch tips (master and develop) is not useful, because applying those differences to one of the branch tips would just produce the other snapshot. (In which case, why are we even bothering with branches?) So that's not how merge works.

Instead, merge finds a snapshot that is somewhere in the past, back before master and develop diverged. By comparing that snapshot with the one at the end of master, Git can see what has changed in master. By comparing that same snapshot with the one at the end of develop, Git can see what has changed in develop. And then, Git can combine these two sets of changes, so as to keep your changes, but add their changes as well.

This process is simple—well, relatively simple—algorithmically (though a lot of work in practice, which is why we have the computer do it). In some cases it's too simple, and produces the wrong results. Yours would appear to be one of those cases.

If you find the commit where the bug itself is introduced (some point in the past, perhaps the distant past) and make a branch where you fix that bug right after its introduction, you can then merge this branch into both master and develop. The changes from this branch's merge base, with either master or develop, to this branch's tip will be just the fix. The changes from this merge base to the tip of master, or the tip of develop, will be everything else that happened. So merging this branch into both master and develop will typically produce the correct result, without introducing other, unwanted changes. But that's often more difficult—sometimes much more difficult—than just making a hotfix branch for master. So the choice is yours.

You could consider using git cherry-pick as a way to copy the hotfix to the develop branch. Cherry-picking has its own hazards—for instance, if the hotfix proves to have its own bug(s), now you need to fix it twice—but it's another tool in the shop. Git is a big shop with a lot of tools. Pick the correct saw, file, hammer, plane, screwdriver, drill, and so on, and you'll get a lot of good things done. Pick the wrong one and ... well...


1It could potentially print none at all, if the histories were unrelated, but in that case you would have seen an error about unrelated histories.

torek
  • 330,127
  • 43
  • 437
  • 552