Day22|【Git】合并的另一个指令 - Rebase 与取消方式

前面介绍了 git merge 指令合并分支,本篇就来介绍另一种方式: Rebase


从 Rebase 字面来看,是 re 加上 base ,可以理解成「重新定义分支的参考基准」。

使用 git rebase 指令等於是修改历史,他会使分支移动到不同的 Commit 重新定义基准点。

git rebase 指令与 git merge 指令最大的差异是什麽呢?

👉 git rebase 指令不会额外产生新的 Commit 来合并两个分支。

先从以下范例来看整个关系图:

假设现在有两个从 master 分支上的 Commit 出去的两个分支,分别是 one 分支与 two 分支。并且都比 master 领先两个版本。

https://ithelp.ithome.com.tw/upload/images/20211005/20141010nhDoXrog1D.png

https://ithelp.ithome.com.tw/upload/images/20211005/20141010owi7MVvVgw.png

https://ithelp.ithome.com.tw/upload/images/20211005/20141010S6k9VJYpUn.png

👉 情况:使用 git rebase 指令来执行 one 分支合并 two 分支

// 确认当前位於 one 分支上
$ git rebase two # 合并 two 分支

https://ithelp.ithome.com.tw/upload/images/20211005/20141010O78Vf8O92L.png

使用 git log 指令查看现在分支与 Commit 的关系:

https://ithelp.ithome.com.tw/upload/images/20211005/20141010MaKspKDXTM.png

可以发现到本来 two 分支上的 Commit 的 SHA-1 值改变了。
3793657f562c
0807ce9e0cd0

这过程中是做了哪些事呢?我们可以一一拆解

A1 这个 Commit 要接到 two 分支上的 B1 Commit 上,因为 A1 先前的 Commit 基准点改变了,因此需要重新计算 A1 的 SHA-1 值,就会产生新的 Commit 物件 B1 。

https://ithelp.ithome.com.tw/upload/images/20211005/20141010tyv3g0SN3s.png

https://ithelp.ithome.com.tw/upload/images/20211005/2014101034g4ugMiGg.png

而原本接着 A1 的 A2 Commit ,要接到 two 分支上时,原先的 A1 已变成 B1 ,Commit 的 SHA-1 值被改变了,因此 A2 这个 Commit 也需要重新计算新的 SHA-1 值,而产生新的 Commit 物件。

https://ithelp.ithome.com.tw/upload/images/20211005/20141010XucNY2rX4H.png

最後,原本 one 分支指向的 A2 这个 Commit 会改成 B2 这个 Commit 上。

https://ithelp.ithome.com.tw/upload/images/20211005/20141010Tk0bJd0zRf.png

上述计算的过程,在我们执行 git rebase 指令後得到的回馈也有显示:Applying

https://ithelp.ithome.com.tw/upload/images/20211005/20141010FHItRFhVQN.png

意思就是说 git 在重新计算这个 Commit 的 SHA-1 值。

补充|那原本的 Commit 会不见吗?答案是不会的,这些 Commit 依然存在,只是没有一个分支指向他们。一段时间後,就会透过 Git 的资源回收机制回收走了。

同样地,我们可以思考 git rebase 指令中谁合并谁会有差异吗?

如果以最终结果来看,谁合并谁并没有差异,但过程中的历史纪录会有差别喔!


如何取消 rebase ?

方法|

  1. git reflog → git reset --hard
  2. git reset ORIG_HEAD --hard

因为使用 git rebase 指令会导致 Commit 的 SHA-1 值改变,就不能透过 git reset HEAD^--hard 的方式回到合并前的状态。

如果使用 git reset HEAD^--hard 指令,只会拆解最後一个 Commit 而已。

  1. Reflog |使用 Reflog 查看纪录找回我们执行 rebase 指令时的 SHA-1 值。

    $ git reflog # 查询变更轨迹
    

    https://ithelp.ithome.com.tw/upload/images/20211005/2014101047v6Od21fn.png

    https://ithelp.ithome.com.tw/upload/images/20211005/20141010nytYyjqZom.png

    找到相对应的 SHA-1 值後,可以执行以下指令回到当时的状态。

    $ git reset [指定的 SHA-1 值] --hard # 还原指定的 Commit 状态
    

    https://ithelp.ithome.com.tw/upload/images/20211005/20141010Zy9bJtlXvB.png

    如此一来就可以回到执行 git rebase 指令前的状态罗!

  2. ORIG_HEAD

    ORIG_HEAD 会纪录「危险操作」之前的 HEAD 位置。

    $ git reset ORIG_HEAD --hard
    

    https://ithelp.ithome.com.tw/upload/images/20211005/20141010oMyA1Afvak.png

👉 补充|什麽是 ORIG_HEAD

.git 目录里除了有 HEAD 档案,也有一个叫做 ORIG_HEAD 的档案。在这档案里会纪录「危险操作」之前的 HEAD 位置。

什麽是危险操作?举凡执行 mergerebasereset 这些指令有可能造成历史纪录的变动的动作,那麽在执行之前 HEAD 的状态有可能被记录在 ORIG_HEAD 的档案里。


Rebase 的使用时机

使用 rebase 的优势

  1. 不会产生额外专用合并的 Commit
  2. 历史顺序可以依照谁 Rebase 谁来决定。

缺点:相较一般的合并来得没那麽直觉。

上述有提到 rebase 等於是修改历史,因此要避免修改已经推出去的历史,否则会带给合作者的困扰。

👉 对於已经推出去的内容,非必要情况时避免使用 Rebase 。


参考文章:https://www.maxlist.xyz/2020/05/02/git-merge-rebase/


<<:  【网页制作证书】点止学嘢

>>:  学习JavaScript第二天--宣告变数的方法let、const、var

调节磁碟和CPU的矛盾 - InnoDB的Buffer Pool

快取的重要性 我们知道不论是聚簇索引或是二级索引,资料都是储存在表格空间,而表格空间其实只是个抽象概...

Day 2:414. Third Maximum Number

今日题目 题目:414. Third Maximum Numbe 题目主题:Array, Sorti...

Day 30 最後的收尾

前言 今天是这个系列的最後一篇,我们会把之前没有做的东西补起来,他们都是蛮麻烦有点 tricky 的...

聊聊 SaaS 有哪些吧!

前阵子看到了 XChange 成立了天使创投,合夥人 David 分享了他对 SaaS 的看法让我也...

模型架构--2

SphereFace 在2017年发表在CVPR的文章,改进原先使用softmax作为loss fu...