Download & Install Git on your Machine

open up your Terminal / Console and type

 git version

if this command is unknown, you have to install git

  • Mac / Linux: most likely already installed
  • All other operating systems: git-scm.com


Setup

If you're using git for the first time, you might want to setup some configuration settings:

 git config --global user.name "Max Mustermann"
 git config --global user.email max@mustermann.de

These two settings help to identify you when you're pushing your files to a remote server.

Git can produce colorful output with some commands; since some people hate colors way more than the rest likes them, by default the colors are turned off. If you would like to have colors in your output:

 git config --global color.diff auto
 git config --global color.status auto
 git config --global color.branch auto

Sometimes you have to enter messages in a terminal editor and the default may be vim or emacs. If you like to use another editor, there's this global option:

 git config --global core.editor "nano"

These settings are global (for your machine), so you only need to do this once.

Create the Project Folder

Create or select your project folder, change to this dir in terminal and init git. This will create a ".git" folder inside your project. If you want to remove the git version control for whatever reason, you just need to delete this folder

 cd ~/path/to/your/projectFolder

Now create a file. Either in your editor, or use the terminal:

 touch README.md

We're creating a README textfile in the markup language. This file will be shown in most git servers as a starting page and should contain a general description, install and/or compiling instructions, contact and the license.


Init the Project Folder

Now, let's add git to our new folder:

 git init

To check if this was successful you can query the status:

 git status

This is acutally a command, you should remember!

Adding Files

The status should say something like this:

COMPUTERNAME:TestHub username$ git status
# On branch master
#
# Initial commit
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#	README.md
nothing added to commit but untracked files present (use "git add" to track)

So, the status is very useful, as it tells us everything: There's a file ("README.md") that is present in the directory, but not under git's version control. So we add it:

 git add README.md

(Remember to use the TAB-Key for an autocompletion!)

Check again:

 git status

All fine. If you have more files to add, you can use the wildcard operator * like this:

 git add *
 git add *.m
 git add *.* 


Change Stuff

Open REAMDE.md and type something.

Then use the terminal to check the status:

 git status


And we should be informed, that the file was modified and we should commit our changes. Let's do so:


Commit Changes

Commit early and commit often! Really, I mean that! And don't put in glibberish, make a useful comment about what you did:

 git commit -a -m "initial commit"  

This should be the result:

[master (root-commit) b109597] initial commit
 1 file changed, 1 insertion(+)
 create mode 100644 README.md

now, check the status:

 git status

and we should see a clean working directory:

# On branch master
nothing to commit (working directory clean)


Change Stuff (Again)

Repeat step 5 and change the README.md file.

Add a new file "LICENSE.md"

 touch LICENSE.md

Then check the status again

 git status

And you should see:

# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#	modified:   README.md
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#	LICENSE.md

Remembering git status really helps, as it basically tells you everything you have to do:

  1. Changes not staged for commit (so use: commit -a -m "Comment"!)
  2. Untracked files: use "git add <file>..." to include in what will be commited

btw, there's also:

 git help
 git help commit

This explains the -a ("all files") and the -m ("message") parameters.

Exit help with ctrl+Z.


Commit (Again)

Commit early and commit often! Really, I mean that! And don't put in glibberish, make a useful comment about what you did:

 git commit -a -m "Created License, Added welcome text to README"  

Something like this should be the result:

[master bf50d31] Created License, Added welcome text to README
 1 file changed, 7 insertions(+), 1 deletion(-)

now, check the status:

 git status

and we should see a clean working directory:

# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#	LICENSE.md

oh, wait we didn't add the new LICENSE.md file:

 git add *
 git commit -a -m "Added License"
 git status

okay, now it's a clean working directory.

# On branch master
nothing to commit (working directory clean)

btw, remember to use the Arrow UP and Arrow DOWN keys to jump in your terminal command history and reuse what you've typed before.


What's the diff?

Time for a cup of fresh coffee. Now you have a nice version control system for your project and you can work with git locally.

YAY!

So, to see the commits, use:

 git log

and you'll see something like this:

commit a180dfb8aa6fc019fc2ed38a13ee4de517f8256a
Author: Max Mustermann <max@mustermann.de>
Date:   Thu Apr 18 12:56:02 2013 +0200

    Added License

commit bf50d31ecb17998dd45d462c9c2304a12dab3c1d
Author: Max Mustermann <max@mustermann.de>
Date:   Thu Apr 18 12:53:30 2013 +0200

    Created License, Added welcome text to README

commit b10959718cf43e5206ddbffc6b37ccc99726ee74
Author: Max Mustermann <max@mustermann.de>
Date:   Thu Apr 18 12:44:09 2013 +0200

    initial commit

Now you see why we wanted to set the name and email...

you can also try blame

 git blame README.md

Now, change the REAMDE.md again and then see what's the difference to the previous version:

 git diff 

This will automatically show you the diff to the last commit:

diff --git a/README.md b/README.md
index d722c4c..2b1caa7 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,6 @@
 TestHub
-by BUW
+by Michael/BUW
 
-Hallo Welt!
+Hello World!
 
+This will be a cool project! Even cooler, because now I can use git.


GUIGraphical User Interface or not to GUIGraphical User Interface

Though, if you're not a nerd, you might enjoy a decent graphical user interface. Time to grab the GitHub.app

Drag your project folder onto the app.

With the GitHub.app, you experience a nicer commit history, including a file view with diff changes, you can admin branches, and configure your repository.

While we're still local, let's explore another really powerful git feature:

Branching

Adding another branch to your git repo is like duplicating the whole project folder (including the git commit history) and working on a second, completely different version. Like a real folder, you can delete this branch later on or (unlike a real folder) merge it with the current main branch.

So, this is perfect, if you want to test something or if you need to rearrange a lot of files and run in the danger of breaking your project.

