在Git中列出每个分支及其最后修订的日期


138

我需要从我们的远程存储库中删除旧的和未维护的分支。我正在尝试找到一种方法来列出远程分支的上次修改日期,但我做不到。

有没有一种简单的方法可以这样列出远程分支?



3
答案:stackoverflow.com/questions/5188320/…都比这里的答案要好
软件工程师

Answers:


172

commandlinefu有两个有趣的主张:

for k in `git branch | perl -pe s/^..//`; do echo -e `git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k -- | head -n 1`\\t$k; done | sort -r

要么:

for k in `git branch | sed s/^..//`; do echo -e `git log -1 --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k --`\\t"$k";done | sort

这是使用Unix语法的本地分支。使用git branch -r,您可以类似地显示远程分支:

for k in `git branch -r | perl -pe 's/^..(.*?)( ->.*)?$/\1/'`; do echo -e `git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k -- | head -n 1`\\t$k; done | sort -r

Michael Forrest 在评论中提到zsh需要对sed表达式进行转义:

for k in git branch | perl -pe s\/\^\.\.\/\/; do echo -e git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k -- | head -n 1\\t$k; done | sort -r 

kontinuity 在评论中添加:

如果要将其添加到zshrc,则需要以下转义。

alias gbage='for k in `git branch -r | perl -pe '\''s/^..(.*?)( ->.*)?$/\1/'\''`; do echo -e `git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k -- | head -n 1`\\t$k; done | sort -r'

在多行中:

alias gbage='for k in `git branch -r | \
  perl -pe '\''s/^..(.*?)( ->.*)?$/\1/'\''`; \
  do echo -e `git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k -- | \
     head -n 1`\\t$k; done | sort -r'

注:n8tr答案的基础上,git for-each-ref refs/heads更干净。而且更快
另请参阅“ 仅命名选项git branch --list ”。

更普遍地说,三元组在评论中提醒我们:

  • 优先使用现代$(command substitution)语法而不是过时的反引号语法。

(我在2014年用“ shell编程shell编程什么区别?$(command)`command` ” 说明了这一点。)


1
@hansen j:有趣,不是吗?它在Stack Overflow公开发布(codeinthehole.com/archives/…)几个月后启动,并受到SO的启发。另请参阅commandlinefu.com/commands/tagged/67/git以获得更多git commandlinefu;)
VonC 2010年

这个答案将启动stackoverflow.com/questions/5188320/…的屁股。:)
Spundun

@SebastianG不确定:这本身就是一个好问题。
VonC

+1非常棒,您可以将其添加/json到任何commandlinefu.com URL 的末尾,并且将所有命令作为JSON获得。
Noah Sussman 2013年

1
@tripleee谢谢。我已经编辑了答案,并附上了您的评论,以提高知名度。
VonC

121

这是我用的:

git for-each-ref --sort='-committerdate:iso8601' --format=' %(committerdate:iso8601)%09%(refname)' refs/heads

这是输出:

2014-01-22 11:43:18 +0100       refs/heads/master
2014-01-22 11:43:18 +0100       refs/heads/a
2014-01-17 12:34:01 +0100       refs/heads/b
2014-01-14 15:58:33 +0100       refs/heads/maint
2013-12-11 14:20:06 +0100       refs/heads/d/e
2013-12-09 12:48:04 +0100       refs/heads/f

对于远程分支,只需使用“ refs / remotes”而不是“ refs / heads”:

git for-each-ref --sort='-committerdate:iso8601' --format=' %(committerdate:iso8601)%09%(refname)' refs/remotes

基于n8tr的答案,如果您也对该分支的最后一位作者感兴趣,并且您拥有可用的“列”工具,则可以使用:

git for-each-ref --sort='-committerdate:iso8601' --format='%(committerdate:relative)|%(refname:short)|%(committername)' refs/remotes/ | column -s '|' -t

这会给你:

21 minutes ago  refs/remotes/a        John Doe
6 hours ago     refs/remotes/b        Jane Doe
6 days ago      refs/remotes/master   John Doe

您可能需要先调用“ git fetch --prune”,以获取最新信息。


5
很好地使用for-each-ref和format选项。+1。听起来比我在自己的答案中引用的命令容易。
VonC 2014年

2
稍作调整:------- git for-each-ref --sort ='-authordate:iso8601'--format ='%(authordate:relative)%09%(refname:short)'refs / heads -------给您一个相对的日期并消除裁判/裁判的作用
n8tr 2014年

1
对于那些不是立即显而易见的人,我认为这可以显示信息。严格针对当地分支机构。
hBrent

@hBrent您是正确的,它没有完全回答问题。我已经相应地编辑了答案。
ocroquette '16

这对分支进行排序并列出依据authordate(似乎是第一次创建分支时?)。如果更改authordate为,committerdate那么您将在每个分支中看到最近提交的日期。像这样:git for-each-ref --sort='-committerdate:iso8601' --format=' %(committerdate:iso8601)%09%(refname)' refs/heads
Logan Besecker '17

23

建立在Olivier Croquette的基础上,我喜欢使用相对日期并缩短分支名称,如下所示:

git for-each-ref --sort='-authordate:iso8601' --format=' %(authordate:relative)%09%(refname:short)' refs/heads

给您输出:

21 minutes ago  nathan/a_recent_branch
6 hours ago        master
27 hours ago    nathan/some_other_branch
29 hours ago    branch_c
6 days ago      branch_d

我建议制作一个Bash文件以添加所有您喜欢的别名,然后将脚本共享给您的团队。这是添加此示例的示例:

#!/bin/sh

git config --global alias.branches "!echo ' ------------------------------------------------------------' && git for-each-ref --sort='-authordate:iso8601' --format=' %(authordate:relative)%09%(refname:short)' refs/heads && echo ' ------------------------------------------------------------'"

然后,您可以执行以下操作以获取格式正确且经过排序的本地分支列表:

git branches

20

只需添加@VonC的注释,就可以采用您喜欢的解决方案并将其添加到〜/ .gitconfig别名列表中,以方便使用:

[alias]  
    branchdate = !git for-each-ref --sort='-authordate' --format='%(refname)%09%(authordate)' refs/heads | sed -e 's-refs/heads/--'

然后,一个简单的“ git branchdate”将为您打印列表。


3
+1显示如何与.gitconfig一起使用!同样,我将格式字符串更改为:--format='%(authordate)%09%(objectname:short)%09%(refname)'它也获取每个分支的短哈希。
Noah Sussman 2013年

真好 我将在末尾添加“ | tac”,以便以相反的顺序对其进行排序,以便可以很快看到最近触及的分支。

1
你并不需要| tac,只是--sort='authordate'代替-authordate
克里斯蒂安·

4

这也是我在对此进行回顾之后想到的。

for REF in $(git for-each-ref --sort=-committerdate --format="%(objectname)" \
    refs/remotes refs/heads)
do
    if [ "$PREV_REF" != "$REF" ]; then
        PREV_REF=$REF
        git log -n1 $REF --date=short \
            --pretty=format:"%C(auto)%ad %h%d %s %C(yellow)[%an]%C(reset)"
    fi
done

PREV_REF检查是消除重复,如果超过一个分支指向相同的提交。(就像在远程存在的本地分支中一样。)

注意,这是根据OP请求的,git branch --merged并且git branch --no-merged在识别可以轻松删除的分支时很有用。

[ https://git-scm.com/docs/git-branch]


3

排序的远程分支和每个分支的最后提交日期。

for branch in `git branch -r | grep -v HEAD`;do echo -e `git show --format="%ci %cr" $branch | head -n 1` \\t$branch; done | sort -r

1
感谢您提出有关遥控器的OP问题。
arcseldon

1

根据VonC的答案,我做了两个变体。

我的第一个变种:

for k in `git branch -a | sed -e s/^..// -e 's/(detached from .*)/HEAD/'`; do echo -e `git log -1 --pretty=format:"%Cgreen%ci |%Cblue%cr |%Creset$k |%s" $k --`;done | sort | column -t -s "|"

