Git之master主干代碼回滾

http://www.heartthinkdo.com/?p=1791
http://blog.psjay.com/posts/git-revert-merge-commit/

通過(guò)git revert來(lái)實(shí)現(xiàn)線主干代碼的回滾次慢。如下命令

  • 對(duì)于 merge類型的commit對(duì)象,還需要“-m”參數(shù)

git revert -m 1 commit-id

  • 對(duì)于普通的commtit對(duì)象

git revert commit-id

1 問(wèn)題描述

一個(gè)同事不小把自己代碼合并 到了master生成C2。但是在該同事還沒(méi)有回滾之前暑刃,又有其他同事合并到master生成了 C3∷夏纾現(xiàn)在問(wèn)題是我們想要回滾到C1應(yīng)該怎么做吉懊?

1

2 解決問(wèn)題

1拖吼、選擇git revert還是git reset授滓?

git revert是生成新的commit對(duì)象琳水,而git reset是刪除commit對(duì)象,為了保留記錄般堆,使用git revert命令在孝。

2、解決

按時(shí)間順序淮摔,依次回滾每一個(gè)commit對(duì)象私沮,直到自己想要的那個(gè)commit對(duì)象為準(zhǔn)。如下:

  • 回滾C3 ,c3-id是C3對(duì)應(yīng)的那個(gè)commit-id

git revert -m 1 c3-id

  • 回滾C2和橙。其中c2-id是C2對(duì)應(yīng)的那個(gè)commit-id

git revert -m 1 c2-id

3仔燕、上面的命令為什么有“-m 1”造垛?

這是因?yàn)樯厦娴腃2和C3不是普通的commit對(duì)象,都是merge生成的commit對(duì)象涨享。如下圖筋搏,如果需要通過(guò)git revert回滾M3,那么此時(shí)會(huì)在M3后面生成一個(gè)新的commit節(jié)點(diǎn)R,那么這個(gè)新節(jié)點(diǎn)R是屬于M分支(M1->M2->M3->R)還是D分支(D1->D2->D3->R)呢厕隧?此時(shí)可以通過(guò)“-m” 來(lái)指定奔脐,如果是1,表示的是當(dāng)前所在的分支吁讨,如果是2表示的是另外的分支髓迎。

2

對(duì)于上面的問(wèn)題,由于我們當(dāng)前分支是master建丧,我們希望revert之后生成的commit也在master這條分支上排龄,所以指定“-m 1”。

這里需要注意的是翎朱,如果只是普通的commit 對(duì)象橄维,不是merge類型commit對(duì)象(由merge產(chǎn)生commit對(duì)象),就不需要”-m 1″了

3 問(wèn)題總結(jié)

后續(xù)再遇到代碼回滾拴曲,通過(guò)哪些步驟來(lái)做呢争舞?這里總結(jié)了一些步驟。

1澈灼、假設(shè)在master上C0后面有C1竞川、C2、C3三次代碼提交叁熔,此時(shí)需要回滾到C0委乌。

3

2、回滾步驟如下

(1)第一步 切到master代碼荣回,使用git log遭贸,如下圖,獲取到每一個(gè)commit對(duì)象對(duì)應(yīng)的commit-id和commit對(duì)象類型(是普通類型還是merge類型)心软。

commit ee1389bba4bfcaa0ddb850c6e58d1e982fdfcb4d
  Merge:  8397201  7dc873c
  Author:  jie01  <jie01@qq.com>
  Date: Thu Oct  12  20:27:33  2017  +0800
    Merge branch  'fweb_1-0-806_BRANCH'  into master

commit  2f315650dff28e94d654309ed3230c34d32f1000
  Author:  shan03  <shan03@qq.com>
  Date: Tue Oct  17  14:33:16  2017  +0800

commit  7dc873cd34b8bba1fab68635ddf8331ab2babc74
  Merge:  cbaf7d9 d24f133
  Author:  xu01  <xu01@qq.com>
  Date: Thu Oct  12  15:59:13  2017  +0800
    Merge branch  'web_1-0-790_BRANCH'  into financeweb_1-0-806_BRANCH

