Git本地操作進(jìn)階之版本回退,撤銷(xiāo)修改與文件刪除全攻略
前言
在掌握Git本地倉(cāng)庫(kù)的基礎(chǔ)操作后,“如何修正錯(cuò)誤提交”“怎樣找回誤刪文件”“版本回退的風(fēng)險(xiǎn)與應(yīng)對(duì)”成為開(kāi)發(fā)者進(jìn)階的關(guān)鍵課題。代碼開(kāi)發(fā)中,誤改配置、提交冗余文件、刪除核心代碼等情況難以避免,而Git提供的版本回退、撤銷(xiāo)修改、文件刪除機(jī)制,正是解決這些問(wèn)題的 “安全網(wǎng)” 。本文將聚焦這些進(jìn)階操作,拆解其原理、場(chǎng)景與實(shí)操細(xì)節(jié),幫你在代碼出現(xiàn)偏差時(shí),精準(zhǔn)、安全地將版本拉回正軌。
一. Git關(guān)鍵能力:版本回退與撤銷(xiāo)修改
開(kāi)發(fā)階段中,難免會(huì)出現(xiàn)代碼寫(xiě)錯(cuò),提交誤操作等情況,Git提供了完善達(dá)到版本回退和撤銷(xiāo)機(jī)制,可根據(jù)修改所處階段靈活處理。
1.1 版本回退
通過(guò) git reset 命令實(shí)現(xiàn)版本回退,核心是通過(guò) commit id 或 HEAD 指針定位目標(biāo)版本,命令格式為:git reset 【--soft | --mixed | --hard】【HEAD】
關(guān)鍵參數(shù)說(shuō)明:
| 參數(shù) | 作用 | 風(fēng)險(xiǎn)程度 |
|---|---|---|
--mixed | 默認(rèn)參數(shù),僅暫存區(qū)回退到指定版本,工作區(qū)內(nèi)容保持不變 | 低 |
--soft | 僅版本庫(kù)回退,暫存區(qū)和工作區(qū)內(nèi)容均不改變 | 低 |
--hard | 暫存區(qū)、工作區(qū)、版本庫(kù)均回退到指定版本 | 高(工作區(qū)未提交代碼會(huì)丟失) |
HEAD 說(shuō)明:
- 可直接寫(xiě)成 commit id,表?指定退回的版本
- HEAD 表示當(dāng)前版本
- HEAD^ 上一個(gè)版本
- HEAD^^ 上上一個(gè)版本
- 以此類推…
可以使用 ?數(shù)字表示:
- HEAD~0 表示當(dāng)前版本
- HEAD~1 上一個(gè)版本
- HEAD^2 上上一個(gè)版本
- 以此類推…
實(shí)際使用:
為了便于表述,方便測(cè)試回退功能,我們需要先做一下準(zhǔn)備工作:更新3個(gè)版本的ReadMe,并分別進(jìn)行3次提交,如下所示:
# 第一次修改提交 [root@VM-4-4-centos gitcode]# echo "hello version1" >> ReadMe [root@VM-4-4-centos gitcode]# cat ReadMe hello Lotso hello version1 [root@VM-4-4-centos gitcode]# git add ReadMe [root@VM-4-4-centos gitcode]# git commit -m "add version1" [master 40bc6e6] add version1 1 file changed, 1 insertion(+) # 第二次修改提交 [root@VM-4-4-centos gitcode]# echo "hello version2" >> ReadMe [root@VM-4-4-centos gitcode]# cat ReadMe hello Lotso hello version1 hello version2 [root@VM-4-4-centos gitcode]# git add ReadMe [root@VM-4-4-centos gitcode]# git commit -m "add version2" [master 1a083cf] add version2 1 file changed, 1 insertion(+) # 第三次修改提交 [root@VM-4-4-centos gitcode]# echo "hello version3" >> ReadMe [root@VM-4-4-centos gitcode]# cat ReadMe hello Lotso hello version1 hello version2 hello version3 [root@VM-4-4-centos gitcode]# git add ReadMe [root@VM-4-4-centos gitcode]# git commit -m "add version3" [master b592a38] add version3 1 file changed, 1 insertion(+) # 查看歷史記錄 [root@VM-4-4-centos gitcode]# git log --pretty=oneline b592a387a176cfb00c56cd3cbc1d3faca9ba2cee add version3 1a083cf93e6f21ba0bf5419f32125875aa787255 add version2 40bc6e65bb49713bb9d77e00b62fcd190b461ed7 add version1 …… #之前的一些這里就不放出來(lái)了
現(xiàn)在,如果我們提交完 version3 后,發(fā)現(xiàn) version3 編寫(xiě)錯(cuò)誤,想退回到 version2 ,重新基于 version2 開(kāi)始編寫(xiě)。由于我們這里希望的是將工作區(qū)的內(nèi)容也回退到 version2 版本,所以需要用 --hard 參數(shù),示例如下:
[root@VM-4-4-centos gitcode]# git log --pretty=oneline b592a387a176cfb00c56cd3cbc1d3faca9ba2cee add version3 1a083cf93e6f21ba0bf5419f32125875aa787255 add version2 40bc6e65bb49713bb9d77e00b62fcd190b461ed7 add version1 ………… # 指定 version2 的對(duì)應(yīng)版本號(hào),回退到這個(gè)版本 [root@VM-4-4-centos gitcode]# git reset --hard 1a083cf93e6f21ba0bf5419f32125875aa787255 HEAD is now at 1a083cf add version2 [root@VM-4-4-centos gitcode]# cat ReadMe hello Lotso hello version1 hello version2
我們可以發(fā)現(xiàn),此時(shí) ReadMe 文件的內(nèi)容,已經(jīng)回退到 version2 了!,當(dāng)前,我們?cè)俅问褂?git log 查看一下提交日志,會(huì)發(fā)現(xiàn) HEAD 指向了version2 ,如下所示:
[root@VM-4-4-centos gitcode]# git log --pretty=oneline --decorate 1a083cf93e6f21ba0bf5419f32125875aa787255 (HEAD, master) add version2 40bc6e65bb49713bb9d77e00b62fcd190b461ed7 add version1 …………
到這里一般回退功能就演示完畢了,但是如果我后悔了,想再回到 version3 怎么辦?我們可以繼續(xù)使用 git reset 命令,回退到 version3 版本 ,但是我們必須拿到 version3 的 commit id 去指定回退版本。
但是我們看到了 git log 并不能打印出 version3 的 commit id ,運(yùn)氣好的話我們可以從終端上去找找之前的記錄,運(yùn)氣不好的話 commit id 就已經(jīng)被我們搞丟了~~
值得一提的是 Git 還提供了一個(gè) git reflog 命令能補(bǔ)救一下,該命令用來(lái)記錄本地的每一次指令。
[root@VM-4-4-centos gitcode]# git reflog
1a083cf HEAD@{0}: reset: moving to 1a083cf93e6f21ba0bf5419f32125875aa7
b592a38 HEAD@{1}: commit: add version3
1a083cf HEAD@{2}: commit: add version2
40bc6e6 HEAD@{3}: commit: add version1
eb85e67 HEAD@{4}: commit: delete
54cffd0 HEAD@{5}: commit: add 3 file3
1e3f5b8 HEAD@{6}: commit: commit my first file
fcce812 HEAD@{7}: commit (initial): add first file
(END)
這樣,你就可以很方便的找到你的所有的操作記錄了,但是 b592a38 這個(gè)是啥東西?這個(gè)是 version3 的 commit id 的部分。Git 版本回退的時(shí)候,也可以使用部分的 commit id 來(lái)代表目標(biāo)版本。示例如下:
# 回退到 version3 [root@VM-4-4-centos gitcode]# git reset --hard b592a38 HEAD is now at b592a38 add version3 # 查看工作區(qū) [root@VM-4-4-centos gitcode]# cat ReadMe hello Lotso hello version1 hello version2 hello version3 # 查看 log [root@VM-4-4-centos gitcode]# git log --pretty=oneline --decorate b592a387a176cfb00c56cd3cbc1d3faca9ba2cee (HEAD, master) add version3 1a083cf93e6f21ba0bf5419f32125875aa787255 add version2 40bc6e65bb49713bb9d77e00b62fcd190b461ed7 add version1 …………
可往往是理想很豐滿,現(xiàn)實(shí)很骨感。在實(shí)際開(kāi)發(fā)中,由于長(zhǎng)時(shí)間的開(kāi)發(fā),很可能會(huì)導(dǎo)致 commit id 早就找不到了,可突然某一天,我又想回到 version3 ,那該如何操作呢?貌似現(xiàn)在是不可能了~
補(bǔ)充說(shuō)明:
Git 版本的回退速度特別快,因?yàn)?Git 在內(nèi)部有個(gè)指向當(dāng)前分支(此處是master)的HEAD指針,refs/heads/master 文件里保存當(dāng)前 master 分支的最新的 commit id 。當(dāng)我們?cè)诨赝税姹镜臅r(shí)候。Git 僅僅是給refs/heads/master 中存儲(chǔ)一個(gè)特定的version ,可以簡(jiǎn)單理解為如下示意圖:

