Git 的工作原理——快照、分支与提交历史

Git 的工作原理,在一张交互式画布上讲清楚:工作区、暂存区、本地与远程仓库,以及提交如何堆叠出共享的历史。

Git 是一套基于快照的版本控制系统:每一次提交都是仓库的一张完整画面,并链接到它的父提交,而分支不过是沿着提交历史移动的指针。

Git 的工作原理——快照、分支与提交历史

The interactive FlowJam canvas for this explanation — every lane, row and arrow above is a real QueryChart diagram you can open and edit.

How to read this visual

  • 从左到右读三列:编辑、提交、共享。
  • 四个泳道分组是一条流水线:工作区到暂存区、到本地仓库、再到远程仓库——每一条箭头都让这处改动离被共享更近一步。
  • “两个人改了同样的几行?”是全图唯一的分支,两个出口最后都汇入共享的提交历史。

编辑与暂存

“开发者在工作区里修改文件”是尚未提交的现实——磁盘上的文件,还不属于提交历史。“git add 把改动移入暂存区”是刻意插入的中间一步:暂存让你从挑选出来的改动里搭出一次提交,而不是把你碰过的一切统统塞进去。图解把它们分成各自的泳道分组,因为正是这两步式的提交给了 Git 它的精确度。

把快照提交下来

“git commit 为暂存的改动拍下快照”是改动变成永久记录的地方。“Git 保存这次提交,并附上指向父提交的指针”把那张图挑明了——除了第一次提交,每一次提交都指名它前面的那一次,这正是提交历史只能追加、可以审计的原因。“分支指针移动到新的提交上”完成整个动作:分支就是一个指针,所以在某个分支上提交,做的就是移动这个指针。提交本身完全不关心自己落在哪个分支上。

共享提交历史

“git push 把这些提交发送到远程仓库”从“本地仓库”跨进“远程仓库”这个分组——这是数据唯一一次离开你的机器。“远程仓库记录下新的提交历史”就是那份共享副本,而“两个人改了同样的几行?”为合并建模:除非同样的几行被改过,否则 Git 会自动合并分叉的历史;一旦改在同一处,“合并冲突——开发者手动解决”就把人的判断摆到明面上,然后“提交历史已共享并保持最新”合上整条流程。

Key relationships and takeaways

  • 一次提交是一张链接到父提交的完整快照,这让提交历史成为一张只能追加的图。
  • 分支是指向某次提交的指针,而不是装改动的容器——正因如此,创建和切换分支才这么廉价。
  • 暂存是刻意插入的中间一步,让你能决定一次提交里装些什么。
  • Git 是分布式的:每个人本地都握有完整的提交历史,push 和 pull 只交换缺失的那部分。
  • 冲突是例外而不是常态——一旦发生,由人来明确地解决它。

When to use this visual

  • 向一支只把 Git 当作一串命令来用的团队讲清楚快照模型。
  • 用指针模型来解释分支、合并与冲突,而不是靠背命令。
  • 在评审团队的提交与分支工作流时,把讨论落回到提交历史真实的结构上。

运作方式

  1. 把团队真实的工作流画出来

    在各个方框上标注你的团队实际使用的命令——特性分支、Pull Request、变基还是合并——让这张图记录的是你们的做法,而不是教科书的。

  2. 补上分支模型

    在本地仓库这个分组里加入特性分支和主分支两行,并在它们之间画出合并箭头,最后汇入共享的提交历史。

  3. 画出 Pull Request 这道关卡

    在本地推送和远程记录之间加一个决策:一次代码审查加上 CI 检查,必须通过之后分支才能合入 main。

  4. 加上恢复路径

    把撤销分支画进去——回退一次提交、修改提交信息、重置到更早的状态——每一条都落在一个明确的结果上,因为恢复占了 Git 实际用法的一半。

常见问题

Git 是什么,它和其他版本控制有什么不同?

Git 是一套基于快照的分布式版本控制系统。每一次提交存下的是仓库的一张完整画面,外加一个指向父提交的指针,而不只是一份文件改动清单。因为每个开发者本地都有完整的提交历史,大多数操作都能离线完成,协作也就变成了与远程仓库交换提交这件事。

Git 里的分支是什么?

分支是一个可移动的、指向某次提交的指针。当你在一个分支上提交时,指针前进到新的提交;提交本身并不知道、也不在乎自己落在哪个分支上。这就是创建分支为什么是瞬时的,也是切换分支为什么只改变工作区展示的是哪一张快照。

Git 为什么要有暂存区?

暂存区让你有意识地搭出一次提交。你可以改好几个文件,只把属于同一件事的那些放进暂存,然后只提交这一份选择——把无关的工作留在未提交的状态。工作区、暂存区和仓库是三种彼此独立的状态,而这正是图中画出的那条流水线。

Git 是怎么解决合并冲突的?

当两个分支改的是不同的文件、或者不同的行时,Git 会自动合并。当它们改的是同样的几行时,Git 猜不出哪个版本才对,于是标出冲突,交给人来选。冲突是一次决策,不是一次失败——正因如此,图解才把它导向一个明确的解决步骤,然后才轮到共享提交历史。

在 QueryChart(FlowJam)中编辑这张图解

把上面这张 Git 画布原样打开成你自己的图表,把泳道改名成你的工作流,并把你自己的提交历史画出来。

在 QueryChart(FlowJam)中编辑这张图解

可视化图解中的更多内容