Git回滾代碼之reset 和revert

上篇文章講過了Git合并分支,這里不多做講述,在開發(fā)中,有可能遇到的情況是可能有個bug在上個節(jié)點已經(jīng)提交過了,這個版本有復(fù)現(xiàn),現(xiàn)在需要再次測試上個節(jié)點的代碼,怎么辦?

那么我們今天研究一下git resetgit revert的區(qū)別和聯(lián)系。
先看下git reset [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>]
git reset [<mode>][<commit>]
目的是重置當前分支的head指向到commit,并根據(jù)model更新索引(將其重置為<commit>),如果省略model,則默認model--mixed。model必須是下邊的列表:

--soft

不用修改索引文件和工作樹(和所有模式一樣,將head指向commit),這和git status一樣,將保存所有要提交的更改。

--mixed

重置索引,但不重置工作樹(即保留更改的文件,但不標記為提交),并報告未更新的內(nèi)容。這是默認操作。(需要重新添加git add)

如果指定了-n,則刪除的路徑將標記為有意添加

--hard

重置索引樹和工作樹。自<commit>之后,對工作樹中跟蹤文件的任何更改都將被丟棄。

--merge

重置索引并更新工作樹中<commit>和head之間不同的文件,但保留索引和工作樹之間不同的文件(即具有未添加的更改)。如果在<commit>和索引之間不同的文件有未分頁的更改,重置將中止。

換句話說,--merge執(zhí)行類似于git read tree-u-m<commit>的操作,但會轉(zhuǎn)發(fā)未合并的索引項。

--keep

重置索引項并更新工作樹中<commit>和head之間不同的文件。如果<commit>和head之間不同的文件發(fā)生了本地更改,重置將中止。

If you want to undo a commit other than the latest on a branch,is your friend.
如果你不想取消當前分支的最近的commit,請看一下git revert 。這下邊會講。

我們造一個demo如下:


demo

現(xiàn)在我們的HEAD指向節(jié)點d248cd,但是我們想看節(jié)點的file_2的代碼,
我們執(zhí)行命令

git reset --soft head^1

Yong:test_git_revert Yong$ git log --graph
* commit b53ccde9dce1691b555dd5e42c8eb346f736ef81 (HEAD -> master)
| Author: fanguangyong <fanguangyong@xqafu.com>
| Date:   Fri May 10 14:29:07 2019 +0800
|
|     add file_2
|
* commit f5f2498c24c2771f906c2a1ac02b540f092fdcbb
| Author: fanguangyong <fanguangyong@xqafu.com>
| Date:   Fri May 10 14:28:55 2019 +0800
|
|     add file_1
|
* commit e002e347a24ad3079b283156887a7e7d67f881cc
  Author: fanguangyong <fanguangyong@xqafu.com>
  Date:   Fri May 10 14:28:05 2019 +0800

      Initial Commit

然后add file_3不見了,

On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   test_git_revert/ViewController.m

可以看出來 代碼回退過來了,剛才提交的記錄也沒了,只是將head指針前移動了一個,但是修改的test_git_revert/ViewController.m文件是更改了,想要執(zhí)行代碼,還是所有的代碼,緊緊是記錄回退了,代碼卻是所有的代碼(代碼未動),只是工作區(qū)的 跟蹤狀態(tài)不一樣。

記錄

如何測試完了在次更新到最新的節(jié)點呢?

Yong:test_git_revert Yong$ git commit -am 'add file_3_repeat'
[master 200cb3f] add file_3_repeat
 1 file changed, 1 deletion(-)
Yong:test_git_revert Yong$ git log --graph
* commit 200cb3fddf04c03cb1661bf7dc9e7f84525c28b3 (HEAD -> master)
| Author: fanguangyong <fanguangyong@xqafu.com>
| Date:   Fri May 10 17:01:15 2019 +0800
|
|     add file_3_repeat
|
* commit b53ccde9dce1691b555dd5e42c8eb346f736ef81
| Author: fanguangyong <fanguangyong@xqafu.com>
| Date:   Fri May 10 14:29:07 2019 +0800
|
|     add file_2
|
* commit f5f2498c24c2771f906c2a1ac02b540f092fdcbb
| Author: fanguangyong <fanguangyong@xqafu.com>
| Date:   Fri May 10 14:28:55 2019 +0800
|
|     add file_1
|
* commit e002e347a24ad3079b283156887a7e7d67f881cc
  Author: fanguangyong <fanguangyong@xqafu.com>
  Date:   Fri May 10 14:28:05 2019 +0800

      Initial Commit

剛才add file_3已經(jīng)消失了,因為又提交了一次,message變成了add file_3_repeat,新增了一條提交記錄。

那么我們修改一下文件,當前status是:

status

然后執(zhí)行回滾

git reset --soft head^1

結(jié)果是:

--soft

則沒有提交緩存去的文件沒有丟失,回滾的代碼的狀態(tài)是追蹤,但是沒添加到緩存區(qū)。
測試完成當前版本的時候,則再次git add
git add

--mixed
Yong:test_git_revert Yong$ git reset --mixed head^1
Unstaged changes after reset:
M   test_git_revert/ViewController.m