这处理本地和远程分支(-a),处理分离头状态(较长的sed命令,尽管解决方案有点粗糙-它只是用关键字HEAD替换分离的分支信息),添加了提交主题(%s ),然后通过格式字符串中的文字竖线字符将内容放入列中,并将最终结果传递给column -t -s "|"。(您可以使用任何东西作为分隔符,只要它在其余的输出中是您所不期望的即可。)

我的第二个变种非常hacky,但是我确实想要一种仍然可以像“分支”命令那样显示“这是您当前正在使用的分支”的指示器。

CURRENT_BRANCH=0
for k in `git branch -a | sed -e 's/\*/CURRENT_BRANCH_MARKER/' -e 's/(detached from .*)/HEAD/'`
do
    if [ "$k" == 'CURRENT_BRANCH_MARKER' ]; then
        # Set flag, skip output
        CURRENT_BRANCH=1
    elif [ $CURRENT_BRANCH == 0 ]; then
        echo -e `git log -1 --pretty=format:"%Cgreen%ci |%Cblue%cr |%Creset$k |%s" $k --`
    else
        echo -e `git log -1 --pretty=format:"%Cgreen%ci |%Cblue%cr |%Creset* %Cgreen$k%Creset |%s" $k --`
        CURRENT_BRANCH=0
    fi
