At Eljakim (my new employer), work repositories are all svn (lowest common denominator), but several of us access them via git-svn. I’ve created a couple of new ones recently, but thanks to timezones, I never get an svn repo until I’ve already done a day’s work (in git). Getting those commits into svn without losing history is a simple thing when you know how – but when I googled, all I saw were strange and crazy hacks involving arcane commands I didn’t understand. So, here’s the easy way:

  • Check out the svn repo
  • git svn clone

  • Make a folder for your work (assuming it’s not already there)
  • cd svn-repo
    mkdir chani
    touch chani/temp
    git add chani/temp
    git ci
    git svn dcommit

  • Check out just that folder
  • cd ..
    git svn clone merge-repo

  • Connect it to the git repo
  • cd merge-repo
    git remote add mygit /path/to/git-repo
    git fetch mygit
    git checkout -b mymerge mygit/master

  • Rebase your work on top of svn
  • git rebase master
    git checkout master
    git merge --ff-only mymerge

  • Clean up the temp file (is thre a way to just commit an empty dir in git?)
  • git rm temp
    git ci

  • And send it to the server!
  • git svn dcommit

  • Switch back to the primary repo (optional)
  • cd ..
    rm -rf merge-repo
    cd svn-repo
    git svn rebase

Of course, you don’t have to delete the merge repo, you could keep using it as your primary repo – but the way things are set up here I always end up wanting my checkout to be a level above that. :)

Edit: Also, make sure you move or delete the original git repo once the commits are safely in svn. I spent half the day continuing to work in the pure git repo after blogging this… >.< oh well, at least I just had to copy&paste off my blog to fix it. :P

{April 7, 2010}   git branch surgery

Arno just wrote about his solution to forgetting what git branch you’re on. I suffer from the same problem – I’d forget me own head if it wasn’t screwed on – but I came up with a different solution. :)

I’m been using git-svn more and more, to the point where I actually won’t write code without it if I expect the patch to take more than a few hours. I’ve accumulated several of these git-svn repos now (often within svn) and I’ve been getting more comfortable working with git, so I’ve started performing minor branch surgery.

say you were on branch foo yesterday, hacking away at a cool feature. Today, you start thinking about feature bar, and hack a bit on that. A few commits later, you remember where you’re committing to, and realise this feature doesn’t belong in that branch. However, it does *depend* on feature foo, or at least you know you’ll be dcommitting foo before bar, so you at least have things in the right order.

Now, first you create a branch to keep bar safe.
git checkout -b bar
now that that’s safe… well, I’m sure there’s a better way to do this, but the *easy* way is to first get rid of foo:
git branch -d foo
then look up the hash of the last commit that actually should belong to foo (copy&paste is your friend):
git log
run over to that commit:
git checkout <hash>
and recreate the branch there:
git checkout -b foo

ta-daa! now branch foo has gone back in time to where it should have ended, and branch bar builds on foo with your latest commits. :) and if you’d forgotten to create bar first, git would have refused to delete foo, so you don’t have to worry much about losing anything to a typo (so long as that typo is not -D. stay away from the dragons ;)

oh, and do remember to go back to branch bar before you continue hacking. :)

et cetera