Git Subtree Merging reports conflict when merging a simple upstream change

我与影子孤独终老i 提交于 2019-12-01 06:47:40

What read-tree is doing in this case is just adding to a directory in your current tree the contents of another tree. This contents are added just like regular file and directories being created and added, there is no history carried over. All these files will be treated as if you created them.

When you try to merge the process fails since it sees that sub_branch history created the data file, and the target directory also contain a different data file created by you.

The page you are using is missing a very important step to make subtree works properly, so that you can actually be able to pull updates to it.

The proper example can be seen in both these pages: https://www.kernel.org/pub/software/scm/git/docs/howto/using-merge-subtree.html https://help.github.com/articles/working-with-subtree-merge

What it is missing in your case is to properly link the history when you create the subtree:

# 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

After this your main repository will contain the history of the sub repository. Calls to the merge that was failing should now work properly. Calling git log --graph will let you see how the different commits are being merged.

The problem is that Git 1.8.2.2 (March 2013) was just the version introducing a bug which affects git merge -s subtree.
The Subtree Merging section mentioned by Tim Swast, which still has the issue, should work better with Git 2.19 (Q3 2018).

The automatic tree-matching in "git merge -s subtree" was broken 5 years ago and nobody has noticed since then, which is now fixed.

See commit 2ec4150 (02 Aug 2018) by Jeff King (peff).
Helped-by: René Scharfe (rscharfe).
(Merged by Junio C Hamano -- gitster -- in commit 60858f3, 17 Aug 2018)

score_trees(): fix iteration over trees with missing entries

In score_trees(), we walk over two sorted trees to find which entries are missing or have different content between the two.
So if we have two trees with these entries:

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

we'd expect the loop to:

  • compare "a" to "a"
  • compare "b" to "c"; because these are sorted lists, we know that the second tree does not have "b"
  • compare "c" to "c"
  • compare "d" to end-of-list; we know that the first tree does not have "d"

And prior to d8febde (match-trees: simplify score_trees() using tree_entry(), 2013-03-24, Git 1.8.2.2) that worked.
But after that commit, we mistakenly increment the tree pointers for every loop iteration, even when we've processed the entry for only one side.
As a result, we end up doing this:

  • compare "a" to "a"
  • compare "b" to "c"; we know that we do not have "b", but we still increment both tree pointers; at this point we're out of sync and all further comparisons are wrong
  • compare "c" to "d" and mistakenly claim that the second tree does not have "c"
  • exit the loop, mistakenly not realizing that the first tree does not have "d"

So contrary to the claim in d8febde, we really do need to manually use update_tree_entry(), because advancing the tree pointer depends on the entry comparison.

That means we must stop using tree_entry() to access each entry, since it auto-advances the pointer.
Instead:

  • we'll use tree_desc.size directly to know if there's anything left to look at (which is what tree_entry() was doing under the hood)
  • rather than do an extra struct assignment to "e1" and "e2", we can just access the "entry" field of tree_desc directly.
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!