master 分支和 'origin/master' 已经发散了,如何' undiverge' 分支'?

Posted

技术标签:

【中文标题】master 分支和 \'origin/master\' 已经发散了,如何\' undiverge\' 分支\'?【英文标题】:master branch and 'origin/master' have diverged, how to 'undiverge' branches'?master 分支和 'origin/master' 已经发散了,如何' undiverge' 分支'? 【发布时间】:2011-01-27 23:26:00 【问题描述】:

不知何故,我的 master 和我的 origin/master 分支出现了分歧。 我其实不希望他们分道扬镳。

如何查看这些差异并合并它们?

【问题讨论】:

发散是什么意思? 推送它之后,你会重新调整你的主人吗? 我收到一条消息,说“您的分支和 'origin/master' 已经分歧,# 并且分别有 1 和 1 个不同的提交。” 我已更新我的答案以反映“分歧”警告信息。 这个博客的解释对我的帮助比下面的任何答案都大:sebgoo.blogspot.com/2012/02/… 在我自己的本地分支“分歧”后撤消对它的所有更改(需要推拉,当我没有做任何更改时,我记得): git reset --hard origin/my-branch 。仅当您知道自己没有进行任何要保留的本地更改时才执行此操作。 【参考方案1】:

您可以review the differences 使用:

git log HEAD..origin/master

pulling it 之前(获取 + 合并)(另见 "How do you get git to always pull from a specific branch?")


当您收到如下消息时:

“您的分支和 'origin/master' 已经分道扬镳,分别有 1 个和 1 个不同的提交。”

,检查你是否need to update origin。如果 origin 是最新的,那么当您在本地进行自己的提交时,一些提交已从另一个仓库推送到 origin

... o ---- o ---- A ---- B  origin/master (upstream work)
                   \
                    C  master (your work)

您将提交 C 基于提交 A,因为那是您当时从上游获取的最新工作。

但是,在您尝试推回原点之前,其他人推送了提交 B。 发展历史已经分道扬镳。

然后您可以合并或变基。详情请见Pro Git: Git Branching - Rebasing。

合并

使用 git 合并命令:

$ git merge origin/master

这告诉 Git 将来自 origin/master 的更改集成到您的工作中并创建一个合并提交。 历史图表现在看起来像这样:

... o ---- o ---- A ---- B  origin/master (upstream work)
                   \      \
                    C ---- M  master (your work)

新的合并,提交 M,有两个父级,每个父级代表一个开发路径,导致存储在该提交中的内容。

请注意,M 背后的历史现在是非线性的。

变基

使用 git rebase 命令:

$ git rebase origin/master

这告诉 Git 重播提交 C(您的工作),就好像您基于提交 B 而不是 A。 CVS 和 Subversion 用户在提交前更新时,通常会在上游工作之上重新调整本地更改。 Git 只是在提交和变基步骤之间添加了明确的分隔。

历史图表现在如下所示:

... o ---- o ---- A ---- B  origin/master (upstream work)
                          \
                           C'  master (your work)

提交 C' 是由 git rebase 命令创建的新提交。 它在两个方面与 C 不同:

    它有不同的历史:B 而不是 A。 它的内容解释了 B 和 C 的变化;它与合并示例中的 M 相同。

请注意,C' 背后的历史仍然是线性的。 我们选择(目前)仅允许 cmake.org/cmake.git 中的线性历史记录。 这种方法保留了以前使用的基于 CVS 的工作流程,并且可以简化过渡。 将 C' 推送到我们的存储库的尝试将起作用(假设您有权限并且在您变基时没有人推送)。

git pull 命令提供了一种从源获取并在其上重新定位本地工作的简写方式:

$ git pull --rebase

这将上述 fetch 和 rebase 步骤组合成一个命令。

【讨论】:

