使用`git for-each-ref`和`git log`在源上的每个远程分支上显示最近的提交

dum*_*dad 8 git

完成git fetch --all --prune从远程存储库获取refs后,我现在想要查看每个分支上的最新提交origin

命令

git for-each-ref --format='%(refname:short)' | grep 'origin/'
Run Code Online (Sandbox Code Playgroud)

列出所有十六个分支origin,因此我希望以下命令显示每个分支的最新提交

git for-each-ref --format='%(refname:short)' | grep 'origin/' | 
xargs git log --source -n 1 
Run Code Online (Sandbox Code Playgroud)

(注意,当我运行它时,这是一行;为了便于阅读,我将它拆分为两行.)

但是该命令不起作用,它只列出一个提交:似乎一个提交限制适用于整个列表而不是依次应用于每个分支.

我究竟做错了什么?

(请注意,我也尝试在此处调整解决方案

git for-each-ref --format='%(refname:short)' | grep 'origin/' | 
xargs git show --oneline 
Run Code Online (Sandbox Code Playgroud)

但是该--oneline标志被忽略,结果太冗长了.)

Von*_*onC 7

一个更简单的解决方案是使用git ls-remote origin:

git ls-remote --heads origin
Run Code Online (Sandbox Code Playgroud)

例如,在git repo中:

C:\Users\vonc\prog\git\git>git ls-remote --heads origin|
117eea7eaaeb5ecb77d9b7cebdb40b4e85f37374        refs/heads/maint
f5b6079871904ba5b0a8548f91545f126caf898b        refs/heads/master
edb03e5a9b9b63d0864557f99f339b2b5f3a9e4e        refs/heads/next
014438bc5bdf9deef0d3888e58c9f76addc1106c        refs/heads/pu
56f24e80f0af4dd3591c8f143183b59cf9a34620        refs/heads/tmp
33f854ca9eb8251f5b7fa1c670d4abcdd76764ce        refs/heads/todo
Run Code Online (Sandbox Code Playgroud)

这将列出最近的提交......即使没有先获取!

这可以轻松格式化和别名:

C:\Users\vonc\prog\git\git>
git config alias.rh "!git ls-remote -h origin | while read b; do PAGER='' git log -n1 --color --pretty=format:'%ct%C(yellow)%d%Creset - %Cred%h%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset%n' --abbrev-commit $( echo $b | cut -d' ' -f1 ) --; done | sort -rn -k1,10 | cut -c11-"
Run Code Online (Sandbox Code Playgroud)

然后一个简单的git rh将给出:

C:\Users\vonc\prog\git\git>git rh
 (origin/master, origin/HEAD) - f5b6079 Second batch for 2.7 (3 months ago) <Junio C Hamano>
 (origin/next, next) - edb03e5 Sync with 2.1-rc2 (1 year, 5 months ago) <Junio C Hamano>
 (origin/tmp, tmp) - 56f24e8 completion: handle '!f() { ... }; f' and "!sh -c '...' -" aliases (1 year, 7 months ago) <Steffen Prohaska>
 (origin/pu) - 014438b Merge branch 'nd/multiple-work-trees' into pu (1 year, 10 months ago) <Junio C Hamano>
 (origin/todo) - 33f854c What's cooking (2013/07 #09) (2 years, 5 months ago) <Junio C Hamano>
 (tag: v1.8.3.4, origin/maint) - 117eea7 Git 1.8.3.4 (2 years, 6 months ago) <Junio C Hamano>
Run Code Online (Sandbox Code Playgroud)

那是:

git rh


这个别名假设遥控器被命名为"origin".

要使其接受参数,可以将其更改为函数:

C:\Users\vonc\prog\git\git>git config alias.rh "!f() { git ls-remote -h $1 | while read b; do PAGER='' git log -n1 --pretty=format:'%h%n' --abbrev-commit $( echo $b | cut -d' ' -f1 ) --; done; }; f"
                                                                        ^^
Run Code Online (Sandbox Code Playgroud)

然后:

C:\Users\vonc\prog\git\git>git rh upstream
833e482
7548842
ef7b32d
f67e31e
e2281f4
Run Code Online (Sandbox Code Playgroud)


and*_*ann 5

问题是 git log 只打印一个 ref 的日志,这就是为什么你的 xargs 调用不起作用。如果您例如调用git log -n 1 origin/master origin/not_master(使用 xargs 将导致这样的调用),您将获得最新提交的日志,然后该列表仅限于第一个条目。我不知道如果这两个分支出现分歧,究竟会发生什么,但是,您仍然会将完整的日志输出限制为只有一个条目。

除了 VonC 的详细答案之外,如果您将 git log 命令包装在循环中而不是使用 xargs,则可以修改您的命令以获得所需的结果:

for ref in $(git for-each-ref --format='%(refname:short)' | grep 'origin/')
do
    git --no-pager log $ref -n 1 --oneline
done
Run Code Online (Sandbox Code Playgroud)

使用 --no-pager 选项将输出直接发送到控制台。


dum*_*dad 5

结合 Andrew C 对原帖的评论,即模式匹配可以包含在 git 命令中(而不是使用 grep),andreas-hofmann 的观点(在他的回答中)xargs 正在混淆参数,那么另一种可能的解决方案是

git for-each-ref --format='%(refname:short)' refs/remotes/origin/ | xargs -n1 git log --max-count=1 --source
Run Code Online (Sandbox Code Playgroud)

这会将模式匹配交换到 git 命令中,并告诉 xargs 一次最多提供一个参数。

(注意 git 的 for-each-ref 命令中的模式匹配从匹配开始,所以我必须使用 'refs/remotes/origin/' 而不是可以与 grep 一起使用的模式 'origin/'。我为简洁起见,可以将 --max-count=1 替换为 -1。)