我需要从我们的远程存储库中删除旧的和未维护的分支。我正在尝试找到一种方法来按远程分支的最后修改日期列出远程分支,但我做不到。
有没有一种简单的方法可以以这种方式列出远程分支?
我需要从我们的远程存储库中删除旧的和未维护的分支。我正在尝试找到一种方法来按远程分支的最后修改日期列出远程分支,但我做不到。
有没有一种简单的方法可以以这种方式列出远程分支?
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
如果您想将它添加到您的 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`
? ”来说明这一点)
- 不要阅读带有
for
.- 可能切换到
git for-each-ref refs/remote
以机器可读格式获取远程分支名称
这是我使用的:
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”以获取最新信息。
在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
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...
这是我在查看此内容后得出的结论。
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
对于确定可以轻松删除哪些分支很有用。
排序的远程分支和每个分支的最后提交日期。
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
根据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,但它确实有效!(大多数情况下。出于某种原因,我的最后一列在当前分支线上出现了缩进。)
在 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}
我做了一个简单的别名,不确定这是否是确切要求的,但这很简单
我这样做是因为我想列出所有分支,而不仅仅是我的本地分支,上面的命令只做
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
或者你可以使用我的 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++;
}
?>
这是一个可以添加到 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
}