git with the program

code :: source code management with git

git is a distributed revision control and source code management (SCM) system with an emphasis on speed. git was designed by linus torvalds, of linux fame, for managing the development of the kernel. every git working directory is a fully fledged repository, complete with revision tracking abilities independent of a network or centralized server. git is 100% open-source, freeware, and distributed under the GNU general public license v2.

why use git?

speed and performance.
git is very fast. nearly all operations are preformed locally, giving it a huge speed advantage over other centralized systems which constantly have to communicate with an external server. git handles large repositories very well with is simple, yet very effective, design. and it's programmed in C, which reduces the run-time overhead of other higher level programming languages.

complete history.
every git repository, whether created locally or cloned from a remote location, contains its entire history. once you have a copy of the repository you can move forward and backward in time from the bleeding edge to the initial commit. if you make a few mistakes, introduce some new bug, or just want to reset to a previous state, your just one command away.

git is distributed.
managing your project with git can be either completely offline or a combination of on and offline. git can do almost everything offline: adding, committing, branching, merging, etc. many SCMs think this is a bad thing, but i couldn't disagree more. you can use git with a centralized server or not. it has all the powers of subversion and more.

cheap branching.
with git, it takes less than a second to create a branch. everything happens in your local repository so there's no need to connect to a central server. you can create a branch to test a new feature, try new techniques, etc, without affecting your "master" branch. you can switch between branches on the fly and watch the contents of your working directory change immediately after executing the command. and, if you want, you can branch out from another branch, or merge it back into another branch.

git is clean.
there is only one .git folder for your entire project. other source code management systems, like subversion, create SCM folders in every directory. with git you can easily remove or rename directories in your repository without the worry of messing up things up. and if you want to remove SCM from your project is it's a snap with git, just delete the single .git directory and you're done.

data assurance.
the data model that git employs ensures the cryptographic integrity of every bit of/in your project. every object in your repository is checksummed via SHA-1 hash. this hash both identifies objects and is used to check them in and out of the repository. it's impossible to retrieve something from a git repository other than exactly what you put in. it's also impossible to change anything in the repository (filenames, content, timestamps, commit messages, or any other tracked data) without changing all the hash ids of everything after it. a real world example of this is when the linux kernel site was hacked.


the git community uses many terms and abbreviations, let's start by demystifying some of them

SCM = source code manager/management
an application used to manage your code. some examples would be:

  • git
  • subversion (svn)
  • mercurial
  • bitkeeper
  • cvs

each of these work differently. they have similar goals, managing your code, but do it in very different ways. wikipedia has a good article on comparing and contrasting them. this article will (obviously) be focused on git, but i will mention SVN from time to time.

where all the git magic occurs. these are the "behind the scenes" files that git creates and uses, these files all live in the .git directory.

a commit is a full snapshot of your repository at a given time. git identifies commits by a 40 character SHA-1 hash. but 99% of the time people use the "human hash" version, which is just the first 7 characters of the hash identifier (git will complain if a shortened id is ambiguous and give you suggestions). if you're worried about hash collisions in git, read linus' retort from the mailing list.

repo = repository
a git repo is a repository of code that's being managed by git.

working directory
the area where your checked out files reside. files in the working directory are ready to be viewed, modified, or added or removed from the index.

the staging area where files are added/removed prior to committing them to the repository. this index is also sometimes referred to as the staging area or the directory cache.

we like to say that git tracks your changes. any file you choose to add to your repository index is tracked by git. it will notice any change, no matter how subtle.

a pointer referring to the most recent commit on the current branch. when you checkout a previous commit your HEAD will move to whatever point you have checked out.

the given context of your repository. git enables you to have multiple branches that have their own commits. a branch can be based upon other commits or work autonomously from others. (e.g. the master being the stable code branch, while the others are for new features, bug fixes, etc. or a repo with three branches -bin: compiled application, -src: source code, -docs: documentation.)

a special list of commits used to hold temporary changes, like an internal git clipboard.