(2) 第二步 按時(shí)間倒序革砸,依次執(zhí)行”git revert”回滾每一個(gè)commit對(duì)象

  • 對(duì)于 merge類型的commit對(duì)象,需要“-m”參數(shù)
    git revert -m 1 commit-id
  • 對(duì)于普通的commtit對(duì)象
    git revert commit-id

所以回滾命令如下

  • 回滾C3糯累,merge類型commit對(duì)象,需要-m

git revert -m 1 ee1389bba4bfcaa0ddb850c6e58d1e982fdfcb4d

  • 回滾C2,普通commit對(duì)象

git revert 2f315650dff28e94d654309ed3230c34d32f1000

  • 回滾C1册踩,merge類型commit對(duì)象泳姐,需要-m

git revert -m 1 7dc873cd34b8bba1fab68635ddf8331ab2babc74

后續(xù)問(wèn)題

比如說(shuō)當(dāng)M3執(zhí)行了git revet生成RM3,此時(shí)在master上又有其他人提交了M4,我們還需要在dev上進(jìn)行開(kāi)發(fā)D4和D5暂吉,如下圖

Snip20171203_2

此時(shí)怎么合并D5到master的M4

(1)第一步 master合并到D5

因?yàn)閙aster執(zhí)行了git revert撤銷操作胖秒,所以此時(shí)D1和D2的代碼會(huì)被刪除缎患?

  • 在master上執(zhí)行g(shù)it revert撤銷 RM3
  • 將master合并到dev的D5

(2)第二步 將dev的合并到master

附1 其他方法-通過(guò)覆蓋方法來(lái)實(shí)現(xiàn)回滾主干

步驟如下:

  • 第一步 分別拉兩份代碼。第一份代碼上面基于master新建一個(gè)分支F1阎肝,作為發(fā)布分支挤渔;第二份代碼可以通過(guò)git checkout切到自己想要回滾的那個(gè)版本上(切到某個(gè)commit對(duì)象上)。
  • 第二步 刪除分支F1對(duì)應(yīng)的代碼风题,把第二份代碼拷貝到F1上面判导,即使用第二份代碼覆蓋F1的代碼。沛硅。
  • 第三步 提交F1代碼眼刃,并合并到master。

附2 git revert和git reset區(qū)別

1摇肌、git revert 擂红。只是撤銷某一次commit的操作,并沒(méi)有刪除commit對(duì)象围小;并且會(huì)生成一個(gè)新的commit對(duì)象昵骤。

假設(shè)分支為m1->m2->m3。當(dāng)我們”git revet m2″生成m4肯适,此時(shí)在m4里面只是把m2的操作撤銷了而已变秦,并沒(méi)有撤銷m2和m3對(duì)象。此時(shí)分支為“m1->m2->m3->m4”

2疹娶、git reset伴栓。刪除某一個(gè)commit之后所有commit提交對(duì)象;不會(huì)產(chǎn)生新的commit對(duì)象雨饺。

假設(shè)m1->m2->m3钳垮,當(dāng)我們git reset m2,此時(shí)并沒(méi)有生成新的commit對(duì)象额港,并且刪除了m2和m3兩個(gè)commit對(duì)象饺窿,此時(shí)分分支為”m1->m2″

撤銷提交

Git 的 revert 命令可以用來(lái)撤銷提交(commit),對(duì)于常規(guī)的提交來(lái)說(shuō)移斩,revert 命令十分直觀易用肚医,相當(dāng)于做一次被 revert 的提交的「反操作」并形成一個(gè)新的 commit,但是當(dāng)你需要撤銷一個(gè)合并(merge)的時(shí)候向瓷,事情就變得稍微復(fù)雜了一些肠套。

