git的工作流
工作區:即自己當前分支所修改的代碼,git add xx 之前的!不包括 git add xx 和 git commit xxx 之后的。
暫存區:已經 git add xxx 進去,且未 git commit xxx 的。
本地分支:已經git commit -m xxx 提交到本地分支的。
語法格式
HEAD^:上一次提交
HEAD~n:之前的n次提交
HEAD ComitHash:目標版本號CommitHash
代碼回滾
1、工作區
git checkout a.txt # 丟棄某個文件,或者
git checkout ./ # 丟棄全部
git checkout – . 丟棄全部,也包括:新增的文件會被刪除、刪除的文件會恢復回來、修改的文件會回去。這幾個前提都說的是,回到暫存區之前的樣子。對之前保存在暫存區里的代碼不會有任何影響。對commit提交到本地分支的代碼就更沒影響了。當然,如果你之前壓根都沒有暫存或commit,那就是回到你上次pull下來的樣子了。
2、 緩存區
代碼git add到緩存區,並未commit提交
git reset HEAD .
git reset HEAD a.txt
這個命令僅改變暫存區,並不改變工作區,這意味着在無任何其他操作的情況下,工作區中的實際文件同該命令運行之前無任何變化
3、本地庫
commit到本地分支、但沒有git push到遠程
1、git reset --hard HEAD^ :重置stage區和工作目錄
例如你在上次 commit 之后又對文件做了一些改動:把修改后的ganmes.txt文件add到stage區,修改后的shopping list.txt保留在工作目錄

執行:git reset --hard HEAD^后,
你工作目錄里的新改動和已經add到stage區的新改動也一起全都消失了:

2、reset --soft:保留工作目錄,並把重置 HEAD 所帶來的新的差異放進暫存區
保留工作目錄和暫存區中的內容,並把重置 HEAD 所帶來的新的差異放進暫存區。
例子同上,假設此時當前 commit 的改動內容是新增了 laughters.txt 文件:
如果這時你執行:
git reset --soft HEAD^

這就是--soft 和 --hard 的區別:--hard 會清空工作目錄和暫存區的改動,*而 --soft則會保留工作目錄的內容,並把因為保留工作目錄內容所帶來的新的文件差異放進暫存區。
3、reset 不加參數(mixed):保留工作目錄,並清空暫存區
reset 如果不加參數,那么默認使用 --mixed 參數。它的行為是:保留工作目錄,並且清空暫存區。也就是說,工作目錄的修改、暫存區的內容以及由 reset 所導致的新的文件差異,都會被放進工作目錄。簡而言之,就是「把所有差異都混合(mixed)放在工作目錄中」。
例子:新增了 laughters.txt 文件
這時如果你執行無參數的reset或者帶--mixed參數:
git reset HEAD^
git reset --mixed HEAD^
工作目錄的修改、暫存區的內容以及由 reset 所導致的新的文件差異,都會被放進工作目錄
.assets/2196407-20201111120755845-1712549243.png)
reset三種模式區別
- --hard:重置位置的同時,直接將 working Tree工作目錄、 index 暫存區及 repository 都重置成目標Reset節點的內容,所以效果看起來等同於清空暫存區和工作區。
- --soft:重置位置的同時,保留working Tree工作目錄和index暫存區的內容,只讓repository中的內容和 reset 目標節點保持一致,因此原節點和reset節點之間的【差異變更集】會放入index暫存區中(Staged files)。所以效果看起來就是工作目錄的內容不變,暫存區原有的內容也不變,只是原節點和Reset節點之間的所有差異都會放到暫存區中。
- --mixed(默認):重置位置的同時,只保留Working Tree工作目錄的內容,但會將 Index暫存區 和 Repository 中的內容更改和reset目標節點一致,因此原節點和Reset節點之間的【差異變更集】會放入Working Tree工作目錄中。所以效果看起來就是原節點和Reset節點之間的所有差異都會放到工作目錄中。
4、提交已經push到遠程倉庫
方式一:使用revert
#撤銷前n次提交並生成一次新的提交
git revert -n HEAD~n
#回到某次提交
git revert -n 版本號
然后重新push
注意revert功能是撤銷某次提交而不是撤銷到某次提交,
-n
取消自動提交
tips:
(1)這個命令會生成一個新的提交記錄,新的提交記錄的修改就是把要移除的那次需要移除的提交的修改抵消掉
(2)如果工作區或暫存區還有修改未提交,那么會提示需要先提交或存儲起來;
(3)如果在移除的過程中發生了沖突,可以在解決了沖突后,使用 git add添加修改的沖突文件, git revert --continue
來繼續操作,如果沒有需要提交的,也可以使用 git revert --skip
來繼續下一步,如果后續還有沖突,也同樣如此,直到移除的操作全部完成;當然也可以使用 git revert --abort
來停止移除操作,恢復到執行git revert
原理: git revert是用於“重做”某一個版本,以達到撤銷該版本的修改的目的。比如,我們commit了三個版本(版本一、版本二、 版本三),突然發現版本二不行(如:有bug),想要撤銷版本二,但又不想影響撤銷版本三的提交,就可以用 git revert 命令來反做版本二,生成新的版本四,這個版本四里會保留版本三的東西,但撤銷了版本二的東西。如下圖所示:
適用場景: 如果我們想撤銷之前的某一版本,但是又想保留該目標版本后面的版本,記錄下這整個版本變動流程,就可以用這種方法。
示例
考慮這個例子,我們提交了 6 個版本,其中 3-4 包含了錯誤的代碼需要被回滾掉。 同時希望不影響到后續的 5-6。
* 982d4f6 (HEAD -> master) version 6
* 54cc9dc version 5
* 551c408 version 4, harttle screwed it up again
* 7e345c9 version 3, harttle screwed it up
* f7742cd version 2
* 6c4db3f version 1
這種情況在團隊協作的開發中會很常見:可能是流程或認為原因不小心合入了錯誤的代碼, 也可能是合入一段時間后才發現存在問題。 總之已經存在后續提交,使得直接回滾不太現實。
下面的部分就開始介紹具體操作了,同時我們假設遠程分支是受保護的(不允許 Force Push)。 思路是從產生一個新的 Commit 撤銷之前的錯誤提交。
使用 git revert
git revert --no-commit f7742cd..551c408
git commit -a -m 'This reverts commit 7e345c9 and 551c408'
其中 f7742cd 是 version 2,551c408 是 version 4,這樣被移除的是 version 3 和 version 4。 注意 revert 命令會對每個撤銷的 commit 進行一次提交,--no-commit 后可以最后一起手動提交。
方式二:使用reset
git reset --hard HEAD^
git push 目標分支 本地分支 -f
此時如果用“git push”會報錯,因為我們本地庫HEAD指向的版本比遠程庫的要舊,要強制推送
reset(回滾到)和revert(重做)的區別
- revert是放棄指定提交的修改,但是會生成一次新的提交,需要填寫提交注釋,以前的歷史記錄都在;
- reset是指將HEAD指針指到先前已存在的歷史提交,歷史記錄中不會出現放棄的提交記錄。
場景
情況一:修改的文件已被git commit
,但想再次修改不再產生新的Commit
# 修改最后一次提交
$ git add sample.txt
$ git commit --amend -m"說明"
參考文檔:
https://www.jianshu.com/p/c2ec5f06cf1a
https://blog.csdn.net/yxlshk/article/details/79944535