为什么混帐拉起源发展--rebase事业冲突时的git拉出身发展不?

问题描述 投票:1回答:1

现在,一般我用

git pull origin develop

为获得来自开发分支的最新更新。最近,我的团队一直过渡到使用衍合,而不是合并,所以我有点糊涂了一些东西。之前我的工作流程是非常简单的。我先签入开发分支和使用

git checkout -b feature/foo

然后我会让我的变化,提交,然后把他们。通常情况下,开发分支将就此做了一些改变,我会用

 git pull origin develop

以获得最新的变化,并有冲突只有当其他人修改了同一个文件。然而,当我使用

git pull origin develop --rebase

我注意到,我会冲突与我自己的分支机构,即使我谁已经修改它的唯一的人。对此有一个特别的原因?有没有办法避免这些合并冲突,我有我自己的分支?

git merge version-control rebase pull
1个回答
2
投票

首先,让我们注意,git pull主要包括运行两个Git的命令。这意味着它的意思是一个方便的操作,让你git pullentergit fetch而不是键入git .....。第一个命令总是git fetch,第二个是你的选择:它默认为git merge,但你可以选择git rebase。它需要几乎同样多的打字做一个命令为两个,当你想变基,所以它不是真的毕竟很方便,我建议使用单独的git fetch和第二个命令,至少要等到你很熟悉Git.1

所以,你的问题真的解决了一个简单的办法:为什么有时重订有合并没有冲突?而且还有一个问题的答案,这实际上是相当简单:再次基于主要只是反复摘樱桃,樱桃采摘是合并的一种形式。所以,当你合并,你有一个地方,你可以得到的冲突。如果你变基10名提交,你有十个地方,你可以得到的冲突。冲突本身可以是不同的为好,但机遇的规模是这里的主要因素。


1IN库与子模块,git pull可以递归到子模块,在这种情况下,它两个以上的命令和它的便利方面变得显著。您还可以配置git pull默认运行git rebase,使得方便重新出现,即使没有子模块。我还是鼓励新用户使用两个独立的命令,不过,对于该语法git pull是有点怪异,几乎所有其他的Git的东西有点不同,它太容易混淆得到。有一个分配给拉了太多神奇的时候,居然所有的法术是从第二个命令,你需要学习合并理解变基。


Merging

虽然实现全棘手的小波折,合并背后的想法很简单。当我们问Git的合并,我们有“我们的工作”和“工作”。 Git的需要找出我们改变了他们改变什么,并结合这些变化。

为了做到这一点,Git的需要找到一个共同的起点。一个提交不是一套的变化都:它实际上是一个快照。 Git的可以显示这些快照从它的前任不同,即之一,同时抽取快照,看看有什么不同。因此,如果我们从一些开始犯了一些哈希ID B,他们也从同一开始承诺:

          C--D   <-- our-branch (HEAD)
         /
...--A--B
         \
          E--F   <-- their-branch

随后的Git可以在B快照比较我们最新的,D,以及他们最新的,F。无论是在B-VS-D不同的东西,我们改变了。无论是在B-VS-F不同的东西,他们改变了。 Git的则结合了变化,应用组合变化,从合并基础B快照,并提交结果,不是一个而是两个前辈挂钩起来:

          C--D
         /    \
...--A--B      G   <-- our-branch (HEAD)
         \    /
          E--F   <-- their-branch

为了达到这个目标,Git有运行:

  • git diff --find-renames hash-of-B hash-of-D(我们改变)
  • git diff --find-renames hash-of-B hash-of-F(他们改变什么)

当Git的去这两个差异列表结合起来,可以有地方,我们和他们改变了同一个文件的同一行。如果我们没有对这些线路进行相同的更改,Git会声明冲突并停止合并在中间,不作承诺G着呢,迫使我们收拾残局,并完成合并创建G

Cherry-picking

背后摘樱桃的想法是复制一个承诺。要复制一个承诺,我们可以让Git把它变成一组更改:

  • git diff --find-renames hash-of-parent hash-of-commit

然后,我们可以采取这些变化,并用手涂抹别的地方他们,即其他一些承诺。举例来说,如果我们有:

          C--D   <-- our-branch (HEAD)
         /
...--A--B
         \
          E--F   <-- their-branch

我们喜欢他们在F做,但不想E本身呢,我们可以diff的E VS F,看看他们做了什么。我们可以用它来尝试使我们在D快照相同的变化。然后,我们让自己一个新的承诺,让我们称之为F'意味着F的副本:

          C--D--F'  <-- our-branch (HEAD)
         /
...--A--B
         \
          E--F   <-- their-branch

但是,如果我们在C取得显著的改变,或他们在E取得显著的改变,可能很难让他们从EF所做的更改与什么在我们D快照排队。对于Git的来帮助我们,并自动执行此复制,Git会想知道:什么是ED之间有什么不同?也就是说,Git会想要运行:

  • qazxsw POI(我们在qazxsw POI,VS qazxsw POI)
  • git diff --find-renames hash-of-E hash-of-D(他们在C改变)

别急,我们刚才看到上面同样的模式,E中!而事实上,这恰恰是混帐在这里所做的:它使用相同的代码git diff --find-renames hash-of-E hash-of-F,它只是强制合并基础,这将是F对于常规合并,是犯git merge,母公司承诺git merge,我们是樱桃-picking。现在的Git结合了变化且其变动,将组合组更改快照中基在B,并就自己的最终E提交,但这次作为一个经常犯。

