我想获得Git存储库中所有分支的列表,其中“最新”分支位于顶部,“最新的”分支是最近提交的分支(因此,更可能是我想关注的分支)。

有没有一种方法可以使用Git(a)按最新提交对分支列表进行排序,或者(b)以某种机器可读格式将分支列表与每个分支的最后提交日期一起获取?

最坏的情况是,我总是可以运行gitbranch获取所有分支的列表,解析其输出,然后运行git-log-n 1 branchname--format=format:%ci获取每个分支的提交日期。但这将在Windows环境下运行,在那里启动一个新进程相对昂贵,因此如果有很多分支,每个分支启动一次Git可执行文件可能会很慢。有没有一种方法可以用一个命令完成所有这些?


当前回答

其他答案似乎不允许传递-vv来获得详细的输出。

所以这里有一个单行程序,按照提交日期、保存颜色等对gitbranch-vv进行排序:

git branch -vv --color=always | while read; do echo -e $(git log -1 --format=%ct $(echo "_$REPLY" | awk '{print $2}' | perl -pe 's/\e\[?.*?[\@-~]//g') 2> /dev/null || git log -1 --format=%ct)"\t$REPLY"; done | sort -r | cut -f 2

如果您还想打印提交日期,可以使用以下版本:

git branch -vv --color=always | while read; do echo -e $(git log -1 --format=%ci $(echo "_$REPLY" | awk '{print $2}' | perl -pe 's/\e\[?.*?[\@-~]//g') 2> /dev/null || git log -1 --format=%ci)" $REPLY"; done | sort -r | cut -d ' ' -f -1,4-

样本输出:

2013-09-15   master                  da39a3e [origin/master: behind 7] Some patch
2013-09-11 * (detached from 3eba4b8) 3eba4b8 Some other patch
2013-09-09   my-feature              e5e6b4b [master: ahead 2, behind 25] WIP

拆分成多行可能更易读:

git branch -vv --color=always | while read; do
    # The underscore is because the active branch is preceded by a '*', and
    # for awk I need the columns to line up. The perl call is to strip out
    # ansi colors; if you don't pass --color=always above you can skip this
    local branch=$(echo "_$REPLY" | awk '{print $2}' | perl -pe 's/\e\[?.*?[\@-~]//g')
    # git log fails when you pass a detached head as a branch name.
    # Hide the error and get the date of the current head.
    local branch_modified=$(git log -1 --format=%ci "$branch" 2> /dev/null || git log -1 --format=%ci)
    echo -e "$branch_modified $REPLY"
# cut strips the time and timezone columns, leaving only the date
done | sort -r | cut -d ' ' -f -1,4-

这也应该与git分支的其他参数一起使用,例如-vvr列出远程跟踪分支,或-vva列出远程跟踪和本地分支。

其他回答

我发现以下命令对我的目的很有用。

git branch --sort=-committerdate | head -n 10

这将列出最新的10个分支。它很短,也可以在没有别名的情况下使用。

我使用以下别名:

