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:
oss/repo with the good and clean stuff to configure all the servers I manage;
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
# 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
# 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
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.