Merge Commit
在描述 merge commit 之前,先來(lái)簡(jiǎn)短地描述一下常規(guī)的 commit猖任。每當(dāng)你做了一批操作(增加你稚、修改、或刪除)之后,你執(zhí)行 git commit 便會(huì)得到一個(gè)常規(guī)的 Commit刁赖。執(zhí)行 git show <commit> 將會(huì)輸出詳細(xì)的增刪情況搁痛。

Merge commit 則不是這樣。每當(dāng)你使用 git merge 合并兩個(gè)分支宇弛,你將會(huì)得到一個(gè)新的 merge commit鸡典。執(zhí)行 git show <commit> 之后,會(huì)有類似的輸出:

commit 19b7d40d2ebefb4236a8ab630f89e4afca6e9dbe
Merge: b0ef24a cca45f9
......
其中枪芒,Merge 這一行代表的是這個(gè)合并 parents彻况,它可以用來(lái)表明 merge 操作的線索。

舉個(gè)例子病苗,通常疗垛,我們的穩(wěn)定代碼都在 master 分支,而開(kāi)發(fā)過(guò)程使用 dev 分支硫朦,當(dāng)開(kāi)發(fā)完成后贷腕,再把 dev 分支 merge 進(jìn) master 分支:

a -> b -> c -> f -- g -> h (master)
           \      /
            d -> e  (dev)

上圖中,g 是 merge commit咬展,其他的都是常規(guī) commit泽裳。g 的兩個(gè) parent 分別是 f 和 e。

Revert a Merge Commit
當(dāng)你使用 git revert 撤銷一個(gè) merge commit 時(shí)破婆,如果除了 commit 號(hào)而不加任何其他參數(shù)涮总,git 將會(huì)提示錯(cuò)誤:

git revert g
error: Commit g is a merge but no -m option was given.
fatal: revert failed
在你合并兩個(gè)分支并試圖撤銷時(shí),Git 并不知道你到底需要保留哪一個(gè)分支上所做的修改祷舀。從 Git 的角度來(lái)看瀑梗,master 分支和 dev 在地位上是完全平等的,只是在 workflow 中裳扯,master 被人為約定成了「主分支」抛丽。

于是 Git 需要你通過(guò) m 或 mainline 參數(shù)來(lái)指定「主線」。merge commit 的 parents 一定是在兩個(gè)不同的線索上饰豺,因此可以通過(guò) parent 來(lái)表示「主線」亿鲜。m 參數(shù)的值可以是 1 或者 2,對(duì)應(yīng)著 parent 在 merge commit 信息中的順序冤吨。

以上面那張圖為例蒿柳,我們查看 commit g 的內(nèi)容:

git show g
commit g
Merge: f e
那么,$ git revert -m 1 g 將會(huì)保留 master 分支上的修改漩蟆,撤銷 dev 分支上的修改垒探。

撤銷成功之后,Git 將會(huì)生成一個(gè)新的 Commit怠李,提交歷史就成了這樣:


a -> b -> c -> f -- g -> h -> G (master)
           \      /
            d -> e  (dev)

其中 G 是撤銷 g 生成的 commit叛复。通過(guò) $ git show G 之后仔引,我們會(huì)發(fā)現(xiàn) G 是一個(gè)常規(guī)提交,內(nèi)容就是撤銷 merge 時(shí)被丟棄的那條線索的所有 commit 的「反操作」的合集褐奥。

Recover a Reverted Merging
上面的提交歷史在實(shí)踐中通常對(duì)應(yīng)著這樣的情況:

工程師在 master 分支切出了 dev 分支編寫新功能,開(kāi)發(fā)完成后合并 dev 分支到 master 分支并上線翘簇。上線之后撬码,發(fā)現(xiàn)了 dev 分支引入了嚴(yán)重的 bug,而其他人已經(jīng)在最新的 master 上切出了新的分支并進(jìn)行開(kāi)發(fā)版保,所以不能簡(jiǎn)單地在 master 分支上通過(guò)重置(git reset )來(lái)回滾代碼呜笑,只能選擇 revert 那個(gè) merge commit。

