Friday, June 19, 2009

git-svn workflow

I've been doing bi-directional git-svn sync for a few weeks now and have finally started to understand how to get the workflow working smoothly, so I wanted to write it down to share with everyone.

There are many git-svn tutorials out there, but unfortunately I found them lacking a little. They either didn't work, or didn't sufficiently explain what they were doing and thus I couldn't reproduce in my situation.

My svn repo is really simple; it's just a trunk/ folder. I had been deploying to production with "svn up". Every once in a while I'd make an urgent change on production and commit it back.

To get started with git, I just did a git-svn clone, then pushed that to a GitHub repo.

The "best practice" workflow seemed to be:

git checkout -b topic-branch
git commit -a -m "made some changes"
git dcommit

And then a

git svn rebase

To get the remote changes from svn into the local branch.

But then I started running into trouble when my git-svn rebase's would start having conflicts. I could tell by the code in the local git branch that I was already up-to-date with the svn repo, but I didn't know how to get "git" to understand this. It seemed to have lost track.

While I am still not exactly sure how this works, I was able to get around it by doing the "git rebase --skip" over and over again until the rebase was done. Then you can compare the files in the git vs svn and see that they're the same to feel confident you're sync'd and up-to-date.

What I've been doing now that seems to work is:

git checkout master
git svn rebase
==> Current branch master is up to date.
git checkout -b feature
git commit -a -m "finished new feature"
git merge master
git checkout master
git svn rebase
==> Current branch master is up to date.
git merge feature
git dcommit

This has been working well. The thing that's very important is that you should only ever "git svn rebase" from the same branch. Things get crazy when you start running that command in multiple branches. I do not claim to understand why (yet). But it is true.

If you're ever out of whack and a bit scared you're gonna hose things up, here are some helpful things I used to see what was up:

To see what dcommit will send to svn, do:
# git svn dcommit --dry-run
Committing to file:///Users/Shared/Development/svnroot/virtualtour/trunk ...
diff-tree 4bbc56e05ecf379bcab2ae155d51fdb04a67bd57~1 4bbc56e05ecf379bcab2ae155d51fdb04a67bd57

The above output shows the diff-tree arguments that will be used to generate the patches sent to svn. You can view the actual diffs with:

# git diff-tree 4bbc56e05ecf379bcab2ae155d51fdb04a67bd57~1 4bbc56e05ecf379bcab2ae155d51fdb04a67bd57 -u

This makes it pretty easy to figure out what git-svn will do without doing it.

Hopefull this info will help someone else out of a jam.

Enjoy,
Alan

1 comments:

  1. I foudn the note about "git svn dcommit --dry-run" and doing "git %s -u" with the lines of output really helpful, thanks!

    I'll also be careful in future to only do "git svnrebase" from the master branch. Afterwards, I'll use git commands to update feature branches from the master..
    ReplyDelete