[英]master branch and 'origin/master' have diverged, how to 'undiverge' branches'?
不知何故,我的master
和我的origin/master
分支已经分道扬镳了。
我其实不希望他们分道扬镳。
如何查看这些差异并将它们合并?
您可以通过以下方式查看差异:
git log HEAD..origin/master
在拉取之前(获取 + 合并)(另请参阅“如何让 git 始终从特定分支拉取?” )
当您收到如下消息时:
“您的分支和 'origin/master' 已经分歧,分别有 1 个和 1 个不同的提交。”
,检查是否需要更新origin
。 如果origin
是最新的,那么当您在本地进行自己的提交时,一些提交已从另一个仓库推送到origin
。
... o ---- o ---- A ---- B origin/master (upstream work)
\
C master (your work)
您基于提交 A 提交 C,因为那是您当时从上游获取的最新工作。
但是,在您尝试推回原点之前,其他人推送了提交 B。
发展历史已经分道扬镳。
然后,您可以合并或变基。 有关详细信息,请参阅Pro Git:Git 分支 - 变基。
合并
使用 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 不同:
请注意,C' 背后的历史仍然是线性的。
我们选择(目前)在cmake.org/cmake.git
中只允许线性历史。
这种方法保留了以前使用的基于 CVS 的工作流程,并且可以简化过渡。
将 C' 推送到我们的存储库的尝试将起作用(假设您有权限并且在您变基时没有人推送)。
git pull 命令提供了一种从源获取并在其上重新定位本地工作的简写方式:
$ git pull --rebase
这将上述 fetch 和 rebase 步骤组合成一个命令。
即使在阅读了上述回复之后,我也有这个问题并且对导致它的原因感到困惑。 我的解决方案是
git reset --hard origin/master
然后,这只是将我的(本地)master 副本(我假设它搞砸了)重置到正确的点,如(远程)origin/master 所示。
警告:您将丢失尚未推送到
origin/master
的所有更改。
git pull --rebase origin/master
是一个可以在大多数情况下为您提供帮助的命令。
编辑:从 origin/master 拉取提交并将您的更改应用于新拉取的分支历史记录。
当我尝试重新定位一个跟踪远程分支的分支时,我发现自己处于这种情况,并且我试图在 master 上重新定位它。 在这种情况下,如果您尝试 rebase,您很可能会发现您的分支出现分歧,并且可能会造成不适合 git nubees 的混乱!
假设您在分支 my_remote_tracking_branch 上,该分支是从 master 分支的
$ git status
# 在分支 my_remote_tracking_branch
没有什么可提交的(工作目录干净)
现在你正试图从 master 变基为:
git rebase 大师
立即停止并为自己省点麻烦! 相反,使用合并:
git 合并大师
是的,你最终会在你的分支上得到额外的提交。 但是除非你准备好“不发散”的分支,否则这将是一个比 rebase 更顺畅的工作流程。 有关更详细的说明,请参阅此博客。
另一方面,如果您的分支只是一个本地分支(即尚未推送到任何远程),您绝对应该做一个 rebase(在这种情况下您的分支不会发散)。
现在,如果您正在阅读本文,因为您已经由于这种变基而处于“分歧”场景,您可以使用以下方法从原始提交(即处于未分歧状态)返回到最后一次提交:
git reset --hard origin/my_remote_tracking_branch
在我的情况下,这是我导致消息分歧的原因:我做了git push
但随后做了git commit --amend
以向提交消息添加一些内容。 然后我也做了另一个提交。
所以在我的情况下,这仅仅意味着 origin/master 已经过时了。 因为我知道没有其他人在触摸 origin/master,所以修复很简单: git push -f
(其中-f
表示强制)
我相信这应该对我有所帮助:
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
分支在我的情况下,我已经将更改推送到origin/master
,然后意识到我不应该这样做:-( 这很复杂,因为本地更改位于子树中。所以我回到了“糟糕的”本地更改(使用SourceTree),然后我得到了“分歧消息”。
在本地修复我的混乱之后(这里的细节并不重要),我想“及时移回”远程origin/master
分支,以便它再次与本地master
分支同步。 我的解决方案是:
git push origin master -f
注意-f
(强制)开关。 这删除了错误地推送到origin/master
的“错误更改”,现在本地和远程分支是同步的。
请记住,这是一个潜在的破坏性操作,因此只有在您 100% 确定及时“移回”远程主机是可以的时才执行它。
我知道这里有很多答案,但我认为git reset --soft HEAD~1
值得关注,因为它可以让您在解决分歧状态的同时保留最后一次本地(未推送)提交的更改。 我认为这是一个比 pull with rebase
更通用的解决方案,因为本地提交可以被审查甚至移动到另一个分支。
关键是使用--soft
,而不是苛刻的--hard
。 如果提交超过 1 次,则HEAD~x
的变体应该可以工作。 所以这里是解决我的情况的所有步骤(我有 1 个本地提交和 8 个远程提交):
1) git reset --soft HEAD~1
撤消本地提交。 对于接下来的步骤,我使用了 SourceTree 中的接口,但我认为以下命令也应该可以工作:
2) git stash
从 1) 到 stash 的变化。 现在所有的变化都是安全的,不再有分歧了。
3) git pull
以获取远程更改。
4) git stash pop
或git stash apply
应用最后隐藏的更改,如果需要,然后进行新的提交。 当想要丢弃本地提交中的更改时,此步骤与2)是可选的。 此外,当想要提交到另一个分支时,应在切换到所需的分支后完成此步骤。
我已经通过移动到最后提交给 origin/master 的commit_sha来修复它。
git reset --hard commit_sha
警告:在“commit_sha”提交之后,您将丢失所有提交的内容。
要查看差异:
git difftool --dir-diff master origin/master
这将显示两个分支之间的更改或差异。 在 araxis(我的最爱)中,它以文件夹差异样式显示。 显示每个更改的文件。 然后我可以单击一个文件来查看文件中更改的详细信息。
在我的情况下,这是由于没有提交我的冲突解决方案造成的。
问题是由运行git pull
命令引起的。 原点的更改导致与我的本地存储库发生冲突,我解决了。 但是,我没有提交它们。 此时的解决方案是提交更改( git commit
已解决的文件)
如果您在解决冲突后还修改了一些文件,则git status
命令会将本地修改显示为未暂存的本地修改,并将合并解析显示为暂存的本地修改。 这可以通过首先通过git commit
合并中的更改,然后像往常一样添加和提交未暂存的更改来正确解决(例如,通过git commit -a
)。
将 123 替换为您的分支偏离原点的提交数。
git reset HEAD~123 && git reset && git checkout . && git clean -fd && git pull
git reset --soft origin/my_remote_tracking_branch
This way you will not loose your local changes
为了更直接地回答原始问题,您可以检查实际的冲突差异:
git diff HEAD..origin/master
并使用此信息来决定是将源的更改拉入本地存储库还是将本地更改推送到源。
我更喜欢这样做更方便和更安全的方式。
# 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 commit --amend -m "New message"
当我使用git push --force-with-lease repo_name branch_name
时没有问题。
当我创建一个基于分支 A 的分支时遇到了这个问题
git checkout -b a
然后我将分支a的上游设置为原始分支B
git branch -u origin/B
然后我收到上面的错误消息。
为我解决这个问题的一种方法是,
git checkout -b b origin/B
你可能会遇到这种情况,只从远程拉取 1 条历史记录:
$ git pull --depth=1
fatal: refusing to merge unrelated histories
$ git status
Your branch and 'origin/main' have diverged,
and have 1 and 1 different commits each, respectively.
根据上面的答案,这会导致两个分支分歧到不同的“线”,所以 Git 认为这是不相关的历史。
---a---b---main
\ \
x x x x diverged, cannot be merged anymore
\ \
---?---?---?---c(origin/main)
最后,简单的解决方法是: git reset --hard origin/main
,如果您不关心本地更改,否则您将丢失所有工作。
或尝试git pull --depth=2
。
就我而言,当我将X ver.1提交从分支B推送到其远程跟踪分支remote_B时,我收到了这条消息。然后在我的本地存储库中,我进行了更改并将其修改为相同的提交,即。 X版本 2 。
现在我们在远程仓库提交X ver1并在本地提交X ver.2 。 然后 git 会告诉你警告
您的本地分支和remote_ 分别有 1 个和 1 个不同的提交
要解决这个问题,您有两个选择:
1.从远程跟踪分支中拉取更改。
git reset --hard HEAD
git checkout --track remoteRepoName/branch_name
2.强制将修改后的提交推送到远程仓库。 (仅在推送X ver1提交后没有任何人拉取远程仓库时推荐)
git push -f remote_repo_name remote_branch_name
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.