Setting Up and Using Git

From Center for Cognitive Neuroscience
Jump to: navigation, search

Introduction

GIT is a decentralized version control system. This differs from CVS, SVN, and various other VCS's in that there is no need for a central repository though one can be used if desired. All working directories are self contained and complete projects in their own right. In the dynamic collaboration environments typically found in research and open source communities this is particularly appealing. It is suited for small projects and very large projects alike and is extremely fast for either. Further, branching and merging (often a royal pain in other version control environments) are first class citizens. They are the natural way to make changes. Typical work flow involves branching, then merging with the trunk all in the course of one session.

This is NOT a complete git tutorial. It's only a quick walk through and is not intended to be either exhaustive in even the loosest sense of the word.

For full information on Git please see the GIT home site or any of the many, many tutorials found with a simple google search.

Windows

GIT is primarily designed for UNIX based systems. Specifically, it was written by Linus Torvalds as a BitKeeper replacement for the linux kernel project. There is a Windows client, however this tutorial focuses on installation via Cygwin. Not because I view it as superior, I have no experience with the windows client to make a fair comparison, but because it is what I am most familiar and comfortable with.

Installing CygWin + GIT

Installing Cygwin couldn't be simpler.

  • Download the Setup.exe
  • Double click for installation
  • Accept the defaults until you reach the package selection screen
  • Select the following packages (if you click 'View' until it is set to 'Full', you get an alphabetized list)
    • openssl
    • openssh
    • git
    • git-gui (graphical front end for git, basic but alright)
  • Click next and watch the pretty color bars move to the left.
If you ever want to add or update packages to cygwin, you just rerun the setup. It'll auto-detect a previous install and run in update/upgrade mode.

OS X

First, install MacPorts. Their documentation is thorough and complete, so the process is not repeated here. Next, issue the following commands

$ sudo port selfupdate
$ sudo port install git-core

That's it, you're done.

Help! I got a 'command not found: port' error!

You skipped the MacPorts installation instructions didn't you? *hint* check the part about modifying your PATH.

Using Public/Private Keys with GIT

GIT operates over SSH and it's very common to use public/private key authentication for interacting with remote repositories. This section walks you through creating these keys, setting up a ssh config entry for the repository, and doing a quick "clone, branch, change, merge, push" cycle. This is a typical development cycle.

Creating public/private keys

For more information on public/private key authentication please see IBM's tutorial. The following command initiates the creation of a DSA public/private key pair.

$ ssh-keygen -t dsa

This walks you through a series prompts, the first of which is:

$ ssh-keygen -t dsa
Generating public/private dsa key pair.
Enter file in which to save the key (/home/James/.ssh/id_dsa): 

Since we're creating a pub/priv key for git, let's save the key as "git_dsa". Then you are then prompted for a password. Choose a decent password for your new key.

Enter file in which to save the key (/home/James/.ssh/id_dsa): /home/James/.ssh/git_dsa
Created directory '/home/James/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again:  
Your identification has been saved in /home/James/.ssh/git_dsa.
Your public key has been saved in /home/James/.ssh/git_dsa.pub.
The key fingerprint is:
1f:d8:9b:9f:69:94:3d:ed:bc:cc:62:0f:18:2b:6a:34 James@James-PC
The key's randomart image is:
+--[ DSA 1024]----+
|                 |
|                 |
|                 |
|         o       |
|        S o. o . |
|       E . +* o .|
|      . ..++ . + |
|       .. ...=+ o|
|      ..   .= o=.|
+-----------------+


Notice that we gave the full path to the new key and the ~/.ssh directory is created for us. That's all there is to creating a key.

Setting up the ssh config file

This is covered in great detail in the Creating_SSH_Shortcuts_Using_SSH_Config tutorial on the HowTo_Pages, so here we'll just show a typical configuration for a git host. Open up your ~/.ssh/config with your favorite text editor and create the following entry:

Host git
    Hostname mygit.host.com
    User gituser
    IdentityFile /home/James/.ssh/git_dsa
    

Notice that we've specified the key to use with the full path to our git_dsa created in the previous step.

Important!

If this is your first time creating a .ssh/config file you likely need to correct the permissions. This is done by

$ chmod 600 ~/.ssh/config


Giving out public key to the git host

The final step to gain access is giving our *public* key to the git host. It is very important that you only give your *public* key (this is the file ending in .pub). You should never, ever, not even on threat of having to watch endless repeats of Family Ties for the rest of your life give anyone your private key file.

You can do this via email, or scp if you own the account you're using the key for. If you control the host/account you wish to log into simply copy the contents of the git_dsa.pub into the ~/.ssh/authorized_keys file. If it does not exist, create it.

Then you can log in via:

$ ssh git

Using SSH Agent for single password

Windows/Cygwin PreRequisite

On windows there are a few extra steps, but we're used to that by now. First, we need to modify our ~/.bashrc to contain the following (thank you Web Weaver Tech):

