#前言
git rebase命令經(jīng)常被認(rèn)為是Git的巫術(shù),初學(xué)者應(yīng)該遠(yuǎn)離它,但它實(shí)際上可以讓開發(fā)團(tuán)隊(duì)在使用時(shí)更加輕松。今天,我們將git rebase與相關(guān)git merge命令進(jìn)行比較。
#概念
首先要理解的是git rebase和git merge解決了同樣的問題。這兩個(gè)命令都旨在將更改從一個(gè)分支集成到另一個(gè)分支 - 它們只是以不同的方式進(jìn)行。試想一下當(dāng)你開始在專用分支中開發(fā)新功能時(shí)另一個(gè)團(tuán)隊(duì)成員以新提交更新master分支會(huì)發(fā)生什么。這會(huì)出現(xiàn)分叉歷史記錄,對(duì)于使用Git作為協(xié)作工具的任何人來說都應(yīng)該很熟悉。
當(dāng)合并master分支到你的feature分支時(shí),你有兩個(gè)選擇:merge或rebase。
#Merge
最簡單最常用的是將master分支合并到feature分支中:
git checkout feature git merge master 或者,你可以簡化為一行: git merge master feature
這會(huì)在feature分支中創(chuàng)建一個(gè)新的“merge commit”,它將兩個(gè)分支的歷史聯(lián)系在一起,為你生成如下所示的分支結(jié)構(gòu):
合并很好,因?yàn)樗且环N非破壞性的操作。現(xiàn)有分支結(jié)構(gòu)不會(huì)以任何方式更改。這避免了rebase的所有潛在缺陷(下面細(xì)說)。另一方面,這也意味著每次上游更改時(shí)feature都需要合并,且有無關(guān)的合并提交。如果master改動(dòng)非常頻繁,這可能會(huì)嚴(yán)重污染你分支的歷史記錄。盡管可以使用高級(jí)git log選項(xiàng)減輕此問題的影響,但它可能使其他開發(fā)人員難以理解項(xiàng)目的歷史更改記錄。
#Rebase
作為merge的替代方法,你可以使用以下命令將feature分支rebase到master分支上:
git checkout feature git rebase master
這會(huì)將整個(gè)feature分支移動(dòng)到master分支的頂端,從而有效地整合了所有master的新提交。但是,rebase不是使用merge commit,而是通過為原始分支中的每個(gè)提交創(chuàng)建全新的提交來重寫項(xiàng)目歷史記錄。
rebase的主要好處是可以獲得更清晰的項(xiàng)目歷史記錄。首先,它消除了不必要的git merge產(chǎn)生的merge commit。其次,正如在上圖中所看到的,rebase也會(huì)產(chǎn)生完美線性的項(xiàng)目歷史記錄 - 你可以從feature分支頂端一直跟隨到項(xiàng)目的開始而沒有任何的分叉。
這使得它比命令git log,git bisect和gitk更容易瀏覽項(xiàng)目。但是,對(duì)這個(gè)原始的提交歷史記錄有兩個(gè)權(quán)衡:安全性和可追溯性。如果你不遵循rebase的黃金法則,重寫項(xiàng)目歷史記錄可能會(huì)對(duì)你的協(xié)作工作流程造成災(zāi)難性后果。其次rebase會(huì)丟失merge commit提供的上下文 - 你無法看到上游更改何時(shí)合并到功能中。
Interactive rebase使你有機(jī)會(huì)在將提交移動(dòng)到新分支時(shí)更改提交。這比自動(dòng)rebase更強(qiáng)大,因?yàn)樗峁┝藢?duì)分支提交歷史的完全控制。通常,這用于在合并特征分支到master分支之前清理雜亂的歷史記錄。要開始基于交互式會(huì)話,請(qǐng)將i選項(xiàng)傳遞給git rebase命令:
git checkout feature git rebase -i master
這將打開一個(gè)文本編輯器,列出即將移動(dòng)的所有提交:
pick 33d5b7a Message for commit #1 pick 9480b3d Message for commit #2 pick 5c67e61 Message for commit #3
列表準(zhǔn)確給出了執(zhí)行rebase后分支的概況。通過更改pick命令和(或)重新排序,可以使分支的歷史記錄成為你想要的內(nèi)容。例如,如果第二次提交修復(fù)了第一次提交中的一個(gè)小問題,你可以使用以下fixup命令將它們壓縮為單個(gè)提交:
pick 33d5b7a Message for commit #1 fixup 9480b3d Message for commit #2 pick 5c67e61 Message for commit #3
保存并關(guān)閉文件時(shí),Git將根據(jù)你的指令執(zhí)行rebase,從而產(chǎn)生如下所示的項(xiàng)目歷史記錄:
消除這種無意義的提交使你的歷史記錄更可讀。這是git merge無法做到的事情。
rebase的黃金法則
一旦你理解了什么是rebase,最重要的是了解什么時(shí)候不使用它。git rebase的黃金法則是永遠(yuǎn)不要在公共分支使用它。例如,想想如果你把master分支rebase到你的feature分支會(huì)發(fā)生什么:
rebase將master所有提交移動(dòng)到feature頂端。問題是這只發(fā)生在你的倉庫中。所有其他開發(fā)人員仍在使用原始版本master。由于rebase導(dǎo)致全新的提交,
Git會(huì)認(rèn)為你的master分支的歷史與其他人的歷史不同。同步兩個(gè)master分支的唯一方法是將它們合并在一起,從而產(chǎn)生額外的合并提交和兩組包含相同更改的提交(原始提交和來自rebase分支的更改)。
這將是一個(gè)非常令人困惑的情況。因此,在你運(yùn)行g(shù)it rebase之前,總是問自己,“還有其他人在用這個(gè)分支嗎?”如果答案是肯定的,那就把你的手從鍵盤上移開,考慮使用非破壞性的方式進(jìn)行(例如,git revert命令)。否則,你可以隨心所欲地重寫歷史記錄。
強(qiáng)制推
如果你嘗試將rebase過的master分支推到遠(yuǎn)程倉庫,Git將阻止你這樣做,因?yàn)樗c遠(yuǎn)程master分支沖突。但是,你可以通過傳遞--force標(biāo)志來強(qiáng)制推送,如下所示:
#這個(gè)命令要非常小心! git push --force
這將覆蓋遠(yuǎn)程master分支以匹配rebase過的分支,并使團(tuán)隊(duì)的其他成員感到困惑。因此,只有在確切知道自己在做什么時(shí)才能非常小心地使用此命令。
工作流rebase可以根據(jù)你團(tuán)隊(duì)的需要盡多地或少量地整合到你現(xiàn)有的Git工作流程中。在本節(jié)中,我們將了解rebase在功能開發(fā)的各個(gè)階段的好處。任何工作流程git rebase的第一步是為每個(gè)功能創(chuàng)建專用分支。這為你提供了必要的分支結(jié)構(gòu),以安全地利用rebase:
本地清理
將rebase加入工作流程的最佳方法之一是清理本地正在進(jìn)行的功能。通過定期執(zhí)行交互式rebase,你可以確保功能中的每個(gè)提交都具有針對(duì)性和意義。這使你可以寫代碼而無需擔(dān)心將其分解為隔離多個(gè)的提交 - 你可以在事后修復(fù)它。
調(diào)用git rebase時(shí),有兩個(gè)基(base)選項(xiàng):feature的父分支(例如master),或feature中的歷史提交。我們?cè)贗nteractive Rebasing部分看到了第一個(gè)選項(xiàng)的示例。當(dāng)你只需要修復(fù)最后幾次提交時(shí),后一種選擇很好。例如,以下命令僅針對(duì)最后3次提交的交互式rebase。
git checkout feature git rebase -i HEAD~3
通過指定HEAD~3為新的基,你實(shí)際上并沒有移動(dòng)分支 - 你只是交互式地重寫其后的3個(gè)提交。請(qǐng)注意,這不會(huì)將上游更改合并到feature分支中。
如果要使用此方法重寫整個(gè)功能,git merge-base命令可用于查找feature分支的原始基。以下內(nèi)容返回原始基礎(chǔ)的提交ID,然后你可以將其傳遞給
git rebase: git merge-base feature master
交互式rebase的使用是引入git rebase工作流的好方法,因?yàn)樗挥绊懕镜胤种АF渌_發(fā)人員唯一能看到的就是你的成品,這應(yīng)該是一個(gè)簡潔易懂的分支歷史記錄。
但同樣,這僅適用于私有功能分支。如果你通過相同的分支與其他開發(fā)人員協(xié)作,則該分支是公共的,并且你能重寫其歷史記錄。
#總結(jié)
這就是你需要知道的關(guān)于rebase你的分支。如果你更喜歡提交的干凈,消除不必要合并的線性歷史記錄,那么你在繼承另一分支的更改時(shí)應(yīng)該使用git rebase 而不是git merge。
另一方面,如果你想保留項(xiàng)目的完整歷史記錄并避免重寫公共提交的風(fēng)險(xiǎn),你可以仍然使用git merge。這兩種選擇都是完全可以的,但至少可以選擇利用git rebase有它的好處。
-
Git
+關(guān)注
關(guān)注
0文章
201瀏覽量
15889 -
Feature
+關(guān)注
關(guān)注
1文章
80瀏覽量
7881
原文標(biāo)題:git只知道m(xù)erge,試試rebase!
文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
Git常用命令總結(jié)
Git常用的超級(jí)實(shí)用命令

git命令的基本使用
開發(fā)人員在使用Git時(shí)幾種常見錯(cuò)誤
Git命令解析-merge、rebase

Git命令解析-patch、apply、diff
帶你一步一步了解Git的底層原理

通俗易懂的Git各指令的本質(zhì)
git的命令和參數(shù)
Git命令的綜合手冊(cè)怎么找
git基本操作命令用法

Git中最常用的命令介紹

評(píng)論