this is git configuration data that's specific to a repo. this information is found under .git/config, in plain text. it holds information about remote repos, the correlation between local and remote branches, and more. there is also a global git config which hold default configurations for all repos. the global config lives in your home directory in a file named .gitconfig

these are special event-based scripts to enforce policy. hooks are local only files that also live in the .git directory. they are user specific and are not cloned/pushed/pulled from remote repos.

data structures

in general, git only has two data structures: the mutable index that caches information about the working directory and the next revision to be committed; and an immutable, append only object database. the index is used as a correlation between the object db and the working tree.

there are four types of objects in the database:

  • blob: the raw content of a file. No filename, timestamp, or other metadata.
  • tree: a list of filenames, complete with metadata , and a symbolic link to the blob or other tree that it's describing.
  • commit: this object links tree objects together into a history. it contains the name of the root level tree, timestamp, user supplied commit message, and the names of zero or more parent commits.
  • tag: this is a simple user defined reference to another object (usually a commit id) that can hold more metadata about an object. frequently these are used as the equivalent of bookmarks for release versions (e.g. v1, v1.5, v2, etc)... but since they are user defined use them as you like :D

the object database is located under .git/objects/
each object is identified by a SHA-1 hash of its contents. for optimal speed and indexing, the object is lives in a directory that's named with the first two characters of the hash, then the object file itself is named with the remaining 38 characters of the hash. this creates a fixed 256-way partitioning of all objects. this even distribution will optimize file systems which have restrictions on the total number of files per directory. with each revision of a file, its contents change. thus git recognizes the file as a new hash, and stores it as a new blob. and in the opposite situation, files that do not change or just change name or location will not be rewritten to git's object database. examining the trees in each commit object will reveal this correlation. when the contents of a file is saved to a blob, it is done using zlib compression. note, you can create packs of objects to save disk space which alternatively uses the delta compression method. this is usually only necessary in huge repositories with large commit histories.

download & install

git is available in two flavors: CLI (command line interface) and GUI (graphical user interface) for the big three operating systems: windows, linux and mac. the source code is also available.

personally i use, and suggest first learning, the command line version. this article will focus on git from that perspective. if you first understand the commands, using a GUI will make a lot more sense.

additional front-end tweaks

**this section is completely optional, and has no effect on using git.**

i primarily use windows (i dabble in linux), and have a few more notes about git for windows. windows doesn't have a native "terminal", only a lame "command prompt". so git is shipped/powered by a terminal emulator called minGW. this application by itself is amazing. it adds many linux bash commands (and shell scripts!) to windows that you can use with or without git (e.g. grep and ssh). but alas, the minGW terminal window is pretty lack-luster. that's why i use a terminal front-end called console2. console2 adds lots of great features, some functional others aesthetic. it supports multiple terminals, i personally use the windows command prompt, git/minGW, and shortcuts to the python interpreter and mysql console. it features tabs for multiple open terminals, copy/paste functionality, customizable hotkeys, resizable windows, transparency, background images, personalized colors, and more.

after installing console2 you need to set it up. run the application and right click anywhere on the screen and select: edit >> settings. then choose "tabs" from the accordion menu on the left. the default tab for the windows command prompt should already exist, notice the "shell" value is set to cmd.exe create a new tab and name it git bash (or whatever). set the shell value to your install location of git with the \bin\sh.exe application suffexed with --login - i
mine looks like this:
C:\Program Files (x86)\Git\bin\sh.exe --login -i

you might also want to make this your default tab for console2. while you're here, check out the other options like the cursor style and color, window title and icon. also, go under the "behavior" options and enable copy/paste (you'll thank me later). you can paste by pressing the insert key or right clicking the window and selecting: edit >> paste. to copy text from the terminal hold the SHIFT key and highlight your text with the mouse (yeah i know, it sux using the mouse as opposed to the keyboard arrow keys, but it's better than nothing).

custom welcome screen.
it's possible to setup git to run a number of tasks when it first loads via a shell script. tn your user's home directory (windows: C:\users\your_user_name\   linux: ~/) there's a hidden file called .bashrc (if it's not there just create it. enter: touch .bashrc in the terminal). you can do two things in this file, create aliases and set default files to run on startup. the last line on my .bashrc is ~/ — this a script that displays some ascii art i made. since it's listed (on its own line) in the file, it will be called after application startup. the contents of that file are as follows:

