Git by Example

Overview and introduction to Git - an open source version control system designed to handle very large projects with speed and efficiency, but just as well suited for small personal repositories.

Create a git repository

cd ~
mkdir recipes
cd recipes
git init

Copy / clone a repository

via ssh

cd ~
git clone user@host:/path/to/repo your_local_dir_name

local repository

git clone /orig/repo /your/copy

A note about local cloning.

git knows where you cloned from, and arranges for the the changes to be pushed back there.

but in /orig/repo the changes won't be there yet. You need to :

cd /orig/repo
git checkout HEAD .

Create a cvs like central repository

See git for cvs users.

mkdir /pub/my-repo.git
cd /pub/my-repo.git
git --bare init --shared

Ensure everyone has group read/write permissions on that directory. Then they can clone the repository with:

git clone user@host:/pub/my-repo.git shared-repo

Setting your name / email

View

git config user.name
git config user.email

Change/set - current repository only

git config user.name Fred
git config user.email fred@gmail.com

Change/set - in ALL your (local) repositories. This updates ~/.gitconfig

git config --global user.name Fred
git config --global user.email fred@gmail.com

Alternatively edit ~/.gitconfig directly

Ways to commit a file

create cake.txt and add some text to it.

to commit it:

# Add cake.txt to the index, ready to be committed
git add cake.txt
# Commit all files in the index.
git commit

or

# Add to the index and commit cake.txt in one go.
git commit cake.txt

or

# Add & commit with a message
git commit -m "initial recipe" cake.txt

or

# Add all files that have changed, and commit them
git commit -a [-m "your message"]

Diffs

Edit cake.txt but do not commit it.

Show the differences

git diff

Show the differences with color

git diff --color

Show a summary of the changes

git diff --stat

Add the file to the index, and try diff

git add cake.txt
 
# diffs of files not yet added (none)
git diff
 
# diffs of added files (cake.txt)
git diff --cached

Logging

see all the commits:

git log

see all the commits, with the diff's:

git log -p

note that these show you what happened on the current branch. Switch branches, and you'll likely get a different log (unless you've just branched).

Branching

Create a branch

git branch oven_temp

Show branches that exist. * indicates the current branch

git branch

Change to branch "oven_temp"

git checkout oven_temp

Change back to "master", aka, trunk

git checkout master

Or, to create a branch and change to it in one step:

git checkout -b your_branch_name

Merging

Make a change on the branch

git checkout oven_temp
# edit cake.txt
git commit -m "your message" cake.txt

Change back to master, and merge in the change

git checkout master
git diff [master] oven_temp
git merge oven_temp

Delete the oven_temp branch

git branch -d oven-temp

Rebasing

Think of it as:

Or put another way:

git checkout branch_name
git rebase master

If conflicts occur, and sooner or later they will,

# manually edit the conflicting files
git add file(s)
git rebase --continue

See also "git-mergetool"

Reworking commit history

You want:

git rebase --interactive COMMIT_ID

COMMIT_ID should be the one BEFORE you want to fiddle with.

To learn about splitting a single commit up into multiple commits:

man git-rebase
# see "SPLITTING COMMITS" section

when is a (branch) change applied?

A change applies to the branch you are on when you COMMIT. Not when you edit or add the file.

git checkout -b cream
cat 'full fat milk & whip' > cream.txt
git add cream.txt
git checkout master
ls

although you've switched branches (from cream to master), the file still exists. Until you've committed it, it's not really part of git yet.

git commit -m "recipe for cream" cream.txt
git checkout cream
ls

cream.txt is no longer there. You where on master when it was committed, you're now on the cream branch.

git checkout master
ls

cream.txt exists again. If you want to get the file back into the cream branch, rebase is your friend:

git checkout cream
git rebase master

fixing a commit

# edit file
git commit -m "a bad message" file
git commit --amend

it is only safe to amend the commit messages that have not been seen by anyone else (aka, you've not pushed, nobody else has pulled from you).

revert all changes

This will throw away ALL your uncommitted changes.

Any (and all) changes will be un-done. Files you deleted will be recovered (provided they have been added to the git repository). If you had added any files to the index (git add), they will be undone.

You'll have a fresh, clean, current copy of the head / master / trunk.

If you've created a file, but never committed it, it will remain un-touched.

git checkout -f

revert one file

Remove the file, and checkout a fresh copy

rm cake.txt
git checkout cake.txt

If you had previously added the file to the index, even the above will still leave git thinking cake.txt has been modified:

git checkout -f # get a clean repo
# edit cake.txt
git add cake.txt
rm cake.txt
git checkout cake.txt
git status

To "unstage" a file, aka remove it from the index:

git reset HEAD cake.txt

You'll still have your file, it'll still contain your original changes, but it won't get committed until you re-add it to the index (or commit -a, or commit <path>)

rewriting history

You've committed a bunch of things, but you want to "remove" some of the commits, merge other, adjust the commit messages.

This only works if nobody else has seen your changes. You've not pushed, nobody has pulled.

First, make sure everything is commited.

Next, use "git log [-p]" to find the commit id where you would have branched, and the commit id of most recent point in history.

git reset --hard COMMIT_ID_WHERE_YOU_WOULD_HAVE_BRANCHED
git checkout -b some_temp_branch_name
git merge COMMIT_ID_OF_MOST_RECENT_STATE
git rebase --interactive master
git checkout master
git merge some_temp_branch_name

If you hit conflicts, fix them, then:

git rebase --continue

gitconfig

~/.gitconfig

The bits on the left of the = in the [alias] section you can change to anything you prefer.

[user]   # Edit by hand, or via "git config --global user.name" etc.
  name   = Nemo
  email  = nemo@sysmonblog.co.uk
[color]  # Ensure we get color
  diff   = auto
  branch = auto
  status = auto
[alias]  # shortcuts
  b      = branch
  c      = checkout
  co     = commit
  d      = diff -b
  dc     = diff -b --cached
  ds     = diff -b --stat
  s      = status
  # summary of what you're going to push
  ps     = log --pretty=oneline origin..master
  # like "git log", but include the diffs
  w      = whatchanged -p
  # changes since we last did a push
  wo     = whatchanged -p origin..

See Also

The follow we have found useful/interesting:

Feedback / Comments

We'd welcome tips, suggestions, corrections, feedback or comments via email or as comments on our blog.

Copyright 2008 blog@sysmonblog.co.uk