[英]Visualize git branch dependency
是否有工具可以显示特定分支已合并到哪些分支? 例如,如果“A”已合并为“B”和“C”但未合并为“D”,如何输出“B”和“C”? 我只需要分支名称。
在这里意识到分支名称实际上并不意味着什么是很重要的。
分支名称只是指向提交的标签或指针。 可以将它们视为可以粘贴到提交中的黄色粘滞便笺,甚至粘滞箭头之一 。 这是重要的提交 。 提交的标识是其哈希ID。 提交是永久性的1且不可更改,并且每个提交记录其直接父级(大多数提交)或父级(对于合并提交为2或更多)的哈希ID。 这就是生成提交图的原因 ,除了可以随时添加它之外,它与提交本身一样永久且不可更改。
图表本身决定了存储库的实际“分支”:
(older commits towards the left, newer ones towards the right)
o--A
/
...--o--o
\
o--o--B
图的这个特定部分显示了两个分支,以两个提示 A
和B
结尾。 在A
添加新提交会给我们C
,它会记住A
作为其父级:
o--A--C
/
...--o--o
\
o--o--B
如果我们现在增加一个合并提交 -让我们把它叫做M
为“合并”是谁的父母都是 C
和 B
,我们得到:
o--A--C
/ \
...--o--o M
\ /
o--o--B
它需要两个标签 - 两个粘滞音符箭头 - 记住A
和B
,或者记住C
和B
,但是现在我们有M
,我们可以处理其中一个标签并保留一个指向M
粘滞便笺箭头本身:
o--A--C
/ \
...--o--o M <-- branch
\ /
o--o--B
所以这是一个分支的名字是什么,做:这是一个指针,指向一个单一的承诺,这Git会认为是尖端提交提交的一些向后寻找链条。 由于Git向后工作,从这个提示开始,Git将遍历合并的所有部分,以查找通过向后工作可以达到的所有提交。 由于M
有两个父C
和B
,Git将访问提交C
,然后访问A
,依此类推B
,然后所有提交到B
的左边。
当然,我们可以将标签指向A
和/或B
和/或C
:
.... <-- tag: v1.0
.
.
o--A--C
/ \
...--o--o M <-- branch
\ /
o--o--B <-- feature
如图所示,标签不必是分支名称。 分支名称的特殊功能是,通过使用git checkout name
“在”分支上“”,我们所做的任何新提交都将自动更新名称以指向新提交。 新提交将指回先前的提交。
这也是git branch --contains
背后的概念。 因为提交B
可达从提交M
,通过起始于M
和倒退一个步骤, git branch --contains specifier-for-
将打印名B
branch
。 该名称指向M
和M
到达B
更一般地说,Git反复询问并回答了这个问题:
X
提交的祖先Y
? 使用git branch --contains anything that finds some commit
,Git会询问有关每个分支名称的每个分支提示的问题:
target=$(git rev-parse $argument) || exit 1
git for-each-ref --format='%(refname)' refs/heads |
while read fullbranchname; do
branchtip=$(git rev-parse $fullbranchname)
if git merge-base --is-ancestor $branchtip $target; then
echo "branch ${fullbranchname#refs/heads/} contains $argument"
fi
done
如果$argument
是分支名称(如branch
,则将其转换为哈希ID的操作将选择commit M
的哈希ID。 然后将refs/heads/feature
转换为散列ID的操作选择B
的散列ID,并且git merge-base --is-ancestor
回答问题是提交B
是提交M
的祖先 (并且它是)。 2
你要问的是有点复杂:你希望,对于每个分支名称,不仅要确定这个分支的提示提交是否在某个选定分支的提示提交之前 (如git branch --contains
那样),但是对于每个这样的分支名称,哪些是更多的祖先,哪些是更少 - 祖先-y 。 这个问题可以回答,但仅限于某些情况 。
例如,考虑一下这个图:
...--o--o--o--o---M1--M2-o <-- master
\ \ / /
\ o--o / <-- feature1
\ /
o--o--o--o <-- feature2
我认为你希望feature2
被称为“after” feature1
,因为feature1
的合并提交是在feature2
提示的合并提交之后feature1
。 3但合并并不总是只将两个提交放在一起。 4考虑:
o--o--o <-- feature1
/ \
...--o--o--o--o---M1--o <-- master
\ /
o--o--o <-- feature2
现在没有明显的顺序: feature1
和feature2
都是通过一次提交同时引入的。
(当然,如果我们删除两个feature
名称中的一个,那就解决了问题。如果我们删除这两个名字,它甚至会更加解决!😀)
1您可以通过删除对提交的所有访问权限来删除提交。 Git从已知的名称 - 分支和标记名称以及所有其他形式的引用开始,并在图形中向后工作。 如果此向后工作到达提交,则提交将必须保留。 如果没有,则提交符合删除条件。 还有其他名称,除了显而易见的名称之外,通常会使提交至少保留30天。
2我们可以消除git rev-parse
调用,因为git merge-base
接受一个分支名称来代替一个哈希ID。 当给出一个名字时,它只是找到提交哈希,就像git rev-parse
一样。 我把它们放在主要用于说明。
3您必须编写自己的代码才能产生这种排序。 请注意,它并不像比较各个分支的提示提交那么简单; 我们需要知道哪些合并(如果有的话)引入这些提示,并比较合并。 我们还必须考虑将其提示嵌入非合并子子图中形成的分支:
..... <-- branch3
.
...--o--o--o--o <-- branch1
.
........ <-- branch2
在这里,我想我们想要声明branch2 < branch3
。
4,即使在一对-AT-A-时间合并的情况下,可以反复合并一些犯了一些主线,这有问题( 有可能的排序,但你必须选择一些图的遍历算法挑选一个总让烦恼在此点餐)。 基本上,请记住,当您使用DAG时 ,您正在处理一个poset 。
如果你的意思是一个图形工具, gitk
似乎是一个很好的起点。
或者,您可能更喜欢CLI,它对某些需求非常有用,请尝试一下:
git log --oneline --decorate --simplify-by-decoration --graph --all
更具体地说,问题是“如何知道哪些分支合并到分支A?”
git branch --contains A
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.