日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

5.1 代码合并:Merge、Rebase的选择

發(fā)布時(shí)間:2025/3/21 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 5.1 代码合并:Merge、Rebase的选择 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

BY 童仲毅(geeeeeeeeek@github)

這是一篇在原文(BY atlassian)基礎(chǔ)上演繹的譯文。除非另行注明,頁(yè)面上所有內(nèi)容采用知識(shí)共享-署名(CC BY 2.5 AU)協(xié)議共享。

git rebase?這個(gè)命令經(jīng)常被人認(rèn)為是一種Git巫術(shù),初學(xué)者應(yīng)該避而遠(yuǎn)之。但如果使用得當(dāng)?shù)脑?#xff0c;它能給你的團(tuán)隊(duì)開(kāi)發(fā)省去太多煩惱。在這篇文章中,我們會(huì)比較git rebase和類(lèi)似的git merge命令,找到Git工作流中rebase的所有用法。

概述

你要知道的第一件事是,git rebase?和git merge?做的事其實(shí)是一樣的。它們都被設(shè)計(jì)來(lái)將一個(gè)分支的更改并入另一個(gè)分支,只不過(guò)方式有些不同。

想象一下,你剛創(chuàng)建了一個(gè)專(zhuān)門(mén)的分支開(kāi)發(fā)新功能,然后團(tuán)隊(duì)中另一個(gè)成員在master分支上添加了新的提交。這就會(huì)造成提交歷史被Fork一份,用Git來(lái)協(xié)作的開(kāi)發(fā)者應(yīng)該都很清楚。

現(xiàn)在,如果master中新的提交和你的工作是相關(guān)的。為了將新的提交并入你的分支,你有兩個(gè)選擇:merge或rebase。

Merge

將master分支合并到feature分支最簡(jiǎn)單的辦法就是用下面這些命令:

git checkout feature git merge master

或者,你也可以把它們壓縮在一行里。

git merge master feature

feature分支中新的合并提交(merge commit)將兩個(gè)分支的歷史連在了一起。你會(huì)得到下面這樣的分支結(jié)構(gòu):

Merge好在它是一個(gè)安全的操作。現(xiàn)有的分支不會(huì)被更改,避免了rebase潛在的缺點(diǎn)(后面會(huì)說(shuō))。

另一方面,這同樣意味著每次合并上游更改時(shí)feature分支都會(huì)引入一個(gè)外來(lái)的合并提交。如果master非常活躍的話,這或多或少會(huì)污染你的分支歷史。雖然高級(jí)的git log?選項(xiàng)可以減輕這個(gè)問(wèn)題,但對(duì)于開(kāi)發(fā)者來(lái)說(shuō),還是會(huì)增加理解項(xiàng)目歷史的難度。

Rebase

作為merge的替代選擇,你可以像下面這樣將feature分支并入master分支:

git checkout feature git rebase master

它會(huì)把整個(gè)feature分支移動(dòng)到master分支的后面,有效地把所有master分支上新的提交并入過(guò)來(lái)。但是,rebase為原分支上每一個(gè)提交創(chuàng)建一個(gè)新的提交,重寫(xiě)了項(xiàng)目歷史,并且不會(huì)帶來(lái)合并提交。

rebase最大的好處是你的項(xiàng)目歷史會(huì)非常整潔。首先,它不像git merge?那樣引入不必要的合并提交。其次,如上圖所示,rebase導(dǎo)致最后的項(xiàng)目歷史呈現(xiàn)出完美的線性——你可以從項(xiàng)目終點(diǎn)到起點(diǎn)瀏覽而不需要任何的Fork。這讓你更容易使用git log?、git bisect?和gitk?來(lái)查看項(xiàng)目歷史。

