- Clone the repo.
- Filter out everything but that one file.
Cloning can be done normally with git clone
. That will work fine on a directory like git clone /path/to/the/repo
. Then remove remote pointing back to the clone.
git clone /path/to/the/repo
git remote rm origin
Then use git filter-branch
to filter out everything but that one file. This is easiest to accomplish with an index filter that deletes all files and then restores just the one.
git rm --cached -qr -- . && git reset -q $GIT_COMMIT -- YOURFILENAME
An index filter works by checking out each individual commit with all the changes staged. You're running this command, and then recommitting it. It first removes all the changes from staging, then restores that one file to its state in that commit. $GIT_COMMIT
is the commit being rewritten. YOURFILENAME
is the file you want to keep.
If you're doing all branches and tags with --all
, add a tag filter which ensures the tags are rewritten. That's as simple as --tag-name-filter cat
. It will not change the content of the tags, but it will ensure they're moved to the rewritten commits.
Finally, you'll want --prune-empty
to remove any now empty commits that didn't involve that file. There will be a lot of them.
Here it is all together.
git filter-branch \
--index-filter 'git rm --cached -qr -- . && git reset -q $GIT_COMMIT -- YOURFILENAME' \
--tag-name-filter cat
--prune-empty \
-- --all
git subtree split
on a renamed directory. – Rockabillygit subtree split ...
andgit filter-branch ...
solutions without success. Those basically only work for subdirectories where everything in it was never altered outside that directory. What I want is a commit & log history that is what you see when you rungit log MyFile.ext
. – Kalgoorlie