Git 的本质
文章目录
介绍
网上存在太多介绍 Git 的文章,也有很多的书籍,如 ProGit - Book,它们都没有从一个设计层面介绍 Git 的原理。
提交
Git 将提交信息与提交内容分离处理。
- 提交信息:作者、时间、父提交等等。
- 提交内容:文件修改。
这一点是学习使用 Git 的误区,很多人没有理解这一点,导致遇到问题不知道如何解决,不知道如何设计工作流。
图
只看提交信息中提交与其父提交的话,可以将提交看作图的结点,每一个提交都有零个到多个父提交的连接,从而组合成了一个有向无环图。
Git 很多操作都是在处理这张图,例如:merge
、cherry-pick
、rebase
等等。
merge
:创建一个新结点连接两个或更多结点。cherry-pick
:将一个结点的父结点修改为其他结点。rebase
:将一连串结点中第一个结点的父结点修改为其他结点。
快照
提交内容在 Git 中就是快照,是所有文件的当前状态。
由于提交大部分都会修改文件内容,因此需要减少自动生成的提交,例如 merge
操作。如果本地与远程都有提交,那么执行 pull
时会相当于 fetch
+ merge
,然后在本地就会自动生成一个合并提交。如果存在冲突就需要在此次合并提交中解决。
具体详细信息可以参考:
merge
操作本身有多种算法,可以根据实际需要选择使用。这其实带来一个问题,合并时无法保证所有的改动就是对的,因此合并时需要仔细检查所有改动,有可能算法会计算错误,导致合并出了错误的结果。
因此最好的办法就是减少类似 merge
操作引入的自动提交。
实例
当理解以上概念后,可以用来解决实际问题。
一个功能分支合并到主干时未进行正确的操作,导致丢失了一部分内容。发现错误后重新合并 Git 会直接提示已合并过。
假设其中功能分支为 feature
,主分支为 master
,合并提交为 M
,那么主分支上合并提交前的提交是 M^1
。
|
|
原理非常简单:通过重新生成一个包含正确快照的提交,然后合并此提交到主分支中的图上。