I work a lot with code that Martin Fowler calls „existing” 🙂 Very often I’d like to refactor it as the files are large with multiple classes inside. The Git codebase is very old, with many, many commits inside. Each commit holds very useful information needed during bug fixing.
As so, I’d like to split the file, preserving code history at the same time. I found that Git is not so smart in such case, but I found very nice blogposts by Raymond Chen, where he describes the whole process – how to split files correctly.
The thing is that I don’t use git console and I think many of you neither. So I decided to repeat the procedure described by Raymond with my code, with my tools and write all my remarks in one post. I hope you will find it useful.
Splitting files in Git: the easy way with misleading commits
Raymond proposed at least three procedures of splitting. Most intuitive and simplest is the one with „misleading commits”. Take a look into the gallery to see how I perform it. I’m using SmartGit that I described briefly here (polish language), but I hope that Git plugin for Visual Studio or any other graphical tool will let you do it just as easy.
Note that splitting file on a feature branch with subsequent squashed merge to master and deletion of the feature branch clears the history.
Git will show the extracted files as completely new and without history that we wanted to preserve! Take a look at the screen below to see how the history looks like when I squash merged my Splitting_TransactionStatement branch to the master and deleted all sub-branches.
If you’re interested in the internals of Git’s mechanisms note that there is a free book about it. Look for chapter 10: Git internals.
In short, the fail happens because Git doesn’t have any complex database that contains information about the history, but rather it compares trees to determine what happened. If the tree is continuous, (we wanted to achieve this by introducing that sub-branches), then Git can determine full history. If it has gaps, then it cannot. By squash commit and removal of sub-branches we broke the tree and our newly extracted files are new for git, with clear history. And I doubt we can do anything about it. If I will know something more, I will let you know.