162

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

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

4

11 回答 11

191

commandlinefu有 2 个有趣的命题:

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

更一般地说,triplee在评论中提醒我们:

  • 比过时的反引号语法更喜欢现代$(command substitution)语法。

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

  • 不要阅读带有for.
  • 可能切换到git for-each-ref refs/remote以机器可读格式获取远程分支名称
于 2010-03-25T09:24:41.393 回答
140

这是我使用的:

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”以获取最新信息。

于 2014-01-23T09:49:38.103 回答
32

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
于 2014-05-29T22:20:40.673 回答
21

Just to add to the comment by @VonC, take your preferred solution and add it to your ~/.gitconfig alias list for convenience:

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

Then a simple "git branchdate" prints the list for you...

于 2013-02-27T16:58:43.087 回答
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 --mergedgit branch --no-merged对于确定可以轻松删除哪些分支很有用。

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

于 2015-06-18T00:34:50.637 回答
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
于 2015-06-01T13:19:48.380 回答
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( ),并通过格式字符串中的文字管道字符将内容放入列中,并将最终结果传递给column -t -s "|". (你可以使用任何东西作为分隔符,只要它是你在输出的其余部分不期望的东西。)

我的第二个变体非常老套,但我真的想要一些仍然像分支命令一样具有“这是您当前所在的分支”的指示符的东西。

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,但它确实有效!(大多数情况下。出于某种原因,我的最后一列在当前分支线上出现了缩进。)

于 2014-11-05T22:36:44.547 回答
1

在 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}
于 2017-01-24T17:34:21.670 回答
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

试着让我知道它是否有帮助,快乐的 gitting

于 2019-12-12T04:07:36.030 回答
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++;
    }
?>
于 2012-05-24T11:54:04.100 回答
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
}
于 2016-03-14T15:39:39.367 回答