Как разрешить конфликт git слияния, из командной строки, используя данную стратегию, только для одного файла?

Скажем, я сделал слияние git и столкнулся с конфликтом в каком-то файле, скажем package.json или pom.xml и, возможно, некоторые другие файлы.

Я хотел бы

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

Из-за 2), я не могу использовать git merge -Xours, так как это разрешит ВСЕ конфликты. Я хочу разрешить только конфликты в одном файле.

Из-за 3), я не могу использовать git checkout --ours package.json, так как это может потерять некоторые изменения из входной ветки.

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

Обычно у типичного случая есть две ветки с полем version в package.json, как показано ниже:

$ git diff
diff --cc package.json
index 75c469b,f709434..0000000
--- a/package.json
+++ b/package.json
@@@ -1,6 -1,6 +1,12 @@@
  {
    "name": "test",
++<<<<<<< HEAD
 +  "version": "2.0.1",
++||||||| merged common ancestors
++  "version": "1.0.0",
++=======
+   "version": "1.0.2",
++>>>>>>> master

Можно ли разрешить конфликт для файла JUST ONE, используя данную стратегию? Что-то вроде:

git-resolve-conflict --ours package.json

Ответ 1

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

Чтобы иметь простую в использовании команду, вы можете использовать следующий bash script (для импорта в .bashrc, или вы также можете установить его с помощью npm install -g git-resolve-conflict):

git-resolve-conflict() {
  STRATEGY="$1"
  FILE_PATH="$2"

  if [ -z "$FILE_PATH" ] || [ -z "$STRATEGY" ]; then
    echo "Usage:   git-resolve-conflict <strategy> <file>"
    echo ""
    echo "Example: git-resolve-conflict --ours package.json"
    echo "Example: git-resolve-conflict --union package.json"
    echo "Example: git-resolve-conflict --theirs package.json"
    return
  fi

  git show :1:"$FILE_PATH" > ./tmp.common
  git show :2:"$FILE_PATH" > ./tmp.ours
  git show :3:"$FILE_PATH" > ./tmp.theirs

  git merge-file "$STRATEGY" -p ./tmp.ours ./tmp.common ./tmp.theirs > "$FILE_PATH"
  git add "$FILE_PATH"

  rm ./tmp.common
  rm ./tmp.ours
  rm ./tmp.theirs
}

(Примечание. Я продолжаю обновлять script в своем репозитории GitHub, проверяю репо на последние улучшения: https://github.com/jakub-g/git-resolve-conflict/blob/base/lib/git-resolve-conflict.sh)

В конкретном примере, как описано в вопросе, использование будет следующим:

git-resolve-conflict --ours package.json

Пошаговое исследование:

https://github.com/jakub-g/git-resolve-conflict

Bonus:

Если в подпапках имеется несколько файлов package.json и вы хотите разрешить слияние для всех из них, находящихся в конфликтующем состоянии:

for ITEM in $(git diff --name-only --diff-filter=U | grep package.json$); do git-resolve-conflict --ours $ITEM; done