Git 如何優(yōu)雅地回退代碼
來(lái)源:cnblogs.com/zhenbianshu/p/12018714.html
前言
最后決定先將代碼回退到 A 版本之前,再基于舊版本修復(fù) Bug,也就開(kāi)始了五個(gè)小時(shí)的受苦之路。
基礎(chǔ)試探
revert
git revert commit_id 能產(chǎn)生一個(gè) 與 commit_id 完全相反的提交,即 commit_id 里是添加, revert 提交里就是刪除。mainline所以 revert 的文案被廢棄了。
Reset
reset 了, reset 也能使代碼回到某次提交,但跟 revert 不同的是, reset 是將提交的 HEAD 指針指到某次提交,之后的提交記錄會(huì)消失,就像從沒(méi)有過(guò)這么一次提交。--hard 選項(xiàng)完全拋棄這些舊代碼,reset 后再?gòu)?qiáng)制推到遠(yuǎn)端。master> git reset --hard commit_id
master> git push --force origin master
reflog 恢復(fù),但也是一番折騰。另外,reset 畢竟太野蠻,我們還是想能保留提交歷史,以后排查問(wèn)題也可以參考。
升級(jí)融合
rebase
rebase 把多個(gè)提交合并成一個(gè)提交,再使用 revert 產(chǎn)生一次反提交,這種方法的思路非常清晰,把 revert 和 rebase 兩個(gè)命令搭配得很好,相當(dāng)于使用 revert 回退的升級(jí)版。首先,切出一個(gè)新分支 F,使用 git log 查詢一下 要回退到的 commit 版本 N。使用命令 git rebase -i N, -i 指定交互模式后,會(huì)打開(kāi) git rebase 編輯界面,形如:pick 6fa5869 commit1
pick 0b84ee7 commit2
pick 986c6c8 commit3
pick 91a0dcc commit4這些 commit 自舊到新由上而下排列,我們只需要在 commit_id 前添加操作命令即可。
在合并 commit 這個(gè)需求里,我們可以選擇
pick(p)最舊的 commit1,然后在后續(xù)的 commit_id 前添加squash(s)命令,將這些 commits 都合并到最舊的 commit1 上。保存 rebase 結(jié)果后,再編輯 commit 信息,使這次 rebase 失效,git 會(huì)將之前的這些 commit 都刪除,并將其更改合并為一個(gè)新的 commit5 如果出錯(cuò)了,也可以使用
git rebase --abort/--continue/--edit-todo對(duì)之前的編輯進(jìn)行撤銷、繼續(xù)編輯。這個(gè)時(shí)候,主分支上的提交記錄是 older, commit1, commit2, commit3, commit4而 F 分支上的提交記錄是 older, commit5,由于 F 分支的祖先節(jié)點(diǎn)是 older,明顯落后于主分支的 commit4,將 F 分支向主分支合并是不允許的所以我們需要執(zhí)行
git merge master將主分支向 F 分支合并,合并后 git 會(huì)發(fā)現(xiàn) commit1 到 commit4 提交的內(nèi)容和 F 分支上 commit5 的修改內(nèi)容是完全相同的,會(huì)自動(dòng)進(jìn)行合并,內(nèi)容不變,但多了一個(gè) commit5。再在 F 分支上對(duì) commit5 進(jìn)行一次 revert 反提交,就實(shí)現(xiàn)了把 commit1 到 commit4 的提交全部回退。
這種方法的取巧之處在于巧妙地利用了 rebase 操作歷史提交的功能和 git 識(shí)別修改相同自動(dòng)合并的特性,操作雖然復(fù)雜,但歷史提交保留得還算完整。
rebase 這種修改歷史提交的功能非常實(shí)用,能夠很好地解決我們遇到的一個(gè)小功能提交了好多次才好使,而把 git 歷史弄得亂七八糟的問(wèn)題,只需要注意避免在多人同時(shí)開(kāi)發(fā)的分支使用就行了。
文件操作
這種更可行的方式就是對(duì)文件操作,然后讓 git 來(lái)識(shí)別變更,具體是:
從主分支上切出一個(gè)跟主分支完全相同的分支 F。
從文件管理系統(tǒng)復(fù)制項(xiàng)目文件夾為 bak,在 bak 內(nèi)使用
git checkout N將代碼切到想要的歷史提交,這時(shí)候 git 會(huì)將 bak 內(nèi)的文件恢復(fù)到 N 狀態(tài)。在從文件管理系統(tǒng)內(nèi),將 bak 文件夾下
除了 .git文件夾下的所有內(nèi)容復(fù)制粘貼到原項(xiàng)目目錄下。git 會(huì)純從文件級(jí)別識(shí)別到變更,然后更新工作區(qū)。在原項(xiàng)目目錄下執(zhí)行
add 和 commit,完成反提交。
小結(jié)
最后終于靠著文件操作方式成功完成了代碼回退,事后想來(lái)真是一把心酸淚。
revert 適合需要回退的歷史提交不多,且無(wú)合并沖突的情景。
如果你可以向 master 強(qiáng)推代碼,且想讓 git log 里不再出現(xiàn)被回退代碼的痕跡,可以使用
git reset --hard + git push --force的方式。如果你有些 geek,追求用”正規(guī)而正統(tǒng)”的方式來(lái)回退代碼,rebase + revert 滿足你的需求。
如果你不在乎是否優(yōu)雅,想用最簡(jiǎn)單,最直接的方式,文件操作正合適。
git 真的是非常牛逼的代碼管理工具,入手簡(jiǎn)單,三五個(gè)命令組合起來(lái)就足夠完成工作需求,又對(duì) geeker 們非常友好,你想要的騷操作它都支持,學(xué)無(wú)止境啊。
