git pull *after* git rebase?

fquxozlt  于 2023-06-20  发布在  Git
关注(0)|答案(6)|浏览(170)

我有一个功能分支和一个主分支。
主分支已经发展,我的意思是有这些更新,以分散尽可能少的主分支。
所以我在两个分支中都有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消息指的是什么:什么是在哪个版本上应用提交?

uoifb46i

uoifb46i1#

    • tl; drmaster上重定feature的基之前,您应该使用git pullgit pull --rebase更新masterfeature。* * 在master之上重新设置feature分支后,无需git pull**。

在您当前的工作流程中,git status告诉您以下内容的原因:
你的分支和'origin/feature'已经偏离了,分别有27和2个不同的提交。
是因为你的rebased feature分支现在有25个新的提交,这些提交无法从origin/feature访问(因为它们来自master上的rebase),加上2个提交,这些提交***********************************************************************************************************************************************************************************这些提交包含相同的更改(即它们是 * 补丁等价 *),但它们有不同的SHA-1哈希值,因为它们基于origin/feature中的不同提交,而不是您在本地存储库中重新基于它们的提交。
举个例子。让我们假设这是您在master上执行git pull之前的历史记录:

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)

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

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

如果你在feature上执行git status,Git会告诉你,你的feature分支已经从origin/feature分支分叉,分别有3FD'E')和2DE)次提交。
请注意,D'E'包含与DE相同的更改,但具有不同的提交ID,因为它们已基于F进行了重定。
解决方案是在masterfeature上执行git pull *,然后 * 在master上重定向feature。但是,由于您可能在feature上有尚未推送到origin的提交,因此您需要执行以下操作:

git checkout feature && git pull --rebase

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

更新rebase的后果:

根据这一评论,我扩展了分歧的分支。git status报告featureorigin/feature在变基后 * diverge * 的原因是因为变基带来了新的提交到feature,加上它 * 重写 * 了以前推送到origin/feature的提交。
考虑一下pull之后,rebase之前的情况:

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已经 * diverged ,它们的共同祖先是commit C。这是因为feature现在包含来自master的新提交F加上D'E'(读作“ D prime ”和“ E prime *”),它们是在F之上应用的提交DE。即使它们包含相同的更改,Git也会认为它们是不同的,因为它们具有不同的提交ID。同时,origin/feature仍然引用DE
在这一点上,你已经 * 重写了历史 *:你已经修改了现有的提交,通过rebased他们,有效地创建“新”的。
现在,如果你在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的共同祖先)
1.应用origin/feature中的DE
1.应用FD'E'
但是,注意到D'E'包含与DE相同的更改,Git会丢弃它们,导致历史如下所示:

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

请注意,提交F(以前可从feature访问)是如何应用于origin/feature之上的,从而导致F'。在这一点上,git status会告诉你:
您的分支比'origin/feature'领先1次提交。
当然,该提交是F'

siotufzp

siotufzp2#

如果masterfeature/branch的远程版本分别是最新的,则只需重置本地特性分支

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

然后如果你想从master分支引入改变,

git rebase origin/master
7y4bm7vi

7y4bm7vi3#

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

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通知上游repo有关rebase的信息。* 这将使旧的历史松散,并以重写的历史取而代之
另一种方法是避免在已经推送到任何其他存储库的分支上使用git rebase,或者完全避免使用git rebase
这是一种更简洁的方法 *:它导致了历史的发生,而不是像git rebase那样讲述关于历史的谎言。至少我喜欢这样

lskq00tm

lskq00tm4#

have 27 and 2 different commits each告诉你,你现在有27个来自master的新提交,还有2个在你的分支中没有的新提交。
因为origin/<yourbranch>已经被rebase大量修改,它不再与origin/<yourbranch>有一个公共的基。因此,您不希望在变基之后从origin/<yourbranch>中提取更改,因为如您所见,所有H***都将丢失。
如果您知道本地分支中需要对origin/<yourbranch>进行更改,那么请在变基之前提取这些更改。
如果你确定自从你上次推送后没有人修改过origin/<yourbranch>(如果这是你自己的特性分支,这是一个安全的赌注),你可以使用push --force再次将它们同步。然后origin/<yourbranch>将再次拥有与本地分支相同的基础,该基础将包含所有最新的master更改。

dvtswwa3

dvtswwa35#

此错误是因为在调用git checkout feature/branch后未调用git fetch origin。为了避免将来出现此错误,您可以按顺序执行以下命令:

git checkout feature/branch
git fetch origin
git rebase master
vxbzzdmp

vxbzzdmp6#

在寻找解决办法。以下为我工作。

git checkout feature/branch
git rebase main
git pull --rebase

在变基之后(尽管我确保我在本地有所有最新的),状态显示我必须再次在我的特性分支上拉下提交。所以我只是确保git pull --rebase和它的工作就像一个魅力。

相关问题