Rebase, what is rebase and what advantage can we take using rebase before merge than merging directly. Read more for details. These contents come from a part of pro-git, and you can get the entire book from links in this link.
合并,合并
下面是两种 Merge 操作
- 三方合并:两个分支 server 和 client,当前分支是 server,那么 merge 操作(#server:
git merge client
)将会对 {server.HEAD, client.HEAD, 两分支的最近的共同前驱} 进行“三方合并”,并将server的HEAD指向合并之后的快照。 - 快进合并:如果一个合并可以通过直接移动HEAD指针来正确实现,那么这就是一个“快进合并”,的确像快进一样。快进合并是“三方合并”的一种特殊情况,共同前驱即为待merge分支的HEAD。比如分支A 在新产生分支B 后没有任何演化,那么 B merge A 就是一个快进合并。
变基,变基
顾名思义,“变基”,改变基础,基础就是之前提交过的”快照”。
变基操作的话我们用 server
和 client
这两个分支举例不是很恰当,因为在普遍意义上这是两个平行的分支。现在把分支换成 master
和 bug-fix
:产品出bug了,我们在 bug-fix
这个分支来修。
修好了提交代码之后,进行变基操作的 话(#bug-fix: git rebase master
)。具体过程是:查找两分支的共同前驱C,计算 bug-fix.HEAD
针对C进行的修改Δ1,然后将 bug-fix.HEAD
指向 master.HEAD
,然后在移动后的bug-fix.HEAD上 ”重演“ Δ1,变基操作就结束了。
”重演“干了什么
根据Δ1的结果计算新的快照并提交,用到的信息来自之前的快照。然后视情况移除一些提交。
Sample
1 | # 一些初始化仓库和分支的操作:在 master 初始提交(A)之后,创建 fix 分支,然后创建一个提交(B.f),然后切换回 master 并进行另一个提交(B.m)。 |
Graph
- a) 变基前的状态
- a -> b, 这个例子比较简单,两个分支的公共前驱就是A,Δ1就是B.f,之后就是在 B.m 上重演 B.f,相当于直接提交。不能简单认为fix的头指针直接指到 B.m 了。
- b) 变基后的状态
- c) 快进合并
- d) 清理(Optional)
变基的风险,拉取公有仓库代码后,提交前如果使用了变基的话,可能会覆盖某些提交,别人再次提交之后可能出现同一个快照的两个副本,这种情况下使用变基需要整个团队的配合。
变基会消除掉提交记录中分支的真实轨迹,所以是否要保留这些信息、保留哪部分信息,因人而异。不过向开源库之类的项目 PR 前,将所做的修改 rebase 到 master 分支上是很值得肯定的。
Ref:
Pro Git: https://git-scm.com/book/en/v2/Git-Branching-Rebasing
@阿弥陀佛大锅炉