## 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](http://www.kernel.org/pub/software/scm/git/docs/user-manual.html#how-to-make-a-commit) ## 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". [More info](http://www.kernel.org/pub/software/scm/git/docs/user-manual.html#how-git-stores-references). ## 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 : "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 . ## 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..FETCH_HEAD' means 'show everything that is reachable from the FETCH_HEAD 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 ## 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 : $ 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. 1. 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`.) 1. HEAD can be an SHA-1 hash (though this is unusual); in this case you have a "detached HEAD". 1. Commits always go on top of HEAD. (Whether HEAD is an alias of a branch, or a hash.) 1. 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.) 1. ? To prevent such a commit from being garbage collected, name it with a branch--`git branch mybranch`. 1. 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. 1. git remote add github git@github.com:ithinkihaveacat/config.git 1. git push github master # pushes the master branch to github ## HOWTO: Convert an `svn` repository to `git` See . ## 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](http://github.com/defunkt/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. 1. Then it copies the tree of the HEAD commit to the index, unless you said `--soft`. 1. Finally, it copies the contents of the index to the working tree, if you said `--hard`. See . Alternatively: * `--soft` moves 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. * `--hard` copies the target to both the working tree and the index. (After `--hard`, `git status` will 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 : "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](http://stackoverflow.com/questions/2922652/git-is-there-a-way-to-figure-out-where-a-commit-was-cherry-picked-from/2937724#2937724). 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](http://stackoverflow.com/questions/1710894/using-git-show-all-commits-that-are-in-one-branch-but-not-the-others) 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](http://help.github.com/splitting-a-subpath-to-a-new-repo/). ## 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](https://git.wiki.kernel.org/index.php/GitFaq). 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 . ## 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 .) ## 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