主分支和“起源/主”已经分开了,如何“使分支不分开”?


964

我的主人和我的原籍/主人分支以某种方式发生了分歧。
我实际上不希望他们分开。

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


2
你所说的分歧是什么意思?推送后,您是否会重新设置母版?
哈森

13
我收到一条消息,说“您的分支和'起源/主'已经分歧,#分别具有1和1个不同的提交。”
Frank

我已经更新了答案,以反映该“不同”的警告消息。
VonC 2010年

接受的答案另一个问题也可能在解决某些情况下,这可能会发挥作用有帮助(比如你想移动你的主人,但它已经被压入):stackoverflow.com/questions/2862590/...
lindes 2012年

8
在这个博客的解释让我无限地超过了任何答复如下:sebgoo.blogspot.com/2012/02/...

Answers:


1013

您可以通过以下方式查看差异

git log HEAD..origin/master

取之前(获取+合并)(另请参见“如何使git始终从特定分支拉取?”


当您收到如下消息时:

“您的分支机构和'起源/主机构'已经分歧,#分别具有1和1个不同的提交。”

,检查是否需要更新origin。如果origin是最新的,则origin当您在本地进行自己的提交时,某些提交已从另一个存储库中推送到其他提交。

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

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

但是,在您尝试将其推回原点之前,其他人则推动了提交B。
开发历史已分成不同的路径。

然后,您可以合并或变基。有关详细信息,请参见Pro Git:Git分支-重新设置。

合并

使用git merge命令:

$ 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有两点不同:

  1. 它具有不同的历史记录:B代替A。
  2. 它的内容说明了B和C的变化;它与合并示例中的M相同。

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

git pull命令提供了一种从原始位置获取信息并以其为基础的本地工作的简便方法:

$ git pull --rebase

这将上述获取和重新设置步骤组合为一个命令。


5
我在查找相同问题时发现了这个问题,您能解释一下为什么'git reset --hard HEAD'不能解决问题吗?
内斯,2010年

12
@Neth:因为它与分阶段的修改(即索引中存在但尚未提交的修改)无关,而是与本地提交(与远程上的提交不同)有关。git reset --hard HEAD只会删除任何本地索引未提交的修改,并且不会协调本地和远程提交之间的差异。只有合并或重新设置才能将两组提交(本地提交和远程提交)组合在一起。
VonC

4
哇,感谢您的出色回应。我们不小心做了一个没有“ --rebase”的“ git pull”,而“ git rebase origin / master”仅仅是解决方法!
mrooney

3
怎么样-我只想忽略/转储我的本地更改,并与我的遥控器所在的本地分支在一起?换句话说,我想master指出B你的例子。
CygnusX1 2012年

23
@ CygnusX1 git reset --hard origin/master就像在下面的答案中提到的那样:stackoverflow.com/a/8476004/6309
VonC 2012年

725

我已经知道了这个问题,并弄不清楚是什么原因造成的,即使在阅读了以上答复之后也是如此。我的解决办法是

git reset --hard origin/master

然后,只需将我的(本地)master副本(我认为是搞砸了)重置为正确的点,如(远程)origin / master所示。

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


21
是的,感觉有点像是假人选项,但是,如果没有真正的危险,并且您在这里快速修复
可行

7
这需要先在master分支上(“ git checkout master”)。
2013年

当我从原点获得最新消息时,这种情况发生了一次,然后其他人强行将其推到原点,这导致先前的原点提交被还原。因此,我的本地分支具有还原的提交,当我尝试从源中获取最新消息时,它说我必须合并。在这种情况下,重置--hard origin /(branch)很有意义,因为问题已在原点得到修复。
Landon Poch 2013年

96
你或许应该提醒用户,这将让他们失去尚未推到原点的所有变化
佩德罗洛雷罗

6
@PedroLoureiro提交已真正丢失,您仍然可以使用git reflog或在中找到它们gitk --all。但是,当然,硬重置不是重新设置基准。
sebkraemer

52
git pull --rebase origin/master 

是一个可以在大多数时间为您提供帮助的命令。

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


89
请提及命令的作用,否则人们可能会运行该命令并最终
搞砸

1
如果没有问题,那么您应该以包含所有更改origin / master的master结束,并且所有本地提交都将在此之上重播。对我来说似乎很好。
PhilippClaßen2013年

7
除非存在实际差异,否则将使您处于中止的基础恢复中。
2015年

这将产生一个错误:错误:无法合并更改。补丁在0024请求和响应模型上失败
IgorGanapolsky

32

当我尝试对正在跟踪远程分支的分支进行重新基准设置时,我发现自己处于这种情况,而我试图将其重新建立在master上。在这种情况下,如果您尝试重新设置基准,您很可能会发现分支发散了,并且会创建一个不适用于git nubees的混乱!

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

$ git status

#在分支my_remote_tracking_branch

无需提交(工作目录干净)

现在,您尝试将master设置为:

git rebase master

立即停止,为自己省去一些麻烦!而是使用merge作为:

git合并大师

是的,您最终将在分支上获得额外的提交。但是,除非您愿意使用“不分叉”的分支,否则工作流程将比重新定支要平稳得多。有关更多详细说明,请参见此博客

另一方面,如果您的分支机构只是本地分支机构(即尚未推送到任何远程分支机构),则一定要进行重新设置基准(在这种情况下,您的分支机构不会分叉)。

现在,如果你正在读这篇文章,因为你已经一个“分歧”的情况,由于这样的底垫中,你可以回到过去的使用从原点(即在未发散状态)承诺:

git reset --hard origin / my_remote_tracking_branch


5
经验法则是,rebase如果您要重新定级的分支尚未发布(并由其他人使用),则使用该规则。否则,请使用merge。如果您对已经发布(和使用过)的分支进行重新定位,则必须协调各种阴谋,以便在使用该分支的每个开发人员之间重写历史记录。
Mikko Rantalainen

1
不幸的是我没有做之前阅读这条消息git rebase master...
维塔利·伊萨耶夫

如果我在分支'foobar'上做git rebase master,那么从技术上讲foobar是与origin / foobar分开的,直到我执行git push -f,对吗?
Relipse


1
git reset --hard origin/my_remote_tracking_branch是真正有效的方法
roothahn

23

在我的情况下,这是我引起差异消息的步骤:我做了,git push但是随后确实git commit --amend在提交消息中添加了一些内容。然后我又做了一次提交。

因此,就我而言,这仅意味着原产地/原产地已经过时。因为我知道没有其他人是感人的起源/主,修复是微不足道的:git push -f (其中-f手段力)


7
+1用于git push -f覆盖先前提交并推送到原始位置的更改。我也确信没有其他人碰过这个仓库。
zacharydl 2014年

4
非常危险的命令。请写下有关该命令的风险因素的简短信息。
J4cK

1
@Trickster:我已经描述了风险:“因为我知道没有其他人在触摸起源/母版”。我认为,在那种情况下,这不是冒险的命令。
达伦·库克

1
如果有人在master上提交命令,然后一个人运行git push -f命令,则它是高风险命令
J4cK

11

以我为例,我将更改推送到origin/master,然后意识到我不应该这样做:-(这很复杂,因为本地更改位于子树中。所以我回到了“坏”本地之前的最后一次提交。更改(使用SourceTree),然后得到“分歧消息”。

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

git push origin master -f

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

请记住,这是一种潜在的破坏性操作,因此仅在您100%确定及时“移回”远程主站就可以了。


总是有用的,但肯定不能回答问题。
Thibault D.

1
@ThibaultD。即使没有,这正是我想要的。
尼尔·乔杜里

我正在You are not allowed to force push code to a protected branch on this project.。我正在努力推我的叉子。
BanAnanas

我不得不对gitlab回购取消保护 stackoverflow.com/questions/32246503/...
BanAnanas

5

我知道这里有很多答案,但是我认为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反正会自动隐藏。stackoverflow.com/a/30209750/6309
VonC

4

要查看差异:

git difftool --dir-diff master origin/master

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


1
有趣的git-dir使用:+1
VonC

3

就我而言,这是由于未提交我的冲突解决方案引起的。

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

如果自解决冲突以来还修改了某些文件,该git status命令将把本地修改显示为未暂存的本地修改,并将合并解析显示为已暂存的本地修改。可以通过以下方法正确解决此问题:首先通过提交来自合并的更改git commit,然后像往常一样(例如,通过添加和提交未分级的更改git commit -a)。


0

当我尝试编辑上次提交的消息时,我有相同的消息,即使用已推送的提交:git commit --amend -m "New message" 当我使用git push --force-with-lease repo_name branch_name 进行更改时,没有问题。


0

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

git checkout -b a

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

git branch -u origin/B

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

为我解决此问题的一种方法是

  • 删除分支
  • 创建一个新的分支b
git checkout -b b origin/B
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.