Yong:test_git_revert Yong$ git log --graph
* commit b53ccde9dce1691b555dd5e42c8eb346f736ef81 (HEAD -> master)
| Author: fanguangyong <fanguangyong@xqafu.com>
| Date:   Fri May 10 14:29:07 2019 +0800
|
|     add file_2
|
* commit f5f2498c24c2771f906c2a1ac02b540f092fdcbb
| Author: fanguangyong <fanguangyong@xqafu.com>
| Date:   Fri May 10 14:28:55 2019 +0800
|
|     add file_1
|

代碼混滾了,直接輸出了最后的一次更改。提交的記錄也丟失。
修改好代碼 執(zhí)行 git add

git add

--hard
hard

執(zhí)行之后查看本地git緩存區(qū)的數(shù)據(jù)有變化嗎?


數(shù)據(jù)

--hard丟失節(jié)點3的數(shù)據(jù)。


如何恢復(fù)--hard丟失的節(jié)點數(shù)據(jù)

再測試一下本地有未追蹤的文件的時候:

未追蹤file

然后回滾代碼:
回滾代碼

文件丟失了怎么找回呢?那么我們測試一下git reflog看看能不能找回?
能不能找回

現(xiàn)在我們的head指向2b8edf8,那么我們讓head指向到e55c3e4

$ git reset --hard head@{1}
HEAD is now at e55c3e4 add file3
未提交的丟失

我們執(zhí)行查找lost的命令:

git fsck --lost-found


Checking object directories: 100% (256/256), done.
dangling commit e55c3e450d0a743b6a64db248065b3fdece153d1
dangling blob 6c3bfcdf65a27027ca3168bf2981487fa4ad5dfa

e55c3e450d0a743b6a64db248065b3fdece153d1是我們最后提交的代碼節(jié)點,
6c3bfcdf65a27027ca3168bf2981487fa4ad5dfa是我們最后add之后形成的commit
然后執(zhí)行git show 6c3bfcdf65a27027ca3168bf2981487fa4ad5dfa

git show

如果該條記錄數(shù) 是dangling commit id類型直接使用git merge commit_id即可實現(xiàn)數(shù)據(jù)恢復(fù),如果是dangling blob id類型則需要使用git show 6c3bfcd> somefileName將其轉(zhuǎn)儲到文件或者使用使用腳本下載本數(shù)據(jù)寫入到相關(guān)的文件
最后修改的文件成功找回。

那么不會回退節(jié)點怎么處理呢?
git給我們提供了git revert,會形成一個新的節(jié)點。

名稱
git-revert- 恢復(fù)一些現(xiàn)有的提交

描述
給定一個或多個現(xiàn)有提交,還原相關(guān)修補程序引入的更改,并記錄一些記錄它們的新提交。這需要您的工作樹是干凈的(沒有HEAD提交的修改)。

注意:git revert用于記錄一些新的提交以反轉(zhuǎn)某些早期提交的效果(通常只有一個錯誤的提交)。如果你想丟棄工作目錄中所有未提交的更改,你應(yīng)該看到git-reset [1],特別是--hard選項。如果你想在另一個提交中提取特定文件,你應(yīng)該看到git-checkout [1],特別是git checkout <commit> -- <filename>語法。請注意這些替代方案,因為它們都會丟棄工作目錄中未提交的更改。

--continue
使用.git / sequencer中的信息繼續(xù)正在進行的操作 。可以在解決失敗的挑選或恢復(fù)中的沖突后繼續(xù)使用。

-- quit
忘記當前正在進行的操作。在櫻桃挑選或恢復(fù)失敗后,可用于清除順序器狀態(tài)。

--abort
取消操作并返回到預(yù)序列狀態(tài)。

例子
git revert HEAD~3
還原HEAD中第四個最后一次提交所指定的更改,并使用還原的更改創(chuàng)建一個新提交。

git revert -n master~5..master~2

將提交所做的更改從master(包含)中的第五次提交恢復(fù)為master(包含)中的第三次提交,但不要使用還原的更改創(chuàng)建任何提交?;謴?fù)僅修改工作樹和索引。

恢復(fù)一個提交記錄并生成一個新的記錄:


新的記錄

恢復(fù)并生成一個新的記錄

生成了這個,又不想要了這個節(jié)點怎么辦?
執(zhí)行git reset --hard head^1即可

hard

Q & A:

1.想恢復(fù)到某個版本并且測試代碼怎么辦?

使用git reset --hard [commit_id]回滾,測試完之后,使用git reflog查看記錄,并再次使用git reset --hard [commit_id]回滾到指定代碼版本。

2.想恢復(fù)到某個版本并且測試代碼,又測試出來一些bug該怎么辦?

使用git reset --hard [commit_id]回滾之后修改代碼,修改完成之后可以進行 git push -f進行強制推送到遠程,前提是同學沒有進行push,否則會覆蓋掉其他同學的代碼導致其他業(yè)務(wù)線出問題。

--hard恢復(fù)容易丟文件,切不容易查找,慎用?;貪L代碼并生成新的提交記錄可使用git revert [commit_id],用完之后再使用--hard丟掉即可。使用reset的時候最好有為緩存的文件及時addcommit,這也是個好習慣。

參考資料:
官方資料
falstaff

最后編輯于
?著作權(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)容