git pull *after* git rebase?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42861353/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 04:53:12  来源:igfitidea点击:

git pull *after* git rebase?

gitrebase

提问by tisek

I have a feature branch, and a master branch.

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

Master branch has evolved and I mean to have those updates to diverging as little as possible from master branch.

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

So I git pullin both branches, git checkout feature/branchand finally git rebase master.

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

Now here I either expect everything to work smoothly orconflicts showing up that I need to resolve before continuing rebase until all master commits are re-applied successfully on feature branch.

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

Now what really happened in my case is something I do not understand:

现在在我的情况下真正发生的是我不明白的事情:

$>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*

Now, as much as I can understand he load of conflicts after the pull; I do not understand the need for a pull. Logically, it should rollback to master when it got branched, save the commits made on the branch, forward to latest commit on master and then apply the saved commits.

现在,据我所知,拉动后他有很多冲突;我不明白需要拉。从逻辑上讲,它应该在分支时回滚到 master,保存在分支上所做的提交,转发到 master 上的最新提交,然后应用保存的提交。

I do not understand to what the Applyingmessage refers to: what is applying the commits on which version?

我不明白该Applying消息指的是什么:什么应用了哪个版本的提交?

回答by Enrico Campidoglio

tl;drYou should update both masterand featurewith git pulland git pull --rebasebeforerebasing featureon top of master. There is no need to do agit pullafteryou have rebased your featurebranch on top of master.

文艺青年最爱的你应该同时更新master,并featuregit pullgit pull --rebase以前重订基feature之上master有没有必要做了git pull之后,你已经重订的feature分支之上master

With your current workflow, the reason why git statusis telling you this:

使用您当前的工作流程,原因git status告诉您:

Your branch and 'origin/feature' have diverged, and have 27 and 2 different commits each, respectively.

您的分支和 'origin/feature' 有分歧,分别有 27 次和 2 次不同的提交。

is because your rebased featurebranch now has 25new commits that aren't reachable from origin/feature(since they came from the rebase on master) plus 2commits that arereachable from origin/featurebut have different commit IDs. Those commits contain the same changes (i.e. they're patch equivalent) but they have different SHA-1 hashes because they are based off of a different commit in origin/featurethan the one you rebased them on in your local repository.

是因为你的衍合feature分支现在有25个新提交不是来自可达origin/feature(因为他们从底垫来master加)2所提交这从可达的origin/feature,但有不同的提交的ID。这些提交包含相同的更改(即它们是补丁等效的),但它们具有不同的 SHA-1 哈希值,因为它们基于origin/feature与您在本地存储库中重新基于它们的提交不同的提交。

Here's an example. Let's assume that this is your history beforedoing git pullon master:

这是一个例子。让我们假设这是你的历史之前git pullmaster

A - B - C (master)
         \
          D - E (feature)

After git pull, mastergot commit F:

之后git pullmaster得到提交F

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

At that point, you rebase featureon top of master, which appliesDand E:

在这一点上,您feature基于master适用于DE

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

In the meantime, the remote branch origin/featureis still based off commit C:

同时,远程分支origin/feature仍然基于 commit C

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

If you do a git statuson feature, Git will tell you that your featurebranch has diverged from origin/featurewith 3(F, D', E') and 2(D, E) commits, respectively.

如果您执行git statuson feature,Git 会告诉您您的feature分支已分别origin/feature3( F, D', E') 和2( D, E) 提交不同。

Note that D'and E'contain the same changes as Dand Ebut have different commit IDs because they have been rebased on top of F.

请注意,D'andE'包含与and相同的更改DE但具有不同的提交 ID,因为它们已重新基于F.

The solution is to do git pullon both masterand featurebeforerebasing featureon master. However, since you may have commits on featurethat you haven't yet pushed to origin, you would want to do:

解决的办法是做git pull上都masterfeature之前衍合featuremaster。但是,由于您可能已经提交了feature尚未推送到的提交origin,因此您需要执行以下操作:

git checkout feature && git pull --rebase

to avoid creating a merge commitbetween origin/featureand your local feature.

避免产生合并提交之间origin/feature和当地feature

Update on the consequences of rebasing:

更新重新定位的后果:

In light of this comment, I expanded on the diverging branches. The reason why git statusreports that featureand origin/featuredivergeafter the rebase is due to the fact that rebasing brings in new commits to feature, plus it rewritesthe commits that were previously pushed to origin/feature.

鉴于此评论,我扩展了不同的分支。在 rebase 后git status报告featureorigin/feature分歧的原因是因为 rebase 带来了新的提交feature,而且它重写了之前推送到的提交origin/feature

Consider the situation afterthe pull but beforethe rebase:

审时度势拉,但底垫:

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

At this point, featureand origin/featurepoint to the same commit E—in other words, they're in "sync". After rebasing featureon top of master, history will look like this:

在这一点上,featureorigin/feature指向相同的提交E-换句话说,他们在“同步”。在feature基于之后master,历史将如下所示:

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

