
在merge PR的過程中,rebase and merge會產生衝突,因此需要補充一下Git rebase的知識點。
- Understanding Rebase (And Merge) in Git
- Merging vs. Rebasing
- webstorm 的 Rebase Current onto selected什麼操作?
- rebase and merge 一個Pull request做了什麼操作?
Understanding Rebase (And Merge) in Git
merge 是Git中最簡單也是最常用的整合change的方法,但是這並不是唯一的一種方式。 Rebase是另外一種可選的但是略微高階的整合方式。
合併提交的case
通常情況下,一個由人類認真建立的commit,是一個有意義的單元:它僅僅包含相關的change並且每個commit都伴隨著一個comment。 有一種merge commit可以讓所有comments丟失:Git自動建立的commit,並且由Git填充所有的differ change。沒有語義,沒有主題。當然,這些獨立commits的內容是保留的。但是history分成了註釋的,分離的有意義的commit,由於這個原因,在一次merge commit中不會保留。 這就是為什麼有些人不喜歡merge,喜歡rebase的原因。
Rebase之美
與一籠統把commits塞到一個commit不同,一個rebase會保留原始的commits。 專案的歷史是一條單的,直線。沒有任何跡象表明它在某個時候拆分出一個分支來。

我們來一步一步拆分一個rebase操作。方案很簡單:我們想用rebase整合branch-B到branch-A。

命令很簡單:
git rebase branch-B
複製程式碼
首先,線條開始分支後,Git將"undo"所有的branch-A上的commits(在共同的祖提交後)。當然,它不會丟棄它們,而是臨時將它們存了起來。

其次,它會應用我們想整合的來自branch-B的commits。此使,兩個分支是相同的。

最後,branch-A的新commits重新被應用,但是在一個新的位置,在branch-B的後面。(they are rebased)。 結果就是development在一條直線上開發。不是一個commit包含了所有的改變,而是讓原始commit結構保持原樣。

下面嘗試開BranchA,BranchB兩個分支,然後基於webstorm的Version Control,觀察git rebase操作會不會有上述的變化。
BranchA

BranchB

Rebase BranchA onto branchB

rebase的是誰,就修改的是誰 onto的是誰,誰就是被rebase的分支的新commits
其實,rebase只做了一件事:更新base branch!(重點!重點!重點!)
而想將誰的更新內容作為新的base branch的提交,就將作為topicBranch。
非常重要的命令。
git checkout baseBranch
git rebase topicBranch
複製程式碼
再說的通俗一點,其實就是:挑了一個branch,把它的特性拿過來,放在我的新特性之前。
Merging vs. Rebasing
看完上面這篇文章後,並沒有搞清楚rebase做了什麼操作,所以還是需要多讀一些文章。
- 對於初學者來說,git rebase命令就像一個magic voodoo
- merge和rebase都是用來從一個分支到另一個分支integrate changes的,只是方式不同

Merge Option
git checkout feature
git merge master
複製程式碼
git merge master feature
複製程式碼
會有一個'merge commit', 但是merge是非常安全的,不會像rebase有很多陷阱。 但是若master非常活躍,每次merge都會有要給'merge commit',會導致feature的commit history很髒。

Rebase Option
git checkout feature
git rebase master
複製程式碼
-
feature從master tip處開始合併master上的commits
-
重寫project的history
-
rebase後,project的history更加乾淨了。沒了多餘的'merge commit',並且成了一條線。
-
rebase 需要遵循Golden Rule of Rebasing,否則會導致災難性的合作workflow。
-
rebase 會丟失掉merge commit,導致看不到之後合併到feature的commit。
靈活一點的Rebasing
- 選擇特定的commits移動到新分支,加一個i選項
- fixup某一個提交
git checkout feature
git rebase -i master
複製程式碼
pick 33d5b7a Message for commit #1
pick 9480b3d Message for commit #2
pick 5c67e61 Message for commit #3
複製程式碼
pick 33d5b7a Message for commit #1
fixup 9480b3d Message for commit #2
pick 5c67e61 Message for commit #3
複製程式碼

Golden Rule of Rebasing
永遠不要在public 分支上使用git rebase!

Force-Pushing
若想將rebased的master分支推到遠端倉庫,Git 將會阻止你,因為它與遠端的master分支衝突了。但是,你可以force push。
# 這個命令一定要小心使用
git push --force
複製程式碼
- 只有100%確定自己在做什麼時再force,否則會讓團隊的人很困惑
- 若是想將某個feature遠端分支徹底替換掉,可以這樣做。
下面嘗試開master,feture兩個分支,然後基於webstorm的Version Control,觀察git rebase操作會不會有上述的變化。
master

feature

git checkout feature
git rebase master
# resolve conflict1
git rebase --continue
# resolve confict2
git rebase --continue
複製程式碼
Rebase feature onto master

webstorm 的 Rebase Current onto selected什麼操作?
可以理解成下圖這樣。
Rebase feature onto master


Current在WebStorm中指右下角的branch,selected一般指的original branch。
rebase and merge 一個Pull request做了什麼操作?

git checkout feature
git rebase master
複製程式碼
像下圖這樣:

