Git 常用撤销操作

1. 没有 add 撤销

git checkout <file-path>

这样就可以把文件恢复到 git 版本里的样子。

2.add 后撤销

如果修改的文件已经 add 了,可以用下面的方法撤销 add。

git reset HEAD <file-name> # 撤销某个文件
git reset # 撤销所有文件

同样,另一个操作也可以达到一样的效果

git rm --cached <file-name> # 删除文件
git rm -r --cached <dir-name> # 删除目录

3. 撤销 commit 操作

我现在做了一些修改,然后提交了。

如果想撤销这个 commit,但是自己的修改不变,可以使用下面的方法。

git reset HEAD~1

如果想练修改也撤销掉,就使用

git reset --hard HEAD~1

4. 已经被跟踪的文件改为不跟踪

有的文件在加入版本库之后又需要放入到 .gitignore 文件里不再被追踪。可以这样

git rm <file-path> # git rm -r <dir-path>
git add <file-path>
git commit -m'xxx' 

# 然后把这个文件加入到 .gitignore 文件里就可以被正常排出了。

5.merge 后要撤销

merge 操作如果不是 fast-forwarded 模式的都会有一次提交,查看日志就像这样:

commit 2f9e61e4520c03c9d4f6618411c6f283e4e214a8 (HEAD -> master)
Merge: 6dba022 6b04fc2
Author: Laily <i@laily.net>
Date:  Mon Sep 18 22:42:38 2017 +0800

    Merge branch 'dev'

commit 字段是这次合并生成的 commit 的 id,这个 commit 又称为 merge commit。Merge 这个字段后有两个值,分别是 merge 的两个分支最后的 commit id。我这次合并是在 master 分支上合并了 dev 分支,所以这个 6dba022 是 master 分支在合并前的最后一次 commit id,6b04fc2 则是 dev。

如果这个时候我想要撤销这个合并操作,则可以用下面的命令

git revert 2f9e61e4520c03c9d4f6618411c6f283e4e214a8 -m 1

这样会增加一次提交,revert 掉了这个合并。

-m 1 表示保留 merge 字段中第一个 commit id 的信息,也就是撤销后恢复到 master 分支原本的状态,如果是 -m 2 就是恢复到 dev 分支的状态。

这个方法有两个问题

  • 如果合并的时候是 fast-forwarded 模式则不会生成 merge commit。所以以防需要回滚,可以在合并的时候使用 git merge --no-ff dev 这样强制生成一个 merge commit。
  • 使用了 revert 回滚之后如果又需要再次合并 dev 分支,则需要 revert 掉前面的 revert 提交, 然后再合并。