done | sort | column -t -s "|"

这会将*标记当前分支的转换为关键字,并且当循环主体看到关键字时,它会设置一个标志并且不输出任何内容。该标志用于指示下一行应使用替代格式。就像我说的那样,它完全是hacky,但是可以用!(通常。由于某种原因,我的最后一列在当前分支行上已被淘汰。)


不幸的是,VonC答案中的信息并不是编写脚本的良好基础。看到这里git-blame.blogspot.com/2013/06/…–
Andrew C

嗯 这显示了一种获取当前分支名称(如果它具有名称)的方法。有没有[首选]方法来获得机器友好的分支列表?(以及通过当前输出直接或通过某种方式询问git来区分当前分支的某种方法“这与HEAD相同吗?”)
benkc 2014年

git for-each-ref是处理脚本的脚本友好方式。您必须运行一次symbolic-ref才能获取当前分支。
2014年

+1为努力,但这确实是我的答案。stackoverflow.com/a/16971547/6309或(更完整)stackoverflow.com/a/19585361/6309涉及的“ sed”较少。
VonC 2014年

1

我做了一个简单的别名,不确定这是否是正确的要求,但是很简单

我这样做是因为我想列出所有分支,而不仅仅是我的本地分支,以上命令仅列出这些分支

alias git_brs="git fetch && git branch -av --format='\''%(authordate)%09%(authordate:relative)%09%(refname)'\'"

您可以通过管道grep origin仅获取来源

该列表列出了所有分支以及最近修改的日期,可帮助我确定我应该拉哪个版本的最新版本

这导致以下显示类型

Wed Feb 4 23:21:56 2019 +0230   8 days ago      refs/heads/foo
Tue Feb 3 12:18:04 2019 +0230   10 days ago     refs/heads/master
Mon Feb 9 12:19:33 2019 +0230   4 days ago      refs/heads/bar
Wed Feb 11 16:34:00 2019 +0230  2 days ago      refs/heads/xyz
Tue Feb 3 12:18:04 2019 +0230   10 days ago     refs/remotes/origin/HEAD
Mon Feb 9 12:19:33 2019 +0230   4 days ago      refs/remotes/origin/foo
Tue Feb 3 12:18:04 2019 +0230   10 days ago     refs/remotes/origin/master
Tue Feb 3 12:18:04 2019 +0230   10 days ago     refs/remotes/origin/bar
Tue Feb 3 12:18:04 2019 +0230   10 days ago     refs/remotes/origin/xyz

尝试让我知道是否有帮助


漂亮又简单。没有特殊的酱料。
MrMas

0

或者您可以使用我的PHP脚本https://gist.github.com/2780984

#!/usr/bin/env php
<?php
    $local = exec("git branch | xargs $1");
    $lines = explode(" ", $local);
    $limit = strtotime("-2 week");
    $exclude = array("*", "master");
    foreach ($exclude as $i) {
        $k = array_search($i, $lines);
        unset($lines[$k]);
    }
    $k = 0;
    foreach ($lines as $line) {
        $output[$k]['name'] = $line;
        $output[$k]['time'] = exec('git log '.$line.' --pretty=format:"%at" -1');
        if ($limit>$output[$k]['time']) {
            echo "This branch should be deleted $line\n";
            exec("git branch -d $line");
        }
        $k++;
    }
?>

0

您可以将以下功能添加到您的bash_profile中,以使其变得更容易。

在Git存储库中的用法:

  • branch 打印所有本地分支
  • branch -r 打印所有远程分支

功能:

branch() {
   local pattern="s/^..//"
   local arg=""
   if [[ $@ == "-r" ]]; then
      pattern="s/^..(.*?)( ->.*)?$/\1/"
      arg=" -r "
      echo '-r provided'
   fi
   for k in $(git branch $arg | perl -pe "$pattern"); do
      echo -e $(git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k -- | head -n 1)\\t$k
   done | sort -r
}

0

在PowerShell中,以下内容显示了已合并且已存在至少两周的远程分支(该author:relative格式开始显示几周而不是两周后的天数):

$safeBranchRegex = "origin/(HEAD|master|develop)$";
$remoteMergedBranches = git branch --remote --merged | %{$_.trim()};
git for-each-ref --sort='authordate:iso8601' --format=' %(authordate:relative)%09%(refname:short)' refs/remotes | ?{$_ -match "(weeks|months|years) ago" -and $_ -notmatch "origin/(HEAD|master|qa/)"} | %{$_.substring($_.indexof("origin/"))} | ?{$_ -in $remoteMergedBranches}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.