新提交重新使用提交信息的提交F本身也使新的承诺E(其中有一些新的哈希ID,从F'的不同)类似于F很多:F'可能显示了相同或非常相似的,DIFF列出各,当然同样的提交日志信息。

F,此合并过程,我喜欢称之为合并为一个动词,可能会出错。如果不出差错,Git的抱怨合并冲突,以合并未完成的停止,让你收拾残局和提交。当你提交,Git会知道你完成了一个F和在这一点上提交信息给你的副本,使git show

Rebase is repeated cherry-picking

做一个git merge,Git的方法:

  • 列出你有你的分支,不可达的(一个技术术语的提交:看git cherry-pick从目标;
  • 修剪这个列表中,如果合适,见下文;
  • 检查出目标提交作为“分离HEAD”;
  • 反反复复,一次提交的时间,使用F'复制每次提交这在list.2

一旦所有的待复制的提交已被成功复制,移动的Git分支名称复制列表的末尾。

假设我们要实现一个类似的设置之前,虽然我将列出几个在这里提交:

git rebase target

我们运行Think Like (a) Git,这样的Git列出了提交复制:git cherry-pick,按照这个顺序。然后,Git首先出来承诺 C--D--E--F <-- our-branch (HEAD) / ...--A--B \ G--H <-- their-branch 为“分离的头”:

git rebase their-branch

现在Git会摘樱桃C-D-E-F复制。如果顺利的话:

H

Git的重复的 C--D--E--F <-- our-branch / ...--A--B \ G--H <-- their-branch, HEAD C C--D--E--F <-- our-branch / ...--A--B \ G--H <-- their-branch \ C' <-- HEAD 。一旦完成DE我们在此状态下:

F

Git的完成复制DE后,底垫的最后一步是将抽出的名字 C--D--E--F <-- our-branch / ...--A--B \ G--H <-- their-branch \ C'-D'-E' <-- HEAD 到指向最终复制承诺,并重新连接F它:

F'

每个摘樱桃做一个三路合并,与操作是母公司的合并基础提交被复制和“我们的”承诺是在脱离our-branch音符,最初这是他们犯HEAD之一,并作为我们进步,它变成了“他们的承诺 C--D--E--F [abandoned] / ...--A--B \ G--H <-- their-branch \ C'-D'-E'-F' <-- our-branch (HEAD) 加上我们的工作”随着时间的推移。在“他们的”承诺是,每一次,我们自己的承诺。每个摘樱桃可以拥有所有常见的合并冲突,但在大多数情况下,多数人都没有。

有两种情况尤其是特别恶劣。其中的一个,可能是最常见的,就是任何时候你自己提交的,在列表中HEAD举例来说,本身的东西,是在H链樱桃选秀权(这往往不仅仅是两次提交,而更长的时间) - 或反之亦然,例如,可能H本质上是C-D-E-F

如果你,或者他们,能够使该摘樱桃早轻松,没有冲突,你可能拷贝看起来几乎一模一样,甚至100%的完全一样,一个G-H链。如果是这样的话,可以GIT中认识到,它是这样一个副本,从“被复制”列表中删除。在我们的例子中,如果H是真的D',和Git可以看到,Git会从待复制列表中删除G-H,只有复制H。但如果不是,如果,例如,他们不得不改变D'一堆自己的副本,使D,Git会尝试复制C-E-F而这些变化几乎肯定会与他们修改D冲突。

如果合并,而不是复制,你会比较H VS D(他们)和H VS B(你的)和冲突的可能性也许减少。即使有冲突,他们可能更明显,更容易解决。如果冲突是因为一个不必要的副本,他们往往会根据我的经验,看棘手。

另一个常见的问题的情况是,在你的H链,你最后几次提交了东西,你为了使合并更容易专门做了。也就是说,有人可能会说是这样的:我们改变foo的子系统,现在你需要第三个参数,你以后樱桃采摘B的变化增加了第三个参数F。复制C-D-E-FF时,你会得到冲突。你可能会跳过复制E,因为它是一个摘樱桃,然后复制C不需要你固定在DE冲突之后,但是这需要两个副本是需要修复,一个是自动删除,和一个你自己的,手动降。

因此,在最后,F做一个合并,但D做了很多的樱桃挑选,每一个都是-内部-合并,并且每一个都可以导致合并冲突。这并不奇怪,底垫得到更多的冲突!


2Technically,一个普通的(非交互式)E经常不使用git merge。相反,它使用了,实际上,git rebase。使用git rebase总是使用git cherry-pickgit format-patch ... | git am ...迫使非交互式git rebase -i使用git cherry-pick。即普通重订避免它事实上主要是刚刚从缓缴古(2008前期涨幅那么,可能)Git的,之前是教摘樱桃做一个适当的三方合并。

git rebase -m步骤使用git rebase,因此,如果一个补丁失败,Git会“回落”到三路合并。结果通常是一样的,但格式补丁管到上午方法从来没有发现重命名的文件。这使得格式补丁式的速度更快,但没有那么好。

© www.soinside.com 2019 - 2024. All rights reserved.