4

我开始学习 git 1.8.2 中的子树合并。我创建了一个简单的示例来测试对迁移到主项目的第三方 repo 的更改。

我正在关注6.7 Git Tools - Subtree Merging示例。

“子”项目作为子目录包含在“主”项目中。

在我对“子”项目进行更改后,当我尝试将更改合并到“主”项目中时,git 会报告冲突。

测试总结

  1. 为项目'main'和'sub'创建了repos(sub而不是rack)
  2. 将名为 sub_remote 的远程添加到引用 sub 的 main
  3. 使用 sub_branch 跟踪 sub_remote
  4. 在“子”项目的文件中更改并提交一行
  5. 将更改从 sub 拉到 main/sub_branch
  6. 将 main/sub_branch 合并到 main/master。

合并因冲突而失败。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
4

2 回答 2

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/文章/使用子树合并

在您的情况下缺少的是在创建子树时正确链接历史记录:

# 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将让您看到不同的提交是如何被合并的。

于 2013-04-05T19:02:10.137 回答
0

问题是 Git 1.8.2.2(2013 年 3 月)只是引入了一个影响git merge -s subtree. Tim Swast提到
的子树合并部分仍然存在问题,应该可以更好地与 Git 2.19(2018 年第三季度)一起使用。

" " 中的自动树匹配在git merge -s subtree5 年前就被破坏了,从那时起就没有人注意到了,现在已经修复了。

请参阅Jeff King ( ) 的提交 2ec4150(2018 年 8 月 2 日。 帮助者:René Scharfe ( )(由Junio C Hamano 合并 -- --提交 60858f3中,2018 年 8 月 17 日)peff
rscharfe
gitster

score_trees():修复缺少条目的树的迭代

score_trees()中,我们遍历两棵已排序的树以查找缺少哪些条目或两者之间具有不同内容的条目。
因此,如果我们有两个包含这些条目的树:

one   two
---   ---
a     a
b     c
c     d

我们希望循环:

  • 将“a”与“a”进行比较
  • 将“b”与“c”进行比较;因为这些是排序列表,我们知道第二棵树没有“b”
  • 比较“c”和“c”
  • 将“d”与列表末尾进行比较;我们知道第一棵树没有“d”

并且在d8febde ( match-trees: simple score_trees()using tree_entry(), 2013-03-24, Git 1.8.2.2) 之前有效。
但是在那次提交之后,我们错误地为每次循环迭代增加了树指针,即使我们只处理了一侧的条目
结果,我们最终这样做:

  • 将“a”与“a”进行比较
  • 将“b”与“c”进行比较;我们知道我们没有“b”,但我们仍然递增两个树指针;在这一点上,我们不同步,所有进一步的比较都是错误的
  • 将“c”与“d”进行比较,并错误地声称第二棵树没有“c”
  • 退出循环,错误地没有意识到第一棵树没有“d”

因此,与d8febde中的说法相反,我们确实需要手动使用update_tree_entry(),因为推进树指针取决于条目比较。

这意味着我们必须停止使用tree_entry()来访问每个条目,因为它会自动推进指针。
反而:

  • 我们将tree_desc.size直接使用来了解是否还有其他需要查看的内容(这就是幕后tree_entry()所做的)
  • 我们可以直接访问“ ”字段,而不是对“ e1”和“ ”进行额外的结构分配。e2entrytree_desc
于 2018-08-19T14:06:58.233 回答