考虑这个示例git
存储库。
#!/bin/bash -e
rm -rf example
git init example
cd example
echo 0 > file.txt
git add file.txt
git commit -am "initial commit"
git branch branch1
echo 1 > file.txt
git commit -am "1 (on master)"
git branch branch2
git checkout branch1
echo 2 > file2.txt
git add file2.txt
git commit -m "2 (on branch1)"
git merge --no-edit master
echo 3 > file2.txt
git commit -am "3 (on branch1)"
git checkout master
echo 4 > file.txt
git commit -am "4 (on master)"
git checkout branch1
git merge --no-edit master
echo 5 > file2.txt
git commit -am "5 (on branch1)"
git checkout branch2
echo 6 > file3.txt
git add file3.txt
git commit -m "6 (on branch2)"
git checkout master
git merge --no-edit branch2
git merge --no-edit branch1
上面的脚本在branch1
分支之外创建了两个分支(branch2
和master
);我们将master
合并到branch1
几次,然后最终将branch1
合并回master
。同时,我们会在branch2
合并之前将master
合并回branch1
。
如果我在主人身上git log --graph --oneline
,结果看起来很复杂。
* 4f71184 Merge branch 'branch1'
|\
| * d58e9f0 5 (on branch1)
| * b19c9b4 Merge branch 'master' into branch1
| |\
| * | 212f4d6 3 (on branch1)
| * | 1ac0082 Merge branch 'master' into branch1
| |\ \
| * | | 26cf8e0 2 (on branch1)
* | | | 9aaa8c5 Merge branch 'branch2'
|\ \ \ \
| |_|_|/
|/| | |
| * | | 425aead 6 (on branch2)
| | |/
| |/|
* | | 67a7fed 4 (on master)
|/ /
* | 6a56133 1 (on master)
|/
* 0d4f076 initial commit
在这个例子中,我主要关注master
和branch1
之间的合并;我对合并到master
的其他分支上的提交不感兴趣。在这种情况下,只有另一个分支(branch2
)并且它只有一个提交,所以它不会使图形太乱,但是当有很多很多时它会变得更糟更多分支在玩,但我只想关注master
和branch1
。
如果我使用git log --graph --oneline --first-parent master branch1
,图表看起来几乎正确,仅观察master
和branch1
中的第一个父项,但合并提交没有合并即使第二个父项出现在日志中,也会在它们上绘制线条。
* 4f71184 Merge branch 'branch1'
| * d58e9f0 5 (on branch1)
| * b19c9b4 Merge branch 'master' into branch1
| * 212f4d6 3 (on branch1)
| * 1ac0082 Merge branch 'master' into branch1
| * 26cf8e0 2 (on branch1)
* | 9aaa8c5 Merge branch 'branch2'
* | 67a7fed 4 (on master)
* | 6a56133 1 (on master)
|/
* 0d4f076 initial commit
我认为我想要的是这样,从日志中删除branch2
提交425aead
。 (再次,它不是更清楚,但如果有更多的分支,如branch2
,价值会更明显。)
* 4f71184 Merge branch 'branch1'
|\
| * d58e9f0 5 (on branch1)
| * b19c9b4 Merge branch 'master' into branch1
| |\
| * | 212f4d6 3 (on branch1)
| * | 1ac0082 Merge branch 'master' into branch1
| |\ \
| * | | 26cf8e0 2 (on branch1)
* | | | 9aaa8c5 Merge branch 'branch2'
| \ \ \
| _|_|/
|/ | |
| |/
| /|
* | | 67a7fed 4 (on master)
|/ /
* | 6a56133 1 (on master)
|/
* 0d4f076 initial commit
有没有办法在这里得到我想要的东西?
答案 0 :(得分:0)
不幸的是,没有。问题源于git log
将其提交选择过程与其绘图过程相结合的方式。没有--first-parent
,它跟随每个合并提交的所有父项 - 但与 --first-parent
,它剥离其他父项,以便当它到达节点之间的连接点时,即使它绘制的两个提交都有一个合并链接,链接也是从内部数据结构中消失。
如果您可以在--no-walk
中合并--graph
和git log
,则可以这样做:
git rev-list --first-parent master branch1 |
git log --no-walk --stdin --decorate --oneline --graph
即,我们收集要首先显示的节点(git rev-list
),然后指示git log
重新获取具有完整父节点信息的特定提交图节点,并将它们排序为一个可绘图的形式,然后绘制它们。但你不能:
fatal: cannot combine --no-walk with --graph
这最终是一个相当困难的问题,尽管如果您决定深入研究git log
的图形绘制代码,那么一种中途解决方案似乎可以实现。从本质上讲,我们希望将日志记录分成两部分:一个--first-parent
扫描以收集节点,然后第二次重新扫描重新遍历图形,重新填充每个内核的数据结构提交,抛出父链接到我们在第一次扫描期间没有加载的节点(而不是丢弃除第一次扫描之外的所有节点)。这为我们提供了一个适合绘图的修改后的提交图,我们甚至不需要rev-list
和--stdin
。
答案 1 :(得分:0)
git log --graph
不会做正确的事情,但使用dot
(又名Graphviz)生成正确的图表非常容易。
我使用了来自this answer的git-log-dot
脚本:
#!/usr/bin/python
import subprocess, sys, re
args = ['git', 'log', '--pretty=format:%x00%H%x01%h%x01%P%x00'] + sys.argv[1:]
rows = subprocess.check_output(args).split('\x00')[1::2]
seen_commits = set([row.split('\x01')[0] for row in rows])
print("digraph G {")
for row in rows:
columns = row.split('\x01')
commit = columns[0]
label = columns[1]
print('"{}" [label="{}"];'.format(commit, label))
for parent in columns[2].split(' '):
if parent == "":
continue
if not parent in seen_commits:
continue
print('"{}" -> "{}"'.format(commit, parent))
print("}")
如果您将该文件放在$PATH
git-log-dot
和chmod +x git-log-dot
上,git
会在您输入git log-dot
时自动运行该文件。 (这是git
作为单独脚本git-checkout
,git-reset
等分发时遗留下来的遗留问题。)
您还需要Graphviz。在macOS上我用brew install graphviz
安装了它;在Ubuntu上我相信你可以用sudo apt-get graphviz
安装它。
绘制整个回购图仍然看起来有点令人困惑:
git log-dot | dot -Tpng -o graph.png
但是只绘制master
和branch1
的第一个父母,看起来像哨子一样干净:
git log-dot --first-parent master branch1 | dot -Tpng -o graph.png
(在上面的示例中,我还使用-Grankdir = LR使图形水平,但默认的垂直方向也非常好。)