This question is related to, e.g., How to move files from one git repo to another (not a clone), preserving history Detach (move) subdirectory into separate Git repository but the problem (or at least the solution, I think) is different. I have the following directory structure:
abc/
.git/
def/
file1.txt
file2.txt
xyz/
file3.txt
The directory abc
is the root of a git repository, say repo1
.
What I want is to put file2.txt
in a different repository, repo2
(local and linked to a remote). However, I do not want to move file2.txt
out of the directory (as in the related questions). All other files and folders (def, file1.txt, xyz/*
) have to stay in repo1
.
When I do git commit
or git push
, changes to file1.txt
should go to repo1
and changes to file2.txt
should go to repo2
.
As a workaround, I could make an additional directory in def
and move file2.txt
there, if that makes it any easier. However, I don't want to move file2.txt
out of the current tree.
The history of file2.txt
does not necessarily need to be preserved in this move.
First of all, make sure you commit or stash any change and your work tree is clean. Run git status
to be sure.
It's possible to accomplish your goal in two easy steps.
Create a new empty repo in abc/def
. Configure it to ignore everything but file2.txt
(an any other file you want to process the same way as file2.txt
). Add .gitignore
and file2.txt
to the new repo and commit:
$ cd abc/def
$ git init
$ echo '*' > .gitignore
$ echo '!/file2.txt' >> .gitignore
$ git add .
$ git status
$ git commit
Read carefully the output of git status
and verify it added only the desired files to the repo. Commit if everything is ok or tweak .gitignore
and the index until they reach the state you need.
Go to the abc
repo, add def/file2.txt
and def/.gitignore
to the ignore list of this repo, remove def/file2.txt
from the index and commit:
$ cd ..
$ echo '/def/file2.txt' >> .gitignore
$ echo '/def/.gitignore' >> .gitignore
$ git rm --cached def/file2.txt
$ git status
$ git commit
Again, read the output of git status
before committing.
You can work with both repos as usual. They are independent, they are not linked in any way (apart from the fact that each repo is configured to ignore the files managed by the other one).
If you don't push the inner repo to a remote location, I recommend you to move its .git
directory (the repository itself) somewhere outside the abc
directory to prevent its accidental removal. The command is simple. Inside the abc/def
directory run:
git init --separate-git-dir=/path-where-to-move-the-git-dir
You can run this command line when you create the abc/def
repo or you can run it after that. The data contained in the repo is safe. It only moves the repo to the indicated location.