我开始在git 1.8.2中学习子树合并。我创建了一个简单的示例来测试对迁移到主项目的第三方仓库的更改。
我正在关注6.7 Git Tools - Subtree Merging示例。
'sub'项目作为'main'项目的子目录包含在内。
在我对'sub'项目进行更改后,当我尝试将更改合并到'main'项目时,git会报告冲突。
测试摘要
合并因冲突而失败。 Merge对要保留的更改行的版本感到困惑。
<<<<<<< HEAD
main
=======
main upstream change
>>>>>>> sub_branch
main.git
sub
sub.git
tm
完成测试脚本
#!/bin/sh
# initialize empty repos
for i in main sub
do
rm -rf $i{,.git}
mkdir $i.git
cd $i.git;
git --bare init;
cd ..;
git clone $i.git
cd $i
echo $i > readme.md
git add readme.md
git commit -a -m "added readme.md"
git push origin master
cd ..
done
# add data to sub
ls > sub/data
cd sub
git add data
git commit -m "Added data"
git push origin master
cd ..
# add sub as a sub-tree in main
cd main
git remote add sub_remote ../sub.git
git fetch sub_remote
git checkout -b sub_branch sub_remote/master
git checkout master
git read-tree --prefix=sub/ -u sub_branch
git commit -m "Added sub"
git push origin master
cd ..
# make change to sub
cd sub
sed -i -e 's/main$/main upstream change/' data
git commit -a -m "upstream change made to data"
git push origin master
cd ..
# merge sub change to main
cd main
git checkout sub_branch
git pull
#merge sub_branch changes into master
git checkout master
git merge -s subtree sub_branch
cat sub/data
答案 0 :(得分:6)
在这种情况下read-tree
正在做的只是在当前树中添加另一棵树的内容。添加此内容就像创建和添加常规文件和目录一样,没有历史记录。所有这些文件都将被视为您创建它们。
当您尝试合并进程失败时,因为它看到sub_branch历史记录创建了data
文件,并且目标目录还包含由您创建的不同data
文件。
您正在使用的页面缺少使子树正常工作的非常重要的步骤,因此您实际上可以对其进行更新。
在这两个页面中都可以看到正确的示例: https://www.kernel.org/pub/software/scm/git/docs/howto/using-merge-subtree.html https://help.github.com/articles/working-with-subtree-merge
在您的案例中缺少的是在创建子树时正确链接历史记录:
# create the merge record but not change anything in your tree yet
git merge -s ours --no-commit sub_branch
# bring the changes and place them in the proper subdirectory
git read-tree --prefix=sub/ -u sub_branch
在此之后,您的main
存储库将包含sub
存储库的历史记录。调用失败的合并现在应该正常工作。调用git log --graph
将让您了解如何合并不同的提交。
答案 1 :(得分:0)
问题在于Git 1.8.2.2(2013年3月)仅仅是引入了会影响git merge -s subtree
的错误的版本。
Subtree Merging section提到的Tim Swast仍然存在问题,应该与Git 2.19(2018年第三季度)更好地配合。
“ git merge -s subtree
”中的自动树匹配已于5年前中断,此后没有人注意到,现已修复。
请参见commit 2ec4150的Jeff King (peff
)(2018年8月2日)。
帮助者:René Scharfe (rscharfe
)。
(由Junio C Hamano -- gitster
--在commit 60858f3中合并,2018年8月17日)
score_trees()
:修复缺少条目的树上的迭代在
score_trees()
中,我们遍历两棵排序的树,以查找哪些条目缺失或两者之间内容不同。
因此,如果我们有两棵树包含这些条目:one two --- --- a a b c c d
我们希望循环能够完成:
- 将“ a”与“ a”进行比较
- 将“ b”与“ c”进行比较;因为这些是排序列表,所以我们知道第二棵树没有“ b”
- 将“ c”与“ c”进行比较
- 将“ d”与列表末尾进行比较;我们知道第一棵树没有“ d”
在有效的d8febde之前(
match-trees
:使用score_trees()
(2013年3月24日,Git 1.8.2.2)简化tree_entry()
。
但是在提交之后,即使每次仅处理一侧的条目,我们都会为每次循环迭代错误地增加树指针。
结果,我们最终这样做:
- 将“ a”与“ a”进行比较
- 将“ b”与“ c”进行比较;我们知道我们没有“ b”,但是我们仍然增加了两个树指针; 目前我们不同步,所有进一步的比较都是错误的
- 将“ c”与“ d”进行比较,并错误地认为第二棵树没有“ c”
- 退出循环,错误地没有意识到第一棵树没有“ d”
因此,与d8febde中的声明相反,我们确实需要手动使用
update_tree_entry()
,因为推进树指针取决于条目比较。这意味着我们必须停止使用
tree_entry()
来访问每个条目,因为它会自动使指针前进。
相反:
- 我们将直接使用
tree_desc.size
来了解是否还有需要看的东西(这是tree_entry()
在幕后所做的事情)- 我们可以直接访问
e1
的“e2
”字段,而不是对“entry
”和“tree_desc
”进行额外的结构分配。