不過(guò),這種簡(jiǎn)單的提交歷史會(huì)帶來(lái)兩個(gè)后果:安全性和可跟蹤性。如果你違反了Rebase黃金法則,重寫(xiě)項(xiàng)目歷史可能會(huì)給你的協(xié)作工作流帶來(lái)災(zāi)難性的影響。此外,rebase不會(huì)有合并提交中附帶的信息——你看不到feature分支中并入了上游的哪些更改。

交互式的rebase

交互式的rebase允許你更改并入新分支的提交。這比自動(dòng)的rebase更加強(qiáng)大,因?yàn)樗峁┝藢?duì)分支上提交歷史完整的控制。一般來(lái)說(shuō),這被用于將feature分支并入master分支之前,清理混亂的歷史。

把-i?傳入git rebase?選項(xiàng)來(lái)開(kāi)始一個(gè)交互式的rebase過(guò)程:

git checkout feature git rebase -i master

它會(huì)打開(kāi)一個(gè)文本編輯器,顯示所有將被移動(dòng)的提交:

pick 33d5b7a Message for commit #1 pick 9480b3d Message for commit #2 pick 5c67e61 Message for commit #3

這個(gè)列表定義了rebase將被執(zhí)行后分支會(huì)是什么樣的。更改pick?命令或者重新排序,這個(gè)分支的歷史就能如你所愿了。比如說(shuō),如果第二個(gè)提交修復(fù)了第一個(gè)提交中的小問(wèn)題,你可以用fixup?命令把它們合到一個(gè)提交中:

pick 33d5b7a Message for commit #1 fixup 9480b3d Message for commit #2 pick 5c67e61 Message for commit #3

保存后關(guān)閉文件,Git會(huì)根據(jù)你的指令來(lái)執(zhí)行rebase,項(xiàng)目歷史看上去會(huì)是這樣:

忽略不重要的提交會(huì)讓你的feature分支的歷史更清晰易讀。這是git merge?做不到的。

Rebase的黃金法則

當(dāng)你理解rebase是什么的時(shí)候,最重要的就是什么時(shí)候?不能?用rebase。git rebase?的黃金法則便是,絕不要在公共的分支上使用它。

比如說(shuō),如果你把master分支rebase到你的feature分支上會(huì)發(fā)生什么:

這次rebase將master分支上的所有提交都移到了feature分支后面。問(wèn)題是它只發(fā)生在你的代碼倉(cāng)庫(kù)中,其他所有的開(kāi)發(fā)者還在原來(lái)的master上工作。因?yàn)閞ebase引起了新的提交,Git會(huì)認(rèn)為你的master分支和其他人的master已經(jīng)分叉了。

同步兩個(gè)master分支的唯一辦法是把它們merge到一起,導(dǎo)致一個(gè)額外的合并提交和兩堆包含同樣更改的提交。不用說(shuō),這會(huì)讓人非常困惑。

所以,在你運(yùn)行g(shù)it rebase?之前,一定要問(wèn)問(wèn)你自己“有沒(méi)有別人正在這個(gè)分支上工作?”。如果答案是肯定的,那么把你的爪子放回去,重新找到一個(gè)無(wú)害的方式(如git revert)來(lái)提交你的更改。不然的話,你可以隨心所欲地重寫(xiě)歷史。

強(qiáng)制推送

如果你想把rebase之后的master分支推送到遠(yuǎn)程倉(cāng)庫(kù),Git會(huì)阻止你這么做,因?yàn)閮蓚€(gè)分支包含沖突。但你可以傳入--force?標(biāo)記來(lái)強(qiáng)行推送。就像下面一樣:

# 小心使用這個(gè)命令! git push --force

它會(huì)重寫(xiě)遠(yuǎn)程的master分支來(lái)匹配你倉(cāng)庫(kù)中rebase之后的master分支,對(duì)于團(tuán)隊(duì)中其他成員來(lái)說(shuō)這看上去很詭異。所以,務(wù)必小心這個(gè)命令,只有當(dāng)你知道你在做什么的時(shí)候再使用。

