【问题标题】:'git merge -s subtree' works incorrectly'git merge -s subtree' 工作不正确
【发布时间】:2016-10-10 08:32:48
【问题描述】:

一周前,我使用来自相应分支的代码(从 gi​​thub 跟踪上游)重置了 %current% 分支中的“ceph-ansible”文件夹的状态:

# git read-tree --prefix=ceph-ansible/ -u ceph_ansible

然后我提交了一些更改,包括:

  1. 重命名文件并提交:

    # git mv site.yml.sample site.yml
    
  2. 做了一些更改并提交

  3. 通过以下方式从原始分支提取更新:

    # git merge -s subtree --squash ceph_ansible
    

它说:

自动合并 ceph-ansible/site.yml.sample

废话

Squash 提交 -- 不更新 HEAD

自动合并进展顺利;在按要求提交之前停止

我可以看到“我的”ceph-ansible/site.yml 已删除(以及我添加的一些新文件),ceph-ansible/site.yml.sample 已恢复并且不包含我的更改(它只是恢复到我更改之前的状态)。

git log ceph_ansible site.yml.sample 显示 2016 年 8 月 26 日(= ceph-ansible 分支的最新更改),我在 %current% 分支中的更改是今年 10 月,因此也不应该有任何冲突。

我相信这种行为有一些明显的解释。你能帮帮我吗?

更新:我注意到我的 git 已经很老了(1.8.3)并且是从源代码压缩包(2.10.1)构建的。现在的输出是:

# ~/gitbuild/git-2.10.1/git merge -s subtree --squash ceph_ansible
fatal: refusing to merge unrelated histories

快速谷歌搜索显示 (Git refusing to merge unrelated histories ) 默认行为已更改。添加“--allow-unrelated-histories”会清除错误消息,但合并本身仍然是错误的(我的更改丢失了)。

此错误消息可能解释了为什么 git 无法正确合并它(因为这些 repos 没有任何关系,对吧)。有人可以确认一下吗? “merge -s subtree”真的不会合并分支吗?

【问题讨论】:

  • 其他人(或某物)进行了删除和修改。反过来想一想:假设您对一个文件进行了一系列更改,然后创建了一个 PR。完成 PR 后,您会希望您所做的事情能够反映在目标分支中。好吧,在这种情况下,某人的愿望实现了,但不是你的。
  • @TimBiegeleisen,感谢您的快速回复!这可以完美地解释它,但正如我所写的 git log ceph_ansible site.yml.sample 在 10 月份并没有向我展示任何东西。我如何证明你的想法?
  • 在合并期间,您的一些工作被丢弃,以支持来自另一个分支的版本。至少,我会这样解释(我准备错了)。
  • @TimBiegeleisen,另外 2 个反对该理论的意见:
  • @TimBiegeleisen,对这一理论的另外 2 个观察结果: * 我在“外部”看不到任何变化,这个文件只是恢复到我的变化之前的状态 * 我的其他不相关的变化被丢弃了,谢谢你的想法!

标签: git github


【解决方案1】:

我已将这个问题发布到 Git 的邮件列表中,但很少有好心人给我很好地解释了这种行为:

当你从ceph_ansible合并时,没有共享历史记录,而git 使用空树作为共同祖先。

我想你可能还没有完全理解 --squash 的含义 标志确实...这就是导致您的问题的原因,而不是-s 选项。

壁球合并采用将从原点合并的提交 分支并将它们压缩成一个补丁并将它们应用于 当前分支作为新提交...但是这个新提交不是合并 提交(也就是说,当你用“git show”等查看它时,提交 将只有一个父母,而不是像正常人那样有两个或更多的父母 合并提交)。

基本上,它是差异加补丁操作的语法糖加 一些 Git 的优点使它更易于使用。

但最终一旦你完成了,Git 并不知道这个新的提交 与原始分支有任何关系。所以接下来 合并时,Git 不知道之前有合并,并且 它将尝试从头开始合并所有内容,而不是从 上一个公共合并点。

因此,要么您必须使用普通的非壁球合并,要么,如果您 不想在你的项目中携带 ceph_ansible 历史,你需要 在某处记录原始上游提交(可能在 提交读取树结果时提交消息),然后询问 git 在后续合并期间将其用作合并基础(这将 需要使用管道代码,因为 git-merge 想要计算合并 基地本身)。

git subtree 命令(来自 contrib)允许另一种方式:它 压缩合并子项目的历史(就像使用交互式变基一样 'squash'),然后合并这个 squash 提交。

【讨论】:

    猜你喜欢
    • 2012-07-29
    • 2023-03-20
    • 2015-04-20
    • 2016-01-15
    • 2011-03-14
    • 2018-12-25
    • 1970-01-01
    • 2016-07-26
    • 2011-04-17
    相关资源
    最近更新 更多