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?