Git-Subversion

This article shows how to import a Subversion repository to Git.

Import Subversion Repository

based on a migration tutorial

  1. Prepare a file of users (Edit the lines to match uname = Firstname Lastname <email@example.com>)

    $ svn log -q | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > authors-transform.txt
    $ vim authors-transform.txt
    
  2. Checkout the Subversion repository

    $ git svn clone https://svn.example.com/svn/baserepo/some/subdirectory --no-metadata -A ../authors-transform.txt
    
    • --no-metadata : if that's a one-time import, this waives the linkage of Git Commits to Subversion Revisions. If you want to update the Git Repo after further Subversion Commits, don't use this parameter!
    • -A ../authors-transform.txt : used to translate Subversion usernames to Git's Name/E-Mail commit entries.

    This uses the previously created authors file to convert Subversion accounts to names and E-Mail addresses used in Git commits.

  3. If you have set svn:ignore properties, convert them to .gitignore

    $ git svn show-ignore > .gitignore
    $ git add .gitignore
    $ git commit -m "Convert svn:ignore properties to .gitignore"
    
  4. Bring the Repository to a Server. Here are two alternatives.

    1. Create an attatched Git repository that can pull in (and merge?) later changes from Subversion (untested so far). Don't use the --no-metadata parameter to git svn clone (Step 2) in this case!

      • Create a repository on a server (or locally) to push to

        $ ssh git@www.example.com
        $ mkdir -p git/MyNewRepo.git
        $ cd git/MyNewRepo.git
        $ git init --bare
        $ exit
        
      • Then add the new repository to the Subversion checkout

        $ git remote add bare git@www.example.com:git/MyNewRepo.git
        $ git config remote.bare.push 'refs/remotes/*:refs/heads/*'
        $ git push bare
        $ git push bare master
        

      The refspec in the second command configures a git push bare (without explicit branch) to always push all remote branches to this remote repo.

    2. This proceeding is to create a detatched once-only import to move a repository from Subversion over to Git. This uses a temporary Git repo (called git-svn) that pushes to a server. By doing so, the connection to Subversion gets lost (this can most probably also be achieved by other ways...).

      • The new repo was created on Github and cloned to the local hard disk. This create a clean connection between the local clone and the upstream repo.

      • Then I had two Git repos (and the old Subversion): The new.git is a clone of the Github repo and is correctly tied to that one (for pushing).

        checkout/$ ls
        new.git     old.git-svn      old.svn
        
      • In the Git-Svn repo, add the new.git as remote repo with the name myclone:

        checkout/old.git-svn/$ git remote add myclone ../new.git
        checkout/old.git-svn/$ git config remote.myclone.push 'refs/remotes/*:refs/heads/*'
        checkout/old.git-svn/$ git push myclone
        
      • This results in new.git having the new branch git-svn that can be merged to the master branch:

        checkout/new.git/$ git branch
         git-svn
        *master
        checkout/new.git/$ git checkout git-svn
        checkout/new.git/$ ls
        checkout/new.git/$ git checkout master
        checkout/new.git/$ git merge git-svn
        checkout/new.git/$ git branch -d git-svn
        
      • Check everything, and if it's fine, push the new master branch to the Server.

  5. There are more steps to follow in the original tutorial, especially if using the default Subversion layout with trunk, branches and tags. Check if everything works, then you can delete the git-svn checkout.

social