Важное первое замечание: ваш git update-index
здесь не очень функционален. Rebase должен будет касаться файлов, помеченных --skip-worktree
, если основная операция слияния должна касаться их. Это не коснется их, если нет. Пометка файлов может может принести вам полезную ошибку во время операции выбора вишни (я не проверял это, но вы можете проверить это самостоятельно).
Повторная обработка повторяется git cherry-pick
(или иногда эквивалент). Каждый вишневый кирк использует процесс слияния - то, что я люблю называть слияние как глагол или для слияния - и, как вы видите, слияния могут иметь конфликты слияния. Два отличия git cherry-pick
от обычного слияния:
- База слияния является просто родителем коммита, выбранного вишней.
- Коммит, который будетв конце делается обычный коммит (без слияния).
Включение rerere
будет иметь тот же эффект, что и для любого другого git merge
, так как повторное использование записанных разрешений происходит в том жепуть. Это не поможет вам в вашем случае, потому что вы уже используете -X theirs
, который исключает конфликт, который может разрешить rerere
.
Конфликты во время слияния возникают либо из того, что я называю операции высокого уровня , для всего дерева файлов или из работы низкого уровня слияния. Я использую эти две фразы, чтобы различать два разных раздела кода в движке слияния Git. По сути, объединение выполняется двумя git diff
операциями:
git diff --find-renames <base> <tip1>
git diff --find-renames <base> <tip2>
Эти разности являются внутренними по отношению к git merge
, который имеет встроенный механизм различий, и могут передавать различные опции, которые труднодостичь через командную строку, но принцип тот же:
Функция поиска переименования просматривает файлы, добавленные и / или удаленные, и пытается найти соответствие левой стороне (база слияниясторона) "удаленный" файл против "добавленного" файла с правой стороны. Если это так, Git решает, что этот файл был переименован .
Подобное сопоставление имен файлов приводит к отображению идентичности: базовый файл с именем F B имеет новое имя F L с левой стороны и F R с правой стороны. Все три имени могут быть равными, или два или все три могут отличаться, но в любом случае, это «один и тот же» файл. Он также оставляет нам файлы, которые добавляются и / или удаляются с обеих сторон, и файлы, которые могут или не могут быть изменены с одной или обеих сторон.
Теперь мы должны объединить всеменяется ... но это происходит сначала при именах файлов и уровне существования :
Если левая сторона удаляет файл F d и правая сторона не меняет его, это нормально. Но если левая сторона удаляет его, а правая изменяет, мы имеем конфликт удаления / изменения . (Если правая сторона удаляет его, а левая изменяет его, у нас возникает тот же конфликт, обратный.)
Если левая сторона переименовывает файл, а правая сторона удаляет его (илито же самое с заменой сторон), у нас конфликт переименования / удаления .
Если обе стороны добавляют новый файл с нуля, но с тем же именем, у нас есть добавить / добавить конфликт .
Если обе стороны переименуют базовый файл F B , но с двумя разными именами *F L и F R , у нас конфликт переименования / переименования .
Git разрешает нет этих конфликтов самостоятельно. Это конфликты high level .
Решив или не разрешив любые операции с деревьями высокого уровня, мы теперь имеем случаи, когда один и тот же файл переносился из базы в обе подсказки ветви - с помощью "тот же файл "с учетом переименований, как указано выше - но был изменен обеими сторонами. Git теперь запускает код из отдельного файла с именем ll-merge.c
: низкоуровневый код слияния.
LLСлияние позволяет пользователям определять драйверы слияния . При их использовании вся операция зависит от драйвера слияния, который просто получает данные всех трех входных файлов (базовый, левый / HEAD и правый / их). При использовании встроенных драйверов слияния разрешение конфликтов может выполняться автоматически с использованием -X
extended-options: -X theirs
выбирает изменение правой стороны, отбрасывая левую сторону (base-vs-HEAD) изменить. -X ours
выбирает левостороннее изменение. Без этих опций Git просто объявляет конфликт, когда изменения перекрываются или примыкают.
Поскольку вы используете -X theirs
и получаете конфликты, мы можем заключить, что вы должны получать высокий уровень конфликтов. Повторный код Git не записывает и не может повторно использовать эти разрешения.
Чтобы обнаружить их после прекращения слияния из-за конфликта, вы можете использовать git status
или проверить индекс / промежуточную область с помощью git ls-files --stage
. К сожалению, Git делает плохую (как в большинстве случаев несуществующую) работу по записи того, что на самом деле было конфликтами высокого уровня. Он печатает конфликты, поэтому, если вы фиксируете вывод, вы можете его проанализировать;или вы можете запустить собственную команду git diff --find-renames --name-status
, чтобы увидеть, что видел слияние.
В общем случае слияний, git diff --find-renames
проблематично, так как git merge
может создать временную фиксацию, которая содержит то, что вызывает Git база виртуального слияния . Однако для cherry-pick база слияния является просто родителем коммита, выбранного в данный момент, поэтому использование этого метода может быть надежным. Вам придется написать код в любом случае.