0

I'm wondering what's the bet way to integrate "Hotfixes" into the Git workflow.

It seems that all recommendations for Git workflow tutorials recommend that Hotfixes are both pulled to the Master branch and the development/feature branches.

However, what about hotfixes which fix a state of production which was replaced/changed/re-factored in the development branch anyway?

To give you an idea, what I mean:

Say, you deployed the following code to production

function fetchDogs() {
   return cats;
}

Two weeks later you notice that you've mixed up cats and dogs. You create a hotfix branch for it, replace cats with dogs, push it to master and deploy it. So, far so good.

However, imagine that in the meanwhile you've noticed that the structure of your function is inefficient anyway, so on your development branch you had changed it to:

function fetchAnimals(whichAnimal) {
       return animals[whichAnimal];
    }

However, you cannot deploy that since it is not yet tested (or for whatever reason).

So, if you pull the hotfix to the development branch, you'll probably get a complete unnecessary and superfluous merge conflict. (And it happened too often in my projects that merge conflicts not solved carefully enough lead to unwanted artifacts in the code.)

If, however, you don't pull it, you cannot push to master anymore.

How to solve such situations?

(After having written my question I realized that this question How should gitflow hotfixes work? deals probably with the very same problem. Since, however, there is no real answer to that one, I though I'd give it a try anyway.)

cis
  • 1,053
  • 10
  • 32
  • To me it seems like very valid conflict. You may have done the refactoring which fixed the issue, or you could still be calling somewhere `fetchAnimals(cats)` where you mean to get dogs, or you did not do any refactoring at all but added, for example, logging into the `fetchDogs()`. You cannot know it until you see the actual texts which conflicted. – max630 Aug 17 '17 at 12:57

1 Answers1

1

The act of merging does several things.

First, the obvious: By default it applies the textual changes from (in this case) the hotfix to (in this case) the dev branch.

Second, as you allude, it helps git understand that the changes that were made by (in this case) the hotfix are accounted for in (in this case) the dev branch.

But maybe the most important thing it does: it puts the code changes made on the hotfix (since the hitfix/dev merge base) side-by-side with the changes made on dev (since the merge base) and provides an opportunity to review the results and ensure that the changes made in the hotfix really are in fact accounted for on dev.

I think of this last point as the logical merge operation, whereas the mixing of textual changes is just one physical operation that typically accomplishes that task.

Now, you object that if the merge is unnecessary, and someone resolves the merge incorrectly, this can introduce new bugs. Well, ok... but here's another way to look at it. Analyzing the changes in dev and the changes in the hotfix, and deciding that no physical merge is necessary, is just another strategy for performing the logical merge. And, because your analysis might not take everything into account, this strategy also might admit bugs. (And those are likely to be embarrassing bugs because you already fixed them.) And beyond that it has two disadvantages compared to doing the physical merge:

First (again as you note) it doesn't give git a way to know that the hotfix is accounted for in dev. Merging the hotfix into dev has documentary value, even if you perform the merge using the ours strategy (i.e. ignoring the hotfix altogether).

Second, the merge into dev has implications for testing. A hotfix by its nature must introduce at least one new test case. That should be merged into your codebase even if none of the production code from the hotfix is still relevant. (And if refactoring changes how the test case needs to be written, that's part of the merge.) Moreover, the merge commit needs to be run through the full test suite (which should also negate any concern that poor merge work would introduce bugs at this point).

Bottom line is, if your testing is loose enough to falsify any part of what I just said, then worrying about how best to merge hotfixes is just arguing about what color to make the deck chairs on the Titanic.

The last potential objection I can think of would be the so-called "evil merge". If somehow a hotfix is obviated by later changes to dev and yet a default merge would successfully auto-resolve (which I find highly unlikely, but for the sake of argument...), then producing a non-default merge (by using a strategy like ours, or by amending the merge commit, or by using --no-commit, ...) can cause trouble down the line with some operations. The biggest concern would be rebasing, and in this context I don't think that's likely to be an issue. But if it worries you, you could always complete the auto-merge and then use a subsequent commit to apply the "correct" merged state.

Mark Adelsberger
  • 32,904
  • 2
  • 24
  • 41