Git 如何遺棄已經(jīng) Push 的提交

作者:咕咚移動技術(shù)團隊-nanchen

題目看起來很像是提供解決方案的文章,但實際上我并不會給大家直接提供解決方案添吗,我們追求的從來不應(yīng)該是答案沥曹,而是探索的過程。當然碟联,如果你只想查看答案的話妓美,請直接拉到文章最底部。

寫在前面

相信大家都知道鲤孵,Git 相比于 SVN壶栋,優(yōu)勢不言而喻,以致于現(xiàn)在大多數(shù)公司的項目都在采用 Git 進行管理普监。作為一個開發(fā)人員贵试,對 Git 的使用自然應(yīng)該是得心應(yīng)手。

如果你還不會使用 Git 的話凯正,那我勸你還是不要聲張毙玻,好好的去學習一番,再自己弄個實驗項目走一下流程漆际,以免遭到同事的鄙視淆珊。

每個公司都會有自己不一樣的 Git 分支管理規(guī)范,特別是在開發(fā)人員較多的公司奸汇,Git 的分支管理規(guī)范就顯得更加重要施符。前面比較出名的 Git Flow 分支管理策略相信不少人都已經(jīng)了解了,不熟悉的當然也可以去看看:http://nvie.com/posts/a-successful-git-branching-model/

分支管理

