获取传递给git合并命令的分支名称

3

我正在编写一个 prepare-commit-msg(作为 pre-merge 的钩子),需要获取合并的源分支名称并传递给 REST API。换句话说,我需要从 git merge <branchname> 中获取 branchname 的值。

到目前为止,我已经尝试了 rev-parse MERGE_HEAD,但似乎在 hook 触发时还没有设置它。目前,我只是使用 git revparse --abbrev-ref @{-1} 来获取我最后所在的分支,但这并不一定是我要合并的分支。

我正在尝试执行的规则是,除非满足某些条件,否则用户不能将其功能分支与主分支合并。如果有更好的钩子来实现这一点,那也会有所帮助。Prepare-commit-msg 是唯一一个似乎具有提交类型参数的钩子。


我不确定在 git 中是否可能,因为 prepare-commit-msg 钩子甚至不会在 fast-forward 合并时运行。 - Arkadiusz Drabczyk
好的。我已经关闭了快进式合并,并且只使用拉取请求操作。我希望他们早点添加预合并钩子 :( - COPatrick
1个回答

4
到目前为止,我已经尝试解析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? 它可能是提交ABC中的任何一个。 如果它是提交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 br2git merge br3。(我会留下绘制结果图表的练习,但请注意,与以前一样,唯一移动的名称blarg。)
无论如何,这是说的一个冗长的方式,即使你可以获得某人作为参数发出的分支的名称 - 而且通常可以:它被隐藏在.git/MERGE_MSG中 - 它实际上并不重要。在Git中,分支名称几乎无关紧要。重要的是提交。
那么你能做什么呢?
“我试图强制执行的规则是,除非满足某些条件,否则用户不应该能够将其特性分支与主分支合并。如果有更好的挂钩可以使用,则也会有所帮助。Prepare-commit-msg是唯一具有提交类型作为参数的钩子。”
听起来真正的目标是禁止提交导致任何新提交或提交出现在master,除非这些新提交符合某些约束条件。当然,我不知道你的约束条件是什么,我只能注意到几个问题:
  • git merge在自动成功合并时完全跳过常规的pre-commitcommit-msg钩子。因此,您需要使用prepare-commit-msg钩子来尽早捕获这个问题。

  • 但是,如果prepare-commit-msg钩子在git merge期间退出非零,则合并仍在进行中。随后的git commit将提交合并。这个操作会运行pre-commitcommit-msg钩子(不像自动合并成功)。同样,退出非零虽然阻止了提交,但合并仍在进行中,准备好被提交。

  • 用户始终可以跳过这些钩子(或不设置它们)。要真正强制执行某些内容,您需要在提交进入您控制的某个存储库时进行此操作。在许多典型的设置中,这意味着在一个集中式存储库中,个人开发人员将其工作git push。您可以在pre-receiveupdate钩子中执行此强制执行(以及通过Gitlite及其更高级的系统)。

所有这些说法,可能仍然很不错,以便在个人开发者端执行一些规则,以便他们不会做很多工作并认为一切都很好,然后去推送并且推送失败。处理 此事 的最简单方法是编写一个包装器供某人使用:而不是直接运行 git checkout master; git merge featureX,他们运行您的包装器,该包装器进行预检查,然后只有在看起来不错的情况下才会 调用 git merge
您仍然可以在集中服务器上实施严格的强制执行,以确保开发人员没有绕过规则。但是,您为他们提供了一个帮助工具,并说:“如果您想避免在非常晚的时候绊倒规则,请使用此工具。”

那个,@torek,你的回答很好!感谢你抽出时间来做这一切。那回答了我的问题。我想我会采用包装器路线。我认为这是一个不错的短期解决方案。从长远来看,我想我会选择服务器端钩子。但我们正在使用Bitbucket服务器,将他们的插件SDK放到我们的隔离网络上有点麻烦...官僚主义和所有爵士乐...再次感谢你的帮助! - COPatrick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接