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.

source

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:

More info.

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

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"?

  1. HEAD is a pointer to the node in the object graph that the working directory is associated with.
  2. HEAD is usually an alias of a branch. (This isn't just a model of how it works--.git/HEAD is typically something like ref: refs/heads/live.)
  3. HEAD can be an SHA-1 hash (though this is unusual); in this case you have a "detached HEAD".
  4. Commits always go on top of HEAD. (Whether HEAD is an alias of a branch, or a hash.)
  5. 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.)
  6. ? To prevent such a commit from being garbage collected, name it with a branch--git branch mybranch.
  7. 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.

  1. Create the repository in github.
  2. git remote add github git@github.com:ithinkihaveacat/config.git
  3. 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:

  1. It points the HEAD ref at a new 'target' commit, if you specified one.
  2. Then it copies the tree of the HEAD commit to the index, unless you said --soft.
  3. 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:

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.

More information.

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:

  1. Set the GIT_SSH environment variable to point to plink.exe.
  2. Run plink -agent github.com to 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