最近=“!r(){count=$1;每个ref的git--sort=-committedate-refs/heads--format='%(HEAD)%(颜色:黄色)%(refname:short)|%(颜色∶粗体绿色)%(committedate:relative)|%

其产生:

我们还可以给出自定义计数。,

git最近20(默认值为10)。

git2.7(2015年第4季度)将引入直接使用git分支的分支排序:请参见提交aa3bc55、提交aedcb7d、提交1511b22、提交f65f139。。。(2015年9月23日),提交aedcb7d,提交1511b22,提交ca41799(2015年12月24日),并提交f65f139。。。(2015年9月23日)Karthik Nayak(Karthik纳亚克)。(2015年10月15日,Junio C Hamano(吉斯特)在提交第7f11b48页时合并)

特别是提交aedcb7d:

branch.c:使用“ref filter”API

使“branch.c”使用“ref filter”API来迭代ref排序。这将删除替换它的“branch.c”中使用的大部分代码调用“ref filter”库。

它添加了选项--sort=<key>:

根据给定的关键字排序。前缀-按值的降序排序。您可以多次使用--sort=<key>选项,在这种情况下,最后一个键将成为主键。支持的密钥与git for each-ref中的密钥相同。排序顺序默认为基于完整的refname(包括refs/…前缀)进行排序。首先列出分离的HEAD(如果存在),然后列出本地分支,最后列出远程跟踪分支。

在这里:

git branch --sort=-committerdate 

或者(见下文Git 2.19)

# if you are sure to /always/ want to see branches ordered by commits:
git config --global branch.sort -committerdate
git branch

另见Karthik Nayak(KarthikNayak)的承诺9e46833(2015年10月30日)。帮助人:Junio C Hamano(吉斯特)。(由Junio C Hamano--gitster合并,提交415095f,2015年11月3日)

当根据数值排序时(例如--sort=objectsize),当两个引用都保持相同值时,不会进行回退比较。如Johannes Sixt($gmane/280117)所指出的,这可能会导致意外结果(即,不能预先确定列出具有相等值的引用的顺序)。因此,回退到基于refname的字母比较只要其他标准相等。$git分支--sort=objectsize*(HEAD与fromtag分离)分支二分支一主人


使用Git 2.19,可以默认设置排序顺序。gitbranch支持一个configbranch.sort,就像git标记,它已经有了一个configtag.sort。参见Samuel Maftoul(“”)的承诺560ae1c(2018年8月16日)。(于2018年8月27日由Junio C Hamano--gitster在提交d89db6f中合并)

分支排序:

此变量控制由gitbranch显示的分支的排序顺序。如果不提供“--sort=<value>”选项,将使用此变量的值作为默认值。


要列出远程分支,请使用gitbranch-r--sort=objectsize。-r标志使其列出远程分支而不是本地分支。


在Git 2.27(2020年第二季度)中,“Git branch”和其他“for each ref”变体接受了多个--sort=<key>选项,其优先级递增,但在“--ignore case”处理方面存在一些漏洞,以及与refname的连接中断,这些问题已得到解决。

参见Jeff King(peff)的承诺7c5045f,承诺76f9e56(2020年5月3日)。(由Junio C Hamano--gitster合并,于2020年5月8日提交6de1630)

ref筛选器:仅在所有用户排序后应用回退refname排序签字人:Jeff King

提交9e468334b4(“ref-filter:fallback on alphabetic comparison”,2015-10-30,Git v2.7.0-rc0--第10批中列出的合并)教导ref-filter的排序回退到比较参考名。但它在错误的级别执行了这一操作,覆盖了来自用户的单个“--sort”键的比较结果,而不是在所有排序键都用完之后。这对于一个“--sort”选项是正确的,但对于多个选项则不正确。我们将打破第一个键与refname之间的任何联系,并且永远不会计算第二个键。为了让事情变得更有趣,我们有时只应用了这种回退!对于像“taggeremail”这样需要字符串比较的字段,我们确实会返回strcmp()的结果,即使它是0。但对于“taggerdate”等数字“value”字段,我们确实应用了回退。这就是为什么我们的多重排序测试忽略了这一点:它使用taggeremail作为主要比较。因此,让我们从添加一个更严格的测试开始。我们将有一组提交,表达两个标签电子邮件、日期和参考名的每一个组合。然后,我们可以确认我们的排序应用了正确的优先级,我们将同时命中字符串和值比较器。这确实显示了错误,修复方法很简单:在所有ref_sorting键都用完之后,将回退移到外部compare_refs()函数。注意,在外部函数中,我们没有“ignore_case”标志,因为它是每个单独ref_sorting元素的一部分。由于我们没有使用用户的密钥进行匹配,因此这种回退应该做什么是值得商榷的。但到目前为止,我们一直在努力尊重这面旗帜,所以最不具侵略性的事情就是继续这样做。由于当前代码中的所有调用方要么为所有键设置标志,要么为无设置标志,因此我们只能从第一个键中提取标志。在一个假设的世界中,用户真的可以分别翻转按键的不区分大小写,我们可能需要扩展代码以将这种情况与“忽略大小写”区分开来。


“git-branch--sort”(man)的实现写入了分离的HEAD显示,它一直都是破解的,git 2.31(2021第1季度)对此进行了清理。

请参阅提交4045f65、提交2708ce6、提交7c269a7、提交d094748、提交75c50e5(2021 1月7日),以及提交08bf6a8、提交ffdd02a(2021 1月6日),作者为瓦尔·阿恩弗·比亚马森(avar)。(由Junio C Hamano——gitster——于2021 1月25日提交9e409d7合并)

branch:在反向排序下首先显示“HEAD detached”签字人:Ævar ArnfjörěBjarmason

更改类似“gitbranch-l-sort=-objectsize”(man)的输出,以在输出的开头显示“(HEAD detached at<hash>)”消息。在前面的提交中添加compare_dedetached_head()函数之前,我们会将此输出作为紧急效果发出。为了进行排序,考虑“(HEAD detached at<hash>)”消息的对象大小、类型或其他非属性没有任何意义。让我们总是在顶部发射。首先对其进行排序的唯一原因是,我们将其注入到ref过滤器机制中,因此内置/branch.c不需要进行自己的“我分离了吗?”检测。


在Git 2.35(2022年第1季度)中,类似于“Git-c branch.sort=伪分支new HEAD”(man),即。不需要排序键信息的“gitbranch”(man)命令的操作模式不再因看到伪排序键而出错。

参见Junio C Hamano(gitster)的commit 98e7ab6,commit 1a89796(2021 10月20日)。(由Junio C Hamano——gitster——于2021 11月29日提交5126145合并)

对于每个ref:延迟解析--sort=<atom>选项

for-each ref命令系列在看到每个--sort=<atom>选项时立即调用解析器,当<atom>未被识别时,甚至在命令行上看到其他选项之前就终止。相反,将它们累积在字符串列表中,并在命令行解析完成后将它们解析为ref_sorting结构。因此,“gitbranch-sort=fake-h”(man)过去无法提供简短的帮助,这可能是一个特性,现在可以了,这与其他选项的工作方式更加一致。

下面是我用来在最近的分支之间切换的一个小脚本:

#!/bin/bash
# sudo bash

re='^[0-9]+$'

if [[ "$1" =~ $re ]]; then
    lines="$1"
else
    lines=10
fi
branches="$(git recent | tail -n $lines | nl)"
branches_nf="$(git recent-nf | tail -n $lines | nl)"
echo "$branches"

# Prompt which server to connect to
max="$(echo "$branches" | wc -l)"
index=
while [[ ! ( "$index" =~ ^[0-9]+$ && "$index" -gt 0 && "$index" -le "$max" ) ]]; do
    echo -n "Checkout to: "
    read index
done

branch="$( echo "$branches_nf" | sed -n "${index}p" | awk '{ print $NF }' )"
git co $branch
clear

使用这两个别名:

recent = for-each-ref --sort=committerdate refs/heads/ --format=' %(color:blue) %(authorname) %(color:yellow)%(refname:short)%(color:reset)'
recent-nf = for-each-ref --sort=committerdate refs/heads/ --format=' %(authorname) %(refname:short)'

只需在Git存储库中调用它,它将显示最后N个分支(默认为10个)和每个分支旁边的数字。输入分支机构的编号,它将签出:

对每个ref使用git的--sort=-committendate选项;

从Git 2.7.0开始,Git分支也可用:

基本用法:

git for-each-ref --sort=-committerdate refs/heads/

# Or using git branch (since version 2.7.0)
git branch --sort=-committerdate  # DESC
git branch --sort=committerdate  # ASC

结果:

高级用法:

git for-each-ref --sort=committerdate refs/heads/ --format='%(HEAD) %(color:yellow)%(refname:short)%(color:reset) - %(color:red)%(objectname:short)%(color:reset) - %(contents:subject) - %(authorname) (%(color:green)%(committerdate:relative)%(color:reset))'

结果:

Pro用法(Unix):

您可以在~/.gitconfig中放入以下代码段。recentb别名接受两个参数:

refbranch:前面和后面的列是根据哪个分支计算的。默认主机计数:显示最近的分支。默认值20

[alias]
    # ATTENTION: All aliases prefixed with ! run in /bin/sh make sure you use sh syntax, not bash/zsh or whatever
    recentb = "!r() { refbranch=$1 count=$2; git for-each-ref --sort=-committerdate refs/heads --format='%(refname:short)|%(HEAD)%(color:yellow)%(refname:short)|%(color:bold green)%(committerdate:relative)|%(color:blue)%(subject)|%(color:magenta)%(authorname)%(color:reset)' --color=always --count=${count:-20} | while read line; do branch=$(echo \"$line\" | awk 'BEGIN { FS = \"|\" }; { print $1 }' | tr -d '*'); ahead=$(git rev-list --count \"${refbranch:-origin/master}..${branch}\"); behind=$(git rev-list --count \"${branch}..${refbranch:-origin/master}\"); colorline=$(echo \"$line\" | sed 's/^[^|]*|//'); echo \"$ahead|$behind|$colorline\" | awk -F'|' -vOFS='|' '{$5=substr($5,1,70)}1' ; done | ( echo \"ahead|behind||branch|lastcommit|message|author\\n\" && cat) | column -ts'|';}; r"

结果: