threads / discuss / 20347

Subtree merging of sub-directories between repositories?

Subject: Subtree merging of sub-directories between repositories?

## tl;dr

4 messages between Aug 2, 2009 and Aug 2, 2009.

replies: 3people: 2as markdown or json

skillzero@gmail.com· Aug 2, 2009, 06:37 UTC · lore

Is it possible to use the subtree merge strategy to import just one directory from a repository into a directory of a different repository? The subtree merge example describes bringing in an entire repository as a directory, but I'm not sure how to adapt that to just import part of the source repository. The repositories are completely different, but repository A has a couple directories I want to import into repository B (along with the history that affected those directories). I may also make changes on either side and it would be nice to be able to re-merge in either direction.

I was thinking I might need something like the git-subtree script, but maybe this can be done with standard git commands?

Avery Pennarun· Aug 2, 2009, 08:30 UTC · re: skillzero@gmail.com · lore

Re: Subtree merging of sub-directories between repositories?

On Sun, Aug 2, 2009 at 2:37 AM, <skillzero@gmail.com> wrote:
Show 12 quoted lines
> Is it possible to use the subtree merge strategy to import just one
> directory from a repository into a directory of a different
> repository? The subtree merge example describes bringing in an entire
> repository as a directory, but I'm not sure how to adapt that to just
> import part of the source repository. The repositories are completely
> different, but repository A has a couple directories I want to import
> into repository B (along with the history that affected those
> directories). I may also make changes on either side and it would be
> nice to be able to re-merge in either direction.
>
> I was thinking I might need something like the git-subtree script, but
> maybe this can be done with standard git commands?

git tracks the history of the entire tree, not each subtree. So if you use the existing set of commit objects in A, then you'll pull in *all* the files of A.

You have basically two choices here:
1) Merge the *entire* history of project A into project B, and during
the merge, delete the files you don't want.  (This will result in a
repo that's about the size of A+B, even if you only keep 1% of the
files, and every change to every file in A will now show up in B's
history.)  Merging future changes from A to B will be relatively easy
(although you'll get conflicts on those files you deleted), but
merging from B back to A will probably make a mess.
2) Use "git subtree split" to take the subdir of A and give it a
history of its own, then merge that history into a subdir of B (using
"git subtree add" or any other subtree merge method you want to use).
You can then git subtree split/merge back and forth between A and B in
the future to copy future changes from one to the other.

The disadvantage of #2 is that git subtree ends up creating new "fake" commit objects for your new shared subproject. If you merge the new subproject back into A, you'll end up with some duplicate commit messages (unless you use --squash).

Hope this helps.
Have fun,
Avery
skillzero@gmail.com· Aug 2, 2009, 18:05 UTC · re: Avery Pennarun · lore

Re: Subtree merging of sub-directories between repositories?

On Sun, Aug 2, 2009 at 1:30 AM, Avery Pennarun<apenwarr@gmail.com> wrote:
Show 38 quoted lines
> On Sun, Aug 2, 2009 at 2:37 AM, <skillzero@gmail.com> wrote:
>> Is it possible to use the subtree merge strategy to import just one
>> directory from a repository into a directory of a different
>> repository? The subtree merge example describes bringing in an entire
>> repository as a directory, but I'm not sure how to adapt that to just
>> import part of the source repository. The repositories are completely
>> different, but repository A has a couple directories I want to import
>> into repository B (along with the history that affected those
>> directories). I may also make changes on either side and it would be
>> nice to be able to re-merge in either direction.
>>
>> I was thinking I might need something like the git-subtree script, but
>> maybe this can be done with standard git commands?
>
> git tracks the history of the entire tree, not each subtree.  So if
> you use the existing set of commit objects in A, then you'll pull in
> *all* the files of A.
>
> You have basically two choices here:
>
> 1) Merge the *entire* history of project A into project B, and during
> the merge, delete the files you don't want.  (This will result in a
> repo that's about the size of A+B, even if you only keep 1% of the
> files, and every change to every file in A will now show up in B's
> history.)  Merging future changes from A to B will be relatively easy
> (although you'll get conflicts on those files you deleted), but
> merging from B back to A will probably make a mess.
>
> 2) Use "git subtree split" to take the subdir of A and give it a
> history of its own, then merge that history into a subdir of B (using
> "git subtree add" or any other subtree merge method you want to use).
> You can then git subtree split/merge back and forth between A and B in
> the future to copy future changes from one to the other.
>
> The disadvantage of #2 is that git subtree ends up creating new "fake"
> commit objects for your new shared subproject.  If you merge the new
> subproject back into A, you'll end up with some duplicate commit
> messages (unless you use --squash).

Thanks for the help. I tried #2 and it sort of worked. The history was imported, but the resulting paths were flattened. Here's what I did:

From repository 1: git subtree split --prefix=A/B/C --rejoin ... printed commit ID 11f1ef890c49634e822a40a818a6ac88bfc50f07

From repository 2: git remote add -f Repo1 /path/to/repo/1 git subtree add --prefix=X/Y/C 11f1ef890c49634e822a40a818a6ac88bfc50f07

If I do 'git log X/Y/C', I only see a single commit:
    Add 'X/Y/C/' from commit '11f1ef890c49634e822a40a818a6ac88bfc50f07'
    git-subtree-dir: X/Y/C
    git-subtree-mainline: 8b07aa647895aa8a7597dc545821bfd195ecaf7f
    git-subtree-split: 11f1ef890c49634e822a40a818a6ac88bfc50f07

The full history doesn't seem to be associated with that directory. If I do 'git log --name-only --topo-order', I see the full history, but the files are listed as:

file.c
and I was expecting to see:
X/Y/C/file.c

Because I'd want to be able to do 'git log X/Y/C' and see all the commits that affect that directory.

Is there a way to import such that the relative paths are retained? So for the above example, since file.c came from A/B/C/file.c in the original repository, I'd want it to show up in the log for X/Y/C/file.c.

Avery Pennarun· Aug 2, 2009, 18:53 UTC · re: skillzero@gmail.com · lore

Re: Subtree merging of sub-directories between repositories?

On Sun, Aug 2, 2009 at 2:05 PM, <skillzero@gmail.com> wrote:
Show 9 quoted lines
> On Sun, Aug 2, 2009 at 1:30 AM, Avery Pennarun<apenwarr@gmail.com> wrote:
>> 2) Use "git subtree split" to take the subdir of A and give it a
>> history of its own, then merge that history into a subdir of B (using
>> "git subtree add" or any other subtree merge method you want to use).
>> You can then git subtree split/merge back and forth between A and B in
>> the future to copy future changes from one to the other.
>
> Thanks for the help. I tried #2 and it sort of worked. The history was
> imported, but the resulting paths were flattened. Here's what I did:
[...]
Show 12 quoted lines
> The full history doesn't seem to be associated with that directory. If
> I do 'git log --name-only --topo-order', I see the full history, but
> the files are listed as:
>
> file.c
>
> and I was expecting to see:
>
> X/Y/C/file.c
>
> Because I'd want to be able to do 'git log X/Y/C' and see all the
> commits that affect that directory.

Yeah, this is a tricky one. Git has all the necessary information to "know" that the files were "moved" from file.c (in the subtree project history) to X/Y/C.file.c (in your superproject). But "git log" doesn't use this information for anything at the moment, and "--follow" doesn't seem to make it work.

Since I don't have the required skills or knowledge to fix git's history following, my hope is that this will magically start working in a future version of git because someone like you gets annoyed with it :)

Have fun,
Avery

← back to recent threads