僅有的幾個(gè)強(qiáng)制推送的使用場(chǎng)景之一是,當(dāng)你在想向遠(yuǎn)程倉(cāng)庫(kù)推送了一個(gè)私有分支之后,執(zhí)行了一個(gè)本地的清理(比如說(shuō)為了回滾)。這就像是在說(shuō)“哦,其實(shí)我并不想推送之前那個(gè)feature分支的。用我現(xiàn)在的版本替換掉吧。”同樣,你要注意沒(méi)有別人正在這個(gè)feature分支上工作。

工作流

rebase可以或多或少應(yīng)用在你們團(tuán)隊(duì)的Git工作流中。在這一節(jié)中,我們來(lái)看看在feature分支開(kāi)發(fā)的各個(gè)階段中,rebase有哪些好處。

第一步是在任何和git rebase?有關(guān)的工作流中為每一個(gè)feature專(zhuān)門(mén)創(chuàng)建一個(gè)分支。它會(huì)給你帶來(lái)安全使用rebase的分支結(jié)構(gòu):

本地清理

在你工作流中使用rebase最好的用法之一就是清理本地正在開(kāi)發(fā)的分支。隔一段時(shí)間執(zhí)行一次交互式rebase,你可以保證你feature分支中的每一個(gè)提交都是專(zhuān)注和有意義的。你在寫(xiě)代碼時(shí)不用擔(dān)心造成孤立的提交——因?yàn)槟愫竺嬉欢苄迯?fù)。

調(diào)用git rebase?的時(shí)候,你有兩個(gè)基(base)可以選擇:上游分支(比如master)或者你feature分支中早先的一個(gè)提交。我們?cè)凇敖换ナ絩ebase”一節(jié)看到了第一種的例子。后一種在當(dāng)你只需要修改最新幾次提交時(shí)也很有用。比如說(shuō),下面的命令對(duì)最新的3次提交進(jìn)行了交互式rebase:

git checkout feature git rebase -i HEAD~3

通過(guò)指定HEAD~3作為新的基提交,你實(shí)際上沒(méi)有移動(dòng)分支——你只是將之后的3次提交重寫(xiě)了。注意它不會(huì)把上游分支的更改并入到feature分支中。

如果你想用這個(gè)方法重寫(xiě)整個(gè)feature分支,git merge-base?命令非常方便地找出feature分支開(kāi)始分叉的基。下面這段命令返回基提交的ID,你可以接下來(lái)將它傳給git rebase:

git merge-base feature master

交互式rebase是在你工作流中引入git rebase?的的好辦法,因?yàn)樗挥绊懕镜胤种АF渌_(kāi)發(fā)者只能看到你已經(jīng)完成的結(jié)果,那就是一個(gè)非常整潔、易于追蹤的分支歷史。

但同樣的,這只能用在私有分支上。如果你在同一個(gè)feature分支和其他開(kāi)發(fā)者合作的話,這個(gè)分支是公開(kāi)的,你不能重寫(xiě)這個(gè)歷史。

用帶有交互式的rebase清理本地提交,這是無(wú)法用git merge?命令代替的。

將上游分支上的更改并入feature分支

在概覽一節(jié),我們看到了feature分支如何通過(guò)git merge?或git rebase?來(lái)并入上游分支。merge是保留你完整歷史的安全選擇,rebase將你的feature分支移動(dòng)到master分支后面,創(chuàng)建一個(gè)線性的歷史。

git rebase?的用法和本地清理非常類(lèi)似(而且可以同時(shí)使用),但之間并入了master上的上游更改。

記住,rebase到遠(yuǎn)程分支而不是master也是完全合法的。當(dāng)你和另一個(gè)開(kāi)發(fā)者在同一個(gè)feature分之上協(xié)作的時(shí)候,你會(huì)用到這個(gè)用法,將他們的更改并入你的項(xiàng)目。

