一、第一篇解釋
1、前言
如果你作爲一名開發人員,許多時候必須在 Merge和 Rebase 之間進行選擇。 我們從互聯網上獲得的所有參考文檔文章,幾乎都告訴我們“不要使用 Rebase,它可能會導致嚴重的問題。”在這裏,我將解釋什麼是 merge 和 rebase,爲什麼你應該(或者不應該)使用它們,以及如何做。Git Merge 和 Git Rebase 其實是都是爲了完成同樣的目的。 它們旨在將來自多個分支的更改集成到一個分支中。 雖然最終目標是相同的,但這兩種方法以不同的方式實現。這個問題在 Git 社區中引起了分歧。有些人認爲應該總是使用 rebase ,而另一些人則認爲應該總是使用 merge 。雙方都有一些令人信服的好處。
2、git merge
- merge 是一種常見的做法,不管創建分支是爲了測試、修復 bug 還是其他原因,將提交更改合併到另一個位置。 更具體地說,merge 獲取源分支的內容並將它們與目標分支集成。 在此過程中,僅更改目標分支。 源分支歷史保持不變。
- 優點:
- 簡單而又熟悉
- 保留完整的歷史和時間順序
- 維持分支的上下文
- 缺點:
- 提交歷史記錄可能會被許多合併提交污染
- 使用 git bisect 進行調試會變得更難
- 如何操作(假設A、B兩個分支,需要將A分支合併到B分支上):
git checkout B 切換到B分支上
git merge A 將A分支合併到B分支上
或是通過:
git merge A B 將A分支合併到B分支上
3、git rebase
- Rebase 是將更改從一個分支集成到另一個分支的另一種方法。 Rebase 將所有更改壓縮爲單個“補丁”。然後它將補丁集成到目標分支上。與 merge 不同,重定位使歷史變得扁平,因爲它將完成的工作從一個分支轉移到另一個分支。在這個過程中,不需要的歷史記錄被消除。Rebases 是更改應從層次結構頂部向下傳遞的方式,並且 Merge 是它們向上流回的方式
- 優點:
- 簡化可能複雜的歷史記錄
- 操作單個提交很容易(例如還原它們)
- 避免分支頻繁合併提交,頻繁回購。
- 通過將它們作爲單個提交來清理中間提交,這對DevOps團隊很有幫助
- 缺點:
- 將該功能分解爲少量提交可以隱藏上下文
- 在團隊合作時,重新定位公共存儲庫可能會很危險
- 可能帶來更多的工作:使用rebase 來保持您的 feature 分支始終更新
- 使用遠程分支 Rebase 需要強制推送。人們面臨的最大問題是他們強制推送,但還沒有設置 git push 默認值。這會導致對本地和遠程上具有相同名稱的所有分支進行更新,這是非常可怕的,並且處理起來非常糟糕。
- 如何操作(將 feature 分支 Rebase 到主分支上):
git checkout feature
git rebase master
- 這會將整個 feature 分支移動到主分支的頂部。它通過爲 原始(feature)分支中的每個提交創建全新的提交來重寫項目歷史。
4、交互式的 rebase
這允許在將提交移動到新分支時更改提交。 這比自動 rebase 更強大,因爲它提供了對分支的提交歷史的完全控制。 通常,這用於在將 feature 分支合併到主分支之前,清理雜亂的歷史記錄。
bash 代碼:
$ git checkout feature
$ git rebase -i master
這將通過打開編輯器,列出即將移動的所有提交。
bash 代碼:
pick 22d6d7c Commit message#1
pick 44e8a9b Commit message#2
pick 79f1d2h Commit message#3
這精確定義了 rebase 執行後分支的確切內容。通過重新排序實體,可以使歷史記錄看起來像您想要的任何內容。例如,可以使用 fixup ,squash ,edit 等命令代替 pick。
5、我們應選擇哪種方式
團隊在設置 Git rebase 與 merge 策略時,需要考慮幾個問題:
- 考慮跨組織的重基和Git能力級別。確定相對於可追溯性和合並歷史,您更重視重基的簡單性的程度。
- 考慮整個組織的 rebase 和 Git能力水平。 相對於 merge 的可追溯性和歷史記錄,確定您重視 rebase 的簡單程度。
- 最後,應該在清晰的分支策略的上下文中考慮關於 merge 和 rebase 的決策,成功的分支策略是圍繞團隊組織設計的。
6、個人意見
隨着團隊的增長,使用始終 merge 策略管理或跟蹤開發更改將變得非常困難。要有一個清晰易懂的提交歷史記錄,使用 Rebase 是合理和有效的。
通過考慮以下情況和指南,您可以充分利用 Rebase :
- 你在本地開發:如果您還沒有與其他人合作。此時,你應該更喜歡 rebase 而不是 merge 以保持歷史的整潔。如果您擁有存儲庫的個人分支並且未與其他開發人員共享,那麼即使您已經推送到分支之後,也可以安全地進行 rebase 。
- 您的代碼已經準備好接受評審:您創建了一個 pull 請求。其他人正在評審您的工作,並可能將其提取到他們的分支中進行本地評審。此時,您不應該 rebase 你的工作。您應該創建 rework 提交併更新您的 feature 分支。這有助於拉取請求中的可追溯性,並防止意外的歷史記錄破壞。
- 評審已經完成,準備集成到目標分支中:恭喜你!您將要刪除您的 feature 分支。考慮到其他開發人員從現在起不會在這些更改中進行獲取合併,這是您清理歷史記錄的機會。此時,您可以重寫歷史記錄並摺疊原始提交,並將那些討厭的’pr rework’和’merge’提交到一小組重點提交中。爲這些提交創建顯式合併是可選的,但有價值。它記錄了該功能何時升級爲 master 。
二、第二篇解釋
1、什麼是 rebase?
- git rebase 你其實可以把它理解成是“重新設置基線”,將你的當前分支重新設置開始點。這個時候才能知道你當前分支於你需要比較的分支之間的差異。
原理很簡單:rebase需要基於一個分支來設置你當前的分支的基線,這基線就是當前分支的開始時間軸向後移動到最新的跟蹤分支的最後面,這樣你的當前分支就是最新的跟蹤分支。這裏的操作是基於文件事務處理的,所以你不用怕中間失敗會影響文件的一致性。在中間的過程中你可以隨時取消rebase 事務。
官方解釋: https://git-scm.com/book/zh/v2/Git-分支-變基
2、git rebase 和 git merge 有啥區別?
- rebase會把你當前分支的 commit 放到公共分支的最後面,所以叫變基。就好像你從公共分支又重新拉出來這個分支一樣。
舉例:如果你從 master 拉了個feature分支出來,然後你提交了幾個 commit,這個時候剛好有人把他開發的東西合併到 master 了,這個時候 master 就比你拉分支的時候多了幾個 commit,如果這個時候你 rebase master 的話,就會把你當前的幾個 commit,放到那個人 commit 的後面。
- merge 會把公共分支和你當前的commit 合併在一起,形成一個新的 commit 提交。
3、注意:
- 不要在公共分支使用rebase
- 本地和遠端對應同一條分支,優先使用rebase,而不是merge
4、拋出問題:
-
爲什麼不要再公共分支使用rebase?
因爲往後放的這些 commit 都是新的,這樣其他從這個公共分支拉出去的人,都需要再 rebase,相當於你 rebase 東西進來,就都是新的 commit 了
1-2-3 是現在的分支狀態
這個時候從原來的master ,checkout出來一個prod分支
然後master提交了4.5,prod提交了6.7
這個時候master分支狀態就是1-2-3-4-5,prod狀態變成1-2-3-6-7
如果在prod上用rebase master ,prod分支狀態就成了1-2-3-4-5-6-7
如果是merge
1-2-3-6-7-8
… |4-5|
會出來一個8,這個8的提交就是把4-5合進來的提交 -
merge和rebase實際上只是用的場景不一樣
更通俗的解釋一波,比如rebase,你自己開發分支一直在做,然後某一天,你想把主線的修改合到你的分支上,做一次集成,這種情況就用rebase比較好.把你的提交都放在主線修改的頭上如果用merge,腦袋上頂着一筆merge的8,你如果想回退你分支上的某個提交就很麻煩,還有一個重要的問題,rebase的話,本來我的分支是從3拉出來的,rebase完了之後,就不知道我當時是從哪兒拉出來的我的開發分支同樣的,如果你在主分支上用rebase, rebase其他分支的修改,是不是要是別人想看主分支上有什麼歷史,他看到的就不是完整的歷史課,這個歷史已經被你篡改了
5、常用指令
-
git rebase -I dev 可以將dev分支合併到當前分支
這裏的”-i“是指交互模式。就是說你可以干預rebase這個事務的過程,包括設置commit message,暫停commit等等。 -
git rebase –abort 放棄一次合併
-
合併多次commit操作:
1 git rebase -i dev
2 修改最後幾次commit記錄中的pick 爲squash
3 保存退出,彈出修改文件,修改commit記錄再次保存退出(刪除多餘的change-id 只保留一個)
4 git add .
5 git rebase --continue