「Git 介紹」Ch1: 什麼是 git rebase
最近自己對 git 的概念又整理了一下,先來介紹一下 git rebase
一. (What?) git rebase 可以做什麼 ?
除了 git merge
的另一種選擇
- merge 的常見三種方式:
git rebase
,git merge
,git cherry-pick
- 一般做 merge 常見大概會有 rebase、merge、cherry-pick,這篇只先針對 rebase 做分享,rebase 可以做的事情算是滿多的。
- 與 git merge 的差別 ?
- 最主要在使用
git merge
的時候,如果你有注意,其實都會再產生一個做 merge 這件事情的 commit,在git log --graph --all
線圖上就不會是線性,線會轉彎然後合起來,最常見的情況是會產生小耳朵(小耳朵link)。然而在使用git rebase
做 merge 時,它會是用接點的方式接在前面,rebase 顧名思義,重新定義 base(它的根),而當然實際 git 的實作, 不是單純拿原本的 commit 接上去,其實是複製了一份過去,SHA-1 值也是重新產生,是會改變的。
- 最主要在使用
有一個狀況 git merge 還是會保持一條線
(除非parent branch 的 commit 始終包含在 child branch 裡,parent branch 從來沒變更過,現在要把 parent 的進度更新成 child 的進度,這時候的 merge 會走 ff(fast-forward),也就是說不會產生額外的 commit,但這裡不討論這個,先假設 branch 間已經有分歧了,也是合作比較常見的狀況)。
如果在上述情況下 git merge 不想走 ff 可以
git merge --no-ff
這樣一定會產生一個 commit, git 會請你再留一個 commit message。
二. 以下分享 git rebase
, git merge
的差異
Ⅰ. 先來看 git merge
,接下來藉由圖片和實例讓大家參考:
如果是 git merge
的情況:
- 目前我在
master
加了add 01 project
commit 接著在master
commit 完後,建了一個分支add-02project
,並 commit 了三次,停在feat: add 02.js
,接著我繼續從add-02project
分支建了add-03project
分支,並 commit 一次feat: add 03.html
,然後我回頭從master
建add-04project
分支 commit 一次feat: add 04.html
,以上都只是我亂建的不重要,只是為了講解一下。
接下來重點是我想讓
add-04project
branch 與add-03project
branch 做 merge,
這裡如果我先做git merge
:
- 目前 HEAD 在 add-04project,下指令
$ git merge add-03project
意思是 : merge branch
add-03project
into branchadd-04project
接著,
你會看到線圖產生變化,多了一個 commit
cbcfe7b
是 for merge 的,然後線圖也還是原本的線,只是接在一起了。
Ⅱ. 那現在來看如果使用 git rebase
- 原本的情況和圖1一樣,HEAD 一樣在
add-04project
branch :
在這裡下
$ git rebase add-03project
字面意思是請幫我把我當前的 branch 的根換成
add-03project
branch,所以實際上它會把當前 branch 進度複製接到add-03project
branch 上,這時候會呈現如下:
- 會發現變成一條線了,且
add-04project
commit 內容也都在,但 SHA-1 會重新計算。
三. rebase 反悔了怎麼辦:
git reset --hard <SHA-1值>
記得在使用 git rebase 的時候,如果反悔了剛剛的操作,不能用
git reset --hard HEAD^
做相對路徑切換, 它是不會切回原樣的,要記得直接用絕對路徑切換,下git reflog
看想切回去的地方,然後下git reset --hard <SHA-1值>
也就是直接放 commit ID,或著是 reflog 上的 HEAD@{x},git reset --hard HEAD@{x}
|
|
四. git rebase -i
(會進入 rebase 的互動模式,之後分享一下)
- 我把它稱作小小時光機,但就像 Back to the Future 演的那樣,很酷也容易不小心出問題。
- 可以做滿多事,但也要注意有時會更動到歷史紀錄,在多人協作專案,更是要小心操作。
五. (Why?) 為什麼需要 git rebase
先說結論:
- 直接先說我自己認為的結論,
git rebase
只是工具,不管是 git merge、git rebase 還是其他 git 指令,其實都是因應情況、團隊開發模式等情況下,去做合理使用,只要在合適的情況使用 rebase 我相信是沒問題的,使用 rebase 有時可以讓專案的進度 (commit 顆粒) 更清晰。
那什麼是合適的情況 ? :
以下情況我根據自身經驗認為會使用或是可以使用:
1. 遠端 master(main) branch 的 code 進度更新了, 這時候自己的分支開發了一個功能,準備推上去,可以使用 rebase
讓自己的 branch 進度更新,最後再推上去自己的分支
$ git fetch upstream
$ git rebase upstream/master
$ git push origin 自己的 branch
2. 同理更新自己的 fork repo:
$ git checkout master
$ git fetch upstream
$ git rebase upstream/master
$ git push origin master
3. 整理 git 歷史紀錄,可以修改、合併、變更、刪除等等..
# 使用互動模式
$ git rebase -i <SHA-1>
The End:
Review:
git rebase
與git merge
的差異git rebase
反悔如何處理git rebase
使用時機的取捨- 在團隊協作中善用工具,follow 大家的共識