使用 Git,我如何显示所有共享一个共同祖先的提交树?

Posted

技术标签:

【中文标题】使用 Git,我如何显示所有共享一个共同祖先的提交树?【英文标题】:With Git, how can I show the tree of commits that all share a common ancestor? 【发布时间】:2015-11-03 21:46:27 【问题描述】:

假设我有一个“master”分支,一个为我的团队审查和批准更改的分支(称为“stage”),以及一堆基于 stage 分支的功能分支。 (这个想法是将更改分组为从阶段到主的公共拉取请求。)

如何根据阶段分支的“根”显示所有更改的日志?我希望能够看到该团队/主题正在进行的所有功能。用普通的 Git 术语来说,我怎样才能获得可以到达给定(根)提交的所有提交的日志?对于我的生活,我找不到办法做到这一点。我可以对具有共同祖先的两个分支执行此操作,但不适用于从共同祖先派生的 N 个分支。

【问题讨论】:

听起来你想要git merge-base --octopus(找到一个 N 分支合并基础,类似于通常的两个分支合并基础),然后是 git log <list of heads> ^<base> 但这是相当递归的。要获取包含给定提交的所有更改的列表,我需要提供包含该提交的所有提示的列表。如果我能做到这一点,我就快完成了。但我们可以从那里开始。所以我的推论问题是,给定一个提交,我怎样才能找到可以到达该提交的所有提示? git branch --contains <id> 将打印所有本地分支标签的列表,这些标签将该提交作为其分支提示的祖先。如果需要(可能不需要),添加-r 以包括远程跟踪分支。 (我从你的问题中得到的印象是你已经有了分支提示标签的列表。) 【参考方案1】:

我认为这可以通过结合使用git branch --contains <id>(正如torek 在对该问题的评论中所建议的那样)和git rev-list 的组合来完成。

具体来说,假设您对所有感兴趣的分支都有本地分支(如果没有,请尝试将-r-a 添加到git branches 命令),那么以下应该做我认为你追求的是:

$ git rev-list $(git branches --contains <ancestor>) --not <ancestor> --pretty=oneline

gitrev-list 是一个命令,它会列出一些父母可以访问但其他人不能访问的所有修订的列表。 在上述调用中,我们使用包含给定祖先的所有分支列表作为起点,然后排除该祖先之前的所有历史记录。 添加--pretty=oneline 告诉命令包含提交的简要描述;它通常只会每行输出一个修订 ID。

请记住,这可能并不完全符合您的要求,因为我认为提交是按时间顺序排列的,而不是按提交的拓扑图排序的。 git rev-list 有很多选项大量,所以可能有一个可以控制排序。

如果您真的只想列出 所有 具有给定祖先的提交,那么有一种更暴力的方法可以做到这一点(尽管它会包括其他无法访问的提交和存储)。 我们再次使用rev-list,虽然我们没有传递有趣的分支列表,而是指定--all

$ git rev-list --all --not <ancestor> --pretty=oneline

【讨论】:

什么是git branches?我似乎在 git 2.25.1 上没有那个命令,而且表面的谷歌搜索也没有打开它……也许这曾经是一个命令的名称?【参考方案2】:

如何获取可以到达给定(根)提交的所有提交的日志?

git log --ancestry-path --all --not $given

具有您想要的任何显示选项。 --graph --decorate --oneline 是通常的起点,--simplify-by-decoration 显示尽可能少的未修饰提交,同时仍显示分支结构。

【讨论】:

【参考方案3】:

我被同样的问题困住了。 谷歌搜索没有带来合适的东西,所以我决定写一个脚本。 https://gist.github.com/lvitya/66a9f519d30b7fd2c90d8f95a0b3a1a1 它有助于可视化您的提交树。

这里是脚本的内容 git_show_graph_from_ancestor.sh

#!/bin/bash -x
# $1 == ancestor

BR_LIST=$(git for-each-ref --contains "$1" --format="%(refname)")
git log "$1"^! $BR_LIST --oneline --decorate --graph

这会生成从给定祖先开始的所有提交的图表。即你可以看到所有基于公共主分支的特性分支。

$ ~/scripts/git_show_graph_from_ancestor.sh master
* feature2
* commit
* commit
| * feature1
| * commit
|/
* master

【讨论】:

请不要只发布一些工具或库作为答案。至少在答案本身中展示how it solves the problem。 好的,所以我不得不发布 bash 脚本的内容。 这(即使用 git for-each-ref )产生了我正在寻找的答案:有问题的分支以及植根于那里的所有其他分支。

以上是关于使用 Git,我如何显示所有共享一个共同祖先的提交树?的主要内容,如果未能解决你的问题,请参考以下文章

git bisect 如何选择一个没有第一个好的提交作为祖先的提交? (使用--first-parent)

Git中分支变基的原理

idea的git无法使用三路合并

如何使用nokogiri找到具有共同最近祖先的相同深度的所有链接

Git:找到两个分支的共同祖先

如何在 git 存储库中重写提交者名称? [复制]