如果禁用强制推送,有没有办法将origin master回滚到之前的提交? 我有A - > B - > C C是错误提交,顺便说一句,B是合并提交。我希望master origin返回B,但是服务器策略拒绝强制推送。
还有其他办法吗?
答案 0 :(得分:3)
在进入技术选项之前,我们应该认识到“无力推动”政策意味着你无意做到你所描述的。从裁判的历史中删除提交是“强制推动”所做的事情的关键(超越常规推动)。通常,原始仓库拒绝强制推送是有充分理由的 - 请参阅git rebase
文档中的“恢复上游rebase”部分,因为即使您不使用rebase
命令,同样的情况也是如此适用。
有些选项可能“足够好”而不是实际删除C
;我会回过头来看。
但是好吧,让我们假设无论出于何种原因你(以及你的团队/回购所有者/谁负责决定这是否合适)了解成本并仍然想要这样做,但不能改变你的政策设置服务器正在执行。
还有另一种方法可以删除C
吗?
不简单。无论如何,不是将原始回购视为遥控器。根据定义,“强制推送”是从远程参考历史中提交提交的操作。
选项1 :嗯,我不知道您的原始回购是如何托管的。服务器软件是否为您提供了操作仓库的选项?如果是这样,这是你最好的选择。
选项2 :如果您可以直接访问原始仓库 - 如果您可以登录某个允许您将其视为本地仓库的地方 - 那么您可以这样做。该过程与您在本地执行的过程基本相同,除非您可能必须首先创建工作树(因为通常原点是裸仓库)。像
这样的东西git worktree add /path/to/create/a/worktree/at master
# cd into the new work tree
git reset --hard HEAD^
然后删除工作树(rm -r ...
)并清理(git worktree prune
),以便git不会担心影响工作树的推送。
选项3 :如果您可以直接访问repo文件,但由于某些原因无法对它们运行git,理论上您可以重写ref本身。直接在git文件上工作是一个危险的游戏,我并不是真的推荐它,但是没有人说我在考虑选项时没有彻底。
除非你对git有足够的了解就可以自己解决这个问题,但这样做可能是个坏主意,所以我继续前进......
选项4 :我想你可以替换整个回购。我们真的到了这里的底部。
那么如果我不能(或决定不)删除C
该怎么办?
你可以revert
代替它。当您还原提交M
时,会创建一个新的提交W
,通过创建M
来“撤消”所做的任何更改。所以
git revert C
会给你
(origin/master)
|
A --- B --- C --- !C <--(master)
/
... X
其中!C
与TREE
具有相同的B
(内容状态)。这可以在没有--force
的情况下推送。它是否“足够好”取决于。
如果C
包含敏感数据(密码,密钥),您可能真的希望它不在历史记录中。我的建议是更改密码并撤销密钥。 (即使您 从历史记录中移除C
,您能否保证没有人复制过它?)
如果C
包含大型二进制文件......这是个坏消息。回购将永远受到由此产生的膨胀的负担。用重写的历史记录替换repo是唯一真正的修复(这会让我们回到上面的选项)。
但如果它只是一个“哎呀”,那么将它从历史中删除是可以理解的,但并非必要。不希望在其历史记录中看到C
的个人可以考虑使用git replace
来“替换”!C
与B
“{1}}”但它可能不值得。 (请注意,replace
只会产生对历史记录更改的错觉,并且有一些记录的怪癖;任何决定使用它的人都应该至少阅读该命令的基本文档。)