根据定义,任何分支中的最后一次提交是存储在分支名称中的哈希 ID。
鉴于您使用refs/remotes/origin/blah 查看origin/blah,而不是分支名字,你在看你自己的远程跟踪名称.这些是复制自其他一些 Git 存储库的分支名称,因此它们具有相同的属性。但这些不是分支名称,它们是远程跟踪名称。 (在其他一些 Git 存储库中,它们是或当时是分支名称。现在,它们可能是字面上的秒过时了。无论出于何种目的,您都需要确保一切正常。考虑运行git fetch --prune 或git remote update --prune,这样它只有几秒钟,而不是几分钟、几小时或更长时间。)
您现有的代码有一个(轻微的)缺陷,如下所示:
$ echo remotes/origin/feature/one/two/three/four | cut -d"/" -f 3,4,5
feature/one/two
但是,您应该使用 Git,而不是使用 git branch -a管道命令,git for-each-ref,在这里。这使您可以使用%(refname:short):
$ git for-each-ref --format='%(refname:short)' refs/remotes
origin/HEAD
origin/main
origin/maint
origin/master
origin/next
origin/seen
origin/todo
例如。您可能仍想放弃 HEAD 符号引用和 master 之一,但您现在可以直接获取提交哈希 ID:
$ git for-each-ref --format='%(objectname) %(refname:short)' refs/remotes
9bf691b78cf906751e65d65ba0c6ffdcd9a5a12c origin/HEAD
9bf691b78cf906751e65d65ba0c6ffdcd9a5a12c origin/main
ad60dddad72dfb8367bd695028b5b8dc6c33661b origin/maint
9bf691b78cf906751e65d65ba0c6ffdcd9a5a12c origin/master
91fe8e635439f67be8837601cbf4bd61eddc41b4 origin/next
d0cdfd77733ad946e8c60e9b50286778fb813e56 origin/seen
59d992158534c8291f548563a9c949dae4ad7796 origin/todo
像以前一样通过grep -v 将其通过管道丢弃/master 和/HEAD:
$ git for-each-ref --format='%(objectname) %(refname:short)' refs/remotes | grep -E -v '/master$|/HEAD$'
9bf691b78cf906751e65d65ba0c6ffdcd9a5a12c origin/main
ad60dddad72dfb8367bd695028b5b8dc6c33661b origin/maint
91fe8e635439f67be8837601cbf4bd61eddc41b4 origin/next
d0cdfd77733ad946e8c60e9b50286778fb813e56 origin/seen
59d992158534c8291f548563a9c949dae4ad7796 origin/todo
可以直接拒绝for-each-ref 中不需要的名称,但要复杂得多,无论如何我们都必须运行git log 来获取作者信息,所以我们不妨将for-each-ref 部分留在这里。
不过,我们现在应该做的是管道输出至一个外壳脚本。该脚本可以:
- 从提交中获取更多信息,例如作者和提交者姓名;
- 计算任何其他提交的提前和/或落后计数,包括由
refs/remotes/origin/master 标识的提交;
- 根据需要格式化输出。
从这里开始,它是简单的 shell 编程,有一个警告:没有与 git log 等效的管道,因此您必须在此处使用瓷器命令。有关所有可用的 % 指令,请参阅 PRETTY FORMATS section of the git log documentation。
要计算哈希 $h 与 refs/remotes/origin/master 相比提交的前后值,请使用 git rev-list --count --left-right:
$ git rev-list --count --left-right d0cdfd77733ad946e8c60e9b50286778fb813e56...refs/remotes/origin/master
253 0
这表明 origin/seen 比 origin/master 提前 253 倍,在 origin/master 之后为零(或等效地,origin/master 比 origin/seen 提前 0 倍,落后 253 倍)。请注意,这需要三点语法,并且不依赖于上游设置。
虽然git log -1 --format=%ad d0cdfd77733ad946e8c60e9b50286778fb813e56 工作正常:
$ git log -1 --format=%ad d0cdfd77733ad946e8c60e9b50286778fb813e56
Wed Aug 17 15:47:50 2022 -0700
我个人更喜欢git log --no-walk。可以将多个提交哈希 ID 写入 git log --no-walk(例如,使用 --stdin),而 -1 则不是这种情况。在这种特殊情况下,您想一次控制所有项目,但没有压倒一切的理由更喜欢--no-walk。
您的最终脚本可能类似于:
git for-each-ref --format='%(objectname) %(refname:short)' refs/remotes |
grep -E -v '/master$|/HEAD$' |
while read hash ref; do
author=$(git log --no-walk --format="%an (%ae)" $hash);
authordate=$(git log --no-walk --format="%ad" $hash);
aheadbehind=$(git rev-list --count --left-right $hash...origin/master);
... insert other items here as desired ...
echo "$ref,$hash,$author,$authordate,$aheadbehind,..."
done > output-csv.csv
或类似的。
如果您只想要“领先”计数,而不是领先和落后,请注意git rev-list --count refs/remotes/origin/master..$hash(注意:二点,没有--left-right) 获得该数字。
这个能够以牺牲可读性为代价,提高效率。通过在指定的哈希上使用单个 git log 调用可能会获得最大的效率提升:您可能能够以正确的格式生成大部分您想要的信息。但是请注意,某人的姓名可能包含逗号(或任何您的 CSV 文件分隔符)。清理文本总是明智的。当Little Bobby Tables 出现时,您不想成为负责数据库的学校管理员。