我的组织广泛使用git分支。因此,我们在过去一年中已经生产了2000多个分支机构。我们现在正在尝试采取一种策略来清理所有特定年龄的旧分支。我知道如何删除分支,但我找不到一种简单的方法来列出具有给定年龄的所有分支。计划是建立一个cron,定期删除给定年龄的所有分支,但某些列表中的分支除外。
之前有没有人尝试过这样的事情?
答案 0 :(得分:19)
使用提交者日期的答案是一个很好的方向...如果你想删除指向旧提交的分支。但是你可能想要删除实际上很旧的分支;如果您今天创建一个指向去年提交的分支,您不希望它被擦除!
所以,你想要检查一下reflog日期。
您可以使用git reflog show --date=local mybranch
8b733bc mybranch@{Tue Mar 22 13:21:49 2011}: commit: foo
7e36e81 mybranch@{Tue Mar 22 13:21:25 2011}: commit: bar
99803da mybranch@{Tue Mar 22 13:20:45 2011}: branch: Created from otherbranch
(您可能也喜欢--date=relative
)
顶部的条目是该分支上发生的最新事情,所以我们关心的是这一点。不幸的是,日期没有日志格式占位符,所以为了抓住日期,我们做了一些工作:
git log -g -n 1 --date=local --pretty=%gd mybranch | sed 's/.*{\(.*\)}/\1/'
# Prints "Mon Mar 21 13:23:26 2011"
当然,对于脚本来说,这不是很有用,所以让我们继续前进并获得大纪元时间:
git log -g -n 1 --date=raw --pretty=%gd mybranch | sed 's/.*{\(.*\) .*/\1/'
# Prints 1300731806
现在我们到了某个地方!
#!/bin/bash
cutoff_date=$(date --date="July 23, 2010" +%s)
git for-each-ref refs/heads --format='%(refname)' | while read branch; do
reflog_date=$(git log -g -n 1 --date=raw --pretty=%gd $branch -- | sed 's/.*{\(.*\) .*/\1/')
if [ -n "$reflog_date" && "$reflog_date" -lt "$cutoff_date" ]; then
git branch -D ${branch#refs/heads/}
fi
done
示例脚本!我使用date
来转换截止的人类可读日期,然后对于每个分支,我检查了reflog的最后日期是否在截止之前,如果是,则删除分支。您可以在那里添加对白名单的检查,以避免意外删除您关心的内容。 (编辑:如果分支超过90天,这将不会删除它们,因为他们的reflogs已经是空的......在这种情况下你真正想要做什么。你可以回到检查提交日期,此时应该非常安全。)
编辑:这是另一种方法。在截止时间使reflogs到期,然后删除reflog为空的分支。这里的问题是,如果截止时间早于您的reflogs已经过期的时间(90天),那么它实际上只是删除超过90天的分支。当然,你可以解决这个问题。
#!/bin/bash
# Git lets you use very readable time formats!
cutoff_time="1 year ago"
# other examples:
# cutoff_time="July 23, 2010"
# cutoff_time="yesterday"
git for-each-ref refs/heads --format='%(refname)' | egrep -v 'master|other-whitelisted-branch' |
while read branch; do
git reflog expire --expire="$cutoff_time" $branch
if [ "$(git reflog show -1 $branch | wc -l)" -eq 0 ]; then
git branch -D ${branch#refs/heads/}
fi
done
答案 1 :(得分:4)
更新:如Jefromi和cebewee所示,此解决方案会查看每个分支提示的提交的“提交者日期”,在某些情况下,这不会是足够好 - 使用前者的示例,如果您关心最近基于较旧分支创建的分支,则需要使用Jefromi's answer中的reflog。我认为在很多情况下,这已经足够了,所以我要离开答案而不是删除它......
我最近对此进行了blog post,其中一个脚本按照该分支上最后一次提交日期的递增顺序列出了分支,我发现这对你的情况非常类似。该脚本基于git for-each-ref --sort=committerdate
:
#!/bin/sh
for C in $(git for-each-ref --sort=committerdate refs/heads --format='%(refname)')
do
git show -s --format="%ci $C" "$C"
done
答案 2 :(得分:1)
您需要编写脚本,然后使用它来获取日期:
git log -1 branchName --format=%ci
这应该为您提供可以订购的日期。
现在你只需要遍历分支:
for branch in $(git branch -r); do yourscript $branch; done
希望这会有所帮助。
答案 3 :(得分:1)
我最终得到了这个解决方案:
for k in $(git branch -r | awk -F/ '/\/Your_prefix_here/{print $2}' | sed /\*/d); do
if [ -z "$(git log -1 --since='Jul 31, 2015' -s origin/$k)" ]; then
echo deleting "$(git log -1 --pretty=format:"%ct" origin/$k) origin/$k";
fi;
done
它也按照给定的模式过滤分支,因为我们使用try-XX约定进行分支。
答案 4 :(得分:0)
要找出分支最后更改的时间(与分支中最后一次提交的日期相对),您需要使用reflog。 git reflog branchName -1--date=relative
为分支显示最新的reflog条目以及最后一次更改分支的日期。
有各种不同的日期格式,请选择一个易于解析的用例。
此解决方案的一个问题是,在IIRC的90天内,reflog默认过期。因此,如果分支上的最后一次更改超过90天(并且您需要gc),则不会获得有关此分支的任何信息。您可以通过更改reflog的过期时间来避免这种情况,请参阅git-config。
答案 5 :(得分:0)
一个非常简单的解决方案,并不总是有效:
只需查看.git/refs/heads/
并按修改日期排序即可。
请注意,如果存储库是较新的或某种情况,这将无效,因为git根本不会跟踪此类信息。但是,如果你有一个中央存储库,它可能会在以后很好地工作,否则它不会发生太大变化。