就像Edward Thomson said in his answer,你猜对了,你必须把git-merge-mystrategy.sh 放到一个Git 可以通过$PATH 找到的文件中。该文件必须是可执行的(在 Unix/Linux 上为 chmod +x,我不知道在 Windows 上是什么),并且如果您以 git merge -s mystrategy 运行它,则可以通过名称 git-merge-mystrategy 找到它。 (您可以运行 git merge -s mystrategy.sh 以在 $PATH 中搜索 git-merge-mystrategy.sh。)
更大的问题是正确的合并策略不容易写出来。这个:
merge-file -q --ours "$2" "$1" "$3";
不会工作。您的策略将使用git merge 计算的特定参数调用,但没有一个是文件名。我将在这里用一个非功能性的合并策略脚本来说明这一点。
如果你运行:
git merge --strategy mystrategy develop
您的脚本将使用四个 (!) 参数调用。如果你运行:
git merge -s mystrategy -Xa -Xkcd=12 --find-renames=35 develop
您的脚本将获得七个参数:
$ cat ~/scripts/git-merge-silly
#! /bin/sh
echo "I got $# arguments..."
for i do
printf "%s\n" "$i"
done
read junk
$ chmod +x ~/scripts/git-merge-silly
$ git merge -s silly -Xa -Xkcd=12 -X find-renames=35 b1
I got 7 arguments...
--a
--kcd=12
--find-renames=35
4f95ecf496de9dfe175e7ed4dd97972adf0ca625
--
HEAD
439e327bc8f8e78d74b27ae89f433451eec09111
(此时脚本正在从标准输入读取变量junk,所以一切都暂停了,我可以点击 CTRL+C 来中断它并停止虚假合并)。
以下是论点及其含义:
-
--<em>whatever</em>:这通过扩展策略选项-X <em>whatever</em>。如您所见,这些参数没有经过审查:它们实际上只是任意字符串(-Xkcd 选项是什么意思?)。
-
-- 之前的散列,或者在某些情况下是多个散列:这是合并基,如果有多个则是合并基,来自要合并的头部。
-
--:这将合并基与指定要合并的头的字符串分开。
-
HEAD:这永远是下一个论点;它被编译成git merge。这是本地头,对于像-s ours(或-s theirs,如果存在的话)这样的策略,它有一点额外的意义,但对于大多数合并策略,你应该同样对待它作为剩下的论点。
- 一个或多个哈希 ID:这些是 Git 所称的要合并的 远程头。在这种情况下,运行
git merge ... develop 后,Git 已将 develop 解析为特定的提交 ID,即名为 develop 的分支的提示提交,并且该提交是远程 HEAD。
作为一种合并策略,您现在的工作是:
- 查找自合并基础到各个头(HEAD 加上每个遥控器)以来的变化
- 组合这些更改,将生成的组合文件写入索引和工作树
- 退出时显示您的成功或失败状态。
引用the git merge source here 可能是最简单的:
此时,我们需要一个真正的合并。不管是什么策略
我们使用,它将对索引进行操作,可能会影响
工作树,并且在干净地解决后,具有所需的
索引中的树——这意味着索引必须在
与头部提交同步。策略负责
以确保这一点。
还有just a bit later:
当发生冲突时,后端以 1 退出
留待解决,没有时有 2
完全处理给定的合并。
如果您在命令行上提供多个 -s 选项,git merge 代码将(在现代 Git 中)为您运行 git stash,然后在每个策略尝试之间执行 git reset --hard 和 git stash apply,直到通过以 0 状态退出而完全成功(在这种情况下,Git 会获取它的结果)或者它用尽了可以尝试的策略。在用完策略后,如果其中一些退出 1 而不是 2,Git 会选择产生“最佳”结果的策略,其中“最佳”是一个有点奇怪的衡量标准:更改文件的最小数字总和(与 HEAD 提交相比) ) 并且未合并的文件被认为是“最佳”结果。 (在我看来,也许未合并的文件应该更重,在这里。)然后它将在再次硬重置后重新运行最佳合并。
无论如何,这一切的关键在于您在合并策略中还有很多工作要做。明智的做法是在继续之前确保索引和工作树处于可恢复的状态,如果不是,则拒绝合并(使用“请提交或存储您的更改”)。同样,如果有多个合并基础,您可以使用exit 2 完全拒绝尝试,否则您必须对多个合并基础做一些事情。 (resolve 策略选择其中一个并忽略其余的,这是一个有效的选项,尽管并不总是最好的。recursive 策略合并合并基础,并将生成的提交用作新的合并基础。)
然后,对于每个头(您自己的常规 HEAD 头和每个远程头),您必须找到更改。通常的递归和解析策略,除非正好有两个头,否则拒绝运行,运行git diff,默认情况下重命名检测设置为 50%,允许-X 参数更改此设置,以便检测文件创建、删除、并在与基础相比时在每个头部中重命名。然后他们在高级别合并这些文件 - 或者无法合并它们,从而在索引中留下高级别冲突 - 并且对于在 base-to-each-head 中标识的每个文件对,使用 @ 在较低级别合并这些文件987654362@.
在您的策略中,您需要完成所有这些相同的工作,除了对于一个特定文件,您会以您想要的方式使用git merge-file -q --ours在这里。