Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cherry-picking with git-svn

I'm facing the problem of merging a subset of revisions from one topic-branch to another. Since I am using git-svn, I was curious to see if it is possible to use cherry-picking for this. Using Subversion, I would do:

svn merge -c A
svn merge -c B
svn merge -c C
...
svn commit ...

what will happen if I try to do this?

git checkout branch1
git cherry-pick A
git cherry-pick B
git cherry-pick C
git svn dcommit

If I read the git svn man-page, the answers is "don't do that", but I get the impression when googling around that git svn does a much better job now with these kinds of issues.

like image 842
JesperE Avatar asked Dec 13 '10 13:12

JesperE


2 Answers

git-svn had a serious problem related to cherry-picked commits:

Suppose you have commit a1b2c3f9 which is already dcommitted into svn repository:

  $ git show a1b2c3f9
  commit a1b2c3f9...
  Author: Happy Dev <happyd@43fe5c0-...>
  Date:   Mon Nov 14 13:01:38 2011 +0000

  Commit message

  git-svn-id: https://host/svn/branches/some-branch@1000 43fe5c0-...

See this git-svn-id line? This is how git-svn understands where your commit lies in Subversion repository.

Now you want to cherry-pick this commit to master branch you're currently on:

  $ git cherry-pick a1b2c3f9

If there were no merge conflicts, git creates a new commit, say, 9f3c2b1a and here what we have:

  $ git show 9f3c2b1a
  commit 9f3c2b1a...
  Author: Happy Dev <happyd@43fe5c0-...>
  Date:   Mon Nov 14 13:01:39 2011 +0000

  Commit message

  git-svn-id: https://host/svn/branches/some-branch@1000 43fe5c0-...

So, Git created a commit with exactly the same message. This caused serious problems. Former versions of git-svn sent such commit into wrong branch — ^/branches/some-branch instead of ^/trunk/.

This problem is already fixed in the latest versions of Git. But there is another one which is still present:

git-svn doesn't honor merge-tracking mechanism of Subversion.

Subversion tracks merge information on performed cherry-picks, so the command

  $ svn merge -c 1000 ^/branches/some-branch trunk-working-copy

adjusts the svn:mergeinfo property of trunk-working-copy as follows:

  + /branches/some-branch: 1000

This way Subversion understands that this particular revision was already merged into ^/trunk/ branch thus it skips this change in further merges.

When you run git cherry-pick and then git svn dcommit Subversion repository doesn't get svn:mergeinfo modification.


Here goes the disclaimer:
Currently I don't work on SmartGit but I work in a close contact with SmartGit developers.

Syntevo company developed SmartGit — a great replacement of git-svn. This Git client resolves all the issues I've described above:

So, you cherry-pick a1b2c3f9 commit:

  $ git cherry-pick a1b2c3f9

as result you get 9f3c2b1a commit, and then you push it into Subversion repository. SmartGit does everything to keep merge-tracking information, so ^/trunk/ branch gets necessary modification of its svn:mergeinfo property:

  + /branches/some-branch: 1000

You can perform Git cherry-pick either from SmartGit itself or using Git command line interface. In the second case commit message should have git-svn-id line of the cherry-pick source.

SmartGit is proprietary software but it's free for non-commercial usage. It has a lot of great features, for more information please refer to SmartGit documentation.

There is another interesting project which solves certain problems with git-svn — SubGit. Basically it is the server-side solution for synchronizing changes between Subversion and Git repositories. It's much more superior than git-svn and doesn't have its problems.

As svn-via-git user, I believe, you might be interested in that too.

like image 119
vadishev Avatar answered Oct 21 '22 02:10

vadishev


When you do git svn dcommit, it will sequentially run an svn commit for each git commit between your svn tracking branch and whatever HEAD is in git. In your example, that's three commits – one each for A, B, and C – since git cherry-pick commits the changes right away. Granted, you could use git rebase -i to squash those commits together into a single revision before you run git svn dcommit to push them to svn.

Running git-svn completely ignores all svn:mergeinfo properties. From the git-svn man page:

We ignore all SVN properties except svn:executable. Any unhandled properties are logged to $GIT_DIR/svn/<refname>/unhandled.log

like image 37
Mike Seplowitz Avatar answered Oct 21 '22 02:10

Mike Seplowitz