我在查找同样的问题时发现了这个问题,你能解释一下为什么 'git reset --hard HEAD' 没有解决问题吗? @Neth:因为它不是关于分阶段的修改(即修改存在于索引中但尚未提交),而是关于 本地提交(与偏僻的)。 git reset --hard HEAD 只会删除任何本地索引的未提交修改,并且不会协调本地和远程 commits 之间的差异。只有合并或变基才能将两组提交(本地提交和远程提交)放在一起。 哇,感谢您的精彩回复。我们不小心做了一个没有“--rebase”的“git pull”,而“git rebase origin/master”就是解决方法! 怎么样 - 我只想忽略/转储我的本地更改并与远程所在的本地分支一起使用?换句话说,我希望 master 在您的示例中指向 B @CygnusX1 这将是一个git reset --hard origin/master,如下面的答案所述:***.com/a/8476004/6309【参考方案2】:

即使在阅读了上述回复之后,我也有这个问题并且对导致它的原因感到困惑。我的解决方案是做

git reset --hard origin/master

然后这只是将我的(本地)master 副本(我认为它搞砸了)重置到正确的点,由(远程)origin/master 表示。

警告:您将丢失所有尚未推送到 origin/master 的更改。

【讨论】:

是的,感觉有点像傻瓜选项,但如果没有真正的危险并且你来这里是为了快速修复 - 这很有效(无论如何对我来说) 这需要在master分支之前(“git checkout master”)。 嗨skiphoppy,感谢您的提示。我同意 PandaWood 的观点(无意冒犯),这似乎有点像一个傻瓜选项。但话说回来,我对 Git 更高级的方面并没有那么丰富。 origin/master 位是我所需要的——不知何故,我刚刚在本地搞砸了,真的很想恢复原点,但是没有明确的远程名称的重置是行不通的。谢谢! @PedroLoureiro 提交确实丢失了,您仍然可以使用git reflog 找到提交或在gitk --all 中查看它们。但是,硬重置当然不是变基。【参考方案3】:
git pull --rebase origin/master 

是一个可以在大多数情况下为您提供帮助的命令。

编辑:从源站/主站拉取提交并将您的更改应用于新拉取的分支历史记录。

【讨论】:

请说明该命令的作用,否则人们可能会运行它并最终搞砸 如果没有问题,你应该最终得到你的 master 包含所有更改 origin/master 加上你所有的本地提交将在它之上重放。对我来说似乎很好。 除非存在真正的差异并且它会让您处于中止的变基中。 这会产生一个错误:错误:无法合并更改。补丁在 0024 请求和响应模型中失败【参考方案4】:

在我的例子中,我做了什么来导致 diverged 消息:我做了git push,但随后做了git commit --amend 向提交消息添加了一些内容。然后我也做了另一个提交。

所以在我的例子中,这仅仅意味着 origin/master 已经过时了。因为我知道没有其他人在触摸 origin/master,所以修复很简单:git push -f(其中-f 表示强制)

【讨论】:

+1 for git push -f 覆盖之前提交并推送到源的更改。我也确信没有其他人接触过存储库。 非常危险的命令。请写下有关命令风险因素的简短信息。 @Trickster:我已经描述了风险:“因为我知道没有其他人接触过起源/主人”。我相信,在这种情况下,这不是一个冒险的命令。 如果有人在 master 上提交,然后一个人运行命令 git push -f 那么它是高风险命令 感谢您的回答。我的 CI 有一个 git commit --amend 并且会因此而失败。修改本地提交是有意义的,在 CI 中,如果您在提交之前进行修改,那么您在技术上修改了已经推送的远程提交,因此它将其视为一种转移。【参考方案5】:

当我尝试rebase 一个跟踪远程分支的分支时,我发现自己处于这种情况,并且我试图将它重新设置在 master 上。在这种情况下,如果您尝试变基,您很可能会发现您的分支发散,它可能会造成不适合 git nubees 的混乱!

假设您在分支 my_remote_tracking_branch,该分支是从 master 分支的

$ git status

