Ven*_*emo 3 git version-control merge github pull-request
我为 GitHub 上的一个开源项目做出了贡献。创建了一个拉取请求,维护者对其进行了审查,他要求我返工一些东西。与此同时,其他好人也做出了贡献。因此,首先我习惯于git rebase master在最新分支之上对拉取请求进行变基master,然后使用git rebase -i HEAD~5交互式变基功能来修复我的一些提交,然后再git push --force对我自己的远程分支进行变基。
然而,此后,GitHub 认为master由于冲突,我的分支无法再合并到该分支中。事实上,它认为我的分支中添加了一些其他提交(不是我的),这显然与master.
我做错了什么,我该如何纠正?
假设该master分支有以下历史
(master) A -> B -> C -> D
Run Code Online (Sandbox Code Playgroud)
然后我提交X、Y和Z,所以我的分支历史记录是:
(my-branch) A -> B -> C -> D -> X -> Y -> Z
Run Code Online (Sandbox Code Playgroud)
我们还假设有人同时承诺并E推动:master
(master) A -> B -> C -> D -> E
Run Code Online (Sandbox Code Playgroud)
所以首先我要做git rebase master的就是my-branch. 之后我的分支历史是:
(my-branch) A -> B -> C -> D -> E -> X -> Y -> Z
Run Code Online (Sandbox Code Playgroud)
然后我就git rebase -i HEAD~5喜欢这样:
pick D
pick E
pick X
sqash Y
edit Z
Run Code Online (Sandbox Code Playgroud)
请注意,我不会更改D或E。
之后我的历史看起来像:
(my-branch) A -> B -> C -> D -> E -> X -> Z
Run Code Online (Sandbox Code Playgroud)
那我就这么做了git push myremote my-branch --force。
此后,GitHub 声称我的拉取请求无法再合并,因为我的分支上的提交C、D、 和与、、上的E冲突。请注意,我没有编辑这些提交,只是我自己的提交(甚至不是交互式变基的一部分)。CDEmasterC
为什么会有git这样的行为?
如何避免 git 交互式 rebase 搞乱拉取请求?
您必须对交互式变基(或任何变基,实际上,但它往往更频繁地出现在交互式变基中,因为它非常灵活)小心一点。
\n\n更详细地考虑提交图可能会有所帮助。具体来说,这种画法本质上是有些错误的:
\n\n\n\n\nRun Code Online (Sandbox Code Playgroud)\n(master) A -> B -> C -> D\n
最好将其绘制为:
\n\nA <-B <-C <-D <--master\nRun Code Online (Sandbox Code Playgroud)\n\n这里的关键是将分支名称放在右侧,并带有一个箭头。其余的箭头可以转换为直连杆:
\n\nA--B--C--D <-- master\nRun Code Online (Sandbox Code Playgroud)\n\n因为所有提交都是只读的。绘制内部箭头很困难,因此知道它们实际上无法改变,我们可以将它们绘制为连接线。绘制它们的原因(至少在最初)是箭头连接到子级,而不是父级:子级知道其父级提交是谁\xe2\x80\x94D知道返回到C,例如\xe2\ x80\x94但是父母不知道他们的孩子是谁。没有办法从A到B; 我们只能从Bback 到A,然后意识到,嘿,我们是从 到这里的,所以毕竟B一定有一条从A到 的路径。B
这是使用 Git 时的一个关键认识:它会向后执行所有操作。
\n\n所有这些都很重要的原因都与并行开发过程中发生的情况有关。正如你所说,你做了X、Y、 和Z:
A--B--C--D <-- master\n \\\n X--Y--Z <-- my-branch\nRun Code Online (Sandbox Code Playgroud)\n\n您X了解D,但D与其他几个 Git 存储库共享的 \xe2\x80\x94 对您的X.
同时,其他人也提出了E,这也指向D。如果我们想象某种神一样的超级存储库,它以某种方式同时了解E 所有 X-Y-Z信息,我们可以这样画它:
E <-- third-person\n /\nA--B--C--D <-- master\n \\\n X--Y--Z <-- my-branch\nRun Code Online (Sandbox Code Playgroud)\n\n然后他们\xe2\x80\x94“他们”在这里是GitHub\xe2\x80\x94上的开源小组采用了这个第三E人称master:
E <-- master, third-person\n /\nA--B--C--D\nRun Code Online (Sandbox Code Playgroud)\n\n(也许他们还不知道你的情况X-Y-Z,所以我们就把他们从图纸上去掉)。现在,您运行git fetch upstream到本地计算机来获取 GitHub 存储库版本,并且在您的存储库中(仍然有 )X-Y-Z,您有:
E <-- upstream/master\n /\nA--B--C--D <-- master, origin/master\n \\\n X--Y--Z <-- my-branch (HEAD), origin/my-branch\nRun Code Online (Sandbox Code Playgroud)\n\n(我在这里假设 yourorigin代表你的GitHub 分支,而 yourupstream代表你创建分支的原始 GitHub 存储库)。
当您运行git rebase upstream/master或表明master要提交E并运行时git rebase master,您的 Git 会复制提交X、Y和Z:
X\'-Y\'-Z\' <-- my-branch (HEAD)\n /\n E <-- upstream/master\n /\nA--B--C--D <-- master, origin/master\n \\\n X--Y--Z <-- origin/my-branch\nRun Code Online (Sandbox Code Playgroud)\n\n(此图假设您没有更新您的master;如果您更新了,我们可以稍微不同地绘制它)。
这些副本\xe2\x80\x94(标有刻度线的副本X\'-Y\'-Z\'\xe2\x80\x94)已准备好供您强制推送到叉子。假设您此时这样做,您的分叉将拥有它们,并且原始X-Y-Z链将被放弃:
X\'-Y\'-Z\' <-- my-branch (HEAD), origin/my-branch\n /\n E <-- upstream/master\n /\nA--B--C--D <-- master, origin/master\n \\\n X--Y--Z [abandoned]\nRun Code Online (Sandbox Code Playgroud)\n\n如果我们也更新您自己master的origin/master,我们将能够以更简单的方式重新绘制所有这些:
A--B--C--D--E <-- master, origin/master, upstream/master\n \\\n X\'-Y\'-Z\' <-- my-branch (HEAD), origin/my-branch\nRun Code Online (Sandbox Code Playgroud)\n\n(所有这些都位于您计算机上的存储库\xe2\x80\x94on GitHub 上,在您的 fork 中,这些只是命名master,my-branch没有部分,而且根本origin/没有部分)。upstream/
您的拉取请求将自动更新以使用新的X\'-Y\'-Z\'提交,只需添加到提交E\xe2\x80\x94 即可,因此如果它们的存储库仍然以 commit 结尾E,那么它们吸收您的提交应该不会有问题。
如果你想挤进Y\'\的消息X\'并做一些事情,你现在可以使用交互式变基来做到这一点。Z\'或者,您可以执行所有这些操作,而不是最初的变基:
$ git checkout my-branch\n$ git rebase -i upstream/master\nRun Code Online (Sandbox Code Playgroud)\n\n请注意,upstream/master这里在我们的图中实际上意味着“提交”,这是具有as和 或或作为您自己的提示的E那些之一。Eupstream/masterZZ\'my-branch
my-branch现在,Git 将列出已在但未在 上的三个提交的列表upstream/master,即,从Z或开始Z\'并向后工作到A,列出这些提交,然后从该列表中删除所有从 开始E并向后工作的提交。这三个提交的哈希 ID 将进入三个pick命令。
现在,您可以像以前一样将一项更改为压缩,一项更改为编辑:因为您只处理自己的提交,而不处理其他人的提交,所以您不会将其他人的提交复制到新的和不同的提交。完成编辑后,您将再次获得新的提交\xe2\x80\x94如果您已经复制X到X\'、YtoY\'和Zto Z\',现在您拥有X"的是X\'+ Y\'(压缩),以及Z"的编辑版本Z\'但连接到X":
X"-Z" <-- my-branch (HEAD)\n /\nA--B--C--D--E <-- master, origin/master, upstream/master\n \\\n X\'-Y\'-Z\' <-- origin/my-branch\nRun Code Online (Sandbox Code Playgroud)\n\n您现在可以将它们强制推送到您的 fork,以便它们my-branch(您在此处的 Git 存储库中调用origin/my-branch)更改为指向 commit Z",现在您的 fork 再次更新,并且您的拉取请求会自动更新,您\' re(仍然,或最终真正)准备好让他们查看X"和Z"。
| 归档时间: |
|
| 查看次数: |
1280 次 |
| 最近记录: |