一條Sql的執行過程
什麼是git merge?
git merge是我們在git操作中頻繁會用到的一個命令,它主要實現的功能便是為我們進行分支程式碼的合併,也就是將兩個或兩個以上的開發歷史合併在一起的操作。
它有以下兩種用途:
- 更新程式碼時,整合另一個程式碼倉庫中的變化,也就是git pull命令中,我們使用git pull命令時,實際上相當於git fetch+git merge,進行了遠端倉庫程式碼的拉取,以及整合另一程式碼倉庫中的變化
- 用於從一個分支到另一個分支的合併,我們一般會通過該命令進行從指定的commit(s)合併到當前分支的操作,要注意的是這裡的指定commit(s)是指從這些歷史commit節點開始,一直到當前分開的時候。git merge有個重要的特點,便是在合併過程中,它會建立一個新的commit節點,來作為我們的合併結果節點,如下圖
b. 我們從D的位置,checkout出一個新分支feature,並增加了兩次提交E和F。
c. 然後我們想將feature分支合併到master上,此時我們只需要在master分支上執行git merge feature此時將在master上將合併結果生成一個新的commit節點G,最終推送遠端分支。
可見merge命令的強大和便利,通過分支來完成需求程式碼的編寫,再通過合併的方式,保證了主分支的整潔性。
什麼是git rebase?
說完了git merge,我們來說一說git rebase。
我們可以把git rebase理解成是“重新設定基線”,將你的當前分支重新設定開始點。我們便能知道你當前分支與你需要比較的分支之間的差異。
也就是基於一個分支來設定你當前的分支的基線,這基線就是當前分支的開始時間軸向後移動到最新的跟蹤分支的最後面,這樣你的當前分支就是最新的跟蹤分支。
它有以下幾點用途:
- 合併提交記錄,比如說對於我們拉取出來的開發分支,可能會在開發過程中多次提交測試,會產生很多不規範的、不必要的提交,這類提交將會造成我們的分支汙染,當出現問題需要回退時,將增加難度。
- 合併分支,乍一看好像與merge命令擁有同樣的功能,是的,它們都能合併,不過彼此的合併原理卻大大不同,git merge是將合併結果產生新節點,不影響歷史的提交,而git rebase是基於變基的操作,它會將分支的開始點基於rebase的分支重新設定,並將rebase的分支重新提交,直接貼到該分支開始點之後,再之後才是該分支自己的提交。多說無益,我們根據這兩點來描述下場景,加深大家的理解:
合併提交記錄
假設此時分支上有三次提交,分別是first commit,second commit,third commit,我希望將前兩次進行合併,最終得到兩次提交的結果。
a. 我們使用“git rebase -i HEAD~3”命令檢視最近三次提交,並開啟一個編輯器,其中第一列為“操作指令”,第二列和第三列為我們的提交資訊:
git rebase -i HEAD~3
b. 操作指令包括:pick:保留該commit;reword:保留該commit但是修改commit資訊;edit:保留該commit但是要修改commit內容;squash:將該commit和前一個commit合併;fixup:將該commit和前一個commit合併,並不保留該commit的commit資訊;exec:執行shell命令;drop:刪除該commit。在本次操作中,我們將使用squash命令,將第二個合併到第一個裡面去,修改後儲存退出,如下:
在編輯器中修改,將第二個的操作指令修改為squash
c. 儲存退出,進入編輯器,對合並後的commit資訊進行編輯,我們將“1&2 commit.”編輯到this is a combination of 2 commits的下面。並儲存退出。
d. 最後我們來看下結果,通過git log看日誌 或者 git rebase -i,可見第二次提交已經不見了,第一次提交的提交資訊變成了我們剛剛修改的“1&2 commit.”。便完成了提交記錄的合併。
合併分支
假設我們現在有個需求開發,所以我們就從主分支master上拉出了一個開發分支dev,在該分支上迭代程式碼,但此時其他同事也在同時進行開發,也就是如下情況:
兩個開發分支都從commit-C處拉取處新分支
若dev2分支提前完成,將程式碼合併到了master分支上了,此時master分支就變成如下:
master的提交記錄便發生了變化,增加了新節點H
那麼為了提交不衝突,此時我們會使用merge命令,將修改後的master合併到dev分支上,結果便會導致dev分支會出現一些merge的資訊,汙染了dev分支的commits,那麼此時我們就可以使用rebase命令,來將master的變化合併到dev上,該操作會將dev分支的開始節點進行變基,變成master當前的狀態,再增加我們的新修改
通過git rebase master,進行變基合併
也就是說,當我們在dev分支上使用git rebase master後,git會把dev分支裡面的每個commit取消掉,然後把上面的操作臨時儲存成 patch 檔案,存在 .git/rebase 目錄下;然後,把 dev 分支更新到最新的 master 分支;最後,把上面儲存的 patch 檔案應用到 dev 分支上;
結果便是,原先dev分支是從C開始的,通過變基後,變成了從H開始,就相當於此時剛從master拉取的一個新分支,這麼一看,是不是dev的commit-log就變成很整潔,沒有受到汙染呢。
兩者的區別
通過上述兩者的描述,我們就能總結出這兩個命令的區別啦:
rebase:會把你當前分支的 commit 放到公共分支的最後面,所以叫變基。就好像你從公共分支又重新拉出來這個分支一樣。
就像剛剛上面的例子: 如果你從 master 拉了個dev分支出來,然後你提交了幾個 commit,這個時候剛好有人把他開發的東西合併到 master 了,這個時候 master 就比你拉分支的時候多了幾個 commit,如果這個時候你 rebase master 的話,就會把你當前的幾個 commit,放到那個人 commit 的後面。
merge:會把公共分支和你當前的commit 合併在一起,形成一個新的 commit 提交。
兩者的使用場景
merge命令一般用於將開發分支、熱修復分支等合併到主分支上,因為該命令不會修改分支的歷史資訊,只會增加新節點,非常適合主分支這種穩定性且需要用於版本控制的分支上。
rebase命令一般用於將基分支的新提交記錄,合併到正在進行開發任務或修復任務的分支上,因為該命令能保證開發分支的歷史與基分支的歷史保持一致,從而減少汙染性。
但要注意,rebase命令最好不要用於一個公共的分支,假設你們公司的開發分支是一個公用的分支,此時多人在這個分支上開發,由於rebase的修改歷史的特點,可能會出現丟失修改的問題,對於這種運用,建議團隊之間進行溝通後決定使用merge或rebase來保證該公用開發分支的可用和完整。
我在工作中的運用
在工作中,我們會擁有自己的開發分支,在完成需求需要進行版本迭代的時候,會將開發分支的提交合併到master上,一般我的操作如下:
a. 通過git stash,將我自己開發分支的程式碼儲存到暫存區中,恢復本地倉庫到修改前的狀態;
b. checkout master進入主分支,git pull拉取master的最新commits;
c. checkout mydev進入開發分支,通過git rebase master將master最新的提交,合併到自己的開發分支上, 保證該分支的歷史提交與master相同;
d. git stash pop將自己的修改取出;git commit、git push提交到遠端開發分支上;
e. 發起merge請求,合併到master分支;
stash的原理:
將本地沒提交的內容(git commit
的內容不會被快取 但git add
的內容會被快取)進行快取並從當前分支移除,快取的資料結構為堆疊,先進後出
轉載:https://baijiahao.baidu.com/s?id=1680806105354751556&wfr=spider&for=pc