I had the unfortunate experience of having to use Subversion again after using Git for a long time. It is amazing how fast I can forget. After renaming a directory at the prompt, and the agony that goes with it, I decided to switch back to Git.
$ mv requester sampler # svn agony after renaming a directory $ svn st ? sampler ! requester ! requester.rb A sampler.rb
The tool to use when using Git with Subversion is, of course,
git svn works very well as long as you remember that Subversion is not Git. It does not handle merging well, and it will bite you if you don't respect that. So what does this actually mean? It means:
Always keep the Git master in sync with Subversion
To do this you have two commands you can use.
# Rebases the commits from the upstream Subversion server with your local master. $ git svn rebase
You should only
git svn rebase in your Git master, and you should ALWAYS do it before you
git svn dcommit anything to the subversion repository.
git svn rebase keeps the upstream subversion in sync with your local master by pulling down the changes, kind of like
# Commits the changes you have in your local master to the upstream Subversion server. $ git svn dcommit
When you have changes ready to commit, you commit them to subversion with
git svn dcommit. You should ALWAYS
git svn rebase before you do the update, or it will fail.
That's it! As long as you follow these two simple rules, your life with
git svn will be easy. If you forget to follow them, you will be bitten. When you get bitten, the cool thing about Git is that even if you screw up, it is always possible to sort it out.
It that was all there was to it, there would be no reason to use Git instead of Subversion. Git really shines when it comes to branching and merging. You may create as many local branches as you like with
git branch branch_name or
git checkout -b branch_name. You can hack around in these local branches as much as you want and merge them together. But, before you merge them into the master branch, you must rebase with master! Not merge, rebase! Rebase means replay the commits on top of the named branch. It creates new commits, the same content, but with a different SHA-1.
# Example session (master)$ git svn rebase (master)$ git checkout -b dev hack, hack, hack, ... (dev)$ git commit -am 'Commit the changes' (dev)$ git checkout master (master)$ git checkout -b bugfix hack, hack, hack, ..., done (bugfix)$ git checkout master (master)$ git svn rebase (master)$ git checkout bugfix $ git rebase master (bugfix)$ git checkout master (master)$ git merge --ff bugfix # --ff only fast-forwards, merges that don't need to merge. (master)$ git svn dcommit (master)$ git branch -D bugfix # delete the branch it is not needed anymore (master)$ git checkout dev hack, hack, hack, ..., done (dev)$ git checkout master (master)$ git svn rebase (master)$ git checkout dev (dev)$ git rebase master (dev)$ git checkout master (master)$ git merge --ff dev # --ff only fast-forwards, merges that don't need to merge. (master)$ git svn dcommit
Another thing to be aware of is that
git svn dcommit creates an extra commit, so even if you haven't changed anything in the master you need to rebase the local branch with the master. This is only needed if you don't delete the branches after you are done with a commit.
In the example above, I ended with a
git svn dcommit and I didn't remove the
(master)$ git svn dcommit # from above (master)$ git co dev (dev)$ git rebase master # rebases the extra commit created by git svn dcommit
If you forget to rebase or something else happens that hinders a clean merge into the master. You can always back out of it with
git reset --hard.
(master)$ git svn dcommit ... failed miserably, because I failed to git svn rebase, bollocks! (aa..88dd|MERGING)$ git reset --hard (master)$ git svn rebase (master)$ git svn dcommit # Nice and clean commit
To get started you need to clone a subversion repository.
$ git svn clone http://svn.example.com/project/trunk $ cd trunk (master)$ git ...