Git history rewriting

A little off-topic, but I just spent hours trying to get this to work. Basically, I’m moving a bunch of Rails plugins over to github and need to edit the history to move all files up one level. For example, PackR looks like this in SVN:

trunk
  packr
    lib
    tasks
    test
    ...
branches
  3.1
    packr
      lib
      ...

It’s like that so that when you call script/install http://.../packr/trunk/packr it creates the right directory in vendor/plugins. When moving to Git I wanted to remove that superfluous packr directory, and the example in Git’s docs didn’t work for me (kept complaining that it couldn’t stat index.new). Here’s how I got this to work, it’s probably not the most elegant thing since my knowledge of bash scripting and sed is slim to non-existent, but hey it works:

git filter-branch --tree-filter ' \
    for dir in $(git ls-files | \
            sed -r "s/^packr//g" | sed -r "s/[^\/]+$//g"); \
        do mkdir -p .$dir; \
    done; \
    for file in $(git ls-files | sed -r "s/^packr//g"); \
        do mv -f packr$file .$file; \
    done' \
--tag-name-filter 'cat' HEAD

Eh voila, PackR is up on github!

If you’ve enjoyed this article, you might enjoy my recently published book JavaScript Testing Recipes. It’s full of simple techniques for writing modular, maintainable JavaScript apps in the browser and on the server.