echo -e "                             "
echo -e "  \e[00;32m      xxx         "
echo -e "  \e[00;32m      xxx        \e[01;33m welcome to GIT"
echo -e "  \e[00;32m xxxxxxxxxxxxx   \e[01;33m the information manager from hell"
echo -e "  \e[00;32m xxxxxxxxxxxxx    "
echo -e "  \e[00;32m      xxx         "
echo -e "  \e[00;32m      xxx         "
echo -e "  \e[00;32m                 \e[01;37m " $(git --version)
echo -e "  \e[00;31m xxxxxxxxxxxxx   \e[01;37m powered by console 2.00.148"
echo -e "  \e[00;31m xxxxxxxxxxxxx    "
echo -e "                             "
echo -e "  \e[01;30m   xx   xxxxxx    "
echo -e "  \e[01;30m  xx    xx xx    \e[01;37m run \e[00;32m'git help git'"
echo -e "  \e[01;30m xx     xx  xx   \e[01;37m to display the help index."
echo -e "  \e[01;30m xx         xx    "
echo -e "  \e[01;30m  xx       xx    \e[01;37m run \e[00;32m'git help '"
echo -e "  \e[01;30m   xxxxxxxxx     \e[01;37m to display help for specific commands."
echo -e "  \e[01;30m     xxxxx        "
echo -e "\e[00m                       "

if you save that file as in your home directory, add it to the .bashrc, and restart console2... BOOM! some awesome looking ascii art appears every time git runs :D
ok, enough of that, let's take about git.


you should start by globally telling git who you are. your name and email are used in all commit messages. the global values will be used by default for all your git repositories.

git config --global "xero harrison"
git config --global ""

this information is saved in the .gitconfig file in your home directory
(windows: C:/user/your_username/   linux: ~/)
to view this information use:

git config
git config

if for some reason you'd like to override your default config settings in a specific repo issue the commands:

git config "xero harrison"
git config ""

notice we dropped the --global flag, this tells git to apply these only to the repo we're working in.

terminal navigation

it's easy to reenter previous commands.
you can scroll through your terminal history by pressing up and down.

most commands can be auto-completed by pressing the tab key, even branch and tag names.
gi <tab> chec <tab> ma <tab>
will autocomplete to:
git checkout master

creating aliases will speed up your workflow by making you type less. you can manually add them to the .gitconfig file but there's a simple command to create them automatically. if you want to add a global alias to call the git checkout command simply as git co enter:
git config --global
if you wanted to add an alias for just the current repo drop the --global flag.

a good, all be it very dangerous, alias git undo will remove any changes in the current branch. since these changes have not yet been committed to SCM this action is irrevocable.
git config alias.undo=reset --hard

one of my favorite aliases is a custom version of git log. it adds cool ascii art branch graphs, and IMHO just the right amount of commit info is git graph:
git config alias.graph=log --graph --color --pretty=format:"%C(yellow)%H%C(green)%d%C(reset)%n%x20%cd%n%x20%cn%x20(%ce)%n%x20%s%n"

this brings me to paging. when your repo has a long enough history, like 6 or more commits, not all of that data can be displayed on the screen at once, so the terminal will page it. for those of you unfamiliar with the linux terminal, paging describes when only one page of data is displayed at a time. this feature is a holdover from the days before you could just scroll backwards, but it makes viewing a large amount of data more pleasant. when information in the terminal is being paged the command prompt at the bottom of the screen will be replaced by a colon and the blinking cursor. if you want to move up or down a single line press the up or down keys. to move down an entire page at one press the space bar or to move up or down a page press the page up or page down keys. when you reach the end of your paged data the colon at the bottom of the screen will be replaced with the word END in an inverted color pallet. to quit paging, at any time, just press the Q key.

