Reputation: 1025
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
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
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
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