关于git:master分支和’origin / master’有分歧,如何’分散’分支’?

master branch and 'origin/master' have diverged, how to 'undiverge' branches'?

不知怎的,我的主人和我的起源/主人的分支出现了分歧。事实上,我不想让他们分道扬镳。如何查看这些差异并"合并"它们?


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

1
git log HEAD..origin/master

在拉它之前(fetch+merge)(另请参见"如何让git总是从特定的分支拉?")

当您收到如下信息时:

"Your branch and 'origin/master' have diverged, # and have 1 and 1 different commit(s) each, respectively."

,检查是否需要更新origin。如果origin是最新的,那么当您在本地作出自己的承诺时,一些承诺已从另一个回购协议推送到origin

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

您将commit c基于commit a,因为这是您当时从上游提取的最新工作。

但是,在您试图将其推回到源站之前,其他人推送了commit b。发展史已分道扬镳。

然后可以合并或重新设置基。有关详细信息,请参见pro-git:git分支-重新平衡。

合并

使用git merge命令:

1
$ git merge origin/master

这告诉Git将来自origin/master的更改集成到您的工作中,并创建合并提交。历史图表如下:

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

新的合并commit m有两个父级,每个父级表示一个开发路径,该开发路径导致存储在该commit中的内容。

注意,m后面的历史现在是非线性的。

重碱

使用git-rebase命令:

1
$ git rebase origin/master

这告诉Git重放commit c(您的工作),就好像您是基于commit b而不是a。cvs和subversion用户在提交前更新时,通常会在上游工作的基础上重新调整本地更改。Git只是在commit和rebase步骤之间添加了显式的分离。

历史图表如下:

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

commit c'是由git-rebase命令创建的新commit。它与C有两种不同之处:

  • 它有着不同的历史:B而不是A。
  • 它的内容解释了B和C中的变化;它与合并示例中的m相同。
  • 注意,c'后面的历史仍然是线性的。我们选择(目前)只允许cmake.org/cmake.git中的线性历史。这种方法保留了以前使用的基于CVS的工作流,并可能简化转换。尝试将C'推送到我们的存储库中是可行的(假设您有权限,并且在重新平衡时没有人推)。

    git pull命令提供了一种从源站获取并重新设置本地工作的快捷方式:

    1
    $ git pull --rebase

    这将上述获取和重新平衡步骤组合成一个命令。


    我有过这样的经历,即使在阅读了以上的回答之后,我仍然对造成这种情况的原因感到困惑。我的解决办法是

    1
    git reset --hard origin/master

    然后,这只会将我的(本地)主文件副本(我认为是错误的)重置到正确的点,如(远程)源文件/主文件所示。

    WARNING: You will lose all changes not yet pushed to origin/master.


    1
    git pull --rebase origin/master

    是一个可以在大部分时间帮助您的命令。

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


    当我尝试重新平衡跟踪远程分支的分支时,我发现自己处于这种情况,我尝试在master上重新平衡它。在这种情况下,如果你尝试重新平衡,你很可能会发现你的分支分叉,它会造成一个混乱,而不是吉特努比!

    假设你在我的远程跟踪分支上,它是从master分支的。

    BLCK1

    现在,您正试图从master重新设置为:

    墨水

    现在停下来,省去一些麻烦!相反,使用go as:

    黑色1-2

    是的,您的分支最后会得到额外的提交。但是,除非您准备使用"不分散"的分支,否则这将是一个比重新平衡更平滑的工作流。有关更详细的解释,请参阅本博客。

    另一方面,如果您的分支只是一个本地分支(也就是说,还没有被推到任何远程分支),那么您一定要重新平衡(在这种情况下,您的分支不会出现分歧)。

    现在,如果您阅读此内容是因为您已经处于由于这种重新平衡而导致的"分散"场景中,那么您可以使用以下命令从源站(即处于未分散状态)返回到最后一次提交:

    黑色1-3


    在我的例子中,我是这样做的:我做了git push,然后做了git commit --amend,在commit消息中添加了一些内容。然后我又做了一个承诺。

    所以在我的例子中,这意味着原点/主节点已经过时了。因为我知道没有其他人接触到原点/主点,所以修复是微不足道的:git push -f(其中-f表示力)


    在我的例子中,我已经将更改推到了EDOCX1,然后意识到我不应该这样做:(由于局部更改是在子树中的,所以这很复杂。所以我回到了"坏"本地更改(使用sourcetree)之前的最后一次好提交,然后得到了"分歧消息"。

    在本地修复了我的混乱之后(细节在这里并不重要),我想"及时地返回"远程EDOCX1-5分支,以便它再次与本地EDOCX1同步。我的解决方案是:

    ZZU1

    注意EDOCX1-8(强制)开关。这删除了错误推送到EDOCX1的"错误更改",现在本地和远程分支同步。

    请记住,这是一个潜在的破坏性操作,因此只有在您100%确定"向后移动"远程主机在时间上是正常的情况下才执行它。


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

    关键是使用--soft,而不是使用苛刻的--hard。如果提交次数超过1次,则可以对HEAD~x进行更改。下面是解决我的情况的所有步骤(我在远程有1个本地提交和8个提交):

    1)git reset --soft HEAD~1撤销本地提交。在接下来的步骤中,我使用了sourcetree中的接口,但我认为以下命令也应该有效:

    2)git stash到stash的变化从1)。现在所有的变化都是安全的,不再有分歧。

    3)git pull获取远程更改。

    4)git stash popgit stash apply应用最后一次隐藏的更改,如果需要,随后执行新的承诺。当想要在本地提交中废弃更改时,此步骤是可选的,还有2)。此外,当想要提交到另一个分支时,应该在切换到所需分支之后完成此步骤。


    要查看差异:

    EDOCX1-10型

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


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

    问题是由运行EDOCX1命令引起的。源代码的更改导致了与本地回购协议的冲突,我解决了这一问题。但是,我没有承诺。此时的解决方案是提交更改(EDOCX1)

    如果在解决冲突后修改了一些文件,那么EDOCX1命令将本地修改显示为未过时的本地修改,并将解决方案合并为阶段性本地修改。这可以通过首先由EDOCX1提交来自合并的更改,然后像往常一样添加和提交未老化的更改(例如由EDOCX1)来正确解决。


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