Skip to content

Instantly share code, notes, and snippets.

@vermie
Created January 2, 2012 18:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save vermie/1551680 to your computer and use it in GitHub Desktop.
Save vermie/1551680 to your computer and use it in GitHub Desktop.
git
############## details ################
============== structure ================
repository
a tree of objects which are under version control
objects are any of the following:
blob: binary data (usually a file)
tree: points to blobs (files) and other trees (subdirectories)
commit: points to a tree (your projects root directory), and points to the parent commit(s)
if a tree/blob doesn't change, then it is reused by future commits
a good example can be found at http://evadeflow.com/wp-content/uploads/2011/01/git_object_graph.png
yellow shapes are commits, blue shapes are trees, and black shapes are blobs
in general, you don't need to understand what trees/blobs are... but it's really simple graph stuff, so any developer should be able to figure it out
----------------------------------------
working directory
the files you edit live here
index
the files which you are about to commit live here
you manipulate it with 'git add' and 'git rm' (or 'git gui')
commit
conceptually, a snapshot of the project
actually, a commit actually contains/shows only the changes made since the previous commit
this is the 'atomic' unit of a repository's history
it is identified with a hash id, which is a hash of the contents of the commit and the commit's parent commit(s) id(s)
branch
a label which points to a commit
tag
a label which points to a commit
HEAD
a commit which is pointed to by a branch (it is that branchs' HEAD, or tip)
revision
signifies that you can use any of the following mechanisms to reference a commit object:
a branch name, a tag name, a commit hash, or HEAD
can combine any of the above with ^ and ~n (such as HEAD~2 for the commits before head, or HEAD^ for the commit before head)
branch vs tag
mostly, you can conceptualize a branch as a container of commits
when you add a commit to a branch, the branch now points to that commit (corollary: new commit becomes the new HEAD of that branch)
tags are static - they will always point to the commit you applied them to (unless you delete/move it)
remote tracking branch
this is a reference to the state of a branch on a remote repository.
you push to and pull from these.
============== commands ================
git gui
graphical interface for fetch, add, commit, push, checkout, branch, reset, merge
the commands in the gui are more limited than their bash equivalent
git gui blame file
graphical interface for blame on the file specified
gitk
shows branch/merge tree structure
also a graphical interface for log, tag, reset, checkout, cherry-pick
the commands in gitk are more limited than their bash equivalent
git fetch
retrieve changes from remote repositories - does NOT update your local branches (for that, see git pull)
git fetch -p
prune remote-tracking branches from your local repository if the remote branch has been deleted
this removes the reference to the remote branch, but leaves your local branch intact (if you have one)
git fetch --tags
force retrieval of tags (usually only necessary if someone moves a tag from one commit to another)
git add file
stage the file named 'file' to the index; this tells git which changes you are about to commit
additionally, this command marks a conflicted file as resolved
git commit -m "commit message" [options]
create a new commit out of the changes you have staged to the index
the commit message is required
--amend tell git to modify the HEAD commit, instead of create a new one
--author=Name assign an author to the commit (just part of their name as it shows up in existing commits is fine)
If you need to specify a new author, you use --author="Fname Lname <email@address.com>"
----------------------------------------
git branch
list local branches
git branch -r
list remote branches
git branch -a
list local and remote branches
git branch newname revision
create a new branch named 'newname', and create it as a copy a copy of 'revision'
if 'revision' is not specified, use the current branch HEAD
(use 'git checkout -b' as a shortcut to create and checkout at the same time)
git branch --set-upstream local remote
set the remote branch named 'remote' as the "remote tracking-branch" for local branch named 'local'
when you do 'git pull' or 'git push' with no parameters, the remote tracking-branch is used
----------------------------------------
git pull
first perform 'git fetch', then 'git merge' to apply any changes from the remote-tracking branch to the current branch
git pull --rebase
like 'git pull' only your changes (if any) are rebased onto the remote changes
essentially, if you have any work that the remote branch doesn't have, a rebase will
1) rewind your local branch to the point where it diverged from the remote branch
2) fast-forward merge (your local is now exactly like the remote branch)
3) re-commit the commits rewound in step 1
git push
push your local changes in all branches to all remote repositories
only pushes branches which are configured for it (see 'git branch --set-upstream')
git push repo
push your local changes in any branch to the repository 'repo'
git push repo branch
push your local changes in 'branch' to the repository 'repo'
if the repository doesn't contain a branch with the name 'branch', create it
git push repo local:remote
push local branch 'local' to the branch 'remote' in repository 'repo' (not recommended, it's usually best to use the above command so that your branches have the same name)
git push -f repo branch
push your local changes in 'branch' to the repository 'repo'
your local version will overwrite the remote version
git push repo :remote
delete the branch 'remote' from repository 'repo'
this should be done with care!
----------------------------------------
git checkout branch
switch to branch named 'branch'
if branch doesn't exist locally, but it is found on the in 1 remote repo, creates a locally copy based on the remote branch
git checkout -b newname
create a new branch named 'newname', based on the current branch, then switch to the new branch 'newname'
git checkout -b newname revision
create a new branch named 'newname', based on revision 'revision', then switch to the new branch 'newname'
git checkout -- path
checkout specific path, replacing your working directory copy with the version in the HEAD commit of the current branch
path can refer to a specific file, or to a directory (in which case you replace the entire directory contents as well)
git checkout revision -- path
as above, but checkout the version of the file/directory as it was in the specivied 'revision'
----------------------------------------
git merge revision
merge the changes from the specified commit, along with that commit's parents and ancestors, into the current branch
if the current branch has changes not in the specified version, a merge is performed - conflicts may occur, and a new 'merge commit' will be added to the history
otherwise, the current branch is just an old version of the specified revision - does a 'fast-forward' which just retrieves the new files
git merge --no-ff revision
as above, but always create a 'merge commit'
git merge revision revision ...
merges multiple things into the current branch
most often used to merge more than one branch at a time
----------------------------------------
git reset
clear the index (undo everything you've done with git add/rm since the last commit)
git reset --hard
clear the index and reset the working directory to the HEAD commit (undo everything you've done since the last commit)
use with caution, you will lose all un-commited changes (except new files - see 'git clean')
git reset revision
as above (can be used with --hard), but instead of resetting to the HEAD commit of the current branch, reset to the specified revision
----------------------------------------
git tag
list tags
git tag tagname
tag the HEAD commit with the specified name
tags act as pointers to arbitrary points in the history - usefull for identifying releases and release candidates
git tag tagname revision
tag the specified commit with the specified name
git tag -f tagname revision
as above, and move the tag if it already exists
git tag -d tagname
delete the specified tag
----------------------------------------
git cherry-pick revision
apply the changes caused by the specified commit to the working directory, then commit them to the current branch with the same commit message as the original commit
essentially copies a commit to the current branch
----------------------------------------
git log
show the commit history for the current branch
git log revision
show the commit history for specified revision
git log -- path
show the commit history for the current branch, but limit the output to commits which modified the specififed path
can optionally specify a revision immediately before the --
----------------------------------------
git blame file
show commit info for each line in the current version of the file specified
usefull for tracking down which commit caused a regression, or discovering who is a good person to ask about how certain code works, etc
----------------------------------------
git clean -f
remove untracked files from the working directory
git clean -fd
remove untracked files and directories from the working directory
git clean -x
when used with either -f or -d, also remove ignored files
----------------------------------------
git gc
pack loose objects into a pack file, increasing the compression ratio of the repository
git gc --prune
delete dangling objects from the repository
dangling objects are those which are reachable from 0 branches and 0 tags
git repack -ad
pack all objects into one pack file, giving maximum compression ratio for the repository
############## simplified ##############
use 'git gui' for most common operations, like staging and commiting
use 'git fetch' often so you can see when someone pushes changes (in git gui as 'Remote > Fetch from...')
use 'git pull --rebase' to update your local branch with the most recent version (command-line only)
rebase helps you keep a simple, linear commit history when you are collaborating with someone
not useful if are are just integrating different branches/forks into your local branch
use 'git push' to send your changes to a remote repository (in git gui as 'Remote > Push...' or using the Push button)
use 'gitk' to browse the commit history for your current branch
can pass additional params to gitk (or git log):
gitk b1 b2 b3 # look at history for branches b1, b2, and b3
gitk ^b1 b2 # look at the history for b2, but ignore any commit that is already in b1
gitk b1 -- src/ # look at the history for b1, but only show commits that modified files in the src directory
use 'gitk' to tag commits (right click a commit in the top-left pane)
############## repo hosting ##############
git clone --bare repo-url repo-path
create a bare clone of the repo located at 'repo-url' into the directory 'repo-path'
a bare clone doesn't have a working directory, and can be used as a shared repository
git daemon --reuseaddr --base-path=/path/to/repo --export-all --verbose --enable=receive-pack
run a service which enables the use of the 'git://' protocol
can run hooks on the remo repo (enabled with the --enable option), like a buildbot or tweeting the commit message
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment