跳至主要内容

Git 撤销上一次提交:新手分步指南

本指南教您如何使用正确的命令和工具安全地撤销您在 Git 中的上一次提交,无论是单人开发还是团队协作。
Srujana Maddula
Srujana Maddula

创建您的免费账户

实践并学习路径你的进步。

使用 Google 继续继续即表示您接受我们的 使用条款,我们的 隐私政策 ,并且您的数据存储在美国。

如果您参与过团队编程项目,就会知道一旦尝试撤销更改,事情可能会很快失控。一步走错,轻则抹掉自己的工作,重则破坏队友刚推送的内容。

这就是为什么了解 Git 提供的“撤销”机制以及各自适用场景如此重要。有些命令适合团队环境,而另一些更适合 本地 清理,在这种情况下您可以放心地重写历史。

本指南将带您逐步了解。您将学到撤销提交的不同方法、其工作原理,以及在不同情境下应当选择哪一种。

理解 Git 提交历史 

有没有按过“Ctrl+S”保存文档版本,之后再回到那个版本?Git 的一次提交做的正是类似的事,但作用于整个代码库。

Git 中的提交是什么?

一次 git commit 是您项目的某一时刻快照。它冻结当前所有文件的状态,并为该版本分配唯一 ID,就像给代码拍了一张带时间戳的照片。若之后出现问题,您随时可以回到那个时间点。

它如何工作?当您修改仓库中的文件时,更改并不会立即保存。它们先仅存在于本地的工作目录中。要保存这些更改,您需要先暂存(stage),再提交到仓库。提交历史就是对该仓库执行的所有提交的日志。 

本地提交 vs 远程提交

本地提交保留在您的机器上,直到您决定共享之前同事或协作者都看不到。这意味着您对此有更多掌控:您可以重写历史、压缩、删除或重置,而不影响他人。

另一方面,远程提交对所有在该仓库上工作的人可见。这意味着您不应重写或删除这些提交。如果这么做,而队友正在使用同一远程分支,就会给他们造成破坏。因此在重写共享历史之前,您应格外谨慎并明确自己在做什么。 

在本地撤销上一次 Git 提交

在 Git 中,HEAD 指向项目历史中的最新一次提交。使用 git reset 命令时,您就是在让 Git 将该指针移到另一个提交上。 

下面我们拆解如何使用 git reset 在不同场景中撤销上一次提交。

使用 git reset --soft HEAD~1

它会将 HEAD 回退一个提交,但保留更改在暂存区。您的文件不会被动到,所有提交过的内容仍然排队等待在暂存区。适用于只想撤销提交本身,但保留所有更改且保持已暂存的情况。

使用 git reset --mixed HEAD~1

这一步走得更远。它同样将 HEAD 回退一个提交,但会清空暂存区。您的文件仍在工作目录中,但没有任何内容处于已暂存状态。这是 git reset 的默认模式。

使用 git reset --head HEAD~1

它会回退 HEAD、清空暂存区,并清除工作目录中的更改。就像上一次提交(及其所有更改)从未存在过。

谨慎使用——一旦这些更改被抹掉,就很难找回。因此,只有当您完全确定不需要上一次提交的任何内容时再运行它。

示例 1:在本地撤销上一次提交(安全返工)

假设您刚刚完成一次提交,却发现忘了更新 README 文件。

情境:

您已提交了对 main.py 的更改,但忘记更新 README.md。您想修订上一次提交而不影响他人,且尚未推送任何内容。

解决方案:

使用 git reset --soft HEAD~1 撤销提交并保留更改在暂存区:

git reset --soft HEAD~1

现在,更新 README 文件,将其加入暂存并重新提交所有内容:

git add README.md
git commit -m "Update main.py and README.md"

✅ 原理:由于该提交尚未推送,您可以重写本地历史而不会影响任何人。

撤销已推送的 Git 提交

您已经推送了一次提交……然后开始后悔。谁都会遇到这种情况。但如何在不破坏团队成员工作的情况下撤销它呢? 

使用 git push --force 重写历史

通常,只有当您的本地分支刚刚拉取并与远程分支保持最新时,Git 才允许您推送。但您可以通过像 push --force 这样的“超能力”命令绕过这一规则。它会用本地分支的内容覆盖远程的整个历史。