terminal primer

first off, every command in both git and the terminal have help documentation built in. for general terminal commands, call the command with the --help flag to view the man pages for the command
cd --help
ls --help
grep --help

git has its own command called help, that you pass the command you want to know more about to it
git help branch
git help commit
git help stash

working with the file system.
you change directories with the cd command:
move to a subfolder
cd (name)
move up a directory
cd ..
move up a directory and into a subfolder called docs
cd ../docs
change to your home directory
cd ~/

You can view files in your current directory with ls command:

create a directory
mkdir (name)

delete a file or directory
rm (name)

delete a directory and all its files and sub directories
rm -rf (name)

rename/move a file
mv (old) (new)
mv README.txt
mv dev/file.txt release/file.txt

basic concepts

unlike other SCMs, git tracks the states of files, not necessarily the files themselves.

if you want to see a list of the git commands just open the terminal and enter

this will display a list of the so-called "porcelain" commands. these are the high level commands that you will normally use. but if you want to see the full list of "plumbing" commands that the higher level commands and git itself uses internally enter
git help --all

if you want to see the current version of git that your using enter
git --version

starting out
to initialize a git repo in your current directory
git init
git will display a message that the repo was initialized successfully, similar to:
Initialized empty Git repository in c:/repos/test/.git/

you will also notice that the directory name in the terminal will now say (master) after it. this tells you the current branch you're working on with git (master is the default).

when git creates a new repository it's empty by default. to manage a file's content you'll have to explicitly add it to the repo to be tracked.

ignoring files
create a file called .gitignore in the root of your project (actually you can put this file anywhere, or put multiple ones in multiple directories). then list all the files or expressions for files git should ignore. e.g.
#this is a comment
but just creating the .gitignore isn't enough... you'll need to add it the repository for git to track.

adding and staging files to be tracked by git
once you have created or edited a file in your repo, stage it
git add (filename)
once the file is staged, git is ready to add it to the next commit.
you can add files individually by using git add with a filename
git add index.php
or multiple files
git add index.php login.php /somedir/somefile.php
or you can add all the files in the current directory by using
git add .
(fyi: the argument . [period or dot] in linux parlance, is shorthand for the current directory)

moving, renaming, and deleting tracked files
once you have added a file to git you can move or rename it the same way as you do in the terminal, just prefix the command with git
git mv (old file) (new file)
similarly, you remove files in the same manner
git rm (filename)
moving and renaming files this way will keep your git workflow simple. in the end, calling git mv is the same as if you'd delete the file with git from a location then add it back in a new location. since the content of the file has not changed, only its location, the file will still have the same SHA-1 hash and a new blob object will not be added to the database. only a new tree and new commit will be created.

viewing the current status of your working directory
to see what's ready to be added or removed in your next commit
git status

or use the --short or -s flag to view the shortened output
git status -s
git status --short

calling status will show you a list of the files to be added, modified, or deleted from the repo in the next commit. this gives you a general overview of the differences between your index and HEAD commit as well as untracked files in your working directory. but you can dig deeper than that...

to view the exact changes made to a particular file you can diff it
git diff (filename)

the diff output will show you all the changes made to the file on a line by line basis. additions are marked by a plus and deletions are marked by a minus (optionally they are colored in green or red, respectively, if you have colored output enabled).

if that's too much data for you to digest you can use the --stat flag to show only the number of insertions and deletions in the file.

git diff (filename) --stat

you can also diff branches
git diff (branch name) (other branch)

saving a moment in time
once you have made some modifications, and added all the files you want to track, you're ready to commit it to the repo and save a snapshot of that moment.
git commit

the commit command has a few arguments that you might want to use.
git commit -m 'your commit message'
use the -m flag to append a message to your commit inline, otherwise git will open your text editor for you to enter a message in.
git commit -a
using the -a flag will automatically add all the files already staged that have been modified since the last commit. that means any files you've already added, not new ones.
or you can combine those two into one!
git commit -am 'a commit message goes here!'

