Show most recent commit on each remote branch on o

2020-06-14 23:14发布

Having done git fetch --all --prune to fetch refs from the remote repositories I now want to see the most recent commit on each of the branches on origin

The command

git for-each-ref --format='%(refname:short)' | grep 'origin/'

lists all sixteen branches on origin, and so I would expect the following command to show the most recent commit from each one

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

(N.B. This is one line when I run it; I have split it over two for readability.)

However the command does not work, it only lists one commit: it seems the one commit limit applies to the entire list and not to each branch in turn.

What am I doing wrong?

(Note that I have also tried to adapt the solution here

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

but the --oneline flag is ignored and the result is too verbose.)

标签: git
3条回答
你好瞎i
2楼-- · 2020-06-14 23:25

The problem is that git log only prints the log of one ref, that is why your xargs call is not working. If you e.g. call git log -n 1 origin/master origin/not_master (using xargs will result in a call like this) you'll get the log up to the most recent commit and that list is then limited to the first entry. I don't know what exactly will happen if the two branches have diverged, but still, you'll limit the complete log output to only one entry.

Additionally to VonC's detailed answer, you can modify your command to achieve the desired result if you wrap the git log command in a loop instead of using xargs:

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

Use the --no-pager option to send the output directly to the console.

查看更多
成全新的幸福
3楼-- · 2020-06-14 23:37

Combining Andrew C's comment on the original post, that the pattern matching can be included in the git command (instead of using grep), with andreas-hofmann's point (in his answer) that xargs is conflating arguments, then another possible solution is this

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

This swaps the pattern matching to occur in the git command and tells xargs to provide at most one argument at a time.

(N.B. The pattern matching in git's for-each-ref command goes from the start of the match so I have to use 'refs/remotes/origin/' instead of the pattern 'origin/' which I could use with grep. And I could replace --max-count=1 with -1 for brevity.)

查看更多
老娘就宠你
4楼-- · 2020-06-14 23:46

A simpler solution is to use git ls-remote origin:

git ls-remote --heads origin

For example, in the 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

That will list the most recent commits... even without fetching first!

That can be formatted and aliases easily:

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-"

Then a simple git rh would give:

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>

That is:

git rh


This alias assume the remote is named 'origin' though.

To make it accept a parameter, it can be changed to a function:

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"
                                                                        ^^

Then:

C:\Users\vonc\prog\git\git>git rh upstream
833e482
7548842
ef7b32d
f67e31e
e2281f4
查看更多
登录 后发表回答