即使合并后文件中存在冲突标记,为什么git mergetool也没有显示冲突?

I’m checked out on feature/my-branch and running git merge dev. The conflict markers added to the file are:

<<<<<<< HEAD
    let foo = "foo"
    let bar = "bar"
||||||| merged common ancestors
    let baz = "baz"
    let bar = "bar"
=======
    let baz = "baz"
    let qux = "qux"
>>>>>>> dev

I then run git mergetool. I have p4mergetool set as my mergetool and it seems to be working. My .gitconfig:

[merge]
    tool = p4mergetool
    conflictstyle = diff3
[mergetool "p4mergetool"]
    cmd = /Applications/p4merge.app/Contents/Resources/launchp4merge $PWD/$BASE $PWD/$REMOTE $PWD/$LOCAL $PWD/$MERGED
    trustExitCode = true

The git mergetool auto resolves the above conflict (0 conflicts shown in the tool) as:

let foo = "foo"
let qux = "qux"

这样做很有意义:即使HEAD和dev发生冲突,我们也可以看到一个分支更新了一行,另一分支更新了另一行。因此,我们可能可以假设我们想要的。

我的问题是:

  1. Is there a way to run/configure git-mergetool or p4mergetool specifically to NOT make this assumption and still show a conflict?
  2. Do I need to run both commands:

    git merge dev
    git mergetool
    

    to have this conflict solved this automatically? I.e. produce the output:

    let foo = "foo"
    let qux = "qux"
    

Said another way: is there a git merge strategy/arguments that I can use to simply run the merge command to produce:

let foo = "foo"
let qux = "qux"
评论
  • 惊魂者
    惊魂者 回复
    这样做很有意义:即使HEAD和dev发生冲突,我们也可以看到一个分支更新了一行,另一分支更新了另一行。因此,我们可能可以假设我们想要的。

    没错

    1. Is there a way to run/configure git-mergetool or p4mergetool specifically to NOT make this assumption and still show a conflict?

    git mergetool does not make the assumption, so we can conclude that p4mergetool must be the one doing it. I don't have p4mergetool, though, so I don't know if it has a configuration knob to change this.

    我需要同时运行两个命令吗?

    是的:Git自己的合并有点愚蠢,只是注意到,天哪,左侧的此更改范围邻接(触摸)或重叠右侧的其他更改范围,因此我们称其为冲突并由用户处理。

    What git mergetool does is extract the three files—merge base, left or local or --ours, and right or remote or --theirs versions of some file—and run some other, non-Git program on the three files. When that program finishes, git mergetool can either trust its exit code to decide whether the tool itself merged the files correctly, or run some file comparisons, or just ask you directly: is the work-tree copy of the file now the correct merged copy?

    If the work-tree copy is now the correct final result (or at least git mergetool believes this), git mergetool runs git add, which marks the conflict as being resolved.1 Otherwise, it leaves the conflict in place.

    (我倾向于只在编辑器中解决合并冲突。)

    1A file is unmerged if there are any copies of it in any nonzero index slots. A file is merged if there is one copy of it, in slot zero—the normal slot number. Except using some of Git's low-level diagnostic-ish commands (git ls-index --stage, really), you can't actually see these staging slot numbers, but git status calls the file unmerged and tells you whether it is in all three slots (UU) or in just the left or right one (UD and DU respectively). I'm not sure off hand what git status says about a file in slot 1, which would represent the merge base copy of a file with a rename/rename conflict.

    Normally we just use git add or perhaps git rm to overwrite the higher-numbered slots. In the rare case of wanting to restore a resolved file to conflicted state, git checkout -m can do that.