gitgit-subtreegit-subrepo

git subtree - merge the whole subrepository with multiple subfolders into the main repository


I have read and used git subtree functionality a lot. Especially are useful these links Add subdirectory of remote repo with git-subtree

If I have main repo:

base/folder1
base/folder2

And I have sub repo (repo2):

base/folder3
base/folder4

I cant change the structure of the folders, as this is inherit from some other SCM platform, and build process expects this folder structure.

How I can use git-subtree to have both of the subfolders (folder3 and folder4) inside my main repo and in the same time to track changes from a subrepo? (that is where git subtree should come into place)

I couldn't find way for this.

Ideally with sub-tree I would like to accomplish a repo with this structure:

base/folder1
base/folder2
base/folder3
base/folder4

I have tried with:

$ git subtree add --prefix . repo2 master --squash
prefix '.' already exists.
$ git subtree add --prefix base repo2 master --squash
prefix 'base' already exists.

If I add into some other folder like "repo2"

  $ git subtree add --prefix repo2 repo2 master --squash

Then this would work but then I would have structure:

base/folder1
base/folder2
base/repo2/folder3
base/repo2/folder4

which is NOT what I want.

Is this possible to achieve with git and subtree functionality?

Thank you


Solution

  • I don't know any simple way to do what you want. Git doesn't really allow working with separate subdirectories. The entity is the entire repository, the unit of work is a commit which includes a copy of the entire working tree. git subtree allows to export/import subdirectories but you need intermediate repositories to store them.

    You can export subfolders from repo2 but you cannot do that in one step — git subtree allows only one prefix. So you need to create two empty intermediate repositories. Let's say their hosting is at <URL>; lets name these new repos r2f3 and r2f4 to remember their content came from repo2 folder3 and f…4 (if <URL> is actually local filesystem or SSH-accessed filesystem the new repos must be bare because you will push into them; repos at Git hostings are always bare).

    First you export subfolders from repo2 into these new repositories:

    $ cd repo2
    $ git subtree push -P base/folder3 <URL>:r2f3
    $ git subtree push -P base/folder4 <URL>:r2f4
    

    The very repo2 stays unchanged except for two new branches, the result of git subtree split ran by git subtree push.

    Now import them into repo1:

    $ cd repo1
    $ git subtree add -P base/folder3 <URL>:r2f3
    $ git subtree add -P base/folder4 <URL>:r2f4
    

    When you have new commits in repo2 you do re-export and re-import:

    $ cd repo2
    $ git subtree push -P base/folder3 <URL>:r2f3
    
    $ cd repo1
    $ git subtree pull -P base/folder3 <URL>:r2f3
    

    When you have new commits in repo1 that touch folder3 or 4 you do re-export and re-import in the reverse direction:

    $ cd repo1
    $ git subtree push -P base/folder4 <URL>:r2f4
    
    $ cd repo2
    $ git subtree pull -P base/folder4 <URL>:r2f4
    

    Cumbersome, yes. But works and could be automated with scripts.