开发者

Evil merges in git - where do they come from?

I've read this question and the answers, but what isn't clear to me is WHO creates the "changes that do not appear in any parent".

Is it the git merge algorithm screwing up?

Or is it because the user has to manually adjust the conflicts to get the thing开发者_如何学C to build, introducing new code which wasn't in either parent?


It is explained in the first comment of the correct answer. You merge without doing a commit (either through conflict or --no-commit) and then add additional changes to the merge before committing.

Note, resolving a merge conflict is not evil, you simply pick code which exists in one or both sides of the conflict. If you add some code which does not exist in either side, you have now turned the merge evil.


That comment was an interesting illustration of how an "evil" merge can occur:

Sometimes the minimal manual resolution results in lines that weren't there.
Eg.

  • 'ours' changes the name of a function,
  • 'theirs' changes the return value,
  • we need a method with new name and new return val).

Is this an evil one? IOW: are evil merges sometimes necessary

Note that this article mentions "evil merges" in another context (unintented merges), and advocate for always rebasing, rather than merging... but that would ignore the danger of a git pull --rebase.


Junio C Hamano, main maintainer for git, precise in his April 2013 blog post:

A canonical example of where "evil merge" happens in real life (and is a good thing) is to adjust for semantic conflicts. It almost never have anything to do with textual conflicts.

(typically an API change, for instance: you add a parameter, while another developer add a call to that function... but without any extra parameter)

That means you have to fix the semantic conflict (like a missing argument for a function which now takes one) at the time of the merge, which means creating a line which:

  • doesn't exist in your code (where you did correctly made API changes)
  • doesn't exist in the remote branch you are now merging (where the other developer wasn't aware of the API change)

That makes the merge an "evil merge".

With "git log -c/--cc", such a line will show with double-plus in the multi-way patch output to show that "this did not exist in either parent".

From git log man page:

Diff Formatting

-c::

With this option, diff output for a merge commit shows the differences from each of the parents to the merge result simultaneously instead of showing pairwise diff between a parent and the result one at a time.
Furthermore, it lists only files which were modified from all parents.


It happens when a developer has a merge conflict that he must manually fix, and in doing so, he changes code that is not related to the merge conflict itself. Git's merging algorithms will not insert unrelated, "evil" code changes by itself.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