Seb*_*lis 11 git hook git-submodules githooks
我正在尝试update为git 编写一个钩子,如果子模块被更新为子模块的上游存储库中不存在的提交ID,则会跳转.换句话说,我想强制用户在将更改推送到子模块指针之前将更改推送到子模块存储库.
一个警告:
我一直在玩一个想法,但感觉必须有一个更好的方法来做到这一点.这是我计划在更新钩子中做的事情:
refs/heads/.如果没有,请尽早退出.git rev-list得到被推版本列表.git show <revision_id>并使用一个正则表达式,查看子模块是否已更新(通过搜索`+子项目提交[0-9a-f] +)..gitmodules特定commit(git show <revision_id>:.gitmodules)所看到的文件内容.cd到3.4中找到的路径并执行git rev-parse --quiet --verify <updated_submodule_commit_id>以查看该存储库中是否存在该提交.如果没有,则以非零状态退出.(注意:我相信3.2的结果可能会在修订版本中缓存,只要输出git rev-parse --quiet --verify <revision_id>:.gitmodules不会从一个修订版更改为下一个修订版.我将此部分留下来以简化解决方案.)
所以是的,这看起来相当复杂,我不禁想知道是否有一些内部git命令可能会让我的生活变得更轻松.或者也许有不同的方式来思考这个问题?
稍后编辑:从 Git 1.7.7 开始,git-push现在有一个--recurse-submodules=check选项,如果任何子模块提交尚未推送到其远程,则拒绝推送父项目。似乎push.recurseSubmodules还没有添加相应的配置参数。这当然并不能完全解决问题 - 无知的用户仍然可以在没有检查的情况下推送 - 但它非常相关!
我认为最好的方法是查看所有推送的提交之间的差异,而不是检查每个单独的提交:git diff <old> <new>。不过,你确实不想查看整个差异;它可能是巨大的。不幸的是, git-submodule Ceramic 命令在裸存储库中不起作用,但您仍然应该能够快速检查.gitmodules以获取路径列表(也许还有 URL)。对于每一个,您都可以git diff <old> <new> -- path,如果存在差异,则获取新的子模块提交。(如果你担心 000000 旧提交的可能性,git show我相信你可以只使用新的提交。)
一旦处理完所有这些,您就可以将问题简化为检查给定的提交是否存在于给定的远程存储库中。不幸的是,正如您所注意到的,这并不简单,至少据我所知。保留本地的、最新的克隆可能是你最好的选择,而且听起来你在这方面做得很好。
顺便说一句,我认为缓存在这里无关紧要,因为更新挂钩每个引用一次。是的,您可以在预接收挂钩中执行此操作,该挂钩获取标准输入上的所有引用,但我不明白为什么您应该费心做更多工作。这不会是一项昂贵的操作,并且通过更新挂钩,您可以单独接受或拒绝正在推送的各个分支,而不是因为只有一个分支不好而阻止所有分支更新。
如果你想省点麻烦,我可能会避免解析 gitmodules 文件,并将列表硬编码到钩子中。我怀疑你的子模块列表经常变化,所以维护它可能比编写自动化的东西更便宜。