如何理解git rebase?

clipboard.png

在merge PR的過程當中,rebase and merge會產生衝突,所以須要補充一下Git rebase的知識點。git

Understanding Rebase (And Merge) in Git

merge 是Git中最簡單也是最經常使用的集成change的方法,可是這並非惟一的一種方式。
Rebase是另一種可選的可是略微高級的集成方式。web

合併提交的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。
項目的歷史是一條單的,直線。沒有任何跡象代表它在某個時候拆分出一個分支來。
image
在一次rebase後,看起來就像development歷來沒有被拆分紅不一樣的分支。webstorm

咱們來一步一步拆分一個rebase操做。方案很簡單:咱們想用rebase集成branch-B到branch-A。
image
一個rebase以前的方案。spa

命令很簡單:3d

git rebase branch-B

首先,線條開始分支後,Git將"undo"全部的branch-A上的commits(在共同的祖提交後)。固然,它不會丟棄它們,而是臨時將它們存了起來。
imagecode

其次,它會應用咱們想集成的來自branch-B的commits。此使,兩個分支是相同的。
imageorm

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

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

BranchA
image

BranchB
image

Rebase BranchA onto branchB
image
其實就是將branchB的母分支branchA進行了integrate changes,也就是把branchB的2次commit,放在共同的起點與branchA的新commit之間,或者也能夠理解成將branchA的新commit,移動到了branchB的2次commits以後。

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的,只是方式不一樣

image

Merge Option

git checkout feature
git merge master
git merge master feature

會有一個'merge commit', 可是merge是很是安全的,不會像rebase有不少陷阱。
可是若master很是活躍,每次merge都會有要給'merge commit',會致使feature的commit history很髒。
image

Rebase Option

git checkout feature
git rebase master
  • feature從master tip處開始合併master上的commits
  • 重寫project的history

image

  • 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

image

Golden Rule of Rebasing

永遠不要在public 分支上使用git rebase!
image
每次使用git rebase前,問本身"有沒有人也正在基於這個branch寫代碼?"如果的話,就老老實實用merge,不要嘗試rebase。
如有gitflow的經驗,其實就是當你開了一個feature/foo時,若同事也開了一個feature/bar,並且大家是同時基於develop checkout出來的分支,那麼當develop有hotfix merge進去時,若你想拉去最新的develop代碼,就不能用git rebase,只能用merge,不然會致使同事的develop分支與咱們的develop分支不一樣,而此時她想再與咱們保持同步是很複雜的。

Force-Pushing

若想將rebased的master分支推到遠程倉庫,Git 將會阻止你,由於它與遠程的master分支衝突了。可是,你能夠force push。

# 這個命令必定要當心使用
git push --force
  • 只有100%肯定本身在作什麼時再force,不然會讓團隊的人很困惑
  • 如果想將某個feature遠程分支完全替換掉,能夠這樣作。

下面嘗試開master,feture兩個分支,而後基於webstorm的Version Control,觀察git rebase操做會不會有上述的變化。

master
image

feature
image

git checkout feature
git rebase master
# resolve conflict1
git rebase --continue
# resolve confict2
git rebase --continue

Rebase feature onto master
image

webstorm 的 Rebase Current onto selected什麼操做?

能夠理解成下圖這樣。

Rebase feature onto master

image

image

Current在WebStorm中指右下角的branch,selected通常指的original branch。

rebase and merge 一個Pull request作了什麼操做?

image
至關於:

git checkout feature
git rebase master

像下圖這樣:
image

image

相關文章
相關標籤/搜索