到目前为止,我已经尝试解析MERGE_HEAD,但是当挂钩触发时,它似乎尚未设置。
那是正确的;但问题比那更大。(或者也许更小!:-))(我在这里还要注意{{link1:Arkadiusz Drabczyk的评论}}:不进行合并的git merge
-即快进式合并- 跳过了所有。)
首先,考虑如果用户运行了什么:
git merge a97131c
这个分支正在合并哪个分支?好的,让我们画一下图表:
...--*--o--o--@ <-- blarg (HEAD), xtest
\
o--A--B <-- br1
\
C <-- br2, br3
HEAD
告诉我们当前分支的名称是blarg
,因此尽管当前提交是提交@
(其哈希值可能为9fd178a
),但一旦实际进行合并提交,它就是名称blarg
将指向新的合并提交。
接下来,哪个提交是a97131c
? 它可能是提交A
、B
和C
中的任何一个。 如果它是提交A
,那么它本身就不是任何分支的末端,因此没有适当的名称来合并分支。 我们只是合并提交A
,以便结果为:
...--*--o--o--o <-- xtest
\ \
o-----A--@ <-- blarg (HEAD)
|\
| B <-- br1
\
C <-- br2, br3
如果
a97131c
是提交
B
的ID,我们可能正在执行
git merge br1
,所以结果将会是:
...--*--o--o--o <-- xtest
\ \
o @ <-- blarg (HEAD)
\ /
A----B <-- br1
\
C <-- br2, br3
如果
a97131c
是提交
C
的ID,那么我们可能正在执行
git merge br2
或
git merge br3
。(我会留下绘制结果图表的练习,但请注意,与以前一样,唯一移动的
名称是
blarg
。)
无论如何,这是说的一个冗长的方式,即使你可以获得某人作为参数发出的分支的
名称 - 而且通常可以:它被隐藏在
.git/MERGE_MSG
中 - 它实际上并不重要。在Git中,分支名称几乎无关紧要。重要的是提交。
那么你能做什么呢?
“我试图强制执行的规则是,除非满足某些条件,否则用户不应该能够将其特性分支与主分支合并。如果有更好的挂钩可以使用,则也会有所帮助。Prepare-commit-msg是唯一具有提交类型作为参数的钩子。”
听起来真正的目标是禁止提交导致
任何新提交或提交出现在
master
,除非这些新提交符合某些约束条件。当然,我不知道你的约束条件是什么,我只能注意到几个问题:
git merge
在自动成功合并时完全跳过常规的pre-commit
和commit-msg
钩子。因此,您需要使用prepare-commit-msg
钩子来尽早捕获这个问题。
但是,如果prepare-commit-msg
钩子在git merge
期间退出非零,则合并仍在进行中。随后的git commit
将提交合并。这个操作会运行pre-commit
和commit-msg
钩子(不像自动合并成功)。同样,退出非零虽然阻止了提交,但合并仍在进行中,准备好被提交。
用户始终可以跳过这些钩子(或不设置它们)。要真正强制执行某些内容,您需要在提交进入您控制的某个存储库时进行此操作。在许多典型的设置中,这意味着在一个集中式存储库中,个人开发人员将其工作git push
。您可以在pre-receive
或update
钩子中执行此强制执行(以及通过Gitlite及其更高级的系统)。
所有这些说法,可能仍然很不错,以便在个人开发者端执行一些规则,以便他们不会做很多工作并认为一切都很好,然后去推送并且推送失败。处理
此事 的最简单方法是编写一个包装器供某人使用:而不是直接运行
git checkout master; git merge featureX
,他们运行您的包装器,该包装器进行预检查,然后只有在看起来不错的情况下才会
调用 git merge
。
您仍然可以在集中服务器上实施严格的强制执行,以确保开发人员没有绕过规则。但是,您为他们提供了一个帮助工具,并说:“如果您想避免在非常晚的时候绊倒规则,请使用此工具。”
git
中是否可能,因为prepare-commit-msg
钩子甚至不会在fast-forward
合并时运行。 - Arkadiusz Drabczyk