К сожалению, вы не можете.Когда вы находитесь в середине конфликтующего слияния, вы должны либо завершить это слияние, либо полностью прервать его, чтобы начать другое слияние.Здесь вы тоже не то, что вам нужно («закончите и начните новый», вы можете получить его там, но оно запутанно и подвержено ошибкам).
Git действительно должен иметь инструмент «приостановить слияние», чтобы позволить вам сделатьэто чище.Возможно, можно написать один, но у меня нет времени, чтобы сделать это.
Почему это так (долго)
Давайте начнем с некоторого фона.Проблема на данный момент сводится к выполнению трехсторонних слияний на отдельных файлах - но как мы сюда попали?
Типичное слияние Git - или, точнее, то, что я привык называть истинное слияние , в отличие от операции "ускоренной пересылки", которая выполняется не по принципу слияния, которая в основном выполняется просто, как через git checkout
или git reset --hard
, и использует три входа.Вы указываете один из этих входных данных, --theirs
commit.Два других являются неявными: это текущий или --ours
коммит и база слияния , рассчитанная вашей стратегией слияния .Стратегия по умолчанию для этого вида слияния - та, которую вы выбрали в обеих примерах команд: -s recursive
.
цель этого вида слияния - объединить работу.Фиксация базы слияния служит общей отправной точкой, с которой вы (в своей ветви --ours
) выполнили некоторую работу, а они (в своей ветви --theirs
) выполнили некоторую работу, которую Git теперь должен объединить.Поскольку вы оба начали с одного и того же коммита, это облегчает объединение: Git может запустить git diff
из базы слияния в ваш коммит, чтобы увидеть, что вы сделали, и второй git diff
от слиянияОсновываясь на их коммите, чтобы увидеть, что они сделали.
Запустив эти две команды diff (или их внутренний эквивалент), Git может затем связать каждый базовый файл с одним файлом в вашем коммите и с одним файломв их совершении.Выполнение diff и сопряжение файлов - все это является частью стратегии слияния, но еще не завершено: этот процесс просто уменьшает проблему, вплоть до того, что теперь приходится объединять работу для каждой группы файлов.
Игнорируя сложные случаи, такие как новые файлы, переименованные файлы и удаленные файлы, теперь у нас есть стратегия слияния, для каждого имени пути P:
- посмотрите на содержимое P в базе слияния;
- посмотрите на содержание P в коммите
--ours
;и - посмотрите на содержимое P в коммите
--theirs
.
В качестве кратчайшего пути, если содержимое одинаково в двух илитри из трех версий, объединить нечего, и Git может просто выбрать версию --ours
, которая уже есть в индексе, или поместить версию --theirs
в индекс в зависимости от ситуации.
Если нет, хотя - если все три версии отличаются - тогда этот конкретный файл требует фактического слияния.Git копирует все три версии в индекс в слотах 1, 2 и 3, которые зарезервированы для процесса слияния, и вызывает код слияния , один файл за один раз .Этот код объединяет один файл , используя три версии .Три версии - это те, которые теперь хранятся в индексе (мы можем извлечь все три в рабочее дерево позже, если захотим, но это то, где они есть).
Код слияния низкого уровня - это то, что мыдумать о том, когда мы думаем о конфликтах слияния.На самом деле, хотя, если низкоуровневый код способен объединять без конфликтов, он удаляет три версии из индекса, добавляет вместо этого объедините файл как запись нулевого уровня и продолжайте, как если бы не было никаких проблем.Только при сбое низкоуровневое слияние записывает в рабочее дерево версию файла конфликтующего слияния .Он оставляет все три входа в индексе.
Вы не можете начать новое слияние, если у вас есть неполное слияние
Примечаниечто в приведенной выше последовательности Git использует индексную / промежуточную область для хранения трех версий каждого конфликтующего файла и рабочее дерево для хранения объединенной версии при остановке.Для этого Git должен начинаться с индекса clean и рабочего дерева.Если бы индекс и рабочее дерево не были чистыми для начала, этот процесс мог бы уничтожить несохраненную работу.
Поэтому Git говорит «нет», если вы пытаетесь запустить git merge
с неразрешенным конфликтом слияния илинезафиксированный индекс или грязное рабочее дерево.Если вы прервите существующее, продолжающееся слияние, это уничтожит все, что вы сделали до сих пор, и переустановит ваш индекс и рабочее дерево так, чтобы они были чистыми, но это уничтожит все, что вы сделали до сих пор.
Ваш единственный вариант - закончить слияние - пометить все решенные и зафиксировать.Но это создает новый коммит в текущей ветке.Если затем вы начнете второе слияние, подразумеваемая база слияния - это только что сделанный вами коммит, а не исходная база слияния, которая была у вас во время предыдущего коммита.Это означает, что вы должны сохранить коммит слияния, но затем отменить его с git reset
или его эквивалентом.Это сложная и подверженная ошибкам часть.
Если бы мы только могли повторить низкоуровневое слияние с различными параметрами
В низкоуровневом коде используется большая часть-X
опций, например -X ours
или -X theirs
, или, в вашем случае, -X ignore-space-at-eol
.Если бы у нас был прямой доступ к этому низкоуровневому коду, мы могли бы просто запустить его сами.Это позволило бы нам добавить -X ignore-space-at-eol
для одного конкретного файла, в котором имел конфликты.
К сожалению, в то время как есть команда git merge-file
, это не код, который используется git merge-recursive
(код merge-recursive
в ll-merge.c
, который реализует объединение низкого уровня, а не merge-file.c
, который реализует git merge-file
).Команда merge-file
не принимает опции -X
.Это делает , берет --ours
, --theirs
и даже --union
.Он вызывает код, который может принять -X ignore-space-at-eol
, но у него нет параметра командной строки, чтобы установить это.Если бы это заняло -X ignore-space-at-eol
, вы бы смогли достичь того, что хотели напрямую.