1.2 撤銷(xiāo)修改
根據(jù)修改所處階段(工作區(qū) / 暫存區(qū)),選擇不同的撤銷(xiāo)命令:
場(chǎng)景 1:修改僅在工作區(qū),未執(zhí)行g(shù)it add
使用 git checkout -- [file](這個(gè) - - 很重要,一旦省略會(huì)變成別的意思) 丟棄工作區(qū)修改,恢復(fù)到最近一次git add或git commit時(shí)的狀態(tài):
友情提示:千萬(wàn)不要想著用什么 git diff xxx 找到差異去手動(dòng)刪除,那要是改的地方多得刪多久啊,這不得累麻了
# 向 ReadMe 新增一行內(nèi)容 [root@VM-4-4-centos gitcode]# echo "It is shift" >> ReadMe [root@VM-4-4-centos gitcode]# cat ReadMe hello Lotso hello version1 hello version2 hello version3 It is shift # 恢復(fù)到上一次 add 或 commit [root@VM-4-4-centos gitcode]# git checkout -- ReadMe [root@VM-4-4-centos gitcode]# cat ReadMe hello Lotso hello version1 hello version2 hello version3
場(chǎng)景 2:修改已執(zhí)行g(shù)it add到暫存區(qū),未commit
add 后還是保存到了暫存區(qū),怎么撤銷(xiāo)呢?
# 向 ReadMe 新增一行內(nèi)容 [root@VM-4-4-centos gitcode]# echo "It is shit" >> ReadMe [root@VM-4-4-centos gitcode]# cat ReadMe hello Lotso hello version1 hello version2 hello version3 It is shit # add 存入暫存區(qū) [root@VM-4-4-centos gitcode]# git add ReadMe # git status 查看一下 [root@VM-4-4-centos gitcode]# git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: ReadMe #
那我們?cè)撛趺醋瞿??我們?lái)回憶一下之前學(xué)過(guò)的 git reset 回退命令。該命令如果使用 --mixed 參數(shù),可以將暫存區(qū)的內(nèi)容回退到指定的版本內(nèi)容,但工作區(qū)文件保持不變,我們?cè)俳又蒙厦鎴?chǎng)景一的方法解決一下不就好了。
總的來(lái)說(shuō)就是:先將暫存區(qū)修改撤銷(xiāo)到工作區(qū),再丟棄工作區(qū)修改:
# 先將暫存區(qū)修改撤銷(xiāo)到工作區(qū),--mixed 是默認(rèn)參數(shù),可以省略 [root@VM-4-4-centos gitcode]# git reset HEAD ReadMe Unstaged changes after reset: M ReadMe # git status 查看一下 [root@VM-4-4-centos gitcode]# git status # On branch master # Changes not staged for commit: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # modified: ReadMe # no changes added to commit (use "git add" and/or "git commit -a") # 類似于場(chǎng)景一,丟棄工作區(qū)的修改 [root@VM-4-4-centos gitcode]# git checkout -- ReadMe [root@VM-4-4-centos gitcode]# git status # On branch master nothing to commit, working directory clean [root@VM-4-4-centos gitcode]# cat ReadMe hello Lotso hello version1 hello version2 hello version3
成功恢復(fù)了!!!
場(chǎng)景 3:修改已commit到版本庫(kù)(未推送到遠(yuǎn)程)
直接通過(guò) git reset --hard 回退到上一個(gè)版本即可。
注意:若已推送(push)到遠(yuǎn)程倉(cāng)庫(kù),此操作會(huì)導(dǎo)致本地與遠(yuǎn)程版本不一致,需謹(jǐn)慎,這個(gè)遠(yuǎn)程倉(cāng)庫(kù)我們?cè)诤竺鏁?huì)講的。
# 向 ReadMe 中新增一行內(nèi)容 [root@VM-4-4-centos gitcode]# echo "I like coding" >> ReadMe [root@VM-4-4-centos gitcode]# cat ReadMe hello Lotso hello version1 hello version2 hello version3 I like coding # 添加 + 提交 [root@VM-4-4-centos gitcode]# git add ReadMe [root@VM-4-4-centos gitcode]# git commit -m "test quash" [master 1a0a253] test quash 1 file changed, 1 insertion(+) # 回退到上一個(gè)版本 [root@VM-4-4-centos gitcode]# git reset --hard HEAD^ HEAD is now at b592a38 add version3 [root@VM-4-4-centos gitcode]# cat ReadMe hello Lotso hello version1 hello version2 hello version3
二. Git 文件刪除:徹底刪除與誤刪恢復(fù)
在 Git 中,刪除文件也是一種 “修改操作”,需根據(jù)需求選擇 “徹底刪除” 或 “恢復(fù)誤刪文件”:
2.1 誤刪工作區(qū)文件,需恢復(fù)
[root@VM-4-4-centos gitcode]# ls file1 ReadMe [root@VM-4-4-centos gitcode]# rm file1 rm: remove regular empty file ‘file1'? y
直接這樣刪除其實(shí)是沒(méi)用的,反而徒增煩惱,git status 命令會(huì)立刻告訴你那些文件被刪除了;
[root@VM-4-4-centos gitcode]# git status # On branch master # Changes not staged for commit: # (use "git add/rm <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # deleted: file1 # no changes added to commit (use "git add" and/or "git commit -a")
此時(shí),工作區(qū)就和版本庫(kù)不太一樣了,要?jiǎng)h文件,目前除了要?jiǎng)h工作區(qū)的文件以外,還要清除版本庫(kù)的我文件。當(dāng)然,我們這里如果是誤刪,可以直接使用 git checkout -- file 來(lái)進(jìn)行恢復(fù),之前講過(guò)(刪除也是修改)。
[root@VM-4-4-centos gitcode]# ls ReadMe [root@VM-4-4-centos gitcode]# git checkout -- file1 [root@VM-4-4-centos gitcode]# ls file1 ReadMe
2.2 確認(rèn)刪除文件,同步到版本庫(kù)
這里想要恢復(fù)也是可以的哈,上面也講到過(guò)的。
# 從工作區(qū)和暫存區(qū)同時(shí)刪除file1 [root@VM-4-4-centos gitcode]# git rm file1 rm 'file1' [root@VM-4-4-centos gitcode]# git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # deleted: file1 # # 提交刪除操作到版本庫(kù) [root@VM-4-4-centos gitcode]# git commit -m "deleted file1" [master c213450] deleted file1 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 file1 [root@VM-4-4-centos gitcode]# git status # On branch master nothing to commit, working directory clean
到此這篇關(guān)于Git本地操作進(jìn)階之版本回退,撤銷(xiāo)修改與文件刪除全攻略的文章就介紹到這了,更多相關(guān)Git本地操作內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
如何在Linux?系統(tǒng)中使用apt?包管理器安裝?Git?LFS
Git LFS是一個(gè)開(kāi)源擴(kuò)展,用于解決Git在處理大型文件時(shí)的效率和性能問(wèn)題,這篇文章主要介紹了在?Linux系統(tǒng)中使用apt包管理器來(lái)安裝Git LFS的問(wèn)題,需要的朋友可以參考下2023-05-05
Objective-C 動(dòng)態(tài)調(diào)用NSInvocation 的方法
NSInvocation是Objective-C編程中一個(gè)強(qiáng)大的特性,它允許開(kāi)發(fā)者在運(yùn)行時(shí)動(dòng)態(tài)地調(diào)用方法,本文詳細(xì)介紹了如何使用NSInvocation來(lái)獲取方法的選擇器、創(chuàng)建實(shí)例、設(shè)置目標(biāo)對(duì)象和方法參數(shù),并執(zhí)行方法,感興趣的朋友跟隨小編一起看看吧2024-09-09
教你使用Typora?+?阿里云OSS?+?PicGo?搭建私人圖床(最新)
這篇文章主要介紹了教你使用Typora?+?阿里云OSS?+?PicGo?搭建私人圖床,我這里使用的是阿里云對(duì)象存儲(chǔ)OSS,你可以使用騰訊、七牛云對(duì)象存儲(chǔ)等皆可,需要的朋友可以參考下2022-04-04
解決Git?merge時(shí)報(bào)錯(cuò):refusing?to?merge?unrelated?histories問(wèn)題
在使用Git進(jìn)行分支合并時(shí),可能會(huì)遇到"refusing?to?merge?unrelated?histories"錯(cuò)誤,這是因?yàn)閲L試合并的兩個(gè)分支具有不相關(guān)的歷史記錄,解決方法包括使用--allow-unrelated-histories參數(shù)來(lái)合并分支,保留各自歷史,或者直接用一個(gè)分支的內(nèi)容覆蓋另一個(gè)分支2024-10-10

