Идеальная ситуация для разрешения конфликтов - это когда вы заранее знаете, каким образом вы хотите их разрешить, и можете передать опции стратегии рекурсивного слияния -Xours
или -Xtheirs
. За пределами этого я вижу три сценарных:
- Вы хотите просто сохранить одну версию файла (вероятно, ее следует использовать только для двоичных файлов, которые не могут быть объединены, так как в противном случае конфликтующие и не конфликтующие файлы могут не синхронизироваться друг с другом).
- Вы хотите просто решить все конфликты в определенном направлении.
- Вам необходимо разрешить некоторые конфликты вручную, а затем разрешить все остальные в определенном направлении.
Для решения этих трех сценариев вы можете добавить следующие строки в файл .gitconfig
(или эквивалентный):
[merge]
conflictstyle = diff3
[mergetool.getours]
cmd = git-checkout --ours ${MERGED}
trustExitCode = true
[mergetool.mergeours]
cmd = git-merge-file --ours ${LOCAL} ${BASE} ${REMOTE} -p > ${MERGED}
trustExitCode = true
[mergetool.keepours]
cmd = sed -I '' -e '/^<<<<<<</d' -e '/^|||||||/,/^>>>>>>>/d' ${MERGED}
trustExitCode = true
[mergetool.gettheirs]
cmd = git-checkout --theirs ${MERGED}
trustExitCode = true
[mergetool.mergetheirs]
cmd = git-merge-file --theirs ${LOCAL} ${BASE} ${REMOTE} -p > ${MERGED}
trustExitCode = true
[mergetool.keeptheirs]
cmd = sed -I '' -e '/^<<<<<<</,/^=======/d' -e '/^>>>>>>>/d' ${MERGED}
trustExitCode = true
Инструмент get(ours|theirs)
просто сохраняет соответствующую версию файла и удаляет все изменения из другой версии (поэтому объединение не происходит).
Инструмент merge(ours|theirs)
повторно выполняет трехстороннее объединение из локальной, базовой и удаленной версий файла, выбирая разрешение конфликтов в заданном направлении. Это имеет некоторые оговорки, в частности: он игнорирует параметры diff, которые были переданы команде слияния (например, алгоритм и обработка пробелов); выполняет слияние из исходных файлов (поэтому любые ручные изменения в файле отбрасываются, что может быть как хорошим, так и плохим); и имеет преимущество в том, что его нельзя спутать с маркерами diff, которые должны быть в файле.
Инструмент keep(ours|theirs)
просто редактирует маркеры diff и вложенные секции, обнаруживая их по регулярному выражению. Преимущество этого в том, что он сохраняет параметры diff из команды merge и позволяет вам разрешать некоторые конфликты вручную, а затем автоматически разрешать остальные. Недостатком является то, что если в файле есть другие маркеры конфликта, он может запутаться.
Все они используются при запуске git mergetool -t (get|merge|keep)(ours|theirs) [<filename>]
, где, если <filename>
не указан, он обрабатывает все конфликтующие файлы.
Вообще говоря, если вы знаете, что нет никаких различий, мешающих регулярному выражению, варианты команды keep*
являются наиболее мощными. Если вы оставите параметр mergetool.keepBackup
не установленным или true, то после слияния вы можете сравнить файл *.orig
с результатом слияния, чтобы убедиться, что он имеет смысл. Например, после mergetool
я запускаю следующее, чтобы проверить изменения перед фиксацией:
for f in `find . -name '*.orig'`; do vimdiff $f ${f%.orig}; done
Примечание : Если merge.conflictstyle
не равно diff3
, тогда вместо шаблона /^|||||||/
в правиле sed
должно быть /^=======/
.