这就是为什么 --force 功能强大却危险。在团队环境中,如果您尚未将同事的提交拉取到本地分支,它可能会删除他们的提交。只有在完全清楚后果时才使用它——理想情况下,只在您独自维护该仓库时使用。

除了 push --force,还有 pull --force,同样是需要谨慎使用的强力命令。了解更多内容请见 这里。

使用 git revert 的更安全替代方案

如果您想撤销提交但不删除历史,git revert 是最佳选择。它不会移除提交;而是创建一个新的提交来抵消这些更改。

比如,您提交了一个名为 streamlit_app.py 的文件,现在想去掉它。git revert 会生成一个新的提交,仅删除这个文件,同时保持其余历史不变。

默认情况下,git revert 作用于最近的一次提交。不过,您也可以通过指定提交 ID 来回退更早的提交。

示例 2:在共享分支上安全撤销已推送的提交

假设您推送了一个错误的配置更改,需要在不删除历史的情况下将其回退。

情境:

您推送了一次向 config.yaml 添加错误行的提交。团队已经在同一远程分支(main)上工作,因此您不能使用 reset 或强制推送。

解决方案:

使用 git revert 安全地撤销该提交:

git revert <commit-hash>

这会打开一个文本编辑器让您确认回退信息。保存并关闭编辑器后,将创建一个新的提交来撤销先前的提交。

如果要回退的是最后一次提交:

git revert HEAD

然后推送更改:

git push origin main

✅ 原理:git revert 不会重写历史——它会新增一个提交。因此对共享分支和团队协作流程来说是安全的。

可视化与确认更改

有时,您只是想看看目前发生了什么——有点像回滚到之前的版本,找到想要撤销的那次提交。Git 提供了相应工具来实现这一点。

使用 git log 检查提交历史 

在终端中运行 git log,您会看到当前分支上的所有提交列表。您可以借此定位需要撤销或修改的特定提交。 

例如:git log 的输出可能如下:

  • e3a1b7f 修复 README 中的拼写错误  
  • 4f2c9a1 添加登录校验  
  • 9d5b3e8 初始化提交  

每一行都会显示提交哈希和消息。如果想撤销某个特定更改,只需复制该提交哈希并配合 git revert 使用即可。 

使用图形化工具或扩展

如果您不是开发者或没用过版本控制,这些命令行指令可能像外语一样晦涩。这时图形化工具就派上用场了。它们让 Git 变得可视化且对新手友好,您无需死记硬背命令即可专注于核心工作。

GitHub Desktop 

GitHub Desktop 是一款免费的应用,为您提供简洁易用的界面来操作 GitHub 仓库。安装后,您可以用它创建分支、进行提交、推送到远程并管理项目,全部通过点击而非 Git 命令 完成。

如果您是 Git 新手,或只是想更顺畅地管理更改,它再合适不过。

GitHub desktop user interface

GitHub Desktop 用户界面。图片来源。 

Sourcetree

Sourcetree 是一款免费的 Git 图形化工具,支持 Mac 和 Windows。它为管理分支、提交与合并提供可视化方式,无需接触终端。它轻量、对初学者友好,并能很好地与 GitHub、GitLab、Bitbucket 等常用平台协作。 

由于由 Atlassian 开发,它也能与 Jira、Confluence、Bamboo 等 Atlassian 工具良好集成,如果您的团队已在使用该生态,这是不错的选择。

Sourcetree user interface

Sourcetree 用户界面。图片来源。 

GitKraken

GitKraken 是一款功能丰富的 Git 图形化工具,让使用仓库变得顺滑而直观。它的亮点是图谱视图——五彩交互的时间线,清晰展示仓库历史中的分支、合并与提交。

左侧是项目的文件树,右侧是您点击的提交、文件或分支的详细信息。它直观、对新手友好,同时也为高级用户提供强大功能。

GitKraken 对个人使用免费,但如果您在企业环境中或管理私有仓库,则需要付费计划。

Gitkraken user interface

Gitkraken 用户界面。图片来源。

撤销 Git 提交的最佳实践

只要遵循良好实践,撤销提交并不可怕。我们来谈谈有哪些做法。

