【问题标题】:Get list of final branches (which are final tips)获取最终分支列表(这是最终提示)
【发布时间】:2013-02-02 15:16:27
【问题描述】:

我怎样才能得到一个分支列表,这些分支只是最终分支(不是任何其他提交的父级) - 换句话说,分支是提交树的提示(最终节点)。 我希望在git branch 命令中有一些选项,例如 --final 或 --tips,但只有 --merged、--no-merged 和 --contains 选项。

【问题讨论】:

  • 由于 Git 保存的是提交的父节点而不是子节点,因此在历史图中找到叶节点(您描述的“提示”)并不那么简单。编写一个脚本来找出你想知道的内容相对容易,但它需要遍历你的 repo 中的所有提交。
  • 我想找到可以被我删除的分支。例如,如果我将删除非叶节点提示中的分支,我将为我清理无用的分支。任何非最终分支都可以恢复,因为它们的提交将在树内。

标签: git tree branch hierarchy git-branch


【解决方案1】:

已经有一些有用的答案,但没有给出所要求的:一个列表或分支(对我来说,这意味着分支名称,而不是提交 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

获取非提示分支名称列表

在整理东西时,您可能希望看到非尖端的分支。这是一种获取它们列表的方法。唯一的变化是&amp;&amp; 变成了||

{
        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

然后,您可以在自己喜欢的工具中查看这些分支,看看是否可以删除它们。

【讨论】:

    【解决方案2】:
    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'
    

    【讨论】:

      【解决方案3】:

      如果你得到一个所有 ref 的列表,你可以列出所有不是另一个 ref 的父级的 ref:

      refs=`git show-ref -s`
      git log --oneline --decorate $refs --not `echo "$refs" | sed 's/$/^/'`
      

      这通过过滤掉所有父提交来工作。

      【讨论】:

      • 我认为这行不通:并非所有的 refs 在refs 目录中都有文件,其中一些在packed-refs 文件中。
      • 另外,由于某种原因,您的代码对我来说根本不起作用:它不会返回任何内容。
      • No git show-refs 有 git show-ref 但是你的行没有输出 你想用 s/$/^/ 做什么?例如: $ echo $refs 722aaacadeb64136d19dab91c7516682c2a8c796 3b242412889ca1101914c2834858ebdc9efa4839 refs之间有空格。我试过 s/ /\n/g 但它没有帮助定义叶节点:(
      • 我在看什么。又遗留了一个问题。如何验证所有这些 refs 是否在另一个 repo 中,我可以安全地删除该 repo。有选择吗?
      【解决方案4】:

      由于分支只是在工作目录中处于活动状态时添加新提交时移动的标签——所有分支都是树的“定义”叶节点。

      但我认为您要的是那些与另一个分支的叶子提交没有共同祖先的分支。这样您就需要CE,而不是ABD

      -A-o-B-o-C
            \
             D-o-E
      

      如果是这样,就有可能找到所有不共享共同祖先的所有分支的列表,即另一个分支的叶子提交。例如,DE 共享 D 的当前叶提交的共同祖先。

      这很可能通过脚本来完成,但我不知道有一个 git 命令可以为您完成所有分支。但是 git 过去让我感到惊讶,它可以通过组合(有时是晦涩的)命令参数来完成。


      在您发表评论后,我做了更多思考,我想我更好地理解了为什么您的要求不可能(或可能有用)作为命令。这是因为像 git merge --squash &lt;branch&gt; 这样的命令不会创建合并提交。创建的提交只是另一个常规提交 - 没有任何内容表明它来自另一个分支。

      例如,开始于:

      -A-o-B-o-C
            \
             D-o-E
      

      使用HEAD C 命令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
      

      运行此程序将为您提供视觉效果,让您可以快速查看“端点”分支的位置。提示:添加&gt;&gt; &lt;filename&gt;.txt 将图形转储到可以用铅笔标记的文本文件中。

      此外,一旦您确定了要保留的“端点”分支,请运行以下命令以查看来自 &lt;branch&gt; 的分支的祖先列表。这是列出完全合并(通过合并提交)到&lt;branch&gt; 的分支。

      git branch --merged <branch>
      

      这可能不是您想要的——但正如我上面解释的那样,我认为这不可能。希望这些命令会有所帮助。

      【讨论】:

      • 是的,我想在您的示例中找到 C 和 E 分支,而不是 A、B、D。例如,我有一个包含许多分支的存储库,我想清理分支引用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-23
      • 2018-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多