There are dozens of GIT guides available on the internet. However, none of them answer the exact questions that I get asked (as the resident GIT advocate) in the exact way that I would answer them.
So for the first round of questions:
Is this really better than SVN?
Yes, Git is not only different, but better than SVN. Git treats your source code as you probably do, as one coherent entity. That means operations like deletes, renames, and branches (especially branches) work seamlessly.
Why are some of the operations named so obtusely (and oppositely of SVN)?
Git clean
, reset
, revert
(as one example) all do different things that make sense, but stump someone just coming over from SVN. There are likely three main reasons for it. The first version of Git was written over 4 days by Linus Torvalds in a fit of code rage over the last VCS tool. Secondly, Linus has a noted dislike for all things CVS (and by extension SVN). Finally, Git is not really derived from any one VCS system, so command names and operations have multiple influences.
In SVN, I work on trunk. What do I work on in Git?
The Git analog to trunk
is master
.
How do I get work done?
Probably the most important question covered in this blog post. In SVN you have two basic operations svn up
and svn ci
(update and commit, if you use a gui).
Git requires a few more commands. To create a repository, you need to clone it. Unlike SVN, which only stores a snapshot of your current version on your local disk, Git gives you local access to your whole repository. To do that, issue the command in your shell:
git clone <repository_url>
After some moments (moments directly proportional to your repository size) you’ll have access to your code. When you make a change and want to commit it, you’ll have to tell Git that with the following:
git add <path/to/file>
Or if you want to commit everything, it’s just:
git add .
Since Git does everything on a repository level, it handles the recursion automatically.
Committing is very similar to SVN:
git commit -m "My commit message"
This will commit
everything you added
above.
Now this is the part that confuses most newcomers. Git has just committed to the repository on your computer. In order for anyone else to see your change, you need to push
the code to the remote repo:
git push
Depending on how you checked out your branch, you might need to specify where to push:
git push origin/master
Git is distributed, so you can push your code to any other Git repository (advanced feature, not covered here).
Pulling code down after the initial clone is a matter of executing:
git pull
I followed the steps, I’m trying to get remote changes and I’m getting an error about my working copy. What do I do?
This is a very common error and another conceptual change from SVN. SVN updates files, in Git you are updating your repository. When you do a git pull
, you are in effect telling Git “merge my changes with that repository over there”. Git doesn’t like it when you do that with a dirty working copy because your working copy is where Git will have you resolve the conflicts.
There are two ways to solve this error and do the update.
1) execute a git commit
. This seems odd at first, but only because the SVN workflow conditions one to treat committing with fear. In Git, your commits only go to your local repository so you will not create adverse effects for your fellow developers. Changes are only published when you do a git push
.
2) use stashes. If you don’t want to commit, Git allows you to stash your current changes on a stack with the appropriately named git stash
command. So you can git stash
, git pull
, then fix any conflicts. When you are finished, simply type git stash apply
and the previous changes will be applied on top of your newly updated working copy.
I made a bunch of local commits, did a git pull
then git push
and git log
says that I just merged a bunch of other people’s changes. What just happened?
As described above, when you do a git pull
, you are actually merging your local repository with the remote. That last commit encompasses all the magic that just happened in that merge. Git needs to track this, so that when you roll back a commit, Git “does the right thing.” As with anything Git, there is another way.
I created a local feature branch, what’s the best way to keep it in sync with master
?
Git gives you two primary mechanisms for keeping branches in sync; merge
and rebase
.
Merge is the primary mechanism for dealing with remote branches. It views each branch as it’s own stream of changes and seeks to combine them back into one. This is not Ghostbusters, so it’s actually quite safe.
Rebase, on the other hand, is a time machine that rewrites history. Calling git rebase <branch>
tells Git that your current branch started at the current HEAD
of the other branch. What this means in practice is that you’ll have cleaner merges for local branches, since the only differences between the branches are the new commits in the feature branch.
Are there any good visual tools?
SVN has been around for a while now so there are tons of great tools along with very good IDE support.
For anything but the most basic features, I find the Git support in both Intellij and Eclipse lacking.
There are three GUI Git tools I like (all mac centric). My favorite is Git Tower. It’s not free, but I think it offers enough of an experience upgrade to be worth it over the free tools.
Source Tree is free and almost as good as GitTower. I find it’s a little slower, stash support is not as nice, and chunk delta’s don’t work that great, so I’ve stuck with Tower. Source Tree is a lot better than most IDE’s, pretty light on resources, so it’s worth a look.
Finally there’s GitHub for Mac. It’s completely irrelevant if you’re not using GitHub, but if you are, it makes the common things very easy.
Is that all?
Yes, for now. One topic that I plan to discuss shortly is how to use git to move code between one’s laptop and desktop. Git has a lot of features, so I may do a more advanced post in the future, should the need arise.