Git notes
Contents
- 1 git notes
- 1.1 show previous revisions of a file
- 1.2 High level view of all changes, including merges
- 1.3 pretty printing upstream tracked branches
- 1.4 checkout remote tracked branch
- 1.5 set upstream branch for local branch that has no tracking
- 1.6 pull and push errors when working in a clone of an empty repository
- 1.7 Search for deleted files in version history (search for all the times the file was changed)
- 1.8 git checkout old revision by refid or date.
- 1.9 Show how local refs map to remote
- 1.10 delete local and remote branches
- 1.11 git pruning remote branches
- 1.12 git push a bundle
- 1.13 detached
- 1.14 show untracked files
- 1.15 show staged files (show added files, show cached files)
- 1.16 How to use git diff
- 1.17 show the current branch and remote origin
- 1.18 show ahead of origin
- 1.19 show contents of a file at a given revision
- 1.20 List the file names in a given commit ID
- 1.21 See what would change before a 'git pull' (don't use 'git pull')
- 1.22 error: failed to push some refs
- 1.23 git checkout
- 1.24 create from tag
- 1.25 Push only a single branch to a remote
- 1.26 git remote
- 1.27 find which branch has a commit ID
- 1.28 find available branches on remote
- 1.29 convert clean repository to 'bare'
- 1.30 git clone
- 1.31 git merge
- 1.32 git log
- 1.33 git show
- 1.34 config
- 1.35 git archive
- 1.36 fix commits with the wrong committer/author name or email address
- 1.37 Git Commit: git/svn commit differences are confusing to newbies
- 1.38 git-svn
- 1.39 VCS command translation
- 1.40 Cheat Sheet
git notes
show previous revisions of a file
This shows the current version of a given file in the current directory.
git show HEAD~0:./FILENAME
This shows the previous version of a given file in the current directory.
git show HEAD~1:./FILENAME
High level view of all changes, including merges
git log --oneline --graph --all
pretty printing upstream tracked branches
# git for-each-ref --format='%(refname:short) -up-> %(upstream:short)' refs/heads | column -t develop -up-> origin/develop master -up-> release-tag1 -up-> origin/release-tag1 release-tag2 -up-> origin/release-tag2
checkout remote tracked branch
git fetch -a git checkout develop
set upstream branch for local branch that has no tracking
You ran git branch release-tag2, but didn't specify an upstream tracking branch. To fix this, first list your branches and the associated upstream branch to see where you are, then use git branch again to set the upstream tracking branch; finally, list your branches again to see that it is now tracking upstream.
# git for-each-ref --format='%(refname:short): %(upstream:short)' refs/heads develop: origin/develop master: release-tag1: origin/release-tag1 release-tag2: # git branch -u origin/release-tag2 release-tag2 Branch release-tag2 set up to track remote branch release-tag2 from origin by rebasing. # git for-each-ref --format='%(refname:short): %(upstream:short)' refs/heads develop: origin/develop master: release-tag1: origin/release-sprint49 release-tag2: origin/release-tag2
pull and push errors when working in a clone of an empty repository
If you are getting errors like No refs in common and none specified, failed to push some refs, and Your configuration specifies to merge with the ref 'master' from the remote, but no such ref was fetched. then the fix is easy (run git push origin master). The reason this happens is because your cloned repository is so new that is doesn't even have branch definitions.
$ git pull Your configuration specifies to merge with the ref 'master' from the remote, but no such ref was fetched. $ git push No refs in common and none specified; doing nothing. Perhaps you should specify a branch such as 'master'. fatal: The remote end hung up unexpectedly error: failed to push some refs to 'git@git.noah.org:dotfiles'
The solution is to simply run this command:
$ git push origin master
Search for deleted files in version history (search for all the times the file was changed)
A long time ago someone removed or moved a file. You want to go back to that old version to research the code.
git log -- rootfs/etc/skel/.bashrc
You can also search by the leading directory path even though git doesn't think about directories. For example, search for when anything from rootfs/etc/skel was deleted:
git log -- rootfs/etc/skel/.bashrc
git checkout old revision by refid or date.
This will show you the refids of revisions in a date range. Then you can pick a revision and check it out.
git log --since='2013-12-01' --until='2013-12-25' git checkout ff009a rootfs/etc/skel/.bashrc
It is also possible to checkout by date. Note that in this example the file target is just a . (period). This tells git to checkout the entire tree at the given version (or the given age, in this case).
git checkout master@{1 month 2 weeks 3 days 1 hour 1 second ago} .
Show how local refs map to remote
git for-each-ref --format='%(refname:short): %(upstream:short)' refs/heads
Can also be done for a single local branch using config:
git config branch.${BRANCH_LOCAL}.remote
delete local and remote branches
Delete a local branch.
git branch -d branch_name
Delete a remote branch. Note the cryptic syntax with the :. Remember, this is dangerous.
git push origin :branch_name
git pruning remote branches
If a remote branch has been pulled into your local repository and then subsequently removed from the remote then your local copy of the branch will remain until you prune it. The git remote prune command can be used to clean up stale branches. Use the --dry-run option to list the stale branches that would be deleted.
git remote prune origin --dry-run # then git remote prune origin
git push a bundle
Sometimes you cannot directly push to a remote and the remote cannot pull from you. This can also happen if you clone from a repository that has a branch checked out (the remote is non-bare). The solution is to create a bundle. This is what would have been pushed to the remote. You can then transfer this bundle to the remote somehow (email, scp, etc.) and have the remote pull the bundle.
The main concern is specifying the range of commits that you want to bundle because git has no way of knowing how far back in time it was when your copy and the remote were last identical. If you don't specify how far back in history to bundle then the default is to bundle the entire history. This is equivalent to making an archive of the entire repository. Luckily, the bundle command allows you to specify a range of history by number of commits or by time.
This would bundle the last commit:
git bundle create noahs_changes.bundle --max-count=1
This bundles the last commit:
git bundle create noahs_changes.bundle HEAD^..
This bundle all commits since a given commit ID. Note that this would be every commit after the given commit ID. If you want to include the given commit ID you need to add a ^.
git bundle create noahs_changes.bundle 531a17dacdf23b9c0ebfd6b0fd60b7c41b8798ab^..
Now email or scp this bundle file to the remote. On the remote side do something like the following with the bundle. Note that FETCH_HEAD is the special location where git stores fetched objects. Notice that git log is used to examine the contents of FETCH_HEAD before it is merged.
git ls-remote . git ls-remote noahs_changes.bundle git fetch noahs_changes.bundle git log -p ..FETCH_HEAD git merge FETCH_HEAD
Or, if you trust the bundle simply do this:
git pull noahs_changes.bundle
After merging you should see that a git log on the local and remote repositories should give identical results. Note especially that the commit IDs match on both sides.
Note that git format-patch can be used for similar purposes, but it does not preserve history, so if the remote were to apply your patch you would end up with identical contents of files in the repository but with different commit IDs and history.
detached
A deteched HEAD state happens when your local working copy is not associated with any branch. This means you are looking at code that you cannot commit to any branch. This happens when you checkout a tag, or during some situations where you have a merge conflict to resolve. You can see this condition by running the following:
git checkout master^0 # or git checkout HEAD^0
To get back to normal simply checkout the branch you were previously working on:
git checkout master
show untracked files
git ls-files --other --exclude-standard
show staged files (show added files, show cached files)
The term cached is less used now. It seems that staged is preferred. For example, compare the operation of git ls-files --cache to git diff --cached --name-only.
Git terminology can be confusing. There are synonyms for many terms. When you add a file you are adding it to the cache, which is also called stage. Some git commands even have synonyms. For example, the following two commands are identical in function. This lists the names of files that have been staged. In other words, this lists the names of files that have been added to the cache. Remember, this is what you do just prior to a commit ('git add hello_world.c).
git diff --cached --name-only git diff --staged --name-only
I wish there was a more plumbing way to do this. This example uses the porcelain interface.
How to use git diff
- git diff
- shows diff between the working directory and the index. This show your working copy changes that have not been added to the index.
- git diff --cached
- shows diff between index and the HEAD. The HEAD is the last commit. This show what would be added by the next commit.
- git diff HEAD
- shows a diff between the working directory and the HEAD (the last commit).
- git diff origin
- (or git diff origin/HEAD) shows a diff between what is committed locally and the remote origin. Note that you must run git fetch or git remote update to fetch the index of the remotes. Otherwise you will only see the diff since the last time you ran a command to download the remote index. Don't use git pull in this situation because, while it will download the remote index, it will also merge and commit the diffs to your index, so then there would be no diffs to see. You can get similar information using git rev-list origin..HEAD, which will show you rev IDs (see #show ahead of origin.
- git diff HEAD^ some_file.txt
- shows diff of a file with a previous version.
- git diff HEAD^^ some_file.txt
- shows diff of a file with two versions in the past.
- git diff HEAD@{3} some_file.txt
- shows diff of a file three versions in the past.
If you just want to see the names of the files with diffs instead of the delta itself then add the --name-only option to git diff.
git diff --name-only origin
show the current branch and remote origin
This shows your branch while gracefully handling the case when your local is detached. This doesn't tell you anything about the origin. If you are detached then you are not tracking any remote. For testing this you can use git checkout HEAD^0 to put your working directory in a detached state. The symbolic-ref command shows which branch the given symbolic ref refers to. The HEAD symbolic ref is the working directory, so this shows which branch that the working directory is on.
( git symbolic-ref HEAD 2>/dev/null || git rev-parse HEAD 2>/dev/null ) | sed "s/refs\/heads\///"
Here are some other ways to get the branch:
git describe --contains --all HEAD git branch 2>/dev/null | sed -e '/^[^*]/d' -e 's/\* \(.*\)/\1/'
This shows both the remote and branch your are on.
git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD)
Another way to do this is to use a combination of two commands.
REMOTE=$(git remote) REMOTE_BRANCH="${REMOTE}/$(git rev-parse --abbrev-ref HEAD)"
Also note that if your working cope is detached then the following will show HEAD instead of a remote branch:
$(git rev-parse --abbrev-ref HEAD)
Putting this all together in a script snippet:
REMOTE_BRANCH=$(git rev-parse --abbrev-ref HEAD) BRANCH=$(git symbolic-ref HEAD 2>/dev/null | sed "s/refs\/heads\///") if [ -z "${BRANCH}" ]; then BRANCH="Detached: $(git rev-parse HEAD 2>/dev/null)" fi
Git is simple, no?
show ahead of origin
See #show remote origin and branch for finding REMOTE_BRANCH.
git rev-list ${REMOTE_BRANCH}..HEAD
That will list each commit ID you are ahead of the remote branch. Pipe through wc to get a count
git rev-list ${REMOTE_BRANCH}..HEAD | wc
show contents of a file at a given revision
git show ${COMMIT_ID}:${FILE_PATH}
Use git log to find a commit ID that you are interested in viewing. The use git show with the commit ID, a colon, and the filename. You may truncate the commit ID as desired.
git log ./maze.py git show a25bc6d73d55529d26294cea96b5d740302f2130:./maze.py git show a25bc6d7:./maze.py
If you only ask git to show the commit ID then it will display the diff of the entire commit, which may include other files.
git show a25bc6d73d55529d26294cea96b5d740302f2130
List the file names in a given commit ID
This lists the files in commit ID a25bc6d73d55529d26294cea96b5d740302f2130.
git diff-tree --no-commit-id --name-only -r a25bc6d
See what would change before a 'git pull' (don't use 'git pull')
The git pull command does a fetch and a merge. It is best to avoid git pull. Instead use git fetch then see what remote changes have been made before you merge into your local branch. This can never mess up your local copy since git fetch simply makes a local mirror of what is on the remote. After doing a git fetch you can use one of the following commands to examine the remote changes.
git fetch git log HEAD..origin git log -p HEAD..origin # shows each patch git diff HEAD...origin # with three dots shows a single diff of all changes. git cherry-pick
error: failed to push some refs
33c7f02..d82b08f dev -> dev ! [rejected] release -> release (non-fast-forward) error: failed to push some refs to 'username@git.example.com:engineering.git' To prevent you from losing history, non-fast-forward updates were rejected Merge the remote changes (e.g. 'git pull') before pushing again. See the 'Note about fast-forwards' section of 'git push --help' for details.
The important thing to notice is that the dev branch succeeded, but the release branch was rejected. This can be confusing if you have the dev branch checked out. If you didn't read the message carefully you might think that your dev push was rejected. You might then do all the things you are told to do to fix the problem (git pull) on the dev branch. This, of course, will have no effect. The solution is to switch to the release branch and bring your copy up to date before pushing again.
git checkout release git pull git push git checkout dev
What makes this confusing is that git pull seems to update the branch you have checked out; whereas git push will push all the branches you have edited.
git checkout
The following creates a branch, checks it out, and tracks it to a remote origin all in one step.
git checkout -b <BRANCH_NAME> origin/<BRANCH_NAME>
create from tag
git checkout <TAG_NAME) -b <NEW_BRANCH_NAME> git push origin <NEW_BRANCH_NAME>
Push only a single branch to a remote
By default, git will push all of your local branches to remote branches. You can push only the checked-out branch with the following:
git push HEAD # older style git push origin release
You can set this behavior as the default with the following configuration:
git config push.default simple # older style git config push.default upstream
git remote
When using git-remote over ssh it seems that you have to use the full path on the remote server, and not the path relative to the user you are connecting as. Also, you must put a trailing slash on the path. For example:
git ls-remote ssh://username@git.example.org/home/username/repositorium/engineering/
find which branch has a commit ID
Sometimes I have a commit ID, but I don't know what branch it's in. The following will show which branch contains the given commit ID.
git branch --contains <HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH>
find available branches on remote
This will show which branches are available on a remote server. It will also show the latest commit ID for each branch.
git ls-remote origin
convert clean repository to 'bare'
Bare repositories on a remote can take two forms. Both of these will behave the same if you clone with git clone user@example.com:repo.
~/repo/.git/ ~/repo.git/
cd repo git config --bool core.bare true
or
mv repo/.git repo.git git --git-dir=repo.git config core.bare true rm -rf repo
Or do this:
git reset --hard HEAD
When pushing to a remote repository that you have cloned from you might get an error like this:
remote: error: refusing to update checked out branch: refs/heads/master remote: error: By default, updating the current branch in a non-bare repository remote: error: is denied, because it will make the index and work tree inconsistent remote: error: with what you pushed, and will require 'git reset --hard' to match remote: error: the work tree to HEAD.
Converting the remote repository to a bare repository will fix this.
git clone
git clone git fetch git pull
git merge
Checkout the branch that you want to merge into. In this example, I want to merge a branch named feature-pxe-boot back into master.
git checkout master
Then just merge feature-pxe-boot
git merge feature-pxe-boot
The merged files are automatically committed. All you have to do is push if you want other people to see the merged commits.
git push
git log
The default format for git log does not show the files that were modified in a commit. The following adds the list of modified files to the log output.
git log --name-status
See also #config for the alias git ll which does the same thing.
git show
git show <object>
Example, after finding the refid of a commit using git log you can show what changes were actually part of that commit.
$ git show 263fe4ca6744757f596f12750cd4a8b1412d69e8 commit 263fe4ca6744757f596f12750cd4a8b1412d69e8 Author: Noah Spurrier <noah@noah.org> Date: Tue Feb 19 12:19:41 2013 -0800 Documented this feature because I forgot where I put it. diff --git a/XenResources/config/xm4.tmpl b/XenResources/config/xm4.tmpl index 8e949d3..d476222 100644 --- a/XenResources/config/xm4.tmpl +++ b/XenResources/config/xm4.tmpl @@ -17,6 +17,9 @@ } } memory = '{$memory}' +# This allows you to get the name of the Xen host while inside the guest. +# Do something like this to get the vmhost name: +# VMHOST=$(sed -e 's/^.*vmhost=\([^[:space:]]*\)$/\1/' /proc/cmdline) extra = "vmhost="+os.popen('hostname -f').read().strip() #
config
The git config command will update ~/.gitconfig.
git config --global user.name "Noah Spurrier" git config --global user.email noah@noah.org git config --global core.editor vim git config --global color.ui auto git config --global merge.tool vimdiff git config --global push.default simple
You can also edit the ~/.gitconfig file directly. The following also contains a few simple aliases that I like to use.
[user] name = Noah Spurrier email = noah@noah.org [core] editor = vim [color] ui = auto [merge] tool = vimdiff [push] default = simple [alias] # See also https://git.wiki.kernel.org/index.php/Aliases retrack = "!retrack() { git config \"branch.$1.remote\" $(dirname \"$2\"); git config \"branch.$1.merge\" \"refs/heads/$(basename \"$2\")\"; }; retrack" ####graph = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative graph = log --graph --pretty='format:%h,%ci,%d, %s <%ae>' ll = log --name-status
git archive
This is like an export. It retrieves a remote git repository without the .git metadata (history).
git archive --remote=ssh://username@www.example.org/home/username/repositorium/engineering/ HEAD > git_archive.tar
You can also use this to retrieve subdirectories of repositories. The follow retrieves only the subdirectory "dotfiles". Note that the selection of subdirectory is made after HEAD::
git archive --remote=ssh://username@www.example.org/home/username/repositorium/engineering/ --prefix=dotfiles/ HEAD:dotfiles > dotfiles_archive.tar
fix commits with the wrong committer/author name or email address
This basically completely rewrites your history. All of your git ref hashes will change.
git filter-branch --env-filter 'GIT_AUTHOR_NAME="Noah Spurrier";GIT_AUTHOR_EMAIL="noah@noah.org";GIT_COMMITTER_NAME="Noah Spurrier";GIT_COMMITTER_EMAIL="noah@noah.org";' HEAD
Git Commit: git/svn commit differences are confusing to newbies
Do a `git commit -a` in most cases.
Git stages commits into an index before they are committed, so a commit is a two step process. The `git-status` command will show which modifications have been indexed for the next commit. The `git-add` command will index a modified or new file for the next commit.
A `git fetch` also is done as a two step process. I especially like this feature. When you do a `git fetch` files are pulled from a remote server, but they are not immediately merged into your working copy. I despise this about SVN. Instead the remote files (actually their diffs) are held in the index where you can browse them and choose which parts to merge into your working copy.
Notice that the message below from `git-status` says two things. It shows files that have been modified and it shows which of those changes have been added to the commit. Notice here that one file is modified, but no changes have actually been added to the commit.
$ git-status # On branch master # Changed but not updated: # (use "git add <file>..." to update what will be committed) # # modified: dotfiles/.vimrc # no changes added to commit (use "git add" and/or "git commit -a")
You can have git automatically index all modified files with `git commit -a`. This is usually what most SVN users expect.
git-svn
dcommit
- When you want to do "svn up", instead do "git svn rebase". If you have conflicts use `git mergetool` then `git rebase --continue`.
- When you have everything up-to-date do `git svn dcommit`.
- If git complains about files not being up-to-date do `git svn rebase` again.
VCS command translation
See also this table in Wikipedia: VCS commands
git | subversion | notes |
---|---|---|
git clone url | svn checkout url | `git+ssh` works just like `svn+ssh` git clone git+ssh://noah@www.example.org/home/noah/src |
git pull | svn update | |
git status | svn status | The output from git is more clear. |
git -f checkout path | svn revert path | This deletes your local changes. |
git add file | svn add file | |
git rm file | svn rm file | |
git mv file | svn mv file | |
git commit -a | svn commit | |
git log | svn log | |
git show rev:path/to/file | svn cat url | |
git show rev:path/to/directory | svn list url | |
git show rev | svn log -rrev url | |
git branch branch_name | svn copy http://example.com/svn/trunk http://example.com/svn/branches/branch_name | |
git merge --no-commit branch_name | svn merge -r 20:HEAD http://example.com/svn/branches/branch_name | This is reason #1 why SVN sucks. Merge tracking is crap. As of version 1.5 they have some limited support for merge tracking, but it still blows. |
git tag -a tag_name | svn copy http://example.com/svn/trunk http://example.com/svn/tags/tag_name | SVN doesn't really have tags. Most people just use copy. The downside is that people can commit to tags, which kind of defeats the purpose. |
Cheat Sheet
Originally from http://cheat.errtheblog.com/s/git
Setup
git clone <repo>
clone the repository specified by <repo>; this is similar to "checkout" in some other version control systems such as Subversion and CVS
Add colors to your ~/.gitconfig file:
[color] ui = auto [color "branch"] current = yellow reverse local = yellow remote = green [color "diff"] meta = yellow bold frag = magenta bold old = red bold new = green bold [color "status"] added = yellow changed = green untracked = cyan
Highlight whitespace in diffs
[color] ui = true [color "diff"] whitespace = red reverse [core] whitespace=fix,-indent-with-non-tab,trailing-space,cr-at-eol
Add aliases to your ~/.gitconfig file:
[alias] st = status ci = commit br = branch co = checkout df = diff lg = log -p lol = log --graph --decorate --pretty=oneline --abbrev-commit lola = log --graph --decorate --pretty=oneline --abbrev-commit --all ls = ls-files
Configuration
git config -e [--global]
edit the .git/config [or ~/.gitconfig] file in your $EDITOR
git config --global user.name 'John Doe' git config --global user.email johndoe@example.com
sets your name and email for commit messages
git config branch.autosetupmerge true
tells git-branch and git-checkout to setup new branches so that git-pull(1) will appropriately merge from that remote branch. Recommended. Without this, you will have to add --track to your branch command or manually merge remote tracking branches with "fetch" and then "merge".
git config core.autocrlf true
This setting tells git to convert the newlines to the system’s standard when checking out files, and to LF newlines when committing in
You can add "--global" after "git config" to any of these commands to make it apply to all git repos (writes to ~/.gitconfig).
Info
git reflog
Use this to recover from *major* fuck ups! It's basically a log of the last few actions and you might have luck and find old commits that have been lost by doing a complex merge.
git diff
show a diff of the changes made since your last commit to diff one file: "git diff -- <filename>" to show a diff between staging area and HEAD: `git diff --cached`
git status
show files added to the staging area, files with changes, and untracked files
git log
show recent commits, most recent on top. Useful options: --color with color --graph with an ASCII-art commit graph on the left --decorate with branch and tag names on appropriate commits --stat with stats (files changed, insertions, and deletions) -p with full diffs --author=foo only by a certain author --after="MMM DD YYYY" ex. ("Jun 20 2008") only commits after a certain date --before="MMM DD YYYY" only commits that occur before a certain date --merge only the commits involved in the current merge conflicts
git log <ref>..<ref>
show commits between the specified range. Useful for seeing changes from remotes: git log HEAD..origin/master # after git remote update
git show <rev>
show the changeset (diff) of a commit specified by <rev>, which can be any SHA1 commit ID, branch name, or tag (shows the last commit (HEAD) by default)
git show --name-only <rev>
show only the names of the files that changed, no diff information.
git blame <file>
show who authored each line in <file>
git blame <file> <rev>
show who authored each line in <file> as of <rev> (allows blame to go back in time)
git gui blame
really nice GUI interface to git blame
git whatchanged <file>
show only the commits which affected <file> listing the most recent first E.g. view all changes made to a file on a branch: git whatchanged <branch> <file> | grep commit | \ colrm 1 7 | xargs -I % git show % <file> this could be combined with git remote show <remote> to find all changes on all branches to a particular file.
git diff <commit> head path/to/fubar
show the diff between a file on the current branch and potentially another branch
git diff head -- <file>
use this form when doing git diff on cherry-pick'ed (but not committed) changes somehow changes are not shown when using just git diff.
git ls-files
list all files in the index and under version control.
git ls-remote <remote> [HEAD]
show the current version on the remote repo. This can be used to check whether a local is required by comparing the local head revision.
Adding / Deleting
git add <file1> <file2> ...
add <file1>, <file2>, etc... to the project
git add <dir>
add all files under directory <dir> to the project, including subdirectories
git add .
add all files under the current directory to the project *WARNING*: including untracked files.
git rm <file1> <file2> ...
remove <file1>, <file2>, etc... from the project
git rm $(git ls-files --deleted)
remove all deleted files from the project
git rm --cached <file1> <file2> ...
commits absence of <file1>, <file2>, etc... from the project
Ignoring
Option 1:
Edit $GIT_DIR/info/exclude. See Environment Variables below for explanation on $GIT_DIR.
Option 2:
Add a file .gitignore to the root of your project. This file will be checked in.
Either way you need to add patterns to exclude to these files.
Staging
git add <file1> <file2> ... git stage <file1> <file2> ...
add changes in <file1>, <file2> ... to the staging area (to be included in the next commit
git add -p git stage --patch
interactively walk through the current changes (hunks) in the working tree, and decide which changes to add to the staging area.
git add -i git stage --interactive
interactively add files/changes to the staging area. For a simpler mode (no menu), try `git add --patch` (above)
Unstaging
git reset HEAD <file1> <file2> ...
remove the specified files from the next commit
Committing
git commit <file1> <file2> ... [-m <msg>]
commit <file1>, <file2>, etc..., optionally using commit message <msg>, otherwise opening your editor to let you type a commit message
git commit -a
commit all files changed since your last commit (does not include new (untracked) files)
git commit -v
commit verbosely, i.e. includes the diff of the contents being committed in the commit message screen
git commit --amend
edit the commit message of the most recent commit
git commit --amend <file1> <file2> ...
redo previous commit, including changes made to <file1>, <file2>, etc...
Branching
git branch
list all local branches
git branch -r
list all remote branches
git branch -a
list all local and remote branches
git branch <branch>
create a new branch named <branch>, referencing the same point in history as the current branch
git branch <branch> <start-point>
create a new branch named <branch>, referencing <start-point>, which may be specified any way you like, including using a branch name or a tag name
git push <repo> <start-point>:refs/heads/<branch>
create a new remote branch named <branch>, referencing <start-point> on the remote. Example: git push origin origin:refs/heads/branch-1 Example: git push origin origin/branch-1:refs/heads/branch-2
git branch --track <branch> <remote-branch>
create a tracking branch. Will push/pull changes to/from another repository. Example: git branch --track experimental origin/experimental
git branch -d <branch>
delete the branch <branch>; if the branch you are deleting points to a commit which is not reachable from the current branch, this command will fail with a warning.
git branch -r -d <remote-branch>
delete a remote-tracking branch. Example: git branch -r -d wycats/master
git branch -D <branch>
even if the branch points to a commit not reachable from the current branch, you may know that that commit is still reachable from some other branch or tag. In that case it is safe to use this command to force git to delete the branch.
git checkout <branch>
make the current branch <branch>, updating the working directory to reflect the version referenced by <branch>
git checkout -b <new> <start-point>
create a new branch <new> referencing <start-point>, and check it out.
git push <repository> :<branch>
removes a branch from a remote repository. Example: git push origin :old_branch_to_be_deleted
git co <branch> <path to new file>
Checkout a file from another branch and add it to this branch. File will still need to be added to the git branch, but it's present. Eg. git co remote_at_origin__tick702_antifraud_blocking ..../...nt_elements_for_iframe_blocked_page.rb
git show <branch> -- <path to file that does not exist>
Eg. git show remote_tick702 -- path/to/fubar.txt show the contents of a file that was created on another branch and that does not exist on the current branch.
git show <rev>:<repo path to file>
Show the contents of a file at the specific revision. Note: path has to be absolute within the repo.
Merging
git merge <branch>
merge branch <branch> into the current branch; this command is idempotent and can be run as many times as needed to keep the current branch up-to-date with changes in <branch>
git merge <branch> --no-commit
merge branch <branch> into the current branch, but do not autocommit the result; allows you to make further tweaks
git merge <branch> -s ours
merge branch <branch> into the current branch, but drops any changes in <branch>, using the current tree as the new tree
Cherry-Picking
git cherry-pick [--edit] [-n] [-m parent-number] [-s] [-x] <commit>
selectively merge a single commit from another local branch Example: git cherry-pick 7300a6130d9447e18a931e898b64eefedea19544
Squashing
WARNING: "git rebase" changes history. Be careful. Google it.
git rebase --interactive HEAD~10
(then change all but the first "pick" to "squash") squash the last 10 commits into one big commit
Conflicts
git mergetool
work through conflicted files by opening them in your mergetool (opendiff, kdiff3, etc.) and choosing left/right chunks. The merged result is staged for commit.
For binary files or if mergetool won't do, resolve the conflict(s) manually and then do:
git add <file1> [<file2> ...]
Once all conflicts are resolved and staged, commit the pending merge with:
git commit
Sharing
git fetch <remote>
update the remote-tracking branches for <remote> (defaults to "origin"). Does not initiate a merge into the current branch (see "git pull" below).
git pull
fetch changes from the server, and merge them into the current branch. Note: .git/config must have a [branch "some_name"] section for the current branch, to know which remote-tracking branch to merge into the current branch. Git 1.5.3 and above adds this automatically.
git push
update the server with your commits across all branches that are *COMMON* between your local copy and the server. Local branches that were never pushed to the server in the first place are not shared.
git push origin <branch>
update the server with your commits made to <branch> since your last push. This is always *required* for new branches that you wish to share. After the first explicit push, "git push" by itself is sufficient.
git push origin <branch>:refs/heads/<branch>
E.g. git push origin twitter-experiment:refs/heads/twitter-experiment Which, in fact, is the same as git push origin <branch> but a little more obvious what is happening.
Reverting
git revert <rev>
reverse commit specified by <rev> and commit the result. This does *not* do the same thing as similarly named commands in other VCS's such as "svn revert" or "bzr revert", see below
git checkout <file>
re-checkout <file>, overwriting any local changes
git checkout .
re-checkout all files, overwriting any local changes. This is most similar to "svn revert" if you're used to Subversion commands
Fix mistakes / Undo
git reset --hard
abandon everything since your last commit; this command can be DANGEROUS. If merging has resulted in conflicts and you'd like to just forget about the merge, this command will do that.
git reset --hard ORIG_HEAD
undo your most recent *successful* merge *and* any changes that occurred after. Useful for forgetting about the merge you just did. If there are conflicts (the merge was not successful), use "git reset --hard" (above) instead.
git reset --soft HEAD^
forgot something in your last commit? That's easy to fix. Undo your last commit, but keep the changes in the staging area for editing.
git commit --amend
redo previous commit, including changes you've staged in the meantime. Also used to edit commit message of previous commit.
Plumbing
test <sha1-A> = $(git merge-base <sha1-A> <sha1-B>)
determine if merging sha1-B into sha1-A is achievable as a fast forward; non-zero exit status is false.
Stashing
git stash git stash save <optional-name>
save your local modifications to a new stash (so you can for example "git svn rebase" or "git pull")
git stash apply
restore the changes recorded in the stash on top of the current working tree state
git stash pop
restore the changes from the most recent stash, and remove it from the stack of stashed changes
git stash list
list all current stashes
git stash show <stash-name> -p
show the contents of a stash - accepts all diff args
git stash drop [<stash-name>]
delete the stash
git stash clear
delete all current stashes
Remotes
git remote add <remote> <remote_URL>
adds a remote repository to your git config. Can be then fetched locally. Example: git remote add coreteam git://github.com/wycats/merb-plugins.git git fetch coreteam
git push <remote> :refs/heads/<branch>
delete a branch in a remote repository
git push <remote> <remote>:refs/heads/<remote_branch>
create a branch on a remote repository Example: git push origin origin:refs/heads/new_feature_name
git push <repository> +<remote>:<new_remote>
replace a <remote> branch with <new_remote> think twice before do this Example: git push origin +master:my_branch
git remote prune <remote>
prune deleted remote-tracking branches from "git branch -r" listing
git remote add -t master -m master origin git://example.com/git.git/
add a remote and track its master
git remote show <remote>
show information about the remote server.
git checkout -b <local branch> <remote>/<remote branch>
Eg git checkout -b myfeature origin/myfeature Track a remote branch as a local branch.
git pull <remote> <branch> git push
For branches that are remotely tracked (via git push) but that complain about non-fast forward commits when doing a git push. The pull synchronizes local and remote, and if all goes well, the result is pushable.
Submodules
git submodule add <remote_repository> <path/to/submodule>
add the given repository at the given path. The addition will be part of the next commit.
git submodule update [--init]
Update the registered submodules (clone missing submodules, and checkout the commit specified by the super-repo). --init is needed the first time.
git submodule foreach <command>
Executes the given command within each checked out submodule.
Remove submodules
1. Delete the relevant line from the .gitmodules file. 2. Delete the relevant section from .git/config. 3. Run git rm --cached path_to_submodule (no trailing slash). 4. Commit and delete the now untracked submodule files.
Patches
git format-patch HEAD^
Generate the last commit as a patch that can be applied on another clone (or branch) using 'git am'. Format patch can also generate a patch for all commits using 'git format-patch HEAD^ HEAD' All page files will be enumerated with a prefix, e.g. 0001 is the first patch.
git am <patch file>
Applies the patch file generated by format-patch.
git diff --no-prefix > patchfile
Generates a patch file that can be applied using patch: patch -p0 < patchfile Useful for sharing changes without generating a git commit.
Git Instaweb
git instaweb --httpd=webrick [--start | --stop | --restart]
Environment Variables
GIT_AUTHOR_NAME, GIT_COMMITTER_NAME
Your full name to be recorded in any newly created commits. Overrides user.name in .git/config
GIT_AUTHOR_EMAIL, GIT_COMMITTER_EMAIL
Your email address to be recorded in any newly created commits. Overrides user.email in .git/config
GIT_DIR
Location of the repository to use (for out of working directory repositories)
GIT_WORKING_TREE
Location of the Working Directory - use with GIT_DIR to specifiy the working directory root or to work without being in the working directory at all.