Git: Решить конфликты слияния, используя стратегию - PullRequest
0 голосов
/ 03 июля 2018

Сценарий:

  1. попытка слияния из ветви feature в master

  2. свидетели незначительных конфликтов, например, другой номер версии, который не должен объединяться

Как вы можете сказать git объединять только не конфликтующие части и не трогать конфликтующие, как при запуске git merge -s recursive -Xours feature?

Мое текущее решение - запустить git merge --abort с последующим вышеупомянутым слиянием стратегии. Есть ли способ сделать это без предварительной отмены моего слияния? Я не хочу запускать другой инструмент или работать через каждый конфликт один за другим.

Ни git docs при слиянии , ни этот SO поток не дают никаких советов.

1 Ответ

0 голосов
/ 03 июля 2018

Вам все равно придется работать с каждым файлом один за другим, но вы можете использовать git merge-file для достижения того, что вы хотите. Возможно, вы захотите написать скрипт для выполнения следующих шагов.

Когда Git останавливается с конфликтом слияния, Git оставляет все три версии конфликтующего файла в области index / staging-area. Скажем, например, что конфликтующий файл называется README.txt. Тогда, поскольку произошел конфликт, у вас есть README.txt в вашем рабочем дереве с маркерами конфликта, но у вас также есть:

  • :1:README.txt: README.txt от базы слияния (общий коммит, от которого расходились и ваш текущий коммит, и ваш целевой коммит слияния).
  • :2:README.txt: README.txt из HEAD или --ours commit.
  • :3:README.txt: README.txt из --theirs commit.

Вы можете извлечь каждый из этих трех файлов во временный файл. Например, самый простой способ - использовать git show :1:README.txt > README.txt.base. Есть более изящный способ, который больше подходит для сценариев - команда git mergetool использует это:

checkout_staged_file () {
        tmpfile=$(expr \
                "$(git checkout-index --temp --stage="$1" "$2" 2>/dev/null)" \
                : '\([^ ]*\)    ')

        if test $? -eq 0 && test -n "$tmpfile"
        then
                mv -- "$(git rev-parse --show-cdup)$tmpfile" "$3"
        else
                >"$3"
        fi
}

который он вызывает как:

    checkout_staged_file 1 "$MERGED" "$BASE"
    checkout_staged_file 2 "$MERGED" "$LOCAL"
    checkout_staged_file 3 "$MERGED" "$REMOTE"

В любом случае ваша задача - извлечь эти три файла и запустить:

git merge-file --ours <stage-2-file> <stage-1-file> <stage-3-file>

, который оставит объединенный результат с конфликтами, разрешенными в пользу "наших", в <stage-2-file>.

Таким образом, учитывая все вышеизложенное, если файл с именем README.txt и вы хотите повторить слияние этого одного файла с эквивалентом -X ours, они будут работать (хотя метод git show не подчиняется настройкам CRLF, поэтому вам может понадобиться более интересный материал git checkout-index:

git show :1:README.txt > README.txt.base
git checkout --ours README.txt
git show :3:README.txt > README.txt.other
git merge-file README.txt README.txt.base README.txt.other
rm README.txt.base README.txt.other
git add README.txt

Слияние завершено для README.txt. Повторите эти шесть шагов для всех остальных файлов, для которых вы хотите применить это правило «конфликты переопределения из --ours».

...