Да.Когда слияние завершается конфликтами, индекс содержит все три входных файла (не только ours
и theirs
, но также версию base из коммита слияния-базы).
Файл рабочего дерева, который вы просматривали, - это не то, о чем Git действительно очень заботится.Git напишет на рабочем дереве все возможное для объединения трех входов из индекса - то, что Git заботится о здесь, - и ваша задача, как человека, который наблюдает за слиянием, состоит в том, чтобы затем подойтис правильным результатом слияния и вставкой его обратно в индекс.Если вы можете сделать это только с тем беспорядком, который Git оставил в рабочем дереве, отлично.Если нет ...:
В индексе обычно есть только одна копия каждого файла.Эта одна копия помещается в «нулевой слот», и первоначально она соответствует подтвержденному вами извлеченному коммиту.
Копия файла рабочего дерева существует для , которую вы можете использовать, ноGit на самом деле его не использует, кроме случаев, когда вы запускаете git add <em>file</em>
.Затем Git копирует копию файла рабочего дерева поверх поверх индексной копии, чтобы индексная копия снова соответствовала копии рабочего дерева (и, вероятно, больше не совпадает с копией текущего коммита).
Во времяпри слиянии копия с нулевым временным интервалом оказывается в гнезде 2 (--ours
).Копия того же файла из базы слияния попадает в слот 1. Копия того же файла из другого коммита - того, который вы объединяете - попадает в слот 3 (--theirs
).Git пытается объединить все три копии, и если Git преуспевает сам по себе, Git помещает объединенную версию в нулевой слот (и копирует ее в рабочее дерево) и очищает слоты слияния.Если Git завершается неудачно, он оставляет занятые слоты слияния с пустым нулевым слотом.
Так что, если беспорядок рабочего дерева, оставленный Git, недостаточно хорош, вы можете просто извлечь все три индексные копии.Способ сделать это вручную - использовать git checkout-index
, но в целом более простой (если не совсем понятный) способ сделать это - использовать git mergetool
.
Команда git mergetool
по сути, это большой сценарий оболочки, который запускает git checkout-index
на всех трех копиях каждого еще не распакованного файла, а затем запускает любую команду по вашему выбору для этих трех копий.Эта команда должна записать правильный объединенный файл в четвертый файл:
... настроенная командная строка будет вызываться с $BASE
, установленным на имя временного файла, содержащего общую базу дляобъединить, если доступно;$LOCAL
установить имя временного файла, содержащего содержимое файла в текущей ветке;$REMOTE
установить в качестве имени временного файла, содержащего содержимое файла для слияния, а $MERGED
установить в качестве имени файла, в который инструмент слияния должен записать результат разрешения слияния.
Опять же, все эти временные файлы создаются с помощью git mergetool
с использованием git checkout-index
для извлечения их из индекса.Когда ваш инструмент завершает работу, сценарий использует git add
в файле $MERGED
, чтобы удалить записи слота 1-3 и записать запись с нулевым слотом.
Появляется фраза , если доступна выше, потому что в нескольких угловых случаях произошел конфликт слияния из-за того, что в одном файле отсутствует .Например, конфликт добавления / добавления возникает, когда нет базы слияния версии newfile.ext
, но оба --ours
и --theirs
do имеютnewfile.ext
и два файла не совпадают.Здесь база будет отсутствовать;$LOCAL
и $REMOTE
оба будут существовать.Конфликт изменение / удаление возникает, когда в базовом коммите было file.ext
, вы (--ours
) или они (--theirs
) изменили файл, а другойВы / они удалили файл.Здесь $BASE
будет существовать, но будет существовать только один из $LOCAL
или $REMOTE
.
Поскольку git mergetool
- это сценарий оболочки , выможете скопировать и изменить его - вам понадобится несколько смежных файлов;исследуйте отсюда, и они должны быть очевидны - если вы хотите каким-то образом изменить его работу, которая не поддерживается с помощью флагов и конфигурации инструмента.