Git 撤销修改的四种方法

在使用 Git 的过程中,我们难免会遇到撤销修改的场景。

例如,对不小心改坏的代码进行了 git add 甚至 git commit 操作,需要改回来。

或者,对修改结果不满意,要返回以前的某个版本。

难道我们只能删库重建吗?

答案是否定的。谷月老师带你一起学习 Git 撤销修改的四种方法。

1 撤销工作区文件的修改

当你把工作区中的代码改得一团糟,但是还没有 git add,就可以采用以下两种方法之一,把工作区中的文件恢复到上一次 git add 或上一次 git commit 时的样子。

这两种方法的作用是一样的:都是用暂存区(索引、Stage)中的文件覆盖工作区(Working tree)中的同名文件;如果暂存区中的文件已经提交,那么就用 HEAD 中的文件覆盖工作区中的同名文件。

1.1 方法 1

操作命令:

1
git checkout -- <filename>

1.2 方法 2

操作命令(需要 Git 2.23 以上):

1
git restore <filename>

1.3 例题

【例 1】我要撤销对 test.txt 文件的修改,恢复到上一次 git add 或上一次 git commit 时的样子。

1
2
3
git checkout -- test.txt

git restore test.txt

2. 撤销暂存区文件的修改

如果已经 git add ,只要还没有 git commit,那就还能补救。补救的方法,就是撤销暂存区文件的修改,换句话说,就是用版本库(默认是 HEAD)中的同名文件覆盖暂存区中你要撤销修改的文件,但是不会影响工作区。

这个操作也就是 git add 的逆操作。

2.1 方法 1

操作命令:

1
git reset <filename>

完整形式:

1
git reset --mixed HEAD -- <filename>

其中,--mixed 表示用版本库中的文件覆盖暂存区中的同名文件,但是不会影响工作区;HEAD 就表示用 HEAD 中的文件覆盖暂存区中的同名文件。二者都是默认选项。

2.2 方法 2

操作命令(需要 Git 2.23 以上):

1
git restore -S <filename>

完整形式:

1
git restore --source HEAD --staged <filename>

其中,--source HEAD 就表示用 HEAD 中的文件覆盖暂存区中的同名文件;-S 等价于 --staged, 表示用版本库中的文件覆盖暂存区中的同名文件,但是不会影响工作区。二者都是默认选项。

2.3 例题

【例 2】刚才错误地暂存 test.txt,需要撤销这次暂存。

1
2
3
git reset test.txt

git restore -S test.txt

3 简单粗暴,一次性撤销工作区和暂存区所有文件的修改

这个操作是从版本库中提取所有文件,一次性覆盖工作区中所有同名文件,并清空暂存区。

注意:是所有文件!!!

操作命令:git reset --hard

完整形式:git reset --hard HEAD。其中 HEAD 就表示用 HEAD 中的文件覆盖工作区中的同名文件。

4 调取一个文件过去的版本

反复修改了好几个版本,但是都不如开头的版本好。总之,我们需要从过去的提交中,调取一个文件过去的版本。

4.1 方法 1

分两步走,先用 git reset 把这个文件从过去的某一次提交中提取出来,放进暂存区,再用 git chekcout 命令用暂存区中的这个文件覆盖工作区中的同名文件。

操作命令:

1
2
3
4
# 把这个文件从某一次提交中提取出来,放进暂存区
git reset --mixed <commit-id> -- <filename>
# 用暂存区中的文件覆盖工作区中的同名文件
git checkout -- <filename>

4.2 方法 2

git restore 一步到位。

操作命令(需要 Git 2.23 以上):

1
git restore -s <commit-id> -SW <filename>

完整形式(需要 Git 2.23 以上):

1
git restore --source <commit id> --staged --worktree <filename>

其中 -s <commit-id> 等价于 --source <commit-id>,把这个文件从过去的某一次提交中提取出来;-SW 等价于 --staged --worktree 二者同时使用,表示把这个从版本库中提取出来的文件,分别复制到暂存区和工作区,并覆盖工作区中的同名文件。

4.3 要回到最新版本怎么办?

操作命令:git reset --hard HEAD

这样,git 会从 HEAD 中提取所有文件,一次性覆盖工作区中所有同名文件,并清空暂存区。

4.4 例题

【例 3】调取第二次提交时的 test.txt,放进工作区。

图

1
2
3
4
5
# 查找第二次提交的 commid id 是多少
git log --graph --oneline
# 第二次提交的 commit id 是 bf26f98
git reset --mixed bf26f98 -- test.txt
git checkout -- test.txt

1
2
3
4
# 查找第二次提交的 commid id 是多少
git log --graph --oneline
# 第二次提交的 commit id 是 bf26f98
git restore -s bf26f98 -SW test.txt

5 总结

本文讲解了四种撤销修改的方法:撤销工作区文件的修改、撤销暂存区文件的修改、清空工作区和暂存区所有文件的修改,调取一个文件过去的版本。

6 知识扩展

回滚提交,我们可以用 git revert <commit id>。之所以是“回滚”而不是“撤销”,是因为撤销不会留下提交记录,但是回滚会留下一次提交记录。

在不同的提交之间切换,我们可以用 git reset --hard <commit id>。其中 --hard 可以根据情况改成 --soft 或者 --mixed

7 图片版权

题图:https://www.deviantart.com/black-pixel/art/Git-Wallpaper-Clean-357130508

头图:Image by Michael Pointner from Pixabay


求扫码打赏
“我这么可爱,请给我钱 o(*^ω^*)o”

Git 撤销修改的四种方法
https://blog.kukmoon.com/5c35cbca45a2/
作者
Kukmoon谷月
发布于
2024年12月11日
许可协议