git cherry-pick: вручную принять "наши" или "их" фрагменты в конфликтующих файлах - PullRequest
0 голосов
/ 17 января 2019

В настоящее время я выбираю несколько коммитов в другую ветку (релиз). Я знаю о --strategy-option theirs при сборке вишни, но боюсь, что эта опция не подходит для каждого коммита, который я выбираю.

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

Тем не менее, есть некоторые файлы, в которых я хотел бы пакетно принять все ours или their фрагменты, что становится неудобно делать вручную. Есть ли способ просто принять все ours или their фрагменты в конфликтном файле?

Примечание: git checkout --ours/--theirs кажется неподходящим для выбора вишни, так как он извлекает весь файл из данной ветви. Я хочу принять только противоречивые фрагменты из любой версии.

1 Ответ

0 голосов
/ 17 января 2019

Не очень удобный способ сделать это, но вы можете создать его из инструментов, предоставляемых Git. Основной требуемый инструмент - это git merge-file, который выполняет трехстороннее объединение для одной тройки версий файлов, то есть base + our + их. Он принимает параметры --ours и --theirs для разрешения конфликтов так же, как -X ours и -X theirs для общего слияния, т. Е. Он не просто берет наш файл или их file , он берет наши или их только в конфликтных точках.

Это все замечательно, но где взять три версии? Git остановился из-за конфликта слияния, скажем, main.py. В вашем рабочем дереве main.py содержит беспорядок, оставленный Git, с маркерами <<<<<<< ... >>>>>>> вокруг конфликтующих строк. Но для git merge-file нужны три неотмеченных входных файла: базовая версия слияния, «наша» версия и «их» версия. Но эти три файла находятся в индексе! Если файл F имел конфликт, существует :1:<em>F</em> с базовой версией слияния, :2:<em>F</em> с нашей и :3:<em>F</em> с их.

Чтобы получить их, вы можете использовать git show или git checkout-index. Последний действительно правильный инструмент: git mergetool использует git checkout-index, с этой маленькой функцией оболочки:

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 main.py main.py.base, например, он извлекает копию этапа 1 (базы слияния) от main.py до main.py.base. Повторите с 2 и 3 и подходящими вариантами для третьего аргумента, чтобы получить все три файла. Затем запустите git merge-file для трех файлов, как описано в документации git merge-file .

(Подробнее см. исходный код git mergetool . Это просто большой сценарий оболочки, поэтому его довольно легко читать и изменять для собственных целей.)

...