Nesting multiple repos under one repo

Viewed 19

For the past several days I've been trying to consolidate my class's assignment repos by nesting individually under a repo of the class name. Most of the resources I've found so far, or are suggested to me, are designed to merge two peer repos into one. This isn't what I want. My goal is to nest the assignment repos under a class repo both locally and remotely (and as I understand it; submodules would still be remotely distinct repos, which I don't want):

Now:

  1. assignment 1 repo
  2. assignment 2 repo
  3. assignment 3 repo

Desired:

  1. class repo
    • assignment 1 code, branches, commits
    • assignment 2 code, branches, commits
    • assignment 3 code, branches, commits

I attempted to use this article's instructions, repeating step #4 for assignment 2 & 3's repos, but only the master branch was pulled down, and when I run ~/class-repo/assignment-#-repo$ git pull; an error is returned: error: Pulling is not possible because you have unmerged files..

~/class-repo$ git merge --continue doesn't fix this, it returns: error: Committing is not possible because you have unmerged files.

~/class-repo$ git fetch --all hasn't pulled down all branches for each assignment repo.

How do I preserve the commits and branches of each assignment repo while nesting them in this fashion? I keep hitting brick walls, so if it's not possible to do, I understand.

1 Answers

Just to be clear, what you want is possible, if you're willing to make a few compromises. First, we can bundle everything into a single repository.

Let's assume I have three existing repositories assignment1, assignment2, and assignment3.

I can create an aggregate repository:

$ git init all-assignments

And then import the history of the three individual repositories into this aggregate:

$ cd all-assignments
$ git remote add work1 .../url/to/assignment1
$ git remote add work2 .../url/to/assignment2
$ git remote add work3 .../url/to/assignment3
$ git remote update

And then run this script to create local branches from all the remote branches:

git remote | while read remote; do
  git for-each-ref --format='%(refname)' refs/remotes/$remote/ |
  while read ref; do
    name=$(sed "s|refs/remotes/$remote/||" <<<"$ref")
    echo $name
    git branch $remote-$name $ref
  done
done

This gets us something like:

$ git branch
  work1-master
  work1-super-nifty-feature
  work2-master
  work2-update-before-final
  work3-main
  work3-quickstart
  work3-hackathon

We don't have the file organization you wanted, but we do have the repository histories all in a single place, and we can switch branches as necessary to see the content.


If you really want all the files in the same place at the same time, you can do something awful with git subtree. As above, add all the remotes and run git remote update, and then:

git remote | while read remote; do
    git for-each-ref --format='%(refname)' refs/remotes/$remote/ |
    while read ref; do
        name=$(sed "s|refs/remotes/$remote/||" <<<"$ref")
        echo $name
        git subtree add --prefix $remote/$name $ref
    done
done

This results in:

.
├── work1
│   └── master
│   └── super-nifty-feature
├── work2
│   ├── master
│   └── update-before-final
└── work3
    ├── main
    ├── quickstart
    └── hackathon

So now you have everything in one place, but it's all in the same branch, and each former branch now lives in its own directory.

Related