Git quick reference card
Table of Contents
- Getting started
- Git basics
- Configuring your name and email address
- Getting a Git repository
- Recording changes to the repository
- Viewing the commit history
- Undoing things
- Working with remotes
- Tips and tricks
- Git branching
Why Git is better than X?
Excellent branching and merging
In Subversion, branching and merging is hell: everybody stops work until merge is done.
Branching operations (nearly instantaneous) are Git's "killer feature".
Git encourages a workflow that branches and merges often, even multiple times a day. This can literally change the way that you develop.
(Nearly) Every operation is local
- No network required (you can work offline or off VPN).
- Everything is fast.
Git is a distributed version control system.
Sharing in Git only happens when you want it to (
The 3 states
- Staging area ("cache") = index of what will go into your next commit
- Staging files = adding snapshots of them to the staging area
- Committing files = taking them as they are in the staging area, storing them permanently in Git
- Compressed database in the Git directory
Configuring your name and email address
Set your username and email address explicitly:
git config --global user.name "Your Name" git config --global user.email email@example.com
That goes in file:///cygdrive/d/Users/fni/.gitconfig.
Getting a Git repository
Start to track an existing directory in Git:
It creates and initialize the Git directory (
Clone an existing repository:
git clone git://github.com/fniessen/repo.git
It pulls down every version of every file for the history of the project.
Protocols for remotes
ftp:// are not recommended)
Recording changes to the repository
- Each file can be in one of two states:
Checking the status of your files
Tracking newly created files, or Staging modified files
Stage files (the version of the files as it is at that time you run the command) to the index:
git add <filepattern>
Set up a
.gitignore file, with glob patterns (simplified regular expressions)
Viewing your staged and unstaged changes
See what you have changed but not yet staged:
doesn't show all the changes made since your last commit – only changes that are still unstaged.
See what you have staged that will go into your next commit
git diff --cached # --staged is a synonym
compares your staged changes to your last commit
Committing your changes
Commit your staged changes:
git commit -m "My first commit!"
Skipping the staging area
git commit -a
automatically stage every file that is already tracked (saving all the changes into a single commit).
Remove a file from your tracked files (from your staging area) and also from your working directory
Remove a file from your staging area but keep it in your working directory
git rm --cached
git rm log/\*.log
The backslash is necessary because Git does its own filename expansion in addition to your shell's filename expansion.
Viewing the commit history
List the commits made in the repository
Show the diff introduced in each commit
git log -p
Limiting log output
- after the specified date
- before the specified date
Dates are absolute ("2008-01-15") or relative ("2 weeks").
- search for keywords in the commit messages
- match commit with both author and grep options, for example
- (no term)
Changing your last commit
Fix the commit message:
git commit --amend
Unstaging a staged file
Change which commit the current branch is pointing to.
git reset HEAD <file>
Unmodifying a modified file
Revert a file back to what it looked like when you last committed
git checkout -- <file>
Working with remotes
Showing your remotes
Show the URL that Git has stored for the shortname to be expanded to:
git remote -v
origin is the default shortname Git gives to the server (or repo) you clone
Adding remote repositories
git remote add <shortname> <url>
Fetching and pulling from your remotes
Pull down all the data from the remote project that you don't have yet in your repository (and update the remote refs):
Git will not fetch data in your working directory (only in your Git
directory) – you still have the files in your working directory. It fetches it
in a separate (remote) branch: your
develop or whatever) branch is
Automatically fetch and then merge a remote branch into your current branch:
git pull # It does commit!
It is actually a bad idea to do both at the same time: it is highly recommended
to do manually a
fetch and then do a
merge, unless you're the only person
working at that repository. If
pull blows up on you, it's a little hard to get
out of it.
Pushing to your remotes
master branch to your
git push origin master
This command works only:
- if you cloned from a server to which you have write access and
- if nobody has pushed in the meantime
A tag marks a commit.
Listing your tags
2 main types of tags:
- lightweight = just a pointer to a specific commit
- annotated = pointer to a tag object
Create an annotated tag (full object):
git tag -a <tagname>
Sign your tags with GPG:
git tag -s <tagname>
Create a pointer to the current commit.
git tag <tagname>
Verify the signature.
git tag -v <tagname>
Tagging after the fact
git tag -a <tagname> <commit> git tag -s <tagname> <commit> git tag <tagname> <commit>
By default, the
git push command doesn't transfer tags to remote servers.
git push origin --tags
Tips and tricks
What a branch is
Branches are just names for commits.
Git stores data as a series of snapshots.
Stage a file:
- Checksum (SHA-1 hash) the file
- Store that version of the file in the Git repository
- Add that checksum to the staging area
Default branch name:
Create a new branch (from current branch):
git branch testing
Current branch (that's what's checked out):
HEAD (symbolic ref, pointing to
a branch – or to a commit, when HEAD is detached).
This is a lot different than
HEAD in Subversion or CSV.
Switch to an existing branch:
- Move the
HEADpointer to point to the branch,
- Revert the files in your working directory back to the snapshot that the branch points to (overwrites working dir!).
git checkout testing
Because a branch in Git is actually a simple file that contains the 40 hex-digit SHA-1 checksum of the commit it points to, branches are cheap to create and destroy. Creating a new branch is as quick and simple as writing 41 bytes to a file (40 characters and a newline).
The main difference between a branch and a tag is branches move, tags don't:
when you make a commit with the
master branch currently checked out,
move to point to the new commit, effectively adding it to the branch.
Commit ID = checksum of content (any number of files) + author + date + log message + ID of previous commit.
Every commit's history can be uniquely identified by its ID.
Basic branching and merging
Basic branching (basic workflow)
master clean, in a production-ready state at all times.
Isolate your work (for everybody else's work or your own work).
Create a branch and switch to it at the same time:
git checkout -b feature # branch and checkout
Do your work (edit, test,
make check # run the tests git commit -a
Pull updates from other people (
merge master, test).
git merge master
The usual practice is to first merge
featureto make sure it has all the other stuff that
mastermay have acquired till now.
Share it (merge back into your
masterbranch, that is pull in the work you did in a branch):
git checkout master # branch you wish to merge into git merge feature # branch you merge in
If there is no divergent work to merge together (some local development going on in
master, unrelated to
git mergeis a "fast forward": move the pointer forward to an upstream commit of the commit you're on.
Note -- To avoid cluttering the Git tree with intermediate commits, merge the branch with:
git merge --squash feature
It will look as if you had made all the changes in just one commit. Hence, this only makes sense for trivial things that should have been a single commit all along. Otherwise, you loose the logic between the different commits you've done…
Delete a branch you no longer need:
git branch -d feature
You can also continue to develop on the
featurebranch, once again merging it at some later point in time.
3-way merge when the commit on the branch you're on isn't a direct ancestor of the branch you're merging in:
- Git creates a new snapshot that results from this 3-way merge
- Git automatically creates a new commit that points to it ("merge commit", having more than one parent)
Git determines the best common ancestor, unlike CVS or Subversion.
Basic merge conflicts
If there is a merge conflict (automatic merge failed),
- Manually resolve each conflict section (
- Mark the file as resolved by staging it (
- Finalize the mere commit by typing
You can use a graphical tool to resolve the conflicts:
List your current (local) branches:
Show all the remote branches:
git branch -r
Show all the branches:
git branch -a