git log:在左侧显示第二个父提交

7
考虑这个例子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 master
git merge --no-edit --no-ff branch1
git log --graph --oneline

我们创建了一个名为 branch1 的分支,从 master 分支合并了几次,最后再次合并回 master
运行命令 git log --oneline --graph 会显示出奇怪扭曲的图形。
*   2c3b97a Merge branch 'branch1'
|\
| * 1d722df 5 (on branch1)
| *   54039b6 Merge branch 'master' into branch1
| |\
| |/
|/|
* | d80d82c 4 (on master)
| * 2399286 3 (on branch1)
| *   9a0cb38 Merge branch 'master' into branch1
| |\
| |/
|/|
* | 31df841 1 (on master)
| * 5809072 2 (on branch1)
|/
* 08fc7a6 initial commit

图表如果长这样会更简单:
*   2c3b97a Merge branch 'branch1'
|\
| * 1d722df 5 (on branch1)
| *   54039b6 Merge branch 'master' into branch1
|/|
* | d80d82c 4 (on master)
| * 2399286 3 (on branch1)
| *   9a0cb38 Merge branch 'master' into branch1
|/|
* | 31df841 1 (on master)
| * 5809072 2 (on branch1)
|/
* 08fc7a6 initial commit

据我所知,原因是git log总是更喜欢在右侧显示每个合并提交的“第二个父级”,因此对于每个合并提交,它必须向右蛇行。(“第二个父级”是正在合并的分支,“第一个父级”是我们要合并到的分支。)
1.有没有办法说服git log生成我想要的简单图形?这里有一个2013年的旧gist提出了修复这个问题的建议(“让我指定哪些分支沉到左边”;那里还有其他有趣的想法),但我没有看到任何进展。
2.假设git log无法自然地完成,是否有另一个git提交图形工具/库可用于制作像这样的图形?
4个回答

4
感谢Torek的建议尝试使用dot(又名Graphviz),我编写了这个Python脚本以生成dot文件格式的输出。它生成了一个像这样的图形,我认为看起来非常不错:

enter image description here

#!/usr/bin/env python3
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(b'\x00')[1::2]

seen_commits = set([row.split(b'\x01')[0].decode() for row in rows])

print("digraph G {")
for row in rows:
    columns = row.split(b'\x01')
    commit = columns[0].decode()
    label = columns[1].decode()
    parents = columns[2].decode().split(' ')
    print('"{}" [label="{}"];'.format(commit, label))
    for parent in parents:
        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 log-dotgit将自动运行它。 (这是从旧版本的git分发为单独的脚本git-checkoutgit-reset等时所保留的遗留问题。)
您还需要Graphviz。 在macOS上,我使用brew install graphviz进行安装; 在Ubuntu上,我认为您可以使用sudo apt-get graphviz进行安装。
您可以像下面这样使用git log-dot生成PNG文件:
git log-dot | dot -Tpng -o graph.png

在上面的示例中,我还使用了 -Grankdir=LR 使图形水平,但默认的垂直方向也很好。

这些都只是小调整:(1) 你实际上没有使用 re,因此不需要它。(2) 我建议使用 git rev-list --parents 而不是 git log --pretty=format...,虽然你需要添加 HEAD 作为默认值并自己缩写 rev-id(但这可能是个好主意,因为你可以确定唯一缩写的最小值)。拆分将首先按换行符进行,然后按空格进行,以获取提交及其父集。(3) 可能很酷的是让 Python 代码直接运行 dot,然后打开一个窗口或浏览器... :-) - torek

2
  1. 有没有办法说服git log生成我想要的简单图形?2013年有一个老的gist提出了修复这个问题的建议(“让我指定哪些分支向左沉没”;那里还有其他有趣的想法),但我没有看到任何进展。

没有。(正如我在另一个问题中所说,一般来说这是一个比较难的问题 - 实际上,它通常是“NP难”的。Git的日志绘制代码相当欺骗性,但交换父项可能会解决这个问题,但还有很多其他情况。)

  1. 假设git log不能自然地完成,是否有其他git提交图形化工具/库可用于制作此类图形?

我不知道有任何这样的工具。绘制图形的gitk代码与绘制图形的git log代码非常不同,但是这个问题 - 它概括为“以最小的交叉方式绘制DAG” - 确实很难。虽然有很多绘图程序。据报道,dot非常好。

另请参阅维基百科这个CS stackexchange问题和答案


非常感谢您建议使用“dot”!最终我编写了一个Python脚本来在我的答案中使用它。 - Dan Fabulich
@torek,关于“with minimal crossings”;但是并不需要达到最小化,因为百分之百的完美并非必须。它可以根据用户的一些输入来执行算法。完美并非必需。 - Pacerier
@torek,关于“with minimal crossings”的问题;但是并不需要达到最小化,因为并不需要百分之百的完美。它可以根据用户的一些输入来执行算法。完美并非必需。 - undefined

2
截至2022年,git log似乎与以前的一样。但是GitKraken处理得非常好:

enter image description here


0
假设git log无法自然地完成此操作,是否有其他git提交图形化工具/库可用于制作像这样的图形?
答案是据我所知你不能, 唯一关闭的事情(但不是你要求的)是使用rebase(可以与--onto结合使用),每当您想要时,日志将更加平坦。
但是 - 由于git的本质,您所要求的是不可能的。
实现您尝试做的最接近的方法(但仍不完全符合您的要求)。
git log --all --graph --decorate --oneline --boundary master...branch1

尝试添加--topo-order--no-walk也没有帮助,也没有效果。

总结:

正如你所发现的那样,由于git的本质,这是不可能的。

假设git log无法自然地完成此操作,是否有其他git提交图形化工具/库可用于创建此类图形?

我认为没有其他工具可以做到这一点,因为git不会在同一“行”上与另一个分支显示不同分支提交(在您的示例中为9a0cb38)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接