How can I rewrite history so that all files, except the ones I already moved, are in a subdirectory?
Solution 1:
To rewrite the history with the files moved:
If you want the project's history to look as though all files have always been in the directory foo/bar
, then you need to do a little surgery. Use git filter-branch
with the "tree filter" to rewrite the commits so that anywhere foo/bar
doesn't exist, it is created and all files are moved to it:
git filter-branch --prune-empty --tree-filter '
if [ ! -e foo/bar ]; then
mkdir -p foo/bar
git ls-tree --name-only $GIT_COMMIT | xargs -I files mv files foo/bar
fi'
Now the history will be recorded as if all files were always located in foo/bar
.
To see the history of a moved file:
If you just want to see the history of a file that has been moved or renamed at some point in the past, then simply use the --follow
option to git log
:
git log --follow foo/bar/file.c
Solution 2:
To wrap things up here's a short summary of what I did. The command that worked for me was:
if [ ! -e foo/bar ]; then mkdir -p foo/bar; git ls-tree --name-only $GIT_COMMIT | grep -v ^foo$ | xargs -I files mv files foo/bar || echo ""; fi
The echo command that I added at the end ensured that even when mv fails entire command will continue running. It didn't move contents of foo/bar/foo, but I can live with that.
Thanks a lot to Dan Moulding (!!!) and Jefromi for the help.
Solution 3:
Install git-filter-repo:
git clone https://github.com/newren/git-filter-repo/
Add the git-filter-repo executable to your $PATH (see INSTALL.MD for other options):
# this is just an example, you probably want to edit bashrc,
# or add a symlink to ~/bin or /usr/local/bin
PATH=$PATH:${PWD}/git-filter-repo
Now cd
to the git repo that you want to modify, and run:
git filter-repo --to-subdirectory-filter foo/bar