如何避免git交互重新基址打乱拉取请求?
我参与了GitHub上的一个开源项目。创建了一个pull请求,由维护人员审核,维护人员要求我修改一些东西。与此同时,其他好人也做出了贡献。因此,首先我使用如何避免git交互重新基址打乱拉取请求?,git,github,merge,version-control,pull-request,Git,Github,Merge,Version Control,Pull Request,我参与了GitHub上的一个开源项目。创建了一个pull请求,由维护人员审核,维护人员要求我修改一些东西。与此同时,其他好人也做出了贡献。因此,首先我使用git-rebase-master在最新的master分支上重新设置我的pull请求的基础,然后使用交互式rebase功能git-rebase-I HEAD~5,修复我的一些提交,然后git-push--force到我自己的远程分支 但是,在此之后,GitHub认为由于冲突,我的分支不能再合并到主分支中。事实上,它认为我的分支中添加了一些其他提
git-rebase-master
在最新的master
分支上重新设置我的pull请求的基础,然后使用交互式rebase功能git-rebase-I HEAD~5
,修复我的一些提交,然后git-push--force
到我自己的远程分支
但是,在此之后,GitHub认为由于冲突,我的分支不能再合并到主分支中。事实上,它认为我的分支中添加了一些其他提交(不是我的),这显然与master
中的相同提交冲突
我做错了什么,我怎样才能改正
更多细节
假设master
分支具有以下历史记录
(master) A -> B -> C -> D
然后我提交X
、Y
和Z
,因此我的分支历史记录是:
(my-branch) A -> B -> C -> D -> X -> Y -> Z
(my-branch) A -> B -> C -> D -> E -> X -> Y -> Z
我们还假设有人同时提交并将E
推送到master
:
(master) A -> B -> C -> D -> E
因此,首先我在我的分支上执行git-rebase-master
。在此之后,我的分支历史记录是:
(my-branch) A -> B -> C -> D -> X -> Y -> Z
(my-branch) A -> B -> C -> D -> E -> X -> Y -> Z
然后我做git-rebase-I头~5
如下:
pick D
pick E
pick X
sqash Y
edit Z
E <-- third-person
/
A--B--C--D <-- master
\
X--Y--Z <-- my-branch
请注意,我没有更改D
或E
在此之后,我的历史看起来像:
(my-branch) A -> B -> C -> D -> E -> X -> Z
然后我将myremote推到我的分支--force
在此之后,GitHub声称我的拉请求不能再合并,因为我分支上的提交C
、D
和E
与master
上的C
、D
和E
冲突。请注意,我没有编辑这些提交,只有我自己的提交(而且C
甚至不是交互式重基的一部分)
为什么git
的行为是这样的?
如何避免git interactive rebase打乱pull请求?一个想法是在命令行上指定合并策略,通过从上游存储库获取更改来始终解决冲突
git rebase -s recursive -X ours master
虽然这不是直观的,“我们的”和“他们的”在重新基准期间会发生反转。因此,这将使用合并的上游更改解决任何冲突。要始终接受您的更改,请在重新基础期间传递“他们的”(更多详细信息:)
做你的互动重基清理任何历史,强迫推到你的叉子。。从GitHub的角度来看,在公关过程中不应该有任何冲突。您必须对交互式重新基址(或者任何重新基址,真的,但由于交互式重新基址非常灵活,它往往更频繁地出现)
更详细地考虑提交图可能会有所帮助。具体而言,这种绘图本身就有点错误:
最好将其绘制为:
A <-B <-C <-D <--master
您的X
知道D
,但与其他几个Git存储库共享的D
对您的X
一无所知
同时,其他人制作了E
,这也指向D
。如果我们想象某种神似的超级存储库,不知何故同时知道E
和X-Y-Z
,我们可以这样画它:
pick D
pick E
pick X
sqash Y
edit Z
E <-- third-person
/
A--B--C--D <-- master
\
X--Y--Z <-- my-branch
(他们可能还不知道你的X-Y-Z
,所以我们把他们从图纸上去掉)。现在,您可以在本地计算机上运行git fetch upstream
,以获取GitHub存储库版本,并且在仍然具有X-Y-Z
的存储库中,您有:
E <-- upstream/master
/
A--B--C--D <-- master, origin/master
\
X--Y--Z <-- my-branch (HEAD), origin/my-branch
(此图假设您没有费心更新您的母版
;如果您有,我们可以将其绘制得稍有不同)
这些带有记号标记的副本,X'-Y'-Z'
——可以让您用力推叉。假设您在此时这样做,您的叉子将拥有它们,并且原始的X-Y-Z
链将被放弃:
X'-Y'-Z' <-- my-branch (HEAD), origin/my-branch
/
E <-- upstream/master
/
A--B--C--D <-- master, origin/master
\
X--Y--Z [abandoned]
(所有这些都在GitHub计算机上的存储库中,在您的fork中,它们只是命名为master
和my branch
,没有origin/
部分,也没有上游/
部分)
您的拉取请求将自动更新为使用新的X'-Y'-Z'
提交,它只是添加到提交E
-因此,如果它们的存储库仍然在提交E
时结束,那么它们吸收您的提交应该没有问题
使用交互式重基
如果您希望将Y'
压缩到X'
中,并对Z'
的消息执行某些操作,现在可以使用交互式重基来执行此操作。或者,您可以执行所有这些操作,而不是初始的重新基准:
$ git checkout my-branch
$ git rebase -i upstream/master
请注意,upper/master
在我们的图中真正的意思是“提交E
”,它是将E
作为upper/master
的一种,并且将Z
或Z'
作为您自己的我的分支
的提示
Git现在将列出my branch
上但不在upstream/master
上的三个提交,即,从Z
或Z'
开始并向后工作到a
,列出这些提交,然后从该列表中删除所有从e
开始并向后工作的提交。这三个提交的散列ID将进入三个pick
命令
您现在可以像以前一样将一个更改为挤压,另一个更改为编辑:因为您只处理您的提交,而不处理其他任何人的提交,所以您不会将其他任何人的提交复制到新的和不同的提交。编辑完成后,如果您已经将X
复制到X'
,Y
复制到Y'
,以及Z
复制到Z'
,那么您将再次进行新的提交,现在您有了X'
+Y'
(挤压)和Z'
A--B--C--D--E <-- master, origin/master, upstream/master
\
X'-Y'-Z' <-- my-branch (HEAD), origin/my-branch
$ git checkout my-branch
$ git rebase -i upstream/master
X"-Z" <-- my-branch (HEAD)
/
A--B--C--D--E <-- master, origin/master, upstream/master
\
X'-Y'-Z' <-- origin/my-branch