但是事情還沒(méi)有結(jié)束彻犁。工程師必須切回 dev 分支修復(fù)那些 bug叫胁,于是提交記錄變成了這個(gè)樣子:

a -> b -> c -> f -- g -> h -> G -> i (master)
           \      /
            d -> e -> j -> k (dev)

工程師返回 dev 分支通過(guò) j,k 兩個(gè) commit 修復(fù)了 bug汞幢,其他工程師在 master 上有了新的提交 i⊥斩欤現(xiàn)在到了 dev 分支的內(nèi)容重新上線的時(shí)候了。

直覺(jué)上來(lái)說(shuō)森篷,還是和之前一樣输钩,把 dev 分支合并到 master 分支就好了。于是:

$ git checkout master
$ git merge dev
得到的提交記錄變成了這樣:

a -> b -> c -> f -- g -> h -> G -> i -- m (master)
           \      /                    /
            d -> e -> j -> k ---------    (dev)

m 是新的 merge commit仲智。需要注意的是买乃,這不能得到我們期望的結(jié)果。因?yàn)?d 和 e 兩個(gè)提交曾經(jīng)被丟棄過(guò)钓辆,如此合并到 master 的代碼剪验,并不會(huì)重新包含 d 和 e 兩個(gè)提交的內(nèi)容,相當(dāng)于只有 dev 上的新 commit 被合并了進(jìn)來(lái)前联,而 dev 分支之前的內(nèi)容功戚,依然是被 revert 掉了。

所以蛀恩,如果想恢復(fù)整個(gè) dev 所做的修改疫铜,應(yīng)該:

$ git checkout master
$ git revert G
$ git merge dev
于是,提交歷史變成了這樣:

a -> b -> c -> f -- g -> h -> G -> i -> G' -- m (master)
           \      /                          /
            d -> e -> j -> k ---------------    (dev)

其中 G' 是這次 revert 操作生成的 commit双谆,把之前撤銷合并時(shí)丟棄的代碼恢復(fù)了回來(lái)壳咕,然后再 merge dev 分支,把解 bug 寫的新代碼合并到 master 分支顽馋。

現(xiàn)在谓厘,工程師可以放心地上線沒(méi)有 bug 的新功能了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末寸谜,一起剝皮案震驚了整個(gè)濱河市竟稳,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖他爸,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件聂宾,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡诊笤,警方通過(guò)查閱死者的電腦和手機(jī)系谐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)讨跟,“玉大人纪他,你說(shuō)我怎么就攤上這事×澜常” “怎么了茶袒?”我有些...
    開(kāi)封第一講書人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)凉馆。 經(jīng)常有香客問(wèn)我薪寓,道長(zhǎng),這世上最難降的妖魔是什么句喜? 我笑而不...
    開(kāi)封第一講書人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任预愤,我火速辦了婚禮,結(jié)果婚禮上咳胃,老公的妹妹穿的比我還像新娘植康。我一直安慰自己,他們只是感情好展懈,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布销睁。 她就那樣靜靜地躺著,像睡著了一般存崖。 火紅的嫁衣襯著肌膚如雪冻记。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,816評(píng)論 1 290
  • 那天来惧,我揣著相機(jī)與錄音冗栗,去河邊找鬼。 笑死供搀,一個(gè)胖子當(dāng)著我的面吹牛隅居,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播葛虐,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼胎源,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了屿脐?” 一聲冷哼從身側(cè)響起涕蚤,我...
    開(kāi)封第一講書人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤宪卿,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后万栅,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體佑钾,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年烦粒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了次绘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡撒遣,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出管跺,到底是詐尸還是另有隱情义黎,我是刑警寧澤,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布豁跑,位于F島的核電站廉涕,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏艇拍。R本人自食惡果不足惜狐蜕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望卸夕。 院中可真熱鬧层释,春花似錦、人聲如沸快集。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)个初。三九已至乖寒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間院溺,已是汗流浹背楣嘁。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留珍逸,地道東北人逐虚。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像弄息,于是被迫代替她去往敵國(guó)和親痊班。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348