糟糕,我写错了!Git 花式撤销大法
作为一个版本管理系统,撤销是一个非常重要的功能。特别是在 Vibe Coding 的时候,保不齐会出一些乱子。那么都有 Git 哪些撤销的办法呢?
核心概念速览
在深入场景之前,先理解 Git 的三个主要区域:
- 工作区 (Working Directory): 你在电脑上能看到的文件,可以直接编辑。
- 暂存区 (Staging Area/Index): 使用
git add命令后,文件的快照被添加到的地方,准备下次提交。 - 版本库 (Repository): 使用
git commit命令后,暂存区的文件快照被永久存入.git目录的地方,形成了历史记录。
工作区和暂存区的内容容易被误操作,需要小心。
尚未 commit
这是最常见的情况。如果使用 VSCode 等 GUI,可以直接在 Git 的插件里面点撤销,如果是命令行,则:
-
如果没有
git add# 撤销对单个文件的修改 git checkout -- main.py # 或者使用新版的 git restore git restore main.py # 撤销对所有文件的修改 git restore . # 或者 git checkout -- .以上操作将会把指定文件或者所有文件恢复到最近一次 commit 的状态,此操作不可逆,谨慎使用。
-
修改已经
git add,可以先移出暂存区# 将文件从暂存区撤出,但保留工作区的修改 git reset HEAD main.py # 或者使用新版的 git restore git restore --staged main.py然后,可以根据情况继续按照上面没有
git add的方法继续重置。此操作只是把暂存区的文件放回工作区,不会丢失修改。
已经 commit
-
刚才的提交有问题,想要修改,比如修改文件或者 commit message。这一步也可以用 VSCode 的 git 插件完成。
# 先添加修改的文件。如果只是想修改信息,则忽略这一步。 git add modified.py # 然后再使用 --amend 提交 git commit --amend执行完毕之后,刚才的提交会被重写。旧的提交会被丢弃,以本次提交为准。
Commit ID 会改变,因此如果已经 Push,则需要谨慎使用这一个命令。
-
想要彻底撤销最近的一次或者多次提交。
由于 VSCode 的 git 插件没有提供
git reset的选项,因此只能在命令行中完成。下面三种模式本质上是
HEAD指针的移动,commit 并不会真的消失,git reflog仍然可以看到,也可以恢复。-
温柔模式:
soft仅仅撤销提交的动作,工作区和暂存区里面的文件不会有任何变化。
git reset --soft HEAD~1 -
默认模式:
mixed不加额外参数,默认就是
mixed模式,工作区里面的文件不会变化。执行下面的命令,刚才的提交,连同已经提交在暂存区里面的内容,都会返回到工作区中。
相当于先
--soft,再执行git reset把暂存区的文件重置。git reset HEAD~1 # 相当于 git reset --mixed HEAD~1 -
完全重置:
hard暂存区和工作目录里面的文件全部都会变成目标提交的样子,也就是说,新的修改会完全丢失。
这个选项是最危险的,需要谨慎使用。
git reset --hard HEAD~1
-
如何修改分支指针?
运行下面的命令,即可把分支的头指向指定的 commit。
git branch -f <branch-name> <commit-hash>
这个命令不会影响工作区和暂存区,但是移动的分支不能是当前分支。
如果是当前分支,则需要先 detach,或者先切换到其他分支,此时需要先commit 或者 stash 来保存修改,然后再修改分支指针。
更多阅读
