## 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). ## TIP: Introduction to git Important concepts Object database Four types of object stored in the object database: * Tags * Pointers/references are SHA-1 hashes (hashes used extensively in git, and exposed to the user). These are the fundamental, and only data structures--every git operation and limitation and error message can be thought of in terms of these data structures, so if, when faced with an operation you don't understand, you can interpret it in terms of these data structures, you'll be okay. For example, there are operations for copying parts of the global object database into your local object database, copying an object and all its descendants into your local database (all released stable versions, for example). Working copy, index Remote branches and tracking git merge does a commit. (And git pull is the equivalent of git fetch; git merge, so it does a commit as well.) branch *names* are not stored in the git object database--the object database doesn't know anything about branch names. branch names are merely short-form references to objects in the object database (or remote object databases). A branch also serves to identify a line of development. (It's kind of a "leaf" in a graph--but since the edges are directional, it picks out a line of development.) In fact, you can think of your local git object database as a subset of all a global git object database, which consists of everyone's merged git object databases. ## 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" returns previously unknown commits. ## FAQ: What's a branch? Conceptually, what is branch? Is is the same as a tag? Are they stored in the repository (object database) itself? ## 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. ## FAQ: How to refer to things? e.g. hexadecimal, tag, "refs/heads/foo". ## FAQ: When is your local repository modified? When is the remote repository modified? e.g. upon merge? Seems to modify repositories a little more eagerly than svn. ## FAQ: What states can a file be in? "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 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 If ## 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" 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? Compare stage and HEAD: $ git diff --cached Compare index and tree: $ git diff Compare branches: $ git diff master..dev ... restrict display to filenames: $ git diff --name-status master..dev Compare trees: # diff of last three commits $ git log -p master~3..master Move file from working directory to index (staging area): $ git add filename Move file from index (staging area) to working directory: $ git reset HEAD filename Move file from staging area to tree: $ git commit Move file from tree to staging area: NA Move tag backwards: $ git reset --hard a6b4c974 (This possibly also replaces the staging area?) Move tag forwards: $ git merge a6b4c974 # or $ git merge $branch Move files from "working copy" into stash (useful to run tests on the change you're planning to commit): $ git stash save --keep-index # same thing $ git stash --keep-index (Note "working copy" is the wrong word here, because this command leaves files in the index unchanged--they stay on disk, and are part of the commit.) Move files from 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? i.e. HEAD, etc. ## 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 your ## 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 To merge the changes ??? ## FAQ: What are the special symbols, and what do they mean? * HEAD * FETCH_HEAD * ~3 - three parents away from symbol See the "Specifying Revisions" section in `git help rev-parse`. ## FAQ: What does `git push` do? Without any arguments, `git push` synchronises your local "active branch" with the remote branch (`remotes/origin/master`?) of the same name. ## FAQ: What are the important `git` concepts? ... and how might they compare to `svn`? * Tags * Branches Document: git branch mybranch git checkout mybranch (i.e. moves branch pointer to "working tree") ## FAQ: How should the term "origin" be interpreted? ... in commands like git push origin :heads/functional See http://github.com/guides/remove-a-remote-branch Operations that are not saved in the repository/operations that modify the repository * Removing a remote branch * Pretty much anything to do with rebasing * (branches aren't part of the repository proper ... a branch points to something in the repository, but isn't part of the repository--?) ## HOWTO: Fix up previous commit $ 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 to 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; a `git pull` may complain, and provide some help text.) ## HOWTO: Remove a remote tracking branch $ git branch -d dev ## HOWTO: Push a branch to a remote server i.e. create a branch on the origin server, for example if you want to e.g. make a branch appear on Github. $ git push origin mybranch ## HOWTO: Remove/delete 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? 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` i.e. how to permanently switch an `svn` repository to a `git` repository 1. Clone the `svn` repository as if you were creating a `git` repository to track it: git svn clone svn+ssh://svn.beebo.org/srv/svn/ssh/trunk ssh This creates a directory `ssh` in the current directory that is a `git` repository. 1. Remove all `svn` tracking information from `.git` ???? git remote rm git-svn (You can also manually remove the [svn-remote "svn"] section.) NOTE: This still leaves the `git-svn` reference in the history, somehow. How to remove this? 1. Create a corresponding bare repository. (This is where you're ultimately going to push changes.) # in e.g. /srv/git git init --bare ssh 1. Add the newly created bare repository as the remote "origin" cd ssh && git remote add origin mjs@mel.beebo.org:/srv/git/ssh 1. Push the changes to the remote bare repository git push origin master (For some reason, the first time you push you need to specify the remote and the branch. This won't be necessary the next time you push changes.) ## 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`).