Reputation: 6836
I have a long (~2 years) repo with a lots of commits/branches, now for some reasons I need to change the root folder of the repository to one folder above.
Some examples to clarify the concept.
I have my repository inside a folder:
c:\workspace\test\src\
so in my repo has all the changes in files/subfolder of the above one.
I would like to move the repository to:
c:\workspace\test
being able from now on to add all the changes in the test folder mantaining the old repository history..
so all the old commits that are marked in folder "\"
, now should be checked in folder "\src"
for the old commits I can or can not have (it really does not matter) the actual content of the folder..
is that possible?
I hope what I explained is comprehensible..
Upvotes: 6
Views: 7962
Reputation: 101
First, clone your repo so that you can work on it in isolation, and so that your original stays intact in case anything goes wrong here.
git clone --no-hardlinks c:\workspace\test\src c:\sandbox
write a script that makes the appropriate changes at any single commit. I'm not familiar with Windows scripting, but you'll want your script to create a new subdirectory named src
(i.e., c:\sandbox\src
), then move everything except the .git
directory and any .git*
files (e.g., .gitignore
) into that new subdirectory. Ensure that your script will work properly on any commit in the repo, not just on the current state. Then run:
git filter-branch --tree-filter c:\absolute\path\to\your\script
This will cause git to checkout each commit in the repo, run your script, and then replace the commit with the end result. Next, if you have any ignored or uncommitted files, you'll want to copy them into the appropriate places in your new repo. Check to make sure that the filter-branch had the intended effect and the new repo looks how you wanted it to. Once you're sure that you're happy, delete c:\workspace\test
and then move c:\sandbox
to c:\workspace\test
.
I prefer to use --tree-filter
, as shown here, rather than --index-filter
. It's less efficient (since it has to checkout each commit rather than editing the index directly), but I find it much more intuitive. If needed, it will also allow you to make changes to the content of files in the repo (updating absolute paths, perhaps).
Upvotes: 0
Reputation: 60487
git filter-branch --index-filter '
git read-tree $(printf "040000 tree %s\tsrc\n" `git rev-parse HEAD:` | git mktree)
' -- --branches --tags
mv .git ..
cd ..
Do see the docs in those commands; the usage is very straightforward. The advice in filter-branch
's docs about getting it to do its work on a tmpfs is likely to be worthwhile with two years of history to deal with.
You might want to grep -ri c.workspace.test .git
to check for absolute paths in your configs and such, to verify they're still valid.
Upvotes: 0
Reputation: 5659
I think you mean that the top-level directory of your repo is c:\workspace\test\
and you want c:\workspace\test\src\
to be the new top-level directory. First, check that this is the case:
cd c:\workspace\test\src
git rev-parse --show-toplevel #print repo top-level directory
It should print something like c:\workspace\test\
if that is really your top-level directory.
If it is, you can use the git filter-branch
rebasing command to make the 'src' directory the new top-level. Please be careful that this is what you really want to do as it will destructively modify your old history! Any commits affecting this branch will be rebased to contain the src
folder as the new top-level. Back up your current branch first.
cd c:\workspace\test\
git branch oldRoot #this backs up your current branch to a new branch called "oldRoot"
git filter-branch --subdirectory-filter src HEAD #this modifies your history
Warning!!! Note that:
For more info, read the "Making a Subdirectory the New Root" and "The Perils of Rebasing" sections in the Git Book.
Upvotes: 3
Reputation: 62469
Sounds like you should only need to do this:
c:\workspace\test\src
to c:\workspace\src
c:\workspace\test
, which is presumably now emptyc:\workspace\src
to c:\workspace\test
git
repositories don't generally keep a track of their parent directories, so moving the repository from one place to another should be harmless. Now, whatever scripts/build files/whatever you have in your repository that may contain hard-coded paths may be a completely different story...
Upvotes: 0
Reputation: 5018
If I understand correctly your question, if you start from a clean git repo (git status
says 'nothing to commit, working directory clean'), you simply have to move the .git
directory from c:\workspace\test\src\
to c:\workspace\test\
.
Then you have to do a 'big' commit with all files in your new layout. Git will see this new commit as a big move. No new content is needed, as files would be the same. Git will only register the new tree layout (with src
) in his .git
dir.
Re-reading the question make me think you may want to have your old commits available in src
subdirectory
If this is the case, you need to fully rewrite your Git repository history using something like git filter-branch --tree-filter '...'
Upvotes: 0