一周前,我重置了一个“ceph-ansible”的状态。 %current branch中的文件夹,来自相应分支的代码(跟踪github的上游):
# git read-tree --prefix=ceph-ansible/ -u ceph_ansible
然后我做了几处修改,包括:
重命名文件并提交:
# git mv site.yml.sample site.yml
进行了一些更改并提交了
从原始分支机构获取更新:
# git merge -s subtree --squash ceph_ansible
它说:
自动合并ceph-ansible / site.yml.sample
blablabla
壁球提交 - 不更新HEAD
自动合并进展顺利;在按要求提交之前停止
我可以看到"我的"删除了ceph-ansible / site.yml(以及我添加的几个新文件),ceph-ansible / site.yml.sample已恢复,并且不包含我的更改(它刚刚恢复到我改变之前的状态。)
git log ceph_ansible site.yml.sample
显示2016年8月26日(=最新更改ceph-ansible分支),我当前%分支的变化是今年10月,所以它不应该是任何冲突。
我相信这种行为有一些明显的解释。你能帮帮我吗?
更新:我注意到我的git已经很老了(1.8.3)并且是从源代码tarball(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无关-历史'清除错误消息,但合并本身仍然是错误的(我的更改丢失)。
此错误消息可能解释了为什么git无法正确合并(因为这些repos没有任何关系,对吧)。有人可以证实这一点吗?没有"合并 - 子树"真的合并分支?
答案 0 :(得分:1)
我已经将这个问题发布到Git的邮件列表中,很少有人给我一个很好的解释这个行为:
从
ceph_ansible
合并时,没有共享历史记录和git 使用空树作为共同的祖先。我想你可能还没有完全理解
--squash
flag确实...这就是导致你的问题的原因,而不是-s
选项。squash merge接受将从原点合并的提交 分支并将它们压成一个补丁并将它们应用到 当前分支作为新提交...但是这个新提交不是合并 提交(即,当您使用“git show”等查看它时,提交 将只有一个父母,而不是两个 - 或更多 - 父母喜欢正常 合并提交)。
基本上,它是diff plus patch操作的语法糖加上 一些Git善良包裹着它,使它更容易使用。
但最终一旦完成,Git就不知道这个新的提交 与原始分支有任何关系。接下来呢 你合并的时候,Git不知道有一个以前的合并和 它会尝试从头开始合并所有内容而不是从头开始 上一个常见的合并点。
所以要么你必须使用正常的非压缩合并,要么就是你 您不需要在项目中携带ceph_ansible历史记录 在某处记录原始的上游提交(可能在 提交读取树结果时提交消息),然后询问git 在后续合并期间使用它作为合并基础(将会 需要使用管道代码,因为git-merge想要计算合并 基地本身)。
git subtree
命令(来自contrib)允许另一种方式:它 压缩合并子项目的历史(就像使用交互式rebase一样) 'squash'),然后合并这个壁球提交。