閑談 git merge 與 git rebase 的區別

來源:互聯網
上載者:User

標籤:

前言

相信大部分使用 Git 的朋友都會遇見相同的疑問,並且也從網上搜尋了不少資料。那麼,為什麼我還要寫這篇文章呢?因為我想嘗試從自己的角度解釋這個問題,如果能給到大家靈光一閃的感悟,便善莫大焉啦。估計點進來的朋友也對 merge 和 rebase 有了一定瞭解,所以我也就不浪費篇幅再去詳細介紹 merge 和 rebase,讓我們直入主題吧。

merge 與 rebase 的區別merge

現在假設我們有一個主分支 master 及一個開發分支 deve,倉庫曆史就像這樣:

現在如果在 master 分支上 git merge deve:Git 會自動根據兩個分支的共同祖先即 e381a81 這個 commit 和兩個分支的最新提交即 8ab7cff 和 696398a 進行一個三方合并,然後將合并中修改的內容產生一個新的 commit,即的 78941cb

rebase

rebase 是什麼情況呢?還是一個初始的倉庫曆史圖:

如果是在 master 分支上 git rebase deve:Git 會從兩個分支的共同祖先 3311ba0 開始提取 master 分支(當前所在分支)上的修改,即 85841be、a016f64 與 e53ec51,再將 master 分支指向 deve 的最新提交(目標分支)即 35b6708 處,然後將剛剛提取的修改依次應用到這個最新提交後面。操作會捨棄 master 分支上提取的 commit,同時不會像 merge 一樣產生一個合并修改內容的 commit,相當於把 master 分支(當前所在分支)上的修改在 deve 分支(目標分支)上原樣複製了一遍,操作完成後的版本曆史就像這樣:

可以看見 master 分支從 deve 分支最新提交 35b6708 開始依次提交了自己的三個 commit(由於是提取修改後重新依次提交,故 commit 的 hash 碼與上面的85841be、a016f64、e53ec51 不同)

rebase -i

rebase 操作加上 -i 選項可以更直觀的看見被提取的 commit 資訊。
仍然在 master 分支上 rebase deve 分支,不過這次要加上 -i 選項,即 git rebase -i deve,然後我們可以得到這樣一個文本資訊框

  • A 地區內的資訊說明了這次 rebase 操作提取了哪些 commit 記錄(f9a7673 與 edb2ba2),會串連到目標分支的哪個 commit (9c86a5c)後面。可以根據 B 地區中的命令說明修改 pick 為其他命令,對該次提取出來的 commit 做額外的操作

  • B 地區內說明了本次 rebase 操作可以選用的命令

  • 通過 :wq 儲存退出後,就會按照剛剛在 A 地區內設定的命令處理 commit 並 rebase。

衝突處理策略的不同
  • merge 遇見衝突後會直接停止,等待手動解決衝突並重新提交 commit 後,才能再次 merge

  • rebase 遇見衝突後會暫停當前操作,開發人員可以選擇手動解決衝突,然後 git rebase --continue 繼續,或者 --skip 跳過(注意此操作中當前分支的修改會直接覆蓋目標分支的衝突部分),亦或者 --abort 直接停止該次 rebase 操作

merge --no-ff 與 merge --ff-only 的區別

上面對 merge 的講述都是基於其預設操作即 --no-ff(git merge xxx = git merge --no-ff xxx)的說明,但是 merge 還有一種常用的選項 --ff-only,那麼這兩種有什麼區別呢?
--no-ff 是 merge 的預設操作,三方合并並提交修改;而 --ff-only 會判斷當前分支可否根據目標分支快速合并,就像下面這樣

此時 deve 分支就可與 master 分支快速合并。
在 deve 分支上 git merge --ff-only master,便得到合并完成後的版本曆史圖

可以發現 --ff-only 產生的記錄和 rebase 十分相似,但是本質上 --ff-only 仍然是合併作業,但 rebase 並沒有做合并,僅僅是提取修改到目標分支後面。

總結:選擇 merge 還是 rebase?
  • merge 是一個合併作業,會將兩個分支的修改合并在一起,預設操作的情況下會提交合并中修改的內容

  • merge 的提交曆史忠實地記錄了實際發生過什麼,關注點在真實的提交曆史上面

  • rebase 並沒有進行合併作業,只是提取了當前分支的修改,將其複製在了目標分支的最新提交後面

  • rebase 的提交曆史反映了項目過程中發生了什麼,關注點在開發過程上面

  • merge 與 rebase 都是非常強大的分支整合命令,沒有優劣之分,使用哪一個應由項目和團隊的開發需求決定

  • merge 和 rebase 還有很多強大的選項,可以使用 git help <command> 查看

最後:一些注意點
  • 使用 merge 時應考慮是採用 --no-ff 預設操作,產生一個對回顧提交曆史並不友好的合并記錄,還是採用 --ff-only 方式

  • rebase 操作會丟棄當前分支已提交的 commit,故不要在已經 push 到遠程,和其他人正在協作開發的分支上執行 rebase 操作

  • 與遠程倉庫同步時,使用 pull 命令預設進行了 git fetch + git merge --no-ff 兩個操作,可以通過加上 --rebase 命令將 fetch 後的 merge 操作改為 rebase 操作,或者僅僅 ‘git fetch remoteName‘,然後才思考採取哪種整合策略 git merge(or rebase) origin/master

  • 開發與 commit 時注意自己此時在哪個分支上

  • 當有修改未 commit 時,不能進行 rebase 操作,此時可以考慮先用 git stash 命令暫存

參考:
    • ProGit 2nd Edition

    • Stackoverflow:Is there a difference between git rebase and git merge --ff-only

    • Git分支管理原則

 

閑談 git merge 與 git rebase 的區別

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.