gitsvnmergegit-svnmergeinfo

git-svn workflow for merging using svn.pushmergeinfo


What is the correct workflow for merging svn tracked branches using git-svn. I've read a little about the git-svn svn.pushmergeinfo config key, and the caveats are:

From http://www.kernel.org/pub/software/scm/git/docs/git-svn.html:

config key: svn.pushmergeinfo

This option will cause git-svn to attempt to automatically populate the svn:mergeinfo property in the SVN repository when possible. Currently, this can only be done when dcommitting non-fast-forward merges where all parents but the first have already been pushed into SVN.

So my normal workflow is:

Assuming I have an SVN branch ^/branches/feature_branch

# Ensure git-svn is configured to populate svn:mergeinfo
git config --global svn.pushmergeinfo true   

# Update my local svn remotes state
git svn fetch

# Track a local branch against a remote SVN backed ^/branches/feature_branch 
git checkout -b local_feature_branch remotes/feature_branch

# Modify files and commit to local git repo
git commit -a -m "changes"
# Push changes to SVN branch ^/branches/feature_branch
git svn dcommit

Then to merge up ^/trunk into my local_feature_branch I assume I do something like?

# Sync to the latest SVN
git svn fetch
# Rebase "master" which is tracking the remote SVN ^/trunk
git checkout master
git svn rebase

# Checkout the local_feature_branch
git checkout local_feature_branch

# Merge "master" into "local_feature" which is tracking ^/trunk
git merge --squash master
git commit -m "merge master which is tracking SVN ^/trunk"

# Dry run the dcommit to SVN which should include svn:mergeinfo property changes
git svn dcommit --dry-run

# Commit merge to trunk
git svn dcommit 

Solution

  • Using merge --squash and svn.pushmergeinfo together doesn't make much sense. With merge --squash, the resulting commit won't be a merge commit, so a subsequent dcommit won't create any mergeinfo.

    I know that (mostly older) threads here on stackoverflow suggest using --squash, but I think that's largely a relic of the past. I have been using git-svn to manage our company's svn repos for close to a year now, and so far it worked great with the following workflow:

    I always make sure before a merge that I am up-to-date and, just to be safe, that I don't have any local unsynced commits:

    # On local_feature_branch
    # Update from SVN
    git svn fetch && git svn rebase -l
    
    # push pending commits
    git svn dcommit
    

    Then I do a 'real' merge, using the "remote" SVN branch as source. This saves switching branches and updating, and ensures that the incoming branch doesn't have any local unsynced commits:

    # Create a real, non-forward merge commit
    git merge --no-ff svn/trunk
    
    # ... and push it to SVN, including mergeinfo
    git svn dcommit
    

    Also, this way the merge gets properly recorded in the local history, so subsequent merges won't have to deal with previously resolved conflicts. With --squash you'd reencounter those with every merge.

    Note however that there is an open issue with mergeinfo when merging back from local_feature_branch to trunk (i.e. a reintegrate in svn-speak): Git-SVN with svn.pushmergeinfo: how to avoid self-referencing mergeinfo lines. This has happened rarely in our repo, but so far it didn't cause any trouble for me.