兩條命令讓你的git自動變基

張京發表於2021-09-26

為什麼要變基

Git官方文件中提到:

在 Git 中整合來自不同分支的修改主要有兩種方法:merge 以及 rebase

merge也就是合併,這個概念很容易理解,我們從分支上拉取程式碼進行修改,再提交的時候,如果遇到了別人的修改,則把我們的修改和他們的修改合併一下。那麼rebase中文譯為變基是什麼意思呢?首先要理解這個basebase也就是基礎的意思,當我們從程式碼分支上獲取程式碼的時候,我們就有了一個基礎,也就是base,此後的修改我們都是在這個基礎之上進行的,但是當我們需要提交修改的時候,遇到了別人的程式碼,變基這個操作就是在這個時候,我們不去合併別人的程式碼,而是直接把我們原先的基礎變掉,變成以別人修改過後的新程式碼為基礎,把我們的修改在這個新的基礎之上重新進行。基礎變掉了,所以叫作變基

那麼,變基有什麼好處呢?好處之一是可以使我們的時間線變得非常乾淨,以前採用合併的時候,時間線裡完整記錄了我們的程式碼是從哪個基礎上拉取出來的,做了哪些修改,然後又在哪個時間點合併回分支去,而採用變基之後,時間線上不再反映拉取的時間點,因為每次提交都是以最新程式碼為基礎的,所以時間線就變成了一根直線。

下面拿兩個真例項子給大家更直觀地看一下:

這是採用自動變基之前的時間線,可以看到,各種混亂:

image.png

這是採用自動變基之後的時間線,非常整齊,可以很清楚地看到哪一次修改之後又發生了什麼修改,而不是多次修改糾纏在一起:

image.png

自動變基

雖然網上關於變基的教程很多,但是一般初學者總會感到茫然,不敢輕易下手,怕萬一把時間線弄壞了,一發不可收拾。而且所有關於變基的命令都和我們已經多年習慣了的pull/add/commit/push不一樣,很多圖形化的工具例如vscode也不直接支援rebase這樣的命令,都需要手工輸入,繁瑣而且容易出錯。所以我們今天不講太多的rebase命令怎麼用,而直接用兩條命令設定一下,從此以後讓你每次提交都可以自動變基,而不必改變之前的任何操作習慣。這兩條命令就是:

git config --global pull.rebase true
git config --global rebase.autoStash true

這兩條命令在任意一臺電腦上都只需要設定一次,而且一次設定,全域性生效,所有的專案以後每次pull/push都會自動變基,再也不用擔心在提交之前忘記變基了。

原理

如果不想了解原理的話,則執行完上面兩條命令就可以去開心地變基了,完全沒有問題。如果想了解一些原理,可以接著往下看。下面我們來詳細解釋一下這兩條命令的原理:

首先,我們要搞清楚一點:什麼時機是變基的時機?一般理解是推送的時候,其實不是,而是從拉取的時候就要開始變基了,因為你拉取的時候,伺服器上可能已經有新程式碼了,所以要變基也是在這個時候,一旦發現有新基礎了,則立馬變掉。所以,通常情況下,我們拉取新程式碼無非就是一個命令:git pull,但現在我們要變基拉取,就需要用git pull --rebase。但是每次這樣執行命令就會很麻煩,而且你在vscode裡也沒有辦法自動加這個引數,所以為了方便起見,我們就設定一下第一條命令,這樣每次拉取它都會自動變基。

但是自動變基往往會帶來一個額外的問題,那就是每次當你手頭有正在編輯的檔案的時候,它就說它無法變基,因為你的工作區不乾淨。為什麼不變基的時候沒有這個問題,而一旦選擇了自動變基,工作區就必須保持乾淨呢?因為變基的操作原理是它需要先把你原生程式碼庫裡還沒有推送的那部分提交反向釋放到工作區,然後從伺服器拉取新程式碼,再以新程式碼為基礎把工作區裡的修改附加上去,因為有這個過程,所以它必須要求你的服務區是乾淨的。為此git提了兩個建議:要麼你把所有修改先全部都commit到本地,要麼你把它們都stash儲存起來。首先說,commit肯定不是一個好主意,因為很有可能這時候我們的工作做到一半,還不適合commit,如果每次pullcommit一下的話,那麼分支樹上會多出很多無用的節點。那隻剩下最後一個選擇,就是每次pull之前都stash一下,pull完了之後再把stash的內容pop出來,但這樣豈不是更麻煩?所以這裡我們用第二條命令設定一下,每次rebase的時候都自動把我們工作區裡的內容自動stash進去,rebase完成之後再自動恢復出來。

其餘要注意的就是有衝突的時候,如果有衝突,則合併完衝突之後,執行一下git rebase --continue就好了,其它和原先的用法沒有任何區別。

相關文章