Branches are simple and inexpensive, so don't hesitate to create new branches!

Let's see which branch we're currently working on:

 git branch

and we see it's

* master

Create a new branch

 git branch -b testing

you can also add -v to see the latest commit:

 git branch -v

and we see:

* master  a180dfb Added License
  testing a180dfb Added License

So, we have our new branch, but the * indicates the active branch, which is still the master branch, let's change the branch with checkout:

 git checkout testing

the reply is:

M	README.md
Switched to branch 'testing'

Test again with

 git branch


Now, we need to change a couple of things, for example, adding some files:

 touch file1.txt
 touch file2.txt

Open a Finder or Explorer window and see, how the directory changes!

 git status
 git add *.txt
 git commit -a -m "added file1 and file2"
 git status 

if we call now:

 git branch -v 

we'll see the difference:

  master  a180dfb Added License
* testing 4aadefc added file1 and file2

But the real magic happens now, when we switch back to the master branch. Watch the directory!

 git checkout master
 git checkout testing

nice, isn't it?

Now, you could either delete the branch if you think it was crap (using git branch -d testing or (and this is what we're going to do) merge this branch with the master branch. We need to switch to the main branch first, and then merge it with the testing branch:

 git checkout master
 git merge testing

And see the result:

Updating a180dfb..4aadefc
Fast-forward
 README.md | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)
 create mode 100644 file1.txt
 create mode 100644 file2.txt

merging branches automatically commits, so we don't need to do anything:

 git branch -v

if you like, you can delete the testing branch now:

 git branch -d testing


Remember that up until this point, we were using git locally. Now, let's create an online repository to work with others

Using Remote Git Servers

You can extend your local git repository with an online git server. This has two advantages:

  • If your computer or hard-disk is lost or damaged, you still have your online repository
  • You can now collaborate with other people and work on the same files at the same time

There are a couple of online services:

  • You set up your own git server (need to install git on your server and have webdav, ssh or other access to the server)
  • You use one of the many online services, for example:
    • github.com, free for open source projects
    • bitbucket.com, free for small groups of up to 5 members
    • please help adding more services here…


The following example shows how to create an account and a repository at github.com:

  1. go to github.com and create an account
  2. next, you need to create SSH Keys; this enables you to upload your files onto the server. You only have to do this once for every computer you're working on:
    1. This step is not part of this tutorial, but it's really simple, see:
    2. Generating SSH Keys


Creating an Online Repository

If you've uploaded your public SSH key for your machine, you can continue setting up your user account and finally, create a new repository:

  1. create a repository
    1. Add a repository name and a nice description (so that others know what this is about!)
    2. select "public" (free) or "private" (paid)
    3. For new repositories, you might select to "initialize this repository" and add a ".gitignore" file, for our example, do not check this

Now we see the commands we need to add. Most of them are already done, we just need to add the remote server and push our repository to the server (that means uploading the files)

Note the (probably) 5th and 6th line saying:

 git remote add origin https://github.com/NameOfUserOrOrganization/NameOfTheRepository.git
 git push -u origin master

So, let's add the remote origin (btw, this will also work via ssh)

 git remote add origin ssh://myserver.com

Push Changes to the Server

Pushing Changes, means uploading to the server. Because you can have more than one remote server in your repository, you have to state its name:

 git push -u origin master

You are probably promted to give your github username and password for the first push.

The result should look like this:

Counting objects: 12, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (8/8), done.
Writing objects: 100% (12/12), 1.08 KiB, done.
Total 12 (delta 0), reused 0 (delta 0)
To https://github.com/NameOfUserOrOrganization/NameOfTheRepository.git
 * [new branch]      master -> master
Branch master set up to track remote branch master from origin.

Changing Stuff (Again)

This time, we want to simulate someone else changing our sources. The easiest way for this demo, is to go to github.com and edit the Readme file. E.g. apply some formatting ('#' creates a headline), and give it a commit message.

Pull or Fetch and Merge

Git has two commands to update itself from a remote repository:

 git fetch 
 git merge 

will synchronize you with another repo, pulling down any data that you do not have locally and giving you bookmarks to where each branch on that remote was when you synchronized. These are called "remote branches" and are identical to local branches except that Git will not allow you to check them out - however, you can merge from them, diff them to other branches, run history logs on them, etc. You do all of that stuff locally after you synchronize.

The second command that will fetch down new data from a remote server is

 git pull

This command will basically run a git fetch immediately followed by a git merge of the branch on that remote that is tracked by whatever branch you are currently in. Running the fetch and merge commands separately involves less magic and less problems.

You should see this reply:

remote: Counting objects: 5, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://github.com/NameOfUserOrOrganization/NameOfTheRepository.git
   4aadefc..aca593b  master     -> origin/master
Updating 4aadefc..aca593b
Fast-forward
 README.md | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

If you like, you can repeat this with fetch & merge instead of pull. First, edit the README.md again or select a LICENSE.md. Then type:

 git fetch

The result is the same as before, only without the Updating... / Fast-forward part

 git status

...however, reveals that our local branch is one commit behind:

# On branch master
# Your branch is behind 'origin/master' by 1 commit, and can be fast-forwarded.
#
nothing to commit (working directory clean)
 git merge origin/master

and now the result is:

Updating aca593b..e2c12f6
Fast-forward
 LICENSE.md | 1 +
 1 file changed, 1 insertion(+)

and git status sais:

# On branch master
nothing to commit (working directory clean)


IDE[[wikipedia:Integrated development environment]] Integration

While it's important to understand git, it's really not necessary to work with the terminal. Many IDEs have excellent version control support. For example Xcode, Coda or Sublime2 (via Plugin) have really nice GUIGraphical User Interface based git/svn integrations.


Where to go from here