Keep git history when splitting a file
The general rule to maintaining blame history is to make a separate move commit first before any edits. It has been my experience that this allows git blame
to work without the need for the -C
option. So in the case of splitting the file up into new files, this can be done in two commits:
- Duplicate the original to the new destinations, making sure to delete the original
- Remove the extra sections from the duplicated files
In the example provided, this would be:
cp a.php b.phpmv a.php c.phpgit add a.php b.php c.phpgit commitvim b.php # delete everything but 1 functionvim c.php # delete the 1 functiongit add b.php c.phpgit commit
I've slightly modified Peter's answer to another question here to create a reusable, non-interactive shell script called git-split.sh
:
#!/bin/shif [[ $# -ne 2 ]] ; then echo "Usage: git-split.sh original copy" exit 0figit mv $1 $2git commit -n -m "Split history $1 to $2"REV=`git rev-parse HEAD`git reset --hard HEAD^git mv $1 tempgit commit -n -m "Split history $1 to $2"git merge $REVgit commit -a -n -m "Split history $1 to $2"git mv temp $1git commit -n -m "Split history $1 to $2"
It simply copies the source file into a new file, and both files have the same history. An explanation why this works can be seen in that other answer
Perhaps this previous SO question could be informative:
How does git track source code moved between files?
To paraphrase the accepted answer: essentially, Git doesn't actually "store" moved code; when generating things like blames for moved code, that's done ex post facto by examining the state of the entire repository from commit to commit.