views:

557

answers:

1

I've got a git-svn checkout of my entire repo (initialized in the standard git svn init -t tags -b branches -T trunk $repo_url fashion, then git svn fetched). I manually svn copy $repo_url/branches/branch1 $repo_url/branches/branch2. I then ran git svn fetch, git checkout -b local-branch2 branch2, made a few commits to branch2, dcommited them back to the SVN repo, and am done with my work on branch2. (Why branch a branch? I wanted to hack at this branch locally in git, but still commit back to SVN and get help from a couple of coworkers while I was working on it).

What I haven't done is merge the branch2 work back into branch1. If I git checkout -b local-branch1 branch1, then git merge branch2, it simply fast-forwards my local-branch1 pointer to where branch2 is.

Instead, I want git to replay all commits made since starting branch2 onto branch1, so that I can dcommit each of them to the SVN repo. It seems like there's a way to do this, but I can't think of it. Maybe git rebase, or a git cherry-pick of each commit made on branch2? (though the latter is a bit tedious). I'd rather not svn merge the two URLs together, as that's a big bucket of hurt.

Ideas? Any parts of this need more explanation?

+4  A: 

The first commit on branch2 that's not on local-branch1 is presumably the commit that created branch2, yes? This should appear as an empty commit in git (e.g. a message, but no contents). Copy its sha1 identifier. Then in local-branch1, try git reset --hard branch2 && git rebase --onto local-branch1@{1} SHA1 (where SHA1 is the copied sha1). This should replay all the commits except that empty one back onto branch 1. You will most likely now want to do an interactive rebase and edit each commit so you can strip out the git-svn-id: line that git-svn adds for you (or you could write a git-filter-branch script to do so, if there's enough commits).

Out of curiosity, why do you want to replay each of the commits? If you want to simply merge your changes in, it's much simpler, you can just do git checkout local-branch1 && git merge --squash branch2 && git commit. This will do a non-fast-forward merge, but it won't actually produce a merge commit (as those confuse git-svn). Instead it will produce the equivalent working tree as if a merge had happened, but with only a single parent. This mirrors how svn merges work.

Kevin Ballard
Looks like that all worked, thanks.I didn't want to do the squash commit, because I wanted to preserve each commit in the repo (diffs and commit messages) in case I needed to regress anything later. I may rethink this approach next time I have to do this, though, because this is a bit messy.
cbowns
Also, a friend just tried this for me: git-svn is now better about ignoring the existing git-svn-id lines in the commit messages and won't go dcommitting to the wrong branch.
cbowns
After making a few more commits, `git svn info` showed me on the wrong branch again for dcommitting (it had me on branch2). I cherry-picked and reset my way back to branch1, and then did a `git checkout master; git reset --hard branch1` to get master back where I wanted it.
cbowns