Почему git mergetool не показывает конфликтов, даже если в файлах после слияния присутствуют маркеры конфликтов? - PullRequest
0 голосов
/ 08 апреля 2020

Я проверен на 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 в качестве моего mergetool, и, похоже, он работает. 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

Автоматически git mergetool разрешает вышеуказанный конфликт (в инструменте показано 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 для получения:

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

1 Ответ

0 голосов
/ 08 апреля 2020

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

Совершенно верно.

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

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

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

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

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

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

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

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


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

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

...