Getting started with GIT on Windows

A visual tutorial for the rest of us

Prerequisites

I assume that you know SVN well enough to have been using it (together with some other people) for some time now, on Windows. This should not come as a surprise, seeing that you read a document with the title "GIT for Subversion users on Windows".

Installation

Well, things have certainly improved since the early days. Now, there are only two products left to install, and it'll all work out like a charm:

  1. Install Git for Windows.
  2. Install TortoiseGIT

Installation instructions should be fairly simple to follow through; for now go with the default options and you should be fine.

Note: GIT is a moving target. I saw a lot of documentation that did not fit the behaviour of current releases; therefor note that I was using the following versions:

Initial SVN Setup

I assume that in the past you have used Subversion mostly in a very straightforward way, something like this:

Note: We're not working with a Subversion HTTP(S) setup here: we are in a corporate environment, and have to live with restrictions, so we'll use a SVN repository on a file server (Windows or Linux doesn't matter). Oh, and of course our interface was mostly Tortoisvn, not the command line: we are on Windows, right?

So our first task will be replicating that exact setup in GIT. This will not give us a lot benefits (it will give us some! I will list them at the end of the exercise), but it will give you a first feel of how working with GIT is like.

Setting up a central repository

The command git init is used to create a repository. Most GIT tutorials start this way; however what they don't tell you is that this is not what you normally would want: instead, what you are looking for is to create a bare repository. The terminology "bare repository" was unfamiliar to me; in GIT parlance (and for our purposes) it means: a repository that can act as a central repository. Non-bare repositorys cannot. So: let's create a bare repository then - but how ?

Well, convention says that you should create a directory with a name ending in .git to create bare repositories in. I have no idea whether this convention is enforced by anybody, but for now lets follow what the cool kids have been doing all along and create such a directory.

Step 1: create a directory named supersomething.git somewhere.

Step 2: right click on that directory and choose Git Create repository here...

In the dialog make sure you tick the "Make it bare" box.

Finally, press OK to create it.

Note: The helpful comment that does not tell you what a bare repository the bloody hell actually is, but that instead gives the impression it is somewhat limited ("can only have changes pushed in"). I find many of the GIT comments frankly misleading. If you need the comment, you won't get any wiser by reading them: if you already know everything, you won't need the comments... Oh well...

Populating the initial repository

In Subversion, populating the initial repository works something like this:

  1. Create a local directory
  2. Checkout the (empty) project in this directory
  3. Add the files to the directory
  4. Add them to Subversion
  5. Commit them to Subversion

This basic sequence works for GIT as well - with some caveats. Let's start:

Step 1: create a directory named C1 somewhere.

Step 2: right click on the directory and choose Git clone

This will bring up a dialog

The URL will be the existing bare repository. Note that I ticked the "recursive" box: it makes sense, even though at this point there is nothing much to see yet.

Once you hit OK, the repository will be 'cloned':

Note: GIT clone is something completely different from SVN checkout:

Take a look at your directory now. It will have a structure somewhat like this:

Note that GIT automatically created a subdirectory for the supersomething project. Note also that there is a .git folder which very much acts like the .svn folder: the local database for GIT.

Step 3: Add your files to the directory

Actually, this is very much the same if you start from scratch, or if you start from an existing set of source files you want to add: copy them to the newly created supersomething GIT clone directory. Do not copy them to .git - but then you wouldn't have done that with .svn either, right?

Note: there is no general recommendation as to a GIT directory structure beyond this point. It is not like the trunc/tags/branches thing SVN has. Just copy the files as you see fit.

Step 4: Add the files to GIT

Now, right click on the new files and choose Git Add...

This should bring up a dialog with all files you selected, including those in subdirectories:

Click OK and you'll see the files being added:

Note how incredibly fast this feels. In many operations GIT is a lot faster than Subversion - something you'll soon accept as default, and then when you switch back to some project in Subversion it will be dearly missed :)

Note also that there is a button Commit right here at the end: click it to commit your changes...

Be sure to add a checkin comment; then press OK:

Again, note how fast this thing is... and then think about what you have just done.

Note that the dialog above has a Push button. The GIT push operation is the one that takes your repository and 'commits' it to the central repository. For now, because we're just starting, let's assume that nobody has changed something centrally, so we can proceed. You press the button and this dialog shows up:

Press OK and GIT rushes along

So now, the files are in the central repository!

Step 5: Confirm this by creating yet another clone

Just to verify that what we've done so far makes any sense, create another directory C2, clone supersomething.git in it, and then take a look. You will see that the new directory now contains all the files from C1, just as you were expecting them to be.

Reverting local changes

At the beginning we said that when working offline, we want to use the SCM offline to track local changes. Well, it should be obvious by now how we can do this:

This process is not as intuitive as it seems to someone having used Subversion for many years, so I am going to spend a couple of minutes on it. When you bring up GIT show log, you will see an intimidating dialog like this:

This dialog has three areas:

  1. The top window is the commit list. In a single commit multiple files can be committed, so they do not reflect a single file, but rather a set of files committed at one point.
  2. In the middle window you see the comment associated with each commit.
  3. In the bottom window you see the files associated with each commit.

If, like me, you foolishly think that you revert a commit... you are most certainly wrong. These options are for GIT ninjas, not GIT noobies like us, stay away from them. To revert a file, go to the version (in the top window), then select the file in the bottom window, right click on the file, and there you can say "revert to this revision". Do not, I repeat DO NOT try "Reset master to this" or "Rebase master to this" unless you've been working with GIT for many weeks and know what you're doing.

Resolving a minor conflict

So far we've played by the rules. Now, let's raise a little conflict (just a little one to start, there is more to come!)

Now, in a situation like that, what would have been the response of Subversion? It would have said our copy is out of date, and we need to do a SVN Update first. This is exactly the same situation we have here, only the names have been changed to protect the innocent: we need to do a GIT pull. Note the handy button at the bottom of the dialog! Click it...

Press OK and the files are pulled

Only now, you are in a situation like after an SVN Update: you have a local copy that matches what is on the server, and you can now probably push it. Note that there is a button "Pulled Diff" at the bottom: this shows you exactly the changes that were pulled:

So anyway, now you can do another GIT push, and this time it will work like a charm.

Where are we?

Let's do a short recap of our original motivation. We stated that in offline mode, these were our major issues with Subversion:

Things have certainly changed with GIT already - we can do all of these now!

You can see at this point that M3 and M1 are really interconnected, and how GIT improves this workflow greatly for you. But now let's see something even better:

Working with Branches

Branches in Subversion are much more complicated than in GIT: actually, branches in GIT are really great. How does it work?

You are working in your repository, and you want to try out something. Say, you want to try a new feature TOAST() for SUPERSOMETHING. In Subverison, you would have probably labeled the last release before the change; then started working on the change (rather than really doing a branch). In GIT, if you want to start something but you're not sure yet if it works out, start a branch!

Step 1: Create the branch

This dialog will show up:

Give it a smart name, and be sure to tick "Switch to new branch"

Once GIT has completed its stuff, you are working in the new branch: work as you wish, and commit as often as you like. Any commits you'll do will be to that branch, not to the 'master' branch.

Step 2: Switching branches

Once the dialog is up

You'll be able to switch seamlessly between any of the different 'feature' branches you've done.

Step 3: Merging the branch back to 'master'

Once you are back in 'master', you can do this:

The dialog

allows you to basically set the feature you want to merge back into the main tree. And then you will follow that up with the usual GIT pull / GIT push thingy.

Next

Read Chapter 2 - Migrating a project from SVN to GIT


GK, Sept. 14, 2014