export SSH_AUTH_SOCK=/tmp/.ssh-socket
ssh-add -l 2>&1 >/dev/null
if [ $? = 2 ]; then
   # Exit status 2 means couldn't connect to ssh-agent; start one now
   ssh-agent -a $SSH_AUTH_SOCK >/tmp/.ssh-script
   . /tmp/.ssh-script
   echo $SSH_AGENT_PID >/tmp/.ssh-agent-pid
fi
function kill-agent {
   pid=`cat /tmp/.ssh-agent-pid`
   kill $pid
}

Next, enter the following in your environment variables (Control Panel => System => Advanced Settings => Environment Variables):

NAME: SSH_AUTH_SOCK
VALUE: /tmp/.ssh-socket

After this, the standard directions below should work for you.

All Other Platforms

You may notice you still have to use a password to login, so why all the trouble of creating a public/private key? Well, actually, with the SSH Agent you only need to enter your password once. There is a fix for this though. Upon opening terminal, issue the following command

$ ssh-add ~/.ssh/git_dsa

Where 'git_dsa' is the name of the key you wish to add. You can add as many as you like and, obviously, the names may differ. After entering your password, you'll be able to log into any host using this key without a pass for as long as you're logged in. If using our previous host example, we would clone a project called "Foo" by using the full path to the project.

Cloning a project over ssh

Now we can fetch projects from our git user. If you were on windows, I know it feels like a lot of work. But we're almost there!

$ git clone ssh://git/full/path/too/Foo.git 

From there on out, it's standard git management.

Git Work Flow

This is just a quickie run through of a git work flow. We're going to assume you've cloned a git project named Foo.

Create and Checkout a Working Branch

As mentioned before, branching is a first class citizen. Before we make any changes, let's create a working branch. We'll call it "development".

$ git branch development

To see our branches, execute the branch command with no arguments.

$ git branch
    development
 * master

The 'master' branch is the default main branch. The development branch is the one we just created. The '*' prepended to the master indicates this is the branch we're currently in.

To actually use the development branch, we must first check it out

$ git checkout development

Now we see the '*' by development

$ git branch
*  development
    master

The above two steps can be condensed into a single step by:

$ git checkout -b development

This means 'checkout the development branch and create it if it doesn't exist'.

Modify Files and Commit changes

Open a file and make some trivial change and close it. In this case, I modify a file called "temp". Now let's commit our changes:

$ git commit -a -m "Edited the temp file"
Created commit c75b3d3: Edited the temp file
1 files changed, 3 insertions(+), 0 deletions(-)
  • -a commits all changes
  • -m says we're going to enter the comment inline. otherwise a text editor is opened for the commit comment.

Merge development with master

In git, we merge by "pulling" from one branch to another. So to merge with the master branch, we first check out master than 'pull' development into it.

$ git checkout master
$ git pull . development
From .
 * branch            development -> FETCH_HEAD
Updating 6d26cca..c75b3d3
Fast forward
 temp |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

If you check the temp file, you'll see our changes are available. If there were any conflicts you'd be prompted to resolve them. The process should be familiar to anyone used to version control. Since we no longer need it, we can delete the development branch if we wish

$ git branch -d development
Deleted branch development.

Send Our Changes to the Main Repository

All of the steps above only modify our local repository. They have absolutely no effect on the main repository we cloned earlier. If we wish to send these changes upstream we "push" our changes.

But before we do this, we need to catch up to any changes that other developer's may have made with our remote repository. To do this, we should do a git rebase.

$ git rebase origin

This will "sync" our two repositories. Technically, it first rewinds the commits we've made locally, pulls the remote commits, then replays our local commits on top of them. Again, resolve any conflicts that need resolving.

Pushing of changes should *only* be done on bare repositories. If another developer wants your changes, they should "pull" from your repository into theirs.

Finally,

$ git push origin master

Alternate Git Work Flow (working with a remote development branch)

This walks through working with a remote development branch (instead of merging a local branch into master).

List remote branches

$ git branch -r 

You'll get output similar to this (assuming the remote is named "origin")

 origin/HEAD -> origin/master
 origin/dev
 origin/development
 origin/master

Checkout the remote branch

$ git checkout -b development origin/development

This will create a local branch named development that is a clone of the remote branch development on origin.

Checking out a remote branch with tracking

You can also check out a remote branch with tracking. Tracking "links" a branch with a specific remote branch. The benefit is that you no longer have to specific the remote branch when pulling, rebasing, or pushing changes.

So, instead of:

$ git push origin development

Or:

$ git rebase origin development

You'd simply have to do:

$ git rebase
$ git push

To check out a remote branch with tracking:

$ git branch --track development origin/development && git checkout development

Rebase the development branch

Next, you rebase against the remote development branch, this is pretty much the same as the previous example except we must specify the remote branch name

$ git rebase origin/development

Again, resolve any conflicts that might occur.

Push our changes to the central repository

$ git push origin development

External Links