Per*_*ver 5 git tree branch hierarchy git-branch
我怎样才能获得只有最终分支(不是任何其他提交的父级)的分支列表 - 换句话说,分支是提交树的提示(最终节点).我期待一些选项,如git branch命令中的--final或--tips,但只有--merged, - no-merged和--contains选项.
更新以处理任何数量的分支、任何类型的提示:
git for-each-ref --format='%(objectname)^{commit}' \
| git cat-file --batch-check='%(objectname)^!' \
| grep -v missing \
| git log --oneline --stdin
Run Code Online (Sandbox Code Playgroud)
这是相当可调整的,您可以限制您正在寻找的提示类型,仅列出那些带有 for-each-ref 的参考,您可以为标签提示添加更多排除项,等等。
已经有一些有用的答案,但没有给出所要求的内容:列表或分支(对我来说,这意味着分支名称,而不是提交 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"
}
Run Code Online (Sandbox Code Playgroud)
结果如下:
** 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
Run Code Online (Sandbox Code Playgroud)
整理东西时,您可能想看到非尖端分支。这是获取它们列表的方法。唯一的改变是&&成为||。
{
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"
}
Run Code Online (Sandbox Code Playgroud)
结果如下:
** 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
Run Code Online (Sandbox Code Playgroud)
您可以根据需要进行装饰,例如更改:
echo $branchname
Run Code Online (Sandbox Code Playgroud)
进入
echo -e "$branchname\t$commitid\t$message"
Run Code Online (Sandbox Code Playgroud)
结果如下所示:
** 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
Run Code Online (Sandbox Code Playgroud)
然后,您可以在您最喜欢的工具中查看这些分支,看看删除它们是否有意义。
由于分支只是在工作目录中处于活动状态时添加新提交时移动的标签 - 所有分支“根据定义”都是树的叶节点。
但我认为您要求的是那些与另一个分支的叶提交没有共同祖先的分支。这样您就需要C和E,但不需要A下面的B或。D
-A-o-B-o-C
\
D-o-E
Run Code Online (Sandbox Code Playgroud)
如果是这种情况,则可以找到不共享共同祖先(即另一个分支的叶提交)的所有分支的列表。例如,D并共享 的当前叶子提交E的共同祖先。D
这可能可以通过脚本来完成,但我不知道有哪个 git 命令可以为您、所有分支执行此操作。但 git 过去曾让我感到惊讶,因为它可以通过其(有时是晦涩的)命令参数的组合来完成。
在您发表评论后,我做了更多思考,我想我更好地理解为什么您的要求作为命令不可能(或可能有用)。这是因为像这样的命令git merge --squash <branch>不会创建合并提交。创建的提交只是另一个常规提交——不包含任何表明它来自另一个分支的内容。
例如,从以下内容开始:
-A-o-B-o-C
\
D-o-E
Run Code Online (Sandbox Code Playgroud)
并且 with HEADatC命令会将索引中git merge --squash E包含的所有更改准备好提交。E一旦提交,树就会看起来像
-A-o-B-o-o-C <== notice branch `C` has moved forward one commit
\
D-o-E
Run Code Online (Sandbox Code Playgroud)
现在的提交C包含所有更改,D-o-E没有说明它来自哪里。 D-o-E现在可能不需要,但是除了项目知识之外什么也没有可以告诉你这一点。
了解了您想要做的事情将是一个手动过程;我确实想到了几个命令可以帮助您确定是否可以删除分支。
此git log命令生成仅包含已修饰的提交(分支、标签和 HEAD)的图表。
git log --all --graph --oneline --simplify-by-decoration --decorate
Run Code Online (Sandbox Code Playgroud)
运行它会给你一个视觉效果,让你快速看到“终点”分支在哪里。提示:添加>> <filename>.txt将图形转储到可以用铅笔标记的文本文件。
此外,一旦您确定了要保留的“端点”分支,请运行以下命令以查看来自 的分支的祖先列表<branch>。这列出了完全合并(通过合并提交)到<branch>.
git branch --merged <branch>
Run Code Online (Sandbox Code Playgroud)
这可能并不完全是您想要的——但正如我上面所解释的,我认为这是不可能的。希望这些命令能有所帮助。