1、撤销还未 add 的操作
如果还没有执行git add
,此时被认为尚未暂存以备提交的变更,git status
结果如下:
位于分支 dev
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git checkout -- <文件>..." 丢弃工作区的改动)
修改: README.md
删除: package-lock.json
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
此时可直接按照提示使用git checkout --
操作即可:
git checkout -- README.md package-lock.json # 支持单个或多个文件
git checkout -- . # 支持目录,会恢复该目录下所有文件
git checkout -- '*.c' # 也可以支持通配符
原理说明:
2、撤销已经 add 但还未 commit 的操作
此时git status
的结果如下:
要提交的变更:
(使用 "git reset HEAD <文件>..." 以取消暂存)
修改: README.md
删除: package-lock.json
因此根据提示,使用git reset HEAD
操作即可:
git reset HEAD README.md package-lock.json # 支持单个或多个文件
git reset HEAD . # 支持目录,会恢复该目录下所有文件
注意撤销后,只是将撤销 commit 操作,如果想完全恢复,还需要执行上面的git checkout --
的操作。
原理说明:
3、撤销某次 commit 之后所有操作
git checkout
可以从任何一个提交中恢复文件,撤销该提交之后所有的操作:
git checkout 1816af0 README.md package-lock.json # 支持单个或多个文件
其中1816af0
是提交的 ID ,是要被恢复到的,应该是被改坏那次提交之前的那次提交。该操作之后,文件被恢复到那一次提交时的状态,那之后所有的提交所做的改动都被丢弃。
如果想把所有文件都恢复到之前的某一次 commit ,此时有两种方法。如果那次 commit 之后的还未 push ,可以直接reset hard
,此时那次 commit 之后的所有提交都将直接丢弃,当前节点直接指向到指定的 commit 节点:
git reset --hard 1816af0
4、撤销某次 commit 当次的操作
现在我们有一次错误提交,在这之后又有了很多次正确的提交,但我们需要撤销这个错误的 commit ,但保留之后的正确的 commit。
如果从错误提交开始的所有提交都没有被推送到服务器,此时可以使用rebase -i
:
git rebase -i 284d399
然后再弹出的提示中,把错误的提交前面的pick
改成drop
即可:
pick 0052aac wrong commit
pick 940d3d4 commit1
pick cf2eed6 commit2
此时涉及到的所有 commit 都会被重写, id 也会改变。但出错的 commit 在时间线里被删除,就像历史上没有存在过一样,有助于保持干净的时间线。
我们也可以使用git revert
:
git revert 1816af0
其中1816af0
是错误的提交。它在现有时间线后面,再增加一个新的 commit ,撤销指定的 commit。这个方法适合之前的 commit 已经推送到服务器的时候,而且如果远程分支被保护,这也是唯一的方法。
Q. E. D.