以前可能有人问过这个问题,但我费了好大劲才找到它。
很多时候,有经验的 git
用户会说“不要 rebase
已经公开的存储库!”这是正确的。但我没有看到任何处理后果的信息。我知道我们不应该让自己陷入这种情况,但当它确实发生时我们该怎么办?
Original: A--B--C--D--E--F
My Repo: A--B--C--D
\
X--Y--Z
Rebased: A--B
\
L--M--N--O
所以我fetch
,这应该很简单,对吧?然后……然后会发生什么?如果我执行 `pull --rebase
,它应该会在某个时候失败,因为 C--D
丢失了。我实际会遇到哪些错误,我该如何解决?
最佳答案
在 git-rebase
联机帮助页中有一个名为“从上游 REBASE 恢复”的部分对此进行了很好的描述。
获取
针对您的具体情况,让我们来看看会发生什么。如果您只是获取,所做的就是更新您的远程跟踪分支。这仍然可以正常工作 - 它会给你一个警告,不过:
From <url>:
+ abc123...def456 master -> origin/master (forced update)
pull
pull ,无论是正常( merge )还是 rebase ,都会在内部调用 fetch。因此,如果您尚未获取,您将看到“强制更新”警告。如果已经fetch了,之前有强制更新警告,现在没有强制更新警告了。如果在 merge 之后有一个很大的差异报告作为 merge 的一部分,您也可能会错过强制更新警告。获取之后,git-pull 然后根据请求调用 merge 或 rebase。这就是它变得真正可怕的地方。就 Git 现在而言,提交 C
和 D
现在只是本地提交。有一次它们被出版并不重要。所以 Git 将像往常一样 merge/ rebase 。
merge :
- A - B - L - M - N - O (origin/master)
\ \
C - D - X - Y - Z - Q (master)
rebase :
- A - B - L - M - N - O (origin/master) - C' - D' - X' - Y' - Z' (master)
现在,如果删除提交 C 和 D 使后面的提交不同,那么任何一个都可能会发生冲突。 merge 冲突是您会注意到的唯一其他错误。但如果它们是孤立的更改,那么一切都会“正常”。如果用户没有注意到,那么随后可能会推送此历史记录,从而重新引入已删除的提交!有时这可能是相对良性的。也许 L 实际上是 C,在提交消息中修复了一个拼写错误,而 MNO 与 DEF 相同,只是父级不同。因此,重新引入 C 和 D 只会扰乱历史。但也许它非常危险:也许删除 C 修复了一些可怕的错误,并且它刚刚被重新引入。
避免问题
这就是为什么重写已发布的历史是一个真的坏主意。最好的情况是以一些重复的提交结束,最坏的情况是用户在不知不觉中破坏了一切。因此,如果确实发生了,您要做的第一件事就是告诉所有人并指导他们如何恢复。接下来的事情是警惕地监控随后发布的所有内容,以确保它不会重新引入旧的提交。如果你在这方面的另一边,从公共(public) repo 中获取,希望你足够信任维护者永远不会 rebase 稳定分支,或者告诉你他们是否这样做。如果您不信任它们,那么最好先获取然后 merge/ rebase ,而不是 pull ,这样您就可以注意到“强制更新”消息并非常小心地继续。
本地恢复
如何恢复的细节各不相同;我推荐前面提到的联机帮助页。很难确切地说出你需要做什么——这取决于 C 是否被重写为 L(也许 D 为 M)或者它们是全新的提交,以及你是否想要 rebase 或 merge 。如果您只想 rebase ,将 XYZ rebase 到 O 就足够了。如果你想 merge ,你需要将 XYZ rebase 到 B 或 M,然后 merge O。
关于git - 您如何处理已经重新设置基础的公共(public)存储库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8448973/