# 在分支 my_remote_tracking_branch

没有提交(工作目录干净)

现在你正试图从 master 变基为:

git rebase master

立即停止,为自己省点麻烦!相反,使用合并:

git 合并大师

是的,您最终会在您的分支上进行额外的提交。但除非你准备好“不分叉”的分支,否则这将是一个比变基更顺畅的工作流程。有关更详细的说明,请参阅 this blog。

另一方面,如果您的分支只是一个本地 分支(即尚未推送到任何远程),您绝对应该做一个变基(并且您的分支不会发散 em> 在这种情况下)。

现在,如果您正在阅读本文是因为您已经 由于此类变基而处于“分歧”场景中,您可以从源返回到最后一次提交(即处于未分歧状态)通过使用:

git reset --hard origin/my_remote_tracking_branch

【讨论】:

一个经验法则是使用rebase,如果您正在变基的分支尚未发布(并且被其他人使用)。否则,请使用merge。如果你对已经发布(和使用)的分支进行变基,你必须协调一个阴谋来重写每个使用过你的分支的开发人员的历史。 很遗憾,在git rebase master... 如果我在分支 'foobar' 上执行 git rebase master ,那么技术上 foobar 与 origin/foobar 不同,直到我执行 git push -f ,对吗? jarrodspillers.com/git/2009/08/19/… git reset --hard origin/my_remote_tracking_branch 是真正有效的方法【参考方案6】:

在我的情况下,这是由于没有提交我的冲突解决方案造成的。

问题是由运行git pull 命令引起的。原点的更改导致与我的本地存储库发生冲突,我解决了。但是,我没有提交它们。此时的解决方案是提交更改(git commit解析的文件)

如果您在解决冲突后还修改了一些文件,git status 命令会将本地修改显示为未暂存的本地修改,并将合并解析显示为暂存的本地修改。这可以通过首先由git commit 提交合并中的更改来正确解决,然后像往常一样添加和提交未暂存的更改(例如,由git commit -a)。

【讨论】:

【参考方案7】:

在我的情况下,我已经将更改推送到 origin/master,然后意识到我不应该这样做 :-( 由于本地更改位于子树中,这很复杂。所以我回到了最后一个好的提交在“糟糕”的本地更改(使用 SourceTree)之前,然后我得到了“分歧消息”。

在本地修复我的混乱之后(这里的细节并不重要),我想“及时回到”远程origin/master 分支,以便它再次与本地master 同步。我的解决方案是:

git push origin master -f

注意-f(强制)开关。这删除了错误地推送到origin/master的“错误更改”,现在本地和远程分支是同步的。

请记住,这是一个具有潜在破坏性的操作,因此只有在您 100% 确定及时“移回”远程主机是可行的情况下才执行此操作。

【讨论】:

总是有用,但肯定不能回答问题。 @ThibaultD。即使没有,这正是我想要的。 我收到了 You are not allowed to force push code to a protected branch on this project. 。我正试图推到我的叉子上。 我不得不取消对 gitlab repo ***.com/questions/32246503/…的保护 是的,我在 master 上有一些不应该存在的提交,如果您不关心删除它们,上述或“git push --force”工作(重写历史和删除)分歧的远程提交)。如果您想保留提交但不在 master 上,则可以将它们移动到另一个分支。【参考方案8】:

查看差异:

git difftool --dir-diff master origin/master

这将显示两个分支之间的更改或差异。在 araxis(我最喜欢的)中,它以文件夹差异样式显示。显示每个更改的文件。然后我可以单击一个文件来查看文件中更改的详细信息。

【讨论】:

git-dir 的有趣使用:+1【参考方案9】:

我知道这里有很多答案,但我认为git reset --soft HEAD~1 值得关注,因为它可以让您在解决分歧状态的同时保留最后一次本地(未推送)提交中的更改。我认为这是一个比使用rebase 拉取更通用的解决方案,因为可以审查本地提交,甚至可以将其移动到另一个分支。

