tags:

views:

339

answers:

1

My typical git-svn workflow is:

git checkout -b story-xyz
git commit -a -m "work"
git commit -a -m "more work"
git checkout master
git svn fetch
git merge remotes/trunk
git checkout story-xyz
git rebase master (sometimes with -i)
git checkout master
git merge story-xyz

At this point I have my master and story-xyz branches pointing to the same commit, one or more commits ahead of remotes/trunk. Everything since remotes/trunk is in one linear history.

last svn commit [remotes/trunk] <--- work <--- more work [master, story-xyz]

I then run

git svn dcommit

I expected to see the commits between remotes/trunk and master become Subversion revisions, and end up with a single linear history with remotes/trunk, master and story-xyz all pointing to the latest revision, like so:

last svn commit <--- work <--- more work [master, story-xyz, remotes/trunk]

My Subversion revisions go in fine, but I end up with a two-branched structure. The common root of the branch is the Subversion HEAD before I committed. Both branches contain the same series of commits, in the sense that they contain the same diffs. The branch story-xyz is at the head of one branch, remotes/trunk and master at the other:

last svn commit <--- work <--- more work [master, remotes/trunk]
                  |
                  \- work <--- more work [story-xyz]

The git commits that I had before running git svn dcommit are on the lower branch (story-xyz), with my git commit messages, git user name and email, and git commit timestamps. The commits on the upper branch are new git commits. They use my Subversion username, the timestamp when I ran the dcommit, and the commit messages have the git-svn-id field appended to them.

This is all OK, and I can carry on working. The problem is that I look in gitk and see what looks like an unmerged branch story-xyz. It's pretty hard to tell the difference between a story branch that I have merged back into master, and one that I haven't. The most obvious way to spot it is the duplicate commit messages. I could delete the story-xyz branch, but that feels like I'm not using git properly and I've lost some of my history.

Am I missing something that would stop git-svn from doing this? Or is this just one of the ways that interacting with Subversion dilutes the power and freedom of git?

+2  A: 

I don't think you're really missing anything. You might be doing some unnecessary work, though. In this case, you have two pointers to the "more work" commit, and you are asking git-svn to move one of them. The other one still stays where it is.

You don't really need the master branch. Git-svn doesn't care about what branch you are dcommiting. IIRC, it uses the first svn-remote it can find among the ancestors of the current commit.

I'll offer another version of the workflow:

git checkout -b story-xyz remotes/trunk
git commit -a -m "work"
git commit -a -m "more work"
git svn fetch
git rebase remotes/trunk (with -i, perhaps)
git svn dcommit

This should give you a tree without the extra branch. You need to be careful with fast-forward merges, though.

Antti Rasinen
Thanks, I will try this today. It looks like this will completely remove the need for master - so do you intend that the history of remotes/trunk is now our 'main line' of history?
Alex Scordellis
The history of remotes/trunk is the 'main line' also in your case. Look at your last graph. The history of master is the same as the history of remotes/trunk. Both are equally valid as "main line" -- remotes even more so, because it's the _shared_ main line.You don't have to eliminate master completely. You can just leave it hanging at some earlier point in history. Then if you need to do e.g. one commit, you can checkout master and svn rebase it to the present day.
Antti Rasinen
Yes, that makes sense. I suppose I was too tied to the idea of 'master' being so special that we had to keep it around and up to date. Haven't had a chance to try out your workflow yet, but if it works as expected I'll accept the answer.
Alex Scordellis
Worked, thank you. I've also just worked out why this doesn't leave duplicate commits - thanks to your clear explanation: "In this case, you have two pointers to the "more work" commit, and you are asking git-svn to move one of them. The other one still stays where it is."
Alex Scordellis

related questions