重新基于rebase后,Git分支发生了分歧

187

我已经在本地重新基于一个已经推送的分支。

Git建议我的分支和远程分支已经发生了分歧,并且:

"他们各自有109和73个不同的提交"

推送我的分支是否会解决这个问题 - 也就是说,这种情况在重新基于后是可以预期的吗?


我遇到了同样的问题。我们可以说“正确的做法”是先基于本地分支进行变基,然后再推送吗? - Mher Didaryan
4个回答

233

当您变基(rebase)一个分支时,您必须将任何在要变基的分支上方的提交重写到该分支上。这是因为提交的属性之一是其父提交(或父提交)。当您变基时,您正在更改分支上最早的本地提交的父提交 - 因此通过提交三传递此更改会更改所有本地提交的哈希值。

由于您已经推送了该分支,因此应该将源分支合并而不是对其进行变基。使用-f标志可以“强制推送”您的新分支,但普通推送不起作用,因为分支历史记录的完整性将被破坏。如果您与其他人在此分支上协作,则强制推送是一个坏主意,因为它会导致其他协作者的历史记录突然不匹配。

简而言之 - 如果您不进行协作,请使用push -f推送分支。如果您正在进行协作,请将分支重置为先前状态,然后合并源分支。


5
既然你已经推送了分支,那么你应该合并源分支-为什么呢? - hammett
2
@HamiltonVerissimo Jason的第一句话是:“当您rebase一个分支时,您必须将位于您正在rebase的分支上方的任何提交的提交重写到该分支上。”即使“上面”提交中捕获的更改具有相同的逻辑内容,它们也被应用于不同的基础,因此是具有不同哈希的不同提交。如果其他开发人员从预重新基础的分支工作,则执行git push -f将极大地干扰其工作流程。因此,既然这个分支已经推送到公共源,他应该进行合并。 - awolf
9
如果你不确定有没有其他人已经推送了内容,你也可以使用 push --force-with-lease。这样做不会改变原意,让语言更加通俗易懂。 - quadroid
1
@jason-lebrun 合并上游更改的缺点不是你可能会在没有警告的情况下覆盖自己的工作吗?合并冲突是否以与变基相同的方式检测到?例如,如果我从我的分支中删除文件中的某个部分,因为它不再需要,但是其他人对上游的同一部分进行了微小的更改,例如删除一些空格或全局查找/替换操作,那么将其合并到我的分支上是否会用他们微不足道的更改版本替换我的删除操作? - Chris Bloom
1
将另一个分支合并到您的分支中不是一个坏主意吗?例如,将主分支合并到功能分支中 - 这样做不会创建一个新的提交吗?一旦将此功能分支合并到主分支上,这不会导致额外的提交吗? - Ross
显示剩余2条评论

83

你的所有提交都更改了 IDs,因此分歧并不是真正的分叉。

为了解决问题,你需要覆盖你的远程分支:

git push -f origin experiment

http://git-scm.com/book/ch3-6.html

解释:

观察这张图片,可以看到在rebase之后C3不是标记为C3,而是标记为C3'。这是因为它虽然不是原来的C3,但包含了所有的代码更改。

Rebase

在这张图片中,当涉及到远程时,可以看到rebase的过程,以及为什么会出现分叉。

diverge and git push

无论如何,在你进行强制push之后,它将告诉你它进行了(强制更新),此时你应该没问题了。

查看顶部链接,搜索“git push --force”,您将看到更详细的解释。


5
是的。我想这解决了问题。 但是,当你在团队中工作时,强制推送可能无法正常工作,因为你的推送可能会覆盖其他人最近推送的任何工作。我说得对吗? - Hari Krishna Ganji
1
在进行变基之前,请确保您将更改“快进”合并。这可能不会产生所需的效果。 - mimoralea

7

我通过以下方法成功推送重命名提交:


git checkout mybranch
git pull
git push origin mybranch

拉取操作解决了分歧。

在拉取操作之前

Your branch and 'origin/mybranch' have diverged,
and have 2 and 1 different commit(s) each, respectively.

PULL输出

递归合并。mypath/myfile.py | 12 +++++++++++- 1个文件已更改,11次插入(+),1次删除(-)

PULL之后

您的分支领先于“origin/mybranch”3个提交。

PUSH之后

mybranch比仍有一个未处理的拉取请求的分支领先了3个提交, 合并信息添加到提交历史记录中Merge branch mybranch of remote into mybranch

我认为这可能就是强制PUSH所做的事情,但我还没有验证过。

正如其他人所说,如果您已经有一个打开的拉取请求,请避免使用rebase。我提供这个示例作为对我有效的内容。


6
可以通过将目标分支变基到当前本地分支,切换到目标分支,然后将本地分支变基到目标分支来解决此问题,而无需强制推送。由于可能缺失的提交已经添加且不需要再创建,因此这不会产生分歧。以下是更易于理解的示例:
  1. 主分支是 develop
  2. 您检出新分支feature/doing_stuff
  3. 团队成员向develop推送了一个新提交

如果您还没有更新自己的develop分支,则“git checkout develop”和“git rebase feature/doing_stuff”将正确工作,因为自您检出以来没有添加任何提交。但是,如果您已经检出了develop并拉取了新的提交,则在尝试变基时会看到此分歧。在团队环境中通常不建议强制推送,因此可以使用以下简单方法进行修复:

  1. git checkout feature/doing_stuff
  2. git rebase develop
  3. git checkout develop
  4. git rebase feature/doing_stuff

第2步中的变基将缺失的提交带入feature/doing_stuff,因此当进行第4步时,它已为更改更新且不需要创建新提交。

我知道这是可行的解决方案,因为我刚刚遇到了这个问题,并执行了上述步骤以成功推送develop而不强制。我在一个由50多名开发人员组成的团队中工作,因此禁止强制推送除自己测试分支之外的任何内容,所以我必须找到一个解决方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接