As you can see, featureand origin/featurehave diverged, their common ancestor being commit C. This is because featurenow contains the new commit Ffrom masterplus D'and E'(read as "D prime" and "E prime") which are commits Dand Eapplied on top of F. Even though they contain the same changes, Git considers them to be different because they have different commit IDs. Meanwhile, origin/featurestill references Dand E.

正如您所看到的,feature并且origin/feature已经发生分歧,他们的共同祖先是 commit C。这是因为feature现在包含F来自masterplusD'E'(读作“ D prime”和“ E prime”)的新提交,它们是提交DE应用在F. 即使它们包含相同的更改,Git 也会认为它们不同,因为它们具有不同的提交 ID。同时,origin/feature仍然引用DE

At this point, you've rewritten history: you've modified existing commits by virtue of rebasing them, effectively creating "new" ones.

在这一点上,您已经改写了历史:您通过重新设置现有提交修改了它们,有效地创建了“新”提交。

Now, if you were to run git pullon featurethis is what would happen:

现在,如果你要运行git pullfeature会发生什么:

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

Since git pulldoes git fetch+ git merge, this would result in the creation of the merge commit M, whose parents are E'and E.

由于git pullgit fetch+ git merge,这将导致在创建合并的提交M,其父母E'E

If, instead, you ran git pull --rebase(that is, git fetch+ git rebase) then Git would:

相反,如果您运行git pull --rebase(即git fetch+ git rebase),那么 Git 将:

  1. Move featureto commit C(the common ancestor of featureand origin/feature)
  2. Apply Dand Efrom origin/feature
  3. Apply F, D'and E'
  1. 移动feature提交C(的共同祖先featureorigin/feature
  2. 申请DEorigin/feature
  3. 申请FD'E'

However, noticing that D'and E'contain the same changes as Dand E, Git would just discard them, resulting in a history looking like this:

然而,注意到,D'并且E'包含相同的变化DE,Git的也只是将它们丢弃,造成了历史看起来像这样:

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

Notice how commit F, previously reachable from feature, got applied on top of origin/featureresulting in F'. At this point, git statuswould tell you this:

请注意如何提交F,以前从可达feature,得到了应用之上origin/feature产生F'。此时,git status会告诉你:

Your branch is ahead of 'origin/feature' by 1 commit.

您的分支领先于 'origin/feature' 1 次提交。

That commit being, of course, F'.

当然,那个提交是F'.

回答by ashmaroli

If the remote versions of masterand feature/branchare up-to-date individually, then simply reset your local feature branch

如果远程版本master,并feature/branch均达到最新的独立,然后只需重置您的本地特性分支

git checkout feature/branch
git fetch origin feature/branch
git reset --hard origin/feature/branch

then if you want to bring in changes in the masterbranch,

那么如果你想在master分支中引入变化,

git rebase origin/master

回答by Greg Tarsa

The have 27 and 2 different commits eachis telling you that you now have 27 new commits from masterand 2 new commits in your branch that are not present in origin/<yourbranch>.

have 27 and 2 different commits each告诉您,您master的分支中现在有 27 个新提交和 2 个新提交,它们不存在于origin/<yourbranch>.

Because origin/<yourbranch>has been massively changed by the rebase, it no longer has a common base with origin/<yourbranch>. Therefore, you don't want to then pull the changes from origin/<yourbranch>after the rebase, because, as you see, all H*** breaks loose.

因为origin/<yourbranch>已经被 rebase 大规模改变,它不再与origin/<yourbranch>. 因此,您不想origin/<yourbranch>在 rebase之后拉取更改,因为如您所见,所有 H*** 都松动了。

If you know there are changes in origin/<yourbranch>that you need in your local branch, then pull those before you rebase.

如果您知道origin/<yourbranch>本地分支中有您需要的更改,请在变基之前拉取这些更改。

If you are sure no one has changed origin/<yourbranch>since your last push (a safe bet if this is your own feature branch), you can use push --forceto put them into sync again. Then origin/<yourbranch>will again have the same base as your local branch and that base will contain all the latest masterchanges.

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

回答by cmaster - reinstate monica

When you rebased your feature branch on top of master, you created a bunch of new commits. However, your origin/featurebranch is still pointing to the old ones. This is the situation after the rebase:

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

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

While the commit A'contains a similar change set as commit A, it is by no means the same commit. It contains a different tree, and has a different parent.

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

Now, when you try to pull featureagain, you try to create this history:

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

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

You are merging two branches that have introduced very similar, jet different changes. This is bound to create a ton of conflicts, apart from being entirely pointless.

您正在合并两个引入了非常相似、不同的变化的分支。除了完全没有意义之外,这势必会造成大量冲突。

What you need to do is inform your upstream repo about the rebase by using git push -f. This will loose the old history, and replace it with the rewritten one.

您需要做的是使用git push -f. 这将失去旧的历史,并用重写的历史代替它

The alternative is to avoid using git rebaseon branches that you have already pushed to any other repository, or avoid git rebasealtogether. This is the cleaner approach: It results in the history as it has happened, instead of telling lies about history as git rebasedoes. That's at least what I prefer.

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