如何使用给定的策略从命令行仅针对一个文件解决 git 合并冲突?

How to resolve git merge conflict, from command line, using a given strategy, for just one file?

假设我进行了 git 合并,并且在某些文件中存在冲突,比如 package.jsonpom.xml,可能还有一些其他文件。

我愿意

  1. 从命令行自动解决某些文件的合并冲突,而
  2. 让我自己手动解决所有其他冲突,如果有的话,
  3. 确保我不会丢失来自任何分支的有价值的更改。

因为 2),我不能使用 git merge -Xours,因为这会解决 所有 冲突。我只想解决一个特定文件中的冲突。

因为 3),我不能使用 git checkout --ours package.json 因为这可能会丢失输入分支的一些更改。

用例例如:自动合并脚本,它将以预定义的方式解决琐碎的众所周知的冲突,如果其他文件中存在其他冲突则失败。

我经常遇到的典型情况是 package.json 中的 version 字段有两个分支,如下所示:

$ 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

是否可以使用给定的策略解决 一个 文件的冲突?类似于:

git-resolve-conflict --ours package.json

这可以使用 git-merge-file 来实现,尽管它的 API 相当低级。

为了有一个简单易用的命令,可以使用下面的bash脚本(要导入到.bashrc,也可以用[=15=安装]):

git-resolve-conflict() {
  STRATEGY=""
  FILE_PATH=""

  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
}

(注意:我不断更新我的 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

奖金:

如果子文件夹中有多个 package.json 文件,并且想要解决合并问题 for all of them which are in conflicted state:

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