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