一文看懂各種場景的git撤銷回滾操作


在這裏插入圖片描述

前言

當我們對一個地方git init之後會生成.git文件,此文件記錄當前倉庫版本迭代信息,表示當前文件夾下就是一個 git 倉庫,當前倉庫的改動會被 git 所識別和記錄

改動未 add:當我們修改了一個文件還未 add 的時候,我們git status發現改文件是紅色的,表示此文件被改動還沒有 add,當前修改項目的區域我們稱之爲工作區,工作區這個概念很重要,就是倉庫中我們直接修改代碼的地方,git 會顯示需要被 added

add 未 commit:當我們成功 add 之後,再用git status查看,會發現文件變成了綠色,表示已經成功 add 了,但是未 commit,這個綠色的文件在哪呢?在 git 的 stage 暫存區中,這個 stage 暫存區表示即將 commit 的一個緩衝區域,可以 add 不同文件到 stage 暫存區,以後可以一次 commit 來更迭版本

已 commit:當我們成功 commit 文件之後,git status沒有文件顯示(IDE 中表現爲文件白色),表示 commit 成功,commit 就表示倉庫整個版本的更新迭代,就是修改了某一個文件的一個句號,最後 commit 提交成功,都會迭代整個版本,版本迭代在 git 數據結構中表現爲版本庫的指針往後移動一位,以後要講解的回退版本操作就是通過指針移動到之前版本來理解

場景一:工作區改動未 add 還原工作區修改

僅僅是在工作區把代碼改動了一下,但是還沒有來得及 add 這個文件,我們想還原最開始的樣子該怎麼辦呢

git checkout -- README.md

場景二:已 add 未 commit 還原工作區成 stage 但 stage 不變

這個文件我改動了然後 add 了,但是還沒有 commit,之後我又改動了這個文件,可是這時候我想要將其還原成 stage 暫存區中的內容

git checkout -- README.md

場景三:已 add 未 commit 工作區不變撤銷 stage(即撤銷 add)

這個文件我改動了,然後 add 了,未 commit,這個時候又改動了這個文件,但是此時我想將其 add 操作撤銷,也就是刪掉 stage 中的內容

如果撤銷某個文件的 add:

# 只撤銷該文件的 add
git reset HEAD README.md

如果撤銷 stage 暫存區所有的 add

# 撤銷 stage 暫存區所有的 add
git reset HEAD

場景四:已 add 未 commit 還原工作區成最近一次 commit 的版本

這個相當於場景三和場景一的結合

# 場景三
git reset HEAD README.md
# 場景一
git checkout -- README.md

場景五:已 add 已 commit 將整個版本回退到上一次 commit 的版本且工作區保留最新代碼

由於 commit 是整體項目倉庫的版本迭代,即使是你只提交了一個文件,所以回退一般針對於整體而言,而非單個文件

項目中已經 add 和 commit 了,版本已經更新了,這時候我又寫了一部分代碼在工作區,突然我發現這個版本有問題想要將當前版本還原成上一次 commit 的版本,但同時保留當前工作區的所有新代碼,但暫存區會被清空

reset 不帶有模式默認就是 --mixed,表示保留工作區

git reset HEAD^

或者我們可以這樣寫git reset --mixed HEAD^也是一樣的效果

場景六:已 add 已 commit 將某個文件回退到上一次 commit 的版本且工作區保留最新代碼

由於 commit 是整體倉庫的版本迭代,即使是你只提交了一個文件,所以回退一般針對於整體而言,所以說對於單個文件的版本回退是不成功的,但是 git 有其他辦法來實現這個功能

假如我 commit 了多個文件作爲一個版本的話,我現在只想回退其中一個文件的版本該怎麼辦呢?實際上我們回退它並不會真正的回退整個倉庫的版本,當我們 reset 回退之後,我們可以git log查看發現版本依舊是當前版本,只不過它會將該文件上一個版本的內容存放在 stage 暫存區內而已

# 回退某個文件版本(其實本質上是無法回退一個文件的版本,因爲版本是針對於整個倉庫而言。該文件當前依舊是當前版本,該操作只不過是把該文件上一個版本的內容存進了現在的 stage 暫存區內罷了,同時工作區的代碼保持不動)
git reset HEAD^ README.md
# 提交暫存區的代碼,讓文件變成上一個版本的模樣,最終在結果上表現爲該文件版本回退了,但是我們查看該文件的 log 信息,發現它的版本實際上是不減反增的
git commit -m "commit file"

這兩行執行下來最終結果就表現爲這個文件還原成了上一個版本的模樣,實際上 log 並沒有顯示版本回退,反而顯示了新增了一個版本。工作區的代碼保持最新

我們實際在執行的時候會發現我們無法執行git reset --hard HEAD^ README.md這個命令,顯示 git 錯誤信息無法執行帶有 path 的此命令,再一次說明回退只針對於整個項目倉庫的版本而言,對於單個文件本質上無法回退版本!

場景七:已 add 已 commit 將整個版本回退成上一次 commit 的版本且工作區也被還原

整個場景可以與前面的前面的場景進行比較,我們發現都是要求還原成上一個版本,但是這個要求工作區的修改全部不保存在工作區中,也就是工作區也還原成上一個版本,這也是--mixed(默認可以不加)與--hard的區別所在,mixed 表示工作區的一切變動得到保留,hard 表示回退的很徹底,工作區和暫存區都被回退了,我們建議使用 mixed 默認方式,這樣更保險!

git reset --hard HEAD^

場景八:已 add 已 commit 將整個版本回退到某次 commit 的版本且工作區保留最新代碼

假如我們 add commit 二連操作完了,之後我又在工作區改了新代碼,這時候我發現這個項目錯了好幾個版本我要將其還原成某次版本,同時需要保證我工作區代碼是最新的

git reset [commit 版本號]

全部總結

看到上面這麼多種場景是不是覺得好麻煩,而且很難去記憶?實際上當我們理解了這些命令之後,就很容易記住了!下面我講解一下理解的方式

  • 當我們想要把工作區的內容還原成最近一版工作區我們可以使用 checkout 命令

    git checkout -- [文件路徑]
    

    (注:一旦這個文件被 add 就表示工作區已經更新了一次,還原工作區只能還原成最新的那一版)

  • 當我們想要對整個倉庫進行版本回退我們可以使用 reset 命令

    git reset [commit 版本號]
    

    (注:強烈建議不用加 --hard,若還原成上一個版本,版本號用 HEAD^ 即可)

  • 當我們想要對倉庫某一個文件進行版本回退我們可以用 reset 操作單獨文件,來將該文件的某次版本保存進當前 stage 暫存區中

    git reset [commit 版本號] [文件名]
    git commit -m "該文件變成以前的版本"
    

    (注:本質上並不會回退,該文件依舊是當前版本,只不過某次版本存放在了 stage 暫存區中,我們下一步再 commit 即可讓該文件變成以前的版本)

  • 當我們想要對倉庫某個文件 add 提交進行撤銷,我們也可以用 reset [當前版本號] 的操作

    git reset HEAD [文件名]
    

    (注:不得不注意的是git reset [版本號]操作單獨文件是比較特殊的,因爲原則上單個文件不存在版本回退操作,但限於需求,若是想將該文件回退到以往的版本,此操作的結果是工作區保持不變,當前版本不變,當前 stage 暫存區變成目標版本;若版本號爲當前版本 HEAD,此操作的結果是工作區保持不變,當前版本不變,當前 stage 暫存區清空,其實本質就是體現在 stage 區域是之前的版本還是被清空罷了)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章