viewing the state of files in your index and working directory
to view files that have been added to the index and working tree use ls-files.
git ls-files
to show detailed information about staged files
git ls-files --stage
to show other untracked files in the working directory
git ls-files --other
to view ignored files
git ls-files --ignored

viewing history
git has a tool to help visualize the commit history of your repo called git log. the log aggregates the data from your commits including: the manifest of files, commit message, committer name and email, date and time, and the parent commit(s). the log command has a variety of options so you can configure it however you like. or use it in different ways for different scenarios.

running git log with no options will give you a chronological list of commits from newest to oldest.
git log
for a more compact view add the --oneline flag
git log --oneline
but so far these are linear views of history. if you're interested in seeing branches use the --graph flag. this will add cool ascii art branch diagrams to the log results.
git log --graph

you could also combine the --graph and --oneline flags for a more compact graph
git log --oneline --graph
another command I find useful coupled with --graph is --color. this will colorize the output of the log command. in my opinion, this makes viewing the branch topology much easier.
git log --color
another interesting command is --reverse, this will display git's history in reverse order
git log --reverse
so far we've been looking at the logs of our entire repo. but if you want to view the history of a single branch just append the branch name to the command. these results will show you all commits that are "reachable" from that branch. this will include parent commits from the branch you diverged from.
git log (branch name)
it's also possible to have git log show you commits that are present in one branch, but not in another. this is achieved by using two branch names with the second being prefixed with an up carrot (^)
git log (branch name) ^(branch name)
e.g. show a log of the commits in the topic branch that are not in the master branch:
git log topic ^master
log will also allow you to limit your results. the simplest method is to use the -n flag, where n is the number of commits you want to show.
show the previous commit
git log -1
show the previous 5 commits
git log -5
you can also specify a range of commit in since..until format (this is called symmetric difference)
git log (commit id 1)..(commit id 2)
git log dd342da..f9c0201
notice in your results commit dd342da63c is not displayed. git log's formatting will always give you everything beyond your first supplied revision. the command above is the same as calling:
git log ^dd342da f9c0201
your basically saying: show a log of commits that are reachable from f9c020193e excluding those reachable from dd342da63c.
you can also customize the output formatting if the log results by using the --pretty flag.
pretty-print has a few "simple" options: oneline, short, medium (default), full, fuller, email, and raw.
but you can define your own custom style with format. format has *A LOT* of options.
i have overviewed them in this gist on github.
personally, this is the pretty-print that i prefer:
but how you prefer your output is complete up to you. now that you have your "perfect" log created, i suggest making it an alias. then displaying your log, formatted the way you like it, is just one command.

log as lots more options, take a look at the git help (git help log) for a complete list.

navigating commits
if the main point of git is tracking the state of files in your repo, what's the point if you cannot view them again later? git allows you to "travel through time" and revert your working directory to any previous state. to do this you use the checkout command.
git checkout (reference) (filename)
the reference can be a commit id (SHA-1 hash), branch name, tag name, or HEAD reference. optionally, you can supply a filename with your reference. if a filename is used, only that file will be reverted, otherwise the entire working directory will be changed.

a note about HEAD references...
at any given time a particular commit is labeled as the HEAD revision. this is the active point of development in your repo. whenever you add a new commit the HEAD will reference the newly created commit id. but if you checkout a previous commit, the HEAD will be moved to that particular commit id. when the HEAD is not pointing to the current tip of a branch this is called a detached HEAD. please note that you cannot intrinsically commit from a detached head. but it is possible to branch off from it and add commits to the new branch. moving around in history you will eventually want to put the HEAD back to bleeding edge and continue work as normal. the easiest way is to just checkout that branch again.

but calling checkout with just HEAD makes no sense.
git checkout HEAD
since the HEAD is always where you currently are. instead checkout a previous HEAD.
to checkout the previous commit before the current HEAD
git checkout HEAD^
git checkout HEAD~1
to check out 3 commits before the current HEAD
git checkout HEAD^^^
get checkout HEAD~3
notice a pattern here? there are 2 types of notations related to the HEAD reference. the up carrot (^) means one before, while the tilde (~) means the suffixing number before. as you can guess, no one wants to type 15 carrots to move back 15 commits ;D