关键是使用--soft,而不是苛刻的--hard。如果有超过 1 个提交,HEAD~x 的变体应该可以工作。所以这里是解决我的情况的所有步骤(我有 1 个本地提交和 8 个远程提交):

1) git reset --soft HEAD~1 撤消本地提交。对于接下来的步骤,我使用了 SourceTree 中的接口,但我认为以下命令也应该可以工作:

2) git stash 存储来自 1) 的更改。现在所有的变化都是安全的,没有分歧了。

3) git pull 获取远程更改。

4) git stash popgit stash apply 应用最后隐藏的更改,然后根据需要进行新的提交。当想要丢弃本地提交中的更改时,此步骤与 2) 一起是可选的。此外,当想要提交到另一个分支时,应在切换到所需的分支后完成此步骤。

【讨论】:

实际上,这些天来,pull --rebase 无论如何都会自动隐藏。 ***.com/a/30209750/6309【参考方案10】:

当我尝试编辑已推送提交的最后一条提交消息时,我收到了相同的消息,使用:git commit --amend -m "New message" 当我使用 git push --force-with-lease repo_name branch_name 推送更改时 没有问题。

【讨论】:

【参考方案11】:

当我基于分支A创建分支时遇到了这个问题

git checkout -b a

然后我将分支a的上游设置为原始分支B

git branch -u origin/B

然后我得到了上面的错误信息。

为我解决这个问题的一种方法是,

删除分支a 创建一个新的分支 b by
git checkout -b b origin/B

【讨论】:

【参考方案12】:

将 123 替换为您的分支偏离原点的提交数。

git reset HEAD~123 && git reset && git checkout . && git clean -fd && git pull

【讨论】:

【参考方案13】:

git reset --soft origin/my_remote_tracking_branch

This way you will not loose your local changes

【讨论】:

【参考方案14】:

我更喜欢更方便、更安全的方式。

# copying your commit(s) to separate branch
git checkout <last_sync_commit>
git checkout -b temp
git cherry-pick <last_local_commit>

git checkout master
git reset --soft HEAD~1 # or how many commits you have only on local machine
git stash               # safer, can be avoided using hard resetting on the above line
git pull
git cherry-pick <last_local_commit>

# deleting temporary branch
git branch -D temp

【讨论】:

有趣。赞成。不要忘记使用git switch 而不是git checkout:***.com/a/57066202/6309。在您的情况下,例如:git switch -c temp &lt;last_sync_commit&gt;【参考方案15】:

我已通过移动到最后提交给 origin/master 的 commit_sha 来修复它。

git reset --hard commit_sha

警告:在“commit_sha”提交之后,您将丢失所有提交的内容。

【讨论】:

【参考方案16】:

我相信这应该对我有所帮助:

git reset --hard origin/master

但事实并非如此,不知何故,我收到了相同的消息,当我从远程分支中提取更改时,冲突正在发生。因为我确信我根本不需要我现有的本地分支,我只需要远程的 master 分支的精确副本,因此我想出了这个解决方案:

结帐到新分支,例如git checkout -b placeholder-branch。注意:这个分支以后可以删除。 git branch -D master,我这样做是因为我确信我的本地分支被搞砸了,我实际上不需要这个,我只需要来自远程实例的新副本。 git checkout --track origin/master 大功告成,现在您可以使用 git branch -D 删除 placeholder-branch

【讨论】:

以上是关于master 分支和 'origin/master' 已经发散了,如何' undiverge' 分支'?的主要内容,如果未能解决你的问题,请参考以下文章

text git error - master分支和'origin / master'分歧了

$ git push -u origin master

Git开发分支管理

git push origin master 遇到的分支问题

如果不再使用本地分支,我应该使用 `git pull --rebase origin master` 还是 `git rebase origin/master`?

git - 您的分支领先于 'origin/master' 1 次提交