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: <
subgit import --svn-url url://svn.serv/Bla/Bla directory/path/Local.git.Repo
It's all.
+ To update from SVN, a Git repository created by the first command.
subgit import directory/path/Local.git.Repo
I used a way to migrate to Git instantly for a huge repository.
Of course you need some preparation.
But you may don't stop development process, at all.
Here is my way.
My solution looks like:
Migration takes a lot of time for a big SVN repository.
But updating of the completed migration just seconds.
Of course I'm using SubGit, mama. git-svn makes me Blue Screen of Death. Just constantly. And git-svn is boring me with Git's "filename too long" fatal error.
STEPS
1. Download SubGit
2. Prepare migrate and updating commands.
Let's say we do it for Windows (it's trivial to port to Linux).
In a SubGit's installation bin directory (subgit-2.X.X\bin), create two .bat files.
Content of a file/command for the migration:
start subgit import --svn-url url://svn.serv/Bla/Bla directory/path/Local.git.Repo
The "start" command is optional here (Windows). It'll allow to see errors on start and left a shell opened after completion of the SubGit.
You may add here additional parameters similar to git-svn.
I'm using only --default-domain myCompanyDomain.com to fix the domain of the email address of SVN authors.
I have the standard SVN repository's structure (trunk/branches/tags) and we didn't have troubles with "authors mapping". So I'm doing nothing any more.
(If you want to migrate tags like branches or your SVN have multiple branches/tags folders you may consider to use the more verbose SubGit approach)
Tip 1: Use --minimal-revision YourSvnRevNumber to see fast how things boils out (some kind of a debugging).
Especially useful is to see resolved author names or emails.
Or to limit the migration history depth.
Tip 2: Migration may be interrupted (Ctrl + C) and restored by running of the next updating command/file.
I don't advise doing this for big repositories. I have received "Out of memory Java+Windows exception".
Tip 3: Better to create a copy of your result bare repository.
Content of a file/command for updating:
start subgit import directory/path/Local.git.Repo
You may run it any amount of times when you want to obtain the last team's commits to your Git repository.
Warning! Don't touch your bare repository (creation of branches for example).
You'll take the next fatal error:
Unrecoverable error: are out of sync and cannot be synced ... Translating Subversion revisions to Git commits...
3. Run the first command/file. It'll take a loooong time for a big repository. 30 hours for my humble repository.
It's all.
You may update your Git repository from SVN at any time any amount of times by running the second file/command. And before switching of your development team to Git.
It'll take just seconds.
There's one more useful task.
Push your local Git repository to a remote Git repository
Is it your case? Let's proceed.
Run:
$ git remote add origin url://your/repo.git
By default your Git can't send big chunks. fatal: The remote end hung up unexpectedly
Let's run for it:
git config --global http.postBuffer 1073741824
524288000 - 500 MB 1073741824 - 1 GB, etc.
Fix your local certificate troubles. If your git-server uses a broken certificate.
I have disabled certificates.
Also your Git server may have a request amount limitations needing to be corrected.
Run with a local Git:
git push origin --mirror
(git push origin '*:*' for old Git versions)
If you get the following: error: cannot spawn git: No such file or directory... For me the full recreation of my repository solves this error (30 hours). You can try the next commands
git push origin --all
git push origin --tags
Or try to reinstall Git (useless for me). Or you may create branches from all you tags and push them. Or, or, or...
Effectively using Git with Subversion is a gentle introduction to git-svn. For existing SVN repositories, git-svn makes this super easy. If you're starting a new repository, it's vastly easier to first create an empty SVN repository and then import using git-svn than it is going in the opposite direction. Creating a new Git repository then importing into SVN can be done, but it is a bit painful, especially if you're new to Git and hope to preserve the commit history.
I suggest getting comfortable with Git before trying to use git-svn constantly, i.e. keeping SVN as the centralized repo and using Git locally.
However, for a simple migration with all the history, here are the few simple steps:
Initialize the local repo:
mkdir project
cd project
git svn init http://svn.url
Mark how far back you want to start importing revisions:
git svn fetch -r42
(or just "git svn fetch" for all revs)
Actually fetch everything since then:
git svn rebase
You can check the result of the import with Gitk. I'm not sure if this works on Windows, it works on OSX and Linux:
gitk
When you've got your SVN repo cloned locally, you may want to push it to a centralized Git repo for easier collaboration.
First create your empty remote repo (maybe on GitHub?):
git remote add origin git@github.com:user/project-name.git
Then, optionally sync your main branch so the pull operation will automatically merge the remote master with your local master, when both contain new stuff:
git config branch.master.remote origin
git config branch.master.merge refs/heads/master
After that, you may be interested in trying out my very own git_remote_branch
tool, which helps dealing with remote branches:
First explanatory post: "Git remote branches"
Follow-up for the most recent version: "Time to git collaborating with git_remote_branch"
There is a new solution for smooth migration from Subversion to Git (or for using both simultaneously): SubGit.
I'm working on this project myself. We use SubGit in our repositories - some of my teammates use Git and some Subversion and so far it works very well.
To migrate from Subversion to Git with SubGit you need to run:
$ subgit install svn_repos
...
TRANSLATION SUCCESSFUL
After that you'll get Git repository in svn_repos/.git and may clone it, or just continue to use Subversion and this new Git repository together: SubGit will make sure that both are always kept in sync.
In case your Subversion repository contains multiple projects, then multiple Git repositories will be created in svn_repos/git directory. To customize translation before running it do the following:
$ subgit configure svn_repos
$ edit svn_repos/conf/subgit.conf (change mapping, add authors mapping, etc)
$ subgit install svn_repos
With SubGit you may migrate to pure Git (not git-svn) and start using it while still keeping Subversion as long as you need it (for your already configured build tools, for instance).
Hope this helps!
Pro Git 8.2 explains it: http://git-scm.com/book/en/Git-and-Other-Systems-Migrating-to-Git
Create a users file (i.e. users.txt
) for mapping SVN users to Git:
user1 = First Last Name <email@address.com>
user2 = First Last Name <email@address.com>
...
You can use this one-liner to build a template from your existing SVN repository:
svn log -q | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > users.txt
SVN will stop if it finds a missing SVN user not in the file. But after that you can update the file and pick-up where you left off.
Now pull the SVN data from the repository:
git svn clone --stdlayout --no-metadata --authors-file=users.txt svn://hostname/path dest_dir-tmp
This command will create a new Git repository in dest_dir-tmp
and start pulling the SVN repository. Note that the "--stdlayout" flag implies you have the common "trunk/, branches/, tags/" SVN layout. If your layout differs, become familiar with --tags
, --branches
, --trunk
options (in general git svn help
).
All common protocols are allowed: svn://
, http://
, https://
. The URL should target the base repository, something like http://svn.mycompany.com/myrepo/repository. The URL string must not include /trunk
, /tag
or /branches
.
Note that after executing this command it very often looks like the operation is "hanging/freezed", and it's quite normal that it can be stuck for a long time after initializing the new repository. Eventually you will then see log messages which indicates that it's migrating.
Also note that if you omit the --no-metadata
flag, Git will append information about the corresponding SVN revision to the commit message (i.e. git-svn-id: svn://svn.mycompany.com/myrepo/<branchname/trunk>@<RevisionNumber> <Repository UUID>
)
If a user name is not found, update your users.txt
file then:
cd dest_dir-tmp
git svn fetch
You might have to repeat that last command several times, if you have a large project, until all of the Subversion commits have been fetched:
git svn fetch
When completed, Git will checkout the SVN trunk
into a new branch. Any other branches are setup as remotes. You can view the other SVN branches with:
git branch -r
If you want to keep other remote branches in your repository, you want to create a local branch for each one manually. (Skip trunk/master.) If you don't do this, the branches won't get cloned in the final step.
git checkout -b local_branch remote_branch
# It's OK if local_branch and remote_branch are the same name
Tags are imported as branches. You have to create a local branch, make a tag and delete the branch to have them as tags in Git. To do it with tag "v1":
git checkout -b tag_v1 remotes/tags/v1
git checkout master
git tag v1 tag_v1
git branch -D tag_v1
Clone your GIT-SVN repository into a clean Git repository:
git clone dest_dir-tmp dest_dir
rm -rf dest_dir-tmp
cd dest_dir
The local branches that you created earlier from remote branches will only have been copied as remote branches into the new cloned repository. (Skip trunk/master.) For each branch you want to keep:
git checkout -b local_branch origin/remote_branch
Finally, remove the remote from your clean Git repository that points to the now deleted temporary repository:
git remote rm origin