git rebase/squash-为什么我需要再次解决冲突?
我真的试着浏览类似的主题,但我似乎无法掌握这个概念 我进行了回购,做了一些改变。随着时间的推移,我还多次使用了git rebase/squash-为什么我需要再次解决冲突?,git,squash,git-squash,Git,Squash,Git Squash,我真的试着浏览类似的主题,但我似乎无法掌握这个概念 我进行了回购,做了一些改变。随着时间的推移,我还多次使用了git-fetch-upstream和git-merge-upstream/。有一段时间,我解决了一些冲突,并重新进行了测试 现在,当涉及到向上游推进更改时,我想做一次提交。我得到的指令是使用git-fetch-upstream和git-rebase-I-upstream/ 我不明白的是,我又一次坚持要解决冲突。我不明白为什么我需要解决冲突时,我的叉子是当前与它的起源。我本可以备份所有修
git-fetch-upstream
和git-merge-upstream/
。有一段时间,我解决了一些冲突,并重新进行了测试
现在,当涉及到向上游推进更改时,我想做一次提交。我得到的指令是使用git-fetch-upstream
和git-rebase-I-upstream/
我不明白的是,我又一次坚持要解决冲突。我不明白为什么我需要解决冲突时,我的叉子是当前与它的起源。我本可以备份所有修改过的文件,核掉我的fork,再次进行fork,恢复备份,这样我就不会有冲突需要解决,也不会准备提交。这个过程似乎很机械,我不明白为什么我要走这条艰难的路(再次解决冲突)
有人能帮我理解吗?对于“你为什么需要重新解决所有问题”的最佳答案是“你不需要”。但这意味着放弃给你的指示(我不清楚是谁给了你这些指示)
同样,您可以使用git-rere
自动re使用以前的re有线re解决方案。通过这种方式,您正在解决所有问题,但是让Git来完成,而不是手工完成
但是,如果您的意图是在当前上游提示之上进行一次新的“挤压合并”提交(即,非合并,只是普通提交),以从其发出拉请求,则无需进行任何操作。您可以只执行以下命令序列(请注意以下假设):
然后使用源站的web服务上的clicky web按钮发出拉取请求
最终,他们接受您的请求,此时您将删除分支,放弃所有这些工作,转而使用他们接受的新的单一提交。(关于如何重命名/重置,请参见结尾。)或者,他们不接受,此时您可以删除拉取请求的,并继续处理分支
,并最终重复该过程
这假定:
- 您的fork由两个存储库组成:一个存储库位于您自己的计算机/笔记本电脑/任何东西上,另一个存储库位于像GitHub这样的web服务提供商上
- 他们的(
上游
)分支位于同一个web服务提供商上
- 在您的计算机上,在您的存储库中,您使用短名称
upstream
来指代上游存储库(它们的分支),短名称origin
来指代存储在web服务提供商上的您自己的分支。web提供商提供了发出拉取请求的单击按钮
- 也许最重要的是,这假设您愿意放弃该本地分支,以支持上游接受的拉请求(如果发生这种情况)
理解所有这些有几个关键点,其中大部分都与Git的提交图的工作方式有关。剩下的部分涉及Git分发存储库的(单一)魔术,以及各种命令——Git merge
、Git rebase
和Git merge--squash
——实际做了什么,以及Git fetch
和Git push
真正做了什么
我真的不想在这方面再写一篇长篇大论(…太晚了:-),所以让我们通过记下这些要点来总结一下。它们的顺序不是很好,但我不确定是否有好的顺序:有很多相互参照的项目
- Git通常只添加新的提交。添加新提交将导致存储在
HEAD
-中的当前分支名称指向新提交,而新提交将指向HEAD
提交的任何分支
- 但是,
git-rebase
的工作原理是将现有提交复制到新提交,然后放弃原始提交。它使用“分离头”进行复制,其中HEAD
直接指向提交,而不是使用分支名称。(“添加新提交”仍然像往常一样工作,只是它直接更新HEAD
,而不是名称不再存储在HEAD
中的分支。)复制的提交排除任何合并提交。在某种程度上,这意味着您当时所做的任何冲突解决方案都将丢失(除非您启用了git rere
)。(它实际上是因为不同的原因而丢失的,我还没有弄清楚如何解释。)
- 每个副本都是通过
git cherry-pick
制作的,有时是通过运行git cherry-pick
- 每个cherry-pick都可能导致合并冲突,因为cherry-picking-a-commit运行合并机制,我喜欢称之为动词merge
此操作的合并基是被选中的提交的父级,即使这不是一个非常合理的合并基。像往常一样,
--ours
提交是当前的或头
提交,而另一个提交是--他们的
提交是被复制/拾取的提交。新提交在成功的cherry pick结束时作为普通的非合并提交进行
- 相比之下,运行
gitmerge
,就没有那么复杂了,只是有各种不同的情况
有时Git认为,毕竟不需要合并,可以执行快进操作:更改当前分支指向的提交,以便分支指向目标提交
有时需要合并,或者(使用--no ff
)告诉Git即使可以也不要进行快进。在本例中,Git使用
git fetch upstream
git checkout -b for-pull-request upstream/branch
git merge --squash branch
git commit
git push origin -u for-pull-request
...--o--*--o...o...o--T <-- upstream/branch
\ \
A--B---M---C <-- branch (HEAD), origin/branch
A'-B'-C' <-- branch (HEAD)
/
...--o--*--o...o...o--T <-- upstream/branch
\ \
A--B---M---C <-- origin/branch
S <-- branch (HEAD)
/
...--o--o--o...o...o--T <-- upstream/branch
\ \
A--B---M---C <-- origin/branch
...--o--o--o...*...o--T <-- for-pull-request (HEAD), upstream/branch
\ \
A--B---M---C <-- branch, origin/branch
S <-- for-pull-request (HEAD)
/
...--o--o--o...o...o--T <-- upstream/branch
\ \
A--B---M---C <-- branch, origin/branch
S <-- for-pull-request (HEAD), origin/for-pull-request
/
...--o--o--o...o...o--T--S' <-- upstream/branch
\ \
A--B---M---C <-- branch, origin/branch
S <-- for-pull-request, origin/for-pull-request
/
...--o--o--o...o...o--T--S' <-- branch, upstream/branch
\ \
A--B---M---C <-- origin/branch
S [abandoned]
/
...--o--o--o...o...o--T--S' <-- branch, origin/branch, upstream/branch
\ \
A--B---M---C [abandoned]