使用checkout,reset,revert進(jìn)行代碼回滾

git reset和git revert都可以用于撤銷已存在的commit,其中g(shù)it reset可以細(xì)化到針對單個文件進(jìn)行操作。

????首先, 一個Git倉庫主要有三個重要的組成:工作目錄,緩存區(qū)和提交歷史,如圖所示:

Main components of a git repository

1. git reset

git reset通常用來撤銷對緩存區(qū)和工作目錄的修改。用法如下:

(1)git reset <file>

????????從緩存區(qū)移除特定的文件,但不改變工作目錄。

(2)git reset

????????重設(shè)緩存區(qū),匹配最近的一次提交,工作目錄不變。

(3)git reset --hard

????????重設(shè)緩存區(qū)和工作目錄,匹配最近的一次提交。除了取消緩存之外,--hard標(biāo)記還會清除工作目錄中所有未提交的更改,因此使用前確定你想扔掉你所有的本地開發(fā)。

(4)git reset <commit>

????????將當(dāng)前分支的末端移動到commit,將緩存區(qū)重設(shè)到這個commit,但不改變工作目錄。

(5)git reset --hard <commit>

????????將當(dāng)前分支的末端移動到commit,并將緩存區(qū)和工作目錄都重設(shè)到這個commit。

git reset命令會將HEAD指向你指定的commit,也就是說,可以直接通過git reset命令來移除你指定的commit之后的所有commit。例如,下面這兩條命令讓hotfix分支向后回退了兩個commit:

git checkout hotfix

git reset HEAD~2

before git reset


after git reset

注意,hotfix分支現(xiàn)在最后的兩個commit變成了懸掛提交,這意味著下次git進(jìn)行垃圾回收的時候,這兩個commit就會被刪除。因此,如果你希望改變此git倉庫的提交歷史,你可以使用git reset命令。

除了在當(dāng)前分支上操作,你還可以傳入以下參數(shù)來更新緩存區(qū)和工作區(qū):

--soft 緩存區(qū)和工作區(qū)都不會改變

--mixed 默認(rèn)選項。緩存區(qū)和你指定的commit同步,工作區(qū)不發(fā)生改變。

--hard 緩存區(qū)和工作區(qū)都同步到你指定的commit

這些參數(shù)往往針對HEAD來使用。例如你add了某個你不想add的文件,這時可以運行g(shù)it --mixed reset HEAD,此時暫存區(qū)被清空,而你的工作空間并沒有改變。

或者你希望將最近的兩個commit合并成為一個,此時你可以運行g(shù)it --mixed reset HEAD~2,這樣你的commit記錄被改變,緩存區(qū)被清空,但工作空間沒有改變,因此你可以重新add,再重新commit,這樣兩個commit記錄就變成了一個。

另一方面,你希望完全放棄你沒有提交的改動,你可以運行g(shù)it reset --hard HEAD,這樣你的緩存區(qū)和工作空間就被強(qiáng)行更新了。

針對已經(jīng)提交到遠(yuǎn)程的commit,你希望reset到HEAD~1,此時運行:

(1)git reset HEAD~1 此時查看status,發(fā)現(xiàn)有待stage的文件,因為工作空間的文件與HEAD~1的文件不同,因此運行g(shù)it checkout future2.txt即可。(或者最開始就運行:git reset --hard HEAD~1)

(2)然后執(zhí)行強(qiáng)制推送:git push -f

git reset可以針對某個文件,此時reset命令會將你指定的文件加入到緩存區(qū)中(因此文件從HEAD狀態(tài)變成了你指定的某個commit的狀態(tài))。

git reset
git status

可以看到,暫存區(qū)產(chǎn)生了一個變更,這是因為文件從HEAD的內(nèi)容變成了HEAD~2的內(nèi)容(邏輯上),實際上,工作區(qū)域不會發(fā)生改變。而產(chǎn)生Changes not staged for commit的原因是此時工作區(qū)的文件和HEAD~2的文件不相同。

git commit

