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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2514172/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 08:07:06  来源:igfitidea点击:

Listing each branch and its last revision's date in Git

gitmaintenanceadministrationbranch

提问by Roni Yaniv

I need to delete old and unmaintained branches from our remote repository. I'm trying to find a way with which to list the remote branches by their last modified date, and I can't.

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

Is there an easy way to list remote branches this way?

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

回答by VonC

commandlinefuhas 2 interesting propositions:

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

or:

或者:

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

That is for local branches, in a Unix syntax. Using git branch -r, you can similarly show remote branches:

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

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


Michael Forrestmentions in the commentsthat zsh requires escapes for the sedexpression:

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 

kontinuityadds in the comments:

连续性在评论中补充道:

If you want to add it your zshrc the following escape is needed.

如果您想将它添加到您的 zshrc 中,则需要以下转义符。

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

In multiple lines:

在多行中:

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


Note: n8tr's answer, based on git for-each-ref refs/headsis cleaner. And faster.
See also "Name only option for git branch --list?"

注意:基于n8tr答案git for-each-ref refs/heads更干净。而且速度更快
另请参阅“仅命名选项git branch --list

More generally, tripleeereminds us in the comments:

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

  • Prefer modern $(command substitution)syntax over obsolescent backtick syntax.
  • $(command substitution)比过时的反引号语法更喜欢现代语法。

(I illustrated that point in 2014 with "What is the difference between $(command)and `command`in shell programming?")

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

  • Don't read lines with for.
  • Probably switch to git for-each-ref refs/remoteto get remote branch names in machine-readable format
  • 不要阅读带有for.
  • 可能切换到git for-each-ref refs/remote以机器可读格式获取远程分支名称

回答by ocroquette

Here is what I use:

这是我使用的:

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

This is the output:

这是输出:

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

For remote branches, just use "refs/remotes" instead of "refs/heads":

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

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

Building on n8tr's answer, if you are also interested in the last author on the the branch, and if you have the "column" tool available, you can use:

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

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

Which will give you:

这会给你:

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

You may want to call "git fetch --prune" before to have the latest information.

您可能希望在获得最新信息之前调用“git fetch --prune”。

回答by n8tr

Building off of Olivier Croquette, I like using a relative date and shortening the branch name like this:

基于Olivier Croquette,我喜欢使用相对日期并像这样缩短分支名称:

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

Which gives you output:

这给你输出:

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

I recommend making a Bash file for adding all your favorite aliases and then sharing the script out to your team. Here's an example to add just this one:

我建议制作一个 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 ' ------------------------------------------------------------'"

Then you can just do this to get a nicely formatted and sorted local branch list:

然后你可以这样做来获得一个格式化和排序的本地分支列表:

git branches

回答by yngve

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

只是添加到@VonC 的评论中,为方便起见,将您的首选解决方案添加到您的 ~/.gitconfig 别名列表中:

[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...

然后一个简单的“git branchdate”为你打印列表......

回答by go2null

Here is what I came up with after also reviewing this.

这是我在回顾了这个之后想到的。

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

The PREV_REFcheck is to remove duplicates if more than one branch points to the same commit. (As in a local branch that exist in the remote as well.)

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

NOTE that per the OP request, git branch --mergedand git branch --no-mergedare useful in identifying which branches can be easily deleted.

注意,按照OP请求,git branch --mergedgit branch --no-merged在识别该分支可以被容易地删除有用。

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

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

回答by shweta

Sorted remotebranches and the last commit date for each branch.

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

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

回答by Basav

I did a simple alias, not sure if this is what exactly asked, but it is simple

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

I did this as i wanted to list all the branches not just my local branches, which above commands do only

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

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

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

You can pipe above to grep originto get only origins

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

This lists all the branches along with the last date modified, helps me decide which one i should pull for latest version

这列出了所有分支以及最后修改的日期,帮助我决定我应该为最新版本拉取哪个

This results in below type of display

这导致以下类型的显示

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

Try and let me know if it helped, happy gitting

尝试让我知道它是否有帮助,祝你快乐

回答by benkc

I made two variants, based on VonC's answer.

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

My first variant:

我的第一个变体:

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

This handles local and remote branches (-a), handles detached-head state (the longer sed command, though the solution is kind of crude -- it just replaces the detached branch info with the keyword HEAD), adds in the commit subject (%s), and puts things into columns via literal pipe characters in the format string and passing the end result to column -t -s "|". (You could use whatever as the separator, as long as it's something you don't expect in the rest of the output.)

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

My second variant is quite hacky, but I really wanted something that still has an indicator of "this is the branch you're currently on" like the branch command does.

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

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

This turns the *that marks the current branch into a keyword, and when the loop body sees the keyword it instead sets a flag and outputs nothing. The flag is used to indicate that an alternate formatting should be used for the next line. Like I said, it is totally hacky, but it works! (Mostly. For some reason, my last column is getting outdented on the current branch line.)

这会将*标记当前分支的 标记为关键字,并且当循环体看到该关键字时,它会设置一个标志并且不输出任何内容。该标志用于指示下一行应使用替代格式。就像我说的,它完全是hacky,但它有效!(主要是。出于某种原因,我的最后一列在当前分支线上缩进了。)

回答by enderland

Here's a function you can add to your bash_profile to make this easier.

这是一个您可以添加到 bash_profile 中的函数,以简化此操作。

Usage when in a Git repository:

在 Git 存储库中的用法:

  • branchprints all local branches
  • branch -rprints all remote branches
  • branch打印所有本地分支
  • branch -r打印所有远程分支

Function:

功能:

branch() {
   local pattern="s/^..//"
   local arg=""
   if [[ $@ == "-r" ]]; then
      pattern="s/^..(.*?)( ->.*)?$//"
      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
}

回答by Dave Neeley

In PowerShell, the following shows branches on the remote that are already merged and at least two weeks old (the author:relativeformat starts displaying weeks instead of days at two weeks):

在 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}