why? sometimes you need to experiment with your project, but don't want to mess up your current work. perhaps your working on two very similar, yet independent tracks of development. using a branch for each can help you keep your work parallel, yet separate. another reason could be working in a team environment; other people are working on the master branch while you're adding/testing new features in your own branch. later on you can merge your changes back into the main branch along with the work other people have done in the meantime. (more on merging later)

when you create a new branch it forks off from your current commit. any new commits added will be viewed as an independent track of development. other commits can be added to the parent branch without affecting your new, or any other, branch.

to view all the branches in your repo
git branch

notice the asterisk next to your current branch (default is master)? that denotes the branch you're currently working on.

to create a new branch
git branch (branch name)
switch to a new branch (or commit)
git checkout (branch name/commit id)
create a new branch and immediately switch to it
git checkout -b (branch name)
git ships with a branch viewer called gitk. this application shows you a diagram of your repositories history. using the --all flag will show you all the branches in your repo, not just your current one.
gitk --all
you can also view your branches with the log command with the --graph flag
git log --graph
deleing a merged branch
git branch -d (branch name)
deleing an unmerged branch
git branch -D (branch name)


the flip side of branching is merging. once you have completed your work on a branch you can merge those changes into another branch. these changes include file additions, deletions, and modifications. note that the syntax of the merge command takes the supplied branch name and merges it into your current, checked out, branch.
git merge (branch name)
e.g. merge the changes from a branch named topic into your master branch.
git checkout master
git merge topic

for simple merges git will automatically figure out what's different between the branches and combine them (using git diff command internally). but sometimes the differences between branches are too complex or too ambiguous for git to decide on its own. in these cases git will issue a merge conflict. when a conflict occurs, git changes the code in the effected file(s) with conflict markers. these markers make it easy for you to see the differences between branches. all you need to do is delete the markers and leave the correct lines in the file. here's an example of what merge conflict markers look like:

>>>>>>> HEAD
This is the line in the master branch
This is the line in another branch
<<<<<<< branch_name

once a conflict occurs, i find it simple to just grep the files in your repo looking for the conflict markers to find the files that need fixed before the merge can complete.
git status --short | grep "^U[UAD]"
i have this setup as an alias call git conflicts.

once you have fixed all the merge conflicts stage the changes with git add then git commit them to the repository. i almost always mention fixing merge conflicts in the commit message after doing this.

but sometimes after doing a merge things don't work, and you want to revert your repo back to its previous state. to undo a merge you will use the reset command with the --hard flag and set it back to its original head state
git reset --hard ORIG_HEAD


there are two main ways to integrate changes from one branch to another. the simple method previously discussed is the merge. but the alternative is called a rebase. here's the difference, a merge will perform a "three-way" merge between the two newest commits for two given branches and the most recent common ancestor of the two, creating a new commit. the rebase command takes a patch of the changes introduced in one branch and applies it to another branch. the rebase command takes the changes committed to one branch and "replays" them onto another one at a time. bebasing is used to create a cleaner git history. after doing a rebase, run git log and notice that your commit history has been altered. one of your branches will be missing and it's commits will now appear on your other branch, creating a more linear track of development. rebasing replays commits in their original order, as opposed to merging which takes the endpoints and merges them together.

git rebase (branch name)
to rebase the changes from a dev branch onto the master branch
git checkout master
git rebase dev
it's also possible to rebase commits from multiple branches at once. just specify two branch names
git rebase (branch name 1) (branch name 2)
git rebase dev bugfix
you can also specify where to apply the rebase with the --onto flag
git rebase --onto (target branch) (branch to rebase)
git rebase --onto master bugfix
rebasing can get confusing, so git a an interactive rebase tool. use the -i flag to use interactive mode
git rebase -i dev