將暫存區(qū)的內(nèi)容commit并push之后,此時future2.txt文件內(nèi)容就回退為了兩個commit之前的版本,并且commit log都沒有更改。此時查看status:

git status

發(fā)現(xiàn)future2.txt依舊待stage,這是因為git reset命令工作區(qū)不會發(fā)生改變,因此工作區(qū)的文件內(nèi)容與HEAD下的文件內(nèi)容不一致,此時運行:

git checkout future2.txt

來撤銷所有的更改。再次查看status:

git status

并且此時future2的文件內(nèi)容已經(jīng)處于最新狀態(tài)。

git reset總結(jié):(1)git reset在提交級別上,可以撤銷已有的commit,并且清除git log,適用于消除還未提交到遠(yuǎn)程的commit,或者是自己私有的分支,或者并不在意篡改commit log的情況。

(2)git reset針對單個文件時,工作區(qū)不會被改變,暫存區(qū)一定改變。并且不會清除git log,往往最后需要通過git checkout <file>來同步工作區(qū)。 --soft、--mixed?和?--hard?對文件層面的?git reset?毫無作用,因為緩存區(qū)中的文件一定會變化,而工作目錄中的文件一定不變。


2. git revert

git revert命令可以通過指定commit id來對某個commit進(jìn)行撤銷,此命令會生成一個新的commit來執(zhí)行撤銷動作,不會修改過去已有的commit,這避免了Git丟失項目歷史,這一點對你的版本歷史和協(xié)作的可靠性來說是很重要的。git revert用法如下:

(1)git revert <commit>

????????生成了一個新的提交,此提交用于撤銷<commit>引入的修改。

例如,下面的命令會撤銷HEAD前面的第二個commit:

git checkout hotfix

git revert HEAD~2

before revert
after revert

相比?git reset,它不會改變現(xiàn)在的提交歷史。因此,git revert?可以用在公共分支上,git reset?應(yīng)該用在私有分支上。你也可以把?git revert?當(dāng)作撤銷已經(jīng)提交的更改,而?git reset HEAD?用來撤銷沒有提交的更改。


3. git checkout

git checkout這個命令有三個作用:檢出文件,檢出提交和檢出分支。

(1)git checkout master

????????回到master分支。

(2)git checkout <commit> <file>

????????查看文件之前的版本。此時工作目錄中下的<file>被替換為<commit>中的<file>,并將它加入緩存區(qū)。

(3)git checkout <commit>

????????更新工作目錄中的所有文件,使得和某個特定提交下的文件一致。此操作會使你處于HEAD分離的狀態(tài),因此是只讀操作。

git checkout <commit>
git checkout <commit> <file>

git checkout命令除了用于常見的分支切換以外,還可以用于代碼更改的撤銷。例如:

當(dāng) future2.txt 存在還沒有add的changes時,運行g(shù)it checkout future2.txt 可以撤銷future2.txt的更改

git checkout? HEAD~2 future2.txt 可以將當(dāng)前的future2.txt恢復(fù)為HEAD~2的版本,此時工作區(qū)和暫存區(qū)都會改變。

總結(jié):如果文件A修改了,你希望撤銷這個修改,那么可以使用以下方案:

(1)修改還未加入暫存區(qū)(還沒有add),直接運行:

? ? ? ? ?git checkout A

(2)修改已經(jīng)加入了暫存區(qū),但還沒有commit:

? ? ? ? ?git reset HEAD A(修改暫存區(qū))

? ? ? ? ?git checkout A(修改工作區(qū))

(3)修改已經(jīng)commit

? ? ? ? ?git reset HEAD~1(reset到前一個commit)

? ? ? ? ?git checkout A

參考:github.com/geeeeeeeeek/git-recipes/wiki/5.2-%E4%BB%A3%E7%A0%81%E5%9B%9E%E6%BB%9A%EF%BC%9AReset%E3%80%81Checkout%E3%80%81Revert-%E7%9A%84%E9%80%89%E6%8B%A9

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容