Git 有 4 个区:
- 工作区(Working Area)
- 暂存区(Stage)
- 本地仓库(Local Repository)
- 远程仓库(Remote Repository)
以及 5 种状态:
- 未修改(Origin)
- 已修改(Modified)
- 已暂存(Staged)
- 已提交(Committed)
- 已推送(Pushed)
一套完整的命令流程如下所示:
git add . # 把文件放入暂存区
git commit -m "comment" # 把文件从暂存区提交进本地仓库
git push # 把文件从本地仓库推送进远程仓库
那如果想要撤销修改应该如何操作呢?首先得看一下是撤销哪个区的修改:
已修改,未暂存
只修改了文件,但没有执行 git add .,此时可以用 git diff 用于查看工作区和暂存区之间的差异,撤销命令为:
git checkout .
git reset --hard
git checkout . 和 git add . 是站在同一个地方(修改文件之后)朝两个相反方向的操作,即如果想保存修改,就执行 git add . 让修改进入暂存区,如果想撤销修改,就执行 git checkout . 恢复原来的状态。
已暂存,未提交
已经执行了 git add .,但还没有执行 git commit,此时可以用 git diff --cached 看到暂存区和本地仓库之间的差异,撤销命令为:
git reset
git checkout .
# 或者
git reset --hard
git reset 会把修改退回到 git add . 之前的状态,也就是说文件本身还处于已修改未暂存状态,如果想退回未修改状态,还需要执行 git checkout .。
已提交,未推送
既执行了 git add .,又执行了 git commit,这时候代码已经进入了本地仓库,此时可以用 git diff master origin/master 查看本地仓库和远程仓库之间的差异,撤销命令为:
git reset --hard origin/master
因为本地仓库已经被污染了,只能从远程仓库把代码取回来取代本地仓库。
已推送
既 git add 了,又 git commit 了,并且还 git push 了,这时代码已经进入远程仓库,由于本地仓库和远程仓库是等价的,只需要先恢复本地仓库,再强制 push 到远程仓库就好了:
git reset --hard HEAD^ # 回滚到前一个版本
git push -f
如果通过使用 git reset --hard 意外造成了代码丢失,可以通过 git reflog 查找这次撤销操作来找回丢失的代码。