//

Git quick reference card

Table of Contents

Getting started

Choosing Git

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.

Staging area

Distributed

Git is a distributed version control system.

Sharing in Git only happens when you want it to (push, not commit).

Git basics

The 3 states

  • modified
  • staged
  • committed
  • 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

Git basics

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 you@example.com

That goes in file:///cygdrive/d/Users/fni/.gitconfig.

Getting a Git repository

New project

Start to track an existing directory in Git:

git init

It creates and initialize the Git directory (.git).

Existing project

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

ssh:// pull push
http[s]:// pull  
git:// pull  
file:// pull push

(rsync:// and ftp:// are not recommended)

Recording changes to the repository

  • Each file can be in one of two states:
    • Tracked
    • Untracked

Checking the status of your files

git status

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>

Ignoring files

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:
    git diff
    

    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).

Removing files

  • Remove a file from your tracked files (from your staging area) and also from your working directory
    git rm
    
  • 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.

Moving files

git mv

Viewing the commit history

  • List the commits made in the repository
    git log
    
  • Show the diff introduced in each commit
    git log -p
    

Limiting log output

Time-limiting options:

--since
after the specified date
--until
before the specified date

Dates are absolute ("2008-01-15") or relative ("2 weeks").

Search criteria:

--author
--committer

Grep option:

--grep
search for keywords in the commit messages
--all-match
match commit with both author and grep options, for example
(no term)
--pretty

Undoing things

XXX

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 from.

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 fetch

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 master (or develop or whatever) branch is different from origin/master branch.

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

Push your master branch to your origin server:

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

Tagging

A tag marks a commit.

Listing your tags

git tag

Creating tags

2 main types of tags:

  • lightweight = just a pointer to a specific commit
  • annotated = pointer to a tag object

Annotated tags

Create an annotated tag (full object):

git tag -a <tagname>

Signed tags

Sign your tags with GPG:

git tag -s <tagname>

Lightweight tags

Create a pointer to the current commit.

git tag <tagname>

Verifying tags

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>

Sharing tags

By default, the git push command doesn't transfer tags to remote servers.

git push origin --tags

Tips and tricks

Auto-completion

source ~/git-completion.bash

Git aliases

Git branching

What a branch is

Branches are just names for commits.

Git stores data as a series of snapshots.

Stage a file:

  1. Checksum (SHA-1 hash) the file
  2. Store that version of the file in the Git repository
  3. Add that checksum to the staging area

Default branch name: master (pointer).

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 HEAD pointer 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, master will 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)

Keep master clean, in a production-ready state at all times.

  1. 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
    

    Naming convention: feature/cool-new-feature (or hotfix/bug-157). Or feature/username/cool-new-feature?

  2. Do your work (edit, test, add, commit).
    make check                              # run the tests
    git commit -a
    
  3. Pull updates from other people (merge master, test).
    git merge master
    

    The usual practice is to first merge master back into feature to make sure it has all the other stuff that master may have acquired till now.

  4. Share it (merge back into your master branch, 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 feature), git merge is 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…

  5. Delete a branch you no longer need:
    git branch -d feature
    

    You can also continue to develop on the feature branch, once again merging it at some later point in time.

Basic merging

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 (<<<<<<< markers)
  • Mark the file as resolved by staging it (git add)
  • Finalize the mere commit by typing git commit

You can use a graphical tool to resolve the conflicts:

git mergetool

Branch management

List your current (local) branches:

git branch

Show all the remote branches:

git branch -r

Show all the branches:

git branch -a

References

Books