Git Basics
Getting a Git Repository
git init
git clone git://xxx
git config --system|--global
Recording Changes to the Repository
git status -s
git add
git diff
git difftool --tool-help
git commit -s -a
git rm --cached
git mv file_from file_to
Viewing the Commit History
git log -p -2 --stat
git log --pretty=oneline|short|full|fuller
git log --pretty=format:"%h - %an, %ar : %s"
git log --pretty=format"%h %s" --graph
git log --since=2.weeks|"2008-01-15"|"2 years 1 day 3 minutes ago"
git log --pretty=format:"%h %cd - %s" --author="Patrick Steinhardt" --grep="typo"
git log --pretty=format:"%h %cd - %s" --author="Patrick Steinhardt" --grep="typo" --grep="documentation" --all-match
git log -S code_that_may_be_updated
git log --pretty="%h - %s"--since="2008-01-01" --before="2008-11-01" --no-merges -- src/
git log --decorate #shows you where the branch pointers are pointing
Undoing Things
# amend your last commit
git commit --amend
# unstaging a staged file
git reset HEAD <file>...
# unmodifying a modified file
git checkout -- <file>...
Working with Remotes
# showing your remotes
git remote -v
# adding remote repositories
git remote add pb https://github.com/paulboone/ticgit
# fetching and pulling from your remotes
git fetch <remote> # download data but does not merge
git pull <remote> # download data and merge it
# pushing to your remotes
git push <remote> <branch>
# inspecting a remote
git remote show <remote>
# renaming and removing remotes
git remote rename <old_name> <new_name>
git remote rm <remote>
Tagging
# listing your tags
git tag -l "v0.25*"
# creating annotated tags
git tag -a v1.4 -m "my version 1.4" [commit-checksum]
git show v1.4 # show the tag data along with the commit that was tagged
# create lightweight tags
git tag v1.4.1 [commit-checksum] # dont provide -a, -s, or -m
# sharing tags
git push <remote> <tag-name>
git push <remote> --tags # push all of your tags
# checking out tags
git checkout <tag-name> # leads to "detached HEAD state"
git checkout master # leave "detached HEAD state"
Git Aliases
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status
git config --global alias.unstage 'reset HEAD --'
git config --global alias.last 'log -1 HEAD'
Git Branching
Creating a New Branch
# creating a new branch
git branch testing
# switching branches
git checkout testing
# creating a new branch and switch to it at the same time
git checkout -b iss53
Basic Branching and Merging
# switch to master and merge hotfix into it
git checkout master
git merge hotfix
# delete an unused branch
git branch -d hotfix # to force delete a branch use -D instead
# merging conflicts
git mergetool --tool-help
Branch management
# show branches
git branch -v
# show the merged branches for the current branch
git branch --merged
# show the unmerged branches for the current branch
git branch --no-merged
# show merged branches for a specified branch
git branch --merged master
Remote Branches
# showing all remote references
git ls-remote <remote>
git remote show <remote>
# sharing your branch
git push <remote> <local_branche_name>[:<remote_branch_name>]
# create local branch based off the remote branch
git checkout -b <local_branch_name> <remote>/<remote_branche_name>
# shortcut if the local branch name is the same as the remote
git checkout [--track] <remote_branch_name>
# track a different remote branch for the current branch
git branch -u <remote>/<remote_branch_name>
# upstream shothand for merging
git merge @{u} # a shorthand for 'git merget <remote>/<remote_branch_name>
# showing what tracking branches you have set up
git branch -vv
# getting all the latest commits from all the remote servers
git fetch --all
# deleting remote branches
git push <remote> --delete <remote_branch_name>
Rebasing
git rebase master hotfix
git checkout master
git merge hotfix
Distributed Git
Contributing to a Project
Forked Public Project
# clone and commit your work on a topic branch
git clone <url>
cd project
git checkout -b featureA
... work ...
git commit
... work ...
git commit
# creat a fork of the project e.g named myfork
# and add it as a new remote of your local repository
git remote add myfork <url>
# push your work
git push -u myfork featureA
# notify the maintainers that you have work you'd like thme to merge
git request-pull origin/master myfork
Public Project over Email
# do work on a topic branch
git checkout -b topicA
... work ...
git commit
# generate the mbox-formatted files that you can email to the list
git format-patch -M origin/master
# send the patches out
cat *.patch | git imap-send # imap way
git send-email *.patch # SMTP way
Maintaining a project
Applying Patches from E-mail
# contributors use git diff to generate patches
git diff ...
# create a topic branch on which apply patches
git checkout -b sc/ruby_client master
# apply the patch
git apply /tmp/patch-ruby-client.patch
# check if a patch applies cleanly before acutally applying it
git apply --check xxx.patch
Applying a Patch with am
# contributors use format-patch to generate patches
git format-patch ...
# apply the patch
git am xxx.patch
Checking out Remote Branches
# fetch the commits made by a contributor on a forked remote branch
git remote add jessica git://github.com/jessica/myproject.git
git fetch jessica
git checkout -b rubyclient jessica/ruby-client
# one-time pull from a remote
git pull https//github.com/onetimeguy/project
Determining What Is Introduced
# list the commits that are in your contrib branch but are not in your master branch
git log contrib --not master
# show the common ancestor of two branches
git merge-base contrib master
# show diffs on the contrib branch but not in master
git checkout contrib
git diff $(git merge-base contrib master)
# show only the work your current topic branch has introduced since its common ancestor with master
git diff master...contrib
Integrating Contributed Work
# merge
git merget -3 ...
# rebase
git rebase ...
# cherry-picking a single commit
git cherry-pick e43a6
Preparing a Release
git archive master --prefix='project/' | gzip > `git describe master`.tar.gz
git archive master --prefix='project/' --format=zip > `git describe master`.zip
The Shortlog
git shortlog --no-merges master --not v1.0.1
Git Tools
Revision Selection
Individual Commit
# single revision by short SHA-1
git show <short-sha1>
# single revision by branch references
git show <branch-name>
# show the SHA-1 for a branch
git rev-parse <branch-name>
# reflog
git reflog
git show HEAD@{5}
git show HEAD@{1.month.ago}
# see reflog information in git log
git log -g master
# ancestry references
git show HEAD^ # the parent
git show HEAD^2 # the second parent
git show HEAD~ # the parent
git show HEAD~2 # the parent of the parent
Commit Ranges
# show commits that are not yet pushed to origin/master
git log origin/master..HEAD
# show multiple branches
git log refA refB --not refC
git log refA refB ^refC
# pecifies all the commits that are reachable by either of two references but not by both of them
git log refA...refB --left-right
Interactive Staging
git add -i
Stashing and Cleaning
Stashing your work
# stash your current work
git stash
# list the stashed works
git stash list
# apply the stashed work
git stash apply [--index] [stash@{2}]
# remove a stashed work
git stash drop stash@{2}
# apply the stash and then immediately drop it from your stack
git stash pop
Creative Stashing
# Leave the staged files in the index while stashing
git stash --keep-index
# stash untracked files as well as the tracked ones
git stash -u
# stash interactively
git stash --patch
Creating a Branch from a Stash
git stash branch <branch_name>
Cleaning your Working Directory
# clean the untracked files forcely
git clean -f -d
# see what will be cleaned
git clean -n -d
# remove everything but save it in a stash
git stash --all
# clean the untracked files as well as the ones in .ignore
git clean -f -d -x
Searching
git grep
# search through working directory for a string or regular expression
git grep -n --break --heading <somestring>
# to see how many matches are there
git grep --count <somestring>
# to show the context of a string
git grep -p <somestring>
# search through a give tag for a string
git grep -n <somestring> <tagname>
git log searching
# pickaxe search
git log -S <somestring> --oneline
# line log search
git log -L :funcname:file
git log -L /regexp/,/regexp/:file
Rewriting History
Changing Last Commit
git commit --amend [--no-edit]
Changing Multiple Commit Messages
# prepare to change the last 3 commmits
git rebase -i HEAD~3
# amend the commits
git commit --amend
# continue to rebase
git rebase continue
The Nuclear Option: filter-branch
# remove all the passwords.txt from all the commits
git filter-branch --tree-filter 'rm -f passwords.txt' HEAD
# change e-mail for all the commits
git filter-branch --commit-filter '
if [ "$GIT_AUTHOR_EMAIL" = "schacon@localhost" ];
then
GIT_AUTHOR_NAME="Scott Chacon";
GIT_AUTHOR_EMAIL="schacon@example.com";
git commit-tree "$@";
else
git commit-tree "$@";
fi' HEAD
Reset Demystify
|
HEAD |
Index |
WorkDir |
WD Safe? |
| Commit Level |
|
|
|
|
| reset --soft [commit] |
REF |
No |
No |
Yes |
| reset [commit] |
REF |
Yes |
No |
Yes |
| reset --hard [commit] |
REF |
Yes |
Yes |
No |
| checkout <commit> |
HEAD |
Yes |
Yes |
Yes |
| File Level |
|
|
|
|
| reset [commit] <paths> |
No |
Yes |
No |
Yes |
| checkout [commit] <paths> |
No |
Yes |
Yes |
No |
Advanced Merging
Aborting a merge
git merge --aborts
Ignoring Whitspace
git merge -Xignore-space-change <branch>
Manual File Re-merging
# show common version, ours version and theirs version
git show :1:<file>
git show :2:<file>
git show :3:<file>
# show SHA-1 of each version in conflicts
git ls-files -u
# merge file
git merge-file -p <current-file> <base-file> <other-file>
# show diffs between working directory and the base, ours or theirs version
git diff --base
git diff --ours
git diff --theirs
Checking Out Conflicts
# Add base versions in the conflict file
git checkout --conflict=diff3 <file>
Merge log
# show the conflict file on each side
git log --oneline --left-right HEAD...MERGE_HEAD
git log --oneline --left-right --merge
revert the commit
git revert -m 1 HEAD
git revert <commit>
Submodules
Add and initialize sub modules
# add a sub module into current project
git submodule add <url>
# clone a project with sub modules
git clone <project_url>
cd <sub_module_dir>
git submodule init
git submodule update
# clone a project with sub modules in one command
git clone --recurse-submodules <project_url>
Working on a Project with Submodules
# fetch and merge the submodule from remote in one command
git submodule update --remote <sub_moudle>