获取Git仓库的最后提交

8
我有一个中央Git bare仓库。当向该仓库进行推送时,我想运行post-receive hook。该hook将使用Basecamp API在项目中创建一条消息。我想获取刚刚执行的更新信息。目前,我认为git log -2 --stat已经足够好了,但是希望能获得更多信息(更新的分支,新建的文件,删除的文件)。请问是否有人可以帮助我找到需要执行的命令?对于我来说,执行多个命令也没问题,可能没有单个命令可以获取所有信息。
3个回答

3
你可以通过检查和排序.git/refs/heads下的文件来找到最新的提交记录:每当进行新提交时,相应的refs/heads文件会被更改,即当提交到master时,refs/heads/master会被更新。

因此,让我们开发一个解决方案。

第一项任务:找到所有分支(即refs/heads下的所有文件),并打印出它们最后一次更改的时间。由于你要谈论钩子,所以我们给出相对于.git/hooks目录的路径:

find ../refs/heads -type f -printf '%T@ %p\n'

这将生成一个包含所有分支及其更改日期的列表。请参阅find命令的man页面以了解参数说明。
第二个任务:对获取的列表进行排序。
find ../refs/heads -type f -printf '%T@ %p\n' |\
sort

第三步: 我们需要获取列表中最新的元素。由于sort是按照从旧到新的顺序排序的,我们所需的项目位于列表底部。使用tail获取此元素(只有一个元素,因此传递-1标志):

find ../refs/heads -type f -printf '%T@ %p\n' |\
sort    |\
tail -1
第四步: 从获取的行中删除日期。从我们的printf语句中可以知道,日期和路径是用空格分隔的。将其作为分隔符输入到cut中 (-d " "),告诉它我们需要第二个字段(即文件路径, -f 2)。为了方便,我们将该文件路径存储在名为$LATESTHEAD的变量中:
LATESTHEAD=$(\
    find ../refs/heads -type f -printf '%T@ %p\n' |\
    sort    |\
    tail -1 |\
    cut -d ' ' -f 2 )

第五项任务:现在我们知道了文件名,但是我们需要内容。这是可以通过git log传递的最新修订版。使用cat命令来完成任务。将最新修订版存储在$LATESTREV中。

LATESTHEAD=$(\
    find ../refs/heads -type f -printf '%T@ %p\n' |\
    sort    |\
    tail -1 |\
    cut -d ' ' -f 2 )
LATESTREV=$(cat $LATESTHEAD)

现在,你可以使用$LATESTREV来执行任何你想做的“肮脏”操作。

可能不是最优雅的解决方案(可能有人会想出一个更简单的一行代码),但对我有效。


这实际上也很有效。我还需要分支名称,因此我想我必须先运行 第三个任务 以获取分支名称。之后我运行 第五个任务 以获取提交哈希值。之后我运行 git log --stat -1 <commit-hash-here> 以获取完整的提交信息。奇怪的是我不得不添加 -1。如果我不添加它,它会给我所有的东西... 奇怪。无论如何,看起来像是有效的!谢谢eckes! - Jeebs24
抱歉为了推销我的答案,但我不理解为什么你要在这里使用find,如果所有信息都是通过stdin由git调用post-receive时提供的(参见githooks(5))。 - Jonas Schäfer

2

在 git log 命令中添加 --summary 选项将会生成新文件和被删除文件的列表(git 将它们称为“节点”):

git log --stat --summary -1

要获取分支,请尝试运行以下命令:
git branch --contains `git log --oneline -1 |cut -f1 -d\ ` |cut -b3-

注意:我正在我的Mac上进行测试。Unix中的cut是从1开始索引,但我相信Debian中的cut是从0开始索引的。如果是这样,并且您在Debian环境下,将-f1更改为-f0,那么分支命令应该可以正常工作。

2
如果你没有特别的理由使用post-receive,我建议使用update,它会将旧的引用、新的引用和分支作为命令行参数。因此,你可以使用这里建议的git log命令来获取整个日志,并将oldref..newref作为参数(分别替换oldrefnewref)。更多信息请参见githooks(5) manpage on the update hook。你甚至可以在那一点上中止更新,如果需要的话。实际上,在post-receive钩子上,你可以通过标准输入获得相同的信息。我不明白为什么需要执行很多find命令来完成这个任务。

我该如何获取oldrefnewref的信息?我对Git和钩子非常陌生。我已经成功将我的Git仓库连接到了Basecamp,并且运行得很好。但是,如果有更好的方法并且我可以获得更多信息,那就更好了。我打算阅读一下githooks(5)手册,但如果您能提供相同的信息,我将不胜感激。 - Jeebs24
好的,我将切换到“update”钩子。感谢建议,乔纳斯。 - Jeebs24
这个很好用。但请注意,如果您使用 post-receive 钩子,就像使用 update 钩子一样,您无法中止操作(请参见此处):该钩子不会影响 git receive-pack 的结果,因为它是在真正的工作完成后调用的。 - compuphys

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