Ilya Loskutov
Ilya Loskutov

Reputation: 2201

Can git make a guess at what's the merge base when doing a subtree merge and there are no common ancestors?

I'm trying to get my mind around the subtree merge. Let's we need to use one project as a subtree in another one and then have an opportunity to update the first through fetching instruments (and vice versa). Our workflow would be something like that:

$ git init subtree-project
$ cd subtree-project
$ echo foo > foo.TXT
$ git add .
$ git commit -m v1
$ cd ..
$ git init main-project 
$ cd main-project
$ echo boo > boo.TXT
$ git add .
$ git commit -m v1
$ git remote add subtree ../subtree-project
$ git fetch subtree
$ git branch subtree-project-master subtree/master
$ git read-tree --prefix=subtree-directory -u subtree-project-master
$ git commit -am v2 #save a subtree in the master branch

Then the subtree-project was updated (v2). After pulling a new commit into the subtree-project-master branch, I merge it as a subtree (subtree-directory) into the master branch:

$ git merge --squash -s recursive -Xsubtree=subtree-directory subtree-project-master
fatal: refusing to merge unrelated histories

Why does git need the --allow-unrelated-histories flag here? After all, we use a subtree merge and is it not enough for git to silently fulfill fast-forward merging?

Just for clarification of my question: as far as I understand the concept of subtree merge, git in this case can take a guess at what can be regarded as base blob objects for being merged ones. That is, if the main-project borrowed a tree object (and related blob objects) from subtree-project (its v1 state) through the read-tree command, then git can consider that blob objects to be the base for 3-diffing.

I'm almost certain it's a misunderstanding but still need some clarification.

Upvotes: 0

Views: 84

Answers (1)

jthill
jthill

Reputation: 60255

Why does git need the --allow-unrelated-histories flag here?

Because, so far as git can tell, the histories are unrelated. Your original insertion wasn't recorded as a merge, it was done with a no-ancestry read-tree.

Instead, record the merge,

git fetch subtree
# do the first one as a handroll to show git where things go
git merge -s ours --no-commit subtree/master --allow-unrelated-histories
git read-tree -u --prefix=subtree-directory
git commit

and now that git sees what you're doing, you can tell it to do it again:

[... time passes, subtree project changes ...]
git fetch subtree
git merge -s subtree subtree/master

Upvotes: 1

Related Questions