用分支进行试验

每当您要构建新功能或修复缺陷时,从 main 上创建一个单独的分支。在那上面完成全部工作,充分测试后,再把它合并回主分支。

这样一来,任何错误或回滚都安全地局限在您的分支中,不会妨碍团队其他人的工作。

拿不准时,用 git revert

假设您在本地分支上做了几次提交,却不小心推送到了主分支。糟糕。现在您想撤销其中一次提交,又不想搞乱共享历史。这就是 git revert 派上用场的时候。

运行 git revert HEAD~1。这会创建一个新提交,撤销倒数第二次提交的更改(因为 HEAD~1 指向它)。它不会删除任何东西,而是以干净、可追踪的方式反向应用更改。

完成后,别忘了使用 git push origin <your-branch-name> 将修复推送到远程。

注意:如果更改已经推送到共享分支,请使用 git revert。它会保持提交历史完整,不会干扰队友。

记录您的更改

您不需要专门写一页 Confluence 来维护版本历史,因为 Git 已经帮您做了。诀窍是聪明地使用它。

从清晰、有意义的提交消息开始。如果您在回退某些内容,请确保消息解释了为什么要这么做。 

并记录下提交 ID 和变更摘要。通常这就足以满足文档记录的需求。

团队协作 

当您在他人也在使用的分支上运行 git reset、rebase 或 commit --amend 等命令时,您在更改提交历史。任何已拉取旧历史的人现在都会面临冲突。 

因此,只在本地或功能分支上使用重写历史的命令。如果必须强制推送或重写共享历史,请尽早与团队沟通。 

结论 

Git 提供了多种方式来撤销错误;但知道何时、如何使用每种工具,正是自信开发者与迷茫开发者的分水岭。

我们探讨了 git reset 在不同模式下的工作方式、何时使用 git revert,以及为何必须根据具体情境选择合适工具。

总结如下:

  • 在推送到共享分支后避免重写历史
  • 若必须强制推送,请尽早沟通
  • 使用 git revert 安全地撤销已推送的提交

接下来,了解您可以如何在此处回退合并提交。如果您已经掌握基础并准备更进一步,欢迎查看我们的 Git 进阶课程! 

FAQs

git reset --soft HEAD~1 实际上做了什么?

它会将您的 HEAD 指针回退一个提交,但保留所有更改处于已暂存状态。非常适合在不丢失任何工作内容的情况下修订提交。

我何时应使用 git reset --mixed 而不是 --soft?

当您想保留文件改动,但将它们从暂存区移除时使用 --mixed。这有助于在重新提交前进行编辑。

使用 git push --force 有危险吗?

是的,尤其是在团队环境中。它会重写远程分支上的提交历史,如果使用不当,可能会抹掉队友的工作。

git revert 和 git reset 有什么区别?

git revert 会新增一个提交来撤销更改且不触碰历史,而 git reset 会移动 HEAD 并可能更改历史——若已推送则风险更高。

我能在不丢失更改的情况下撤销一次提交吗?

可以,使用 git reset --soft 可保持更改为已暂存,或使用 --mixed 将更改保留在工作目录中。

在共享仓库中撤销提交的最安全方法是什么?

使用 git revert。它通过创建新提交来反转更改并保留历史,避免与队友发生冲突。

我如何找到想要撤销的提交?

使用 git log 列出之前的提交。复制您想回退或重置到的那个提交的哈希值。

GitHub Desktop 等图形化工具能回退提交吗?

可以,图形化工具提供了无需记忆命令行语法即可撤销提交的友好方式,非常适合初学者。

重置后提交历史会怎样?

使用 git reset 后,提交会从您的历史中移除——除非它们已被推送。若已推送,远程仍保留记录,除非您进行强制推送。

推送之后再修改一次提交可以吗?

不可以,除非事先协调。修改提交并强制推送会扰乱共享工作。仅在隔离分支或独立项目中这么做。

Srujana Maddula

作者

Srujana Maddula

Srujana 是一名自由职业技术写作者,拥有计算机科学四年制学位。她擅长撰写各类主题的内容,包括数据科学、云计算、开发、编程、安全等众多领域。她热爱经典文学,也喜欢探索新的旅行目的地。

主题