git log --graph 通过提交 parent 指针动态可视化分支拓扑,需搭配 --oneline --all --simplify-by-decoration --date-order 才能清晰呈现合并关系与分支归属,符号 *、|、/、\ 分别表示普通提交、主干延续、分叉或合并连接线。

Git 本身不存储“分支关系”的元数据,所谓分支图其实是通过提交的 parent 指针和引用(ref)指向动态推导出来的 —— 所以 git log --graph 不是“画关系”,而是“可视化已有拓扑”。
用 git log --graph 看合并结构,关键在参数组合
单独用 git log --graph 很难看清分支归属,容易误判谁合了谁。必须搭配以下参数:
-
--oneline:每提交一行,避免被长提交信息挤垮布局 -
--all:显示所有 ref(含所有本地分支、HEAD、origin/xxx),否则只显示当前分支 -
--simplify-by-decoration:只显示有分支/标签指向的提交,大幅减少干扰节点 -
--date-order或--topo-order:前者按时间排序(适合看线性协作流),后者按拓扑排序(保证父提交总在子之前,更适合看合并依赖)
推荐命令:git log --graph --oneline --all --simplify-by-decoration --date-order
git log --graph 中的星号、竖线、反斜杠代表什么
这些符号不是装饰,是 Git 根据 commit parent 数量实时渲染的拓扑标记:
-
*(带空格):普通提交(1 个 parent) -
*(缩进后带空格):merge 提交(2+ 个 parents),其下缩进行就是各 parent 分支的延伸 -
|:表示当前行所属分支的“主干延续” -
\或/:表示分支分叉或合并时的连接线,方向取决于排序方式和终端宽度
注意:git log --graph 不标注分支名 —— 它只画提交链。分支名靠 --decorate(默认开启)在提交旁标出 (main)、(origin/feature) 等,但若提交没被任何分支引用,就不会显示名字。
为什么有时看不到 merge 提交,或图看起来“断开”
常见原因不是命令写错,而是 Git 的对象模型和 fetch 状态导致:
- 本地没 fetch 远程分支?
origin/feature不在本地 ref 中 → 加--all也看不到它,需先git fetch - merge 提交被
--simplify-by-decoration过滤掉了?该选项会跳过“无分支/标签指向且非 merge”的提交,但 merge 提交只要有一个 parent 被装饰就会保留;如果仍缺失,试试去掉该参数对比 - 用了
--no-merges或配置了log.hideMergeCommits = true?检查git config --get-regexp log - 终端宽度太小?Git 会自动换行或省略连接线,用
git log --graph --format="%h %d %s" --all | cat -n查原始提交链更可靠
想看某两次提交之间的分支差异图?用 git log A..B 范围限定
比如想确认 main 是否已包含 feature/login 的全部改动,不要只跑 git log --graph 猜:
-
git log --graph main...feature/login:显示“仅在其中一个分支上”的提交(对称差集),适合查遗漏 -
git log --graph feature/login ^main:显示在feature/login但不在main的提交(即 feature 独有内容) -
git log --graph main ^feature/login:显示在main但不在feature/login的提交(即 main 已超前的部分)
注意:... 是三个点,不是省略号;^ 是排除操作符,不能写成 - 或 ~。
真正容易被忽略的是:分支图不是静态快照,它随每次 git fetch、git merge、甚至 git rebase 实时变化;同一份日志,在不同机器、不同 fetch 时间点,画出来可能完全不同 —— 别把终端里看到的图当成“权威分支关系”。


















