git 拉 *after* git 变基?

git pull *after* git rebase?

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

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

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

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

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

$>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 消息指的是什么:什么在哪个版本上应用提交?

have 27 and 2 different commits each 告诉您现在有来自 master 的 27 个新提交和分支中的 2 个新提交,这些提交在 origin/<yourbranch>.

中不存在

因为 origin/<yourbranch> 已经被 rebase 大量改变,它不再与 origin/<yourbranch> 有共同的基础。因此,您不想在变基后从 origin/<yourbranch> 中提取更改,因为如您所见,所有 H*** 都松动了。

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

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

如果 masterfeature/branch 的远程版本分别是最新的,那么只需重置您的本地功能分支

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

然后,如果您想在 master 分支中进行更改,

git rebase origin/master

tl;dr 您应该将 masterfeature 更新为 git pullgit pull --rebase 重新设置 featuremaster 之上之前。 git pull之后你已经重新设置了featureb运行ch master 的顶部。

在您当前的工作流程中,git status 告诉您的原因是:

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

是因为你的 rebased feature b运行ch 现在有 25 新的提交,这些提交无法从 origin/feature 访问(因为他们来自 master) 上的 rebase 加上 2 提交 可从 origin/feature 访问,但具有不同的提交 ID。这些提交包含相同的更改(即它们是 等效补丁 )但它们具有不同的 SHA-1 哈希,因为它们基于 origin/feature 中的不同提交而不是那个提交您在本地存储库中将它们重新定位。

举个例子。假设这是您的历史 before doing git pull on master:

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

git pull 之后,master 得到了提交 F:

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

此时,您在 master 之上变基 feature 适用 DE

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

与此同时,远程 b运行ch origin/feature 仍然基于提交 C:

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

如果你在 feature 上做 git status,Git 会告诉你你的 feature b运行ch 已经偏离 origin/feature3 (F, D', E') 和 2 (D , E) 分别提交。

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

解决方案是在 masterfeature 之前都做 git pull,然后 在 [=19= 上重新设置 feature ].但是,由于您可能在 feature 上提交了尚未推送到 origin 的内容,因此您需要执行以下操作:

git checkout feature && git pull --rebase

避免在 origin/feature 和本地 feature 之间创建 合并提交

关于变基后果的更新:

根据 ,我扩展了不同的 b运行ches。 git status 报告 featureorigin/feature diverge 的原因是因为 rebase 带来了对 [=20 的新提交=],加上它 重写 之前推送到 origin/feature 的提交。

考虑拉动但变基之前的情况:

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

此时,featureorigin/feature 指向同一个提交 E——换句话说,它们在“sync”。在 master 之上重新设置 feature 后,历史将如下所示:

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

如您所见,featureorigin/feature 分歧 ,它们的共同祖先是提交 C。这是因为 feature 现在包含来自 master 的新提交 F 加上 D'E' (读作“D prime”和“E prime”)是在F之上应用的提交DE。即使它们包含相同的更改,Git 也认为它们是不同的,因为它们具有不同的提交 ID。同时,origin/feature 仍然引用 DE.

此时,您已经重写了历史:您已经通过变基修改了现有的提交,有效地创建了 "new" 个。

现在,如果您在 feature 运行 git pull 会发生以下情况:

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

由于 git pull 执行 git fetch + git merge,这将导致创建合并提交 M,其父级为 E'E.

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

  1. 移动 feature 提交 Cfeatureorigin/feature 的共同祖先)
  2. origin/feature
  3. 应用 DE
  4. 应用FD'E'

但是,注意到 D'E' 包含与 DE 相同的更改,Git 会丢弃它们,从而导致历史看起来像这样:

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

请注意之前可从 feature 访问的提交 F 如何在 origin/feature 之上应用导致 F'。此时,git status 会告诉你:

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

该提交当然是 F'

当您在 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 通知您的上游仓库有关变基的信息。 这将丢失旧历史,并用重写的历史替换它

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

出现这个错误是因为调用了git checkout feature/branch之后还没有调用git fetch origin。为避免以后出现此错误,您可以按顺序执行以下命令:

git checkout feature/branch
git fetch origin
git rebase master