Seamless git svn setup
I am a power git user and a happy one at that.
Now, I'm forced to use svn and I am not exactly happy to do so. Not so comfortable using git svn
yet.
So, here is the setup I'd like and want.
- I use a git repo, that is git in all ways with many local branches.
- I create multiple branches in git regularly and merge, let git handle all of it.
- I want to send selected git branch as an svn branch with everything mirrored.
- When I delete a local svn mirrored git branch, the svn branch gets deleted too.
The underlining point is that, I want git to do all the hard work of merge and branch and just push to the svn and make it a store.
Sounds like I'm asking for a git-svn tutorial. Except I have gone thro them many times, and yet, I face errors while I 开发者_开发问答do git svn rebase
and git svn commit
very often and it always seems to talk to trunk alone.
What I want is mirrored svn commands sent and mirrored branches.
see this question for a introduction to git svn branch
and that question for how to delete remote branches - or below for a complete summary of the basics of git svn
(including the information from the two questions mentioned).
To give you a more complete tutorial (the complete setup to cover local and remote branches, commiting, merging local branches - see below the horizontal line for just the branch setup), here's how to work easily with a svn repo:
- Initialize your local git repo with
git svn clone <url>
, either with paramter-s
(stdlayout) or with the parameters--trunk, --tags, --branches
to specify the directory of the trunk, tags and branches inside the svn dir.
-s
means, the svn repo has a directory layout like this
/trunk
/branches/new_feature
/branches/long_fix
/tags/0.0.9
/tags/0.1.0
If not, you can specify the location of the trunk, branches and tags with the arguments provided above.
When you clone the repo, you will automatically land in a local branch called master, which will automatically track the trunk.
In this, you do your commits just like you would not know you cloned the repo with git svn
, except you do not push commits:
- Use
git commit
to do commits to your branch - Use
git branch <branch name>
to create local branches - Use
git merge <branch name>
to merge changes from local branches - etc.
You do not need to worry about you are in a git svn
-repo, until you want to push your changes.
From the setup above, we have the local branch master which is tracking trunk. So after doing commits inside the local master-branch, they can be pushed to the trunk with the following command:
git svn dcommit
(inside your local branch master)
(Note the d in dcommit
).
To test where you commits would go, do
git svn dcommit -n
Now comes the interesting part: create branches on your side that are tracked. Really simple reading the question above, I'll just copy and paste the example:
git svn branch -n -m "Branch for authentication bug" auth_bug
Note that this example has the -n
flag which only does a dry run. Remove that flag to do it for real. The command creates the branch auth_bug on the svn repo in the branches-directory you set up above, and
git checkout -b auth_bug auth_bug
creates a local branch auth_bug (first param) and lets it follow the remote branch auth_bug (second param), which is mapped to the dir /branches/auth_bug
on the svn repo. The remote branch auth_bug exists, because you created it with the git svn branch
-command (and could be any other branch already existing).
Inside this local branch auth_bug, all your commits will be pushed to the svn repo in the branches dir /branches/auth_bug
when doing git svn dcommit
(test it by appending -n
to the command.)
To delete a branch (I've not done it before), it looks like git svn
does not handle this for you, so according to another question, you have to to the following directly using the svn
command:
svn rm $URL/branches/the_branch
This deletes the branch from the remote svn repo, and then you have to remove it from your local git repo, depending on it was a branch (like in the command above) or a tag:
git branch -D -r the_branch
rm -rf .git/svn/the_branch
or
git branch -D -r tags/the_tag
rm -rf .git/svn/tags/the_tag
To update your branch with changes from the upstream svn branch ("pull"), you can rebase your branch on top of the change with:
git svn rebase
This fetches new commits in svn, rebases your branch and plays back your local commits (if any).
Intead of git-svn you may try SubGit.
SubGit is a Git-SVN bi-directional server-side mirror.
If you have local access to Subversion repository, you can install SubGit into it just like this:
$ subgit configure $SVN_REPOS
# Adjust $SVN_REPOS/conf/subgit.conf to specify your branches and tags
# Adjust $SVN_REPOS/conf/authors.txt to specify git & svn authors mapping
$ subgit install $SVN_REPOS
...
$ INSTALLATION SUCCESSFUL
SubGit converts Subversion repository into Git (it works in opposite direction as well) and installs SVN and Git hooks. As result Subversion and Git repositories are synchronized: every commit and push starts hooks that convert incoming modifications immediately.
Here are some benefits of using SubGit:
SubGit automatically converts svn:ignore properties into .gitignore files, svn:eol-style and svn:mime-type properties to .gitattributes;
SubGit automatically converts merge-tracking information from Git repository to proper svn:mergeinfo property updates;
One may use any Git client to work with SubGit-powered Git repository, all the changes are immediately propagated to Subversion counterpart.
For more details please refer to SubGit documentation and git-svn comparison page.
And here's the description of how standard Git operations are reflected in Subversion repository:
Create branch foo and push it to the original Git repository:
$ git checkout -b foo master $ git commit -a -m "Implement feature foo" $ git push origin foo
As soon as push is done, Subversion repository gets ^/branches/foo branch copied from ^/trunk with appropriate modifications.
Merge branch foo to master:
$ git checkout master $ git merge foo $ git push
At this moment a new revision created for branch ^/trunk with appropriate modifications including svn:mergeinfo update:
+ /branches/foo:rX-rY
Delete branch from remote repository:
$ git push origin +:refs/heads/foo
After that ^/branches/foo is deleted in SVN repository.
SubGit is a commercial product. It is free for open-source and academic projects and also for projects with up to 10 committers.
Disclaimer: I'm one of SubGit developers.
精彩评论