如何还原已推送的提交?

38

我们想要撤消最近推送到 origin master 的最后 2 个提交。在 TortoiseGit 中,我们可以查看历史记录,并点击倒数第3个提交,选择"将 master 重置为此版本",我们猜测这意味着恢复到该版本。

但是,当您选择此选项时,您必须从以下三个选项中选择一个:

  1. 软重置 - 不更改工作树和索引。
  2. 混合重置 - 不更改工作树,重置索引。
  3. 硬重置 - 重置工作树和索引。

不幸的是,我们不知道应该选择这三个选项中的哪一个 - 我们只想撤消最近的两个提交并回到以前的版本。

下一个问题是,这个操作发生在远程 origin、您的仓库、还是您的工作目录,或者这三个组合?例如,撤消后是否需要进行提交和推送,或者它会为您完成这些操作?

我们猜测 HARD 是我们想要的 - 它将恢复存储库(不确定是哪个)和我们本地的源代码到之前的某个版本。如果是这样,那么为什么它不是默认设置,其他两个选项的用例是什么?无论您是想还原还是不还原,如果您只还原远程存储库而不还原本地工作文件,则会处于混乱的状态。

我们没有任何本地修改过的文件。

请注意,我们非常需要一个不会破坏 Git 的解决方案(我们以前曾经破坏了 Git 并不得不创建一个新的仓库)。也许有其他可能的方法,例如检出以前的版本,然后在最新版本上进行检查,但我们不知道如何操作。

我们可以像下面这样做:

git checkout [revision]

那么我们如何告诉git,我们想将这个版本作为新的主版本或用此替换主版本呢? 我猜我们不能只是提交(commit),因为我们不再处于主版本(head)上。另外,如果您检出先前的版本,并进行修改并提交(commit),您提交(commit)的是什么内容以及提交(commit)到哪里?

我阅读了https://www.atlassian.com/git/tutorials/undoing-changes ,但它没有解决本地和远程repo之间的关系。如果要撤消的提交(commit)都被推送到远程origin主版本,那么现在需要回滚(恢复)远程origin、本地repo和工作目录 - 所有3个位置都必须还原到3个提交(commit)之前的状态。我们并不真正关心是使用重置(reset)还是还原(revert) - 我们只需要一种适用于所有3个位置的方法。

可能正确的步骤是像这样:

   git status (we are on master with a clean working dir)
   git git revert HEAD~2
   git commit -m "revert"
   git push origin mater

但是我们在示例中从未见过这组步骤,如果可能的话,我们宁愿使用Tortoise Git 进行操作。

4个回答

51

你可以用两种方法来实现这个目标。

  1. 你可以删除所有更改,返回到原始状态,这符合你的要求。
  2. 撤销你所做出的更改。

对于第一种解决方案,你可以使用以下命令:

git reset --hard <commit-id>

这将把你当前所在分支的HEAD切换到特定的“commit-id”,这个ID是你认为正确和合适的。

git push -f origin <branch-name>

这个命令将强制推送到你所在的分支。结合上面的命令,可以帮助你从顶部开始删除所有不必要的提交记录,直到此“commit-id”。

注意: 这不会删除“commit-id”,而是会从你的分支中删除“commit-id”之前的所有内容。

对于第二种解决方案,您可以使用以下命令:

git revert <commit-id>

这个命令用于还原你想要撤消的特定“提交 ID”。

如果你错误地将另一个分支合并到你的不同分支中,那么你可以使用这个命令来还原合并请求:

git revert -m 2 <commit-id>

该命令用于还原或删除在合并提交“commit-id”中发生的所有更改。这将允许还原合并提交“commit-id”,同时它将删除与此合并相关的所有提交更改。但是它不会删除与合并一起出现的提交。


1
正如最佳答案所提到的,你应该在推送之前进行提交。 - zeeshan khan

28

这个解决方案节省了我的时间

1) git reset --hard 93827927ed6e245be27f94c93c7e3574e85b91c6 (这是你的提交ID)
2) git reset HEAD~1
3) git stash
4) git add .
5) git commit -m "在这里输入你的新提交信息"
6) git push --force


不确定为什么这个能够工作,但它确实可以!这应该是被接受的答案。 - alaskanloops
这是如何工作的?Git stash 不会清理您的工作区,因此 git add 没有任何更改吗? - ssj_100

12

有两个选择:

  1. 回到历史记录,但保留历史记录:revert
  2. 回到历史记录并更改历史记录,以便提交的内容永远被删除:reset --hardpush --force

如果您不确定,请使用 revert,它是最安全的选项。

如果您真的非常想删除提交并且不关心更改的历史记录,请使用 reset --hardpush --force。这将产生以下影响:

  • 其他人可以重新引入提交
  • 其他人可能依赖已被删除的提交
  • 在公共存储库中,强制推送到主分支是不可接受的

问题

下一个问题是此操作发生在远程原始仓库、您的仓库还是您的工作目录,还是这三者的组合?例如,在还原后是否必须进行提交和推送,或者它会为您执行此操作?

通常,TortoiseGit 中的所有更改都在您的克隆(“工作副本”)中。而且,推送始终是手动操作。

我们猜测 HARD 是我们想要的 - 它将把存储库(不确定哪个)和我们的本地源代码还原到以前的版本。如果是这种情况,为什么这不是默认值,另外两个选项的用例是什么?

因为 hard 删除提交和历史记录,所以它是一项危险的操作。您可能还会删除其他人的更改!

另外两个选项的用例是什么?

请参见What's the difference between git reset --mixed, --soft, and --hard?

TortoiseGit 中的步骤:

还原

  1. 还原提交记录(从日志中)

enter image description here

  1. 提交更改

    enter image description here
  2. 并推送

硬重置和强制推送

  1. 重置(从日志中)

enter image description here

  1. 选择“hard”

enter image description here

  1. 强制推送(勾选“已知更改”复选框)

enter image description here


6
我认为你混淆了revert和reset,可以参考撤销更改revert

git revert命令撤销了一个已提交的快照。但是,它不会从项目历史中删除提交,而是找出如何撤消提交引入的更改,并附加一个新的提交以获取结果内容。这可以防止Git丢失历史记录,这对于您的修订历史的完整性和可靠的协作非常重要。

reset

如果git revert是一种“安全”的撤消更改的方法,那么您可以将git reset视为危险的方法。当您使用git reset撤消(并且提交不再由任何ref或reflog引用)时,就没有办法检索原始副本 - 它是永久性的撤消。在使用此工具时必须小心,因为它是唯一有可能丢失您的工作的Git命令之一。

在您的情况下,最好使用revert:

enter image description here

在这种情况下,您只需创建新提交,撤销特定提交,不更改历史记录。您可以在本地执行此操作,然后推送到远程。
如果您仍想进行重置并且不需要保留本地更改,则执行硬重置:

enter image description here

然后你应该执行强制推送:
git push -f

{btsdaf} - John Little
{btsdaf} - Alexan
{btsdaf} - John Little
{btsdaf} - John Little
如果您选择一个,则只会还原一个,但您可以选择多个。是的,您需要提交和推送。 - Alexan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接