OSDN Git Service

Update document
authorFrank Li <lznuaa@gmail.com>
Mon, 15 Jun 2009 01:38:00 +0000 (09:38 +0800)
committerFrank Li <lznuaa@gmail.com>
Mon, 15 Jun 2009 01:38:00 +0000 (09:38 +0800)
doc/source/en/TortoiseGit/git_book/git_basics.xml [new file with mode: 0644]
doc/source/en/TortoiseGit/git_book/gitbook.xml [new file with mode: 0644]
doc/source/en/TortoiseGit/tortoisegit.xml

diff --git a/doc/source/en/TortoiseGit/git_book/git_basics.xml b/doc/source/en/TortoiseGit/git_book/git_basics.xml
new file mode 100644 (file)
index 0000000..db17ba6
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!DOCTYPE chapter SYSTEM "../../../dtd/dblite.dtd">\r
+\r
+<chapter id="git-book" xmlns:xi="http://www.w3.org/2001/XInclude">\r
+       <title>Git Basic</title>\r
+       <xi:include href="./gitbook.xml"/>\r
+</chapter>\r
\ No newline at end of file
diff --git a/doc/source/en/TortoiseGit/git_book/gitbook.xml b/doc/source/en/TortoiseGit/git_book/gitbook.xml
new file mode 100644 (file)
index 0000000..9a3fbf3
--- /dev/null
@@ -0,0 +1,5352 @@
+<?xml version='1.0'?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<article>
+<articleinfo>
+<title></title>
+</articleinfo>
+
+
+<sect1 id="Git_Community_Boo"><title>Git Community Book</title>
+<sect2 id=""><title></title>
+<para>The open Git resource pulled together by the whole
+community</para>
+
+</sect2><sect2 id="Author"><title>Authors</title>
+Thank these guys: 
+<para>Alecs King (alecsk@gmail.com), Amos Waterland
+(apw@rossby.metr.ou.edu), Andrew Ruder (andy@aeruder.net), Andy
+Parkins (andyparkins@gmail.com), Arjen Laarhoven (arjen@yaph.org),
+Brian Hetro (whee@smaertness.net), Carl Worth (cworth@cworth.org),
+Christian Meder (chris@absolutegiganten.org), Dan McGee
+(dpmcgee@gmail.com), David Kastrup (dak@gnu.org), Dmitry V. Levin
+(ldv@altlinux.org), Francis Daly (francis@daoine.org), Gerrit Pape
+(pape@smarden.org), Greg Louis (glouis@dynamicro.ca), Gustaf
+Hendeby (hendeby@isy.liu.se), Horst H. von Brand
+(vonbrand@inf.utfsm.cl), J. Bruce Fields (bfields@fieldses.org),
+Jakub Narebski (jnareb@gmail.com), Jim Meyering (jim@meyering.net),
+Johan Herland (johan@herland.net), Johannes Schindelin
+(Johannes.Schindelin@gmx.de), Jon Loeliger (jdl@freescale.org),
+Josh Triplett (josh@freedesktop.org), Junio C Hamano
+(gitster@pobox.com), Linus Torvalds (torvalds@osdl.org), Lukas
+Sandström (lukass@etek.chalmers.se), Marcus Fritzsch
+(m@fritschy.de), Michael Coleman (tutufan@gmail.com), Michael Smith
+(msmith@cbnco.com), Mike Coleman (tutufan@gmail.com), Miklos Vajna
+(vmiklos@frugalware.org), Nicolas Pitre (nico@cam.org), Oliver
+Steele (steele@osteele.com), Paolo Ciarrocchi
+(paolo.ciarrocchi@gmail.com), Pavel Roskin (proski@gnu.org), Ralf
+Wildenhues (Ralf.Wildenhues@gmx.de), Robin Rosenberg
+(robin.rosenberg.lists@dewire.com), Santi Béjar
+(sbejar@gmail.com), Scott Chacon (schacon@gmail.com), Sergei
+Organov (osv@javad.com), Shawn Bohrer (shawn.bohrer@gmail.com),
+Shawn O. Pearce (spearce@spearce.org), Steffen Prohaska
+(prohaska@zib.de), Tom Prince (tom.prince@ualberta.net), William
+Pursell (bill.pursell@gmail.com), Yasushi SHOJI
+(yashi@atmark-techno.com)</para>
+</sect2><sect2 id="Maintainer___Edito"><title>Maintainer /
+Editor</title>
+Bug this guy: 
+<para>Scott Chacon (schacon@gmail.com)</para>
+
+</sect2></sect1><sect1 id="Introductio"><title>Introduction</title>
+<sect2 id="Welcome_to_Gi"><title>Welcome to Git</title>
+<para>Welcome to Git - the fast, distributed version control
+system.</para>
+<para>This book is meant to be a starting point for people new to
+Git to learn it as quickly and easily as possible.</para>
+<para>This book will start out by introducing you to the way Git
+stores data, to give you the context for why it is different than
+other VCS tools. This is meant to take you about 20 minutes.</para>
+<para>Next we will cover <emphasis>Basic Git Usage</emphasis> - the
+commands you will be using 90% of the time. These should give you a
+good basis to use Git comfortably for most of what you're going to
+use it for. This section should take you about 30 minutes to read
+through.</para>
+<para>Next we will go over <emphasis>Intermediate Git
+Usage</emphasis> - things that are slightly more complex, but may
+replace some of the basic commands you learned in the first
+section. This will mostly be tricks and commands that will feel
+more comfortable after you know the basic commands.</para>
+<para>After you have all of that mastered, we will cover
+<emphasis>Advanced Git</emphasis> - commands that most people
+probably don't use very often, but can be very helpful in certain
+situations. Learning these commands should round out your
+day-to-day git knowledge; you will be a master of the Git!</para>
+<para>Now that you know Git, we will then cover <emphasis>Working
+with Git</emphasis>. Here we will go over how to use Git in
+scripts, with deployment tools, with editors and more. These
+sections are meant to help you integrate Git into your
+environment.</para>
+<para>Lastly, we will have a series of articles on
+<emphasis>low-level documentation</emphasis> that may help the Git
+hackers who want to learn how the actual internals and protocols
+work in Git.</para>
+<sect3 id="Feedback_and_Contributin"><title>Feedback and
+Contributing</title>
+<para>At any point, if you see a mistake or want to contribute to
+the book, you can send me an email at
+<ulink url="mailto:schacon@gmail.com">schacon@gmail.com</ulink>, or
+you can clone the source of this book at
+<ulink url="http://github.com/schacon/gitbook">http://github.com/schacon/gitbook</ulink>
+and send me a patch or a pull-request.</para>
+</sect3><sect3 id="Reference"><title>References</title>
+<para>Much of this book is pulled together from different sources
+and then added to.If you would like to read some of the original
+articles or resources, please visit them and thank the
+authors:</para>
+<itemizedlist>
+<listitem><ulink url="http://www.kernel.org/pub/software/scm/git/docs/user-manual.html">Git
+User Manual</ulink></listitem>
+<listitem><ulink url="http://www.kernel.org/pub/software/scm/git/docs/gittutorial.html">The
+Git Tutorial</ulink></listitem>
+<listitem><ulink url="http://www.kernel.org/pub/software/scm/git/docs/gittutorial-2.html">The
+Git Tutorial pt 2</ulink></listitem>
+<listitem><ulink url="http://osteele.com/archives/2008/05/my-git-workflow">"My
+Git Workflow" blog post</ulink></listitem>
+</itemizedlist>
+</sect3></sect2><sect2 id="The_Git_Object_Mode"><title>The Git
+Object Model</title>
+<sect3 id="The_SH"><title>The SHA</title>
+<para>All the information needed to represent the history of a
+project is stored in files referenced by a 40-digit "object name"
+that looks something like this:</para>
+<programlisting>
+<literal>6ff87c4664981e4397625791c8ea3bbb5f2279a3
+</literal>
+</programlisting>
+
+<para>You will see these 40-character strings all over the place in
+Git. In each case the name is calculated by taking the SHA1 hash of
+the contents of the object. The SHA1 hash is a cryptographic hash
+function. What that means to us is that it is virtually impossible
+to find two different objects with the same name. This has a number
+of advantages; among others:</para>
+<itemizedlist>
+<listitem>Git can quickly determine whether two objects are
+identical or not, just by comparing names.</listitem>
+<listitem>Since object names are computed the same way in every
+repository, the same content stored in two repositories will always
+be stored under the same name.</listitem>
+<listitem>Git can detect errors when it reads an object, by
+checking that the object's name is still the SHA1 hash of its
+contents.</listitem>
+</itemizedlist>
+</sect3><sect3 id="The_Object"><title>The Objects</title>
+<para>Every object consists of three things - a
+<emphasis>type</emphasis>, a <emphasis>size</emphasis> and
+<emphasis>content</emphasis>. The <emphasis>size</emphasis> is
+simply the size of the contents, the contents depend on what type
+of object it is, and there are four different types of objects:
+"blob", "tree", "commit", and "tag".</para>
+<itemizedlist>
+<listitem>A <para><emphasis>"blob"</emphasis></para> is used to
+store file data - it is generally a file.</listitem>
+<listitem>A <para><emphasis>"tree"</emphasis></para> is basically
+like a directory - it references a bunch of other trees and/or
+blobs (i.e. files and sub-directories)</listitem>
+<listitem>A <para><emphasis>"commit"</emphasis></para> points to a
+single tree, marking it as what the project looked like at a
+certain point in time. It contains meta-information about that
+point in time, such as a timestamp, the author of the changes since
+the last commit, a pointer to the previous commit(s),
+etc.</listitem>
+<listitem>A <para><emphasis>"tag"</emphasis></para> is a way to
+mark a specific commit as special in some way. It is normally used
+to tag certain commits as specific releases or something along
+those lines.</listitem>
+</itemizedlist>
+<para>Almost all of Git is built around manipulating this simple
+structure of four different object types. It is sort of its own
+little filesystem that sits on top of your machine's
+filesystem.</para>
+</sect3><sect3 id="Different_from_SV"><title>Different from
+SVN</title>
+<para>It is important to note that this is very different from most
+SCM systems that you may be familiar with. Subversion, CVS,
+Perforce, Mercurial and the like all use <emphasis>Delta
+Storage</emphasis> systems - they store the differences between one
+commit and the next. Git does not do this - it stores a snapshot of
+what all the files in your project look like in this tree structure
+each time you commit. This is a very important concept to
+understand when using Git.</para>
+</sect3><sect3 id="Blob_Objec"><title>Blob Object</title>
+<para>A blob generally stores the contents of a file.</para>
+<inlinemediaobject><imageobject>
+<imagedata fileref="images/object-blob.png"/>
+</imageobject></inlinemediaobject>
+
+<para>You can use
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-show.html">git
+show</ulink> to examine the contents of any blob. Assuming we have
+the SHA for a blob, we can examine its contents like this:</para>
+<programlisting>
+<literal>$ git show 6ff87c4664
+
+ Note that the only valid version of the GPL as far as this project
+ is concerned is _this_ particular version of the license (ie v2, not
+ v2.2 or v3.x or whatever), unless explicitly otherwise stated.
+...
+</literal>
+</programlisting>
+
+<para>A "blob" object is nothing but a chunk of binary data. It
+doesn't refer to anything else or have attributes of any kind, not
+even a file name.</para>
+<para>Since the blob is entirely defined by its data, if two files
+in a directory tree (or in multiple different versions of the
+repository) have the same contents, they will share the same blob
+object. The object is totally independent of its location in the
+directory tree, and renaming a file does not change the object that
+file is associated with.</para>
+</sect3><sect3 id="Tree_Objec"><title>Tree Object</title>
+<para>A tree is a simple object that has a bunch of pointers to
+blobs and other trees - it generally represents the contents of a
+directory or subdirectory.</para>
+<inlinemediaobject><imageobject>
+<imagedata fileref="images/object-tree.png"/>
+</imageobject></inlinemediaobject>
+
+<para>The ever-versatile
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-show.html">git
+show</ulink> command can also be used to examine tree objects, but
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-ls-tree.html">git
+ls-tree</ulink> will give you more details. Assuming we have the
+SHA for a tree, we can examine it like this:</para>
+<programlisting>
+<literal>$ git ls-tree fb3a8bdd0ce
+100644 blob 63c918c667fa005ff12ad89437f2fdc80926e21c    .gitignore
+100644 blob 5529b198e8d14decbe4ad99db3f7fb632de0439d    .mailmap
+100644 blob 6ff87c4664981e4397625791c8ea3bbb5f2279a3    COPYING
+040000 tree 2fb783e477100ce076f6bf57e4a6f026013dc745    Documentation
+100755 blob 3c0032cec592a765692234f1cba47dfdcc3a9200    GIT-VERSION-GEN
+100644 blob 289b046a443c0647624607d471289b2c7dcd470b    INSTALL
+100644 blob 4eb463797adc693dc168b926b6932ff53f17d0b1    Makefile
+100644 blob 548142c327a6790ff8821d67c2ee1eff7a656b52    README
+...
+</literal>
+</programlisting>
+
+<para>As you can see, a tree object contains a list of entries,
+each with a mode, object type, SHA1 name, and name, sorted by name.
+It represents the contents of a single directory tree.</para>
+<para>An object referenced by a tree may be blob, representing the
+contents of a file, or another tree, representing the contents of a
+subdirectory. Since trees and blobs, like all other objects, are
+named by the SHA1 hash of their contents, two trees have the same
+SHA1 name if and only if their contents (including, recursively,
+the contents of all subdirectories) are identical. This allows git
+to quickly determine the differences between two related tree
+objects, since it can ignore any entries with identical object
+names.</para>
+<para>(Note: in the presence of submodules, trees may also have
+commits as entries. See the <emphasis>Submodules</emphasis>
+section.)</para>
+<para>Note that the files all have mode 644 or 755: git actually
+only pays attention to the executable bit.</para>
+</sect3><sect3 id="Commit_Objec"><title>Commit Object</title>
+<para>The "commit" object links a physical state of a tree with a
+description of how we got there and why.</para>
+<inlinemediaobject><imageobject>
+<imagedata fileref="images/object-commit.png"/>
+</imageobject></inlinemediaobject>
+
+<para>You can use the --pretty=raw option to
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-show.html">git
+show</ulink> or
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-log.html">git
+log</ulink> to examine your favorite commit:</para>
+<programlisting>
+<literal>$ git show -s --pretty=raw 2be7fcb476
+commit 2be7fcb4764f2dbcee52635b91fedb1b3dcf7ab4
+tree fb3a8bdd0ceddd019615af4d57a53f43d8cee2bf
+parent 257a84d9d02e90447b149af58b271c19405edb6a
+author Dave Watson &lt;dwatson@mimvista.com&gt; 1187576872 -0400
+committer Junio C Hamano &lt;gitster@pobox.com&gt; 1187591163 -0700
+
+    Fix misspelling of 'suppress' in docs
+
+    Signed-off-by: Junio C Hamano &lt;gitster@pobox.com&gt;
+</literal>
+</programlisting>
+
+<para>As you can see, a commit is defined by:</para>
+<itemizedlist>
+<listitem>a <para><emphasis>tree</emphasis></para>: The SHA1 name
+of a tree object (as defined below), representing the contents of a
+directory at a certain point in time.</listitem>
+<listitem><para><emphasis>parent(s)</emphasis></para>: The SHA1
+name of some number of commits which represent the immediately
+previous step(s) in the history of the project. The example above
+has one parent; merge commits may have more than one. A commit with
+no parents is called a "root" commit, and represents the initial
+revision of a project. Each project must have at least one root. A
+project can also have multiple roots, though that isn't common (or
+necessarily a good idea).</listitem>
+<listitem>an <para><emphasis>author</emphasis></para>: The name of
+the person responsible for this change, together with its
+date.</listitem>
+<listitem>a <para><emphasis>committer</emphasis></para>: The name
+of the person who actually created the commit, with the date it was
+done. This may be different from the author; for example, if the
+author wrote a patch and emailed it to another person who used the
+patch to create the commit.</listitem>
+<listitem>a <para><emphasis>comment</emphasis></para> describing
+this commit.</listitem>
+</itemizedlist>
+<para>Note that a commit does not itself contain any information
+about what actually changed; all changes are calculated by
+comparing the contents of the tree referred to by this commit with
+the trees associated with its parents. In particular, git does not
+attempt to record file renames explicitly, though it can identify
+cases where the existence of the same file data at changing paths
+suggests a rename. (See, for example, the -M option to
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-diff.html">git
+diff</ulink>).</para>
+<para>A commit is usually created by
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-commit.html">git
+commit</ulink>, which creates a commit whose parent is normally the
+current HEAD, and whose tree is taken from the content currently
+stored in the index.</para>
+</sect3><sect3 id="The_Object_Mode"><title>The Object Model</title>
+<para>So, now that we've looked at the 3 main object types (blob,
+tree and commit), let's take a quick look at how they all fit
+together.</para>
+<para>If we had a simple project with the following directory
+structure:</para>
+<programlisting>
+<literal>$&gt;tree
+.
+|-- README
+`-- lib
+    |-- inc
+    |   `-- tricks.rb
+    `-- mylib.rb
+
+2 directories, 3 files
+</literal>
+</programlisting>
+
+<para>And we committed this to a Git repository, it would be
+represented like this:</para>
+<inlinemediaobject><imageobject>
+<imagedata fileref="images/objects-example.png"/>
+</imageobject></inlinemediaobject>
+
+<para>You can see that we have created a <emphasis>tree</emphasis>
+object for each directory (including the root) and a
+<emphasis>blob</emphasis> object for each file. Then we have a
+<emphasis>commit</emphasis> object to point to the root, so we can
+track what our project looked like when it was committed.</para>
+</sect3><sect3 id="Tag_Objec"><title>Tag Object</title>
+<inlinemediaobject><imageobject>
+<imagedata fileref="images/object-tag.png"/>
+</imageobject></inlinemediaobject>
+
+<para>A tag object contains an object name (called simply
+'object'), object type, tag name, the name of the person ("tagger")
+who created the tag, and a message, which may contain a signature,
+as can be seen using
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-cat-file.html">git
+cat-file</ulink>:</para>
+<programlisting>
+<literal>$ git cat-file tag v1.5.0
+object 437b1b20df4b356c9342dac8d38849f24ef44f27
+type commit
+tag v1.5.0
+tagger Junio C Hamano &lt;junkio@cox.net&gt; 1171411200 +0000
+
+GIT 1.5.0
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.6 (GNU/Linux)
+
+iD8DBQBF0lGqwMbZpPMRm5oRAuRiAJ9ohBLd7s2kqjkKlq1qqC57SbnmzQCdG4ui
+nLE/L9aUXdWeTFPron96DLA=
+=2E+0
+-----END PGP SIGNATURE-----
+</literal>
+</programlisting>
+
+<para>See the
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-tag.html">git
+tag</ulink> command to learn how to create and verify tag objects.
+(Note that
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-tag.html">git
+tag</ulink> can also be used to create "lightweight tags", which
+are not tag objects at all, but just simple references whose names
+begin with "refs/tags/").</para>
+</sect3></sect2><sect2 id="Git_Directory_and_Working_Director"><title>Git
+Directory and Working Directory</title>
+<sect3 id="The_Git_Director"><title>The Git Directory</title>
+<para>The 'git directory' is the directory that stores all Git's
+history and meta information for your project - including all of
+the objects (commits, trees, blobs, tags), all of the pointers to
+where different branches are and more.</para>
+<para>There is only one Git Directory per project (as opposed to
+one per subdirectory like with SVN or CVS), and that directory is
+(by default, though not necessarily) '.git' in the root of your
+project. If you look at the contents of that directory, you can see
+all of your important files:</para>
+<programlisting>
+<literal>$&gt;tree -L 1
+.
+|-- HEAD         # pointer to your current branch
+|-- config       # your configuration preferences
+|-- description  # description of your project 
+|-- hooks/       # pre/post action hooks
+|-- index        # index file (see next section)
+|-- logs/        # a history of where your branches have been
+|-- objects/     # your objects (commits, trees, blobs, tags)
+`-- refs/        # pointers to your branches
+</literal>
+</programlisting>
+
+<para>(there may be some other files/directories in there as well,
+but they are not important for now)</para>
+</sect3><sect3 id="The_Working_Director"><title>The Working
+Directory</title>
+<para>The Git 'working directory' is the directory that holds the
+current checkout of the files you are working on. Files in this
+directory are often removed or replaced by Git as you switch
+branches - this is normal. All your history is stored in the Git
+Directory; the working directory is simply a temporary checkout
+place where you can modify the files until your next commit.</para>
+</sect3></sect2><sect2 id="The_Git_Inde"><title>The Git
+Index</title>
+<para>The Git index is used as a staging area between your working
+directory and your repository. You can use the index to build up a
+set of changes that you want to commit together. When you create a
+commit, what is committed is what is currently in the index, not
+what is in your working directory.</para>
+<sect3 id="Looking_at_the_Inde"><title>Looking at the Index</title>
+<para>The easiest way to see what is in the index is with the
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-status.html">git
+status</ulink> command. When you run git status, you can see which
+files are staged (currently in your index), which are modified but
+not yet staged, and which are completely untracked.</para>
+<programlisting>
+<literal>$&gt;git status
+# On branch master
+# Your branch is behind 'origin/master' by 11 commits, and can be fast-forwarded.
+#
+# Changes to be committed:
+#   (use "git reset HEAD &lt;file&gt;..." to unstage)
+#
+#   modified:   daemon.c
+#
+# Changed but not updated:
+#   (use "git add &lt;file&gt;..." to update what will be committed)
+#
+#   modified:   grep.c
+#   modified:   grep.h
+#
+# Untracked files:
+#   (use "git add &lt;file&gt;..." to include in what will be committed)
+#
+#   blametree
+#   blametree-init
+#   git-gui/git-citool
+</literal>
+</programlisting>
+
+<para>If you blow the index away entirely, you generally haven't
+lost any information as long as you have the name of the tree that
+it described.</para>
+<para>And with that, you should have a pretty good understanding of
+the basics of what Git is doing behind the scenes, and why it is a
+bit different than most other SCM systems. Don't worry if you don't
+totally understand it all right now; we'll revisit all of these
+topics in the next sections. Now we're ready to move on to
+installing, configuring and using Git.</para>
+</sect3></sect2></sect1><sect1 id="First_Tim"><title>First
+Time</title>
+<sect2 id="Installing_Gi"><title>Installing Git</title>
+<sect3 id="Installing_from_Sourc"><title>Installing from
+Source</title>
+<para>In short, on a Unix-based system, you can download the Git
+source code from the <ulink url="http://git-scm.com/download">Git
+Download Page</ulink>, and then run something along the lines of
+:</para>
+<programlisting>
+<literal>$ make prefix=/usr all ;# as yourself
+$ make prefix=/usr install ;# as root
+</literal>
+</programlisting>
+
+<para>You will need the
+<ulink url="http://expat.sourceforge.net/">expat</ulink>,
+<ulink url="http://curl.linux-mirror.org">curl</ulink>,
+<ulink url="http://www.zlib.net">zlib</ulink>, and
+<ulink url="http://www.openssl.org">openssl</ulink> libraries
+installed - though with the possible exception of
+<emphasis>expat</emphasis>, these will normally already be
+there.</para>
+</sect3><sect3 id="Linu"><title>Linux</title>
+<para>If you are running Linux, you can likely install Git easily
+via your native package management system:</para>
+<programlisting>
+<literal>$ yum install git-core
+
+$ apt-get install git-core
+</literal>
+</programlisting>
+
+<para>If that doesn't work, you can download the .deb or .rpm
+packages from here:</para>
+<para><ulink url="http://kernel.org/pub/software/scm/git/RPMS/">RPM
+Packages</ulink></para>
+<para><ulink url="http://www.backports.org/debian/pool/main/g/git-core/">Stable
+Debs</ulink></para>
+<para>If you prefer to install from source on a Linux system, this
+article may be helpful:</para>
+<para><ulink url="http://chrisolsen.org/2008/03/10/installing-git-on-ubuntu/">Article:
+Installing Git on Ubuntu</ulink></para>
+</sect3><sect3 id="Mac_10."><title>Mac 10.4</title>
+<para>In both Mac 10.4 and 10.5, you can install Git via
+<ulink url="http://www.macports.org/">MacPorts</ulink>, if you have
+that installed. If not, you can install it from
+<ulink url="http://www.macports.org/install.php">here</ulink>.</para>
+<para>Once MacPorts is installed, all you should have to do
+is:</para>
+<programlisting>
+<literal>$ sudo port install git-core
+</literal>
+</programlisting>
+
+<para>If you prefer to install from source, these articles may be
+helpful:</para>
+<para><ulink url="http://rails.wincent.com/wiki/Installing_Git_1.5.2.3_on_Mac_OS_X_Tiger">Article:
+Installing Git on Tiger</ulink></para>
+<para><ulink url="http://larrytheliquid.com/2007/12/29/compiling-git-and-git-svn-on-osx-tiger/">Article:
+Installing Git and git-svn on Tiger from source</ulink></para>
+</sect3><sect3 id="Mac_10."><title>Mac 10.5</title>
+<para>With Leopard, you can also install via MacPorts, but here you
+have the additional option of using a nice installer, which you can
+download from here:
+<ulink url="http://code.google.com/p/git-osx-installer/downloads/list?can=3">Git
+OSX Installer</ulink></para>
+<para>If you prefer to install it from source, these guides may be
+particularly helpful to you :</para>
+<para><ulink url="http://solutions.treypiepmeier.com/2008/02/25/installing-git-on-os-x-leopard/">Article:
+Installing Git on OSX Leopard</ulink></para>
+<para><ulink url="http://dysinger.net/2007/12/30/installing-git-on-mac-os-x-105-leopard/">Article:
+Installing Git on OS 10.5</ulink></para>
+</sect3><sect3 id="Window"><title>Windows</title>
+<para>On Windows, installing Git is pretty easy. Simply download
+and install the
+<ulink url="http://code.google.com/p/msysgit/downloads/list">msysGit</ulink>
+package.</para>
+<para>See the <emphasis>Git on Windows</emphasis> chapter for a
+screencast demonstrating installing and using Git on
+Windows.</para>
+</sect3></sect2><sect2 id="Setup_and_Initializatio"><title>Setup
+and Initialization</title>
+<sect3 id="Git_Confi"><title>Git Config</title>
+<para>The first thing you're going to want to do is set up your
+name and email address for Git to use to sign your commits.</para>
+<programlisting>
+<literal>$ git config --global user.name "Scott Chacon"
+$ git config --global user.email "schacon@gmail.com"
+</literal>
+</programlisting>
+
+<para>That will set up a file in your home directory which may be
+used by any of your projects. By default that file is
+<emphasis>~/.gitconfig</emphasis> and the contents will look like
+this:</para>
+<programlisting>
+<literal>[user]
+        name = Scott Chacon
+        email = schacon@gmail.com
+</literal>
+</programlisting>
+
+<para>If you want to override those values for a specific project
+(to use a work email address, for example), you can run the
+<emphasis>git config</emphasis> command without the
+<emphasis>--global</emphasis> option while in that project. This
+will add a [user] section like the one shown above to the
+<emphasis>.git/config</emphasis> file in your project's root
+directory.</para>
+</sect3></sect2></sect1><sect1 id="Basic_Usag"><title>Basic
+Usage</title>
+<sect2 id="Getting_a_Git_Repositor"><title>Getting a Git
+Repository</title>
+<para>So now that we're all set up, we need a Git repository. We
+can do this one of two ways - we can <emphasis>clone</emphasis> one
+that already exists, or we can <emphasis>initialize</emphasis> one
+either from existing files that aren't in source control yet, or
+from an empty directory.</para>
+<sect3 id="Cloning_a_Repositor"><title>Cloning a Repository</title>
+<para>In order to get a copy of a project, you will need to know
+the project's Git URL - the location of the repository. Git can
+operate over many different protocols, so it may begin with ssh://,
+http(s)://, git://, or just a username (in which case git will
+assume ssh). Some repositories may be accessed over more than one
+protocol. For example, the source code to Git itself can be cloned
+either over the git:// protocol:</para>
+<programlisting>
+<literal>git clone git://git.kernel.org/pub/scm/git/git.git
+</literal>
+</programlisting>
+
+<para>or over http:</para>
+<programlisting>
+<literal>git clone http://www.kernel.org/pub/scm/git/git.git
+</literal>
+</programlisting>
+
+<para>The git:// protocol is faster and more efficient, but
+sometimes it is necessary to use http when behind corporate
+firewalls or what have you. In either case you should then have a
+new directory named 'git' that contains all the Git source code and
+history - it is basically a complete copy of what was on the
+server.</para>
+<para>By default, Git will name the new directory it has checked
+out your cloned code into after whatever comes directly before the
+'.git' in the path of the cloned project. (ie. <emphasis>git clone
+http://git.kernel.org/linux/kernel/git/torvalds/linux-2.6.git</emphasis>
+will result in a new directory named 'linux-2.6')</para>
+</sect3><sect3 id="Initializing_a_New_Repositor"><title>Initializing
+a New Repository</title>
+<para>Assume you have a tarball named project.tar.gz with your
+initial work. You can place it under git revision control as
+follows.</para>
+<programlisting>
+<literal>$ tar xzf project.tar.gz
+$ cd project
+$ git init
+</literal>
+</programlisting>
+
+<para>Git will reply</para>
+<programlisting>
+<literal>Initialized empty Git repository in .git/
+</literal>
+</programlisting>
+
+<para>You've now initialized the working directory--you may notice
+a new directory created, named ".git".</para>
+</sect3></sect2><sect2 id="Normal_Workflo"><title>Normal
+Workflow</title>
+<para>Modify some files, then add their updated contents to the
+index:</para>
+<programlisting>
+<literal>$ git add file1 file2 file3
+</literal>
+</programlisting>
+
+<para>You are now ready to commit. You can see what is about to be
+committed using
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-diff.html">git
+diff</ulink> with the --cached option:</para>
+<programlisting>
+<literal>$ git diff --cached
+</literal>
+</programlisting>
+
+<para>(Without --cached,
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-diff.html">git
+diff</ulink> will show you any changes that you've made but not yet
+added to the index.) You can also get a brief summary of the
+situation with
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-status.html">git
+status</ulink>:</para>
+<programlisting>
+<literal>$ git status
+# On branch master
+# Changes to be committed:
+#   (use "git reset HEAD &lt;file&gt;..." to unstage)
+#
+#   modified:   file1
+#   modified:   file2
+#   modified:   file3
+#
+</literal>
+</programlisting>
+
+<para>If you need to make any further adjustments, do so now, and
+then add any newly modified content to the index. Finally, commit
+your changes with:</para>
+<programlisting>
+<literal>$ git commit
+</literal>
+</programlisting>
+
+<para>This will again prompt you for a message describing the
+change, and then record a new version of the project.</para>
+<para>Alternatively, instead of running <literal>git add</literal>
+beforehand, you can use</para>
+<programlisting>
+<literal>$ git commit -a
+</literal>
+</programlisting>
+
+<para>which will automatically notice any modified (but not new)
+files, add them to the index, and commit, all in one step.</para>
+<para>A note on commit messages: Though not required, it's a good
+idea to begin the commit message with a single short (less than 50
+character) line summarizing the change, followed by a blank line
+and then a more thorough description. Tools that turn commits into
+email, for example, use the first line on the Subject: line and the
+rest of the commit message in the body.</para>
+<sect4 id="Git_tracks_content_not_file"><title>Git tracks content
+not files</title>
+<para>Many revision control systems provide an "add" command that
+tells the system to start tracking changes to a new file. Git's
+"add" command does something simpler and more powerful:
+<literal>git add</literal> is used both for new and newly modified
+files, and in both cases it takes a snapshot of the given files and
+stages that content in the index, ready for inclusion in the next
+commit.</para>
+</sect4></sect2><sect2 id="Basic_Branching_and_Mergin"><title>Basic
+Branching and Merging</title>
+<para>A single git repository can maintain multiple branches of
+development. To create a new branch named "experimental",
+use</para>
+<programlisting>
+<literal>$ git branch experimental
+</literal>
+</programlisting>
+
+<para>If you now run</para>
+<programlisting>
+<literal>$ git branch
+</literal>
+</programlisting>
+
+<para>you'll get a list of all existing branches:</para>
+<programlisting>
+<literal> experimental
+* master
+</literal>
+</programlisting>
+
+<para>The "experimental" branch is the one you just created, and
+the "master" branch is a default branch that was created for you
+automatically. The asterisk marks the branch you are currently on;
+type</para>
+<programlisting>
+<literal>$ git checkout experimental
+</literal>
+</programlisting>
+
+<para>to switch to the experimental branch. Now edit a file, commit
+the change, and switch back to the master branch:</para>
+<programlisting>
+<literal>(edit file)
+$ git commit -a
+$ git checkout master
+</literal>
+</programlisting>
+
+<para>Check that the change you made is no longer visible, since it
+was made on the experimental branch and you're back on the master
+branch.</para>
+<para>You can make a different change on the master branch:</para>
+<programlisting>
+<literal>(edit file)
+$ git commit -a
+</literal>
+</programlisting>
+
+<para>at this point the two branches have diverged, with different
+changes made in each. To merge the changes made in experimental
+into master, run</para>
+<programlisting>
+<literal>$ git merge experimental
+</literal>
+</programlisting>
+
+<para>If the changes don't conflict, you're done. If there are
+conflicts, markers will be left in the problematic files showing
+the conflict;</para>
+<programlisting>
+<literal>$ git diff
+</literal>
+</programlisting>
+
+<para>will show this. Once you've edited the files to resolve the
+conflicts,</para>
+<programlisting>
+<literal>$ git commit -a
+</literal>
+</programlisting>
+
+<para>will commit the result of the merge. Finally,</para>
+<programlisting>
+<literal>$ gitk
+</literal>
+</programlisting>
+
+<para>will show a nice graphical representation of the resulting
+history.</para>
+<para>At this point you could delete the experimental branch
+with</para>
+<programlisting>
+<literal>$ git branch -d experimental
+</literal>
+</programlisting>
+
+<para>This command ensures that the changes in the experimental
+branch are already in the current branch.</para>
+<para>If you develop on a branch crazy-idea, then regret it, you
+can always delete the branch with</para>
+<programlisting>
+<literal>$ git branch -D crazy-idea
+</literal>
+</programlisting>
+
+<para>Branches are cheap and easy, so this is a good way to try
+something out.</para>
+<sect3 id="How_to_merg"><title>How to merge</title>
+<para>You can rejoin two diverging branches of development using
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-merge.html">git
+merge</ulink>:</para>
+<programlisting>
+<literal>$ git merge branchname
+</literal>
+</programlisting>
+
+<para>merges the changes made in the branch "branchname" into the
+current branch. If there are conflicts--for example, if the same
+file is modified in two different ways in the remote branch and the
+local branch--then you are warned; the output may look something
+like this:</para>
+<programlisting>
+<literal>$ git merge next
+ 100% (4/4) done
+Auto-merged file.txt
+CONFLICT (content): Merge conflict in file.txt
+Automatic merge failed; fix conflicts and then commit the result.
+</literal>
+</programlisting>
+
+<para>Conflict markers are left in the problematic files, and after
+you resolve the conflicts manually, you can update the index with
+the contents and run git commit, as you normally would when
+modifying a file.</para>
+<para>If you examine the resulting commit using gitk, you will see
+that it has two parents: one pointing to the top of the current
+branch, and one to the top of the other branch.</para>
+</sect3><sect3 id="Resolving_a_merg"><title>Resolving a
+merge</title>
+<para>When a merge isn't resolved automatically, git leaves the
+index and the working tree in a special state that gives you all
+the information you need to help resolve the merge.</para>
+<para>Files with conflicts are marked specially in the index, so
+until you resolve the problem and update the index,
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-commit.html">git
+commit</ulink> will fail:</para>
+<programlisting>
+<literal>$ git commit
+file.txt: needs merge
+</literal>
+</programlisting>
+
+<para>Also,
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-status.html">git
+status</ulink> will list those files as "unmerged", and the files
+with conflicts will have conflict markers added, like this:</para>
+<programlisting>
+<literal>&lt;&lt;&lt;&lt;&lt;&lt;&lt; HEAD:file.txt
+Hello world
+=======
+Goodbye
+&gt;&gt;&gt;&gt;&gt;&gt;&gt; 77976da35a11db4580b80ae27e8d65caf5208086:file.txt
+</literal>
+</programlisting>
+
+<para>All you need to do is edit the files to resolve the
+conflicts, and then</para>
+<programlisting>
+<literal>$ git add file.txt
+$ git commit
+</literal>
+</programlisting>
+
+<para>Note that the commit message will already be filled in for
+you with some information about the merge. Normally you can just
+use this default message unchanged, but you may add additional
+commentary of your own if desired.</para>
+<para>The above is all you need to know to resolve a simple merge.
+But git also provides more information to help resolve
+conflicts:</para>
+</sect3><sect3 id="Undoing_a_merg"><title>Undoing a merge</title>
+<para>If you get stuck and decide to just give up and throw the
+whole mess away, you can always return to the pre-merge state
+with</para>
+<programlisting>
+<literal>$ git reset --hard HEAD
+</literal>
+</programlisting>
+
+<para>Or, if you've already committed the merge that you want to
+throw away,</para>
+<programlisting>
+<literal>$ git reset --hard ORIG_HEAD
+</literal>
+</programlisting>
+
+<para>However, this last command can be dangerous in some
+cases--never throw away a commit if that commit may itself have
+been merged into another branch, as doing so may confuse further
+merges.</para>
+</sect3><sect3 id="Fast-forward_merge"><title>Fast-forward
+merges</title>
+<para>There is one special case not mentioned above, which is
+treated differently. Normally, a merge results in a merge commit
+with two parents, one for each of the two lines of development that
+were merged.</para>
+<para>However, if the current branch has not diverged from the
+other--so every commit present in the current branch is already
+contained in the other--then git just performs a "fast forward";
+the head of the current branch is moved forward to point at the
+head of the merged-in branch, without any new commits being
+created.</para>
+</sect3></sect2><sect2 id="Reviewing_History_-_Git_Lo"><title>Reviewing
+History - Git Log</title>
+<para>The
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-log.html">git
+log</ulink> command can show lists of commits. On its own, it shows
+all commits reachable from the parent commit; but you can also make
+more specific requests:</para>
+<programlisting>
+<literal>$ git log v2.5..        # commits since (not reachable from) v2.5
+$ git log test..master  # commits reachable from master but not test
+$ git log master..test  # commits reachable from test but not master
+$ git log master...test # commits reachable from either test or
+                        #    master, but not both
+$ git log --since="2 weeks ago" # commits from the last 2 weeks
+$ git log Makefile      # commits that modify Makefile
+$ git log fs/           # commits that modify any file under fs/
+$ git log -S'foo()'     # commits that add or remove any file data
+                        # matching the string 'foo()'
+$ git log --no-merges   # dont show merge commits
+</literal>
+</programlisting>
+
+<para>And of course you can combine all of these; the following
+finds commits since v2.5 which touch the Makefile or any file under
+fs:</para>
+<programlisting>
+<literal>$ git log v2.5.. Makefile fs/
+</literal>
+</programlisting>
+
+<para>Git log will show a listing of each commit, with the most
+recent commits first, that match the arguments given to the log
+command.</para>
+<programlisting>
+<literal>commit f491239170cb1463c7c3cd970862d6de636ba787
+Author: Matt McCutchen &lt;matt@mattmccutchen.net&gt;
+Date:   Thu Aug 14 13:37:41 2008 -0400
+
+    git format-patch documentation: clarify what --cover-letter does
+
+commit 7950659dc9ef7f2b50b18010622299c508bfdfc3
+Author: Eric Raible &lt;raible@gmail.com&gt;
+Date:   Thu Aug 14 10:12:54 2008 -0700
+
+    bash completion: 'git apply' should use 'fix' not 'strip'
+    Bring completion up to date with the man page.
+</literal>
+</programlisting>
+
+<para>You can also ask git log to show patches:</para>
+<programlisting>
+<literal>$ git log -p
+
+commit da9973c6f9600d90e64aac647f3ed22dfd692f70
+Author: Robert Schiele &lt;rschiele@gmail.com&gt;
+Date:   Mon Aug 18 16:17:04 2008 +0200
+
+    adapt git-cvsserver manpage to dash-free syntax
+
+diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt
+index c2d3c90..785779e 100644
+--- a/Documentation/git-cvsserver.txt
++++ b/Documentation/git-cvsserver.txt
+@@ -11,7 +11,7 @@ SYNOPSIS
+ SSH:
+
+ [verse]
+-export CVS_SERVER=git-cvsserver
++export CVS_SERVER="git cvsserver"
+ 'cvs' -d :ext:user@server/path/repo.git co &lt;HEAD_name&gt;
+
+ pserver (/etc/inetd.conf):
+</literal>
+</programlisting>
+
+<sect3 id="Log_Stat"><title>Log Stats</title>
+<para>If you pass the <literal>--stat</literal> option to 'git
+log', it will show you which files have changed in that commit and
+how many lines were added and removed from each.</para>
+<programlisting>
+<literal>$ git log --stat
+
+commit dba9194a49452b5f093b96872e19c91b50e526aa
+Author: Junio C Hamano &lt;gitster@pobox.com&gt;
+Date:   Sun Aug 17 15:44:11 2008 -0700
+
+    Start 1.6.0.X maintenance series
+
+ Documentation/RelNotes-1.6.0.1.txt |   15 +++++++++++++++
+ RelNotes                           |    2 +-
+ 2 files changed, 16 insertions(+), 1 deletions(-)
+</literal>
+</programlisting>
+
+</sect3><sect3 id="Formatting_the_Lo"><title>Formatting the
+Log</title>
+<para>You can also format the log output almost however you want.
+The '--pretty' option can take a number of preset formats, such as
+'oneline':</para>
+<programlisting>
+<literal>$ git log --pretty=oneline
+a6b444f570558a5f31ab508dc2a24dc34773825f dammit, this is the second time this has reverted
+49d77f72783e4e9f12d1bbcacc45e7a15c800240 modified index to create refs/heads if it is not 
+9764edd90cf9a423c9698a2f1e814f16f0111238 Add diff-lcs dependency
+e1ba1e3ca83d53a2f16b39c453fad33380f8d1cc Add dependency for Open4
+0f87b4d9020fff756c18323106b3fd4e2f422135 merged recent changes: * accepts relative alt pat
+f0ce7d5979dfb0f415799d086e14a8d2f9653300 updated the Manifest file
+</literal>
+</programlisting>
+
+<para>or you can do 'short' format:</para>
+<programlisting>
+<literal>$ git log --pretty=short
+commit a6b444f570558a5f31ab508dc2a24dc34773825f
+Author: Scott Chacon &lt;schacon@gmail.com&gt;
+
+    dammit, this is the second time this has reverted
+
+commit 49d77f72783e4e9f12d1bbcacc45e7a15c800240
+Author: Scott Chacon &lt;schacon@gmail.com&gt;
+
+    modified index to create refs/heads if it is not there
+
+commit 9764edd90cf9a423c9698a2f1e814f16f0111238
+Author: Hans Engel &lt;engel@engel.uk.to&gt;
+
+    Add diff-lcs dependency
+</literal>
+</programlisting>
+
+<para>You can also use 'medium', 'full', 'fuller', 'email' or
+'raw'. If those formats aren't exactly what you need, you can also
+create your own format with the '--pretty=format' option (see the
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-log.html">git
+log</ulink> docs for all the formatting options).</para>
+<programlisting>
+<literal>$ git log --pretty=format:'%h was %an, %ar, message: %s'
+a6b444f was Scott Chacon, 5 days ago, message: dammit, this is the second time this has re
+49d77f7 was Scott Chacon, 8 days ago, message: modified index to create refs/heads if it i
+9764edd was Hans Engel, 11 days ago, message: Add diff-lcs dependency
+e1ba1e3 was Hans Engel, 11 days ago, message: Add dependency for Open4
+0f87b4d was Scott Chacon, 12 days ago, message: merged recent changes:
+</literal>
+</programlisting>
+
+<para>Another interesting thing you can do is visualize the commit
+graph with the '--graph' option, like so:</para>
+<programlisting>
+<literal>$ git log --pretty=format:'%h : %s' --graph
+* 2d3acf9 : ignore errors from SIGCHLD on trap
+*   5e3ee11 : Merge branch 'master' of git://github.com/dustin/grit
+|\  
+| * 420eac9 : Added a method for getting the current branch.
+* | 30e367c : timeout code and tests
+* | 5a09431 : add timeout protection to grit
+* | e1193f8 : support for heads with slashes in them
+|/  
+* d6016bc : require time for xmlschema
+</literal>
+</programlisting>
+
+<para>It will give a pretty nice ASCII representation of the commit
+history lines.</para>
+</sect3><sect3 id="Ordering_the_Lo"><title>Ordering the Log</title>
+<para>You can also view the log entries in a few different orders.
+Note that git log starts with the most recent commit and works
+backwards through the parents; however, since git history can
+contain multiple independent lines of development, the particular
+order that commits are listed in may be somewhat arbitrary.</para>
+<para>If you want to specify a certain order, you can add an
+ordering option to the git log command.</para>
+<para>By default, the commits are shown in reverse chronological
+order.</para>
+<para>However, you can also specify '--topo-order', which makes the
+commits appear in topological order (i.e. descendant commits are
+shown before their parents). If we view the git log for the Grit
+repo in topo-order, you can see that the development lines are all
+grouped together.</para>
+<programlisting>
+<literal>$ git log --pretty=format:'%h : %s' --topo-order --graph
+*   4a904d7 : Merge branch 'idx2'
+|\  
+| *   dfeffce : merged in bryces changes and fixed some testing issues
+| |\  
+| | * 23f4ecf : Clarify how to get a full count out of Repo#commits
+| | *   9d6d250 : Appropriate time-zone test fix from halorgium
+| | |\  
+| | | * cec36f7 : Fix the to_hash test to run in US/Pacific time
+| | * | decfe7b : fixed manifest and grit.rb to make correct gemspec
+| | * | cd27d57 : added lib/grit/commit_stats.rb to the big list o' files
+| | * | 823a9d9 : cleared out errors by adding in Grit::Git#run method
+| | * |   4eb3bf0 : resolved merge conflicts, hopefully amicably
+| | |\ \  
+| | | * | d065e76 : empty commit to push project to runcoderun
+| | | * | 3fa3284 : whitespace
+| | | * | d01cffd : whitespace
+| | | * | 7c74272 : oops, update version here too
+| | | * | 13f8cc3 : push 0.8.3
+| | | * | 06bae5a : capture stderr and log it if debug is true when running commands
+| | | * | 0b5bedf : update history
+| | | * | d40e1f0 : some docs
+| | | * | ef8a23c : update gemspec to include the newly added files to manifest
+| | | * | 15dd347 : add missing files to manifest; add grit test
+| | | * | 3dabb6a : allow sending debug messages to a user defined logger if provided; tes
+| | | * | eac1c37 : pull out the date in this assertion and compare as xmlschemaw, to avoi
+| | | * | 0a7d387 : Removed debug print.
+| | | * | 4d6b69c : Fixed to close opened file description.
+</literal>
+</programlisting>
+
+<para>You can also use '--date-order', which orders the commits
+primarily by commit date. This option is similar to --topo-order in
+the sense that no parent comes before all of its children, but
+otherwise things are still ordered in the commit timestamp order.
+You can see that development lines are not grouped together here,
+that they jump around as parallel development occurred:</para>
+<programlisting>
+<literal>$ git log --pretty=format:'%h : %s' --date-order --graph
+*   4a904d7 : Merge branch 'idx2'
+|\  
+* | 81a3e0d : updated packfile code to recognize index v2
+| *   dfeffce : merged in bryces changes and fixed some testing issues
+| |\  
+| * | c615d80 : fixed a log issue
+|/ /  
+| * 23f4ecf : Clarify how to get a full count out of Repo#commits
+| *   9d6d250 : Appropriate time-zone test fix from halorgium
+| |\  
+| * | decfe7b : fixed manifest and grit.rb to make correct gemspec
+| * | cd27d57 : added lib/grit/commit_stats.rb to the big list o' file
+| * | 823a9d9 : cleared out errors by adding in Grit::Git#run method
+| * |   4eb3bf0 : resolved merge conflicts, hopefully amicably
+| |\ \  
+| * | | ba23640 : Fix CommitDb errors in test (was this the right fix?
+| * | | 4d8873e : test_commit no longer fails if you're not in PDT
+| * | | b3285ad : Use the appropriate method to find a first occurrenc
+| * | | 44dda6c : more cleanly accept separate options for initializin
+| * | | 839ba9f : needed to be able to ask Repo.new to work with a bar
+| | * | d065e76 : empty commit to push project to runcoderun
+* | | | 791ec6b : updated grit gemspec
+* | | | 756a947 : including code from github updates
+| | * | 3fa3284 : whitespace
+| | * | d01cffd : whitespace
+| * | | a0e4a3d : updated grit gemspec
+| * | | 7569d0d : including code from github updates
+</literal>
+</programlisting>
+
+<para>Lastly, you can reverse the order of the log with the
+'--reverse' option.</para>
+</sect3></sect2><sect2 id="Comparing_Commits_-_Git_Dif"><title>Comparing
+Commits - Git Diff</title>
+<para>You can generate diffs between any two versions of your
+project using
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-diff.html">git
+diff</ulink>:</para>
+<programlisting>
+<literal>$ git diff master..test
+</literal>
+</programlisting>
+
+<para>That will produce the diff between the tips of the two
+branches. If you'd prefer to find the diff from their common
+ancestor to test, you can use three dots instead of two:</para>
+<programlisting>
+<literal>$ git diff master...test
+</literal>
+</programlisting>
+
+<para><ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-diff.html">git
+diff</ulink> is an incredibly useful tool for figuring out what has
+changed between any two points in your project's history, or to see
+what people are trying to introduce in new branches, etc.</para>
+<sect3 id="What_you_will_commi"><title>What you will commit</title>
+<para>You will commonly use
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-diff.html">git
+diff</ulink> for figuring out differences between your last commit,
+your index, and your current working directory. A common use is to
+simply run</para>
+<programlisting>
+<literal>$ git diff
+</literal>
+</programlisting>
+
+<para>which will show you changes in the working directory that are
+not yet staged for the next commit. If you want to see what
+<emphasis>is</emphasis> staged for the next commit, you can
+run</para>
+<programlisting>
+<literal>$ git diff --cached
+</literal>
+</programlisting>
+
+<para>which will show you the difference between the index and your
+last commit; what you would be committing if you run "git commit"
+without the "-a" option. Lastly, you can run</para>
+<programlisting>
+<literal>$ git diff HEAD
+</literal>
+</programlisting>
+
+<para>which shows changes in the working directory since your last
+commit; what you would be committing if you run "git commit
+-a".</para>
+</sect3><sect3 id="More_Diff_Option"><title>More Diff
+Options</title>
+<para>If you want to see how your current working directory differs
+from the state of the project in another branch, you can run
+something like</para>
+<programlisting>
+<literal>$ git diff test
+</literal>
+</programlisting>
+
+<para>This will show you what is different between your current
+working directory and the snapshot on the 'test' branch. You can
+also limit the comparison to a specific file or subdirectory by
+adding a <emphasis>path limiter</emphasis>:</para>
+<programlisting>
+<literal>$ git diff HEAD -- ./lib 
+</literal>
+</programlisting>
+
+<para>That command will show the changes between your current
+working directory and the last commit (or, more accurately, the tip
+of the current branch), limiting the comparison to files in the
+'lib' subdirectory.</para>
+<para>If you don't want to see the whole patch, you can add the
+'--stat' option, which will limit the output to the files that have
+changed along with a little text graph depicting how many lines
+changed in each file.</para>
+<programlisting>
+<literal>$&gt;git diff --stat
+ layout/book_index_template.html                    |    8 ++-
+ text/05_Installing_Git/0_Source.markdown           |   14 ++++++
+ text/05_Installing_Git/1_Linux.markdown            |   17 +++++++
+ text/05_Installing_Git/2_Mac_104.markdown          |   11 +++++
+ text/05_Installing_Git/3_Mac_105.markdown          |    8 ++++
+ text/05_Installing_Git/4_Windows.markdown          |    7 +++
+ .../1_Getting_a_Git_Repo.markdown                  |    7 +++-
+ .../0_ Comparing_Commits_Git_Diff.markdown         |   45 +++++++++++++++++++-
+ .../0_ Hosting_Git_gitweb_repoorcz_github.markdown |    4 +-
+ 9 files changed, 115 insertions(+), 6 deletions(-)
+</literal>
+</programlisting>
+
+<para>Sometimes that makes it easier to see overall what has
+changed, to jog your memory.</para>
+</sect3></sect2><sect2 id="Distributed_Workflow"><title>Distributed
+Workflows</title>
+<para>Suppose that Alice has started a new project with a git
+repository in /home/alice/project, and that Bob, who has a home
+directory on the same machine, wants to contribute.</para>
+<para>Bob begins with:</para>
+<programlisting>
+<literal>$ git clone /home/alice/project myrepo
+</literal>
+</programlisting>
+
+<para>This creates a new directory "myrepo" containing a clone of
+Alice's repository. The clone is on an equal footing with the
+original project, possessing its own copy of the original project's
+history.</para>
+<para>Bob then makes some changes and commits them:</para>
+<programlisting>
+<literal>(edit files)
+$ git commit -a
+(repeat as necessary)
+</literal>
+</programlisting>
+
+<para>When he's ready, he tells Alice to pull changes from the
+repository at /home/bob/myrepo. She does this with:</para>
+<programlisting>
+<literal>$ cd /home/alice/project
+$ git pull /home/bob/myrepo master
+</literal>
+</programlisting>
+
+<para>This merges the changes from Bob's "master" branch into
+Alice's current branch. If Alice has made her own changes in the
+meantime, then she may need to manually fix any conflicts. (Note
+that the "master" argument in the above command is actually
+unnecessary, as it is the default.)</para>
+<para>The "pull" command thus performs two operations: it fetches
+changes from a remote branch, then merges them into the current
+branch.</para>
+<para>When you are working in a small closely knit group, it is not
+unusual to interact with the same repository over and over again.
+By defining 'remote' repository shorthand, you can make it
+easier:</para>
+<programlisting>
+<literal>$ git remote add bob /home/bob/myrepo
+</literal>
+</programlisting>
+
+<para>With this, Alice can perform the first operation alone using
+the "git fetch" command without merging them with her own branch,
+using:</para>
+<programlisting>
+<literal>$ git fetch bob
+</literal>
+</programlisting>
+
+<para>Unlike the longhand form, when Alice fetches from Bob using a
+remote repository shorthand set up with <literal>git
+remote</literal>, what was fetched is stored in a remote tracking
+branch, in this case <literal>bob/master</literal>. So after
+this:</para>
+<programlisting>
+<literal>$ git log -p master..bob/master
+</literal>
+</programlisting>
+
+<para>shows a list of all the changes that Bob made since he
+branched from Alice's master branch.</para>
+<para>After examining those changes, Alice could merge the changes
+into her master branch:</para>
+<programlisting>
+<literal>$ git merge bob/master
+</literal>
+</programlisting>
+
+<para>This <literal>merge</literal> can also be done by 'pulling
+from her own remote tracking branch', like this:</para>
+<programlisting>
+<literal>$ git pull . remotes/bob/master
+</literal>
+</programlisting>
+
+<para>Note that git pull always merges into the current branch,
+regardless of what else is given on the command line.</para>
+<para>Later, Bob can update his repo with Alice's latest changes
+using</para>
+<programlisting>
+<literal>$ git pull
+</literal>
+</programlisting>
+
+<para>Note that he doesn't need to give the path to Alice's
+repository; when Bob cloned Alice's repository, git stored the
+location of her repository in the repository configuration, and
+that location is used for pulls:</para>
+<programlisting>
+<literal>$ git config --get remote.origin.url
+/home/alice/project
+</literal>
+</programlisting>
+
+<para>(The complete configuration created by git-clone is visible
+using "git config -l", and the
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-config.html">git
+config</ulink> man page explains the meaning of each
+option.)</para>
+<para>Git also keeps a pristine copy of Alice's master branch under
+the name "origin/master":</para>
+<programlisting>
+<literal>$ git branch -r
+  origin/master
+</literal>
+</programlisting>
+
+<para>If Bob later decides to work from a different host, he can
+still perform clones and pulls using the ssh protocol:</para>
+<programlisting>
+<literal>$ git clone alice.org:/home/alice/project myrepo
+</literal>
+</programlisting>
+
+<para>Alternatively, git has a native protocol, or can use rsync or
+http; see
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-pull.html">git
+pull</ulink> for details.</para>
+<para>Git can also be used in a CVS-like mode, with a central
+repository that various users push changes to; see
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-push.html">git
+push</ulink> and
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/gitcvs-migration.html">gitcvs-migration</ulink>.</para>
+<sect3 id="Public_git_repositorie"><title>Public git
+repositories</title>
+<para>Another way to submit changes to a project is to tell the
+maintainer of that project to pull the changes from your repository
+using
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-pull.html">git
+pull</ulink>. This is a way to get updates from the "main"
+repository, but it works just as well in the other
+direction.</para>
+<para>If you and the maintainer both have accounts on the same
+machine, then you can just pull changes from each other's
+repositories directly; commands that accept repository URLs as
+arguments will also accept a local directory name:</para>
+<programlisting>
+<literal>$ git clone /path/to/repository
+$ git pull /path/to/other/repository
+</literal>
+</programlisting>
+
+<para>or an ssh URL:</para>
+<programlisting>
+<literal>$ git clone ssh://yourhost/~you/repository
+</literal>
+</programlisting>
+
+<para>For projects with few developers, or for synchronizing a few
+private repositories, this may be all you need.</para>
+<para>However, the more common way to do this is to maintain a
+separate public repository (usually on a different host) for others
+to pull changes from. This is usually more convenient, and allows
+you to cleanly separate private work in progress from publicly
+visible work.</para>
+<para>You will continue to do your day-to-day work in your personal
+repository, but periodically "push" changes from your personal
+repository into your public repository, allowing other developers
+to pull from that repository. So the flow of changes, in a
+situation where there is one other developer with a public
+repository, looks like this:</para>
+<programlisting>
+<literal>                       you push
+  your personal repo ------------------&gt; your public repo
+    ^                                     |
+    |                                     |
+    | you pull                            | they pull
+    |                                     |
+    |                                     |
+        |               they push             V
+  their public repo &lt;------------------- their repo
+</literal>
+</programlisting>
+
+</sect3><sect3 id="Pushing_changes_to_a_public_repositor"><title>Pushing
+changes to a public repository</title>
+<para>Note that exporting via http or git allow other maintainers
+to fetch your latest changes, but they do not allow write access.
+For this, you will need to update the public repository with the
+latest changes created in your private repository.</para>
+<para>The simplest way to do this is using
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-push.html">git
+push</ulink> and ssh; to update the remote branch named "master"
+with the latest state of your branch named "master", run</para>
+<programlisting>
+<literal>$ git push ssh://yourserver.com/~you/proj.git master:master
+</literal>
+</programlisting>
+
+<para>or just</para>
+<programlisting>
+<literal>$ git push ssh://yourserver.com/~you/proj.git master
+</literal>
+</programlisting>
+
+<para>As with git-fetch, git-push will complain if this does not
+result in a fast forward; see the following section for details on
+handling this case.</para>
+<para>Note that the target of a "push" is normally a bare
+repository. You can also push to a repository that has a
+checked-out working tree, but the working tree will not be updated
+by the push. This may lead to unexpected results if the branch you
+push to is the currently checked-out branch!</para>
+<para>As with git-fetch, you may also set up configuration options
+to save typing; so, for example, after</para>
+<programlisting>
+<literal>$ cat &gt;&gt;.git/config &lt;&lt;EOF
+[remote "public-repo"]
+    url = ssh://yourserver.com/~you/proj.git
+EOF
+</literal>
+</programlisting>
+
+<para>you should be able to perform the above push with just</para>
+<programlisting>
+<literal>$ git push public-repo master
+</literal>
+</programlisting>
+
+<para>See the explanations of the remote..url, branch..remote, and
+remote..push options in
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-config.html">git
+config</ulink> for details.</para>
+</sect3><sect3 id="What_to_do_when_a_push_fail"><title>What to do
+when a push fails</title>
+<para>If a push would not result in a fast forward of the remote
+branch, then it will fail with an error like:</para>
+<programlisting>
+<literal>error: remote 'refs/heads/master' is not an ancestor of
+local  'refs/heads/master'.
+Maybe you are not up-to-date and need to pull first?
+error: failed to push to 'ssh://yourserver.com/~you/proj.git'
+</literal>
+</programlisting>
+
+<para>This can happen, for example, if you:</para>
+<programlisting>
+<literal>- use `git-reset --hard` to remove already-published commits, or
+- use `git-commit --amend` to replace already-published commits, or
+- use `git-rebase` to rebase any already-published commits.
+</literal>
+</programlisting>
+
+<para>You may force git-push to perform the update anyway by
+preceding the branch name with a plus sign:</para>
+<programlisting>
+<literal>$ git push ssh://yourserver.com/~you/proj.git +master
+</literal>
+</programlisting>
+
+<para>Normally whenever a branch head in a public repository is
+modified, it is modified to point to a descendant of the commit
+that it pointed to before. By forcing a push in this situation, you
+break that convention.</para>
+<para>Nevertheless, this is a common practice for people that need
+a simple way to publish a work-in-progress patch series, and it is
+an acceptable compromise as long as you warn other developers that
+this is how you intend to manage the branch.</para>
+<para>It's also possible for a push to fail in this way when other
+people have the right to push to the same repository. In that case,
+the correct solution is to retry the push after first updating your
+work: either by a pull, or by a fetch followed by a rebase; see the
+next section and
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/gitcvs-migration.html">gitcvs-migration</ulink>
+for more.</para>
+</sect3></sect2><sect2 id="Git_Ta"><title>Git Tag</title>
+<sect3 id="Lightweight_Tag"><title>Lightweight Tags</title>
+<para>We can create a tag to refer to a particular commit by
+running
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-tag.html">git
+tag</ulink> with no arguments.</para>
+<programlisting>
+<literal>$ git tag stable-1 1b2e1d63ff
+</literal>
+</programlisting>
+
+<para>After that, we can use stable-1 to refer to the commit
+1b2e1d63ff.</para>
+<para>This creates a "lightweight" tag, basically a branch that
+never moves. If you would also like to include a comment with the
+tag, and possibly sign it cryptographically, then we can create a
+<emphasis>tag object</emphasis> instead.</para>
+</sect3><sect3 id="Tag_Object"><title>Tag Objects</title>
+<para>If one of <emphasis>-a</emphasis>, <emphasis>-s</emphasis>,
+or <emphasis>-u &lt;key-id&gt;</emphasis> is passed, the command
+creates a tag object, and requires the tag message. Unless -m  or
+-F  is given, an editor is started for the user to type in the tag
+message.</para>
+<para>When this happens, a new object is added to the Git object
+database and the tag ref points to that <emphasis>tag
+object</emphasis>, rather than the commit itself. The strength of
+this is that you can sign the tag, so you can verify that it is the
+correct commit later. You can create a tag object like this:</para>
+<programlisting>
+<literal>$ git tag -a stable-1 1b2e1d63ff
+</literal>
+</programlisting>
+
+<para>It is actually possible to tag any object, but tagging commit
+objects is the most common. (In the Linux kernel source, the first
+tag object references a tree, rather than a commit)</para>
+</sect3><sect3 id="Signed_Tag"><title>Signed Tags</title>
+<para>If you have a GPG key setup, you can create signed tags
+fairly easily. First, you will probably want to setup your key id
+in your <emphasis>.git/config</emphasis> or
+<emphasis>~.gitconfig</emphasis> file.</para>
+<programlisting>
+<literal>[user]
+    signingkey = &lt;gpg-key-id&gt;
+</literal>
+</programlisting>
+
+<para>You can also set that with</para>
+<programlisting>
+<literal>$ git config (--global) user.signingkey &lt;gpg-key-id&gt;
+</literal>
+</programlisting>
+
+<para>Now you can create a signed tag simply by replacing the
+<emphasis>-a</emphasis> with a <emphasis>-s</emphasis>.</para>
+<programlisting>
+<literal>$ git tag -s stable-1 1b2e1d63ff
+</literal>
+</programlisting>
+
+<para>If you don't have your GPG key in your config file, you can
+accomplish the same thing this way:</para>
+<programlisting>
+<literal>$ git tag -u &lt;gpg-key-id&gt; stable-1 1b2e1d63ff
+</literal>
+</programlisting>
+
+</sect3></sect2></sect1><sect1 id="Intermediate_Usag"><title>Intermediate
+Usage</title>
+<sect2 id="Ignoring_file"><title>Ignoring files</title>
+<para>A project will often generate files that you do 'not' want to
+track with git. This typically includes files generated by a build
+process or temporary backup files made by your editor. Of course,
+'not' tracking files with git is just a matter of 'not' calling
+"<literal>git-add</literal>" on them. But it quickly becomes
+annoying to have these untracked files lying around; e.g. they make
+"<literal>git add .</literal>" and "<literal>git commit
+-a</literal>" practically useless, and they keep showing up in the
+output of "<literal>git status</literal>".</para>
+<para>You can tell git to ignore certain files by creating a file
+called .gitignore in the top level of your working directory, with
+contents such as:</para>
+<programlisting>
+<literal># Lines starting with '#' are considered comments.
+# Ignore any file named foo.txt.
+foo.txt
+# Ignore (generated) html files,
+*.html
+# except foo.html which is maintained by hand.
+!foo.html
+# Ignore objects and archives.
+*.[oa]
+</literal>
+</programlisting>
+
+<para>See
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/gitignore.html">gitignore</ulink>
+for a detailed explanation of the syntax. You can also place
+.gitignore files in other directories in your working tree, and
+they will apply to those directories and their subdirectories. The
+<literal>.gitignore</literal> files can be added to your repository
+like any other files (just run <literal>git add
+.gitignore</literal> and <literal>git commit</literal>, as usual),
+which is convenient when the exclude patterns (such as patterns
+matching build output files) would also make sense for other users
+who clone your repository.</para>
+<para>If you wish the exclude patterns to affect only certain
+repositories (instead of every repository for a given project), you
+may instead put them in a file in your repository named
+.git/info/exclude, or in any file specified by the
+<literal>core.excludesfile</literal> configuration variable. Some
+git commands can also take exclude patterns directly on the command
+line. See
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/gitignore.html">gitignore</ulink>
+for the details.</para>
+</sect2><sect2 id="Rebasin"><title>Rebasing</title>
+<para>Suppose that you create a branch "mywork" on a
+remote-tracking branch "origin".</para>
+<programlisting>
+<literal>$ git checkout -b mywork origin
+</literal>
+</programlisting>
+
+<inlinemediaobject><imageobject>
+<imagedata fileref="images/rebase0.png"/>
+</imageobject></inlinemediaobject>
+
+
+<para>Now you do some work, creating two new commits.</para>
+<programlisting>
+<literal>$ vi file.txt
+$ git commit
+$ vi otherfile.txt
+$ git commit
+...
+</literal>
+</programlisting>
+
+<para>Meanwhile, someone else does some work creating two new
+commits on the origin branch too. This means both 'origin' and
+'mywork' has advanced, which means the work has diverged.</para>
+<inlinemediaobject><imageobject>
+<imagedata fileref="images/rebase1.png"/>
+</imageobject></inlinemediaobject>
+
+<para>At this point, you could use "pull" to merge your changes
+back in; the result would create a new merge commit, like
+this:</para>
+<inlinemediaobject><imageobject>
+<imagedata fileref="images/rebase2.png"/>
+</imageobject></inlinemediaobject>
+
+<para>However, if you prefer to keep the history in mywork a simple
+series of commits without any merges, you may instead choose to use
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html">git
+rebase</ulink>:</para>
+<programlisting>
+<literal>$ git checkout mywork
+$ git rebase origin
+</literal>
+</programlisting>
+
+<para>This will remove each of your commits from mywork,
+temporarily saving them as patches (in a directory named
+".git/rebase"), update mywork to point at the latest version of
+origin, then apply each of the saved patches to the new
+mywork.</para>
+<inlinemediaobject><imageobject>
+<imagedata fileref="images/rebase3.png"/>
+</imageobject></inlinemediaobject>
+
+<para>Once the ref ('mywork') is updated to point to the newly
+created commit objects, your older commits will be abandoned. They
+will likely be removed if you run a pruning garbage collection.
+(see
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-gc.html">git
+gc</ulink>)</para>
+<inlinemediaobject><imageobject>
+<imagedata fileref="images/rebase4.png"/>
+</imageobject></inlinemediaobject>
+
+<para>So now we can look at the difference in our history between
+running a merge and running a rebase:</para>
+<inlinemediaobject><imageobject>
+<imagedata fileref="images/rebase5.png"/>
+</imageobject></inlinemediaobject>
+
+<para>In the process of the rebase, it may discover conflicts. In
+that case it will stop and allow you to fix the conflicts; after
+fixing conflicts, use "git-add" to update the index with those
+contents, and then, instead of running git-commit, just run</para>
+<programlisting>
+<literal>$ git rebase --continue
+</literal>
+</programlisting>
+
+<para>and git will continue applying the rest of the
+patches.</para>
+<para>At any point you may use the <literal>--abort</literal>
+option to abort this process and return mywork to the state it had
+before you started the rebase:</para>
+<programlisting>
+<literal>$ git rebase --abort
+</literal>
+</programlisting>
+
+</sect2><sect2 id="Interactive_Rebasin"><title>Interactive
+Rebasing</title>
+<para>You can also rebase interactively. This is often used to
+re-write your own commit objects before pusing them somewhere. It
+is an easy way to split, merge or re-order commits before sharing
+them with others. You can also use it to clean up commits you've
+pulled from someone when applying them locally.</para>
+<para>If you have a number of commits that you would like to
+somehow modify during the rebase, you can invoke interactive mode
+by passing a '-i' or '--interactive' to the 'git rebase'
+command.</para>
+<programlisting>
+<literal>$ git rebase -i origin/master
+</literal>
+</programlisting>
+
+<para>This will invoke interactive rebase mode on all the commits
+you have made since the last time you have pushed (or merged from
+the origin repository).</para>
+<para>To see what commits those are beforehand, you can run log
+this way:</para>
+<programlisting>
+<literal>$ git log github/master..
+</literal>
+</programlisting>
+
+<para>Once you run the 'rebase -i' command, you will be thrown into
+your editor of choice with something that looks like this:</para>
+<programlisting>
+<literal>pick fc62e55 added file_size
+pick 9824bf4 fixed little thing
+pick 21d80a5 added number to log
+pick 76b9da6 added the apply command
+pick c264051 Revert "added file_size" - not implemented correctly
+
+# Rebase f408319..b04dc3d onto f408319
+#
+# Commands:
+#  p, pick = use commit
+#  e, edit = use commit, but stop for amending
+#  s, squash = use commit, but meld into previous commit
+#
+# If you remove a line here THAT COMMIT WILL BE LOST.
+# However, if you remove everything, the rebase will be aborted.
+#
+</literal>
+</programlisting>
+
+<para>This means that there are 5 commits since you last pushed and
+it gives you one line per commit with the following format:</para>
+<programlisting>
+<literal>(action) (partial-sha) (short commit message)
+</literal>
+</programlisting>
+
+<para>Now, you can change the action (which is by default 'pick')
+to either 'edit' or 'squash', or just leave it as 'pick'. You can
+also reorder the commits just by moving the lines around however
+you want. Then, when you exit the editor, git will try to apply the
+commits however they are now arranged and do the action
+specified.</para>
+<para>If 'pick' is specified, it will simply try to apply the patch
+and save the commit with the same message as before.</para>
+<para>If 'squash' is specified, it will combine that commit with
+the previous one to create a new commit. This will drop you into
+your editor again to merge the commit messages of the two commits
+it is now squashing together. So, if you exit the editor with
+this:</para>
+<programlisting>
+<literal>pick   fc62e55 added file_size
+squash 9824bf4 fixed little thing
+squash 21d80a5 added number to log
+squash 76b9da6 added the apply command
+squash c264051 Revert "added file_size" - not implemented correctly
+</literal>
+</programlisting>
+
+<para>Then you will have to create a single commit message from
+this:</para>
+<programlisting>
+<literal># This is a combination of 5 commits.
+# The first commit's message is:
+added file_size
+
+# This is the 2nd commit message:
+
+fixed little thing
+
+# This is the 3rd commit message:
+
+added number to log
+
+# This is the 4th commit message:
+
+added the apply command
+
+# This is the 5th commit message:
+
+Revert "added file_size" - not implemented correctly
+
+This reverts commit fc62e5543b195f18391886b9f663d5a7eca38e84.
+</literal>
+</programlisting>
+
+<para>Once you have edited that down into once commit message and
+exit the editor, the commit will be saved with your new
+message.</para>
+<para>If 'edit' is specified, it will do the same thing, but then
+pause before moving on to the next one and drop you into the
+command line so you can amend the commit, or change the commit
+contents somehow.</para>
+<para>If you wanted to split a commit, for instance, you would
+specify 'edit' for that commit:</para>
+<programlisting>
+<literal>pick   fc62e55 added file_size
+pick   9824bf4 fixed little thing
+edit   21d80a5 added number to log
+pick   76b9da6 added the apply command
+pick   c264051 Revert "added file_size" - not implemented correctly
+</literal>
+</programlisting>
+
+<para>And then when you get to the command line, you revert that
+commit and create two (or more) new ones. Lets say 21d80a5 modified
+two files, file1 and file2, and you wanted to split them into
+seperate commits. You could do this after the rebase dropped you to
+the command line :</para>
+<programlisting>
+<literal>$ git reset HEAD^
+$ git add file1
+$ git commit 'first part of split commit'
+$ git add file2
+$ git commit 'second part of split commit'
+$ git rebase --continue
+</literal>
+</programlisting>
+
+<para>And now instead of 5 commits, you would have 6.</para>
+<para>The last useful thing that interactive rebase can do is drop
+commits for you. If instead of choosing 'pick', 'squash' or 'edit'
+for the commit line, you simply remove the line, it will remove the
+commit from the history.</para>
+</sect2><sect2 id="Interactive_Addin"><title>Interactive
+Adding</title>
+<para>Interactive Adding is a really nice way of working with and
+visualizing the Git index. To start it up, simply type 'git add
+-i'. Git will show you all the modified files you have and their
+status.</para>
+<programlisting>
+<literal>$&gt;git add -i
+           staged     unstaged path
+  1:    unchanged        +4/-0 assets/stylesheets/style.css
+  2:    unchanged      +23/-11 layout/book_index_template.html
+  3:    unchanged        +7/-7 layout/chapter_template.html
+  4:    unchanged        +3/-3 script/pdf.rb
+  5:    unchanged      +121/-0 text/14_Interactive_Rebasing/0_ Interactive_Rebasing.markdown
+
+*** Commands ***
+  1: status   2: update   3: revert   4: add untracked
+  5: patch    6: diff     7: quit     8: help
+What now&gt; 
+</literal>
+</programlisting>
+
+<para>In this case, we can see that there are 5 modified files that
+have not been added to our index yet (unstaged), and even how many
+lines have been added to or removed from each. It then shows us an
+interactive menu of what we can do in this mode.</para>
+<para>If we want to stage the files, we can type '2' or 'u' for the
+update mode. Then I can specify which files I want to stage (add to
+the index) by typing in the numbers of the files (in this case,
+1-4)</para>
+<programlisting>
+<literal>What now&gt; 2
+           staged     unstaged path
+  1:    unchanged        +4/-0 assets/stylesheets/style.css
+  2:    unchanged      +23/-11 layout/book_index_template.html
+  3:    unchanged        +7/-7 layout/chapter_template.html
+  4:    unchanged        +3/-3 script/pdf.rb
+  5:    unchanged      +121/-0 text/14_Interactive_Rebasing/0_ Interactive_Rebasing.markdown
+Update&gt;&gt; 1-4
+           staged     unstaged path
+* 1:    unchanged        +4/-0 assets/stylesheets/style.css
+* 2:    unchanged      +23/-11 layout/book_index_template.html
+* 3:    unchanged        +7/-7 layout/chapter_template.html
+* 4:    unchanged        +3/-3 script/pdf.rb
+  5:    unchanged      +121/-0 text/14_Interactive_Rebasing/0_ Interactive_Rebasing.markdown
+Update&gt;&gt; 
+</literal>
+</programlisting>
+
+<para>If I hit enter, I will be taken back to the main menu where I
+can see that the file status has changed:</para>
+<programlisting>
+<literal>What now&gt; status
+           staged     unstaged path
+  1:        +4/-0      nothing assets/stylesheets/style.css
+  2:      +23/-11      nothing layout/book_index_template.html
+  3:        +7/-7      nothing layout/chapter_template.html
+  4:        +3/-3      nothing script/pdf.rb
+  5:    unchanged      +121/-0 text/14_Interactive_Rebasing/0_ Interactive_Rebasing.markdown
+</literal>
+</programlisting>
+
+<para>Now we can see the first four files are staged and the last
+one is still not. This is basically a compressed way to see the
+same information we see when we run 'git status' from the command
+line:</para>
+<programlisting>
+<literal>$ git status
+# On branch master
+# Changes to be committed:
+#   (use "git reset HEAD &lt;file&gt;..." to unstage)
+#
+#   modified:   assets/stylesheets/style.css
+#   modified:   layout/book_index_template.html
+#   modified:   layout/chapter_template.html
+#   modified:   script/pdf.rb
+#
+# Changed but not updated:
+#   (use "git add &lt;file&gt;..." to update what will be committed)
+#
+#   modified:   text/14_Interactive_Rebasing/0_ Interactive_Rebasing.markdown
+#
+</literal>
+</programlisting>
+
+<para>There are a number of useful things we can do, including
+unstaging files (3: revert), adding untracked files (4: add
+untracked), and viewing diffs (6: diff). Those are all pretty
+straightforward. However, there is one command that is pretty cool
+here, which is staging patches (5: patch).</para>
+<para>If you type '5' or 'p' in the menu, git will show you your
+diff patch by patch (or hunk by hunk) and ask if you want to stage
+each one. That way you can actually stage for a commit a part of a
+file edit. If you've edited a file and want to only commit part of
+it and not an unfinished part, or commit documentation or
+whitespace changes seperate from substantive changes, you can use
+'git add -i' to do so relatively easily.</para>
+<para>Here I've staged some changes to the book_index_template.html
+file, but not all of them:</para>
+<programlisting>
+<literal>        staged     unstaged path
+1:        +4/-0      nothing assets/stylesheets/style.css
+2:       +20/-7        +3/-4 layout/book_index_template.html
+3:        +7/-7      nothing layout/chapter_template.html
+4:        +3/-3      nothing script/pdf.rb
+5:    unchanged      +121/-0 text/14_Interactive_Rebasing/0_ Interactive_Rebasing.markdown
+6:    unchanged       +85/-0 text/15_Interactive_Adding/0_ Interactive_Adding.markdown
+</literal>
+</programlisting>
+
+<para>When you are done making changes to your index through 'git
+add -i', you simply quit (7: quit) and then run 'git commit' to
+commit the staged changes. Remember <emphasis>not</emphasis> to run
+'git commit -a', which will blow away all the careful changes
+you've just made and simply commit everything.</para>
+</sect2><sect2 id="Stashin"><title>Stashing</title>
+<para>While you are in the middle of working on something
+complicated, you find an unrelated but obvious and trivial bug. You
+would like to fix it before continuing. You can use
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-stash.html">git
+stash</ulink> to save the current state of your work, and after
+fixing the bug (or, optionally after doing so on a different branch
+and then coming back), unstash the work-in-progress changes.</para>
+<programlisting>
+<literal>$ git stash "work in progress for foo feature"
+</literal>
+</programlisting>
+
+<para>This command will save your changes away to the
+<literal>stash</literal>, and reset your working tree and the index
+to match the tip of your current branch. Then you can make your fix
+as usual.</para>
+<programlisting>
+<literal>... edit and test ...
+$ git commit -a -m "blorpl: typofix"
+</literal>
+</programlisting>
+
+<para>After that, you can go back to what you were working on with
+<literal>git stash apply</literal>:</para>
+<programlisting>
+<literal>$ git stash apply
+</literal>
+</programlisting>
+
+<sect3 id="Stash_Queu"><title>Stash Queue</title>
+<para>You can also use stashing to queue up stashed changes.If you
+run 'git stash list' you can see which stashes you have
+saved:</para>
+<programlisting>
+<literal>$&gt;git stash list
+stash@{0}: WIP on book: 51bea1d... fixed images
+stash@{1}: WIP on master: 9705ae6... changed the browse code to the official repo
+</literal>
+</programlisting>
+
+<para>Then you can apply them individually with 'git stash apply
+stash@{1}'. You can clear out the list with 'git stash
+clear'.</para>
+</sect3></sect2><sect2 id="Git_Treeishe"><title>Git
+Treeishes</title>
+<para>There are a number of ways to refer to a particular commit or
+tree other than spelling out the entire 40-character sha. In Git,
+these are referred to as a 'treeish'.</para>
+<sect3 id="Partial_Sh"><title>Partial Sha</title>
+<para>If your commit sha is
+'<literal>980e3ccdaac54a0d4de358f3fe5d718027d96aae</literal>', git
+will recognize any of the following identically:</para>
+<programlisting>
+<literal>980e3ccdaac54a0d4de358f3fe5d718027d96aae
+980e3ccdaac54a0d4
+980e3cc
+</literal>
+</programlisting>
+
+<para>As long as the partial sha is unique - it can't be confused
+with another (which is incredibly unlikely if you use at least 5
+characters), git will expand a partial sha for you.</para>
+</sect3><sect3 id="Branch,_Remote_or_Tag_Nam"><title>Branch, Remote
+or Tag Name</title>
+<para>You can always use a branch, remote or tag name instead of a
+sha, since they are simply pointers anyhow. If your master branch
+is on the 980e3 commit and you've pushed it to origin and have
+tagged it 'v1.0', then all of the following are equivalent:</para>
+<programlisting>
+<literal>980e3ccdaac54a0d4de358f3fe5d718027d96aae
+origin/master
+refs/remotes/origin/master
+master
+refs/heads/master
+v1.0
+refs/tags/v1.0
+</literal>
+</programlisting>
+
+<para>Which means the following will give you identical
+output:</para>
+<programlisting>
+<literal>$ git log master
+
+$ git log refs/tags/v1.0
+</literal>
+</programlisting>
+
+</sect3><sect3 id="Date_Spe"><title>Date Spec</title>
+<para>The Ref Log that git keeps will allow you to do some relative
+stuff locally, such as:</para>
+<programlisting>
+<literal>master@{yesterday}
+
+master@{1 month ago}
+</literal>
+</programlisting>
+
+<para>Which is shorthand for 'where the master branch head was
+yesterday', etc. Note that this format can result in different shas
+on different computers, even if the master branch is currently
+pointing to the same place.</para>
+</sect3><sect3 id="Ordinal_Spe"><title>Ordinal Spec</title>
+<para>This format will give you the Nth previous value of a
+particular reference. For example:</para>
+<programlisting>
+<literal>master@{5}
+</literal>
+</programlisting>
+
+<para>will give you the 5th prior value of the master head
+ref.</para>
+</sect3><sect3 id="Carrot_Paren"><title>Carrot Parent</title>
+<para>This will give you the Nth parent of a particular commit.
+This format is only useful on merge commits - commit objects that
+have more than one direct parent.</para>
+<programlisting>
+<literal>master^2
+</literal>
+</programlisting>
+
+</sect3><sect3 id="Tilde_Spe"><title>Tilde Spec</title>
+<para>The tilde spec will give you the Nth grandparent of a commit
+object. For example,</para>
+<programlisting>
+<literal>master~2
+</literal>
+</programlisting>
+
+<para>will give us the first parent of the first parent of the
+commit that master points to. It is equivalent to:</para>
+<programlisting>
+<literal>master^^
+</literal>
+</programlisting>
+
+<para>You can keep doing this, too. The following specs will point
+to the same commit:</para>
+<programlisting>
+<literal>master^^^^^^
+master~3^~2
+master~6
+</literal>
+</programlisting>
+
+</sect3><sect3 id="Tree_Pointe"><title>Tree Pointer</title>
+<para>This disambiguates a commit from the tree that it points to.
+If you want the sha that a commit points to, you can add the
+'^{tree}' spec to the end of it.</para>
+<programlisting>
+<literal>master^{tree}
+</literal>
+</programlisting>
+
+</sect3><sect3 id="Blob_Spe"><title>Blob Spec</title>
+<para>If you want the sha of a particular blob, you can add the
+blob path at the end of the treeish, like so:</para>
+<programlisting>
+<literal>master:/path/to/file
+</literal>
+</programlisting>
+
+</sect3><sect3 id="Rang"><title>Range</title>
+<para>Finally, you can specify a range of commits with the range
+spec. This will give you all the commits between 7b593b5 and 51bea1
+(where 51bea1 is most recent), excluding 7b593b5 but including
+51bea1:</para>
+<programlisting>
+<literal>7b593b5..51bea1
+</literal>
+</programlisting>
+
+<para>This will include every commit <emphasis>since</emphasis>
+7b593b:</para>
+<programlisting>
+<literal>7b593b.. 
+</literal>
+</programlisting>
+
+</sect3></sect2><sect2 id="Tracking_Branche"><title>Tracking
+Branches</title>
+<para>A 'tracking branch' in Git is a local branch that is
+connected to a remote branch. When you push and pull on that
+branch, it automatically pushes and pulls to the remote branch that
+it is connected with.</para>
+<para>Use this if you always pull from the same upstream branch
+into the new branch, and if you don't want to use "git pull  "
+explicitly.</para>
+<para>The 'git clone' command automatically sets up a 'master'
+branch that is a tracking branch for 'origin/master' - the master
+branch on the cloned repository.</para>
+<para>You can create a tracking branch manually by adding the
+'--track' option to the 'branch' command in Git.</para>
+<programlisting>
+<literal>git branch --track experimental origin/experimental
+</literal>
+</programlisting>
+
+<para>Then when you run:</para>
+<programlisting>
+<literal>$ git pull experimental
+</literal>
+</programlisting>
+
+<para>It will automatically fetch from 'origin' and merge
+'origin/experimental' into your local 'experimental' branch.</para>
+<para>Likewise, when you push to origin, it will push what your
+'experimental' points to to origins 'experimental', without having
+to specify it.</para>
+</sect2><sect2 id="Finding_with_Git_Gre"><title>Finding with Git
+Grep</title>
+<para>Finding files with words or phrases in Git is really easy
+with the
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-grep.html">git
+grep</ulink> command. It is possible to do this with the normal
+unix 'grep' command, but with 'git grep' you can also search
+through previous versions of the project without having to check
+them out.</para>
+<para>For example, if I wanted to see every place that used the
+'xmmap' call in my git.git repository, I could run this:</para>
+<programlisting>
+<literal>$ git grep xmmap
+config.c:               contents = xmmap(NULL, contents_sz, PROT_READ,
+diff.c:         s-&gt;data = xmmap(NULL, s-&gt;size, PROT_READ, MAP_PRIVATE, fd, 0);
+git-compat-util.h:extern void *xmmap(void *start, size_t length, int prot, int fla
+read-cache.c:   mmap = xmmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
+refs.c: log_mapped = xmmap(NULL, mapsz, PROT_READ, MAP_PRIVATE, logfd, 0);
+sha1_file.c:    map = xmmap(NULL, mapsz, PROT_READ, MAP_PRIVATE, fd, 0);
+sha1_file.c:    idx_map = xmmap(NULL, idx_size, PROT_READ, MAP_PRIVATE, fd, 0);
+sha1_file.c:                    win-&gt;base = xmmap(NULL, win-&gt;len,
+sha1_file.c:                    map = xmmap(NULL, *size, PROT_READ, MAP_PRIVATE, f
+sha1_file.c:            buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
+wrapper.c:void *xmmap(void *start, size_t length,
+</literal>
+</programlisting>
+
+<para>If I wanted to see the line number of each match as well, I
+can add the '-n' option:</para>
+<programlisting>
+<literal>$&gt;git grep -n xmmap
+config.c:1016:          contents = xmmap(NULL, contents_sz, PROT_READ,
+diff.c:1833:            s-&gt;data = xmmap(NULL, s-&gt;size, PROT_READ, MAP_PRIVATE, fd,
+git-compat-util.h:291:extern void *xmmap(void *start, size_t length, int prot, int
+read-cache.c:1178:      mmap = xmmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_
+refs.c:1345:    log_mapped = xmmap(NULL, mapsz, PROT_READ, MAP_PRIVATE, logfd, 0);
+sha1_file.c:377:        map = xmmap(NULL, mapsz, PROT_READ, MAP_PRIVATE, fd, 0);
+sha1_file.c:479:        idx_map = xmmap(NULL, idx_size, PROT_READ, MAP_PRIVATE, fd
+sha1_file.c:780:                        win-&gt;base = xmmap(NULL, win-&gt;len,
+sha1_file.c:1076:                       map = xmmap(NULL, *size, PROT_READ, MAP_PR
+sha1_file.c:2393:               buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd
+wrapper.c:89:void *xmmap(void *start, size_t length,
+</literal>
+</programlisting>
+
+<para>If we're only interested in the filename, we can pass the
+'--name-only' option:</para>
+<programlisting>
+<literal>$&gt;git grep --name-only xmmap
+config.c
+diff.c
+git-compat-util.h
+read-cache.c
+refs.c
+sha1_file.c
+wrapper.c
+</literal>
+</programlisting>
+
+<para>We could also see how many line matches we have in each file
+with the '-c' option:</para>
+<programlisting>
+<literal>$&gt;git grep -c xmmap
+config.c:1
+diff.c:1
+git-compat-util.h:1
+read-cache.c:1
+refs.c:1
+sha1_file.c:5
+wrapper.c:1
+</literal>
+</programlisting>
+
+<para>Now, if I wanted to see where that was used in a specific
+version of git, I could add the tag reference to the end, like
+this:</para>
+<programlisting>
+<literal>$ git grep xmmap v1.5.0
+v1.5.0:config.c:                contents = xmmap(NULL, st.st_size, PROT_READ,
+v1.5.0:diff.c:          s-&gt;data = xmmap(NULL, s-&gt;size, PROT_READ, MAP_PRIVATE, fd,
+v1.5.0:git-compat-util.h:static inline void *xmmap(void *start, size_t length,
+v1.5.0:read-cache.c:                    cache_mmap = xmmap(NULL, cache_mmap_size, 
+v1.5.0:refs.c:  log_mapped = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, logfd
+v1.5.0:sha1_file.c:     map = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 
+v1.5.0:sha1_file.c:     idx_map = xmmap(NULL, idx_size, PROT_READ, MAP_PRIVATE, fd
+v1.5.0:sha1_file.c:                     win-&gt;base = xmmap(NULL, win-&gt;len,
+v1.5.0:sha1_file.c:     map = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 
+v1.5.0:sha1_file.c:             buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd
+</literal>
+</programlisting>
+
+<para>We can see that there are some differences between the
+current lines and these lines in version 1.5.0, one of which is
+that xmmap is now used in wrapper.c where it was not back in
+v1.5.0.</para>
+<para>We can also combine search terms in grep. Say we wanted to
+search for where SORT_DIRENT is defined in our repository:</para>
+<programlisting>
+<literal>$ git grep -e '#define' --and -e SORT_DIRENT
+builtin-fsck.c:#define SORT_DIRENT 0
+builtin-fsck.c:#define SORT_DIRENT 1
+</literal>
+</programlisting>
+
+<para>We can also search for every file that has
+<emphasis>both</emphasis> search terms, but display each line that
+has <emphasis>either</emphasis> of the terms in those files:</para>
+<programlisting>
+<literal>$ git grep --all-match -e '#define' -e SORT_DIRENT
+builtin-fsck.c:#define REACHABLE 0x0001
+builtin-fsck.c:#define SEEN      0x0002
+builtin-fsck.c:#define ERROR_OBJECT 01
+builtin-fsck.c:#define ERROR_REACHABLE 02
+builtin-fsck.c:#define SORT_DIRENT 0
+builtin-fsck.c:#define DIRENT_SORT_HINT(de) 0
+builtin-fsck.c:#define SORT_DIRENT 1
+builtin-fsck.c:#define DIRENT_SORT_HINT(de) ((de)-&gt;d_ino)
+builtin-fsck.c:#define MAX_SHA1_ENTRIES (1024)
+builtin-fsck.c: if (SORT_DIRENT)
+</literal>
+</programlisting>
+
+<para>We can also search for lines that have one term and either of
+two other terms, for example, if we wanted to see where we defined
+constants that had either PATH or MAX in the name:</para>
+<programlisting>
+<literal>$ git grep -e '#define' --and \( -e PATH -e MAX \) 
+abspath.c:#define MAXDEPTH 5
+builtin-blame.c:#define MORE_THAN_ONE_PATH      (1u&lt;&lt;13)
+builtin-blame.c:#define MAXSG 16
+builtin-describe.c:#define MAX_TAGS     (FLAG_BITS - 1)
+builtin-fetch-pack.c:#define MAX_IN_VAIN 256
+builtin-fsck.c:#define MAX_SHA1_ENTRIES (1024)
+...
+</literal>
+</programlisting>
+
+</sect2><sect2 id="Undoing_in_Git_-_Reset,_Checkout_and_Rever"><title>Undoing
+in Git - Reset, Checkout and Revert</title>
+<para>Git provides multiple methods for fixing up mistakes as you
+are developing. Selecting an appropriate method depends on whether
+or not you have committed the mistake, and if you have committed
+the mistake, whether you have shared the erroneous commit with
+anyone else.</para>
+<sect3 id="Fixing_un-committed_mistake"><title>Fixing un-committed
+mistakes</title>
+<para>If you've messed up the working tree, but haven't yet
+committed your mistake, you can return the entire working tree to
+the last committed state with</para>
+<programlisting>
+<literal>$ git reset --hard HEAD
+</literal>
+</programlisting>
+
+<para>This will throw away any changes you may have added to the
+git index and as well as any outstanding changes you have in your
+working tree. In other words, it causes the results of "git diff"
+and "git diff --cached" to both be empty.</para>
+<para>If you just want to restore just one file, say your hello.rb,
+use
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-checkout.html">git
+checkout</ulink> instead</para>
+<programlisting>
+<literal>$ git checkout -- hello.rb
+$ git checkout HEAD hello.rb
+</literal>
+</programlisting>
+
+<para>The first command restores hello.rb to the version in the
+index, so that "git diff hello.rb" returns no differences. The
+second command will restore hello.rb to the version in the HEAD
+revision, so that both "git diff hello.rb" and "git diff --cached
+hello.rb" return no differences.</para>
+</sect3><sect3 id="Fixing_committed_mistake"><title>Fixing
+committed mistakes</title>
+<para>If you make a commit that you later wish you hadn't, there
+are two fundamentally different ways to fix the problem:</para>
+<orderedlist>
+<listitem>
+<para>You can create a new commit that undoes whatever was done by
+the old commit. This is the correct thing if your mistake has
+already been made public.</para>
+</listitem>
+<listitem>
+<para>You can go back and modify the old commit. You should never
+do this if you have already made the history public; git does not
+normally expect the "history" of a project to change, and cannot
+correctly perform repeated merges from a branch that has had its
+history changed.</para>
+</listitem>
+</orderedlist>
+
+<sect4 id="Fixing_a_mistake_with_a_new_commi"><title>Fixing a
+mistake with a new commit</title>
+<para>Creating a new commit that reverts an earlier change is very
+easy; just pass the
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-revert.html">git
+revert</ulink> command a reference to the bad commit; for example,
+to revert the most recent commit:</para>
+<programlisting>
+<literal>$ git revert HEAD
+</literal>
+</programlisting>
+
+<para>This will create a new commit which undoes the change in
+HEAD. You will be given a chance to edit the commit message for the
+new commit.</para>
+<para>You can also revert an earlier change, for example, the
+next-to-last:</para>
+<programlisting>
+<literal>$ git revert HEAD^
+</literal>
+</programlisting>
+
+<para>In this case git will attempt to undo the old change while
+leaving intact any changes made since then. If more recent changes
+overlap with the changes to be reverted, then you will be asked to
+fix conflicts manually, just as in the case of resolving a
+merge.</para>
+</sect4><sect4 id="Fixing_a_mistake_by_modifying_a_commi"><title>Fixing
+a mistake by modifying a commit</title>
+<para>If you have just committed something but realize you need to
+fix up that commit, recent versions of
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-commit.html">git
+commit</ulink> support an <emphasis>--amend</emphasis> flag which
+instructs git to replace the HEAD commit with a new one, based on
+the current contents of the index. This gives you an opportunity to
+add files that you forgot to add or correct typos in a commit
+message, prior to pushing the change out for the world to
+see.</para>
+<para>If you find a mistake in an older commit, but still one that
+you have not yet published to the world, you use
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html">git
+rebase</ulink> in interactive mode, with "git rebase -i" marking
+the change that requires correction with <emphasis>edit</emphasis>.
+This will allow you to amend the commit during the rebasing
+process.</para>
+</sect4></sect3></sect2><sect2 id="Maintaining_Gi"><title>Maintaining
+Git</title>
+<sect3 id="Ensuring_good_performanc"><title>Ensuring good
+performance</title>
+<para>On large repositories, git depends on compression to keep the
+history information from taking up too much space on disk or in
+memory.</para>
+<para>This compression is not performed automatically. Therefore
+you should occasionally run
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-gc.html">git
+gc</ulink>:</para>
+<programlisting>
+<literal>$ git gc
+</literal>
+</programlisting>
+
+<para>to recompress the archive. This can be very time-consuming,
+so you may prefer to run git-gc when you are not doing other
+work.</para>
+</sect3><sect3 id="Ensuring_reliabilit"><title>Ensuring
+reliability</title>
+<para>The
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-fsck.html">git
+fsck</ulink> command runs a number of self-consistency checks on
+the repository, and reports on any problems. This may take some
+time. The most common warning by far is about "dangling"
+objects:</para>
+<programlisting>
+<literal>$ git fsck
+dangling commit 7281251ddd2a61e38657c827739c57015671a6b3
+dangling commit 2706a059f258c6b245f298dc4ff2ccd30ec21a63
+dangling commit 13472b7c4b80851a1bc551779171dcb03655e9b5
+dangling blob 218761f9d90712d37a9c5e36f406f92202db07eb
+dangling commit bf093535a34a4d35731aa2bd90fe6b176302f14f
+dangling commit 8e4bec7f2ddaa268bef999853c25755452100f8e
+dangling tree d50bb86186bf27b681d25af89d3b5b68382e4085
+dangling tree b24c2473f1fd3d91352a624795be026d64c8841f
+...
+</literal>
+</programlisting>
+
+<para>Dangling objects are not a problem. At worst they may take up
+a little extra disk space. They can sometimes provide a last-resort
+method for recovering lost work.</para>
+</sect3></sect2><sect2 id="Setting_Up_A_Public_Repositor"><title>Setting
+Up A Public Repository</title>
+<para>Assume your personal repository is in the directory ~/proj.
+We first create a new clone of the repository and tell git-daemon
+that it is meant to be public:</para>
+<programlisting>
+<literal>$ git clone --bare ~/proj proj.git
+$ touch proj.git/git-daemon-export-ok
+</literal>
+</programlisting>
+
+<para>The resulting directory proj.git contains a "bare" git
+repository--it is just the contents of the ".git" directory,
+without any files checked out around it.</para>
+<para>Next, copy proj.git to the server where you plan to host the
+public repository. You can use scp, rsync, or whatever is most
+convenient.</para>
+<sect3 id="Exporting_a_git_repository_via_the_git_proto"><title>Exporting
+a git repository via the git protocol</title>
+<para>This is the preferred method.</para>
+<para>If someone else administers the server, they should tell you
+what directory to put the repository in, and what git:// URL it
+will appear at.</para>
+<para>Otherwise, all you need to do is start
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-daemon.html">git
+daemon</ulink>; it will listen on port 9418. By default, it will
+allow access to any directory that looks like a git directory and
+contains the magic file git-daemon-export-ok. Passing some
+directory paths as git-daemon arguments will further restrict the
+exports to those paths.</para>
+<para>You can also run git-daemon as an inetd service; see the
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-daemon.html">git
+daemon</ulink> man page for details. (See especially the examples
+section.)</para>
+</sect3><sect3 id="Exporting_a_git_repository_via_htt"><title>Exporting
+a git repository via http</title>
+<para>The git protocol gives better performance and reliability,
+but on a host with a web server set up, http exports may be simpler
+to set up.</para>
+<para>All you need to do is place the newly created bare git
+repository in a directory that is exported by the web server, and
+make some adjustments to give web clients some extra information
+they need:</para>
+<programlisting>
+<literal>$ mv proj.git /home/you/public_html/proj.git
+$ cd proj.git
+$ git --bare update-server-info
+$ chmod a+x hooks/post-update
+</literal>
+</programlisting>
+
+<para>(For an explanation of the last two lines, see
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-update-server-info.html">git
+update-server-info</ulink> and
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/githooks.html">githooks</ulink>.)</para>
+<para>Advertise the URL of proj.git. Anybody else should then be
+able to clone or pull from that URL, for example with a command
+line like:</para>
+<programlisting>
+<literal>$ git clone http://yourserver.com/~you/proj.git
+</literal>
+</programlisting>
+
+</sect3></sect2><sect2 id="Setting_Up_a_Private_Repositor"><title>Setting
+Up a Private Repository</title>
+<para>If you need to setup a private repository and want to do so
+locally, rather than using a hosted solution, you have a number of
+options.</para>
+<sect3 id="Repo_Access_over_SS"><title>Repo Access over SSH</title>
+<para>Generally, the easiest solution is to simply use Git over
+SSH. If users already have ssh accounts on a machine, you can put
+the git repository anywhere on the box that they have access to and
+let them access it over normal ssh logins. For example, say you
+have a repository you want to host. You can export it as a bare
+repo and then scp it onto your server like so:</para>
+<programlisting>
+<literal>$ git clone --bare /home/user/myrepo/.git /tmp/myrepo.git
+$ scp -r /tmp/myrepo.git myserver.com:/opt/git/myrepo.git
+</literal>
+</programlisting>
+
+<para>Then someone else with an ssh account on myserver.com can
+clone via:</para>
+<programlisting>
+<literal>$ git clone myserver.com:/opt/git/myrepo.git
+</literal>
+</programlisting>
+
+<para>Which will simply prompt them for thier ssh password or use
+thier public key, however they have ssh authentication
+setup.</para>
+</sect3><sect3 id="Multiple_User_Access_using_Gitosi"><title>Multiple
+User Access using Gitosis</title>
+<para>If you don't want to setup seperate accounts for every user,
+you can use a tool called Gitosis. In gitosis, there is an
+authorized_keys file that contains the public keys of everyone
+authorized to access the repository, and then everyone uses the
+'git' user to do pushes and pulls.</para>
+<para><ulink url="http://www.urbanpuddle.com/articles/2008/07/11/installing-git-on-a-server-ubuntu-or-debian">Installing
+and Setting up Gitosis</ulink></para>
+</sect3></sect2></sect1><sect1 id="Advanced_Gi"><title>Advanced
+Git</title>
+<sect2 id="Creating_New_Empty_Branche"><title>Creating New Empty
+Branches</title>
+<para>Ocasionally, you may want to keep branches in your repository
+that do not share an ancestor with your normal code. Some examples
+of this might be generated documentation or something along those
+lines. If you want to create a new branch head that does not use
+your current codebase as a parent, you can create an empty branch
+like this:</para>
+<programlisting>
+<literal>git symbolic-ref HEAD refs/heads/newbranch 
+rm .git/index 
+git clean -fdx 
+&lt;do work&gt; 
+git add your files 
+git commit -m 'Initial commit'
+</literal>
+</programlisting>
+
+</sect2><sect2 id="Modifying_your_Histor"><title>Modifying your
+History</title>
+<para>Interactive rebasing is a good way to modify individual
+commits.</para>
+<para><ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-filter-branch.html">git
+filter-branch</ulink> is a good way to edit commits en
+masse.</para>
+</sect2><sect2 id="Advanced_Branching_And_Mergin"><title>Advanced
+Branching And Merging</title>
+<sect3 id="Getting_conflict-resolution_help_during_a_me"><title>Getting
+conflict-resolution help during a merge</title>
+<para>All of the changes that git was able to merge automatically
+are already added to the index file, so
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-diff.html">git
+diff</ulink> shows only the conflicts. It uses an unusual
+syntax:</para>
+<programlisting>
+<literal>$ git diff
+diff --cc file.txt
+index 802992c,2b60207..0000000
+--- a/file.txt
++++ b/file.txt
+@@@ -1,1 -1,1 +1,5 @@@
+++&lt;&lt;&lt;&lt;&lt;&lt;&lt; HEAD:file.txt
+ +Hello world
+++=======
++ Goodbye
+++&gt;&gt;&gt;&gt;&gt;&gt;&gt; 77976da35a11db4580b80ae27e8d65caf5208086:file.txt
+</literal>
+</programlisting>
+
+<para>Recall that the commit which will be committed after we
+resolve this conflict will have two parents instead of the usual
+one: one parent will be HEAD, the tip of the current branch; the
+other will be the tip of the other branch, which is stored
+temporarily in MERGE_HEAD.</para>
+<para>During the merge, the index holds three versions of each
+file. Each of these three "file stages" represents a different
+version of the file:</para>
+<programlisting>
+<literal>$ git show :1:file.txt  # the file in a common ancestor of both branches
+$ git show :2:file.txt  # the version from HEAD.
+$ git show :3:file.txt  # the version from MERGE_HEAD.
+</literal>
+</programlisting>
+
+<para>When you ask
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-diff.html">git
+diff</ulink> to show the conflicts, it runs a three-way diff
+between the conflicted merge results in the work tree with stages 2
+and 3 to show only hunks whose contents come from both sides, mixed
+(in other words, when a hunk's merge results come only from stage
+2, that part is not conflicting and is not shown. Same for stage
+3).</para>
+<para>The diff above shows the differences between the working-tree
+version of file.txt and the stage 2 and stage 3 versions. So
+instead of preceding each line by a single "+" or "-", it now uses
+two columns: the first column is used for differences between the
+first parent and the working directory copy, and the second for
+differences between the second parent and the working directory
+copy. (See the "COMBINED DIFF FORMAT" section of
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-diff-files.html">git
+diff-files</ulink> for a details of the format.)</para>
+<para>After resolving the conflict in the obvious way (but before
+updating the index), the diff will look like:</para>
+<programlisting>
+<literal>$ git diff
+diff --cc file.txt
+index 802992c,2b60207..0000000
+--- a/file.txt
++++ b/file.txt
+@@@ -1,1 -1,1 +1,1 @@@
+- Hello world
+-Goodbye
+++Goodbye world
+</literal>
+</programlisting>
+
+<para>This shows that our resolved version deleted "Hello world"
+from the first parent, deleted "Goodbye" from the second parent,
+and added "Goodbye world", which was previously absent from
+both.</para>
+<para>Some special diff options allow diffing the working directory
+against any of these stages:</para>
+<programlisting>
+<literal>$ git diff -1 file.txt      # diff against stage 1
+$ git diff --base file.txt  # same as the above
+$ git diff -2 file.txt      # diff against stage 2
+$ git diff --ours file.txt  # same as the above
+$ git diff -3 file.txt      # diff against stage 3
+$ git diff --theirs file.txt    # same as the above.
+</literal>
+</programlisting>
+
+<para>The
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-log.html">git
+log</ulink> and
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/gitk.html">gitk</ulink>
+commands also provide special help for merges:</para>
+<programlisting>
+<literal>$ git log --merge
+$ gitk --merge
+</literal>
+</programlisting>
+
+<para>These will display all commits which exist only on HEAD or on
+MERGE_HEAD, and which touch an unmerged file.</para>
+<para>You may also use
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-mergetool.html">git
+mergetool</ulink>, which lets you merge the unmerged files using
+external tools such as emacs or kdiff3.</para>
+<para>Each time you resolve the conflicts in a file and update the
+index:</para>
+<programlisting>
+<literal>$ git add file.txt
+</literal>
+</programlisting>
+
+<para>the different stages of that file will be "collapsed", after
+which git-diff will (by default) no longer show diffs for that
+file.</para>
+</sect3><sect3 id="Multiway_Merg"><title>Multiway Merge</title>
+<para>You can merge several heads at one time by simply listing
+them on the same
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-merge.html">git
+merge</ulink> command. For instance,</para>
+<programlisting>
+<literal>$ git merge scott/master rick/master tom/master
+</literal>
+</programlisting>
+
+<para>is the equivalent of:</para>
+<programlisting>
+<literal>$ git merge scott/master
+$ git merge rick/master
+$ git merge tom/master
+</literal>
+</programlisting>
+
+</sect3><sect3 id="Subtre"><title>Subtree</title>
+<para>There are situations where you want to include contents in
+your project from an independently developed project. You can just
+pull from the other project as long as there are no conflicting
+paths.</para>
+<para>The problematic case is when there are conflicting files.
+Potential candidates are Makefiles and other standard filenames.
+You could merge these files but probably you do not want to. A
+better solution for this problem can be to merge the project as its
+own subdirectory. This is not supported by the recursive merge
+strategy, so just pulling won't work.</para>
+<para>What you want is the subtree merge strategy, which helps you
+in such a situation.</para>
+<para>In this example, let's say you have the repository at
+/path/to/B (but it can be an URL as well, if you want). You want to
+merge the master branch of that repository to the dir-B
+subdirectory in your current branch.</para>
+<para>Here is the command sequence you need:</para>
+<programlisting>
+<literal>$ git remote add -f Bproject /path/to/B (1)
+$ git merge -s ours --no-commit Bproject/master (2)
+$ git read-tree --prefix=dir-B/ -u Bproject/master (3)
+$ git commit -m "Merge B project as our subdirectory" (4)
+$ git pull -s subtree Bproject master (5)
+</literal>
+</programlisting>
+
+<para>The benefit of using subtree merge is that it requires less
+administrative burden from the users of your repository. It works
+with older (before Git v1.5.2) clients and you have the code right
+after clone.</para>
+<para>However if you use submodules then you can choose not to
+transfer the submodule objects. This may be a problem with the
+subtree merge.</para>
+<para>Also, in case you make changes to the other project, it is
+easier to submit changes if you just use submodules.</para>
+<para>(from
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/howto/using-merge-subtree.html">Using
+Subtree Merge</ulink>)</para>
+</sect3></sect2><sect2 id="Finding_Issues_-_Git_Bisec"><title>Finding
+Issues - Git Bisect</title>
+<para>Suppose version 2.6.18 of your project worked, but the
+version at "master" crashes. Sometimes the best way to find the
+cause of such a regression is to perform a brute-force search
+through the project's history to find the particular commit that
+caused the problem. The
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-bisect.html">git
+bisect</ulink> command can help you do this:</para>
+<programlisting>
+<literal>$ git bisect start
+$ git bisect good v2.6.18
+$ git bisect bad master
+Bisecting: 3537 revisions left to test after this
+[65934a9a028b88e83e2b0f8b36618fe503349f8e] BLOCK: Make USB storage depend on SCSI rather than selecting it [try #6]
+</literal>
+</programlisting>
+
+<para>If you run "git branch" at this point, you'll see that git
+has temporarily moved you to a new branch named "bisect". This
+branch points to a commit (with commit id 65934...) that is
+reachable from "master" but not from v2.6.18. Compile and test it,
+and see whether it crashes. Assume it does crash. Then:</para>
+<programlisting>
+<literal>$ git bisect bad
+Bisecting: 1769 revisions left to test after this
+[7eff82c8b1511017ae605f0c99ac275a7e21b867] i2c-core: Drop useless bitmaskings
+</literal>
+</programlisting>
+
+<para>checks out an older version. Continue like this, telling git
+at each stage whether the version it gives you is good or bad, and
+notice that the number of revisions left to test is cut
+approximately in half each time.</para>
+<para>After about 13 tests (in this case), it will output the
+commit id of the guilty commit. You can then examine the commit
+with
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-show.html">git
+show</ulink>, find out who wrote it, and mail them your bug report
+with the commit id. Finally, run</para>
+<programlisting>
+<literal>$ git bisect reset
+</literal>
+</programlisting>
+
+<para>to return you to the branch you were on before and delete the
+temporary "bisect" branch.</para>
+<para>Note that the version which git-bisect checks out for you at
+each point is just a suggestion, and you're free to try a different
+version if you think it would be a good idea. For example,
+occasionally you may land on a commit that broke something
+unrelated; run</para>
+<programlisting>
+<literal>$ git bisect visualize
+</literal>
+</programlisting>
+
+<para>which will run gitk and label the commit it chose with a
+marker that says "bisect". Choose a safe-looking commit nearby,
+note its commit id, and check it out with:</para>
+<programlisting>
+<literal>$ git reset --hard fb47ddb2db...
+</literal>
+</programlisting>
+
+<para>then test, run "bisect good" or "bisect bad" as appropriate,
+and continue.</para>
+</sect2><sect2 id="Finding_Issues_-_Git_Blam"><title>Finding Issues
+- Git Blame</title>
+<para>The
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-blame.html">git
+blame</ulink> command is really helpful for figuring out who
+changed which sections of a file. If you simple run 'git blame
+[filename]' you'll get an output of the entire file with the last
+commit sha, date and author for every line in the file.</para>
+<programlisting>
+<literal>$ git blame sha1_file.c
+...
+0fcfd160 (Linus Torvalds  2005-04-18 13:04:43 -0700    8)  */
+0fcfd160 (Linus Torvalds  2005-04-18 13:04:43 -0700    9) #include "cache.h"
+1f688557 (Junio C Hamano  2005-06-27 03:35:33 -0700   10) #include "delta.h"
+a733cb60 (Linus Torvalds  2005-06-28 14:21:02 -0700   11) #include "pack.h"
+8e440259 (Peter Eriksen   2006-04-02 14:44:09 +0200   12) #include "blob.h"
+8e440259 (Peter Eriksen   2006-04-02 14:44:09 +0200   13) #include "commit.h"
+8e440259 (Peter Eriksen   2006-04-02 14:44:09 +0200   14) #include "tag.h"
+8e440259 (Peter Eriksen   2006-04-02 14:44:09 +0200   15) #include "tree.h"
+f35a6d3b (Linus Torvalds  2007-04-09 21:20:29 -0700   16) #include "refs.h"
+70f5d5d3 (Nicolas Pitre   2008-02-28 00:25:19 -0500   17) #include "pack-revindex.h"628522ec (Junio C Hamano              2007-12-29 02:05:47 -0800   18) #include "sha1-lookup.h"
+...
+</literal>
+</programlisting>
+
+<para>This is often helpful if a file had a line reverted or a
+mistake that broke the build to help you see who changed that line
+last.</para>
+<para>You can also specify a start and end line for the
+blame:</para>
+<programlisting>
+<literal>$&gt;git blame -L 160,+10 sha1_file.c 
+ace1534d (Junio C Hamano 2005-05-07 00:38:04 -0700       160)}
+ace1534d (Junio C Hamano 2005-05-07 00:38:04 -0700       161)
+0fcfd160 (Linus Torvalds 2005-04-18 13:04:43 -0700       162)/*
+0fcfd160 (Linus Torvalds 2005-04-18 13:04:43 -0700       163) * NOTE! This returns a statically allocate
+790296fd (Jim Meyering   2008-01-03 15:18:07 +0100       164) * careful about using it. Do an "xstrdup()
+0fcfd160 (Linus Torvalds 2005-04-18 13:04:43 -0700       165) * filename.
+ace1534d (Junio C Hamano 2005-05-07 00:38:04 -0700       166) *
+ace1534d (Junio C Hamano 2005-05-07 00:38:04 -0700       167) * Also note that this returns the location
+ace1534d (Junio C Hamano 2005-05-07 00:38:04 -0700       168) * SHA1 file can happen from any alternate 
+d19938ab (Junio C Hamano 2005-05-09 17:57:56 -0700       169) * DB_ENVIRONMENT environment variable if i
+</literal>
+</programlisting>
+
+</sect2><sect2 id="Git_and_Emai"><title>Git and Email</title>
+<sect3 id="Submitting_patches_to_a_projec"><title>Submitting
+patches to a project</title>
+<para>If you just have a few changes, the simplest way to submit
+them may just be to send them as patches in email:</para>
+<para>First, use
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-format-patch.html">git
+format-patch</ulink>; for example:</para>
+<programlisting>
+<literal>$ git format-patch origin
+</literal>
+</programlisting>
+
+<para>will produce a numbered series of files in the current
+directory, one for each patch in the current branch but not in
+origin/HEAD.</para>
+<para>You can then import these into your mail client and send them
+by hand. However, if you have a lot to send at once, you may prefer
+to use the
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-send-email.html">git
+send-email</ulink> script to automate the process. Consult the
+mailing list for your project first to determine how they prefer
+such patches be handled.</para>
+</sect3><sect3 id="Importing_patches_to_a_projec"><title>Importing
+patches to a project</title>
+<para>Git also provides a tool called
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-am.html">git
+am</ulink> (am stands for "apply mailbox"), for importing such an
+emailed series of patches. Just save all of the patch-containing
+messages, in order, into a single mailbox file, say "patches.mbox",
+then run</para>
+<programlisting>
+<literal>$ git am -3 patches.mbox
+</literal>
+</programlisting>
+
+<para>Git will apply each patch in order; if any conflicts are
+found, it will stop, and you can manually fix the conflicts and
+resolve the merge. (The "-3" option tells git to perform a merge;
+if you would prefer it just to abort and leave your tree and index
+untouched, you may omit that option.)</para>
+<para>Once the index is updated with the results of the conflict
+resolution, instead of creating a new commit, just run</para>
+<programlisting>
+<literal>$ git am --resolved
+</literal>
+</programlisting>
+
+<para>and git will create the commit for you and continue applying
+the remaining patches from the mailbox.</para>
+<para>The final result will be a series of commits, one for each
+patch in the original mailbox, with authorship and commit log
+message each taken from the message containing each patch.</para>
+</sect3></sect2><sect2 id="Customizing_Gi"><title>Customizing
+Git</title>
+<para><ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-config.html">git
+config</ulink></para>
+<sect3 id="Changing_your_Edito"><title>Changing your Editor</title>
+<programlisting>
+<literal>$ git config --global core.editor emacs
+</literal>
+</programlisting>
+
+</sect3><sect3 id="Adding_Aliase"><title>Adding Aliases</title>
+<programlisting>
+<literal>$ git config --global alias.last 'cat-file commit HEAD'
+
+$ git last
+tree c85fbd1996b8e7e5eda1288b56042c0cdb91836b
+parent cdc9a0a28173b6ba4aca00eb34f5aabb39980735
+author Scott Chacon &lt;schacon@gmail.com&gt; 1220473867 -0700
+committer Scott Chacon &lt;schacon@gmail.com&gt; 1220473867 -0700
+
+fixed a weird formatting problem
+
+$ git cat-file commit HEAD
+tree c85fbd1996b8e7e5eda1288b56042c0cdb91836b
+parent cdc9a0a28173b6ba4aca00eb34f5aabb39980735
+author Scott Chacon &lt;schacon@gmail.com&gt; 1220473867 -0700
+committer Scott Chacon &lt;schacon@gmail.com&gt; 1220473867 -0700
+
+fixed a weird formatting problem
+</literal>
+</programlisting>
+
+</sect3><sect3 id="Adding_Colo"><title>Adding Color</title>
+<para>See all color.* options in the
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-config.html">git
+config</ulink> docs</para>
+<programlisting>
+<literal>$ git config color.branch auto
+$ git config color.diff auto
+$ git config color.interactive auto
+$ git config color.status auto
+</literal>
+</programlisting>
+
+<para>Or, you can set all of them on with the color.ui
+option:</para>
+<programlisting>
+<literal>$ git config color.ui true
+</literal>
+</programlisting>
+
+</sect3><sect3 id="Commit_Templat"><title>Commit Template</title>
+<programlisting>
+<literal>$ git config commit.template '/etc/git-commit-template'
+</literal>
+</programlisting>
+
+</sect3><sect3 id="Log_Forma"><title>Log Format</title>
+<programlisting>
+<literal>$ git config format.pretty oneline
+</literal>
+</programlisting>
+
+</sect3><sect3 id="Other_Config_Option"><title>Other Config
+Options</title>
+<para>There are also a number of interesting options for packing,
+gc-ing, merging, remotes, branches, http transport, diffs, paging,
+whitespace and more. If you want to tweak these, check out the
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-config.html">git
+config</ulink> docs.</para>
+</sect3></sect2><sect2 id="Git_Hook"><title>Git Hooks</title>
+<para>Hooks are little scripts you can place in $GIT_DIR/hooks
+directory to trigger action at certain points. When git-init is
+run, a handful example hooks are copied in the hooks directory of
+the new repository, but by default they are all disabled. To enable
+a hook, rename it by removing its .sample suffix.</para>
+<sect3 id="applypatch-ms"><title>applypatch-msg</title>
+<programlisting>
+<literal>GIT_DIR/hooks/applypatch-msg
+</literal>
+</programlisting>
+
+<para>This hook is invoked by git-am script. It takes a single
+parameter, the name of the file that holds the proposed commit log
+message. Exiting with non-zero status causes git-am to abort before
+applying the patch.</para>
+<para>The hook is allowed to edit the message file in place, and
+can be used to normalize the message into some project standard
+format (if the project has one). It can also be used to refuse the
+commit after inspecting the message file. The default
+applypatch-msg hook, when enabled, runs the commit-msg hook, if the
+latter is enabled.</para>
+</sect3><sect3 id="pre-applypatc"><title>pre-applypatch</title>
+<programlisting>
+<literal>GIT_DIR/hooks/pre-applypatch
+</literal>
+</programlisting>
+
+<para>This hook is invoked by git-am. It takes no parameter, and is
+invoked after the patch is applied, but before a commit is made. If
+it exits with non-zero status, then the working tree will not be
+committed after applying the patch.</para>
+<para>It can be used to inspect the current working tree and refuse
+to make a commit if it does not pass certain test. The default
+pre-applypatch hook, when enabled, runs the pre-commit hook, if the
+latter is enabled.</para>
+</sect3><sect3 id="post-applypatc"><title>post-applypatch</title>
+<programlisting>
+<literal>GIT_DIR/hooks/post-applypatch
+</literal>
+</programlisting>
+
+<para>This hook is invoked by 'git-am'. It takes no parameter, and
+is invoked after the patch is applied and a commit is made.</para>
+<para>This hook is meant primarily for notification, and cannot
+affect the outcome of 'git-am'.</para>
+</sect3><sect3 id="pre-commi"><title>pre-commit</title>
+<programlisting>
+<literal>GIT_DIR/hooks/pre-commit
+</literal>
+</programlisting>
+
+<para>This hook is invoked by 'git-commit', and can be bypassed
+with <literal>\--no-verify</literal> option. It takes no parameter,
+and is invoked before obtaining the proposed commit log message and
+making a commit. Exiting with non-zero status from this script
+causes the 'git-commit' to abort.</para>
+<para>The default 'pre-commit' hook, when enabled, catches
+introduction of lines with trailing whitespaces and aborts the
+commit when such a line is found.</para>
+<para>All the 'git-commit' hooks are invoked with the environment
+variable <literal>GIT_EDITOR=:</literal> if the command will not
+bring up an editor to modify the commit message.</para>
+<para>Here is an example of a Ruby script that runs RSpec tests
+before allowing a commit.</para>
+<programlisting>
+  
+html_path = "spec_results.html"  
+`spec -f h:#{html_path} -f p spec` # run the spec. send progress to screen. save html results to html_path  
+
+# find out how many errors were found  
+html = open(html_path).read  
+examples = html.match(/(\d+) examples/)[0].to_i rescue 0  
+failures = html.match(/(\d+) failures/)[0].to_i rescue 0  
+pending = html.match(/(\d+) pending/)[0].to_i rescue 0  
+
+if failures.zero?  
+  puts "0 failures! #{examples} run, #{pending} pending"  
+else  
+  puts "\aDID NOT COMMIT YOUR FILES!"  
+  puts "View spec results at #{File.expand_path(html_path)}"  
+  puts  
+  puts "#{failures} failures! #{examples} run, #{pending} pending"  
+  exit 1  
+end
+</programlisting>
+
+</sect3><sect3 id="prepare-commit-ms"><title>prepare-commit-msg</title>
+<programlisting>
+<literal>GIT_DIR/hooks/prepare-commit-msg
+</literal>
+</programlisting>
+
+<para>This hook is invoked by 'git-commit' right after preparing
+the default log message, and before the editor is started.</para>
+<para>It takes one to three parameters. The first is the name of
+the file that the commit log message. The second is the source of
+the commit message, and can be: <literal>message</literal> (if a
+<literal>-m</literal> or <literal>-F</literal> option was given);
+<literal>template</literal> (if a <literal>-t</literal> option was
+given or the configuration option
+<literal>commit.template</literal> is set);
+<literal>merge</literal> (if the commit is a merge or a
+<literal>.git/MERGE_MSG</literal> file exists);
+<literal>squash</literal> (if a <literal>.git/SQUASH_MSG</literal>
+file exists); or <literal>commit</literal>, followed by a commit
+SHA1 (if a <literal>-c</literal>, <literal>-C</literal> or
+<literal>\--amend</literal> option was given).</para>
+<para>If the exit status is non-zero, 'git-commit' will
+abort.</para>
+<para>The purpose of the hook is to edit the message file in place,
+and it is not suppressed by the <literal>\--no-verify</literal>
+option. A non-zero exit means a failure of the hook and aborts the
+commit. It should not be used as replacement for pre-commit
+hook.</para>
+<para>The sample <literal>prepare-commit-msg</literal> hook that
+comes with git comments out the <literal>Conflicts:</literal> part
+of a merge's commit message.</para>
+</sect3><sect3 id="commit-ms"><title>commit-msg</title>
+<programlisting>
+<literal>GIT_DIR/hooks/commit-msg
+</literal>
+</programlisting>
+
+<para>This hook is invoked by 'git-commit', and can be bypassed
+with <literal>\--no-verify</literal> option. It takes a single
+parameter, the name of the file that holds the proposed commit log
+message. Exiting with non-zero status causes the 'git-commit' to
+abort.</para>
+<para>The hook is allowed to edit the message file in place, and
+can be used to normalize the message into some project standard
+format (if the project has one). It can also be used to refuse the
+commit after inspecting the message file.</para>
+<para>The default 'commit-msg' hook, when enabled, detects
+duplicate "Signed-off-by" lines, and aborts the commit if one is
+found.</para>
+</sect3><sect3 id="post-commi"><title>post-commit</title>
+<programlisting>
+<literal>GIT_DIR/hooks/post-commit
+</literal>
+</programlisting>
+
+<para>This hook is invoked by 'git-commit'. It takes no parameter,
+and is invoked after a commit is made.</para>
+<para>This hook is meant primarily for notification, and cannot
+affect the outcome of 'git-commit'.</para>
+</sect3><sect3 id="pre-rebas"><title>pre-rebase</title>
+<programlisting>
+<literal>GIT_DIR/hooks/pre-rebase
+</literal>
+</programlisting>
+
+<para>This hook is called by 'git-rebase' and can be used to
+prevent a branch from getting rebased.</para>
+</sect3><sect3 id="post-checkou"><title>post-checkout</title>
+<programlisting>
+<literal>GIT_DIR/hooks/post-checkout
+</literal>
+</programlisting>
+
+<para>This hook is invoked when a 'git-checkout' is run after
+having updated the worktree. The hook is given three parameters:
+the ref of the previous HEAD, the ref of the new HEAD (which may or
+may not have changed), and a flag indicating whether the checkout
+was a branch checkout (changing branches, flag=1) or a file
+checkout (retrieving a file from the index, flag=0). This hook
+cannot affect the outcome of 'git-checkout'.</para>
+<para>This hook can be used to perform repository validity checks,
+auto-display differences from the previous HEAD if different, or
+set working dir metadata properties.</para>
+</sect3><sect3 id="post-merg"><title>post-merge</title>
+<programlisting>
+<literal>GIT_DIR/hooks/post-merge
+</literal>
+</programlisting>
+
+<para>This hook is invoked by 'git-merge', which happens when a
+'git-pull' is done on a local repository. The hook takes a single
+parameter, a status flag specifying whether or not the merge being
+done was a squash merge. This hook cannot affect the outcome of
+'git-merge' and is not executed, if the merge failed due to
+conflicts.</para>
+<para>This hook can be used in conjunction with a corresponding
+pre-commit hook to save and restore any form of metadata associated
+with the working tree (eg: permissions/ownership, ACLS, etc). See
+contrib/hooks/setgitperms.perl for an example of how to do
+this.</para>
+</sect3><sect3 id="pre-receiv"><title>pre-receive</title>
+<programlisting>
+<literal>GIT_DIR/hooks/pre-receive
+</literal>
+</programlisting>
+
+<para>This hook is invoked by 'git-receive-pack' on the remote
+repository, which happens when a 'git-push' is done on a local
+repository. Just before starting to update refs on the remote
+repository, the pre-receive hook is invoked. Its exit status
+determines the success or failure of the update.</para>
+<para>This hook executes once for the receive operation. It takes
+no arguments, but for each ref to be updated it receives on
+standard input a line of the format:</para>
+<para>&lt;old-value&gt; SP &lt;new-value&gt; SP &lt;ref-name&gt;
+LF</para>
+<para>where <literal>&lt;old-value&gt;</literal> is the old object
+name stored in the ref, <literal>&lt;new-value&gt;</literal> is the
+new object name to be stored in the ref and
+<literal>&lt;ref-name&gt;</literal> is the full name of the ref.
+When creating a new ref, <literal>&lt;old-value&gt;</literal> is 40
+<literal>0</literal>.</para>
+<para>If the hook exits with non-zero status, none of the refs will
+be updated. If the hook exits with zero, updating of individual
+refs can still be prevented by the &lt;&lt;update,'update'&gt;&gt;
+hook.</para>
+<para>Both standard output and standard error output are forwarded
+to 'git-send-pack' on the other end, so you can simply
+<literal>echo</literal> messages for the user.</para>
+<para>If you wrote it in Ruby, you might get the args this
+way:</para>
+<programlisting>
+rev_old, rev_new, ref = STDIN.read.split(" ")
+</programlisting>
+
+<para>Or in a bash script, something like this would work:</para>
+<programlisting>
+<literal>#!/bin/sh
+# &lt;oldrev&gt; &lt;newrev&gt; &lt;refname&gt;
+# update a blame tree
+while read oldrev newrev ref
+do
+    echo "STARTING [$oldrev $newrev $ref]"
+    for path in `git diff-tree -r $oldrev..$newrev | awk '{print $6}'`
+    do
+      echo "git update-ref refs/blametree/$ref/$path $newrev"
+      `git update-ref refs/blametree/$ref/$path $newrev`
+    done
+done
+</literal>
+</programlisting>
+
+</sect3><sect3 id="updat"><title>update</title>
+<programlisting>
+<literal>GIT_DIR/hooks/update
+</literal>
+</programlisting>
+
+<para>This hook is invoked by 'git-receive-pack' on the remote
+repository, which happens when a 'git-push' is done on a local
+repository. Just before updating the ref on the remote repository,
+the update hook is invoked. Its exit status determines the success
+or failure of the ref update.</para>
+<para>The hook executes once for each ref to be updated, and takes
+three parameters:</para>
+<itemizedlist>
+<listitem>the name of the ref being updated,</listitem>
+<listitem>the old object name stored in the ref,</listitem>
+<listitem>and the new objectname to be stored in the
+ref.</listitem>
+</itemizedlist>
+<para>A zero exit from the update hook allows the ref to be
+updated. Exiting with a non-zero status prevents 'git-receive-pack'
+from updating that ref.</para>
+<para>This hook can be used to prevent 'forced' update on certain
+refs by making sure that the object name is a commit object that is
+a descendant of the commit object named by the old object name.
+That is, to enforce a "fast forward only" policy.</para>
+<para>It could also be used to log the old..new status. However, it
+does not know the entire set of branches, so it would end up firing
+one e-mail per ref when used naively, though. The
+&lt;&lt;post-receive,'post-receive'&gt;&gt; hook is more suited to
+that.</para>
+<para>Another use suggested on the mailing list is to use this hook
+to implement access control which is finer grained than the one
+based on filesystem group.</para>
+<para>Both standard output and standard error output are forwarded
+to 'git-send-pack' on the other end, so you can simply
+<literal>echo</literal> messages for the user.</para>
+<para>The default 'update' hook, when enabled--and with
+<literal>hooks.allowunannotated</literal> config option turned
+on--prevents unannotated tags to be pushed.</para>
+</sect3><sect3 id="post-receiv"><title>post-receive</title>
+<programlisting>
+<literal>GIT_DIR/hooks/post-receive
+</literal>
+</programlisting>
+
+<para>This hook is invoked by 'git-receive-pack' on the remote
+repository, which happens when a 'git-push' is done on a local
+repository. It executes on the remote repository once after all the
+refs have been updated.</para>
+<para>This hook executes once for the receive operation. It takes
+no arguments, but gets the same information as the
+&lt;&lt;pre-receive,'pre-receive'&gt;&gt; hook does on its standard
+input.</para>
+<para>This hook does not affect the outcome of 'git-receive-pack',
+as it is called after the real work is done.</para>
+<para>This supersedes the &lt;&lt;post-update,'post-update'&gt;&gt;
+hook in that it gets both old and new values of all the refs in
+addition to their names.</para>
+<para>Both standard output and standard error output are forwarded
+to 'git-send-pack' on the other end, so you can simply
+<literal>echo</literal> messages for the user.</para>
+<para>The default 'post-receive' hook is empty, but there is a
+sample script <literal>post-receive-email</literal> provided in the
+<literal>contrib/hooks</literal> directory in git distribution,
+which implements sending commit emails.</para>
+</sect3><sect3 id="post-updat"><title>post-update</title>
+<programlisting>
+<literal>GIT_DIR/hooks/post-update
+</literal>
+</programlisting>
+
+<para>This hook is invoked by 'git-receive-pack' on the remote
+repository, which happens when a 'git-push' is done on a local
+repository. It executes on the remote repository once after all the
+refs have been updated.</para>
+<para>It takes a variable number of parameters, each of which is
+the name of ref that was actually updated.</para>
+<para>This hook is meant primarily for notification, and cannot
+affect the outcome of 'git-receive-pack'.</para>
+<para>The 'post-update' hook can tell what are the heads that were
+pushed, but it does not know what their original and updated values
+are, so it is a poor place to do log old..new. The
+&lt;&lt;post-receive,'post-receive'&gt;&gt; hook does get both
+original and updated values of the refs. You might consider it
+instead if you need them.</para>
+<para>When enabled, the default 'post-update' hook runs
+'git-update-server-info' to keep the information used by dumb
+transports (e.g., HTTP) up-to-date. If you are publishing a git
+repository that is accessible via HTTP, you should probably enable
+this hook.</para>
+<para>Both standard output and standard error output are forwarded
+to 'git-send-pack' on the other end, so you can simply
+<literal>echo</literal> messages for the user.</para>
+</sect3><sect3 id="pre-auto-g"><title>pre-auto-gc</title>
+<programlisting>
+<literal>GIT_DIR/hooks/pre-auto-gc
+</literal>
+</programlisting>
+
+<para>This hook is invoked by 'git-gc --auto'. It takes no
+parameter, and exiting with non-zero status from this script causes
+the 'git-gc --auto' to abort.</para>
+</sect3><sect3 id="Reference"><title>References</title>
+<para><ulink url="http://www.kernel.org/pub/software/scm/git/docs/githooks.html">Git
+Hooks</ulink> *
+http://probablycorey.wordpress.com/2008/03/07/git-hooks-make-me-giddy/</para>
+</sect3></sect2><sect2 id="Recovering_Corrupted_Object"><title>Recovering
+Corrupted Objects</title>
+<para><ulink url="http://programblings.com/2008/06/07/the-illustrated-guide-to-recovering-lost-commits-with-git">Recovering
+Lost Commits Blog Post</ulink></para>
+<para><ulink url="http://www.kernel.org/pub/software/scm/git/docs/howto/recover-corrupted-blob-object.txt">Recovering
+Corrupted Blobs by Linus</ulink></para>
+</sect2><sect2 id="Submodule"><title>Submodules</title>
+<para>Large projects are often composed of smaller, self-contained
+modules. For example, an embedded Linux distribution's source tree
+would include every piece of software in the distribution with some
+local modifications; a movie player might need to build against a
+specific, known-working version of a decompression library; several
+independent programs might all share the same build scripts.</para>
+<para>With centralized revision control systems this is often
+accomplished by including every module in one single repository.
+Developers can check out all modules or only the modules they need
+to work with. They can even modify files across several modules in
+a single commit while moving things around or updating APIs and
+translations.</para>
+<para>Git does not allow partial checkouts, so duplicating this
+approach in Git would force developers to keep a local copy of
+modules they are not interested in touching. Commits in an enormous
+checkout would be slower than you'd expect as Git would have to
+scan every directory for changes. If modules have a lot of local
+history, clones would take forever.</para>
+<para>On the plus side, distributed revision control systems can
+much better integrate with external sources. In a centralized
+model, a single arbitrary snapshot of the external project is
+exported from its own revision control and then imported into the
+local revision control on a vendor branch. All the history is
+hidden. With distributed revision control you can clone the entire
+external history and much more easily follow development and
+re-merge local changes.</para>
+<para>Git's submodule support allows a repository to contain, as a
+subdirectory, a checkout of an external project. Submodules
+maintain their own identity; the submodule support just stores the
+submodule repository location and commit ID, so other developers
+who clone the containing project ("superproject") can easily clone
+all the submodules at the same revision. Partial checkouts of the
+superproject are possible: you can tell Git to clone none, some or
+all of the submodules.</para>
+<para>The
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-submodule.html">git
+submodule</ulink> command is available since Git 1.5.3. Users with
+Git 1.5.2 can look up the submodule commits in the repository and
+manually check them out; earlier versions won't recognize the
+submodules at all.</para>
+<para>To see how submodule support works, create (for example) four
+example repositories that can be used later as a submodule:</para>
+<programlisting>
+<literal>$ mkdir ~/git
+$ cd ~/git
+$ for i in a b c d
+do
+    mkdir $i
+    cd $i
+    git init
+    echo "module $i" &gt; $i.txt
+    git add $i.txt
+    git commit -m "Initial commit, submodule $i"
+    cd ..
+done
+</literal>
+</programlisting>
+
+<para>Now create the superproject and add all the
+submodules:</para>
+<programlisting>
+<literal>$ mkdir super
+$ cd super
+$ git init
+$ for i in a b c d
+do
+    git submodule add ~/git/$i $i
+done
+</literal>
+</programlisting>
+
+<para>NOTE: Do not use local URLs here if you plan to publish your
+superproject!</para>
+<para>See what files <literal>git-submodule</literal>
+created:</para>
+<programlisting>
+<literal>$ ls -a
+.  ..  .git  .gitmodules  a  b  c  d
+</literal>
+</programlisting>
+
+<para>The <literal>git-submodule add</literal> command does a
+couple of things:</para>
+<itemizedlist>
+<listitem>It clones the submodule under the current directory and
+by default checks out the master branch.</listitem>
+<listitem>It adds the submodule's clone path to the
+<para><ulink url="http://www.kernel.org/pub/software/scm/git/docs/gitmodules.html">gitmodules</ulink></para>
+file and adds this file to the index, ready to be
+committed.</listitem>
+<listitem>It adds the submodule's current commit ID to the index,
+ready to be committed.</listitem>
+</itemizedlist>
+<para>Commit the superproject:</para>
+<programlisting>
+<literal>$ git commit -m "Add submodules a, b, c and d."
+</literal>
+</programlisting>
+
+<para>Now clone the superproject:</para>
+<programlisting>
+<literal>$ cd ..
+$ git clone super cloned
+$ cd cloned
+</literal>
+</programlisting>
+
+<para>The submodule directories are there, but they're
+empty:</para>
+<programlisting>
+<literal>$ ls -a a
+.  ..
+$ git submodule status
+-d266b9873ad50488163457f025db7cdd9683d88b a
+-e81d457da15309b4fef4249aba9b50187999670d b
+-c1536a972b9affea0f16e0680ba87332dc059146 c
+-d96249ff5d57de5de093e6baff9e0aafa5276a74 d
+</literal>
+</programlisting>
+
+<para>NOTE: The commit object names shown above would be different
+for you, but they should match the HEAD commit object names of your
+repositories. You can check it by running <literal>git ls-remote
+../git/a</literal>.</para>
+<para>Pulling down the submodules is a two-step process. First run
+<literal>git submodule init</literal> to add the submodule
+repository URLs to <literal>.git/config</literal>:</para>
+<programlisting>
+<literal>$ git submodule init
+</literal>
+</programlisting>
+
+<para>Now use <literal>git-submodule update</literal> to clone the
+repositories and check out the commits specified in the
+superproject:</para>
+<programlisting>
+<literal>$ git submodule update
+$ cd a
+$ ls -a
+.  ..  .git  a.txt
+</literal>
+</programlisting>
+
+<para>One major difference between <literal>git-submodule
+update</literal> and <literal>git-submodule add</literal> is that
+<literal>git-submodule update</literal> checks out a specific
+commit, rather than the tip of a branch. It's like checking out a
+tag: the head is detached, so you're not working on a
+branch.</para>
+<programlisting>
+<literal>$ git branch
+* (no branch)
+master
+</literal>
+</programlisting>
+
+<para>If you want to make a change within a submodule and you have
+a detached head, then you should create or checkout a branch, make
+your changes, publish the change within the submodule, and then
+update the superproject to reference the new commit:</para>
+<programlisting>
+<literal>$ git checkout master
+</literal>
+</programlisting>
+
+<para>or</para>
+<programlisting>
+<literal>$ git checkout -b fix-up
+</literal>
+</programlisting>
+
+<para>then</para>
+<programlisting>
+<literal>$ echo "adding a line again" &gt;&gt; a.txt
+$ git commit -a -m "Updated the submodule from within the superproject."
+$ git push
+$ cd ..
+$ git diff
+diff --git a/a b/a
+index d266b98..261dfac 160000
+--- a/a
++++ b/a
+@@ -1 +1 @@
+-Subproject commit d266b9873ad50488163457f025db7cdd9683d88b
++Subproject commit 261dfac35cb99d380eb966e102c1197139f7fa24
+$ git add a
+$ git commit -m "Updated submodule a."
+$ git push
+</literal>
+</programlisting>
+
+<para>You have to run <literal>git submodule update</literal> after
+<literal>git pull</literal> if you want to update submodules,
+too.</para>
+<sect3 id="Pitfalls_with_submodule"><title>Pitfalls with
+submodules</title>
+<para>Always publish the submodule change before publishing the
+change to the superproject that references it. If you forget to
+publish the submodule change, others won't be able to clone the
+repository:</para>
+<programlisting>
+<literal>$ cd ~/git/super/a
+$ echo i added another line to this file &gt;&gt; a.txt
+$ git commit -a -m "doing it wrong this time"
+$ cd ..
+$ git add a
+$ git commit -m "Updated submodule a again."
+$ git push
+$ cd ~/git/cloned
+$ git pull
+$ git submodule update
+error: pathspec '261dfac35cb99d380eb966e102c1197139f7fa24' did not match any file(s) known to git.
+Did you forget to 'git add'?
+Unable to checkout '261dfac35cb99d380eb966e102c1197139f7fa24' in submodule path 'a'
+</literal>
+</programlisting>
+
+<para>If you are staging an updated submodule for commit manually,
+be careful to not add a trailing slash when specifying the path.
+With the slash appended, Git will assume you are removing the
+submodule and checking that directory's contents into the
+containing repository.</para>
+<programlisting>
+<literal>$ cd ~/git/super/a
+$ echo i added another line to this file &gt;&gt; a.txt
+$ git commit -a -m "doing it wrong this time"
+$ cd ..
+$ git add a/
+$ git status
+# On branch master
+# Changes to be committed:
+#   (use "git reset HEAD &lt;file&gt;..." to unstage)
+#
+#       deleted:    a
+#       new file:   a/a.txt
+#
+# Modified submodules:
+#
+# * a aa5c351...0000000 (1):
+#   &lt; Initial commit, submodule a
+#
+</literal>
+</programlisting>
+
+<para>To fix the index after performing this operation, reset the
+changes and then add the submodule without the trailing
+slash.</para>
+<programlisting>
+<literal>$ git reset HEAD A
+$ git add a
+$ git status
+# On branch master
+# Changes to be committed:
+#   (use "git reset HEAD &lt;file&gt;..." to unstage)
+#
+#       modified:   a
+#
+# Modified submodules:
+#
+# * a aa5c351...8d3ba36 (1):
+#   &gt; doing it wrong this time
+#
+</literal>
+</programlisting>
+
+<para>You also should not rewind branches in a submodule beyond
+commits that were ever recorded in any superproject.</para>
+<para>It's not safe to run <literal>git submodule update</literal>
+if you've made and committed changes within a submodule without
+checking out a branch first. They will be silently
+overwritten:</para>
+<programlisting>
+<literal>$ cat a.txt
+module a
+$ echo line added from private2 &gt;&gt; a.txt
+$ git commit -a -m "line added inside private2"
+$ cd ..
+$ git submodule update
+Submodule path 'a': checked out 'd266b9873ad50488163457f025db7cdd9683d88b'
+$ cd a
+$ cat a.txt
+module a
+</literal>
+</programlisting>
+
+<para>NOTE: The changes are still visible in the submodule's
+reflog.</para>
+<para>This is not the case if you did not commit your
+changes.</para>
+</sect3></sect2></sect1><sect1 id="Working_with_Gi"><title>Working
+with Git</title>
+<sect2 id="Git_on_Window"><title>Git on Windows</title>
+<para>(mSysGit)</para>
+</sect2><sect2 id="Deploying_with_Gi"><title>Deploying with
+Git</title>
+<sect3 id="Capistrano_and_Gi"><title>Capistrano and Git</title>
+<para><ulink url="http://github.com/guides/deploying-with-capistrano">GitHub
+Guide on Deploying with Cap</ulink></para>
+<para><ulink url="http://www.vimeo.com/369095">Git and Capistrano
+Screencast</ulink></para>
+</sect3></sect2><sect2 id="Subversion_Integratio"><title>Subversion
+Integration</title>
+</sect2><sect2 id="SCM_Migratio"><title>SCM Migration</title>
+<para>So you've made the decision to move away from your existing
+system and convert your whole project to Git. How can you do that
+easily?</para>
+<sect3 id="Importing_Subversio"><title>Importing Subversion</title>
+<para>Git comes with a script called git-svn that has a clone
+command that will import a subversion repository into a new git
+repository. There is also a free tool on the GitHub service that
+will do this for you.</para>
+<programlisting>
+<literal>$ git-svn clone http://my-project.googlecode.com/svn/trunk new-project
+</literal>
+</programlisting>
+
+<para>This will give you a new Git repository with all the history
+of the original Subversion repo. This takes a pretty good amount of
+time, generally, since it starts with version 1 and checks out and
+commits locally every single revision one by one.</para>
+</sect3><sect3 id="Importing_Perforc"><title>Importing
+Perforce</title>
+<para>In contrib/fast-import you will find the git-p4 script, which
+is a Python script that will import a Perforce repository for
+you.</para>
+<programlisting>
+<literal>$ ~/git.git/contrib/fast-import/git-p4 clone //depot/project/main@all myproject
+</literal>
+</programlisting>
+
+</sect3><sect3 id="Importing_Other"><title>Importing Others</title>
+<para>These are other SCMs that listed high on the Git Survey,
+should find import docs for them. !!TODO!!</para>
+<itemizedlist>
+<listitem>CVS</listitem>
+<listitem>
+<para>Mercurial (hg)</para>
+</listitem>
+<listitem>
+<para>Bazaar-NG</para>
+</listitem>
+<listitem>Darcs</listitem>
+<listitem>ClearCase</listitem>
+</itemizedlist>
+</sect3></sect2><sect2 id="Graphical_Gi"><title>Graphical
+Git</title>
+<para>Git has a couple of fairly popular Graphial User Interfaces
+that can read and/or maniplulate Git repositories.</para>
+<sect3 id="Bundled_GUI"><title>Bundled GUIs</title>
+<para>Git comes with two major GUI programs written in Tcl/Tk. Gitk
+is a repository browser and commit history visualization
+tool.</para>
+<para><ulink url="http://www.kernel.org/pub/software/scm/git/docs/gitk.html">gitk</ulink></para>
+<para><ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-gui.html">git
+gui</ulink> is a tool that helps you visualize the index
+operations, like add, remove and commit. It won't do everything you
+can do on the command line, but for many of the basic operations,
+it's pretty good.</para>
+<para><ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-gui.html">git
+gui</ulink></para>
+</sect3><sect3 id="Third_Party_Project"><title>Third Party
+Projects</title>
+<para>For Mac users, there are
+<ulink url="http://gitx.frim.nl/">GitX</ulink> and
+<ulink url="http://github.com/Caged/gitnub/wikis">GitNub</ulink></para>
+<para>For Linux or other Qt users, there is
+<ulink url="http://digilander.libero.it/mcostalba/">QGit</ulink></para>
+</sect3></sect2><sect2 id="Hosted_Gi"><title>Hosted Git</title>
+<para>github</para>
+<para>repoorcz</para>
+</sect2><sect2 id="Alternative_Use"><title>Alternative Uses</title>
+<para>ContentDistribution</para>
+<para>TicGit</para>
+</sect2><sect2 id="Scripting_and_Gi"><title>Scripting and
+Git</title>
+<sect3 id="Ruby_and_Gi"><title>Ruby and Git</title>
+<para>grit</para>
+<para>jgit + jruby</para>
+</sect3><sect3 id="PHP_and_Gi"><title>PHP and Git</title>
+</sect3><sect3 id="Python_and_Gi"><title>Python and Git</title>
+<para>pygit</para>
+</sect3><sect3 id="Perl_and_Gi"><title>Perl and Git</title>
+<para>perlgit</para>
+</sect3></sect2><sect2 id="Git_and_Editor"><title>Git and
+Editors</title>
+<para>textmate</para>
+<para>eclipse</para>
+<para>netbeans</para>
+</sect2></sect1><sect1 id="Internals_and_Plumbin"><title>Internals
+and Plumbing</title>
+<sect2 id="How_Git_Stores_Object"><title>How Git Stores
+Objects</title>
+<para>This chapter goes into detail about how Git physically stores
+objects.</para>
+<para>All objects are stored as compressed contents by their sha
+values. They contain the object type, size and contents in a
+gzipped format.</para>
+<para>There are two formats that Git keeps objects in - loose
+objects and packed objects.</para>
+<sect3 id="Loose_Object"><title>Loose Objects</title>
+<para>Loose objects are the simpler format. It is simply the
+compressed data stored in a single file on disk. Every object
+written to a seperate file.</para>
+<para>If the sha of your object is
+<literal>ab04d884140f7b0cf8bbf86d6883869f16a46f65</literal>, then
+the file will be stored in the following path:</para>
+<programlisting>
+<literal>GIT_DIR/objects/ab/04d884140f7b0cf8bbf86d6883869f16a46f65
+</literal>
+</programlisting>
+
+<para>It pulls the first two characters off and uses that as the
+subdirectory, so that there are never too many objects in one
+directory. The actual file name is the remaining 38
+characters.</para>
+<para>The easiest way to describe exactly how the object data is
+stored is this Ruby implementation of object storage:</para>
+<programlisting>
+def put_raw_object(content, type)
+  size = content.length.to_s
+
+  header = "#{type} #{size}\0" # type(space)size(null byte)
+  store = header + content
+
+  sha1 = Digest::SHA1.hexdigest(store)
+  path = @git_dir + '/' + sha1[0...2] + '/' + sha1[2..40]
+
+if !File.exists?(path)
+    content = Zlib::Deflate.deflate(store)
+
+FileUtils.mkdir_p(@directory+'/'+sha1[0...2])
+File.open(path, 'w') do |f|
+      f.write content
+end
+end
+return sha1
+end
+</programlisting>
+
+</sect3><sect3 id="Packed_Object"><title>Packed Objects</title>
+<para>The other format for object storage is the packfile. Since
+Git stores each version of each file as a seperate object, it can
+get pretty inefficient. Imagine having a file several thousand
+lines long and changing a single line. Git will store the second
+file in it's entirety, which is a great big waste of space.</para>
+<para>In order to save that space, Git utilizes the packfile. This
+is a format where Git will only save the part that has changed in
+the second file, with a pointer to the file it is similar
+to.</para>
+<para>When objects are written to disk, it is often in the loose
+format, since that format is less expensive to access. However,
+eventually you'll want to save the space by packing up the objects
+- this is done with the
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-gc.html">git
+gc</ulink> command. It will use a rather complicated heuristic to
+determine which files are likely most similar and base the deltas
+off that analysis. There can be multiple packfiles, they can be
+repacked if neccesary
+(<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-repack.html">git
+repack</ulink>) or unpacked back into loose files
+(<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-unpack-objects.html">git
+unpack-objects</ulink>) relatively easily.</para>
+<para>Git will also write out an index file for each packfile that
+is much smaller and contains offsets into the packfile to more
+quickly find specific objects by sha.</para>
+<para>The actual details of the packfile implementation are found
+in the Packfile chapter a little later on.</para>
+</sect3></sect2><sect2 id="Browsing_Git_Object"><title>Browsing Git
+Objects</title>
+<para>We can ask git about particular objects with the cat-file
+command. Note that you can shorten the shas to only a few
+characters to save yourself typing all 40 hex digits:</para>
+<programlisting>
+<literal>$ git-cat-file -t 54196cc2
+commit
+$ git-cat-file commit 54196cc2
+tree 92b8b694ffb1675e5975148e1121810081dbdffe
+author J. Bruce Fields &lt;bfields@puzzle.fieldses.org&gt; 1143414668 -0500
+committer J. Bruce Fields &lt;bfields@puzzle.fieldses.org&gt; 1143414668 -0500
+
+initial commit
+</literal>
+</programlisting>
+
+<para>A tree can refer to one or more "blob" objects, each
+corresponding to a file. In addition, a tree can also refer to
+other tree objects, thus creating a directory hierarchy. You can
+examine the contents of any tree using ls-tree (remember that a
+long enough initial portion of the SHA1 will also work):</para>
+<programlisting>
+<literal>$ git ls-tree 92b8b694
+100644 blob 3b18e512dba79e4c8300dd08aeb37f8e728b8dad    file.txt
+</literal>
+</programlisting>
+
+<para>Thus we see that this tree has one file in it. The SHA1 hash
+is a reference to that file's data:</para>
+<programlisting>
+<literal>$ git cat-file -t 3b18e512
+blob
+</literal>
+</programlisting>
+
+<para>A "blob" is just file data, which we can also examine with
+cat-file:</para>
+<programlisting>
+<literal>$ git cat-file blob 3b18e512
+hello world
+</literal>
+</programlisting>
+
+<para>Note that this is the old file data; so the object that git
+named in its response to the initial tree was a tree with a
+snapshot of the directory state that was recorded by the first
+commit.</para>
+<para>All of these objects are stored under their SHA1 names inside
+the git directory:</para>
+<programlisting>
+<literal>$ find .git/objects/
+.git/objects/
+.git/objects/pack
+.git/objects/info
+.git/objects/3b
+.git/objects/3b/18e512dba79e4c8300dd08aeb37f8e728b8dad
+.git/objects/92
+.git/objects/92/b8b694ffb1675e5975148e1121810081dbdffe
+.git/objects/54
+.git/objects/54/196cc2703dc165cbd373a65a4dcf22d50ae7f7
+.git/objects/a0
+.git/objects/a0/423896973644771497bdc03eb99d5281615b51
+.git/objects/d0
+.git/objects/d0/492b368b66bdabf2ac1fd8c92b39d3db916e59
+.git/objects/c4
+.git/objects/c4/d59f390b9cfd4318117afde11d601c1085f241
+</literal>
+</programlisting>
+
+<para>and the contents of these files is just the compressed data
+plus a header identifying their length and their type. The type is
+either a blob, a tree, a commit, or a tag.</para>
+<para>The simplest commit to find is the HEAD commit, which we can
+find from .git/HEAD:</para>
+<programlisting>
+<literal>$ cat .git/HEAD
+ref: refs/heads/master
+</literal>
+</programlisting>
+
+<para>As you can see, this tells us which branch we're currently
+on, and it tells us this by naming a file under the .git directory,
+which itself contains a SHA1 name referring to a commit object,
+which we can examine with cat-file:</para>
+<programlisting>
+<literal>$ cat .git/refs/heads/master
+c4d59f390b9cfd4318117afde11d601c1085f241
+$ git cat-file -t c4d59f39
+commit
+$ git cat-file commit c4d59f39
+tree d0492b368b66bdabf2ac1fd8c92b39d3db916e59
+parent 54196cc2703dc165cbd373a65a4dcf22d50ae7f7
+author J. Bruce Fields &lt;bfields@puzzle.fieldses.org&gt; 1143418702 -0500
+committer J. Bruce Fields &lt;bfields@puzzle.fieldses.org&gt; 1143418702 -0500
+
+add emphasis
+</literal>
+</programlisting>
+
+<para>The "tree" object here refers to the new state of the
+tree:</para>
+<programlisting>
+<literal>$ git ls-tree d0492b36
+100644 blob a0423896973644771497bdc03eb99d5281615b51    file.txt
+$ git cat-file blob a0423896
+hello world!
+</literal>
+</programlisting>
+
+<para>and the "parent" object refers to the previous commit:</para>
+<programlisting>
+<literal>$ git-cat-file commit 54196cc2
+tree 92b8b694ffb1675e5975148e1121810081dbdffe
+author J. Bruce Fields &lt;bfields@puzzle.fieldses.org&gt; 1143414668 -0500
+committer J. Bruce Fields &lt;bfields@puzzle.fieldses.org&gt; 1143414668 -0500
+</literal>
+</programlisting>
+
+</sect2><sect2 id="Git_Reference"><title>Git References</title>
+<para>Branches, remote-tracking branches, and tags are all
+references to commits. All references are named with a
+slash-separated path name starting with "refs"; the names we've
+been using so far are actually shorthand:</para>
+<programlisting>
+<literal>- The branch "test" is short for "refs/heads/test".
+- The tag "v2.6.18" is short for "refs/tags/v2.6.18".
+- "origin/master" is short for "refs/remotes/origin/master".
+</literal>
+</programlisting>
+
+<para>The full name is occasionally useful if, for example, there
+ever exists a tag and a branch with the same name.</para>
+<para>(Newly created refs are actually stored in the .git/refs
+directory, under the path given by their name. However, for
+efficiency reasons they may also be packed together in a single
+file; see
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-pack-refs.html">git
+pack-refs</ulink>).</para>
+<para>As another useful shortcut, the "HEAD" of a repository can be
+referred to just using the name of that repository. So, for
+example, "origin" is usually a shortcut for the HEAD branch in the
+repository "origin".</para>
+<para>For the complete list of paths which git checks for
+references, and the order it uses to decide which to choose when
+there are multiple references with the same shorthand name, see the
+"SPECIFYING REVISIONS" section of
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-rev-parse.html">git
+rev-parse</ulink>.</para>
+<sect3 id="Showing_commits_unique_to_a_given_branc"><title>Showing
+commits unique to a given branch</title>
+<para>Suppose you would like to see all the commits reachable from
+the branch head named "master" but not from any other head in your
+repository.</para>
+<para>We can list all the heads in this repository with
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-show-ref.html">git
+show-ref</ulink>:</para>
+<programlisting>
+<literal>$ git show-ref --heads
+bf62196b5e363d73353a9dcf094c59595f3153b7 refs/heads/core-tutorial
+db768d5504c1bb46f63ee9d6e1772bd047e05bf9 refs/heads/maint
+a07157ac624b2524a059a3414e99f6f44bebc1e7 refs/heads/master
+24dbc180ea14dc1aebe09f14c8ecf32010690627 refs/heads/tutorial-2
+1e87486ae06626c2f31eaa63d26fc0fd646c8af2 refs/heads/tutorial-fixes
+</literal>
+</programlisting>
+
+<para>We can get just the branch-head names, and remove "master",
+with the help of the standard utilities cut and grep:</para>
+<programlisting>
+<literal>$ git show-ref --heads | cut -d' ' -f2 | grep -v '^refs/heads/master'
+refs/heads/core-tutorial
+refs/heads/maint
+refs/heads/tutorial-2
+refs/heads/tutorial-fixes
+</literal>
+</programlisting>
+
+<para>And then we can ask to see all the commits reachable from
+master but not from these other heads:</para>
+<programlisting>
+<literal>$ gitk master --not $( git show-ref --heads | cut -d' ' -f2 |
+                grep -v '^refs/heads/master' )
+</literal>
+</programlisting>
+
+<para>Obviously, endless variations are possible; for example, to
+see all commits reachable from some head but not from any tag in
+the repository:</para>
+<programlisting>
+<literal>$ gitk $( git show-ref --heads ) --not  $( git show-ref --tags )
+</literal>
+</programlisting>
+
+<para>(See
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-rev-parse.html">git
+rev-parse</ulink> for explanations of commit-selecting syntax such
+as <literal>--not</literal>.)</para>
+<para>(!!update-ref!!)</para>
+</sect3></sect2><sect2 id="The_Git_Inde"><title>The Git
+Index</title>
+<para>The index is a binary file (generally kept in .git/index)
+containing a sorted list of path names, each with permissions and
+the SHA1 of a blob object;
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-ls-files.html">git
+ls-files</ulink> can show you the contents of the index:</para>
+<programlisting>
+<literal>$ git ls-files --stage
+100644 63c918c667fa005ff12ad89437f2fdc80926e21c 0   .gitignore
+100644 5529b198e8d14decbe4ad99db3f7fb632de0439d 0   .mailmap
+100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0   COPYING
+100644 a37b2152bd26be2c2289e1f57a292534a51a93c7 0   Documentation/.gitignore
+100644 fbefe9a45b00a54b58d94d06eca48b03d40a50e0 0   Documentation/Makefile
+...
+100644 2511aef8d89ab52be5ec6a5e46236b4b6bcd07ea 0   xdiff/xtypes.h
+100644 2ade97b2574a9f77e7ae4002a4e07a6a38e46d07 0   xdiff/xutils.c
+100644 d5de8292e05e7c36c4b68857c1cf9855e3d2f70a 0   xdiff/xutils.h
+</literal>
+</programlisting>
+
+<para>Note that in older documentation you may see the index called
+the "current directory cache" or just the "cache". It has three
+important properties:</para>
+<orderedlist>
+<listitem>
+<para>The index contains all the information necessary to generate
+a single (uniquely determined) tree object.</para>
+<para>For example, running
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-commit.html">git
+commit</ulink> generates this tree object from the index, stores it
+in the object database, and uses it as the tree object associated
+with the new commit.</para>
+</listitem>
+<listitem>
+<para>The index enables fast comparisons between the tree object it
+defines and the working tree.</para>
+<para>It does this by storing some additional data for each entry
+(such as the last modified time). This data is not displayed above,
+and is not stored in the created tree object, but it can be used to
+determine quickly which files in the working directory differ from
+what was stored in the index, and thus save git from having to read
+all of the data from such files to look for changes.</para>
+</listitem>
+<listitem>
+<para>It can efficiently represent information about merge
+conflicts between different tree objects, allowing each pathname to
+be associated with sufficient information about the trees involved
+that you can create a three-way merge between them.</para>
+<para>During a merge, the index can store multiple versions of a
+single file (called "stages"). The third column in the
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-ls-files.html">git
+ls-files</ulink> output above is the stage number, and will take on
+values other than 0 for files with merge conflicts.</para>
+</listitem>
+</orderedlist>
+
+<para>The index is thus a sort of temporary staging area, which is
+filled with a tree which you are in the process of working
+on.</para>
+</sect2><sect2 id="The_Packfil"><title>The Packfile</title>
+<para>This chapter explains in detail, down to the bits, how the
+packfile and pack index files are formatted.</para>
+<sect3 id="The_Packfile_Inde"><title>The Packfile Index</title>
+<para>First off, we have the packfile index, which is basically
+just a series of bookmarks into a packfile.</para>
+<para>There are two versions of the packfile index - version one,
+which is the default in versions of Git earlier than 1.6, and
+version two, which is the default from 1.6 forward, but which can
+be read by Git versions going back to 1.5.2, and has been further
+backported to 1.4.4.5 if you are still on the 1.4 series.</para>
+<para>Version 2 also includes a CRC checksum of each object so
+compressed data can be copied directly from pack to pack during
+repacking without undetected data corruption. Version 2 indexes can
+also handle packfiles larger than 4 Gb.</para>
+<inlinemediaobject><imageobject>
+<imagedata fileref="images/packfile-index.png"/>
+</imageobject></inlinemediaobject>
+
+<para>In both formats, the fanout table is simply a way to find the
+offset of a particular sha faster within the index file. The
+offset/sha1[] tables are sorted by sha1[] values (this is to allow
+binary search of this table), and fanout[] table points at the
+offset/sha1[] table in a specific way (so that part of the latter
+table that covers all hashes that start with a given byte can be
+found to avoid 8 iterations of the binary search).</para>
+<para>In version 1, the offsets and shas are in the same space,
+where in version two, there are seperate tables for the shas, crc
+checksums and offsets. At the end of both files are checksum shas
+for both the index file and the packfile it references.</para>
+<para>Importantly, packfile indexes are <emphasis>not</emphasis>
+neccesary to extract objects from a packfile, they are simply used
+to <emphasis>quickly</emphasis> retrieve individual objects from a
+pack. The packfile format is used in upload-pack and receieve-pack
+programs (push and fetch protocols) to transfer objects and there
+is no index used then - it can be built after the fact by scanning
+the packfile.</para>
+</sect3><sect3 id="The_Packfile_Forma"><title>The Packfile
+Format</title>
+<para>The packfile itself is a very simple format. There is a
+header, a series of packed objects (each with it's own header and
+body) and then a checksum trailer. The first four bytes is the
+string 'PACK', which is sort of used to make sure you're getting
+the start of the packfile correctly. This is followed by a 4-byte
+packfile version number and then a 4-byte number of entries in that
+file. In Ruby, you might read the header data like this:</para>
+<programlisting>
+def read_pack_header
+  sig = @session.recv(4)
+  ver = @session.recv(4).unpack("N")[0]
+  entries = @session.recv(4).unpack("N")[0]
+  [sig, ver, entries]
+end
+</programlisting>
+
+<para>After that, you get a series of packed objects, in order of
+thier SHAs which each consist of an object header and object
+contents. At the end of the packfile is a 20-byte SHA1 sum of all
+the shas (in sorted order) in that packfile.</para>
+<inlinemediaobject><imageobject>
+<imagedata fileref="images/packfile-format.png"/>
+</imageobject></inlinemediaobject>
+
+<para>The object header is a series of one or more 1 byte (8 bit)
+hunks that specify the type of object the following data is, and
+the size of the data when expanded. Each byte is really 7 bits of
+data, with the first bit being used to say if that hunk is the last
+one or not before the data starts. If the first bit is a 1, you
+will read another byte, otherwise the data starts next. The first 3
+bits in the first byte specifies the type of data, according to the
+table below.</para>
+<para>(Currently, of the 8 values that can be expressed with 3 bits
+(0-7), 0 (000) is 'undefined' and 5 (101) is not yet used.)</para>
+<para>Here, we can see an example of a header of two bytes, where
+the first specifies that the following data is a commit, and the
+remainder of the first and the last 7 bits of the second specifies
+that the data will be 144 bytes when expanded.</para>
+<inlinemediaobject><imageobject>
+<imagedata fileref="images/packfile-logic.png"/>
+</imageobject></inlinemediaobject>
+
+<para>It is important to note that the size specified in the header
+data is not the size of the data that actually follows, but the
+size of that data <emphasis>when expanded</emphasis>. This is why
+the offsets in the packfile index are so useful, otherwise you have
+to expand every object just to tell when the next header
+starts.</para>
+<para>The data part is just zlib stream for non-delta object types;
+for the two delta object representations, the data portion contains
+something that identifies which base object this delta
+representation depends on, and the delta to apply on the base
+object to resurrect this object. <literal>ref-delta</literal> uses
+20-byte hash of the base object at the beginning of data, while
+<literal>ofs-delta</literal> stores an offset within the same
+packfile to identify the base object. In either case, two important
+constraints a reimplementor must adhere to are:</para>
+<itemizedlist>
+<listitem>
+<para>delta representation must be based on some other object
+within the same packfile;</para>
+</listitem>
+<listitem>
+<para>the base object must be of the same underlying type (blob,
+tree, commit or tag);</para>
+</listitem>
+</itemizedlist>
+</sect3></sect2>
+<sect2 id="Raw_Gi"><title>Raw Git</title>
+<para>Here we will take a look at how to manipulate git at a more
+raw level, in case you would like to write a tool that generates
+new blobs, trees or commits in a more artificial way. If you want
+to write a script that uses more low-level git plumbing to do
+something new, here are some of the tools you'll need.</para>
+<sect3 id="Creating_Blob"><title>Creating Blobs</title>
+<para>Creating a blob in your Git repository and getting a SHA back
+is pretty easy. The
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-hash-object.html">git
+hash-object</ulink> command is all you'll need. To create a blob
+object from an existing file, just run it with the '-w' option
+(which tells it to write the blob, not just compute the
+SHA).</para>
+<programlisting>
+<literal>$ git hash-object -w myfile.txt
+6ff87c4664981e4397625791c8ea3bbb5f2279a3
+
+$ git hash-object -w myfile2.txt
+3bb0e8592a41ae3185ee32266c860714980dbed7
+</literal>
+</programlisting>
+
+<para>The STDOUT output of the command will the the SHA of the blob
+that was created.</para>
+</sect3><sect3 id="Creating_Tree"><title>Creating Trees</title>
+<para>Now lets say you want to create a tree from your new objects.
+The
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-mktree.html">git
+mktree</ulink> command makes it pretty simple to generate new tree
+objects from
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-ls-tree.html">git
+ls-tree</ulink> formatted output. For example, if you write the
+following to a file named '/tmp/tree.txt' :</para>
+<programlisting>
+<literal>100644 blob 6ff87c4664981e4397625791c8ea3bbb5f2279a3    file1
+100644 blob 3bb0e8592a41ae3185ee32266c860714980dbed7    file2
+</literal>
+</programlisting>
+
+<para>and then piped that through the
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-mktree.html">git
+mktree</ulink> command, Git will write a new tree to the object
+database and give you back the new sha of that tree.</para>
+<programlisting>
+<literal>$ cat /tmp/tree.txt | git mk-tree
+f66a66ab6a7bfe86d52a66516ace212efa00fe1f
+</literal>
+</programlisting>
+
+<para>Then, we can take that and make it a subdirectory of yet
+another tree, and so on. If we wanted to create a new tree with
+that one as a subtree, we just create a new file (/tmp/newtree.txt)
+with our new SHA as a tree in it:</para>
+<programlisting>
+<literal>100644 blob 6ff87c4664981e4397625791c8ea3bbb5f2279a3    file1-copy
+040000 tree f66a66ab6a7bfe86d52a66516ace212efa00fe1f    our_files
+</literal>
+</programlisting>
+
+<para>and then use
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-mk-tree.html">git
+mk-tree</ulink> again:</para>
+<programlisting>
+<literal>$ cat /tmp/newtree.txt | git mk-tree
+5bac6559179bd543a024d6d187692343e2d8ae83
+</literal>
+</programlisting>
+
+<para>And we now have an artificial directory structure in Git that
+looks like this:</para>
+<programlisting>
+<literal>.
+|-- file1-copy
+`-- our_files
+    |-- file1
+    `-- file2
+
+1 directory, 3 files
+</literal>
+</programlisting>
+
+<para>without that structure ever having actually existed on disk.
+Plus, we have a SHA (<literal>5bac6559</literal>) that points to
+it.</para>
+</sect3><sect3 id="Rearranging_Tree"><title>Rearranging
+Trees</title>
+<para>We can also do tree manipulation by combining trees into new
+structures using the index file. As a simple example, let's take
+the tree we just created and make a new tree that has two copies of
+our <literal>5bac6559</literal> tree in it using a temporary index
+file. (You can do this by resetting the GIT_INDEX_FILE environment
+variable or on the command line)</para>
+<para>First, we read the tree into our index file under a new
+prefix using the
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-read-tree.html">git
+read-tree</ulink> command, and then write the index contents as a
+tree using the
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-write-tree.html">git
+write-tree</ulink> command:</para>
+<programlisting>
+<literal>$ export GIT_INDEX_FILE=/tmp/index
+$ git read-tree --prefix=copy1/  5bac6559
+$ git read-tree --prefix=copy2/  5bac6559
+$ git write-tree 
+bb2fa6de7625322322382215d9ea78cfe76508c1
+
+$&gt;git ls-tree bb2fa
+040000 tree 5bac6559179bd543a024d6d187692343e2d8ae83    copy1
+040000 tree 5bac6559179bd543a024d6d187692343e2d8ae83    copy2
+</literal>
+</programlisting>
+
+<para>So now we can see that we've created a new tree just from
+index manipulation. You can also do interesting merge operations
+and such in a temporary index this way - see the
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-read-tree.html">git
+read-tree</ulink> docs for more information.</para>
+</sect3><sect3 id="Creating_Commit"><title>Creating Commits</title>
+<para>Now that we have a tree SHA, we can create a commit object
+that points to it. We can do this using the
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-commit-tree.html">git
+commit-tree</ulink> command. Most of the data that goes into the
+commit has to be set as environment variables, so you'll want to
+set the following:</para>
+<programlisting>
+<literal>GIT_AUTHOR_NAME
+GIT_AUTHOR_EMAIL
+GIT_AUTHOR_DATE
+GIT_COMMITTER_NAME
+GIT_COMMITTER_EMAIL
+GIT_COMMITTER_DATE
+</literal>
+</programlisting>
+
+<para>Then you will need to write your commit message to a file or
+somehow pipe it into the command through STDIN. Then, you can
+create your commit object based on the tree sha we have.</para>
+<programlisting>
+<literal>$ git commit-tree bb2fa &lt; /tmp/message
+a5f85ba5875917319471dfd98dfc636c1dc65650
+</literal>
+</programlisting>
+
+<para>If you want to specify one or more parent commits, simply add
+the shas on the command line with a '-p' option before each. The
+SHA of the new commit object will be returned via STDOUT.</para>
+</sect3><sect3 id="Updating_a_Branch_Re"><title>Updating a Branch
+Ref</title>
+<para>Now that we have a new commit object SHA, we can update a
+branch to point to it if we want to. Lets say we want to update our
+'master' branch to point to the new commit we just created - we
+would use the
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-update-ref.html">git
+update-ref</ulink> command:</para>
+<programlisting>
+<literal>$ git update-ref refs/heads/master a5f85ba5875917319471dfd98dfc636c1dc65650
+</literal>
+</programlisting>
+
+</sect3></sect2><sect2 id="Transfer_Protocol"><title>Transfer
+Protocols</title>
+<para>Here we will go over how clients and servers talk to each
+other to transfer Git data around.</para>
+<sect3 id="Fetching_Data_over_HTT"><title>Fetching Data over
+HTTP</title>
+<para>Fetching over an http/s URL will make Git use a slightly
+dumber protocol. In this case, all of the logic is entirely on the
+client side. The server requires no special setup - any static
+webserver will work fine if the git directory you are fetching from
+is in the webserver path.</para>
+<para>In order for this to work, you do need to run a single
+command on the server repo everytime anything is updated, though -
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-update-server-info.html">git
+update-server-info</ulink>, which updates the objects/info/packs
+and info/refs files to list which refs and packfiles are available,
+since you can't do a listing over http. When that command is run,
+the objects/info/packs file looks something like this:</para>
+<programlisting>
+<literal>P pack-ce2bd34abc3d8ebc5922dc81b2e1f30bf17c10cc.pack
+P pack-7ad5f5d05f5e20025898c95296fe4b9c861246d8.pack
+</literal>
+</programlisting>
+
+<para>So that if the fetch can't find a loose file, it can try
+these packfiles. The info/refs file will look something like
+this:</para>
+<programlisting>
+<literal>184063c9b594f8968d61a686b2f6052779551613    refs/heads/development
+32aae7aef7a412d62192f710f2130302997ec883    refs/heads/master
+</literal>
+</programlisting>
+
+<para>Then when you fetch from this repo, it will start with these
+refs and walk the commit objects until the client has all the
+objects that it needs.</para>
+<para>For instance, if you ask to fetch the master branch, it will
+see that master is pointing to <literal>32aae7ae</literal> and that
+your master is pointing to <literal>ab04d88</literal>, so you need
+<literal>32aae7ae</literal>. You fetch that object</para>
+<programlisting>
+<literal>CONNECT http://myserver.com
+GET /git/myproject.git/objects/32/aae7aef7a412d62192f710f2130302997ec883 - 200
+</literal>
+</programlisting>
+
+<para>and it looks like this:</para>
+<programlisting>
+<literal>tree aa176fb83a47d00386be237b450fb9dfb5be251a
+parent bd71cad2d597d0f1827d4a3f67bb96a646f02889
+author Scott Chacon &lt;schacon@gmail.com&gt; 1220463037 -0700
+committer Scott Chacon &lt;schacon@gmail.com&gt; 1220463037 -0700
+
+added chapters on private repo setup, scm migration, raw git
+</literal>
+</programlisting>
+
+<para>So now it fetches the tree
+<literal>aa176fb8</literal>:</para>
+<programlisting>
+<literal>GET /git/myproject.git/objects/aa/176fb83a47d00386be237b450fb9dfb5be251a - 200
+</literal>
+</programlisting>
+
+<para>which looks like this:</para>
+<programlisting>
+<literal>100644 blob 6ff87c4664981e4397625791c8ea3bbb5f2279a3    COPYING
+100644 blob 97b51a6d3685b093cfb345c9e79516e5099a13fb    README
+100644 blob 9d1b23b8660817e4a74006f15fae86e2a508c573    Rakefile
+</literal>
+</programlisting>
+
+<para>So then it fetches those objects:</para>
+<programlisting>
+<literal>GET /git/myproject.git/objects/6f/f87c4664981e4397625791c8ea3bbb5f2279a3 - 200
+GET /git/myproject.git/objects/97/b51a6d3685b093cfb345c9e79516e5099a13fb - 200
+GET /git/myproject.git/objects/9d/1b23b8660817e4a74006f15fae86e2a508c573 - 200
+</literal>
+</programlisting>
+
+<para>It actually does this with Curl, and can open up multiple
+parallel threads to speed up this process. When it's done recursing
+the tree pointed to by the commit, it fetches the next
+parent.</para>
+<programlisting>
+<literal>GET /git/myproject.git/objects/bd/71cad2d597d0f1827d4a3f67bb96a646f02889 - 200
+</literal>
+</programlisting>
+
+<para>Now in this case, the commit that comes back looks like
+this:</para>
+<programlisting>
+<literal>tree b4cc00cf8546edd4fcf29defc3aec14de53e6cf8
+parent ab04d884140f7b0cf8bbf86d6883869f16a46f65
+author Scott Chacon &lt;schacon@gmail.com&gt; 1220421161 -0700
+committer Scott Chacon &lt;schacon@gmail.com&gt; 1220421161 -0700
+
+added chapters on the packfile and how git stores objects
+</literal>
+</programlisting>
+
+<para>and we can see that the parent, <literal>ab04d88</literal> is
+where our master branch is currently pointing. So, we recursively
+fetch this tree and then stop, since we know we have everything
+before this point. You can force Git to double check that we have
+everything with the '--recover' option. See
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-http-fetch.html">git
+http-fetch</ulink> for more information.</para>
+<para>If one of the loose object fetches fails, Git will download
+the packfile indexes looking for the sha that it needs, then
+download that packfile.</para>
+<para>It is important if you are running a git server that serves
+repos this way to implement a post-receive hook that runs the 'git
+update-server-info' command each time or there will be
+confusion.</para>
+</sect3><sect3 id="Fetching_Data_with_Upload_Pac"><title>Fetching
+Data with Upload Pack</title>
+<para>For the smarter protocols, fetching objects is much more
+efficient. A socket is opened, either over ssh or over port 9418
+(in the case of the git:// protocol), and the
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-fetch-pack.html">git
+fetch-pack</ulink> command on the client begins communicating with
+a forked
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-upload-pack.html">git
+upload-pack</ulink> process on the server.</para>
+<para>Then the server will tell the client which SHAs it has for
+each ref, and the client figures out what it needs and responds
+with a list of SHAs it wants and already has.</para>
+<para>At this point, the server will generate a packfile with all
+the objects that the client needs and begin streaming it down to
+the client.</para>
+<para>Let's look at an example.</para>
+<para>The client connects and sends the request header. The clone
+command</para>
+<programlisting>
+<literal>$ git clone git://myserver.com/project.git
+</literal>
+</programlisting>
+
+<para>produces the following request:</para>
+<programlisting>
+<literal>0032git-upload-pack /project.git\000host=myserver.com\000
+</literal>
+</programlisting>
+
+<para>The first four bytes contain the hex length of the line
+(including 4 byte line length and trailing newline if present).
+Following are the command and arguments. This is followed by a null
+byte and then the host information. The request is terminated by a
+null byte.</para>
+<para>The request is processed and turned into a call to
+git-upload-pack:</para>
+<programlisting>
+<literal>$ git-upload-pack /path/to/repos/project.git
+</literal>
+</programlisting>
+
+<para>This immediately returns information of the repo:</para>
+<programlisting>
+<literal>007c74730d410fcb6603ace96f1dc55ea6196122532d HEAD\000multi_ack thin-pack side-band side-band-64k ofs-delta shallow no-progress
+003e7d1665144a3a975c05f1f43902ddaf084e784dbe refs/heads/debug
+003d5a3f6be755bbb7deae50065988cbfa1ffa9ab68a refs/heads/dist
+003e7e47fe2bd8d01d481f44d7af0531bd93d3b21c01 refs/heads/local
+003f74730d410fcb6603ace96f1dc55ea6196122532d refs/heads/master
+0000
+</literal>
+</programlisting>
+
+<para>Each line starts with a four byte line length declaration in
+hex. The section is terminated by a line length declaration of
+0000.</para>
+<para>This is sent back to the client verbatim. The client responds
+with another request:</para>
+<programlisting>
+<literal>0054want 74730d410fcb6603ace96f1dc55ea6196122532d multi_ack side-band-64k ofs-delta
+0032want 7d1665144a3a975c05f1f43902ddaf084e784dbe
+0032want 5a3f6be755bbb7deae50065988cbfa1ffa9ab68a
+0032want 7e47fe2bd8d01d481f44d7af0531bd93d3b21c01
+0032want 74730d410fcb6603ace96f1dc55ea6196122532d
+00000009done
+</literal>
+</programlisting>
+
+<para>The is sent to the open git-upload-pack process which then
+streams out the final response:</para>
+<programlisting>
+<literal>"0008NAK\n"
+"0023\002Counting objects: 2797, done.\n"
+"002b\002Compressing objects:   0% (1/1177)   \r"
+"002c\002Compressing objects:   1% (12/1177)   \r"
+"002c\002Compressing objects:   2% (24/1177)   \r"
+"002c\002Compressing objects:   3% (36/1177)   \r"
+"002c\002Compressing objects:   4% (48/1177)   \r"
+"002c\002Compressing objects:   5% (59/1177)   \r"
+"002c\002Compressing objects:   6% (71/1177)   \r"
+"0053\002Compressing objects:   7% (83/1177)   \rCompressing objects:   8% (95/1177)   \r"
+...
+"005b\002Compressing objects: 100% (1177/1177)   \rCompressing objects: 100% (1177/1177), done.\n"
+"2004\001PACK\000\000\000\002\000\000\n\355\225\017x\234\235\216K\n\302"...
+"2005\001\360\204{\225\376\330\345]z2673"...
+...
+"0037\002Total 2797 (delta 1799), reused 2360 (delta 1529)\n"
+...
+"&lt;\276\255L\273s\005\001w0006\001[0000"
+</literal>
+</programlisting>
+
+<para>See the Packfile chapter previously for the actual format of
+the packfile data in the response.</para>
+</sect3><sect3 id="Pushing_Dat"><title>Pushing Data</title>
+<para>Pushing data over the git and ssh protocols is similar, but
+simpler. Basically what happens is the client requests a
+receive-pack instance, which is started up if the client has
+access, then the server returns all the ref head shas it has again
+and the client generates a packfile of everything the server needs
+(generally only if what is on the server is a direct ancestor of
+what it is pushing) and sends that packfile upstream, where the
+server either stores it on disk and builds an index for it, or
+unpacks it (if there aren't many objects in it)</para>
+<para>This entire process is accomplished through the
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-send-pack.html">git
+send-pack</ulink> command on the client, which is invoked by
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-push.html">git
+push</ulink> and the
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-receive-pack.html">git
+receive-pack</ulink> command on the server side, which is invoked
+by the ssh connect process or git daemon (if it's an open push
+server).</para>
+</sect3></sect2><sect2 id="Glossar"><title>Glossary</title>
+<para>Here we have the meanings of some terms used into Git
+context.These terms were entirely copied from
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/gitglossary.html">Git
+Glossary</ulink>.</para>
+<para><emphasis>alternate object database</emphasis></para>
+<blockquote>
+<para>Via the alternates mechanism, a repository</para>
+<programlisting>
+<literal>can inherit part of its object database
+from another object database, which is called "alternate". 
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>bare repository</emphasis></para>
+<blockquote>
+<para>A bare repository is normally an appropriately</para>
+<programlisting>
+<literal>named directory with a `.git` suffix that does not
+have a locally checked-out copy of any of the files under
+revision control. That is, all of the `git`
+administrative and control files that would normally be present in the
+hidden `.git` sub-directory are directly present in the
+`repository.git` directory instead,
+and no other files are present and checked out. Usually publishers of
+public repositories make bare repositories available.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>blob object</emphasis></para>
+<blockquote>
+<para>Untyped object, e.g. the contents of a file.</para>
+</blockquote>
+<para><emphasis>branch</emphasis></para>
+<blockquote>
+<para>A "branch" is an active line of development. The most
+recent</para>
+<programlisting>
+<literal>commit on a branch is referred to as the tip of
+that branch.  The tip of the branch is referenced by a branch
+head, which moves forward as additional development
+is done on the branch.  A single git
+repository can track an arbitrary number of
+branches, but your working tree is
+associated with just one of them (the "current" or "checked out"
+branch), and HEAD points to that branch.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>cache</emphasis></para>
+<blockquote>
+<para>Obsolete for: index.</para>
+</blockquote>
+<para><emphasis>chain</emphasis></para>
+<blockquote>
+<para>A list of objects, where each object in the list
+contains</para>
+<programlisting>
+<literal>a reference to its successor (for example, the successor of a
+commit could be one of its parents).
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>changeset</emphasis></para>
+<blockquote>
+<para>BitKeeper/cvsps speak for "commit". Since git does not</para>
+<programlisting>
+<literal>store changes, but states, it really does not make sense to use the term
+"changesets" with git.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>checkout</emphasis></para>
+<blockquote>
+<para>The action of updating all or part of the</para>
+<programlisting>
+<literal>working tree with a tree object
+or blob from the
+object database, and updating the
+index and HEAD if the whole working tree has
+been pointed at a new branch.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>cherry-picking</emphasis></para>
+<blockquote>
+<para>In SCM jargon, "cherry pick" means to choose a subset
+of</para>
+<programlisting>
+<literal>changes out of a series of changes (typically commits) and record them
+as a new series of changes on top of a different codebase. In GIT, this is
+performed by the "git cherry-pick" command to extract the change introduced
+by an existing commit and to record it based on the tip
+of the current branch as a new commit.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>clean</emphasis></para>
+<blockquote>
+<para>A working tree is clean, if it</para>
+<programlisting>
+<literal>corresponds to the revision referenced by the current
+head. Also see "dirty".
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>commit</emphasis></para>
+<blockquote>
+<para>As a noun: A single point in the</para>
+<programlisting>
+<literal>git history; the entire history of a project is represented as a
+set of interrelated commits.  The word "commit" is often
+used by git in the same places other revision control systems
+use the words "revision" or "version".  Also used as a short
+hand for commit object.
+</literal>
+</programlisting>
+
+<para>As a verb: The action of storing a new snapshot of the
+project's</para>
+<programlisting>
+<literal>state in the git history, by creating a new commit representing the current
+state of the index and advancing HEAD
+to point at the new commit.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>commit object</emphasis></para>
+<blockquote>
+<para>An object which contains the information about a</para>
+<programlisting>
+<literal>particular revision, such as parents, committer,
+author, date and the tree object which corresponds
+to the top directory of the stored
+revision.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>core git</emphasis></para>
+<blockquote>
+<para>Fundamental data structures and utilities of git. Exposes
+only limited</para>
+<programlisting>
+<literal>source code management tools.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>DAG</emphasis></para>
+<blockquote>
+<para>Directed acyclic graph. The commit objects form a</para>
+<programlisting>
+<literal>directed acyclic graph, because they have parents (directed), and the
+graph of commit objects is acyclic (there is no chain
+which begins and ends with the same object).
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>dangling object</emphasis></para>
+<blockquote>
+<para>An unreachable object which is not</para>
+<programlisting>
+<literal>reachable even from other unreachable objects; a
+dangling object has no references to it from any
+reference or object in the repository.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>detached HEAD</emphasis></para>
+<blockquote>
+<para>Normally the HEAD stores the name of a</para>
+<programlisting>
+<literal>branch.  However, git also allows you to check out
+an arbitrary commit that isn't necessarily the tip of any
+particular branch.  In this case HEAD is said to be "detached".
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>dircache</emphasis></para>
+<blockquote>
+<para>You are <emphasis>waaaaay</emphasis> behind. See
+index.</para>
+</blockquote>
+<para><emphasis>directory</emphasis></para>
+<blockquote>
+<para>The list you get with "ls" :-)</para>
+</blockquote>
+<para><emphasis>dirty</emphasis></para>
+<blockquote>
+<para>A working tree is said to be "dirty" if</para>
+<programlisting>
+<literal>it contains modifications which have not been committed to the current
+branch.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>ent</emphasis></para>
+<blockquote>
+<para>Favorite synonym to "tree-ish" by some total geeks.
+See</para>
+<programlisting>
+<literal>`http://en.wikipedia.org/wiki/Ent_(Middle-earth)` for an in-depth
+explanation. Avoid this term, not to confuse people.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>evil merge</emphasis></para>
+<blockquote>
+<para>An evil merge is a merge that introduces changes that</para>
+<programlisting>
+<literal>do not appear in any parent.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>fast forward</emphasis></para>
+<blockquote>
+<para>A fast-forward is a special type of merge where you have
+a</para>
+<programlisting>
+<literal>revision and you are "merging" another
+branch's changes that happen to be a descendant of what
+you have. In such these cases, you do not make a new merge
+commit but instead just update to his
+revision. This will happen frequently on a
+tracking branch of a remote
+repository.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>fetch</emphasis></para>
+<blockquote>
+<para>Fetching a branch means to get the</para>
+<programlisting>
+<literal>branch's head ref from a remote
+repository, to find out which objects are
+missing from the local object database,
+and to get them, too.  See also <ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-fetch.html">git fetch</ulink>.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>file system</emphasis></para>
+<blockquote>
+<para>Linus Torvalds originally designed git to be a user space
+file system,</para>
+<programlisting>
+<literal>i.e. the infrastructure to hold files and directories. That ensured the
+efficiency and speed of git.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>git archive</emphasis></para>
+<blockquote>
+<para>Synonym for repository (for arch people).</para>
+</blockquote>
+<para><emphasis>grafts</emphasis></para>
+<blockquote>
+<para>Grafts enables two otherwise different lines of development
+to be joined</para>
+<programlisting>
+<literal>together by recording fake ancestry information for commits. This way
+you can make git pretend the set of parents a commit has
+is different from what was recorded when the commit was
+created. Configured via the `.git/info/grafts` file.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>hash</emphasis></para>
+<blockquote>
+<para>In git's context, synonym to object name.</para>
+</blockquote>
+<para><emphasis>head</emphasis></para>
+<blockquote>
+<para>A named reference to the commit at the tip of a</para>
+<programlisting>
+<literal>branch.  Heads are stored in
+`$GIT_DIR/refs/heads/`, except when using packed refs. (See
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-pack-refs.html">git pack-refs</ulink>.)
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>HEAD</emphasis></para>
+<blockquote>
+<para>The current branch. In more detail: Your working tree is
+normally derived</para>
+<programlisting>
+<literal>from the state of the tree referred to by HEAD.  HEAD is a reference to one
+of the heads in your repository, except when using a detached HEAD, in which
+case it may reference an arbitrary commit.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>head ref</emphasis></para>
+<blockquote>
+<para>A synonym for head.</para>
+</blockquote>
+<para><emphasis>hook</emphasis></para>
+<blockquote>
+<para>During the normal execution of several git commands,
+call-outs are made</para>
+<programlisting>
+<literal>to optional scripts that allow a developer to add functionality or
+checking. Typically, the hooks allow for a command to be pre-verified
+and potentially aborted, and allow for a post-notification after the
+operation is done. The hook scripts are found in the
+`$GIT_DIR/hooks/` directory, and are enabled by simply
+removing the `.sample` suffix from the filename. In earlier versions
+of git you had to make them executable.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>index</emphasis></para>
+<blockquote>
+<para>A collection of files with stat information, whose contents
+are stored</para>
+<programlisting>
+<literal>as objects. The index is a stored version of your
+working tree. Truth be told, it can also contain a second, and even
+a third version of a working tree, which are used
+when merging.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>index entry</emphasis></para>
+<blockquote>
+<para>The information regarding a particular file, stored in
+the</para>
+<programlisting>
+<literal>index. An index entry can be unmerged, if a
+merge was started, but not yet finished (i.e. if
+the index contains multiple versions of that file).
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>master</emphasis></para>
+<blockquote>
+<para>The default development branch. Whenever you</para>
+<programlisting>
+<literal>create a git repository, a branch named
+"master" is created, and becomes the active branch. In most
+cases, this contains the local development, though that is
+purely by convention and is not required.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>merge</emphasis></para>
+<blockquote>
+<para>As a verb: To bring the contents of another</para>
+<programlisting>
+<literal>branch (possibly from an external
+repository) into the current branch.  In the
+case where the merged-in branch is from a different repository,
+this is done by first fetching the remote branch
+and then merging the result into the current branch.  This
+combination of fetch and merge operations is called a
+pull.  Merging is performed by an automatic process
+that identifies changes made since the branches diverged, and
+then applies all those changes together.  In cases where changes
+conflict, manual intervention may be required to complete the
+merge.
+</literal>
+</programlisting>
+
+<para>As a noun: unless it is a fast forward, a</para>
+<programlisting>
+<literal>successful merge results in the creation of a new commit
+representing the result of the merge, and having as
+parents the tips of the merged branches.
+This commit is referred to as a "merge commit", or sometimes just a
+"merge".
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>object</emphasis></para>
+<blockquote>
+<para>The unit of storage in git. It is uniquely identified by
+the</para>
+<programlisting>
+<literal>SHA1&gt; of its contents. Consequently, an
+object can not be changed.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>object database</emphasis></para>
+<blockquote>
+<para>Stores a set of "objects", and an individual object is</para>
+<programlisting>
+<literal>identified by its object name. The objects usually
+live in `$GIT_DIR/objects/`.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>object identifier</emphasis></para>
+<blockquote>
+<para>Synonym for object name.</para>
+</blockquote>
+<para><emphasis>object name</emphasis></para>
+<blockquote>
+<para>The unique identifier of an object. The hash</para>
+<programlisting>
+<literal>of the object's contents using the Secure Hash Algorithm
+1 and usually represented by the 40 character hexadecimal encoding of
+the hash of the object.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>object type</emphasis></para>
+<blockquote>
+<para>One of the identifiers "commit", "tree", "tag" or "blob"
+describing the</para>
+<programlisting>
+<literal>type of an object.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>octopus</emphasis></para>
+<blockquote>
+<para>To merge more than two branches. Also denotes an</para>
+<programlisting>
+<literal>intelligent predator.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>origin</emphasis></para>
+<blockquote>
+<para>The default upstream repository. Most projects have</para>
+<programlisting>
+<literal>at least one upstream project which they track. By default
+'origin' is used for that purpose. New upstream updates
+will be fetched into remote tracking branches named
+origin/name-of-upstream-branch, which you can see using
+"`git branch -r`".
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>pack</emphasis></para>
+<blockquote>
+<para>A set of objects which have been compressed into one file (to
+save space</para>
+<programlisting>
+<literal>or to transmit them efficiently).
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>pack index</emphasis></para>
+<blockquote>
+<para>The list of identifiers, and other information, of the
+objects in a</para>
+<programlisting>
+<literal>pack, to assist in efficiently accessing the contents of a
+pack.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>parent</emphasis></para>
+<blockquote>
+<para>A commit object contains a (possibly empty) list</para>
+<programlisting>
+<literal>of the logical predecessor(s) in the line of development, i.e. its
+parents.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>pickaxe</emphasis></para>
+<blockquote>
+<para>The term pickaxe refers to an option to the diffcore</para>
+<programlisting>
+<literal>routines that help select changes that add or delete a given text
+string. With the `--pickaxe-all` option, it can be used to view the full
+changeset that introduced or removed, say, a
+particular line of text. See <ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-diff.html">git diff</ulink>.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>plumbing</emphasis></para>
+<blockquote>
+<para>Cute name for core git.</para>
+</blockquote>
+<para><emphasis>porcelain</emphasis></para>
+<blockquote>
+<para>Cute name for programs and program suites depending on</para>
+<programlisting>
+<literal>core git, presenting a high level access to
+core git. Porcelains expose more of a SCM
+interface than the plumbing.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>pull</emphasis></para>
+<blockquote>
+<para>Pulling a branch means to fetch it and</para>
+<programlisting>
+<literal>merge it.  See also <ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-pull.html">git pull</ulink>.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>push</emphasis></para>
+<blockquote>
+<para>Pushing a branch means to get the branch's</para>
+<programlisting>
+<literal>head ref from a remote repository,
+find out if it is a direct ancestor to the branch's local
+head ref, and in that case, putting all
+objects, which are reachable from the local
+head ref, and which are missing from the remote
+repository, into the remote
+object database, and updating the remote
+head ref. If the remote head is not an
+ancestor to the local head, the push fails.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>reachable</emphasis></para>
+<blockquote>
+<para>All of the ancestors of a given commit are said to be</para>
+<programlisting>
+<literal>"reachable" from that commit. More
+generally, one object is reachable from
+another if we can reach the one from the other by a chain
+that follows tags to whatever they tag,
+commits to their parents or trees, and
+trees to the trees or blobs
+that they contain.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>rebase</emphasis></para>
+<blockquote>
+<para>To reapply a series of changes from a branch to a</para>
+<programlisting>
+<literal>different base, and reset the head of that branch
+to the result.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>ref</emphasis></para>
+<blockquote>
+<para>A 40-byte hex representation of a SHA1 or a name that</para>
+<programlisting>
+<literal>denotes a particular object. These may be stored in
+`$GIT_DIR/refs/`.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>reflog</emphasis></para>
+<blockquote>
+<para>A reflog shows the local "history" of a ref. In other
+words,</para>
+<programlisting>
+<literal>it can tell you what the 3rd last revision in _this_ repository
+was, and what was the current state in _this_ repository,
+yesterday 9:14pm.  See <ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-reflog.html">git reflog</ulink> for details.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>refspec</emphasis></para>
+<blockquote>
+<para>A "refspec" is used by fetch and</para>
+<programlisting>
+<literal>push to describe the mapping between remote
+ref and local ref. They are combined with a colon in
+the format &lt;src&gt;:&lt;dst&gt;, preceded by an optional plus sign, +.
+For example: `git fetch $URL
+refs/heads/master:refs/heads/origin` means "grab the master
+branch head from the $URL and store
+it as my origin branch head". And `git push
+$URL refs/heads/master:refs/heads/to-upstream` means "publish my
+master branch head as to-upstream branch at $URL". See also
+<ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-push.html">git push</ulink>.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>repository</emphasis></para>
+<blockquote>
+<para>A collection of refs together with an</para>
+<programlisting>
+<literal>object database containing all objects
+which are reachable from the refs, possibly
+accompanied by meta data from one or more porcelains. A
+repository can share an object database with other repositories
+via alternates mechanism.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>resolve</emphasis></para>
+<blockquote>
+<para>The action of fixing up manually what a failed
+automatic</para>
+<programlisting>
+<literal>merge left behind.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>revision</emphasis></para>
+<blockquote>
+<para>A particular state of files and directories which was stored
+in the</para>
+<programlisting>
+<literal>object database. It is referenced by a
+commit object.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>rewind</emphasis></para>
+<blockquote>
+<para>To throw away part of the development, i.e. to assign
+the</para>
+<programlisting>
+<literal>head to an earlier revision.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>SCM</emphasis></para>
+<blockquote>
+<para>Source code management (tool).</para>
+</blockquote>
+<para><emphasis>SHA1</emphasis></para>
+<blockquote>
+<para>Synonym for object name.</para>
+</blockquote>
+<para><emphasis>shallow repository</emphasis></para>
+<blockquote>
+<para>A shallow repository has an incomplete</para>
+<programlisting>
+<literal>history some of whose commits have parents cauterized away (in other
+words, git is told to pretend that these commits do not have the
+parents, even though they are recorded in the commit
+object). This is sometimes useful when you are interested only in the
+recent history of a project even though the real history recorded in the
+upstream is much larger. A shallow repository
+is created by giving the `--depth` option to <ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-clone.html">git clone</ulink>, and
+its history can be later deepened with <ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-fetch.html">git fetch</ulink>.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>symref</emphasis></para>
+<blockquote>
+<para>Symbolic reference: instead of containing the SHA1</para>
+<programlisting>
+<literal>id itself, it is of the format 'ref: refs/some/thing' and when
+referenced, it recursively dereferences to this reference.
+'HEAD' is a prime example of a symref. Symbolic
+references are manipulated with the <ulink url="http://www.kernel.org/pub/software/scm/git/docs/git-symbolic-ref.html">git symbolic-ref</ulink>
+command.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>tag</emphasis></para>
+<blockquote>
+<para>A ref pointing to a tag or</para>
+<programlisting>
+<literal>commit object. In contrast to a head,
+a tag is not changed by a commit. Tags (not
+tag objects) are stored in `$GIT_DIR/refs/tags/`. A
+git tag has nothing to do with a Lisp tag (which would be
+called an object type in git's context). A
+tag is most typically used to mark a particular point in the
+commit ancestry chain.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>tag object</emphasis></para>
+<blockquote>
+<para>An object containing a ref pointing to</para>
+<programlisting>
+<literal>another object, which can contain a message just like a
+commit object. It can also contain a (PGP)
+signature, in which case it is called a "signed tag object".
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>topic branch</emphasis></para>
+<blockquote>
+<para>A regular git branch that is used by a developer to</para>
+<programlisting>
+<literal>identify a conceptual line of development. Since branches are very easy
+and inexpensive, it is often desirable to have several small branches
+that each contain very well defined concepts or small incremental yet
+related changes.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>tracking branch</emphasis></para>
+<blockquote>
+<para>A regular git branch that is used to follow changes
+from</para>
+<programlisting>
+<literal>another repository. A tracking
+branch should not contain direct modifications or have local commits
+made to it. A tracking branch can usually be
+identified as the right-hand-side ref in a Pull:
+refspec.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>tree</emphasis></para>
+<blockquote>
+<para>Either a working tree, or a tree object together with the
+dependent</para>
+<programlisting>
+<literal>blob and tree objects (i.e. a stored representation of a working tree).
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>tree object</emphasis></para>
+<blockquote>
+<para>An object containing a list of file names and modes
+along</para>
+<programlisting>
+<literal>with refs to the associated blob and/or tree objects. A
+tree is equivalent to a directory.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>tree-ish</emphasis></para>
+<blockquote>
+<para>A ref pointing to either a commit object, a tree object, or a
+tag</para>
+<programlisting>
+<literal>object pointing to a tag or commit or tree object.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>unmerged index</emphasis></para>
+<blockquote>
+<para>An index which contains unmerged</para>
+<programlisting>
+<literal>index entries.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>unreachable object</emphasis></para>
+<blockquote>
+<para>An object which is not reachable from a</para>
+<programlisting>
+<literal>branch, tag, or any other reference.
+</literal>
+</programlisting>
+</blockquote>
+<para><emphasis>working tree</emphasis></para>
+<blockquote>
+<para>The tree of actual checked out files. The working tree
+is</para>
+<programlisting>
+<literal>normally equal to the HEAD plus any local changes
+that you have made but not yet committed.
+</literal>
+</programlisting>
+</blockquote>
+
+
+
+
+
+</sect2></sect1></article>
index 7a69c14..a5cad59 100644 (file)
@@ -25,7 +25,7 @@
        <!-- include external files -->\r
        <xi:include href="./tsvn_preface.xml"/>\r
        <xi:include href="./tsvn_introduction.xml"/>\r
-       <xi:include href="./tsvn_basics.xml"/>\r
+       <xi:include href="./git_book/git_basics.xml"/>\r
        <!--\r
        <xi:include href="./tsvn_server/server.xml"/>\r
        <xi:include href="./tsvn_repository/repository.xml"/>\r