Git Flow 管理方式把項目分為 5 條線擂找,通常會是下面的管理方式戳吝。

  • Master:作為穩(wěn)定主分支,長期有效贯涎。不可以在此分支進行任何提交听哭,只能接受從 Hotfix 分支或者 Release 分支發(fā)起的 merge request,該分支上的每一個提交都對應(yīng)一個 Tag。
  • Develop:開發(fā)主分支陆盘,長期有效普筹。不可以在此分支上做任何提交,只接受從 Feature 分支發(fā)起的 merge request隘马。所有的 Alpha Release 都應(yīng)該在這個分支發(fā)布太防。
  • Feature:功能分支,生命周期為產(chǎn)品迭代周期酸员,每個分支對應(yīng)一期的需求蜒车。只可以從 Develop 分支進行 Kick Off♂`拢可以 merge Release 分支的代碼酿愧,生命周期結(jié)束后,需要 merge 回 Develop 分支邀泉。方式需要采用 merge request嬉挡。
  • Release:發(fā)布分支,聲明周期從新需求的預發(fā)布到正式發(fā)布呼渣,每一個分支對應(yīng)一個新版本的版本號棘伴。只可以從 Develop 分支 Kick Off寞埠。聲明周期結(jié)束后屁置,需要 Merge 回 Master 及 Develop 分支,方式同樣需要采用 merge request仁连。所有的 Beta Release 均需要在該分支發(fā)布蓝角。
  • Hotfix:熱修復分支,生命周期對應(yīng)一個或者多個需要緊急修復并上線的 Bug饭冬,每一個分支對應(yīng)一個小版本號使鹅。只可以從 Master 分支進行 Kick Off。聲明周期結(jié)束后昌抠,需要 merge 回 Master 分支和 Develop 分支患朱,方式當然也是采用 merge request。

實際上炊苫,如果你熟悉 Git 的話裁厅,你會很快發(fā)現(xiàn)上面的管理方式會存在歷史提交非常混亂的缺點侨艾,但覺得不失為一個 Git 分支管理的經(jīng)典执虹。實際上,我們可以用 rebase 去替換 merge 讓 commit 看起來更加清晰唠梨。對 rebase 和 merge 的優(yōu)劣對比這里暫不做講解袋励,感興趣的可以直接 Google 搜索。

下面就給大家分享一下發(fā)生在咕咚項目的一次坑爹的 Git 體驗。

從 git revert 說起

咕咚項目組并沒有對開發(fā)者限制 Develop 分支和 Master 分支的權(quán)限茬故,我們暫時并沒有一個專門做代碼 Review 和 PR 的角色盖灸,其實一定意義上也提現(xiàn)了團隊對每個人的信任。

我們依然會基于 Develop 做開發(fā)主線磺芭,每個需求迭代期糠雨,團隊成員會從 Develop 拉取自己的分支,并命名于 feture/XX徘跪,然后各自在自己的分支上進行開發(fā)甘邀。

由于大家開發(fā)業(yè)務(wù)上的不同,所以在需求開發(fā)完畢垮庐,整合代碼到 Develop 分支的時候松邪,一般不會出現(xiàn)太多沖突的情況。

而我這邊交接一個需求時哨查,采用 merge 的時候出現(xiàn)了一個奇怪的問題逗抑,我們姑且來重現(xiàn)一下事故現(xiàn)場。

首先使用 git branch 查看一下當前我們的本地分支寒亥。

查看分支

這里先簡單提一下我們要做的操作邮府。

"feature8.28_buyGifts" 是我們同事的分支,基于 "release8.27.0" 拉取溉奕,而 "feature8.29.0_nanchen" 是我的分支褂傀,基于 "release8.28.0" 分支拉取,所以我這邊的分支包含了最新的代碼加勤。

現(xiàn)在由于某些原因仙辟,我需要把同事的 "feature8.28_buyGifs" 分支代碼合并到我的分支上,直接接手他的代碼進行開發(fā)鳄梅。

就不要吐槽為啥不按照功能搞分支開發(fā)了叠国,原因是因為他那邊代碼基本已經(jīng)完成,現(xiàn)在只需要少量修改戴尸。

所以我們就采用 git merge <branch> 命令進行 merge 操作粟焊。

merge

我們用 git status 更容易看明白沖突了什么。

image

可以看到孙蒙,上面沖突的文件全是和同事開發(fā)的需求出現(xiàn)的沖突项棠,所以出現(xiàn)這個沖突其實令人非常懊惱,因為是不可能有其他同事改動到這些文件的马篮。

為了驗證自己的想法沾乘,我們隨意打開一個文件查看。這里就采用 vim <filename> 查看第一個文件浑测。

image

正如我們所想翅阵,確實和同事編寫的需求 Presents 類有關(guān)系歪玲,但看沖突內(nèi)容就更一臉懵逼了,因為看起來掷匠,這應(yīng)該是一個不會沖突的 merge滥崩。

于是趕緊使用 git merge --abort 撤銷這次 merge。再在 "origin/feature8.29.0_nanchen" 查看我們剛剛的文件提交歷史讹语。

image

可以很清晰的看到钙皮,確實是最近沒有任何的修改記錄。

一個 7 個月都沒人動的文件顽决,居然 merge 的時候發(fā)生了沖突短条!這讓我一臉懵逼。(手動黑人問號)

使用 git lg 查看一下該分支的提交歷史才菠,我們希望從中能得到某些思路茸时。

image

注意其中紅框中的 commit,我們這位同事之前想往 "release8.28.0" 合并他分支的代碼赋访,后面又因為某些原因可都,希望撤銷這次提交,他采用了 revert 進行處理蚓耽。雖然 revert 對文件沒有提交記錄渠牲,但 Git 卻認為我們在當前分支更改了這些文件,所以在我們 git merge 的時候步悠,Git 認為這是一次沖突签杈,并選擇了告知我們。

如若如我們所想贤徒,那我們只需要撤銷這次 revert 操作即可芹壕。

我們當然知道,可以通過 reset 命令放棄這次提交接奈,但這里后面已經(jīng)有了非常多的 commit,顯然我們這樣是不行的通孽,我們需要另辟蹊徑序宦。

解決方案?

最容易想到的大概就是直接在 merge 的時候解決沖突了背苦,但通過一系列查看以后互捌,我們發(fā)現(xiàn)文件改動量非常大,直接解決沖突并非易事行剂。所以我們還是得 想辦法取消掉這次 revert 的 commit秕噪,再進行 merge

我們知道厚宰,代碼回滾有三種方式:reset笆怠、checkout,還有我們的 revert吠昭。直觀感受沟沙,我們應(yīng)該在 reset 上想辦法。

我們來看看 reset 有些怎樣的操作方法仪缸。

image

主要想給大家講講:--soft 和 --hard 的區(qū)別。

我們經(jīng)常會用到 git reset --hard <commit> 做「毀尸滅跡」的操作,常常爽到不能自已礁击,因為這不僅可以回退到我們想要的版本,而且還「直接丟棄」了后面提交的代碼逗载,真正的「毀尸滅跡」級別的操作哆窿。

而另外一個 --soft 處理,實際上還具備點人性厉斟,雖然同樣可以回退到我們想要的版本更耻,但目標版本后面的提交都還會存放在 stage 區(qū)域中,以便后面找出證據(jù)捏膨。

說到這秧均,似乎我們已經(jīng)有了思路。

  1. 使用 git reset --soft <revert 操作的 commit ID> 回退到 revert 操作的版本号涯;
  2. 使用 git reset --hard <revert 操作的前一個 commit> 干掉那次 revert 提交目胡;
  3. 最后再把 stage 區(qū)域的所有改動匯聚成一個新的提交 commit 到我們的項目倉庫中。

當然链快,細心的你一定會發(fā)現(xiàn)誉己,在第 1 步操作后,我們還必須執(zhí)行 git stash 命令把所有的改動存到暫存區(qū)域蜗,再在第 2 步操作后使用 git stash pop 命令取出來巨双,直接進行第 2 步操作肯定還是會毀滅證據(jù)的。

我們后面的提交不見了霉祸。

這樣似乎可以解決我們的問題筑累,不過有個弊端:我們后面那么多的提交被合并成一個提交了,以后我們就沒辦法看到了丝蹭,萬一...

不少小伙伴會想到進階方案:

  1. 對 "feature8.29.0_nanchen" 的最新代碼 checkout -b 一個分支 feature_copy慢宗;
  2. 然后使用 git checkout feature8.29.0_nanchen 回到我們的分支;
  3. 然后直接對當前分支 reset 到 revert 的前一個 commit 后奔穿,我們采用 cherry-pick 方式進行傻瓜式改寫便可以把歷史重寫了镜沽。(誰說的我們不能改寫歷史?)

改寫歷史贱田?

改寫歷史缅茉?等等,好像還有一個操作:rebase男摧。

rebase 是 Git 的一個神奇的命令蔬墩,前面我也說了译打,總會有人不喜歡 merge 之后歷史的分叉,這種分叉再匯合后會讓結(jié)構(gòu)看起來非吵镂遥混亂扶平,以致于無法管理。如果你不喜歡 commit 歷史出現(xiàn)分叉蔬蕊,那 rebase 絕對是你的救星结澄。

改寫歷史是 rebase 與生俱來的能力。我們可以用 git rebase -i <commit> 進行歷史的改寫岸夯。

我們試試看在我們的項目中直接使用 git rebase -i <commit> 會怎樣麻献。

image

我們會拿到分支后面的提交歷史,并且前面還有一個 Commands猜扮。我們可以從提示中看到勉吻,上面全寫的 pick 就是代表保持這個提交的意思,edit 代表編輯此次提交...

我們希望刪除此次 revert 這次提交旅赢,那當然我們最關(guān)心的就是 drop 了齿桃,甚至我們可以更加簡單粗暴:直接刪掉這一行

然后我們便開始處理了煮盼。

image

過程中可能會出現(xiàn)沖突短纵,我們只需要解決就好。

解決掉沖突后僵控,再使用 git add <filename> 把它們 merge 進去香到。

image

oh,我們看到我們已經(jīng) rebase 成功了报破。我們再使用 git lg 查看一下提交歷史悠就。

image

我們成功改寫了歷史!

歷史改寫結(jié)束充易,我們還要做我們最開始想做的事情梗脾,進行 merge 操作。

image

可以看到蔽氨,這次我們 merge 確實如我們預期的不再發(fā)生沖突藐唠,方案親測有效!

寫在最后

寫了這么多鹉究,想必大家對解決方案也算比較清楚了。我們主要便是采用 git rebase -i <> 操作進入到 commit 歷史編輯頁面踪宠,然后進行歷史改寫處理自赔!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市柳琢,隨后出現(xiàn)的幾起案子绍妨,更是在濱河造成了極大的恐慌润脸,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件他去,死亡現(xiàn)場離奇詭異毙驯,居然都是意外死亡,警方通過查閱死者的電腦和手機灾测,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門爆价,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人媳搪,你說我怎么就攤上這事铭段。” “怎么了秦爆?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵序愚,是天一觀的道長。 經(jīng)常有香客問我等限,道長爸吮,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任望门,我火速辦了婚禮形娇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘怒允。我一直安慰自己埂软,他們只是感情好,可當我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布纫事。 她就那樣靜靜地躺著勘畔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪丽惶。 梳的紋絲不亂的頭發(fā)上炫七,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天,我揣著相機與錄音钾唬,去河邊找鬼万哪。 笑死,一個胖子當著我的面吹牛抡秆,可吹牛的內(nèi)容都是我干的奕巍。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼儒士,長吁一口氣:“原來是場噩夢啊……” “哼的止!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起着撩,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤诅福,失蹤者是張志新(化名)和其女友劉穎匾委,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體氓润,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡赂乐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了咖气。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挨措。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖采章,靈堂內(nèi)的尸體忽然破棺而出运嗜,到底是詐尸還是另有隱情,我是刑警寧澤悯舟,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布担租,位于F島的核電站,受9級特大地震影響抵怎,放射性物質(zhì)發(fā)生泄漏奋救。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一反惕、第九天 我趴在偏房一處隱蔽的房頂上張望尝艘。 院中可真熱鬧,春花似錦姿染、人聲如沸背亥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽狡汉。三九已至,卻和暖如春闽颇,著一層夾襖步出監(jiān)牢的瞬間盾戴,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工兵多, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留尖啡,地道東北人。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓剩膘,卻偏偏與公主長得像衅斩,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子怠褐,可洞房花燭夜當晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容