Merging two unrelated repositories
I keep a repository for operations-style stuff. Server configurations, Puppet recipes, old CFEngine stuff, the works.
But for some idiotic reason long lost in time, my DNS setup was in a totally unrelated repository. This didn't make that much sense. Even more stupid: other stuff, unrelated to DNS, was also stored in there.
So I had:
- a
oss/
repo with the good and clean stuff to configure all the servers I manage; - a
dns/
repo with all the DNS configuration stuff, and a bunch of other unrelated configurations.
And the goal: merge the history of the network/dns/
directory in the dns/
repo to the dnssrv/
directory of the oss/
repo.
Like this:
# create a copy of my dns/ repo
git clone dns dns_work && cd dns_work
# remove everything except the network/dns/ directory
git filter-branch --prune-empty --subdirectory-filter network/dns -- --all
# move stuff back to the dnssrv/ directory
git filter-branch -f --prune-empty --tree-filter '
mkdir -p .dnssrv;
mv * .dnssrv;
mv .dnssrv dnssrv
' -- --all
# make sure we clean all the cruft
git gc --aggressive
# ok, prepare to merge
cd ../oss && git remote add dns ../dns_work && git fetch dns
# Merge...
git merge dns/master
# Remove the cruft
git remote rm dns && git gc --aggressive
And with that, all the history of my DNS work is merged back into the oss/
repo in the proper directory.
As a final step, I need to remove the network/dns
commits from the dns/
repo:
# prepare...
cd ../dns
# Remove the old directory and any empty commits lying around
git filter-branch -f --prune-empty --tree-filter 'rm -rf network' HEAD
# Cleanup
git gc --aggressive
Done.
One of the common complaints I hear about git is that it allows you to rewrite the history. Although this operation can be very damaging in a repository that is heavily cloned, banning, or making history rewriting a second-class operation feels like banning hammers because you can harm yourself. Git is a tool, and it should make complex, but at times useful operations like this, easy or at least possible.