Почему git mergetool не показывает конфликтов, хотя после слияния в файлах присутствуют маркеры конфликтов?

Я зарегистрирован на feature/my-branch и работаю на git merge dev. Маркеры конфликта, добавленные в файл:

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

Затем я запускаю git mergetool. Я установил p4mergetool в качестве инструмента слияния, и, похоже, он работает. Мой .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

git mergetool auto разрешает вышеупомянутый конфликт (0 конфликтов показано в инструменте) следующим образом:

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

В этом есть смысл: хотя HEAD и dev конфликтуют, мы видим, что одна ветвь обновила одну строку, а другая ветвь обновила другую строку. Таким образом, мы можем вероятно предположить, что хотим.

Мои вопросы:

  1. Есть ли способ запустить/настроить git-mergetool или p4mergetool специально, чтобы НЕ делать это предположение и по-прежнему отображать конфликт?
  2. Мне нужно запустить обе команды:

    git merge dev
    git mergetool
    

    чтобы этот конфликт разрешился автоматически? т.е. производить вывод:

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

Другими словами: есть ли стратегия/аргументы git merge, которые я могу использовать, чтобы просто запустить команду merge для создания:

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

person Nicholas Servidio    schedule 08.04.2020    source источник


Ответы (1)


В этом есть смысл: хотя HEAD и dev конфликтуют, мы видим, что одна ветвь обновила одну строку, а другая ветвь обновила другую строку. Таким образом, мы можем вероятно предположить, что хотим.

Это точно.

  1. Есть ли способ запустить/настроить git-mergetool или p4mergetool специально, чтобы НЕ делать это предположение и по-прежнему отображать конфликт?

git mergetool не делает предположений, поэтому мы можем сделать вывод, что это должен делать p4mergetool. Однако у меня нет p4mergetool, поэтому я не знаю, есть ли у него ручка настройки, чтобы изменить это.

  1. Мне нужно запустить обе команды...

Да: собственное слияние Git довольно глупое и просто замечает, что, черт возьми, этот диапазон изменений слева примыкает (касается) или перекрывает этот другой диапазон изменений справа, поэтому давайте назовем это конфликтом и заставим пользователя справиться с этим. . В этом случае левостороннее изменение (с baz на foo) произошло непосредственно перед правосторонним изменением (bar на qux), поэтому два диапазона соприкасались по краям, и Git сам объявил конфликт. Если бы между ними была одна строка, git merge объединила бы изменения сама по себе, не вызывая конфликта.

(Обратите внимание, что использование -X ours или -X theirs разрешит конфликт, отменив изменение одной стороны и используя только изменение другой. Опять же, вы никогда даже не дойдете до того, чтобы p4mergetool делал свое дело.)

Что делает git mergetool, так это извлекает три файла — объединяет базовую, левую, или локальную, или --ours, и правую, или удаленную, или --theirs версии какого-либо файла — и запускает другую программу, не относящуюся к Git, для этих трех файлов. Когда эта программа завершится, git mergetool может либо доверять своему коду выхода, чтобы решить, правильно ли сам инструмент объединил файлы, либо запустить некоторые сравнения файлов, либо просто спросить вас напрямую: является ли копия файла рабочего дерева теперь правильной объединенной копией?

Если копия рабочего дерева теперь является правильным окончательным результатом (или, по крайней мере, git mergetool считает это), git mergetool запускает git add, который помечает конфликт как разрешенный.1 В противном случае он оставляет конфликт на месте.

(Я обычно разрешаю конфликты слияния в своем редакторе.)


1Файл разъединяется, если в любых ненулевых слотах индекса есть его копии. Файл объединяется, если существует одна его копия в нулевом слоте — обычный номер слота. За исключением использования некоторых низкоуровневых диагностических команд Git (на самом деле git ls-index --stage), вы фактически не можете видеть эти номера промежуточных слотов, но git status называет файл unmerged и говорит вам, находится ли он во всех трех слотах (UU) или только в левом или правом (UD и DU соответственно). Я не уверен навскидку, что git status говорит о файле в слоте 1, который будет представлять базовую копию слияния файла с конфликтом переименования/переименования.

Обычно мы просто используем git add или, возможно, git rm, чтобы перезаписать слоты с более высокими номерами. В редких случаях, когда требуется восстановить разрешенный файл до конфликтного состояния, git checkout -m может это сделать.

person torek    schedule 08.04.2020
comment
Спасибо @torek! О том, чтобы принять ответ. Просто любопытно: у меня нет p4mergetool, поэтому я не знаю, есть ли у него ручка конфигурации, чтобы изменить это. Знаете ли вы о каких-либо средствах слияния, которые имеют конфигурацию для этого? - person Nicholas Servidio; 09.04.2020
comment
Нет - я не использую ни один из них. Я запускал vimdiff в качестве инструмента слияния один или два раза, просто чтобы посмотреть, как он выглядит, и однажды я видел в действии один инструмент слияния, не относящийся к Git. Я запускал git mergetool и указал на несколько вещей, но никогда не экспериментировал с kdiff3 или чем-то еще с инструментом слияния KDE... - person torek; 09.04.2020