我如何获得仅是最终分支(不是任何其他提交的父级)的分支列表 - 换句话说,分支是提交树的提示(最终节点)。我希望在命令中有一些选项,例如 --final 或 --tips,git branch
但只有 --merged、--no-merged 和 --contains 选项。
4 回答
已经有一些有用的答案,但没有给出要求的内容:列表或分支(对我来说,这意味着分支名称,而不是提交 ID)。
获取提示分支名称列表
{
echo "** Below is list of tip branches a.k.a. final nodes."
echo "** These aren't reachable from any other branches."
echo "** Removing them is potentially DANGEROUS: it would make some commit unreachable."
TIPS=$( git rev-list --branches --children | grep -v ' ' | sort )
{ while read branchname commitid message
do grep $commitid < <(echo $TIPS) -q && echo $branchname
done
} < <(git branch -v --no-abbrev | sed 's/\*//' )
echo "** end of list"
}
结果如下所示:
** Below is list of tip branches a.k.a. final nodes.
** These aren't reachable from any other branches.
** Removing them is potentially DANGEROUS: it would make some commit unreachable.
feature-workingonit
dev
** end of list
获取非提示分支名称列表
整理东西时,您可能希望看到非尖端分支。这是一种获取它们列表的方法。唯一的变化是&&
成为||
。
{
echo "** Below is list of non-tip branches a.k.a. inner nodes."
echo "** These are reachable from other branches."
echo "** If you remove them, all commits would stay reachable, but be careful anyway."
TIPS=$( git rev-list --branches --children | grep -v ' ' | sort )
{ while read branchname commitid message
do grep $commitid < <(echo $TIPS) -q || echo $branchname
done
} < <(git branch -v --no-abbrev | sed 's/\*//' )
echo "** end of list"
}
结果如下所示:
** Below is list of non-tip branches a.k.a. inner nodes.
** These are reachable from other branches.
** If you remove them, all commits would stay reachable, but be careful anyway.
feature-alreadymerged
master
** end of list
获取带有提交 ID 和消息的非提示分支名称列表
您可以根据需要进行装饰,例如通过更改:
echo $branchname
进入
echo -e "$branchname\t$commitid\t$message"
结果如下所示:
** Below is list of non-tip branches a.k.a. inner nodes.
** These are reachable from other branches.
** If you remove them, all commits would stay reachable, but be careful anyway.
feature-alreadymerged 426ac5186841876163970afdcc5774d46641abc4 Cool feature foo, ref task #1234
master 39148238924687239872eea425c0e837fafdcfd9 Some commit
** end of list
然后,您可以在您最喜欢的工具中查看这些分支,看看删除它们是否有意义。
git show -s --oneline --decorate $(
git show-branch --independent -a
)
或者
git show -s --format=%d $(
git show-branch --independent -a
)
也许sed
'd品尝。例如,每行拆分所有引用名称并去除分组标点符号
git show -s --format=%d $(git show-branch --independent -a) \
| sed 's/,/\n/g; s/[ ()]//g'
如果您获得所有 ref 的列表,则可以列出所有不是另一个 ref 的父级的 ref:
refs=`git show-ref -s`
git log --oneline --decorate $refs --not `echo "$refs" | sed 's/$/^/'`
这通过过滤掉所有父提交来工作。
由于分支只是在工作目录中处于活动状态时添加新提交时移动的标签——所有分支都是树的“定义”叶节点。
但是我认为您要的是那些与另一个分支的叶子提交没有共同祖先的分支。这样你想要C
and E
,但不是A
,B
orD
在下面。
-A-o-B-o-C
\
D-o-E
如果是这种情况,就有可能找到所有分支的列表,这些分支不共享一个共同的祖先,即另一个分支的叶子提交。例如,D
共享当前叶子提交E
的共同祖先。D
这很可能通过脚本来完成,但我不知道有一个 git 命令可以为您完成所有分支。但是 git 过去让我感到惊讶,因为它可以通过组合(有时是晦涩的)命令参数来完成。
在您发表评论后,我做了更多思考,我想我更好地理解了为什么您的要求不可能(或可能有用)作为命令。这是因为类似的命令git merge --squash <branch>
不会创建合并提交。创建的提交只是另一个常规提交——不包含任何表明它来自另一个分支的内容。
例如,从以下开始:
-A-o-B-o-C
\
D-o-E
并且 with HEAD
atC
命令git merge --squash E
将把包含在E
索引中的所有更改都准备好提交。一旦提交,树看起来像
-A-o-B-o-o-C <== notice branch `C` has moved forward one commit
\
D-o-E
现在的提交C
包含所有更改D-o-E
,没有说明它来自哪里。 D-o-E
现在可能不需要了,但除了项目知识外,没有什么可以告诉你的。
有了它,您就知道您要做的是手动过程;我确实想到了一些可以帮助您确定是否可以删除分支的命令。
此git log
命令仅生成已修饰的提交(分支、标签和 HEAD)的图表。
git log --all --graph --oneline --simplify-by-decoration --decorate
运行此程序将为您提供视觉效果,让您可以快速查看“端点”分支的位置。提示:添加>> <filename>.txt
以将图形转储到可以用铅笔标记的文本文件中。
此外,一旦您确定了要保留的“端点”分支,请运行以下命令以查看来自<branch>
. 这是列出完全合并(通过合并提交)到<branch>
.
git branch --merged <branch>
这可能不是你想要的——但正如我上面解释的那样,我认为这是不可能的。希望这些命令会有所帮助。