Github:在分叉的主服务器上获取和变基分叉
Github: Fetch and rebase fork on forked master
我创建了一个项目的分支,并向 我们的 master
添加了 ~40 次提交。
在某个时间点,我不假思索地用强推重写了历史,因为我无法推动 "for no reason at all" 有时你只想看到世界燃烧。
现在一切都很好,但是在 upstream
上的最后 ~100 次提交不再被认为是相同的:我看到 “提前 240 次提交”。 =23=] 而不是 “提前 40 次提交”。
是否可以获取上游 master 并将我们 master 的提交 rebase 到它上面,然后强制将其推回我们的 master,以便我们和他们的同步所有以前的提交,除了我的?如果是这样,如何?请具体点。
我假设您有一个干净的沙箱,其中 origin
指向您的分支,并且您可以通过不同的 URL 访问上游存储库。我还假设您的沙箱中的 origin/master
和 master
是同步的。
根据这些假设,这应该可行:
git remote add upstream <upstream_url>
git fetch upstream
git checkout master
git rebase upstream/master
希望 rebase 能够正常工作并且不会引入任何重复提交。如果没有,它甚至可能会突出显示为什么您首先必须强制推送。
在开始变基之前,git log --graph --decorate --all
(或gitk -all
或任何其他显示完整图表的可视 Git 日志替换)可能会告诉您遇到问题的原因。
编辑:另一种更保守的方法是使用git cherry-pick
。 rebase 解决方案依赖于 Git 认识到应该是共同的历史由已经存在于 upstream/master
上的提交组成。但是您可以确定要保留的第一个提交的父级,而不是变基,假设 origin/master~40
如果您确实有 40 个提交要保留,并在 upstream/master
末尾添加这些提交:
git remote add upstream <upstream_url>
git fetch upstream
git checkout master
git reset --hard upstream/master
git cherry-pick origin/master~40..origin/master
这会为您提供一个新的 master
,它明确地从 upstream/master
开始,并且只添加您想要的新历史记录。
注意 git reset --hard upstream/master
中的 --hard
:正如 OP 在评论中指出的那样,这是确保您在挑选之前从干净的状态开始所必需的。但首先要确保您没有任何未提交的内容要保存。
完整性检查:在 cherry-pick(或 rebase)之后,git diff master origin/master
应该 return 什么都没有,或者再次指出您需要处理的其他问题。
结束编辑
一旦 rebase 或 cherry-pick 完成并且您已经彻底说服自己这个新的历史是您想要保留的:
git push -f origin master
应该让你的分叉恢复到在 upstream
之前只有 40 次提交。
警告:我没有测试 rebase 解决方案,但根据您对情况的描述,我相当有信心它应该有效。然而,我已经成功地使用了 cherry-pick 解决方案,情况类似。如果您尝试任何一种方法,请报告您的成功或任何需要调整的错误。
我创建了一个项目的分支,并向 我们的 master
添加了 ~40 次提交。
在某个时间点,我不假思索地用强推重写了历史,因为我无法推动 "for no reason at all" 有时你只想看到世界燃烧。
现在一切都很好,但是在 upstream
上的最后 ~100 次提交不再被认为是相同的:我看到 “提前 240 次提交”。 =23=] 而不是 “提前 40 次提交”。
是否可以获取上游 master 并将我们 master 的提交 rebase 到它上面,然后强制将其推回我们的 master,以便我们和他们的同步所有以前的提交,除了我的?如果是这样,如何?请具体点。
我假设您有一个干净的沙箱,其中 origin
指向您的分支,并且您可以通过不同的 URL 访问上游存储库。我还假设您的沙箱中的 origin/master
和 master
是同步的。
根据这些假设,这应该可行:
git remote add upstream <upstream_url>
git fetch upstream
git checkout master
git rebase upstream/master
希望 rebase 能够正常工作并且不会引入任何重复提交。如果没有,它甚至可能会突出显示为什么您首先必须强制推送。
在开始变基之前,git log --graph --decorate --all
(或gitk -all
或任何其他显示完整图表的可视 Git 日志替换)可能会告诉您遇到问题的原因。
编辑:另一种更保守的方法是使用git cherry-pick
。 rebase 解决方案依赖于 Git 认识到应该是共同的历史由已经存在于 upstream/master
上的提交组成。但是您可以确定要保留的第一个提交的父级,而不是变基,假设 origin/master~40
如果您确实有 40 个提交要保留,并在 upstream/master
末尾添加这些提交:
git remote add upstream <upstream_url>
git fetch upstream
git checkout master
git reset --hard upstream/master
git cherry-pick origin/master~40..origin/master
这会为您提供一个新的 master
,它明确地从 upstream/master
开始,并且只添加您想要的新历史记录。
注意 git reset --hard upstream/master
中的 --hard
:正如 OP 在评论中指出的那样,这是确保您在挑选之前从干净的状态开始所必需的。但首先要确保您没有任何未提交的内容要保存。
完整性检查:在 cherry-pick(或 rebase)之后,git diff master origin/master
应该 return 什么都没有,或者再次指出您需要处理的其他问题。
结束编辑
一旦 rebase 或 cherry-pick 完成并且您已经彻底说服自己这个新的历史是您想要保留的:
git push -f origin master
应该让你的分叉恢复到在 upstream
之前只有 40 次提交。
警告:我没有测试 rebase 解决方案,但根据您对情况的描述,我相当有信心它应该有效。然而,我已经成功地使用了 cherry-pick 解决方案,情况类似。如果您尝试任何一种方法,请报告您的成功或任何需要调整的错误。