Merging Raw Source Trees With git

Today I had the “pleasure” to manually merge two versions of the same application that was maintained in two different instances by three different programmers without any version control whatsoever.

The versions were quite different, with directory names changed (for now apparent reason) and all sorts of other funky stuff. Manual merging seemed like the only way to go and I chose git branches as my merging headquarters.

So I had two directories, application_source_a and application_source_b, first things first in application_source_a

git init
git add . && git commit -am 'master'

Next

git checkout -b slave
rm -rf * (careful) && cp /path/to/application_source_b/* .
git add -u && git commit -am 'slave'

There, now I have to branches which I can list with git branch and jump between (git checkout <branch>). I create some short aliases for the session to speed up switching and viewing like so:

alias master=git checkout master
alias slave=git checkout slave
alias tree=git diff-tree master slave --pretty -M -r --abbrev

I start out by switching to master and looking at the tree. And step by step I merge changes from inside the slave by checking out to and fro and bringing in files by using the git checkout <branch> <file|dir> syntax, committing changes in each branch as I go.

Differences in files can be looked at by using the git difftool <branch>:<file> <branch>:<file> -y. And if you’re wondering how to set your default difftool for a repository add a new [diff][/diff] clause to the config file with a tool = vimdiff (or any other tool of your choice) entry (use git config for this).

Now, the sad thing is that when you git diff two files from two branches the files and save changes to the files (which are usually temporary), these changes are not persisted in the repository; at least I have found no way to do this with vimdiff. So I had to rename a file in one branch, bring in the file from another branch, vimdiff it without git involved, and remove the unmerged file after manually merging it.

Once the tree was clean (nothing is output), I did a git merge slave inside the master branch, then git branch -d slave, ending up with a manually merged tree.

git merge would not have worked well in this particular case (it was the first thing I tried) since the structure of the tree has not been kept in sync and there were bits and pieces all over the place.

The most fundamental lesson is – always use version control, no matter how small the project is (it took me two and a half hours to get through a 1000-line application with around 500 static assets). Use services like https://bitbucket.org/ (they seem to offer free private hosting of repositores) if you have no remotely-accessible place to host a repository.

Now, I’m sure there are much more fancy methods of doing this by employing visual tools, for example. What tools do you use? How would you have done this?