撤销 Git 中的更改:Reset、Restore、Revert 详解
理解 git restore、reset 和 revert,以便取消暂存文件、丢弃本地编辑、撤销提交,并避免重写共享历史。
撤销 Git 中的更改:Reset、Restore、Revert 详解
在 Git 中撤销更改是安全的,只要你知道你在修改哪一层:工作目录、暂存区还是提交历史。常用的命令有 git restore、git reset 和 git revert,它们解决不同的问题。
一个大原则很简单:对文件使用 restore,对本地历史更改使用 reset,对撤销其他人可能已经拥有的提交使用 revert。
理解核心概念
请分清这些区域:
- 工作目录:你编辑的文件。
- 暂存区,也称为索引:为下一次提交选中的更改。
- 提交历史:已经记录的提交。
HEAD:你的分支当前指向的提交。
在撤销任何操作之前运行 git status。它会告诉你更改是未暂存、已暂存还是已提交。
git restore:用于丢弃工作目录和暂存区中的更改
当你想要更改工作目录或暂存区中的文件而不移动分支历史时,使用 git restore。
取消暂存文件
如果你错误地暂存了一个文件,使用 --staged 取消暂存:
git restore --staged <file>
要取消暂存所有内容:
git restore --staged .
你的文件编辑仍保留在工作目录中。它们只是从下一次提交中移除。
丢弃工作目录中的更改
要丢弃一个文件中未暂存的编辑:
git restore <file>
这会使工作目录副本与索引匹配。如果文件未暂存,这通常意味着它回到 HEAD。先查看 git diff,因为这会丢弃本地编辑。
要丢弃一个文件的已暂存和未暂存更改,并从 HEAD 恢复:
git restore --source=HEAD --staged --worktree <file>
从特定提交恢复文件
你也可以从较旧的提交中恢复一个文件:
git restore --source=<commit> -- path/to/file
这会更改工作目录中的文件。如果旧版本是你想要的,就提交它。
git reset:重写历史
当你想要移动当前分支指针时,使用 git reset。根据模式的不同,它还可以更改暂存区和工作目录。
理解模式(--soft、--mixed、--hard)
三种常见模式是:
git reset --soft HEAD^
将 HEAD 向后移动一个提交,并保留被撤销提交的更改处于暂存状态。
git reset --mixed HEAD^
将 HEAD 向后移动一个提交,并保留被撤销提交的更改处于未暂存状态。--mixed 是默认模式,所以 git reset HEAD^ 执行相同的操作。
git reset --hard HEAD^
将 HEAD 向后移动一个提交,并从暂存区和工作目录中丢弃相应的更改。这是破坏性的。不要随意运行。
有用的 reset 模式:
git reset --soft HEAD^ # 重做最后一个本地提交,保持更改暂存
git reset HEAD^ # 撤销最后一个本地提交,保持更改未暂存
git reset # 取消所有已暂存的更改
git reset --hard origin/main # 丢弃本地更改并与 origin/main 匹配
重置旧提交
要将分支向后移动两个提交,同时保留工作目录中的更改:
git reset --mixed HEAD~2
只重置本地的提交,或者你的团队同意重写的提交。如果提交已经在共享分支上,优先使用 git revert。
git revert:创建新提交以撤销更改
git revert 创建一个新提交,该提交应用早期提交的逆操作。它不会删除或移动原始提交,因此对于共享分支是安全的。
撤销一个提交:
git revert <commit-hash>
撤销一个范围:
git revert HEAD~3..HEAD
如果出现冲突,解决冲突,暂存文件,然后继续:
git add <fixed-files>
git revert --continue
撤销合并提交需要额外注意,因为 Git 必须知道哪个父提交应被视为主线:
git revert -m 1 <merge-commit>
只有在你理解合并引入了什么时才这样做。对于生产分支,在撤销合并之前请求审查。
选择正确的命令
使用这个快速指南:
- 取消暂存文件:
git restore --staged <file>。 - 丢弃文件中未暂存的编辑:
git restore <file>。 - 撤销最后一个本地提交并保持更改暂存:
git reset --soft HEAD^。 - 撤销最后一个本地提交并保持更改未暂存:
git reset HEAD^。 - 破坏性地丢弃本地更改和提交:
git reset --hard <commit>。 - 安全地撤销已推送的提交:
git revert <commit-hash>。
实用要点
在撤销任何操作之前,运行 git status 并决定你要更改什么。对文件级清理使用 restore,对本地未推送的提交使用 reset,对共享历史使用 revert。当命令包含 --hard 时,暂停并先检查 git diff。