在更新挂钩中仅处理新提交的最佳方法

Best way to process only new commits in an update hook

我正在编写服务器端更新挂钩,并且只想处理推送之前不在存储库中的推送提交,即推送引入的提交。起初我打算做 git rev-list <oldrefvalue>..<newrefvalue>,但如果新提交之一是现有分支的合并,则可以包括现有提交。我想出了几种方法,none 其中让我兴奋的是:

  1. 对于 git rev-list <oldrefvalue>..<newrefvalue> 中的每个提交,执行 git rev-list --all | grep <commit> 以查看它是否是现有提交(显然我会缓存 git rev-list --all 的结果)。
  2. 执行 git for-each-ref --format="^%(objectname)" refs/heads | xargs git rev-list <newrefvalue> 以获取推送的引用可访问但无法通过任何现有分支访问的所有提交

这两种方法中的哪一种比另一种更可取,还是有更好的方法来解决这个问题?

假设你真的想使用 update 钩子,比如

git rev-list <newrefvalue> --not --branches --tags

应该做你需要的。它将跳过任何分支或标记中已经存在的所有提交。但是如果用相同的新提交推送多个分支,它将 运行 多次。您可以使用 pre-receive 挂钩来避免它,它会立即处理所有 ref 更新,并将整个新提交列表获取为:

git rev-list <newrefvalue1> <newrefvalue2> .. <newrefvalueN> --not --branches --tags

在简短的测试中,它似乎只输出一次提交。

请注意,它仅适用于 运行 ref 更新之前的挂钩,即 udpatepre-receive。例如,它不适用于 post-update