How to Setup a Two Way Sync Between SVN and Git

Merging traffic with cars traveling at light speed

I hope you are never in the situation where you need to use these instructions.  It means you are stuck and really don’t want to use SVN.  You think there has to be some way I can use a git repo on my project.  I was in the same place and wrote these steps down to remind myself how to do it.  Things can go very wrong if you don’t follow these step by step.

These instructions are for setting up a two way sync between an existing SVN repository and a GitHub repository. We will be creating an SVN tracking branch (release branch) to push changes into SVN.

Setup

  1. Create a directory on your computer for the git repository (Ex. ~/git)
  2. Download svn-migration-scripts.jar to your home directory (Ex. /Users/rwinkle or ~)
  3. Open your Terminal
  4. Run this command to verify you have all the appropriate software (git, svn, JRE). NOTE: On Mac you will get an error: “You appear to be running on a case-insensitive file-system. This is unsupported, and can result in data loss.” I ignored this message at my own peril.
    java -jar ~/svn-migration-scripts.jar verify
  5. Change the directory to the folder created in step 1 “cd ~/git”
  6. Create the author mapping file (authors.txt) from SVN to Git. SVN only has username whereas Git includes username and email. Run the following command:
    java -jar ~/svn-migration-scripts.jar authors https://mycompany.com/path/to/svn/repo > authors.txt
  7. Open authors.txt in a text editor and update the the email address domain from mycompany.com to your particular domain. Here’s what my authors.txt file contained:
    fffff = fffff <fffff@aaaaa.com>
    sssss = sssss <sssss@aaaaa.com>
    lllll = lllll <lllll@aaaaa.com> 
    scmadmin = scmadmin <scmadm@aaaaa.com>
    rrrrrr = rrrrrr <rrrrr@aaaaa.com>
  8. Clone the SVN repository to a local repository using git svn command
    git clone https://github.com/olsondigital/repo-1234
    cd repo-1234

     

    git svn clone --stdlayout --authors-file=authors.txt https://mycompany.com/path/to/svn/repo repo-1234
  9. Update your local git user profile so that it is accurate and reflects your GitHub username and email
    computername:repo-1234 username$ git config --global --edit
    # This is Git's per-user configuration file.
    [user]
    # Please adapt and uncomment the following lines:
            name = winklerj
            email = robb.winkle@gmail.com

     

  10. If you have an empty GitHub repo, create a README.md file with the following and commit it

    # My Title
    This repository is synced with the current SVN repository
    on a tracking branch svnsync-* where * is the SVN branch. For
    example svnsync-trunk

     

    git add README.md
    git commit -m "Initial commit"

     

  11.  Create a branch to sync with an SVN branch. Use the naming convention svnsync-{svn_branch_name} where svn_branch_name is the branch name in SVN. For the initial sync it should be the latest release branch. You can have multiple git branches that map to the corresponding SVN branch. Below is just one example. (NEVER COMMIT DIRECTLY TO THIS BRANCH OR YOU WILL HAVE CONFLICTS)

    git branch --no-track svnsync-DEV_1_0_0_Release
    git checkout svnsync-DEV_1_10_0_Release

     

  12. Initialize and fetch the SVN repository while the new branch is checked out. NOTE: The fetch timed out on me the first time I ran it. I ran it a second time and it completed.
    git svn init -s https://mycompany.com/path/to/svn/repo
    git svn fetch --authors-file=../authors.txt

     

  13.  Set the author location so you don’t have to enter it each time when fetching
    git config svn-remote.svn.authorsfile ../authors.txt

     

  14. Hard reset master to the branch specified 2 steps back (DEV_1_0_0_Release). This will now make the code from DEV_1_0_0_Release the current commit on master
    git reset --hard remotes/origin/DEV_1_0_0_Release

     

  15. Switch to master, merge your SVN tracking branch into master, and push to the GitHub origin master branch
    git checkout master
    git reset --hard svnsync-DEV_1_0_0_Release
    git push origin master

     

  16. You should now see the SVN code in the GitHub repository https://github.com/olsondigital/repo-1234
  17. Create a develop branch off of master and push to origin
    git checkout master
    git checkout -b develop
    git push origin develop

     

  18. Set develop to the default branch in GitHub

Setup Sync with a New SVN Release Branch

  1. Perform step 11 in the previous section and create a tracking branch in git
  2. Pull down SVN changes
    git svn fetch
  3. Perform step 14 and 15 in the previous section and now your master branch should be on the new SVN branch

Syncing from SVN to Git

This is for keeping Git and SVN in sync. All changes from svn are going to be merged locally and staged to be pushed out to the Github repository.

  1. Update the authors.txt file in the directory created in step 1 of setup (Ex. ~/git). This can be done manually or there are options described here: https://www.atlassian.com/git/tutorials/migrating-synchronize
  2. Checkout the SVN tracking branch
    git checkout svnsync-DEV_1_0_0_Release

     

  3. Fetch the latest changes from SVN
    git svn rebase

     

  4. Switch to master and merge the SVN tracking branch
    git checkout master
    git merge svnsync-DEV_1_0_0_Release

     

  5. Push the merged changes to GitHub origin master
    git push origin master

     


Syncing from Git to SVN

Now going the other direction. This is a bit more complicated than pulling in from svn, but make sure you follow all the steps or you will get nasty errors with the sync. Keep in mind the –no-ff on the merge is very important to include. We also want to make sure everything is fully updated from both Github and the svn server before performing the push to svn.

Typically you will be merging a release branch into SVN so I’m using an example release branch

  1. Checkout the release branch and pull the latest changes from origin
    git checkout release-1_0_0
    git pull origin release-1_0_0

     

  2. Checkout the SVN tracking branch and pull down the latest changes
    git checkout svnsync-DEV_1_0_0_Release
    git svn fetch
    git svn rebase

     

  3. Merge the release into the SVN tracking branch
    git merge --no-ff release-1_0_0

     

  4. Resolve any conflicts
  5. Commit the changes locally
    git commit -a

     

  6. Commit the changes to SVN (NOTE: the order of this and the previous operation are important. If you do them in the wrong order the histories will conflict.)
    git svn dcommit

     

Let me know in the comments if these steps were helpful or if they can be improved upon!

References

Note that these instructions were done on a OS X and branch naming conventions are based on gitflow.  The instructions may vary for Windows or different branching models.  Also the article mentions Github and git interchangeably.  These instructions were done against Github but can be used with any git repository.

Here are the pages I referenced to come up with this method of syncing

Leave a Reply

avatar
  Subscribe  
Notify of