SVN is the version control system I’ve used the most, but lately I’ve been using Git more and more. I’ve also been using Git with projects that have an svn repository thanks to git’s built in svn support.
While working with it, I’ve ran into several typical cases that I’ve often needed to deal with, that I haven’t encountered with SVN, so I thought I’d share some tips with you, as I’m really starting to think Git is a much better tool than SVN.
Issues after starting
When I first cloned an svn repository using Git, I simply issued a git svn clone command. This clones the trunk of the SVN repository, but none of the branches.
Obviously I wanted to have the branches too. To get branches, tags and everything, you can issue the command like this:
git svn clone url/to/repo -T trunk -b branches -t tags
Warning: This can be very very… very slow if you have a large repository.
Refspec glob conflicts
This was a weird message I kept getting during svn rebases and commits. It turns out that Git had somehow mangled its own configuration file, putting the trunk, tags and branches multiple times into it.
You can fix this problem by going to the root of your repository, and into the .git dir. There should be a file called config, which contains a list of URLs to trunk, branches and tags. In my case, they were simply repeated multiple times, and removing the duplicates fixed the Refspec glob conflict error messages for good.
Constantly asking for your repository password
When you use Git with svn+ssh repositories, Git keeps asking for your password. This is especially a problem on Windows, as Git’s svn over http support doesn’t seem to work there at all.
You can fix this, but it requires you have some kind of access to the server with the repository – you need to be able to save your ssh public key there.
Merges with git branches
Don’t do it.
Merging your svn branches with other Git branches is an easy way to mess up your repository and as such you probably should avoid it. cherry-pick and rebase both cause a linear history, and those two can be used (with caution)
You can easily craft commits using git gui. It even lets you choose specific lines to commit, which is useful if you need to split the work you did into more than one commit. You can also use git commit -i to do something similar on the command line.
Saving work in progress
There are two typical methods you can use to save work in progress that you haven’t finished yet.
- git stash: You can stash your changes for later applying it back.
- git commit: You can simply commit your WIP-code.
At first I tended to use git stash – I found having commits that say “WIP”, “foo”, or whatever, weren’t particularily nice.
However, I think using an actual commit is a better approach, because then you usually have a message and a branch. With stash, I often found myself having some stashed code and I had no idea where it belonged. And with git rebase, you can rewrite the history to get rid of those incomplete work in progress commits.
Stash does have its uses though: I do find it convenient if I just want to momentarily put the changes away, but not for a very long period (ie. if I’m leaving stuff over the night, I do a commit instead)
I’ve found that modifying one of my old commits is sometimes useful. For example, because I have a local Git repository, I can commit much more often than I’d commit with SVN. Some even suggest committing after every line, but I think that’s a bit overkill.
git rebase -i, the interactive rebase command which can be used for messing with your old commits, is a very powerful tool. You should be careful with it, as it’s possible to accidentally remove a commit. (It can be retrieved with git reflog so it’s not totally lost, but be careful anyway). You should also be careful to not touch any commits you have already shared with others – be it with git svn dcommit or pushing/pulling.
The simplest usage of rebase is to squash commits. Squashing a commit means it’s merged into the commit before it. This is very convenient if you have multiple work in progress commits, which you can then merge into one. Squashing guide at Git Ready
You can also go back and edit an older commit. This is convenient if you discover you had a bug which you’d rather fix in the same commit where you introduce the feature, or perhaps you want to add better comments to your code. It’s also possible to reorder the commits with rebase.
For more rebase tips, be sure to read my post on Git interactive rebase tips.
What is your favorite trick?
Share it in the comments!