远程 Git 撤销操作

3
我是新手,正在使用WebStorm推送和拉取代码。我们正在共同开发一个项目。昨晚我的朋友更新了一些代码并推送了更改。
今天我拉取了代码并合并了更改,但错误地保留了我的更改并放弃了拉取请求提供的更改。然后将这些更改推送到git远程。
所以现在我想要做的就是:
1. 回退到本地之前的状态,即拉取请求之前的状态,并且在远程上我想要与昨晚相同的状态,即推送请求之前的状态。
因此,这就是我想要做的:
1. 在远程上回滚到以前的版本。 2. 再次拉取代码。 3. 进行合并。 4. 推送新代码。
所以现在在远程上我有:
- 我朋友的代码版本提交, - 然后是我错误的版本提交,其中不包括以前代码提交的合并, - 如果我按照下面关于在本地回滚的答案然后推送,那么我会有我的新回滚代码版本提交。 但是最后我希望在远程上有1 + 3。
让我们用数学方式来看待这个问题:
- X = 打开计算机并更改代码并提交的本地状态。 - Y = 昨晚朋友在他的本地计算机上进行更改并推送到远程的远程状态。 - Z = 当我拉取朋友的代码并开始合并但犯了一些错误并放弃了我的朋友的更改,然后提交并推送代码时基本上是状态x到远程。
因此,基本上:
- 在我的本地,我有状态Z。 - 在远程上,我有状态Z - 在我朋友的本地状态Y。
我希望在远程上有X + Y。

你不能“推送未合并的代码”。只有已提交的代码才能被推送。从你的问题中不清楚发生了什么。如果不知道不想要的git命令的确切顺序,也不知道你期望如何解决这个问题,就无法给出权威的答案。 - Sam Varshavchik
基本上,你需要清理任何混乱(特别是在没有其他人使用的存储库中)的方法是清理你的本地分支。你可以重置到旧版本并挑选要保留的更改。一旦你的分支看起来不错,就可以强制推送。这将修改历史记录,但也会清除你的耻辱痕迹。如果有人(构建服务器)检出此分支,你可能需要擦除/清除工作区并重新开始。 - eckes
@SamVarshavchik 你好,Sam。我想我在合并阶段犯了一些错误,只保留了我的代码,因此推送了由我完成的合并代码,其中没有包含拉取的代码更改。 - Arjun Chaudhary
这仍然是一个缺乏具体细节的模糊描述。如果没有看到执行的所有命令的具体日志,那么只能给出一个模糊的答案:撤销本地分支中的所有更改,然后使用 --force 将其推送到远程。就这样。 - Sam Varshavchik
@SamVarshavchik 你好,Sam,请问问题现在清楚了吗? - Arjun Chaudhary
一种更安全的方法是先拉取(此时本地== 远程,含有您错误提交但没有其他正确提交),撤销错误提交并推送(此时本地== 远程,没有您错误提交但也没有其他正确提交),然后从主分支历史记录中使用git cherry-pick命令选取正确的提交。 - Paul Hicks
2个回答

1
如果您想撤销一个提交,可以使用此命令:
git revert commit id goes here

例子:

git revert aa12bb34

这就是还原的作用:

还原一个提交(commit)的意思是创建一个新的提交(commit),该提交撤销了在错误提交中所做的所有更改。与上述情况类似,错误提交仍然存在,但它不再影响当前主分支(master)和任何将来基于它的提交。


@ArjunChaudhary 这应该适用于远程,而不仅仅是本地。 - Harrison
3
如果您需要将此操作应用到远程代码库,那么在执行“还原”操作后,您需要使用 git push 命令将新的提交推送到远程。由于还原提交只是原始提交的反向操作,因此您可能不需要使用强制推送命令。 - mr rogers
@mrrogers 但这样会再次覆盖远程的正确版本。我必须再次与以前的git代码合并。 - Arjun Chaudhary
是的,您将向前滚动。这不是您想要做的吗?这是我建议您做的。 - Paul Hicks
我同意@paulhicks(当然还有@Harrison)。但你并不是真正的“覆盖”远程,而是添加到它的历史记录中。这是正确的做法,也能实现你想要的目标,即使用正确的内容更新那个分支。如果需要,你始终可以取消操作,因为每个提交都会单独存储。 - mr rogers
显示剩余4条评论

1
根据您提供的部分描述,似乎您没有使用任何“危险”选项,而只是向远程库添加并推送了错误提交。
假设远程存储库为“origin”,相关分支为“master”:
git log origin/master

这应该会给你远程提交的日志。你会看到你的错误合并,以及远程分支上之前的提交记录。
在你开始修复之前,请分叉出一个新的分支,作为标记你当前的最新状态的保险措施。如果出错了,你可以轻松地返回到你的提交点:
git checkout -b master-before-i-tried-to-fix-this-mess

现在,获取合并前的提交哈希值,然后先进行非破坏性检出:
git checkout <hash>

其中 <hash> 是你错误合并之前的直接前一个提交的哈希值。

现在查看你的目录。确信这是远程分支在出问题之前的尖端。

然后,返回到你的本地分支:

git checkout master

现在,强制重置您的主分支到正确的提交:
git reset --hard <hash>

现在,你应该回到执行合并之前的状态。现在再尝试进行合并:
git merge whatever-you-tried-to-merge

一旦你确信已正确合并所有内容:
git push --force

您确实需要确保推送一个良好的远程分支,如果有其他人检出了远程存储库,则需要通知他们您所做的内容。
将修复后的远程分支作为普通提交推送是可能的,但这需要更多的工作,并且实际上是一种更危险的过程。您只需承认错误,并将其用作学习经验。
如果您发现自己再次搞砸了,您需要删除本地主分支,并使用保险策略重新创建它:
git checkout master-before-i-tried-to-fix-this-mess
git branch -D master
git checkout -b master

然后再试一次。

现在,你应该回到执行合并之前的状态。现在尝试再次执行合并操作:git merge whatever-you-tried-to-merge;在此之前,我不需要拉取以前的代码,只需执行合并即可。 - Arjun Chaudhary
我的意思是 git reset --hard <hash> 这个命令只会在本地回滚到以前的提交。现在要与昨晚的代码合并,我还需要在远程上回滚。这样当我再次拉取时,就可以合并两个代码了。 - Arjun Chaudhary
在远程仓库上撤销的唯一方法是从本地分支推送修复。Git中没有“远程撤销”的功能。如果您不使用特性分支,而是像牛仔一样在主分支上提交更改,然后拉取以合并,那么您就会遇到麻烦。您应该使用特性分支,然后将其合并回主分支。这样可以更容易地修复此类错误。现在,您唯一的选择是查看reflog,尝试获取先前工作的片段,提交它,并再次推送。 - Sam Varshavchik
或者,作为替代方案,您可以在合并之前使用“reset --hard”将本地分支重置到最后一次提交,然后再次拉取并正确执行合并。 - Sam Varshavchik
是的,我想做OR版本,但是当你拉取时,它是我提交和上传的代码,与还原相同。是的,我现在学到了教训,以后我会在特性分支上工作。 - Arjun Chaudhary
你可以基本上使用我在另一个分支中建议的方法。让该分支看起来像合并应该看起来的样子。然后,使用“git diff work-branch..master”生成该分支和主分支之间的差异,然后将差异“git apply”到主分支,使其看起来与您的工作分支完全相同,然后推送最终结果。 - Sam Varshavchik

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