比如說(shuō),如果你和另一個(gè)開(kāi)發(fā)者——John——往feature分支上添加了幾個(gè)提交,在從John的倉(cāng)庫(kù)中fetch之后,你的倉(cāng)庫(kù)可能會(huì)像下面這樣:

就和并入master上的上游更改一樣,你可以這樣解決這個(gè)Fork:要么merge你的本地分支和John的分支,要不把你的本地分支rebase到John的分支后面。

注意,這里的rebase沒(méi)有違反Rebase黃金法則,因?yàn)橹挥心愕谋镜胤种系腸ommit被移動(dòng)了,之前的所有東西都沒(méi)有變。這就像是在說(shuō)“把我的改動(dòng)加到John的后面去”。在大多數(shù)情況下,這比通過(guò)合并提交來(lái)同步遠(yuǎn)程分支更符合直覺(jué)。

默認(rèn)情況下,git pull?命令會(huì)執(zhí)行一次merge,但你可以傳入--rebase?來(lái)強(qiáng)制它通過(guò)rebase來(lái)整合遠(yuǎn)程分支。

用Pull Request進(jìn)行審查

如果你將pull request作為你代碼審查過(guò)程中的一環(huán),你需要避免在創(chuàng)建pull request之后使用git rebase。只要你發(fā)起了pull request,其他開(kāi)發(fā)者能看到你的代碼,也就是說(shuō)這個(gè)分支變成了公共分支。重寫(xiě)歷史會(huì)造成Git和你的同事難以找到這個(gè)分支接下來(lái)的任何提交。

來(lái)自其他開(kāi)發(fā)者的任何更改都應(yīng)該用git merge?而不是git rebase?來(lái)并入。

因此,在提交pull request前用交互式的rebase進(jìn)行代碼清理通常是一個(gè)好的做法。

并入通過(guò)的功能分支

如果某個(gè)功能被你們團(tuán)隊(duì)通過(guò)了,你可以選擇將這個(gè)分支rebase到master分支之后,或是使用git merge?來(lái)將這個(gè)功能并入主代碼庫(kù)中。

這和將上游改動(dòng)并入feature分支很相似,但是你不可以在master分支重寫(xiě)提交,你最后需要用git merge?來(lái)并入這個(gè)feature。但是,在merge之前執(zhí)行一次rebase,你可以確保merge是一直向前的,最后生成的是一個(gè)完全線性的提交歷史。這樣你還可以加入pull request之后的提交。

如果你還沒(méi)有完全熟悉git rebase,你還可以在一個(gè)臨時(shí)分支中執(zhí)行rebase。這樣的話,如果你意外地弄亂了你feature分支的歷史,你還可以查看原來(lái)的分支然后重試。

比如說(shuō):

git checkout feature git checkout -b temporary-branch git rebase -i master # [清理目錄](méi) git checkout master git merge temporary-branch

總結(jié)

你使用rebase之前需要知道的知識(shí)點(diǎn)都在這了。如果你想要一個(gè)干凈的、線性的提交歷史,沒(méi)有不必要的合并提交,你應(yīng)該使用git rebase?而不是git merge?來(lái)并入其他分支上的更改。

另一方面,如果你想要保存項(xiàng)目完整的歷史,并且避免重寫(xiě)公共分支上的commit, 你可以使用git merge。兩種選項(xiàng)都很好用,但至少你現(xiàn)在多了git rebase這個(gè)選擇。

這篇文章是『git-recipes』的一部分,點(diǎn)擊目錄查看所有章節(jié)。

from:?https://github.com/geeeeeeeeek/git-recipes/wiki/5.1-%E4%BB%A3%E7%A0%81%E5%90%88%E5%B9%B6%EF%BC%9AMerge%E3%80%81Rebase%E7%9A%84%E9%80%89%E6%8B%A9

總結(jié)

以上是生活随笔為你收集整理的5.1 代码合并:Merge、Rebase的选择的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。