git pull * after * git rebase?

时间:2017-03-17 15:24:23

标签: git rebase

我有一个功能分支和一个主分支。

Master分支已经发展,我的意思是让这些更新尽可能少地与master分支发生分歧。

所以我git pull在两个分支中git checkout feature/branch,最后git rebase master

现在,我要么希望一切顺利运行冲突,我需要在继续rebase之前解决,直到所有主提交在功能分支上成功重新应用。

现在在我的案例中真正发生的事情是我不明白的事情:

$>git rebase master
First, rewinding head to replay your work on top of it...
Applying: myFirstCommitDoneOnTheBranch
Applying: myOtherCommitDoneOnTheBranch
$>git status
On branch feature/branch
Your branch and 'origin/feature/feature' have diverged,
and have 27 and 2 different commits each, respectively.
  (use "git pull" to merge the remote branch into yours)
nothing to commit, working tree clean
$>git pull
*load of conflicts*

现在,尽管我能理解他在拉动之后加载了冲突;我不明白需要拉。从逻辑上讲,它应该在分支时回滚到master,保存在分支上的提交,转发到master上的最新提交,然后应用保存的提交。

我不明白Applying消息所引用的内容:什么是应用哪个版本的提交?

4 个答案:

答案 0 :(得分:60)

tl; dr 您应该先使用masterfeature 更新git pullgit pull --rebase 重新定位{在feature之上{1}}。 <{strong> 之后

根据您当前的工作流程,master告诉您的原因是:

  

您的分支机构和&#39;来源/功能&#39;有分歧,   并分别有27个和2个不同的提交。

是因为您的重新定位的git pull分支现在有 25 新提交,无法从feature到达(因为它们来自{{1}上的rebase +)加上 2 提交, 可以从master访问,但具有不同的提交ID。这些提交包含相同的更改(即它们补丁等效)但它们具有不同的SHA-1哈希值,因为它们基于git status中的不同提交而不是您的提交在本地存储库中重新启用它们。

这是一个例子。我们假设这是在<{1}}上feature之前的历史记录

origin/feature

master之后,origin/feature提交了origin/feature

git pull

此时,您在master之上重新A - B - C (master) \ D - E (feature) ,其中适用 git pullmaster

F

与此同时,远程分支A - B - C - F (master, origin/master) \ D - E (feature) 仍然基于提交feature

master

如果您在D上执行E,Git会告诉您,A - B - C - F (master, origin/master) \ D - E (feature) 分支已与origin/feature分歧 3 ({ {1}},CA - B - C - F (master, origin/master) \ \ \ D' - E' (feature) \ D - E (origin/feature) )和 2 git statusfeature)分别提交。

  

请注意,featureorigin/feature包含与FD'相同的更改,但具有不同的提交ID,因为它们已在E'之上重新定位

解决方案是DE D' {/ 1}} {/ 1}} E' D之前E。但是,由于您可能已经F提交但尚未推送到git pull,您可能希望这样做:

master

以避免在feature与您的本地feature之间创建合并提交

关于变基的后果的更新:

根据this comment,我扩展了分支。 master在rebase之后报告featureorigin 分歧的原因是由于rebase带来了对git checkout feature && git pull --rebase 的新提交,加上重写之前推送到origin/feature的提交。

之后考虑的情况,但在之前

feature

此时,git statusfeature指向相同的提交origin/feature - 换句话说,他们会在&#34; 同步&#34 ;.在feature之上重新定位origin/feature之后,历史记录将如下所示:

A - B - C - F (master)
         \
          D - E (feature, origin/feature)

如您所见,featureorigin/feature 分歧,他们的共同祖先是提交E。这是因为feature现在包含来自masterA - B - C - F (master) \ \ \ D' - E' (feature) \ D - E (origin/feature) feature的新提交origin/feature(读作&#34; D prime &#34;和&#34; E prime &#34;)这些提交Cfeature应用于F之上。尽管它们包含相同的更改,但Git认为它们是不同的,因为它们具有不同的提交ID。同时,master仍引用D'E'

此时,您已经重写了历史记录:您已经通过对其进行重新定位来修改现有提交,从而有效地创建了&#34; new&#34;的。

现在,如果您要在D上运行E,这将会发生什么:

F

由于origin/feature执行D + E,这将导致创建合并提交git pull,其父项为feature且{{1 }}

相反,如果您运行了A - B - C - F (master) \ \ \ D' - E'- M (feature) \ / D - E - (origin/feature) (即git pull + git fetch),那么Git会:

  1. 移动git merge以提交ME'E的共同祖先)
  2. git pull --rebase
  3. 申请git fetchgit rebase
  4. 应用featureCfeature
  5. 但是,注意到origin/featureD包含与Eorigin/feature相同的更改,Git会丢弃它们,导致历史记录如下:< / p>

    F

    请注意先前可从D'访问的提交E'如何应用于D'之上,从而导致E'。此时,D会告诉您:

      

    您的分支机构领先于原创/功能&#39;由1提交。

    当然,提交是E

答案 1 :(得分:7)

如果Table 'my_db.wrong_table_name' doesn't existmaster的远程版本是单独更新的,则只需重置您的本地功能分支

feature/branch

然后,如果您想在git checkout feature/branch git fetch origin feature/branch git reset --hard origin/feature/branch 分支中引入更改,

master

答案 2 :(得分:1)

当您在master上重新设置功能分支时,您创建了一堆新提交。但是,您的origin/feature分支仍指向旧分支。这是rebase之后的情况:

C' (feature)
B'
A'
* (master, origin/master)
*
*
| C (origin/feature)
| B
| A
|/
* some base commit

虽然提交A'包含与提交A类似的更改集,但它绝不是相同的提交。它包含一个不同的树,并且具有不同的父级。

现在,当您尝试再次提取feature时,您会尝试创建此历史记录:

* (feature)
|\
C'|
B'|
A'|
* | (master, origin/master)
* |
* |
| C (origin/feature)
| B
| A
|/
* some base commit

您正在合并两个分支,它们引入了非常相似的,不同的喷射变化。除了毫无意义之外,这必然会造成大量冲突。

您需要做的是使用git push -f通知您的上游代表有关rebase的信息。 这将丢失旧历史记录,并将其替换为重写的

另一种方法是避免在已经推送到任何其他存储库的分支上使用git rebase,或者完全避免使用git rebase这是一种更清洁的方法:它会产生历史,而不是像git rebase那样对历史撒谎。这至少是我喜欢的。

答案 3 :(得分:0)

have 27 and 2 different commits each告诉您,您现在有{27}个来自master的新提交和2个新提交,而origin/<yourbranch>中没有这些提交。

由于rebase已大量更改了origin/<yourbranch>,因此它不再与origin/<yourbranch>具有共同基础。因此,您不希望在rebase之后从origin/<yourbranch>提取更改,因为如您所见,所有H ***都会松动。

如果您知道本地分支机构中需要origin/<yourbranch>的变化,那么请在重新定位之前将其拉出来。

如果您确定自上次推送以来没有人更改origin/<yourbranch>(如果这是您自己的功能分支,则可以安全下注),您可以使用push --force将它们再次同步。然后origin/<yourbranch>将再次与您的本地分支具有相同的基础,并且该基数将包含所有最新的master更改。