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'
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.
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?