问题
I have a number of subdirectories that I want to pull out into a separate repo. In order to extract these with a single command I move (rename) them to a single subdirectory inside the root.
I then run: git subtree split -P my_new_subdir -b newbranch
If I then checkout this new branch and run git log --follow someoldfile
it only shows me the log entries pertaining to the move into the temporary subdirectory. I want to carry over the full history of those files.
Is there a way to preserve full history, including renames when doing a subtree split? Is there another means of achieving the desired outcome?
I have considered using filter-branch on a clone of the repo but I know that will be very slow.
回答1:
Actually it is possible and this issue has been raised here few times although there is no universal way and it looks like you have to compose your own recipe.
If you want just to leave files from my_new_subdir
you need actually to remove all other files by your own. The concept is to use:
git filter-branch --tag-name-filter cat --index-filter \
'git rm -r --cached --ignore-unmatch
unneeded-subdir-1 unneeded-pattern-* unneeded-etc' \
--prune-empty -f -- --all
then to help finding what else have to be deleted you can use sth like:
git log --name-status --all | grep -P '^\w\s+[\S]+$'
or even eg:
git log --name-status --all | grep -P '^\w\s+[\S]+$' | \
sed s/^.// | cut -f 1-2 -d '/' | sort -u
This way you can find all the files/directories (or just first two segments of path in second case) that was present in the repo at anytime. After that you can use following command to clean the repo:
git gc --aggressive
So after moving files to be left into my_new_subdir
I've used combination of above commands to clean up any unneeded files from history. However I still found unrelated merges in the history but in the end I was satisfied with the result. Note that above there is number of parameters to git commands that are crucial to walk through all the history, branches and tags.
To speedup things you can identify the biggest parts of the repo to remove in first iteration then do the git gc --aggressive
. Having i5 CPU and SSD disk it took me about a minute to complete one git filter-branch
iteration and about 1000 history entries has been processed.
来源:https://stackoverflow.com/questions/26304941/follow-renames-when-performing-git-subtree-split