FAQ: What are the different diff commands?
$ git diff --cached # difference between HEAD and the index; what
# would be committed if you ran "commit" now.
$ git diff # difference between the index file and your
# working directory; changes that would not
# be included if you ran "commit" now.
$ git diff HEAD # difference between HEAD and working tree; what
# would be committed if you ran "commit -a" now.
$ git diff origin/master # difference between HEAD and remote
# repository
$ git status # a brief per-file summary of the above.
FAQ: Branch abbreviations
Branch names like "test" or "v2.6.18" are actually abbreviations for full branch names which take the form of a slash separated string beginning with "refs". For example:
- "test" is short for "refs/heads/test".
- "v2.6.18" is short for "refs/tags/v2.6.18".
- "origin/master" is short for "regs/remotes/origin/master".
HOWTO: Merge changes from a remote repository (e.g. github)
Add the repository, and give it the local name mikko:
$ git remote add mikko git://github.com/mkoppanen/php-tokyo_tyrant.git
Pull (download) from this repository, and merge into local branch master:
$ git pull mikko master
Note that by default, this operation merges (i.e. commits) any remote
changes into your local git object database: following it, git diff may
return no results, even if the "pull" retrieved previously unknown
commits. (If you don't want this to happen, do git fetch ...
followed by git merge ....)
FAQ: What's stored in the object database, and what's external to it?
e.g. name, email is not stored in the object database--it's in
~/.gitconfig.
???
FAQ: When is your local repository modified? When is the remote repository modified?
i.e. under what conditions is the tree, index or working copy modified? (git seems to modify repositories a little more eagerly than svn, where the only way to modify a repository is via a commit.)
FAQ: What states can a file be in?
From http://progit.org/book/ch1-3.html:
"Git has three main states that your files can reside in: committed, modified, and staged. Committed means that the data is safely stored in your local database. Modified means that you have changed the file but have not committed it to your database yet. Staged [i.e. cached or "in the index"] means that you have marked a modified file in its current version to go into your next commit snapshot."
FAQ: Reverting changes
If you're made some changes to a file (but it is not yet staged), and now
want to revert them (i.e. equivalent to svn revert myfile):
$ git checkout -- myfile
FAQ: What is the "working copy"?
The working copy is what's on the disk, and visible to tools not aware of git. e.g. if you run "make test", this will happen over the working copy.
Note files in the index are part of the working copy.
FAQ: Places content/files may be
- Working directory
- Stash
- Index
- "Tree"
HOWTO: Visualise tree operations?
How is content moved from one to the other? Can you move it back? How are the different areas referred to? How to diff them?
See http://marklodato.github.com/visual-git-guide/index-en.html.
FAQ: How does the "stash" work?
Move files from "working copy" and index into a stash (useful to run tests on the change you're planning to commit):
$ git stash save
$ git stash # same thing
If you don't want to modify the index, use --keep-index:
$ git stash --keep-index
Move files from the stash into working copy:
$ git stash pop
HOWTO: Refer to branches
A branch seems to be a pointer that can be moved around the object tree. i.e. can point to different parts of the tree.
A tag is a specific point in the tree, that cannot be moved? A sort of permanent branch?
HOWTO: Refer to remote branches
Can you tell if something is remote? Are there "short names" for things that have long names?
HOWTO: Show remote repositories
$ git remote -v
mikko git://github.com/mkoppanen/php-tokyo_tyrant.git (fetch)
mikko git://github.com/mkoppanen/php-tokyo_tyrant.git (push)
origin git@github.com:ithinkihaveacat/php-tokyo_tyrant.git (fetch)
origin git@github.com:ithinkihaveacat/php-tokyo_tyrant.git (push)
HOWTO: Add information from a remote repository to your local repository
$ git fetch mikko
Note that in this case, the changes are not merged into HEAD.
HOWTO: Compare a local branch with a remote branch
You first need to get the changes in the remote repository into your local repository. (This doesn't necessary involve importing them into your tree, just into your object database--?) Do this via:
$ git fetch mikko
You can then view the changes in various ways.
View commit messages:
$ git log HEAD..FETCH_HEAD
("The range notation 'HEAD..FETCHHEAD' means 'show everything that is reachable from the FETCHHEAD but exclude anything that is reachable from HEAD'.")
View diff:
$ git log -p HEAD..FETCH_HEAD
View changes visually:
$ gitk HEAD..FETCH_HEAD
FAQ: What are the special symbols, and what do they mean?
For example HEAD, FETCH_HEAD, FOO~3.
See the "Specifying Revisions" section in git help rev-parse.
HOWTO: Modify most recent commit
e.g. to change a commit message
$ git commit --amend
HOWTO: Cherry pick some changes and not others
$ git add --patch
HOWTO: Change the git object tree interactively
$ git rebase -i HEAD~10
http://blog.madism.org/index.php/2007/09/09/138-git-awsome-ness-git-rebase-interactive
FAQ: What's the opposite of a fast forward merge?
i.e. you want to move a branch pointer back a few revisions.
I don't know how to do this, but this is close:
$ git reset --soft HEAD~2
This moves the current branch back two revisions, but you do lose the individual commit messages. i.e. it's as if you never made the last two commits.
HOWTO: Create a new remote tracking branch
i.e. a remote system has a branch (perhaps added since the initial clone); you want to track this locally.
$ git fetch origin live:live
(This may not add config to .git/config to enable tracking; if this
is the case a git pull may complain, and provide some help text.)
HOWTO: Push a branch to a remote server
i.e. create a branch on the origin server, for example if you want to make a branch appear on Github.
$ git push origin mybranch
HOWTO: Remove/delete a remote branch
From http://github.com/guides/remove-a-remote-branch:
$ git push origin :v0.1.29-compat
HOWTO: Display information about a remote source
$ git remote show origin
produces some useful information about which remote branches exist, what branches are tracked locally, if the local is up to date or not.
FAQ: What's the deal with HEAD? What is it?
i.e. how does it differ from a branch, such as "master"?
- HEAD is a pointer to the node in the object graph that the working directory is associated with.
- HEAD is usually an alias of a branch. (This isn't just a model
of how it works--
.git/HEADis typically something likeref: refs/heads/live.) - HEAD can be an SHA-1 hash (though this is unusual); in this case you have a "detached HEAD".
- Commits always go on top of HEAD. (Whether HEAD is an alias of a branch, or a hash.)
- It's perfectly possible to commit on top of a "detached head", but these commits may be garbage collected. (Only branches, and descendants of branches are kept.)
- ? To prevent such a commit from being garbage collected, name it with a branch--
git branch mybranch. - To move the head, use
git reset.
FAQ: How to push to multiple repositories
e.g. if your "origin" is your own server, but you also want to push to github.
- Create the repository in github.
- git remote add github git@github.com:ithinkihaveacat/config.git
- git push github master # pushes the master branch to github
HOWTO: Convert an svn repository to git
See http://help.github.com/svn-importing/.
HOWTO: Deploy via git?
With subversion, you might deploy the live website via a checked out
copy of ../branches/live, and the dev website via a checked out copy
of ../branches/dev. This initially seems unwise in git, since
every repository contains the full history. (It's possible to
retrieve only a certain branch, and its history on to a particular
depth, but I couldn't really get this working properly.) It's
probably easier to get git to create hardlinks to objects in its
repository instead. Do something like
$ git clone -b dev ../beebo.org dev.beebo.org
$ git clone -b live ../beebo.org beebo.org
where ../beebo.org is the repository containing the dev and live
branches.
HOWTO: Use hub to add remote github repositories
If your remote origin is set to something other than github, but you wish to add a github repository as a remote so that you can push and pull from it, you can do this using hub:
$ hub remote add -p github ithinkihaveacat/config
This creates a new remote named github, which corresponds to
git@github.com:ithinkihaveacat/config.git (see git remote -v).
HOWTO: Push to a new remote repository
i.e. if you have a local repository, freshly created with git init,
and you want to push it to a backup repository, such as mel.beebo.org.
On the system where you want to create the bare backup repository:
$ cd /var/lib/git
# Can't really push to non-bare repositories
$ sudo git init --bare chef
# Make sure `mjs` user can write to repository (specific to my
# setup)
$ sudo chown -R mjs:mjs chef
Check that the local repository has no remotes:
$ git remote -v
If there are remotes, delete them with:
$ git remote rm origin
Add the new remote location:
# $GITROOT is e.g. mjs@mel.beebo.org:/srv/git
$ git remote add origin $GITROOT/chef
# Push to origin (backup system)
$ git push origin master
Once you've done one push, you can tell git to always push and pull
from the same branch with (i.e. to track the remote branch):
$ git branch --set-upstream DE314-import-prices origin/master
(Why do you have to do one push before you can run this command?)
HOWTO: Make an existing branch track a remote branch?
i.e. how do you solve the git pull error message beginning: "You
asked me to pull without telling me which branch you want to merge
with, and 'branch.master.merge' in your configuration file does not
tell me, either."
$ git branch --set-upstream foo upstream/foo
e.g.
$ git branch --set-upstream master origin/master
This adds a [branch "master"] section to .git/config; you can also
make this change by hand.
FAQ: What does "git reset" do?
Most use cases can apparently be reduced to the following three rules:
- It points the HEAD ref at a new 'target' commit, if you specified one.
- Then it copies the tree of the HEAD commit to the index, unless you
said
--soft. - Finally, it copies the contents of the index to the working tree, if
you said
--hard.
See http://blog.plover.com/prog/git-reset.html.
Alternatively:
--softmoves the HEAD ref to the target, but does not touch the working tree or the index. This can lead to a dirty tree--the working tree may have matched HEAD before the reset, but won't necessarily afterwards.--hardcopies the target to both the working tree and the index. (After--hard,git statuswill always report no changes (the tree is not dirty), and changes previously on in the working tree or the index may have been destroyed.)--mixed(the default) copies the target to the index, but not the working tree. (The working tree is unchanged, though changes previously only in the index may have been destroyed.)
FAQ: What does git diff origin/master do?
i.e. does it actually compare your working copy to origin/master retrieved from the network?
git diff origin/master does not perform any network access. i.e. it
doesn't check to see that it has the most recent copy of
origin/master; it compares your local working copy with the state of
the branch master in the remote origin as it exist in the local
repository right now. To update origin/master, use git fetch.
(This won't change any local branches.)
HOWTO: Convert a public github repository to a private repository
i.e. if you want to clone an existing repository, and keep your changes private.
Clone the existing repository:
$ git clone https://github.com/opscode/cookbooks.git beebo-chef
This sets up the repository with an "origin" of github. You need to change this. (The "origin" will become your own private repository.)
$ git remote rename origin opscode
Create a new "bare" repository on the server that holds your own private repository:
$ git init --bare beebo-chef
Set the "origin" of your cloned repository to the new bare repository you've just created. (Which doesn't have anything in it yet.)
$ git remote add origin mjs@mel.beebo.org:/srv/git/beebo-chef
Push your cloned copy of the repository to your private server.
$ git push origin master
At this point, you "moved" the repository from github to your own private repository; you can add private files to the repository and a "git push" will transfer them to your private repository.
The pull changes from the origin, do:
$ git pull opscode master
HOWTO: Change a remote's URL
From http://help.github.com/remotes/:
"There is no direct command to change a remote's URL, so you will
usually run git remote rm followed by git remote add to change a URL.
You can also edit the repo's .git/config file directly to change the
URL without re-fetching the remote."
HOWTO: View commits in one branch, but not another
Show commits in the master branch that are not in live:
$ git log live..master
FAQ: What's github's host public key?
For some reason there seem to be two:
|1|+5uA+MGZh2MRc1K94EO76xj5jeQ=|W3nfnwQ4n+yildCT3d5xoS2t/CI= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
|1|F/qweDtP4Lggk8IyvAB2hp2LBMc=|38s0aU36WqeUar1/pUwC3NnMxCI= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
(Get these by running ssh git@github.com, and confirming that you
want to accept the key.)
FAQ: What's the difference between the merge options --commit,
--ff and --squash?
???
FAQ: What does a "commit" hash store?
i.e. is stage and the working directory in any way part of the commit?
No, the "commit" hash just refers to a collection of files--the staging area and working directory might contain the same collection of files, but they are separate from the "commit" hash.
FAQ: How is my branch ahead of origin/master?
git log shows that the most recent commit matches the most recent
commit on github, but git status says "Your branch is ahead of
'origin/master' by 3 commits." How is this possible?
Well, it's possible that a git push will apparently do nothing.
I've observed this sequence of commands:
$ git status
# On branch master
# Your branch is ahead of 'origin/master' by 3 commits.
#
nothing to commit (working directory clean)
$ git push
Everything up-to-date
$ git status
# On branch master
nothing to commit (working directory clean)
FAQ: What does it mean to say that a tree is "dirty"?
This means that either the staging area, or your working tree, or both, does not match the tree (i.e. set of files) associated with HEAD. This typically happens if you've made some local changes that are not committed.
HOWTO: Set all line endings to LF?
$ git config --global core.eol lf
HOWTO: Show all commits that are in one branch, but not another
A command like
$ git log master ^live --no-merges
shows all commits that are on master, but not on live. However,
if you have cherry picked commits, this is probably not what you want:
since cherry picking a commit creates a new commit, this command still
shows commits as "missing" from one branch even after the commit has
been cherry picked. To see missing cherry picks you need to do
something like:
$ git cherry master live
+ 9938aa8ab03cd1bcebf494ecf344c7ebeea0dcb0
- 3eeeb206722c5ac8155b745b6b8dcd8a10e33277
- 4a845a9534093387365ec2055fe16efc59291e45
The lines prefixed with a + are the refs of commits in live that
are missing from master. (The lines prefixed with - are the refs
of commits that are in both branches.) This output is not especially
helpful; a more useful version, which only shows missing commits, and
includes the log message, is perhaps:
$ git cherry -v master live | grep ^\+
+ 9938aa8ab03cd1bcebf494ecf344c7ebeea0dcb0 Copy dev.sql, live.sql, qa.sql across from the live branch.
+ ee5a658d9a6016b5b12f1d0332b041890ddc0c17 CSS changes.
+ f34341c913a96b27a1ed5a84672976364f5d5b30 Fixing tests.
github can also show you the commits that separate one branch from
another (although like the git log command above, this does not
exclude cherry-picked changes):
https://github.com/sinatra/sinatra/compare/0.9.4...1.0.a
This shows the commits in 1.0.a that are missing from 0.9.4. i.e.
what needs to happen to 0.9.4 to transform it into 1.0.a.
Another related command that is somewhat useful is git branch
--contains. When passed a ref it lists all branches that "contain"
that ref, or in the words of the manual, "shows only the branches that
contain the named commit (in other words, the branches whose tip
commits are descendants of the named commit)."
So, for example, if you do
$ git branch --contains live
* int
live
this means that int is a superset of live--it contains all commits live does.
In contrast,
$ git branch --contains int
* int
means that int is the only branch that contains all commits in that
branch.
A Stack Overflow question contains some more examples, and possible solutions.
HOWTO: Pull all remote branches
git pull only pulls remote tracking branches i.e. local branches
that have been set up to "track" a remote branch. This means that
newly-created remote branches aren't automatically created locally.
(Though note that you can fetch (as opposed to merge) all remotes with
git fetch --all.) You can see all branches--remote and local, with
the command
$ git branch -a
* hotfix-2011-02-21
master
remotes/origin/HEAD -> origin/master
remotes/origin/live
remotes/origin/hotfix-2011-02-21
In this case, the remote branch live is not available locally.
There doesn't seem to be a way to automatically create all remote branches locally. However, you can do this one branch at a time via
$ git checkout -b live origin/live
This does a few things: (1) it creates the local branch live; (2) it
sets this branch up to track the remote branch live on the remote
origin (meaning that git pull while in this branch "will
appropriately merge from the remote branch"); and (3) it checks out
this branch.
Note that if you just do
$ git checkout origin/live
then origin/live is checked out, but no local branch is created:
the working copy is in "detached head" state.
HOWTO: Split one repository into two repositories
If you need to create a repository that's essentially a subset of another repository (perhaps you're make part of a previously-private repo public, for example) try following these instructions from github.
FAQ: Why can't I clone github repositories?
You need to install
[PuTTY](http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html)
and get Pageant running at login, and then do two things:
- Set the
GIT_SSHenvironment variable to point toplink.exe. - Run
plink -agent github.comto accept the server's fingerprint. (For some reason when git is using plink to access github, it can't interactively ask you to accept the host key.)
HOWTO: Revert a merge
If you've done a merge, but you want to get back to how things were before the merge (if you have unexpected merge conflicts, say), you can undo it with:
$ git reset --hard ORIG_HEAD
HOWTO: Add empty directories to a git repository
Strangely, git is actually incapable of representing empty directories in its staging area; see the git FAQ.
One workaround is to add empty .gitignore files to each empty
directory:
$ find . -type d -empty -exec touch {}/.gitignore \;
(Obviously the directories are then no longer genuinely empty, but that may be empty enough for your purposes.)
HOWTO: Remove untracked files
git reset --hard resets the working tree to a previous state, but it
won't remove untracked files. If you want to do this as well, use
git clean:
$ git clean -n
Would remove bin/go
Would remove bin/test.pl
Would remove config/magento-config-20110509153845.sql
Would remove config/magento-config-20110509153904.sql
Would remove config/magento-config-20110509155219.sql
$ git clean -f
Removing bin/go
Removing bin/test.pl
Removing config/magento-config-20110509153845.sql
Removing config/magento-config-20110509153904.sql
Removing config/magento-config-20110509155219.sql
FAQ: What's the "from" and "to" in relation to git diff?
If you're in branch master and you run
$ git diff live-2011-07-11
the diff shows how to get from live-2011-07-11 to master.
HOWTO: Move origin/master to a completely different refspec
Suppose you have two lines of development (a version 1 site, and a
version 2 site, for example), and you put the version 2 site live.
How do you update the master branch from the version 1 development
branch to the version 2 development branch?
First, push the local dev2 branch to origin with the + option to
allow non-fast-forward updates:
$ git push origin +dev2:master
(See git-push(1) for more information on this step.)
At this point, the origin is in the state you want; the problem is
that everyone who's cloned the repository now has a master branch
that diverges wildly from the origin/master branch that they were
tracking; when they checkout master, they'll get a message like:
$ git checkout master
Switched to branch 'master'
Your branch and 'origin/master' have diverged,
and have 164 and 808 different commit(s) each, respectively.
To fix this, they need to delete the master branch, then add it
again, tracking the new origin/master:
$ git branch -D master
Deleted branch master (was 4428499).
$ git checkout master
Branch master set up to track remote branch master from origin.
Switched to a new branch 'master'
Note that if you attempt to delete with -d, you might get:
$ git branch -d master
error: The branch 'master' is not fully merged.
If you are sure you want to delete it, run 'git branch -D master'.
This happens because the local repository has branches which are
ancestors of master--git issues a warning because it's worried
you will lose commits.
HOWTO: Show changed filenames in the git log output
Try:
$ git log --name-status
$ git log --stat
See http://stackoverflow.com/q/1230084/11543.
HOWTO: Unstage a file
(i.e. how to remove a file from the staging area or cache.
If HEAD already exists, you can use reset:
$ git reset -- FILE
More properly, you should use rm --cached:
$ git rm --cached -- FILE
(See http://stackoverflow.com/q/348170.)
HOWTO: Clone an svn repository
You probably want to do it like this:
$ git svn clone --stdlayout --no-minimize-url https://server.com/svn/presentation-layer presentation-layer
(Where https://server.com/svn/presentation-layer contains the
trunk, branches,tags` directories, etc.)
The --no-minimize-url might be necessary if the repository contains
several different repositories; in this case git svn sometimes gets
confused and traverses into a different repository, looking for
"branch points." If you know your repository is self-contained, it's
probably best to make sure no "exploring" goes on.
Note that this doesn't do anything with svn:externals--if your
repository has these you'll need a different system to deal with this.
HOWTO: Change email address per repository
Global settings are in ~/.gitconfig; per-repository settings are in
.git/config and can be changed with git config:
$ git config user.email mjs@email.com
FAQ: What changed in a particular commit?
Use git show:
$ git show 03dbdec63318380ce0fa37ed6fa4fda30be65662
To show only the files that changed:
$ git show --pretty="format:" --name-only 03dbdec63318
HOWTO: Modify a branch with git svn
If does not already exist, create it:
$ git svn branch -m "Extra cool feature" extra-cool-feature
Create branch locally, and associate with branches/release-4.2:
$ git checkout -b extra-cool-feature release-4.2
Make changes as usual, and git commit.
Check that your svn commit will go to the correct branch:
$ git svn dcommit --dry-run
All good? dcommit for real:
$ git svn dcommit