git pull *after* git rebase?

标签 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*

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

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

最佳答案

tl;博士 您应该同时更新 masterfeaturegit pullgit pull --rebase 之前 rebase feature顶部 master . 没有必要做 git pull 您已重新定位您的 feature顶部的分支 master .

以您当前的工作流程,原因 git status告诉你这个:

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



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

这是一个例子。让我们假设这是你做之前的历史 git pullmaster :
A - B - C (master)
         \
          D - E (feature)

git pull , master得到提交 F :
A - B - C - F (master, origin/master)
         \
          D - E (feature)

在这一点上,你 rebase feature顶部 master , 适用 DE :
A - B - C - F (master, origin/master)
             \
              D - E (feature)

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

如果你做 git statusfeature , Git 会告诉你你的 feature分支已与 origin/feature 分道扬镳与 3 ( 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.



解决办法是做git pull在两个 masterfeature rebase 前 featuremaster .但是,由于您可能已经提交了 feature您还没有推送到 origin ,你会想要做:
git checkout feature && git pull --rebase

避免在 origin/feature 之间创建 merge 提交和您本地的 feature .

更新重新定位的后果:

鉴于this comment ,我在发散的分支上展开。原因git status报告 featureorigin/feature rebase 后出现分歧是因为 rebase 为 feature 带来了新的提交。 ,此外它还重写了之前推送到 origin/feature 的提交。 .

考虑 pull 之后但 rebase 之前的情况:
A - B - C - F (master)
         \
          D - E (feature, origin/feature)

此时,featureorigin/feature指向同一个提交 E ——换句话说,它们处于“同步”状态。 rebase 后 feature顶部 master ,历史将如下所示:
A - B - C - F (master)
         \   \
          \   D' - E' (feature)
           \
             D - E (origin/feature)

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

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

现在,如果您要运行 git pullfeature这就是会发生的事情:
A - B - C - F (master)
         \   \
          \   D' - E'- M (feature)
           \         /
             D - E - (origin/feature)

git pull是否git fetch + git merge ,这将导致创建 merge 提交 M ,其 parent 是 E'E .

相反,如果您运行 git pull --rebase (即 git fetch + git rebase )然后 Git 会:
  • 搬家 feature提交 C (featureorigin/feature 的共同祖先)
  • 申请 DE来自 origin/feature
  • 申请 F , D'E'

  • 但是,请注意 D'E'包含与 D 相同的更改和 E , Git 只会丢弃它们,导致历史看起来像这样:
    A - B - C - F (master)
             \   
              D - E - F' (feature)
                  ^
                 (origin/feature)
    

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

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



    当然,那个提交是 F' .

    关于git pull *after* git rebase?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42861353/

    相关文章:

    git - git reset --hard 和 git clean 的区别

    git - 删除不需要的 merge 提交并使用 Git 改基

    git - 无法解决 rebase 冲突

    java - 在 JGit 获取异常 "org.eclipse.jgit.api.errors.InvalidConfigurationException: No value for key remote"

    ruby-on-rails - Sprockets::CircularDependencyError application.js 已经被要求

    git - 如何使用 groovy 获取 Jenkins 工作的 git scm url

    git - 当我将 mercurial 导出到 git 时,为什么结果这么大?

    merge - Gerrit 在提交补丁集之前总是 rebase 以避免合并提交

    git rebase -i 显示一个空的 MacVim 文件

    git - 如何保留要压缩到另一个提交的时间?