Advanced Git Tutorial
by Sarah Sharp
WARNING:
I am a unique snowflake
WARNING:
This tutorial may make you lazy
WARNING:
Some Git features are
dangerous!
What is Git?
● Distributed
● Fast
● Flexible
Git Basics
● See Everyday Git Tutorial:
– http://www.kernel.org/pub/software/scm/git/doc
s/everyday.html
● My git commands:
– git add - git commit
– git diff - git log - git show
– git push - git pull
– git fetch - git rebase
Naming commits
<Commitish>
● (Indirect) hash of repo files, current
commit message, and ancestor commits.
● HEAD refers to the last commit
● ~ at the end means commit before that
– e.g. HEAD~
– ^ is roughly equivalent to ~
● A branch points to a specific commit
● see git rev-parse
Git Philosophy
Git Philosophy
● Commit early, commit often
● One commit represents one idea or one
change.
– Makes it easy to read patches
– Easy to revert unwanted changes later
● Your working directory, index, and local
repo are your scratch pads.
Frequent Use Infrequent Use
The Index, the staging area
Front stage: Back stage:
Changes to be committed Uncommited changes
and unadded files
Staging Changes
● git add <file> – adds a file to the Index
● git commit – commits added changes to
the local repo
● But what about files not added to the
Index?
Staging Changes
● git add <file> – adds a file to the Index
● git commit – commits added changes to
the local repo
● But what about files not added to the
Index?
– Answer: they aren't included in the commit.
● Key idea: You can add and commit files
separately from other files.
– This makes separating changes into small
patches easier.
What changed?
● git status
● git diff
git diff HEAD
local
workspace
repository
git diff index git diff --cached
Advanced Staging
Advanced Staging
● git add --patch
– try the "split" option to split across hunks
● git add -i
– Very powerful tool with lots of options
● Key idea: You can add and commit
different parts of a file separately.
Unstaging changes
● Revert to the last commit
– git reset --hard HEAD
● Remove all added changes from the index
– git reset --mixed HEAD
● Remove some files added to index
– git add -i and choose revert, or
– git reset HEAD filename(s)
Viewing History
Viewing History
● git log
● git log <commit A>..<commit B>
– shows history after commit A, up to commit B
– can omit either commit
– e.g. `git log` `git log origin..` `git log ..v2.6.30`
● git log -p
– shows log as a series of patches
● git log --pretty=oneline –abbrev-commit
Viewing old files
● Contents of a file at a particular commit
– git show <commitish>:<path to file>
● Contents of a directory
– git show <commitish>:<directory>
Pointing Fingers:
git blame
Pointing Fingers
● git blame <file>
– show who committed each line
● git blame <commit ID> <file>
– show the line history before that commit
Branches
Branches
● Only one branch can be checked out
– trunk ~= master
● show all branches
– git branch -a
● switching branches
– git checkout name
● creating new branches
– git checkout -b name <commit>
Advanced Branching
● Merge branches with git merge
– creates a "merge commit"
● Rebase current branch against branch B
– find a common ancestor commit
– apply commits from branch B
– apply commits from current branch
● Apply a commit from one branch
– git cherry-pick
Interacting with other people
Interacting with other people
● Creating a patchset, starting at commitA
– git format-patch -o directory commitA^
--cc=<cced-email>
– use git send-email or `mutt -H <gitpatch>`
● Applying a patch
– git am patchfile
– can also take a mailbox or maildir or stdin
● Pushing a new branch
– git push remote branch
Changing History
Changing History:
DANGER, WILL ROBINSON!
● After a commit, often you will find bugs
– could make a new bug fix commit
– or you could "amend" the previous commit
● Fix your code
● git add <file>
– This adds your code to the index
● git commit --amend
– This modifies the commit in the local repo
– useful to have vim git-commit script installed
Changing History:
DANGER, WILL ROBINSON!
● A total history rewrite:
– git rebase -i <commit ID>
● Can reorder commits
● Can edit commits
● Can "squash" one commit into another
● May have merge conflicts
– edit files, resolve conflicts surrounded by
<<<< and >>>>
– git add files, git rebase --continue
git rebase -i --dontscrewme
● No such command
● git rebase -i the safe way:
– git checkout -b master-rebase
– use `git rebase -i` to move one patch
– resolve any merge conflicts
– squash that patch using `git rebase -i`
– git diff master master-rebase
– git branch -M master master-old
– git branch -M master-rebase master
Git Hooks
Git Hooks
● Hooks are scripts found in .git/hooks/
● Enable them with chmod a+x <file>
● Triggered by various git commands
– e.g. git commit, git push
– pre-commit, post-update
● Examples
– shipped pre-commit hook checks for white
space at the end of line, long lines, etc.
– Checking for swear words?
Git Hooks
● Example post-update hook on remote repo:
#!/bin/sh
cd /home/sarah/blog
unset GIT_DIR
git-fetch origin
git-reset --hard origin/master
● Whenever I push to the remote repository, this
goes into the server's checkout of my blog git
repo and updates it unconditionally.
Setting up a
remote repository
Setting up a
remote repository
● Server needs git and sshd installed to use
git+ssh to push to your repo
● Server needs webDAV installed to allow
push to your repo over https
● http://github.com/ will host your repo
● Next directions assume you have your
own server with git installed
Setting up a
remote repository
1. Make local repo, commit stuff, etc.
2. ssh to the server:
GIT_DIR=/path/to/repo git init --shared
3. Next, tell the local repo about the server:
git remote add origin git+ssh://hostname/path/to/repo
4. Push to the server from the local repo:
git push origin master
5. Clean up the local repo so that you can pull from the
remote server:
git config branch.master.remote origin
git config branch.master.merge refs/heads/master
Resources
● Git work flow diagrams:
http://osteele.com/archives/2008/05/my-git-workflow
● The Tangled Working Copy:
http://tomayko.com/writings/the-thing-about-git
● http://github.com/
● Kernel module examples at http://lwn.net/Kernel/LDD3/
● vim git-commit script will display commit messages in a
more useful manner. Script kept at vim.sourceforge.net.
– sudo aptitude install vim-scripts vim-addon-manager
– vim-addons install git-commit
Creative Commons
Image Attributions
● GIT picture:
http://flickr.com/photos/29862082@N06/2908889599/
● Snowflake:
http://commons.wikimedia.org/wiki/Image:SnowflakesWilson
Bentley.jpg
● Danger:http://flickr.com/photos/dawvon/32305882/
● Cat: http://flickr.com/photos/jamilsoni/118499378/
● Remote: http://flickr.com/photos/markkelley/957631507/
● Philosophy: http://flickr.com/photos/paullew/2442045767/
● Branches: http://flickr.com/photos/shapeshift/136184752/
● Interacting with other people:
http://www.flickr.com/photos/exlibris/3222440467/
Creative Commons
Image Attributions
● Front stage:
http://flickr.com/photos/69108241@N00/118040089/
● Back stage: http://flickr.com/photos/piotramigo/2561391320/
● Hooks:http://www.flickr.com/photos/yabanji/3175297773/
● Blame: http://flickr.com/photos/iandesign/1205496024/
● Ballet: http://www.flickr.com/photos/oudeschool/3553416511/
● Papyrus: http://flickr.com/photos/charlestilford/2548991271/
Thank you!
● Sarah Sharp
● @sarahsharp
● http://sarah.thesharps.us