无法 git 在其他用户的分支贡献后变基
Unable to git rebase following branch contribution from another user
我在将主要开发分支 master
重新定位到我的功能分支 crm-feature
时遇到问题。
我正在尝试使用 git rebase master crm-feature
的正常方法来执行此操作
当我这样做时,我发现当 每个 提交都变成冲突时,我在 rebase 中到达了某个点。
查看 Github 中的提交列表,我看到所有 my 提交(由我编写),然后是其他人的提交,然后我的所有提交似乎都被重新创建因为某些原因。所有这些提交都显示如下:
因此,从顶部的最新到最旧,我的提交日志如下所示:
- 来自其他贡献者 piccolax00 的提交
- 来自其他贡献者 piccolax00 的提交
- 我所有由 piccolax00 用户编写的提交,如上图所示
- 来自其他贡献者的提交
- 我的原始提交
总而言之,我不明白 piccolax00 用户的提交来自何处以及我如何解决它们,因为它们似乎是阻止我将分支重新定位到 master
的原因.该分支是在我休假期间工作的,在我离开之前,我所有的提交都位于顶部,因为我定期重新定位到 master
,以便在重播我在每次都顶。
我不确定该分支是否已经被 piccolax00 用户重新定位,如果是这样的话我的选择是什么?
根据提供的信息,我将对如何解决您的问题进行有根据的猜测。
警告:此解决方案涉及重写存储库的历史记录,如果您不小心,可能会导致数据丢失。 在继续之前备份您的存储库。
在 Git 中制作备份存储库的最简单方法是简单地克隆另一个本地存储库,并在出现问题时从该备份恢复。
(可能)存储库的状态
从您的描述来看,您和合作者的存储库状态似乎是这样的:
# Collaborator history
aaa - ooo - AAA - bb
# Your history
aaa - ccc
在哪里
a
代表你的提交,
o
表示来自其他用户的提交,
A
表示您重写的提交(基于之前的 a
提交),
b
表示 piccolax00 的提交,并且
c
表示您尚未推送到共享上游存储库的新提交。
一个解决方案
假设以上为真,并且提交 o
没有被重写(即 A
是唯一重写的提交),那么您可以使用的一种解决方案是重建使用硬重置和选择性重新设置历史片段的正确历史记录。
拼接你的合作者的分支
首先,我们将从合作者分支的本地副本中拼接出 A
提交(我们称之为 piccolax00
),
开始我在历史记录中最近的 o
提交处创建一个分支 newBase
,并在最近的 [=] 处创建一个分支 oldBase
20=] 提交,
git checkout piccolax00
git branch newBase o
git branch oldBase A
接下来,将 b
系列提交变基到 newBase
分支(即 o
提交),
git rebase --onto newBase oldBase piccolax00
您可能需要重新解决可能发生的冲突。
执行完上述操作后,假设所有冲突都已顺利解决,那么您的合作者的 piccolax00
分支将如下所示,
aaa - ooo - bb
作为完整性检查,将新历史与旧历史进行比较也是一个好主意
git diff piccolax00@{1}
其中 piccolax00@{1}
指的是执行变基之前 piccolax00
分支的状态。如果 piccolax00
和 piccolax00@{1}
顶端的代码状态相同,那么 rebase 没有在代码中引入任何错误。
在顶部拼接您的新提交
理论上,我们执行的较早步骤恢复了上游分支的 "correct" 历史记录,因此执行正常的 rebase 应该使您的分支与其同步,
git checkout crmpicco
git rebase piccolax00
那么你的历史应该是这样的,
aaa - ooo - bb - ccc
然后您需要将这个新历史强制推送到您的上游,因为您已经重写了很多提交,因此它们不再具有与以前相同的 sha ID。
警告:在强制推送重写的共享历史时要非常小心。如果您的任何其他协作者已经将提交添加到 piccolax00 推送的旧共享历史记录,那么 他们将 需要将他们自己的共享历史记录的本地版本与您的任何内容同步重新推动(可能通过更多的变基)。
这就是为什么重写共享历史经常遭到反对,如果操作不当,项目的贡献者要从中恢复可能会很耗时。
无论如何,如果您确定要继续推送重写的共享历史记录,则执行
git push -f upstream crmpicco
其中 upstream
是远程共享仓库,crmpicco
是您要推送的分支。
其他解决方案
以上方案完全有可能没有解决您的问题。如果没有更多信息,我真的无法为您提供更多帮助,但如果您遇到困难,可以按照 and investigate whether or not --fork-point
的帮助,
Look for "recovering from upstream rebase". Git's new(ish, 2.0 or so) --fork-point computation is helpful.
其他资源
我会 post 因为我最终被建议采取与@Cupcake 上面提供的方法略有不同的方法。希望这对以后的人有所帮助。
就命令而言,我做了以下操作:
# made a backup of the branch incase I screw it up during the rebase
git checkout -b crm-feature-branch-original crm-feature-branch
# Rebase my branch onto master and replay my commits on top
git rebase -i crm-feature-branch master
在交互式变基过程中,我 删除了 包含重复提交的行。我可以通过查看 Github.
中的哈希来判断要删除哪些提交,而不是 pick
我有一些冲突,但预计它们不会接近我最初的数量。
我在将主要开发分支 master
重新定位到我的功能分支 crm-feature
时遇到问题。
我正在尝试使用 git rebase master crm-feature
当我这样做时,我发现当 每个 提交都变成冲突时,我在 rebase 中到达了某个点。
查看 Github 中的提交列表,我看到所有 my 提交(由我编写),然后是其他人的提交,然后我的所有提交似乎都被重新创建因为某些原因。所有这些提交都显示如下:
因此,从顶部的最新到最旧,我的提交日志如下所示:
- 来自其他贡献者 piccolax00 的提交
- 来自其他贡献者 piccolax00 的提交
- 我所有由 piccolax00 用户编写的提交,如上图所示
- 来自其他贡献者的提交
- 我的原始提交
总而言之,我不明白 piccolax00 用户的提交来自何处以及我如何解决它们,因为它们似乎是阻止我将分支重新定位到 master
的原因.该分支是在我休假期间工作的,在我离开之前,我所有的提交都位于顶部,因为我定期重新定位到 master
,以便在重播我在每次都顶。
我不确定该分支是否已经被 piccolax00 用户重新定位,如果是这样的话我的选择是什么?
根据提供的信息,我将对如何解决您的问题进行有根据的猜测。
警告:此解决方案涉及重写存储库的历史记录,如果您不小心,可能会导致数据丢失。 在继续之前备份您的存储库。
在 Git 中制作备份存储库的最简单方法是简单地克隆另一个本地存储库,并在出现问题时从该备份恢复。
(可能)存储库的状态
从您的描述来看,您和合作者的存储库状态似乎是这样的:
# Collaborator history
aaa - ooo - AAA - bb
# Your history
aaa - ccc
在哪里
a
代表你的提交,o
表示来自其他用户的提交,A
表示您重写的提交(基于之前的a
提交),b
表示 piccolax00 的提交,并且c
表示您尚未推送到共享上游存储库的新提交。
一个解决方案
假设以上为真,并且提交 o
没有被重写(即 A
是唯一重写的提交),那么您可以使用的一种解决方案是重建使用硬重置和选择性重新设置历史片段的正确历史记录。
拼接你的合作者的分支
首先,我们将从合作者分支的本地副本中拼接出 A
提交(我们称之为 piccolax00
),
开始我在历史记录中最近的
o
提交处创建一个分支newBase
,并在最近的 [=] 处创建一个分支oldBase
20=] 提交,git checkout piccolax00 git branch newBase o git branch oldBase A
接下来,将
b
系列提交变基到newBase
分支(即o
提交),git rebase --onto newBase oldBase piccolax00
您可能需要重新解决可能发生的冲突。
执行完上述操作后,假设所有冲突都已顺利解决,那么您的合作者的 piccolax00
分支将如下所示,
aaa - ooo - bb
作为完整性检查,将新历史与旧历史进行比较也是一个好主意
git diff piccolax00@{1}
其中 piccolax00@{1}
指的是执行变基之前 piccolax00
分支的状态。如果 piccolax00
和 piccolax00@{1}
顶端的代码状态相同,那么 rebase 没有在代码中引入任何错误。
在顶部拼接您的新提交
理论上,我们执行的较早步骤恢复了上游分支的 "correct" 历史记录,因此执行正常的 rebase 应该使您的分支与其同步,
git checkout crmpicco
git rebase piccolax00
那么你的历史应该是这样的,
aaa - ooo - bb - ccc
然后您需要将这个新历史强制推送到您的上游,因为您已经重写了很多提交,因此它们不再具有与以前相同的 sha ID。
警告:在强制推送重写的共享历史时要非常小心。如果您的任何其他协作者已经将提交添加到 piccolax00 推送的旧共享历史记录,那么 他们将 需要将他们自己的共享历史记录的本地版本与您的任何内容同步重新推动(可能通过更多的变基)。
这就是为什么重写共享历史经常遭到反对,如果操作不当,项目的贡献者要从中恢复可能会很耗时。
无论如何,如果您确定要继续推送重写的共享历史记录,则执行
git push -f upstream crmpicco
其中 upstream
是远程共享仓库,crmpicco
是您要推送的分支。
其他解决方案
以上方案完全有可能没有解决您的问题。如果没有更多信息,我真的无法为您提供更多帮助,但如果您遇到困难,可以按照 --fork-point
的帮助,
Look for "recovering from upstream rebase". Git's new(ish, 2.0 or so) --fork-point computation is helpful.
其他资源
我会 post 因为我最终被建议采取与@Cupcake 上面提供的方法略有不同的方法。希望这对以后的人有所帮助。
就命令而言,我做了以下操作:
# made a backup of the branch incase I screw it up during the rebase
git checkout -b crm-feature-branch-original crm-feature-branch
# Rebase my branch onto master and replay my commits on top
git rebase -i crm-feature-branch master
在交互式变基过程中,我 删除了 包含重复提交的行。我可以通过查看 Github.
中的哈希来判断要删除哪些提交,而不是pick
我有一些冲突,但预计它们不会接近我最初的数量。