当尝试恢复到先前的提交(例如123abc)时,我添加了介词“to”的强调,如“revert to”所示,这是至关重要的。您链接问题中
(如何将Git存储库还原到以前的提交?)的
已接受答案指出了这一点:
“这在很大程度上取决于您对‘还原’的理解。”
在单个提交上运行
git revert
可能不足够。如果需要,可以参见那里有关还原多个提交的答案。
运行
git reset --hard
可能足够,但会引入您遇到的问题。这里需要了解以下内容:
分支名 简单地让 Git 找到 特定的提交。我们说分支名 指向 这个提交。使用 git reset
,可以更改某个分支名指向的特定提交。然而,在 git reset
完成之前可能会发生其他事情,这取决于运行的 git reset
的类型:第一步是只更改 你自己的一个分支名。因为你正在考虑(或已经使用)--hard
,所以你的仓库中还有一些重要的变化,但目前来说不那么重要。
每个 Git 仓库都有其自己的分支名。移动其中一个 你的 分支名对任何其他仓库没有影响。
你需要做的是让 其他 Git 仓库 更改其分支名之一。这就是你遇到这个问题的地方:
我不能推送这个(我需要先拉取,而拉取会让我往前走)。
git push
命令是如何要求或者使用 --force
命令—要求其他 Git 仓库更改、创建或删除其中的一些名称(分支名、标签名和其他这样的名称)的方式。但是,每个 Git 仓库都被设置为 轻松接受新的传入提交,同时抵制建议放弃任何现有提交的建议。
当您使用
git reset
将您的一个分支名称“向后移动”,以便
恢复(不是像添加一个撤销提交那样)一些先前的提交时,您正在
有意地丢弃一些现有的提交。由于您控制自己的Git存储库,因此可以在自己的存储库中执行此操作。由于
git reset
命令
旨在执行此类丢弃操作,
1因此它会毫不犹豫地这样做。但是
git push
不是,并且
他们的 Git 会抱怨。
只要您使用
git pull
,
他们的存储库就会让您
放回您从自己的存储库中剪切出来的所有提交。毕竟,Git旨在尽可能轻松地
添加提交!这使您处于目前的情况。
现在您有选择:
强制其他Git仓库放弃一些提交。这需要足够的权限。这也意味着,使用该Git仓库的所有其他人需要采取行动来处理任何他们所克隆的副本,因为他们的副本将热情地恢复您试图修剪的所有提交。所以这对那些其他人有点不好。
或者,使用git revert
或其他命令向您的仓库添加一些提交,最终将文件还原,但不会删除任何旧的提交。新的提交只是添加到旧的提交中。旧的提交仍然存在,供任何想了解它们的人(例如git log
)或使用它们(例如git switch --detach hash-id
)。
添加新提交是Git的设计目的,因此除非有非常强烈的理由放弃旧提交,否则后者是正确的选择。
正如您所链接的问题所指出的那样,如果使用未发布的提交(即只有您拥有的提交,在您自己的私人仓库中),所有这些都会变得更加容易,因为这些提交根本不在任何其他Git仓库中。如果从您自己的分支中删除这些提交,没有人会知道。他们将无法反对
git push
从他们的分支中删除这些提交,因为这些提交不在他们的分支上。(再次强调,每个分支名称对于每个Git仓库是本地的。一个仓库可以向另一个仓库显示存储在其分支名称中的提交哈希ID,但每个仓库都负责在其自己的分支名称中保留其自己的哈希ID。提交被共享;分支名称不会。)
由于您正在查看的提交是已发布的,因此您无法使用此快捷方式。
1这使得git reset
成为一种非常高效的工具,就像某种喷火烤肉架、工业钢切割激光器之类的东西。这种过度强大是Git 2.23现在拥有git restore
的原因之一:你以前需要使用git reset
才能完成的一些事情,现在可以用相对温和的git restore
来完成。如果要求,这两个命令都会丢弃正在进行的工作,但git restore
更像手锯或螺栓切割器之类的东西。