How do I migrate an SVN repository with history to a new Git repository?

前端 未结 30 1614
离开以前
离开以前 2020-11-22 02:51

I read the Git manual, FAQ, Git - SVN crash course, etc. and they all explain this and that, but nowhere can you find a simple instruction like:

SVN repository in: <

相关标签:
30条回答
  • 2020-11-22 03:38

    A somewhat extended answer using just git, SVN, and bash. It includes steps for SVN repositories that do not use the conventional layout with a trunk/branches/tags directory layout (SVN does absolutely nothing to enforce this kind of layout).

    First use this bash script to scan your SVN repo for the different people who contributed and to generate a template for a mapping file:

    #!/usr/bin/env bash
    authors=$(svn log -q | grep -e '^r' | awk 'BEGIN { FS = "|" } ; { print $2 }' | sort | uniq)
    for author in ${authors}; do
      echo "${author} = NAME <USER@DOMAIN>";
    done
    

    Use this to create an authors file where you map svn usernames to usernames and email as set by your developers using git config properties user.name and user.email (note that for a service like GitHub only having a matching email is enough).

    Then have git svn clone the svn repository to a git repository, telling it about the mapping:

    git svn clone --authors-file=authors --stdlayout svn://example.org/Folder/projectroot

    This can take incredibly long, since git svn will individually check out every revision for every tag or branch that exists. (note that tags in SVN are just really branches, so they end up as such in Git). You can speed this up by removing old tags and branches in SVN you don't need.

    Running this on a server in the same network or on the same server can also really speed this up. Also, if for some reason this process gets interrupted you can resume it using

    git svn rebase --continue

    In a lot of cases you're done here. But if your SVN repo has an unconventional layout where you simply have a directory in SVN you want to put in a git branch you can do some extra steps.

    The simplest is to just make a new SVN repo on your server that does follow convention and use svn copy to put your directory in trunk or a branch. This might be the only way if your directory is all the way at the root of the repo, when I last tried this git svn simply refused to do a checkout.

    You can also do this using git. For git svn clone simply use the directory you want to to put in a git branch.

    After run

    git branch --set-upstream master git-svn
    git svn rebase
    

    Note that this required Git 1.7 or higher.

    0 讨论(0)
  • 2020-11-22 03:38

    I´m on a windows machine and made a small Batch to transfer a SVN repo with history (but without branches) to a GIT repo by just calling

    transfer.bat http://svn.my.address/svn/myrepo/trunk https://git.my.address/orga/myrepo

    Perhaps anybody can use it. It creates a TMP-folder checks out the SVN repo there with git and adds the new origin and pushes it... and deletes the folder again.

    @echo off 
    SET FROM=%1 
    SET TO=%2 
    SET TMP=tmp_%random%
    
    echo from:  %FROM% 
    echo to:    %TO% 
    echo tmp:   %TMP%
    
    pause
    
    git svn clone  --no-metadata --authors-file=users.txt %FROM% %TMP%  
    cd %TMP% 
    git remote add origin %TO% 
    git push --set-upstream origin master
    
    
    cd .. 
    echo delete %TMP% ... 
    pause
    
    rmdir /s /q %TMP%
    

    You still need the users.txt with your user-mappings like

    User1 = User One <u.1@xxx.com>
    
    0 讨论(0)
  • 2020-11-22 03:39

    TortoiseGit does this. see this blog post: http://jimmykeen.net/articles/03-nov-2012/how-migrate-from-svn-to-git-windows-using-tortoise-clients

    Yeah, I know answering with links isn't splendid but it's a solution, eh?

    0 讨论(0)
  • 2020-11-22 03:39

    I highly recommend this short series of screencasts I just discovered. The author walks you through the basic operations, and showcases some more advanced usages.

    0 讨论(0)
  • 2020-11-22 03:40

    You have to Install

    git
    git-svn
    

    Copied from this link http://john.albin.net/git/convert-subversion-to-git.

    1. Retrieve a list of all Subversion committers

    Subversion simply lists the username for each commit. Git’s commits have much richer data, but at its simplest, the commit author needs to have a name and email listed. By default the git-svn tool will just list the SVN username in both the author and email fields. But with a little bit of work, you can create a list of all SVN users and what their corresponding Git name and emails are. This list can be used by git-svn to transform plain svn usernames into proper Git committers.

    From the root of your local Subversion checkout, run this command:

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

    That will grab all the log messages, pluck out the usernames, eliminate any duplicate usernames, sort the usernames and place them into a “authors-transform.txt” file. Now edit each line in the file. For example, convert:

    jwilkins = jwilkins <jwilkins>
    

    into this:

    jwilkins = John Albin Wilkins <johnalbin@example.com>
    

    2. Clone the Subversion repository using git-svn

    git svn clone [SVN repo URL] --no-metadata -A authors-transform.txt --stdlayout ~/temp
    

    This will do the standard git-svn transformation (using the authors-transform.txt file you created in step 1) and place the git repository in the “~/temp” folder inside your home directory.

    3. Convert svn:ignore properties to .gitignore

    If your svn repo was using svn:ignore properties, you can easily convert this to a .gitignore file using:

    cd ~/temp
    git svn show-ignore > .gitignore
    git add .gitignore
    git commit -m 'Convert svn:ignore properties to .gitignore.'
    

    4. Push repository to a bare git repository

    First, create a bare repository and make its default branch match svn’s “trunk” branch name.

    git init --bare ~/new-bare.git
    cd ~/new-bare.git
    git symbolic-ref HEAD refs/heads/trunk
    

    Then push the temp repository to the new bare repository.

    cd ~/temp
    git remote add bare ~/new-bare.git
    git config remote.bare.push 'refs/remotes/*:refs/heads/*'
    git push bare
    

    You can now safely delete the ~/temp repository.

    5. Rename “trunk” branch to “master”

    Your main development branch will be named “trunk” which matches the name it was in Subversion. You’ll want to rename it to Git’s standard “master” branch using:

    cd ~/new-bare.git
    git branch -m trunk master
    

    6. Clean up branches and tags

    git-svn makes all of Subversions tags into very-short branches in Git of the form “tags/name”. You’ll want to convert all those branches into actual Git tags using:

    cd ~/new-bare.git
    git for-each-ref --format='%(refname)' refs/heads/tags |
    cut -d / -f 4 |
    while read ref
    do
      git tag "$ref" "refs/heads/tags/$ref";
      git branch -D "tags/$ref";
    done
    

    This step will take a bit of typing. :-) But, don’t worry; your unix shell will provide a > secondary prompt for the extra-long command that starts with git for-each-ref.

    0 讨论(0)
  • 2020-11-22 03:41

    I've posted an step by step guide (here) to convert svn in to git including converting svn tags in to git tags and svn branches in to git branches.

    Short version:

    1) clone svn from an specific revision number. (the revision number must be the oldest you want to migrate)

    git svn clone --username=yourSvnUsername -T trunk_subdir -t tags_subdir -b branches_subdir -r aRevisionNumber svn_url gitreponame
    

    2) fetch svn data. This step it's the one it takes most time.

    cd gitreponame
    git svn fetch
    

    repeat git svn fetch until finishes without error

    3) get master branch updated

    git svn rebase
    

    4) Create local branches from svn branches by copying references

    cp .git/refs/remotes/origin/* .git/refs/heads/
    

    5) convert svn tags into git tags

    git for-each-ref refs/remotes/origin/tags | sed 's#^.*\([[:xdigit:]]\{40\}\).*refs/remotes/origin/tags/\(.*\)$#\2 \1#g' | while read p; do git tag -m "tag from svn" $p; done
    

    6) Put a repository at a better place like github

    git remotes add newrepo git@github.com:aUser/aProjectName.git
    git push newrepo refs/heads/*
    git push --tags newrepo
    

    If you want more details, read my post or ask me.

    0 讨论(0)
提交回复
热议问题