ChatGPT解决这个技术问题 Extra ChatGPT

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

不知何故,我的 master 和我的 origin/master 分支出现了分歧。
我实际上不希望它们分歧。

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

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

N
Nima Mehanian

您可以通过以下方式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)

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

但是,在您尝试推回原点之前,其他人推了提交 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 只会删除任何本地索引的未提交修改,并且不会协调本地和远程 提交 之间的差异。只有合并或变基才能将两组提交(本地提交和远程提交)放在一起。
哇,谢谢你这么棒的回复。我们不小心做了一个没有“--rebase”的“git pull”,而“git rebase origin/master”就是解决方法!
怎么样 - 我只想忽略/转储我的本地更改并与远程所在的本地分支一起使用?换句话说,我希望 master 在您的示例中指向 B
@CygnusX1 这将是一个 git reset --hard origin/master,如下面的答案所述:stackoverflow.com/a/8476004/6309
J
Jalal

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

git reset --hard origin/master

然后,这只是将我的(本地)master 副本(我假设它搞砸了)重置到正确的点,如(远程)origin/master 所示。

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


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

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

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


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

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

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

git status # 在分支上 my_remote_tracking_branch 没有提交(工作目录干净)

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

git rebase 大师

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

git 合并大师

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

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

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

git reset --hard origin/my_remote_tracking_branch


如果您要变基的分支尚未发布(并被其他人使用),则经验法则是使用 rebase。否则,使用 merge。如果你对已经发布(和使用)的分支进行变基,你必须协调一个阴谋来重写每个使用你的分支的开发人员的历史。
不幸的是,在执行 git rebase master 之前我没有阅读此消息...
如果我在分支 'foobar' 上执行 git rebase master ,那么技术上 foobar 与 origin/foobar 不同,直到我执行 git push -f ,对吗?
git reset --hard origin/my_remote_tracking_branch 是真正有效的
D
Darren Cook

就我而言,这是我为导致 diverged 消息所做的事情:我做了 git push,但随后做了 git commit --amend 以在提交消息中添加一些内容。然后我也做了另一个提交。

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


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

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

git reset --hard origin/master

但它没有,不知何故我得到了同样的信息&一旦我从远程分支中提取更改,冲突就发生了。因为我确信我根本不需要我现有的本地分支机构 &我只需要远程的 master 分支的精确副本,因此我想出了这个解决方案:

结帐到新分支,例如 git checkout -b placeholder-branch。注意:此分支可以稍后删除。

git branch -D master,我这样做是因为我确信我的本地分支被搞砸了,我实际上不需要这个,我只需要来自远程实例的新副本。

git checkout --track origin/master & 你已经完成了,现在你可以使用 git branch -D 删除占位符分支


L
Laryx Decidua

就我而言,我已将更改推送到 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 stackoverflow.com/questions/32246503/… 的保护
是的,我在 master 上有一些不应该存在的提交,如果您不关心删除它们,上述或“git push --force”可以工作(重写历史并删除分散的远程提交)。如果您想保留提交但不在 master 上,则可以将它们移动到另一个分支。
B
Bianca Daniciuc

我知道这里有很多答案,但我认为 git reset --soft HEAD~1 值得关注,因为它可以让您在解决分歧状态的同时保留上一次 local(未推送)提交中的更改。我认为这是一个比使用 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 无论如何都会自动隐藏。 stackoverflow.com/a/30209750/6309
S
Shohin

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

git reset --hard commit_sha

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


C
C Johnson

要查看差异:

git difftool --dir-diff master origin/master

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


git-dir 的有趣用法:+1
M
Matt Bond

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

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

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


d
dsmith63

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

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

G
GPopat

git reset --soft origin/my_remote_tracking_branch

This way you will not loose your local changes

H
Hashim Aziz

为了更直接地回答原始问题,您可以检查实际的冲突差异:

git diff HEAD..origin/master

并使用此信息来决定是将源的更改拉入本地存储库还是将本地更改推送到源。


i
igronus

我更喜欢这样做更方便和更安全的方式。

# 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

L
LoveForDroid

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


J
Jeff Wong

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

git checkout -b a

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

git branch -u origin/B

然后我收到上面的错误消息。

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

删除分支a

创建一个新的分支 b 通过

git checkout -b b origin/B

S
S G

就我而言,当我将 X ver.1 提交从分支 B 推送到其远程跟踪分支 remote_B 时,我收到了这条消息。然后在我的本地存储库中,我进行了更改并将其修改为相同的提交,即 X ver.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

这里有几个问题: 1. 这会用本地 master 覆盖远程 master,从而永远删除任何尚未拉到本地的协作工作。我认为他们想重新组合一个有多个更改的分歧分支,而不是删除一个以支持另一个。 2. 您必须删除分支才能使用 git checkout --track 命令 - 如果分支已经存在,它会发出警告。