如何撤销 Git 提交而不丢失更改

GitBeginner
立即练习

引言

Git 是一个强大的版本控制系统,它允许开发者有效地管理他们的代码库。一个常见的任务是撤销更改。虽然 git reset 等命令可以修改提交历史,但 git revert 提供了一种更安全、非破坏性的方式来撤销提交,尤其是在协作项目中。本实验将指导你如何使用 git revert 撤销提交,以及如何使用其选项来保留你的更改以便进一步修改。

检查提交历史

在我们进行任何更改之前,了解项目当前的状态至关重要。实验环境已预先配置了一个 Git 仓库,其中包含一个名为 story.txt 的文件和几个提交。让我们来检查一下提交历史。

首先,使用带 --oneline 选项的 git log 命令来获取提交历史的紧凑视图。此命令将每个提交列在一行上,显示提交哈希和提交消息。

git log --oneline

你应该会看到类似以下的输出。请注意,你的提交哈希会不同:

c7a3e69 (HEAD -> master) Add a second, unwanted line
a9b2d5f Add the first line to the story
f3e1c8a Initial commit: Add story.txt

此日志显示了三个提交。最上面的最新提交的消息是“Add a second, unwanted line”。让我们假设这个提交引入了一个我们需要撤销的错误。

我们还可以查看文件 story.txt 的当前内容:

cat story.txt

输出将是:

Once upon a time, in a land of code.
The hero of our story was a brave developer.
Suddenly, a wild bug appeared!

我们的目标是删除最后一行,“Suddenly, a wild bug appeared!”,这是我们在最新提交中添加的。

使用 git revert 安全撤销

git revert 命令用于创建一个新的提交,该提交会撤销先前提交所做的更改。这是一种安全的撤销更改的方法,因为它不会改变项目的历史。

首先,复制你想要撤销的提交的提交哈希。从上一步的输出中,这是消息为“Add a second, unwanted line”的提交。

现在,使用该哈希运行 git revert 命令。

请将 <your-commit-hash> 替换为你终端中的实际哈希。

git revert <your-commit-hash>

运行此命令后,Git 会打开你的默认文本编辑器(nano),允许你编辑这个新的撤销提交的消息。默认消息通常已经足够。

要保存并退出 nano:

  1. Ctrl+O(写入)然后按 Enter 确认文件名。
  2. Ctrl+X 退出。

现在,让我们再次检查提交历史:

git log --oneline

你会在顶部看到一个新的提交:

e0d5f1b (HEAD -> master) Revert "Add a second, unwanted line"
c7a3e69 Add a second, unwanted line
a9b2d5f Add the first line to the story
f3e1c8a Initial commit: Add story.txt

请注意,原始的“不想要的”提交仍然在历史记录中,但已添加了一个新的“Revert”提交。这个新提交会撤销那个不想要的提交所做的更改。

最后,检查 story.txt 的内容以确认更改已被撤销:

cat story.txt

输出现在应该是:

Once upon a time, in a land of code.
The hero of our story was a brave developer.

不想要的行已被成功删除。

使用 --no-commit 撤销并保留更改

有时,你希望撤销某个提交的更改,但又想将这些更改保留在你的工作目录中以便进行修改。例如,你可能想修复提交中的错误,而不是完全丢弃它。--no-commit(或 -n)选项非常适合此目的。

首先,让我们将仓库重置到上一个撤销操作之前的状态,以便尝试另一种方法。我们将为此使用 git reset。此命令会移动 HEAD 指针,而 --hard 会更新你工作目录中的文件以匹配。

git reset --hard HEAD~1

此命令会移除我们刚刚创建的“Revert”提交。你可以通过运行 git log --oneline 来确认这一点。

现在,让我们再次撤销“不想要的”提交,但这次使用 --no-commit 选项。请记住使用“Add a second, unwanted line”提交的哈希。

请将 <your-commit-hash> 替换为你终端中的实际哈希。

git revert --no-commit <your-commit-hash>

这次,编辑器不会弹出。撤销操作已准备就绪,但尚未提交。检查你的仓库状态:

git status

输出将显示 story.txt 已暂存以供提交:

On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	modified:   story.txt

来自被撤销提交的更改现在已进入你的暂存区。你现在可以修改它们了。让我们用一个更好的行替换掉那个不想要的行。使用 nano 打开 story.txt

nano story.txt

文件看起来会和你之前在步骤 2 中撤销后的样子一样。在文件末尾添加一个新行,使其更好:

And they lived happily ever after.

保存并退出 nano(Ctrl+OEnterCtrl+X)。

现在,将你的更改添加到暂存区,并使用一个新的、描述性的消息提交它们:

git add story.txt
git commit -m "Replace unwanted line with a proper conclusion"

最后,检查日志和文件内容以查看结果:

git log --oneline
cat story.txt

日志显示了你的新提交,并且 story.txt 具有已更正的内容。你已成功撤销了一个提交,同时保留并修改了其更改。

总结

在本实验中,你学会了如何在不丢失工作的情况下安全地撤销 Git 提交。你练习了使用 git log 检查提交历史,执行标准的 git revert 来创建一个撤销先前更改的新提交,以及使用 git revert --no-commit 选项将更改撤销到你的暂存区,从而允许你在创建新提交之前对其进行修改。这些技术对于干净安全地管理项目历史至关重要,尤其是在团队环境中。