摘要:在git裏面常常的一個爭論是到底用rebase仍是用merge?
1. 痛苦嗎?代碼歷史中的迷失羔羊
咱們先來看一個真實的代碼提交歷史圖形化截圖:git
圖片源自 https://storage.kraken.io/kk8yWPxzXVfBD3654oMN/c8b97f4dbb5f7d49fc3eb3624eafff79/london-tube-map-commit.png程序員
https://dev.to/neshaz/git-merge-vs-git-rebase-5134github
不知道你們看到這張圖之後有什麼感覺?是否是很無語呢?我是無語凝噎的感覺。代碼歷史到了這個地步,基本上是廢了的!!!安全
經過本文咱們就來談一下代碼歷史線的問題。這裏涉及到一個代碼歷史的管理問題,若是你但願擁有比較清晰的代碼歷史,從而能夠很快速地追溯你之前的代碼記錄的話,你必定要關注這個話題。工具
若是你做爲一個程序員用過mercurial,你可能對這個rebase概念已經有所瞭解。目前程序員用的最多的source control工具是git。在git裏面常常的一個爭論是到底用rebase仍是用merge?url
說爭論其實是不太準確的。由於在實際工做中,這主要有兩種狀況,一是根本就不知道rebase,另一種是根本就不知道怎麼用rebase。spa
那咱們就說一下rebase和merge的區別,在功能上rebase把你當前的修改工做提高到最前沿,
你本身獨有的修改記錄順序不會改變,可是時間主要會基於當前目標分支的時間戳進行調整。.net
Merge不會改變時間戳。這樣就會致使不一樣的人在合併本身修改代碼記錄的時候,會出現相互交錯的情形。本文開篇是一張代碼提交歷史的截屏,裏面的連線就像電路板同樣複雜。翻譯
出現這樣的狀況,主要是由於程序員不作rebase直接merge形成的。指針
而相似這樣電路板狀的代碼提交歷史是沒有意義的,由於太過複雜了。幾乎沒有可讀性。若是你想去查看某些歷史記錄的時候,很容易被迅速淹沒在這些信息海洋裏面沒法自拔,最後失去自我,迷失了。
2. Git Merge vs. Rebase
小注:雖然已經參考連接中標註,可是有必要再強調一下此節翻譯參考了以下連接的英文內容:
https://dev.to/neshaz/git-merge-vs-git-rebase-5134
Git merge 和rebase的目的是同樣的,它們都是將多個分支合併成一個。雖然他們最終的目標是同樣的,但這兩種方法實現的方式是不一樣的。那麼咱們應該用哪一個呢?
這裏咱們有一個示例倉庫,它有兩個不一樣的分支:主分支和特性分支。咱們想把它們融合在一塊兒。讓咱們來看看如何使用這些方法來解決這個問題。
圖片源自 https://storage.kraken.io/kk8yWPxzXVfBD3654oMN/fc73a41ce658a6a566e2a54d60534ade/git-flow.png
https://dev.to/neshaz/git-merge-vs-git-rebase-5134
Merge
當你運行 git merge 時,你的 HEAD 分支會生成一個新的提交,並保留每一個提交歷史的祖先。
圖片源自 https://storage.kraken.io/kk8yWPxzXVfBD3654oMN/673b91456bdc6fd454c5ad203f825568/git-merge-2.png
https://dev.to/neshaz/git-merge-vs-git-rebase-5134
Fast forward merge是一種不建立提交的合併類型,會更新分支指針到上一次提交。
Rebase
Rebase是將一個分支的修改重寫到另外一個分支上,而不須要建立新的提交。
你在特性分支上的每個提交,都會在主分支上建立一個新的提交。這看起來就像這些提交一直是寫在主分支之上的同樣。
圖片源自 https://storage.kraken.io/kk8yWPxzXVfBD3654oMN/5ade4f7276bc6ad18dad4b6078950ac9/git-rebase.png
https://dev.to/neshaz/git-merge-vs-git-rebase-5134
Merge的優勢和缺點
優勢
- 使用簡單,易於理解。
- 保持源分支的原始上下文。
- 源分支上的提交與其餘分支的提交是分開的。
- 能夠保留提交歷史。
缺點
- 亂
圖片源自 https://storage.kraken.io/kk8yWPxzXVfBD3654oMN/c8b97f4dbb5f7d49fc3eb3624eafff79/london-tube-map-commit.png
https://dev.to/neshaz/git-merge-vs-git-rebase-5134
Rebase的優勢和缺點
優勢
- 代碼歷史是簡化的、線性的、可讀的。
- 與許多獨立的特性分支的提交歷史相比,操做單個提交歷史更容易。
- 乾淨、清晰的提交信息能夠更好地跟蹤一個bug或什麼時候引入的某個功能。能夠避免衆多的單行提交污染歷史。
缺點
- 會更改歷史提交時間,可能會丟失上下文。
比起Merge,你須要更加當心的使用Rebase。
應該用Merge仍是Rebase?
當你的團隊對於rebase不熟悉時,那麼git merge就是你的正確選擇。
- Merge容許保存任何給定功能的提交歷史,而沒必要擔憂覆蓋提交和改變歷史。
- 它能夠避免沒必要要的 git revert或reset。
另外一方面,若是你更看重乾淨、線性的代碼歷史,那麼git rebase是最合適的。這種方式能夠避免沒必要要的提交,並保持更集中和線性的變化!
這裏要注意的是,若是你不正確地重寫了歷史,可能會致使嚴重的問題,因此在使用Rebase時請確保知道你在作什麼。
3. 一杯水與一桶水
先說一下一杯水和一桶水的關係,這個關係能夠用來描述老師向學生傳授知識的情形。主要意思是說老師要是給學生一杯水的話,這個老師必需要有一桶水才行。
其實對於咱們軟件行業來講,這個道理也是適用的。
關於本文的聚焦點代碼歷史,咱們想給外部呈現的是清晰乾淨的代碼歷史記錄。要到的這個目標,咱們須要作不少的工做,這項工做相較於乾淨的代碼歷史就是一桶水與一杯水的關係。
這也是咱們常常說的,對本身狠一點,讓別人舒服一點。對本身狠一點不是一句空話,其實是讓本身絞盡腦汁的去想,如何把這個事情作好?把本身放在對方的角度上去看咱們的輸出結果。咱們問本身,我做爲這些代碼的維護者和接收者,是否是能夠接受這樣混亂的代碼歷史記錄,答案固然是否認的。
明白了這一點,在咱們作代碼歷史管理的時候,再苦再累也是值得的。
一些有多年工做經驗的程序員,他們可能用過不少代碼管理的工具,這些代碼管理工具在使用的時候常常用的一個操做就是merge。進入到git時代之後,這些程序員也保留了這樣的習慣,直接就merge。
我跟一些程序員聊過,他們甚至都沒有意識到有rebase這個操做。有的則以爲rebase太麻煩了,用了幾回就放棄了。
這絕對是人之常情。
當咱們習慣了用一種方式作事的時候,咱們作得越久感受越安全,由於它是行之有效的,可以解決問題的。當有另一種更好的方式,可是卻與之前的方式有很大差別的時候,咱們就會有本能的排斥心理。這是源於咱們對未知領域的一種恐懼感。
離開溫馨區之後,咱們大多數人都會有一種不適應,有的甚至會產生很強烈的失落感。
可是當咱們迴歸本心的時候,咱們會發現咱們所付出的一切,經受的痛苦都是值得的。由於咱們的初心就是讓用戶滿意。代碼歷史的用戶就是咱們這些程序員。
4. 如何正確作rebase?
要點備註:
Rebase相關的要點有這幾個:
- 在本身的分支上作Rebase;
- 要Rebase正確的目標分支,注意這個目標分支不是你的遠程分支,這個地方常常有人犯錯;
- Rebase要常作,以免出現衝突,或者衝突的難度增長;
- 在合入代碼以前,必定要最後作一次Rebase再Merge;
- 最好用Squash Merge, 添加正確的提交消息;
- 不要在主分支上作Rebase;
- 儘可能不要force push;
在主分支上應該rebase嗎? 怎麼去作rebase?
首先,我要強調一下,在主分支上不要作rebase。這是由於若是你在主分支上作了rebase,若是你是第1次push可能沒有問題,可是若是別的人也作了一個rebase,這個時候就致使你的主分支上有兩個不一樣的head,這個時候若是想再push的話就存在問題了。
若是一切可控的話,你能夠很是粗暴的使用強制push。可是若是團隊成員比較多,會致使這樣的操做會沖掉其餘已經進來的提交。
除非萬不得已,咱們堅定不能在主分支上去作rebase。
接下來講一個正確使用rebase的場景。在接到一個任務之後,咱們會在主分支上最新的節點處提交上建立一個新的分支。在新的分支上,咱們會不斷的進行新的提交,直到完成這個分支任務。
到這個時候,咱們想建立一個merge request或者pull request,在此以前,咱們首先要作的就是rebase,rebase選的目標分支是咱們的主分支。
完成此次rebase操做之後,咱們就能夠建立mr或者pr了。在審查過程當中可能有不少修改意見,修改完成之後須要先
rebase再push。如此反覆幾回,mr或者pr審批經過。此時要作一次squash merge把數次提交打包合成一個到主分支上。
以上是我對在正常工做流程中如何使用rebase進行了一個現實案例的描述講解,但願你們去體驗一下,告訴我體會,請留言說說你的想法。
參考文獻
https://dev.to/neshaz/git-merge-vs-git-rebase-5134
https://www.perforce.com/blog/vcs/git-rebase-vs-merge-which-better
https://product.hubspot.com/blog/git-and-github-tutorial-for-beginners
https://git-scm.com/docs/gittutorial