git获取非快进更新
我知道,git获取非快进更新,git,Git,我知道,git fetch在从远程获取提交后,总是在分支和它的远程跟踪之间进行快进合并 我的问题涉及一个场景,在这个场景中,我们将要求git fetch执行非快进合并。是否可以使git获取非快进合并? 如果没有,我将如何解决以下情况 我的本地回购协议(进行了大约2次本地提交——C和B提交) 在这里,origin/master需要合并到master中,但这不会很快。git获取将失败。我不想强制获取,因为我也不想丢失提交C和B 这就是为什么不应该使用git fetch更新当前分支的原因。将git p
git fetch
在从远程获取提交后,总是在分支和它的远程跟踪之间进行快进合并
我的问题涉及一个场景,在这个场景中,我们将要求git fetch
执行非快进合并。是否可以使git获取非快进合并?
如果没有,我将如何解决以下情况
我的本地回购协议(进行了大约2次本地提交——C和B提交)
在这里,origin/master需要合并到master中,但这不会很快。git获取将失败。我不想强制获取,因为我也不想丢失提交C和B
这就是为什么不应该使用git fetch
更新当前分支的原因。将git pull与merge或rebase一起使用。拥有
...--o--o--A <-- origin/master
\
C--B <-- master
使用git pull--rebase origin master可以实现以下目标:
...--o--o--A--D <-- origin/master
\
C'--B' <-- master
这使得git为每个新分支配置rebase。对于现有分支,更改为
git config branch.master.rebase true
(注意:我今天早上一大早就开始写了,今天晚上很晚才写完;问题在中间得到了回答,但完成了所有这些工作后,我仍将发布答案。:-)
TL;博士
git fetch命令从不合并任何内容。它可以更新引用,并且非常愿意以快进的方式更新类似于分支的引用。它更不愿意以非快进方式更新此类参考资料;为此,必须强制更新
快速转发一旦正确脱离合并的概念,就成为引用提交的引用的更改属性。更具体地说,我们通常感兴趣的是分支名称值或远程跟踪名称值是否以快进方式更改。这意味着我们必须查看提交图,因为它是提交图中的新位置,与引用当前选择的提交相结合,决定对该引用的更新是否是快进的
长的
这里的原始主张至少在一个重要方面是错误的:
我知道,git fetch
在从远程获取提交后,总是在分支和它的远程跟踪之间进行快进合并
让我们把它拆开一点,这样我们就有了正确的单词和短语来使用。我们需要知道:
- 什么是参照物李>
- 什么是refspec;最重要的是
- 对引用执行快进更新与非快进更新的含义
git push--force
,它为git正在推送的每个引用设置force标志。git fetch命令具有相同的标志,具有相同的效果,但通常“要么全部,要么什么都没有”太宽,因此git有一种方法可以在更单独的基础上设置强制标志。(这里,gitpush
命令有更多的改进,但我们只顺便提一下。)
参考和参考规范的定义
在Git中,引用在理想情况下只是一个名称,一个对某些特定提交或其他Git对象有意义的名称。1引用总是以refs/
开始,并且大多数情况下会有第二个斜杠分隔的组件来声明它们是哪种引用,例如,refs/heads/
是一个分支名称,refs/tags/
是标记名,refs/remotes/
是远程跟踪名。3
(我们在这里关心的参考,用于决定某些更新是否是快进的,是那些我们希望以“y分支方式”进行的参考:那些在refs/heads/
中的参考和那些在refs/remotes/
中的参考。我们稍后将讨论的规则可以应用于任何参考,但肯定适用于这些参考。)“分支-y”参考。)
如果您使用非限定名称,如master
,Git需要或可以使用引用,Git将使用开头部分概述的六个步骤将缩写名称解析为全名,从而计算出完整引用。4
在Git中,refspec主要是由冒号分隔的一对引用(:
)字符,带有可选的前导加号+
。左侧的引用是源代码,右侧的引用是目标代码。我们将refspec与git fetch
和git push
一起使用,它们连接两个不同的git存储库。源代码引用用于git发送的任何一个存储库提交和其他Git对象,目标是用于接收Git的。特别是对于Git fetch
,则源是另一个Git,目标是我们自己
如果refspec中的引用未完全限定(不以refs/
开头),Git可以使用上面的过程来限定它。如果一个refspec中的两个引用都是非限定的,Git中有一些代码试图将它们都放在适当的名称空间中,但我从来都不太信任这段代码。例如,我不清楚在获取过程中谁真正限定了源和目标:有两个Gits涉及,但另一个Git通常会向我们发送其所有引用的完整列表,因此我们的Git可以使用此列表进行解析。显然,在这里使用完全限定的引用更明智,尽管,以防他们的引用集不符合您自己的期望:如果他们只有refs/tags/xyz
,并且您被期望使用xyz
展开到refs/heads/xyz
,如果它没有展开,您会感到惊讶
在任何refspec中,您都可以省略源部分或目标部分。若要省略目标部分,请在编写refspec时不带冒号,例如,refs/heads/br
。若要省略源部分,请在编写refspec时带冒号,但在此处不带任何内容
...--o--o--A <-- origin/master
\
C--B <-- master
...--o--o--A-----D <-- origin/master
\ \
C--B--M <-- master
...--o--o--A--D <-- origin/master
\
C'--B' <-- master
git config --global branch.autosetuprebase always
git config branch.master.rebase true
A <-B <-C
o--o--C--o--o--o--G <-- master
\
o--o--J <-- develop
............ <-- temp
.
A--B--C--D--E--F--G <-- master
\
H--I--J <-- develop
A--B--C--D--E--F--G <-- master
\
H--I--J--K--L <-- develop
git checkout temp
git merge <hash-of-commit-E>
git fetch origin refs/heads/xyz:refs/heads/abc