如何安全撤销 Git 错误:`Revert`、`Reset` 和 `Checkout` 命令详解
自信地处理 Git 错误!本指南介绍了 `git revert`、`git reset` 和 `git checkout`,以便您安全地撤销提交、恢复文件以及管理您的仓库历史记录。了解何时以及如何使用每个命令来纠正错误而不会丢失宝贵的工作,使其成为任何 Git 用户的必备阅读材料。
如何安全地撤销 Git 错误:详解 Revert、Reset 和 Checkout
Git 错误通常感觉比实际更糟糕。你可能提交了错误的文件、暂存了太多内容,或者将错误的更改推送到了共享分支。安全的修复方法取决于一个问题:更改是否已经共享?
本指南解释了何时使用 git revert、git reset 和 git checkout,并提供了可以仔细复制的示例。简单来说:对已共享的提交使用 git revert,对本地清理使用 git reset,仅在切换分支或恢复旧文件状态时使用 git checkout。
首先,检查你要撤销的内容
在运行任何撤销命令之前,先查看当前状态:
git status
git log --oneline --decorate -5
git status 告诉你是否有未暂存、已暂存或未跟踪的工作。git log 显示最近的提交以及分支指向的位置。
如果你有不想丢失的本地工作,请先创建一个快速的安全分支:
git branch backup-before-undo
如果你选择了错误的命令,这个分支可以让你轻松返回。
对已推送的提交使用 git revert
git revert 会创建一个新提交,该提交应用了先前提交的相反更改。它不会删除历史记录,因此对于共享分支(如 main、develop 或任何其他人可能已拉取的分支)来说是最安全的选择。
假设你的历史记录如下所示:
A -- B -- C -- D main
提交 C 引入了一个错误,但 D 是好的且必须保留。找到提交哈希:
git log --oneline
然后仅还原该提交:
git revert abcdef1
Git 会打开编辑器让你输入还原提交的消息。保存后,历史记录如下所示:
A -- B -- C -- D -- E main
提交 E 撤销了 C 的更改。每个人都可以正常拉取这个新提交。
还原合并提交
合并提交需要一个额外的标志,因为 Git 必须知道哪个父提交是主线:
git revert -m 1 <merge-commit-hash>
对于合并到 main 的正常合并,-m 1 通常意味着“保留第一个父提交”,即你合并到的分支。不要在这里猜测。首先运行以下命令并检查父提交:
git show --summary <merge-commit-hash>
如果你不确定要保留哪个父提交,请询问团队成员或在临时分支上测试还原。
对本地提交使用 git reset
git reset 会移动当前分支指针。根据模式的不同,它还可以更改暂存区和工作文件。主要用于尚未推送的提交。
取消暂存文件
如果你暂存了错误的文件,可以在不更改文件内容的情况下取消暂存:
git restore --staged unwanted_file.txt
较旧的 Git 示例通常使用以下等效命令:
git reset HEAD unwanted_file.txt
两者都将文件从暂存区中移除。你的编辑保留在工作目录中。
撤销最后一次提交但保留更改已暂存
当提交消息错误或你想在重新提交前再添加一个文件时,使用 --soft:
git reset --soft HEAD~1
你的分支向后移动一次提交,但该提交的更改仍处于暂存状态。
撤销最后一次提交并保留更改未暂存
当你希望在再次提交之前重新处理文件时,使用默认的混合重置:
git reset HEAD~1
这会将分支向后移动一次提交,并将更改保留在工作目录中。
丢弃本地提交和文件更改
--hard 会重置分支、暂存区和工作目录中的跟踪文件:
git reset --hard HEAD~1
仅在你确定不需要丢弃的更改时使用此选项。它不会删除未跟踪的文件,但会丢弃跟踪文件的编辑而不会再次询问。
谨慎使用 git checkout
在较旧的 Git 工作流中,git checkout 有两个常见任务:切换分支和恢复文件。较新的 Git 版本将这些任务分成了更清晰的命令:git switch 用于分支,git restore 用于文件。
切换分支:
git switch main
旧版等效命令:
git checkout main
丢弃一个跟踪文件中的未提交更改:
git restore my_file.txt
旧版等效命令:
git checkout -- my_file.txt
该文件恢复对于所选文件中未提交的编辑是破坏性的。如果你以后可能需要这些编辑,请先 stash 它们:
git stash push -m "save work before restore"
如果操作过头,使用 git reflog
如果你运行了 git reset --hard 或错误地移动了分支,git reflog 可能仍然显示 HEAD 之前指向的位置:
git reflog
你可能会看到像 HEAD@{2} 这样的早期条目或重置之前的提交哈希。你可以从中创建一个恢复分支:
git branch recovery <commit-hash>
Reflog 是本地克隆的,不是备份系统,但它通常能帮你从最近的错误中恢复。
应该选择哪个命令?
当错误提交已推送或其他人可能基于它工作时,使用 git revert。
当最后一次本地提交需要重做但更改仍然正确时,使用 git reset --soft。
当你希望将最后一次本地提交恢复为未暂存的文件更改时,使用 git reset。
仅当本地跟踪的更改可以删除时,使用 git reset --hard。
当你想丢弃特定文件中的未提交更改时,使用 git restore 或 git checkout -- <file>。
最安全的习惯是检查 git status,在风险较高时创建一个临时备份分支,并避免重写共享历史。如果提交已到达共享远程仓库,git revert 通常是最干净的修复方法。