rebase 感覺好複雜、好危險。我還是都用 merge 就好。
我以前也是這麼想。不過我後來漸漸發現了各有各的好。
git merge
在幹嘛?
把另一條 branch 的變更合進來,並產生一個 merge commit 記錄這次合併。
A---B---C feature
/ \
D---E---F---G---H dev ← merge commit (H)假設 feature branch 叫 feature/button-component、target branch 是 dev,英文可以說:
- Merge
feature/button-componentintodev(將 feature branch 併入 dev) - Merge
feature/button-component(合併 feature branch)
為什麼要特別英文教學呢?因為我曾遇過有主管 / 同事英文不好,看到 into 不知怎的以為是英文倒裝句,以為是有人把 dev 併入 feature branch 才導致程式壞掉,而不反思是自己有 bug ¯\(ツ)/¯
優點
- 操作直覺,不會動到既有的 commit 歷史
- conflict 一次解完,不用分批處理
- 適合需要保留 合併記錄 的場合(e.g. PR / MR 的 merge)
缺點
- 多人協作一段時間後,
git log會出現大量 merge commit - 歷史不是線性的,像蜘蛛網,不好讀
* Merge branch 'feature/login'
|\
* |
| * feat: integrate login api
* |
|\* feat: build login form
|
* Merge branch 'feature/registration'
|git rebase
在幹嘛?
把你的 commit 一個個搬到 target branch 的最新點後面,重新接上去 aka 變基。
A---B---C feature(rebase 前)
A'--B'--C' feature(rebase 後)
/
D---E---F---G dev注意 A B C 變成了 A' B' C'。因為 base 換了,commit hash 隨之改變。
優點
git log是乾淨的一條線,好讀好追- 同步 target branch 的最新變更,不會多出 merge commit
- 搭配
rebase -i可以整理 commit,squash 或改 message
缺點
- 有 conflict 的話,要一個 commit 解一次,不像 merge 一次解完
- commit hash 會改變,不適合用在已經 push 出去、別人也在用的 branch
- 觀念沒到位前,操作容易出錯
為什麼大家會怕 rebase?
主要有三點:
conflicts 要分批解
merge 是把所有衝突集中在一次解決;
rebase 是每個 commit 都可能有衝突,要一個個處理,解完衝突後,手動 git add,再 git rebase --continue 繼續跑下一個 commit。
雖然麻煩,但換個角度想其實也還行——每次的 conflict 會鎖定在小範圍內,有時反而好處理。
要 force push
rebase 後 commit hash 變了,push 的時候 remote 會拒絕,必須 git push --force 或 git push --force-with-lease。
- 如果確定這個 feature branch 只有自己在用,直接
--force/-f就行。 - 如果這個 feature branch 有別人跟你一起在用,那就要用
--force-with-lease。
--force-with-lease 能幹嘛?一樣是 force push,但如果 remote 有你不知道的新 commit 會先擋下來,避免蓋掉別人的東西。
有必須遵守的鐵則
不要 rebase 已經 push 出去、有其他人在用的 branch。
也就是說,只有自己在用的 feature branch 隨便 rebase + force push 都沒問題;但如果在團隊沒有共識之下,擅自 rebase 了大家都在用的 main 或 dev 或你跟他人一起協作開發的 branch,別人的 commit 歷史就會對不上了。
別人的 commit 歷史對不上會怎麼樣?你 rebase 之後 commit hash 全換了,但別人的 base 還停在舊的 commit hash,他們 pull 或 push 時 Git 會看到兩條分歧的歷史。輕則要手動修、重則搞不清楚哪些變更是真的、哪些是重複的,俗稱搞爛 repo。
我的習慣
我曾經待過:
- 統一用 git merge 的團隊
- 自由、沒規範用哪個的團隊(結果習慣用 git merge 者佔多數、習慣用 git rebase 者會被議論說是有個人堅持)
- 統一用 rebase 的團隊(會看到 merge commit 基本上都是 PR / MR 被 merged 自動產生的。)
當然在公司、在團隊當中就是按照團隊共識來做。至於私人習慣,由於個人 side project 都是一人工作,基本上都在 dev 直接開發也不會發 PR / MR,就用 rebase 啦。
總結
哪個好沒有一定。有機會的話,不妨試試看沒用過的那個。