我想将2个分支与不同的配置文件合并,以便配置文件保持不变即使没有冲突。据我所知here和here,我需要配置自定义合并策略而不是合并驱动程序(我已经配置了合并驱动程序并且工作正常当我有合并的冲突时)
我正在尝试使用this的指导设置我的合并策略。
我在我的项目根目录(放置我的.gitattributes的地方)中创建了git-merge-mystrategy.sh,其中包含以下代码:
merge-file -q --ours "$2" "$1" "$3";
pom.xml merge=ours
当我跑步时:
git merge --strategy mystrategy develop
我明白了:
Could not find merge strategy 'mystrategy'.
Available strategies are: octopus ours recursive resolve subtree.
我可能在here中遗漏了这一部分:在你的路径中创建一个可执行的git-merge-mystrategy 。
请您详细介绍一下如何创建自定义合并策略?
答案 0 :(得分:2)
作为Edward Thomson said in his answer,您猜对了,您必须将git-merge-mystrategy.sh
放入Git可以通过$PATH
找到的文件中。该文件必须是可执行的(在Unix / Linux上chmod +x
,我不知道在Windows上是什么),并且如果您将其作为git-merge-mystrategy
运行,则通过名称git merge -s 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
(此时脚本正在从stdin读取变量junk
,所以一切都暂停,我可以点击 CTRL + C 来中断它停止虚假合并)。
以下是论证的含义,以及它们的含义:
--whatever
:这会通过扩展策略选项-X whatever
。正如你所看到的,没有审查这些论点:它们实际上只是任意字符串(-Xkcd
选项意味着什么?)。--
之前:这是合并基础,或者合并基础,如果有多个,则来自要合并的头部。--
:这将合并基础与指定要合并哪些头的字符串分开。HEAD
:这总是下一个论点;它被编译成git merge
。这是本地头,对于像-s ours
(或-s theirs
这样的策略,如果它存在的话)它有一些额外的意义,但对于大多数合并策略,你应该对待它与其余论点一样。git merge ... develop
后,Git已将develop
解析为特定的提交ID,该提交ID是名为develop
的分支的提示,并且该提交是远程HEAD。作为合并策略,您现在的工作是:
引用the git merge
source here可能最简单:
此时,我们需要一个真正的合并。无论采取何种策略 我们使用,它会对索引进行操作,可能会影响到 工作树,当干净地解决,有所需的 索引中的树 - 这意味着索引必须在 与头部提交同步。战略是负责任的 确保这一点。
当发生冲突时,后端以1退出 剩下要解决,当没有解决时,2 处理给定的合并。
如果您在命令行上提供了多个-s
选项,git merge
代码将(在现代Git中)为您运行git stash
,然后执行git reset --hard
和{每个策略尝试之间的{1}},直到一个完全成功退出0状态 - 在这种情况下Git获取其结果 - 或者它用完了尝试的策略。已经没有策略,如果其中一些退出1而不是2,Git选择产生"最佳"结果,最好的"是一个有点奇怪的措施:更改文件的最小数字总和(与HEAD提交相比)和未合并文件被认为是"最佳"结果。 (在我看来,也许未合并的文件在这里应该更加重要。)然后它将在另一次硬重置之后重新运行最佳合并。
无论如何,所有这一切的要点是你在合并策略中要做很多工作。明智的做法是确保索引和工作树处于合理的可恢复状态,然后再继续进行,并拒绝合并(如果没有,请提交或保存您的更改")。 Simialrly,如果有多个合并库,您可以完全使用git stash apply
拒绝该尝试,但是否则您必须对多个合并库做一些事情。 (exit 2
策略选择其中一个并忽略其余的,这是一个有效的选项,但并不总是最好的。resolve
策略合并合并基础,并使用生成的提交作为新的合并基地。)
然后,对于每个头 - 您自己的常规recursive
头部加上每个远程头部 - 您必须找到更改。通常的递归和解析策略,除非有两个头,否则拒绝运行,默认情况下运行HEAD
并将重命名检测设置为50%,允许git diff
参数更改此值,以便检测文件与基础进行比较时,在每个头中创建,删除和重命名。然后他们在高级别合并这些 - 或者无法合并它们,在索引中留下高级别冲突 - 并且对于从每个头部到每个头部标识的每个文件对,使用{将这些文件合并到较低级别{1}}。
在您的策略中,您需要执行所有相同的工作,除了对于一个特定文件,您将使用-X
的方式你想要的。