rebasing changes history!
when rebasing you abandon existing commits and create new ones. although the new commits a very similar they are still viewed differently by git. so, a rule of thumb in the git community is to never rebase commits that you have already pushed to a public repo. the other people working on the project will be very annoyed, when pushing any changes they might have introduced to the branch you rebased will now be unavailable, they will have to rebase their repositories to match then apply their own changes.


git stash will save your uncommitted changes and remove them from the repo. this works almost like a clipboard. if you're working on something and a huge problem pops up. you can stash you changes, fix the crucal bug, commit your fix, then unstash and get back to what you were working on.
git stash "message"
git stash apply (stash id)
cleaning up the stash (removes everything)
git stash clear

remote repositories

so far all of the commands i've talked about are available offline. but let's talk about working with git over the internet. git can work over a few protocols: HTTP, HTTPS, and SSH.

to copying a git repository from an external site use clone
git clone (repo url)
git clone

by default the name of the server you have cloned from is called origin.
if you use the branch command again with the -a flag (all) you can see remote branches as well
git branch -a

so if you make some changes to your local clone of the repo, you can send it back to the server with the push command. you can optionally use a branch name to push a different branch, not just master. by default git push will only push your master branch.
git push (remote name) (branch name)
git push origin master
git push qoob docs

a note about security. git is the so-called: "stupid content tracker". it's primary function is to manage your code. while git has the ability to sync (both to and from) remote locations, security is not an integrated part of git. it's the burden of the server hosting the remote repo to control who has access to it. any remote repo that is "viewable" can be cloned. but unless access has been setup to accept changes it cannot be pushed to by default. i could talk about this all day, but i want to focus on using git more than setting up a server to host it. you can read more about this in the pro-git book.

software evolves over time. and if your remote repo is in active development, there's a good chance your version will eventually fall behind. if you want to get the latest changes from a remote repo, use the pull command
git pull
This also works with branches as well.
git pull (remote name) (branch name)
git pull origin master
git pull qoob docs

once you have done this you can use the git push/pull command on its own and git will add the remote and branch name for you. but personally i like to be specific and tell git exactly what i want it to do.

another way to get remote changes from a repo is the fetch command. fetch is a more atomic version of the pull command. fetch will both pull the new changes from the remote repo but also merge your local changes. note this only applies to your local clone, the merge that takes place after the pull will only be applied to your copy of the repo, but there's nothing stopping you from pushing it back to the server later.
git fetch (remote name) (branch name)

pulling from a new repository
just because you cloned from one repo doesn't mean you're tied to only one. you can add as many remotes as you want so you can pull/push from any/all of them.
git remote show
will list all the remotes for your working repository.
use the -v (verbose) flag for additional information
git remote -v show

adding a new remote
git remote add (name) (url)
to view info about a remote
git remote show (name)

a note about subversion

lots of people love svn and refuse to stop using it. most versions of git come packaged with the git-svn command (if it's not you can download it separately with the same package manager you used to get git. make sure you also have all the required curl bindings.) this will allow you to use git on a subversion repo. and the best part is, the svn users have no idea you're doing it! the git-svn command will convert all your git commands to svn commands when working with the remote repository. for all your local work, use git as normal. let them live in there "little subversion world", and you can live in the future with us using git ;D

when cloning an svn repository use clone
git-svn clone (url)
then use git as normal, add commit, branch, etc. then when you're done, use the dcommit command. this will take all your git commits and package them as svn commits.
git-svn dcommit
if you want to pull from the svn repo use the rebase command
git-svn rebase
this will take all the changes from the remote svn and apply them one at a time into your local git-svn repo. by using the rebase command this will create a cleaner git history in your repo and allow for a simpler svn syncing.

public git hosting

there are many free/pay sites online to host git repos. most of the free plans focus on open-source projects, and thus are public. if you want a private repo you're more than likely going to have to pay.
here's a list of some of the most popular git hosting sites:

sources (giving credit where credit is due)

everything in this post i learned from using git and reading about it. the following resources are both my citations for this article and a great wealth of knowledge for learning more about git (this article only scratches the surface).