Splitting files while preserving history in git

Have you ever had a file in your git repository which you would like to split, but you also would like to preserve the history of the file?

Here's a way how to do it.

The Problem

We want to move a (two-line) file a.txt inside a git repository to b.txt and c.txt, whereas b.txt contains the first lines of the original file and the c.txt file the second one. You want to preserve the history of these two lines, as a simple git mv a.txt b.txt && cp b.txt c.txt or something similar would cause at least one of the files (the c.txt one in this case) to be a completely new file to git, and therefor have a single commit as history – the creation of it.

I also tested some other ideas, for example a git mv a.txt b.txt && git checkout HEAD a.txt. It results in the same issue.

The solution...

... is a merge conflict! Yuck, you say? No, not at all! It's a really simple merge conflict!

First, you create a branch which causes the merge-conflict later on. Then, you do git mv a.txt b.txt && git commit. You moved the a.txt file now to b.txt, obviously! Now, go to your new branch. The file is still a.txt there. Do a git mv a.txt c.txt && git commit. Maybe you guess what comes next.

Create a merge-conflict by going back to your branch and merging the temporary created branch git merge --no-ff <conflict-branch>. A merge conflict will come up, as you moved a.txt to b.txt one time and to c.txt another time. Now, simply, take both files.

Of course there is also the possibility to delete code in the files inside the branches. Then, you “splitted” the a.txt file into two files but preserved the history.

Awesome!

tags: #git