Git - автоматически создавать отдельные файлы для версий в конфликте

Когда Git обнаруживает конфликт во время слияния, поведение по умолчанию заключается в заполнении файла маркерами <<< >>> ===.

Это нормально в большинстве случаев, но иногда я хотел бы разрешать конфликты по-другому, и мне просто хотелось бы, чтобы Git создавал разные файлы:

  • оригинальная версия,
  • измененная версия A,
  • измененная версия B.

Как это сделать?


Если нет простой команды для создания этих файлов за один раз (что несколько удивительно), возможно, есть способ расширить Git, чтобы он это сделал? Пользовательский mergetool или что-то еще? Просто идея.


Решение:

Я согласился на вариант ответа @Karl Bielefeldt:

savefiles.sh

#!bash
BASE=$1
LOCAL=$2
REMOTE=$3
MERGED=$4

cp "$BASE" "$MERGED.git_BASE"
cp "$LOCAL" "$MERGED.git_LOCAL"
cp "$REMOTE" "$MERGED.git_REMOTE"

# never mark the conflict as merged
exit 1 

CONFIG

mergetool.savefiles.cmd=/path/to/savefiles.sh $BASE $LOCAL $REMOTE $MERGED
mergetool.savefiles.trustexitcode=true

Ответ 1

Создайте файл с именем savefiles.sh со следующим содержимым:

#!/usr/bin/bash

cp $1 /path/to/BASE
cp $2 /path/to/LOCAL
cp $3 /path/to/REMOTE

Выполните следующую команду внутри своего репозитория:

git config mergetool.savefiles.cmd "/path/to/savefiles.sh \$BASE \$LOCAL \$REMOTE"

Добавьте --global, если вы хотите изменить его для другого, чем этот репозиторий.

Затем для запуска этого настраиваемого слияния используйте:

git mergetool --tool=savefiles

Ответ 2

Если вы хотите пойти без mergetool и просто отображать или сохранять файлы в указанных вами состояниях, индекс содержит разные состояния конфликтуемого файла. Вы можете отобразить (и перенаправить на файл, если хотите), с помощью:

$ git show :1:file.txt  # the file in a common ancestor of both branches
$ git show :2:file.txt  # the version from HEAD.
$ git show :3:file.txt  # the version from MERGE_HEAD.

Однако, используя инструмент графического слияния, вы видите 3-оконное представление конфликтующего файла. Обычно это то, что делают люди, поэтому просто поднимите свой любимый инструмент и посмотрите, как связать его с вызовом git mergetool.

Ответ 3

Резюме

git mergetool -y -t bogus <file>

Работает для меня с git 1.7.9.5/Ubuntu 12.04 и msysgit 1.9.4/Windows 7 x64.

Объяснение

Мне просто нравится git создавать отдельные файлы

Я искал то же самое. Пример: при вызове git mergetool -t kdiff3, git похоже, пытается перехитрить меня, вызвав kdiff3 с жестко закодированным флагом --auto который инструктирует kdiff3 автоматически разрешать конфликты и выходить, не показывая мне графический интерфейс или не позволяя мне участвовать в этом процессе (см. также). Когда это произошло, и kdiff3 разрешил конфликты неправильно, я пошел искать это.

Когда я вызываю mergetool так же (где bogus - это строка, которая не является допустимым идентификатором инструмента слияния [например, не на выходе git mergetool --tool-help, если ваша версия git имеет это]), происходит следующее:

  • В нем сообщается "Неизвестный инструмент слияния с фикцией"

  • Индекс и file остаются нетронутыми

  • Сгенерированы следующие файлы (где {num} - целое число, одинаковое во всех файлах, созданных этим вызовом):

    file.BACKUP.{num}
    file.BASE.{num}
    file.LOCAL.{num}
    file.REMOTE.{num}
    

file.BACKUP.{num} идентичен file.

Примечания

Я думаю, что -y не нужно, если mergetool.prompt установлен на false. И, согласно документации, похоже, что в новых версиях git -t подразумевается -y.

Часть -t может быть дополнительно сокращена, например. -t x или -t 0.

Если у вас несколько несвязанных файлов, похоже, нет никакого способа заставить это создавать эти версии для более чем одного файла за раз. Например. если у вас есть несвязанные файлы files/file1 и files/file2, любое из следующего будет генерировать только эти версии (backup, base, local, remote) для file1:

git mergetool -y -t x
git mergetool -y -t x files
git mergetool -y -t x files/file1 files/file2

Однако, если вы разрешите конфликты в file1 и запустите git mergetool снова, он перейдет к следующему файлу.