I am trying to move a single file (call it foo.txt) from one repository to another (unrelated) repository, preserving its history. ebneter's question shows how to do this for a subdirectory. taw's question has some hints and suggestions, but not a step-by-step procedure to follow. jkeating's question looked promising, but didn't work for me. Google searches came up empty for this particular use case. What I am looking for is a clear sequence of commands to accomplish this.
The sequence of commands I started to follow was this:
$ git clone source-repo/ source-repo-copy
$ cd source-repo-copy
$ git filter-branch --tree-filter 'test ! "$@" = "foo.txt" && \
git rm --cached --ignore-unmatch $@ || true' --prune-empty
The logic of my filter command is to git rm
all files that are not foo.txt. I added the || true
to the command to force it to have a zero return value to satisfy filter-branch.
My intention was to set source-repo-copy as a remote for my target repository (target-repo), and assuming git filter-branch
filtered out everything but foo.txt, fetch and merge source-repo-copy into target-repo. Unfortunately, the git filter-branch
command seemed to have no effect. It ran with no errors and appeared to grind through the 600+ commits in source-repo, but when it finished, the git log
and files in source-repo-copy looked the same. Shouldn't all files but foo.txt be missing and all commits that didn't touch it be gone from the log?
At this point I don't know how to proceed. Any suggestions?
This worked for me, but with a whole directory.
As shown here
~$ cd neu
~/neu$ git filter-branch --subdirectory-filter FooBar HEAD
~/neu$ git reset --hard
~/neu$ git remote rm origin
~/neu$ rm -r .git/refs/original/
~/neu$ git reflog expire --expire=now --all
~/neu$ git gc --aggressive
~/neu$ git prune
~/neu$ git remote add origin git://github.com/FooBar/neu.git
EDIT: For a single file:
Filter the directory first:
git filter-branch --prune-empty --subdirectory-filter myDirectory -- --all
Filter the single file:
git filter-branch -f --prune-empty --index-filter "git rm --cached --ignore-unmatch $(git ls-files | grep -v 'keepthisfile.txt')"
Do some cleanup:
git reset --hard
git gc --aggressive
git prune
This should do it.