englebip
englebip

Reputation: 1025

How do I expand a git repository

I have a repository within a subdirectory, and now I would like to have the parent directories under version control too, but keep the current history of the repository.

So with the following tree:

a/b/c

c is currently holding a repository, but I would like to have a repository in a, and include all the history within c.

I'm sure there is a way to go around doing this, perhaps with some git filter-branch? I do not want to use submodules, I would like to have a single repository in the end.

Upvotes: 7

Views: 3522

Answers (3)

Adam Dymitruk
Adam Dymitruk

Reputation: 129624

You have a choice:

You can simply move the current structure into what will be the new structure. Then move the whole repo a level up. git add -A will add all the changes which is a bunch of deletions and new file adds. git status will show them as moved. Each object is stored once, no matter what path it's on so this won't be an expensive operation. This would be the simplest option. At this time you can also put in the other high level directories.

while in c:

mkdir b
cd b
mkdir c
mv <all other objects from top level> c
git add -A
git commit -m "moved everything"
mv c a
# clean up

git will determine the fact that a file was moved if you are doing merges and help you.

Or, you can use filter branch to change history if you like, but all your commits will have different SHA1s. This may be undesireable.

Upvotes: 2

Tobu
Tobu

Reputation: 25436

What you need is to create your new outer repository, and merge the inner one using a subtree merge. There's a quick HOWTO at the bottom of this page.. You should temporarily move c outside of a/b, these instructions expect the c tree doesn't exist at its final location yet.


If you want to make c appear nested in its past history (and are okay with changed sha1s), use filter-branch instead (credit):

git filter-branch --index-filter \
    'git ls-files -s | sed "s#\t#&a/b/c/#" |
            GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
                    git update-index --index-info &&
     mv -T "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' -- --all

Upvotes: 3

Roy Truelove
Roy Truelove

Reputation: 22466

Wouldn't a simple mv work? All of 'c' would just show up as a rename.

Something like this: (please don't cut and paste exactly as I haven't tried this.. just get the gist..)

cp -r /someroot/a/b/c /tmp/tmproot/c    # make a full backup of the given repository
rm -Rf /someroot/a/b/c                  # completely remove c, leaving only a/b
mv -r /someroot/a /tmp/tmproot        # moves a/b to the repository
cd /tmp/tmproot
git mv -r c a/b                         # git-moves c into a/b, so all history of c is retained

now your /tmp/tmproot directory should have a/b/c with the history of c retained

rm /someroot
mv -Rf /tmp/tmproot /someroot               # replace the old rep with your new one

now add everything and commit

Upvotes: 0

Related Questions