]> git.cworth.org Git - hgbook-git/blobdiff - tour.mdwn
Fix broken backslash escapes for < and >
[hgbook-git] / tour.mdwn
index d697f90d9467c2a2132bd4f1f523675f91076a7f..1ac764eeb58a81a2cfcef60319ed09fbf4baca18 100644 (file)
--- a/tour.mdwn
+++ b/tour.mdwn
@@ -1,11 +1,11 @@
-## Chapter 2  
+## Chapter 2
 A tour of git: the basics
 
 ### 2.0 Copyright
 
-This document is a modified version originally known as "Distributed
-revision control with Mercurial" and originally authored by Bryan
-O’Sullivan. The original document was obtained from
+This document is a modified version of a document originally titled
+"Distributed revision control with Mercurial" and originally authored
+by Bryan O’Sullivan. The original document was obtained from
 <http://hgbook.red-bean.com/>.
 
 Copyright © 2006, 2007 Bryan O’Sullivan.
@@ -29,13 +29,23 @@ Changes made by Carl include the following:
     * Eliminate line numbers from examples
     * Modified to describe git instead of mercurial
 
-### 2.1  Installing git on your system
+The source of this modified version can be obtained via git:
+
+       git clone git://cworth.org/git/hgbook-git
+
+or
+
+       git clone http://cworth.org/git/hgbook-git
+
+and can be [browsed online](http://git.cworth.org/git/hgbook-git)
+
+### 2.1 Installing git on your system
 
 Prebuilt binary packages of git are available for many popular
 operating systems. These make it easy to start using git on your
 computer immediately.
 
-#### 2.1.1  Linux
+#### 2.1.1 Linux
 
 Because each Linux distribution has its own packaging tools, policies,
 and rate of development, it’s difficult to give a comprehensive set of
@@ -50,27 +60,27 @@ install git with a single click. The package name to look for is
 often git, but is sometimes git-core, (due to an unfortunate name
 with git, meaning GNU Interactive Tools).
 
-  * Debian 
+  * Debian
 
        apt-get install git-core
 
-  * Fedora Core 
+  * Fedora Core
 
        yum install git
 
-  * Gentoo 
+  * Gentoo
 
-       emerge git
+       emerge dev-util/git
 
-  * OpenSUSE 
+  * OpenSUSE
 
        yum install git
 
-  * Ubuntu 
+  * Ubuntu
 
-       apt-get install git
+       apt-get install git-core
 
-#### 2.1.2  Mac OS X
+#### 2.1.2 Mac OS X
 
 A git-core package is available through
 [macports](http://macports.org). Once macports is enabled, the command
@@ -78,7 +88,7 @@ to install git is:
 
        port install git-core
 
-#### 2.1.3  Windows
+#### 2.1.3 Windows
 
 Git has long been available as part of cygwin, and works reasonably
 well in that environment. Some people find cygwin a particularly
@@ -90,9 +100,9 @@ installers. These include GitMe, a package to install the entire
 development environment necessary to work on improving the msysgit
 port of git, and WinGit, a package for installing just git itself
 without the development environment, (still in Alpha as of September
-2008).
+2007).
 
-### 2.2  Getting started
+### 2.2 Getting started
 
 To begin, we’ll use the “git version” command to find out whether git
 is actually installed properly. Versions 1.5 and newer of git are much
@@ -100,19 +110,19 @@ more friendly to new users than versions 1.4 and older. If you aren't
 yet running version 1.5 or newer, it's highly recommended that you
 upgrade.
 
-       $ git version   
+       $ git version
        git version 1.5.3.2
 
-#### 2.2.1  Built-in help
+#### 2.2.1 Built-in help
 
 Git provides a built-in help system. This is invaluable for those
 times when you find yourself stuck trying to remember how to run a
 command. If you are completely stuck, simply run “git help”; it will
 print a brief list of commonly-used commands, along with a description
 of what each does. If you ask for help on a specific command (such as
-"git help init"), it prints more detailed information. [XXX: Does "git
-help <foo>" work universally as a built-in or does it expect man to be
-present and just call out to "man git-<foo>"?]
+"git help init"), it prints more detailed information. [XXX: Does `git
+help <foo>` work universally as a built-in or does it expect man to be
+present and just call out to `man git-<foo>`?]
 
        [XXX: The original hgbook includes the complete output of "hg
        help init" at this point. I'm not including the corresponding
@@ -125,7 +135,7 @@ present and just call out to "man git-<foo>"?]
        available for git-<foo>? And perhaps alos provide a "git -v
        help" similar to "hg -v help" for more?]
 
-### 2.3  Working with a repository
+### 2.3 Working with a repository
 
 In git, everything happens inside a repository. The repository
 for a project contains all of the files that “belong to” that project,
@@ -136,13 +146,15 @@ a directory tree in your filesystem that git treats as
 special. You can rename or delete a repository any time you like,
 using either the command line or your file browser.
 
-#### 2.3.1  Making a local copy of a repository
+#### 2.3.1 Creating a copy of a remote repository
+
+The "git clone" command is used to create a local copy of a remote
+repository. This is generally the first git operation you will use
+when beginning to work with an existing project.
 
-Copying a repository is just a little bit special. While you could use
-a normal file copying command to make a copy of a repository, it’s
-best to use a built-in command that git provides. This command
-is called “git clone”, because it creates an identical copy of an
-existing repository.
+We've assembled a simple repository that will be used in the examples
+throughout this chapter. Go ahead and clone this repository now so
+that you will be able to follow along:
 
        $ git clone git://cworth.org/git/hello
        Initialized empty Git repository in /tmp/hello/.git/
@@ -195,7 +207,34 @@ What this means for now is that we’re free to experiment with our
 repository, safe in the knowledge that it’s a private “sandbox” that
 won’t affect anyone else.
 
-#### 2.3.2  What’s in a repository?
+#### 2.3.2 Creating copy of a local repository
+
+As mentioned above, a repository can be copied through normal
+file-copying commands. But it's useful to use "git clone" even when
+just making a local copy of a repository. Using "git clone" will be
+much faster and will use much less space than a normal copy. In fact,
+local clones are impressively fast. Go ahead and make a local clone
+now as follows:
+
+       $ git clone hello hello-clone
+       Initialized empty Git repository in /tmp/hello-clone/.git/
+       0 blocks
+
+       [XXX Git says "empty" here, (presumably from the git-init
+       part), but shouldn't the command also report the succesful
+       clone which makes it non-empty? And what the heck does "0
+       blocks" mean? This is not friendly output.]
+
+In fact, let's make a couple more clones at the same time. This isn't
+just to drive home the speed and storage benefits of local clones, but
+we'll use each of these cloned repositories in Section 2.8 when
+discussing how to move commits between repositories:
+
+          $ git clone hello hello-pull
+          $ git clone hello hello-fetch
+          $ git clone hello hello-remote
+
+#### 2.3.2 What’s in a repository?
 
 When we take a more detailed look inside a repository, we can see that
 it contains a directory named .git. This is where git keeps all
@@ -216,707 +255,1024 @@ distinction is that the repository contains the history of your
 project, while the working directory contains a snapshot of your
 project at a particular point in history.
 
-### 2.4  A tour through history
+### 2.4 A tour through history
 
 One of the first things we might want to do with a new, unfamiliar
-repository is understand its history. The “hg log” command gives us a
+repository is understand its history. The “git log” command gives us a
 view of history.
 
-       $ hg log   
-       changeset:   4:b57f9a090b62   
-       tag:         tip   
-       user:        Bryan O'Sullivan <bos@serpentine.com>   
-       date:        Tue Sep 06 15:43:07 2005 -0700   
-       summary:     Trim comments.   
+       $ git log
+       commit a1a0e8b392b17caf50325498df54802fe3c03710
+       Author: Bryan O'Sullivan <bos@serpentine.com>
+       Date:   Tue Sep 6 15:43:07 2005 -0700
+       
+           Trim comments.
+       
+       commit 72d4f10e4a27dbb09ace1503c20dbac1912ee451
+       Author: Bryan O'Sullivan <bos@serpentine.com>
+       Date:   Tue Sep 6 13:15:58 2005 -0700
+       
+           Get make to generate the final binary from a .o file.
+       
+       commit 13ed136b983a9c439eddeea8a1c2076cffbb685f
+       Author: Bryan O'Sullivan <bos@serpentine.com>
+       Date:   Tue Sep 6 13:15:43 2005 -0700
        
-       changeset:   3:ff5d7b70a2a9   
-       user:        Bryan O'Sullivan <bos@serpentine.com>   
-       date:        Tue Sep 06 13:15:58 2005 -0700   
-       summary:     Get make to generate the final binary from a .o file.   
+           Introduce a typo into hello.c.
        
-       changeset:   2:057d3c2d823c   
-       user:        Bryan O'Sullivan <bos@serpentine.com>   
-       date:        Tue Sep 06 13:15:43 2005 -0700   
-       summary:     Introduce a typo into hello.c.   
+       commit 0a633bf58b45fcf1a8299d3c82cd1fd26d3f48f2
+       Author: Bryan O'Sullivan <mpm@selenic.com>
+       Date:   Fri Aug 26 01:21:28 2005 -0700
        
-       changeset:   1:82e55d328c8c   
-       user:        mpm@selenic.com   
-       date:        Fri Aug 26 01:21:28 2005 -0700   
-       summary:     Create a makefile   
+           Create a makefile
        
-       changeset:   0:0a04b987be5a   
-       user:        mpm@selenic.com   
-       date:        Fri Aug 26 01:20:50 2005 -0700   
-       summary:     Create a standard "hello, world" program   
+       commit db7117a9dd9a6e57e8632ea5848e1101eee0fbde
+       Author: Bryan O'Sullivan <mpm@selenic.com>
+       Date:   Fri Aug 26 01:20:50 2005 -0700
        
+           Create a standard "hello, world" program
+
+This command prints a record of output for each change to the project
+that was recorded. In git terminology, we call each of these recorded
+events a commit.
+
+The default fields in a record of output from “git log” are as follows.
+
+  * commit This field consists of a string of 40 hexadecimal characters.
+    This is a unique identifier for referring to particular commits.
+  * Author The identity of the person who authored the commit. This
+    field consist of two sub-fields for the user's name and email
+    address, (or at least an email-like idenitifer). Note that git
+    also stores a separate "Committer" field for the person who
+    commited the change, (since often an author will email a change to
+    a maintainer that commits it). See below for how to instruct "git
+    log" to display it as well.
+  * Date The date and time on which the commit was authored, (again
+    stored separately from the date the change was committed).
+    timezone in which it was created. (The date and time are displayed
+    in the timezone of the person who created the commit.)
+  * commit message The text message that the creator of the commit
+    entered to describe the commit, (generally a one-line summary
+    followed by more supporting text).
+
+The output of the "git log" command can be made more or less verbose
+by means of the --pretty option. For example, with "git log
+--pretty=short" the commit identifier will be omitted and only the
+first line of each commit message will be show. And with "git log
+--pretty=fuller", (the name 'fuller' is in contrast to the default
+--pretty=full), the committer name and dates will be printed in
+addition to the author name and dates.
+
+#### 2.4.1 Commits, revisions, and talking to other people
 
-By default, this command prints a brief paragraph of output for each
-change to the project that was recorded. In git terminology, we
-call each of these recorded events a changeset, because it can contain
-a record of changes to several files.
+As English is a notoriously sloppy language, and computer science has
+a hallowed history of terminological confusion (why use one term when
+four will do?), revision control has a variety of words and phrases
+that mean the same thing. If you are talking about git history
+with other people, you will find that what we have called a “commit”
+is often called a "revision". In other systems, a similar notion
+is referred to as a "changeset". You might even see abbreviations of
+these terms such as "rev", "change", or even "cset".
+
+While it may not matter much what word you use to refer to the concept
+of “a commit”, it's important to know how to name “a specific
+commit”. We have already seen one means of referring to a particular
+commit, the 40-character hexadecimal string shown by "git log". These
+commit identifiers are powerful because they are permanent, unique
+identifiers that always identify the same commit in any copy of a
+repository. If two users are examining a working directory associated
+with the same commit identifier, then those two users have precisely
+the same contents in all files, and exactly the same history leading
+to that commit.
+
+So there are places where it is often important to archive the
+complete commit identifier, (perhaps in bug-tracking systems to
+indicate a specific commit that fixes a bug, for example). But often,
+in more casual settings, it's more convenient to use abbreviated
+commit identifiers. Git accept any unique prefix of a commit
+identifier, (and for reasonably-sized project the first 8 or 10
+characters are almost always unique).
+
+And unlike the permanent commit identifiers, git also provides
+transient means of identifying commits. In fact, in day-to-day use of
+git, you will probably use these names more than commit
+identifiers. One example is branch names, (such as the default
+"master" branch in any git repository), or any project-specific branch
+names such as "stable", "experimental", or "crazy-insane-changes". Git
+also provides a special name "HEAD" which always refers to the current
+branch.
+
+#### 2.4.2 Naming related commits
+
+Git offers simple ways to name revisions that are related to
+particular revisions in the history. One syntax is the ~ suffix which
+refers to the parent of a commit, or if followed by a number, to the
+Nth parent. For example, since "HEAD" refers to the most recent commit
+in the current branch, "HEAD~", refers to the previous commit, and
+"HEAD~2" refers to two commits back in the history.
+
+Another useful syntax is .. which can be used to specify a range of
+commits. So "origin..master" specifies everything that has been
+committed to master since it diverged from origin.
+
+#### 2.4.3 Viewing specific revisions
+
+You can use "git log" to explore the range syntax just introduced. For
+example, to see a list of the most recent 3 revisions you can use
+"HEAD~3..", (the destination of the range is implicitly HEAD in this
+case):
+
+       $ git log HEAD~3..
+       commit a1a0e8b392b17caf50325498df54802fe3c03710
+       Author: Bryan O'Sullivan <bos@serpentine.com>
+       Date:   Tue Sep 6 15:43:07 2005 -0700
+       
+           Trim comments.
+       
+       commit 72d4f10e4a27dbb09ace1503c20dbac1912ee451
+       Author: Bryan O'Sullivan <bos@serpentine.com>
+       Date:   Tue Sep 6 13:15:58 2005 -0700
+       
+           Get make to generate the final binary from a .o file.
+       
+       commit 13ed136b983a9c439eddeea8a1c2076cffbb685f
+       Author: Bryan O'Sullivan <bos@serpentine.com>
+       Date:   Tue Sep 6 13:15:43 2005 -0700
+       
+           Introduce a typo into hello.c.
 
-The fields in a record of output from “hg log” are as follows. 
+#### 2.4.4 Other log filters
 
-  * changeset This field has the format of a number, followed by a
-    colon, followed by a hexadecimal string. These are identifiers for
-    the changeset. There are two identifiers because the number is
-    shorter and easier to type than the hex string.
-  * user The identity of the person who created the changeset. This is
-    a free-form field, but it most often contains a person’s name and
-    email address.
-  * date The date and time on which the changeset was created, and the
-    timezone in which it was created. (The date and time are local to
-    that timezone; they display what time and date it was for the
-    person who created the changeset.)
-  * summary The first line of the text message that the creator of the
-    changeset entered to describe the changeset.
+Besides filtering by commit identifiers, git allows you to easily
+filter the log output according to which files (or directories) are
+modified by listing them after "--" which is necessary to distinguish
+commit names from file names:
 
-The default output printed by “hg log” is purely a summary; it is
-missing a lot of detail.
+       $ git log -- Makefile
+       commit 72d4f10e4a27dbb09ace1503c20dbac1912ee451
+       Author: Bryan O'Sullivan <bos@serpentine.com>
+       Date:   Tue Sep 6 13:15:58 2005 -0700
+       
+           Get make to generate the final binary from a .o file.
+       
+       commit 0a633bf58b45fcf1a8299d3c82cd1fd26d3f48f2
+       Author: Bryan O'Sullivan <mpm@selenic.com>
+       Date:   Fri Aug 26 01:21:28 2005 -0700
+       
+           Create a makefile
 
-Figure [2.1][8] provides a graphical representation of the history of
-the hello repository, to make it a little easier to see which
-direction history is “flowing” in. We’ll be returning to this figure
-several times in this chapter and the chapter that follows.
+And "git log" can also filter based on the dates at which commits were
+created:
 
-* * *
+       $ git log --since="2 weeks ago" --until="yesterday"
 
-![PIC][9]   
+       [XXX: By default, "git log" displays author dates as "Date"
+       but then uses commit dates when given a --since option. That
+       seems like broken defaults to me. Why the inconsistency?]
 
-Figure 2.1: 
-Graphical history of the hello repository
+Another useful option is -n or --max-count which, unsurprisingly,
+limits the maximum number of commits to be displayed.
 
-* * *
+#### 2.4.5 More detailed information
 
-#### 2.4.1  Changesets, revisions, and talking to other people
+While the default information printed by “git log” is useful if you
+already know what you’re looking for, you may need to see more details
+of the change, such as the "diffstat" information with --stat:
 
-As English is a notoriously sloppy language, and computer science has
-a hallowed history of terminological confusion (why use one term when
-four will do?), revision control has a variety of words and phrases
-that mean the same thing. If you are talking about Mercurial history
-with other people, you will find that the word “changeset” is often
-compressed to “change” or (when written) “cset”, and sometimes a
-changeset is referred to as a “revision” or a “rev”.
-
-While it doesn’t matter what word you use to refer to the concept of
-“a changeset”, the identifier that you use to refer to “a specific
-changeset” is of great importance. Recall that the changeset field in
-the output from “hg log” identifies a changeset using both a number
-and a hexadecimal string.
-
-  * The revision number is only valid in that repository, 
-  * while the hex string is the permanent, unchanging identifier that
-    will always identify that exact changeset in every copy of the
-    repository.
-
-This distinction is important. If you send someone an email talking
-about “revision 33”, there’s a high likelihood that their revision 33
-will not be the same as yours. The reason for this is that a revision
-number depends on the order in which changes arrived in a repository,
-and there is no guarantee that the same changes will happen in the
-same order in different repositories. Three changes a,b,c can easily
-appear in one repository as 0,1,2, while in another as 1,0,2.
-
-Mercurial uses revision numbers purely as a convenient shorthand. If
-you need to discuss a changeset with someone, or make a record of a
-changeset for some other reason (for example, in a bug report), use
-the hexadecimal identifier.
-
-#### 2.4.2  Viewing specific revisions
-
-To narrow the output of “hg log” down to a single revision, use the -r
-(or --rev) option. You can use either a revision number or a long-form
-changeset identifier, and you can provide as many revisions as you
-want.
-
-       $ hg log -r 3   
-       changeset:   3:ff5d7b70a2a9   
-       user:        Bryan O'Sullivan <bos@serpentine.com>   
-       date:        Tue Sep 06 13:15:58 2005 -0700   
-       summary:     Get make to generate the final binary from a .o file.   
-       
-       $ hg log -r ff5d7b70a2a9   
-       changeset:   3:ff5d7b70a2a9   
-       user:        Bryan O'Sullivan <bos@serpentine.com>   
-       date:        Tue Sep 06 13:15:58 2005 -0700   
-       summary:     Get make to generate the final binary from a .o file.   
+       $ git log --stat --max-count=3
+       commit a1a0e8b392b17caf50325498df54802fe3c03710
+       Author: Bryan O'Sullivan <bos@serpentine.com>
+       Date:   Tue Sep 6 15:43:07 2005 -0700
        
-       $ hg log -r 1 -r 4   
-       changeset:   1:82e55d328c8c   
-       user:        mpm@selenic.com   
-       date:        Fri Aug 26 01:21:28 2005 -0700   
-       summary:     Create a makefile   
+           Trim comments.
        
-       changeset:   4:b57f9a090b62   
-       tag:         tip   
-       user:        Bryan O'Sullivan <bos@serpentine.com>   
-       date:        Tue Sep 06 15:43:07 2005 -0700   
-       summary:     Trim comments.   
+        hello.c |    8 ++------
+        1 files changed, 2 insertions(+), 6 deletions(-)
        
-
-If you want to see the history of several revisions without having to
-list each one, you can use range notation; this lets you express the
-idea “I want all revisions between a and b, inclusive”.
-
-       $ hg log -r 2:4   
-       changeset:   2:057d3c2d823c   
-       user:        Bryan O'Sullivan <bos@serpentine.com>   
-       date:        Tue Sep 06 13:15:43 2005 -0700   
-       summary:     Introduce a typo into hello.c.   
+       commit 72d4f10e4a27dbb09ace1503c20dbac1912ee451
+       Author: Bryan O'Sullivan <bos@serpentine.com>
+       Date:   Tue Sep 6 13:15:58 2005 -0700
        
-       changeset:   3:ff5d7b70a2a9   
-       user:        Bryan O'Sullivan <bos@serpentine.com>   
-       date:        Tue Sep 06 13:15:58 2005 -0700   
-       summary:     Get make to generate the final binary from a .o file.   
+           Get make to generate the final binary from a .o file.
        
-       changeset:   4:b57f9a090b62   
-       tag:         tip   
-       user:        Bryan O'Sullivan <bos@serpentine.com>   
-       date:        Tue Sep 06 15:43:07 2005 -0700   
-       summary:     Trim comments.   
+        Makefile |    2 ++
+        1 files changed, 2 insertions(+), 0 deletions(-)
        
-
-Mercurial also honours the order in which you specify revisions, so
-“hg log -r 2:4” prints 2,3,4 while “hg log -r 4:2” prints 4,3,2.
-
-#### 2.4.3  More detailed information
-
-While the summary information printed by “hg log” is useful if you
-already know what you’re looking for, you may need to see a complete
-description of the change, or a list of the files changed, if you’re
-trying to decide whether a changeset is the one you’re looking
-for. The “hg log” command’s -v (or --verbose) option gives you this
-extra detail.
-
-       $ hg log -v -r 3   
-       changeset:   3:ff5d7b70a2a9   
-       user:        Bryan O'Sullivan <bos@serpentine.com>   
-       date:        Tue Sep 06 13:15:58 2005 -0700   
-       files:       Makefile   
-       description:   
-       Get make to generate the final binary from a .o file.   
+       commit 13ed136b983a9c439eddeea8a1c2076cffbb685f
+       Author: Bryan O'Sullivan <bos@serpentine.com>
+       Date:   Tue Sep 6 13:15:43 2005 -0700
        
+           Introduce a typo into hello.c.
        
-
-If you want to see both the description and content of a change, add
-the -p (or --patch) option. This displays the content of a change as a
-unified diff (if you’ve never seen a unified diff before, see
-section [12.4][10] for an overview).
-
-       $ hg log -v -p -r 2   
-       changeset:   2:057d3c2d823c   
-       user:        Bryan O'Sullivan <bos@serpentine.com>   
-       date:        Tue Sep 06 13:15:43 2005 -0700   
-       files:       hello.c   
-       description:   
-       Introduce a typo into hello.c.   
+        hello.c |    2 +-
+        1 files changed, 1 insertions(+), 1 deletions(-)
+
+Or perhaps you'd like to see the actual patch content of each change,
+which you can get with -p. That commit with the word typo in its name
+looks suspicous, so let's tak a closer look. Remember that we can name
+it as master~3, HEAD~3, or any prefix of its commit identifier, (such
+as 13ed136b):
+
+       $ git log -p -n 1 13ed136b
+       commit 13ed136b983a9c439eddeea8a1c2076cffbb685f
+       Author: Bryan O'Sullivan <bos@serpentine.com>
+       Date:   Tue Sep 6 13:15:43 2005 -0700
        
+           Introduce a typo into hello.c.
        
-       diff -r 82e55d328c8c -r 057d3c2d823c hello.c   
-       --- a/hello.c Fri Aug 26 01:21:28 2005 -0700   
-       +++ b/hello.c Tue Sep 06 13:15:43 2005 -0700   
-       @@ -11,6 +11,6 @@   
+       diff --git a/hello.c b/hello.c
+       index ed55ec0..80b260c 100644
+       --- a/hello.c
+       +++ b/hello.c
+       @@ -11,6 +11,6 @@
+        
+        int main(int argc, char **argv)
+        {
+       -       printf("hello, world!\n");
+       +       printf("hello, world!\");
+               return 0;
+        }
+
+Of course, wanting to see all this information for a single commit is
+such a common operation that it's given its own name in git, "git
+show". So "git show 13ed136b" is a much easier way to get exactly the
+same output:
+
+       $ git show 13ed136b
+       commit 13ed136b983a9c439eddeea8a1c2076cffbb685f
+       Author: Bryan O'Sullivan <bos@serpentine.com>
+       Date:   Tue Sep 6 13:15:43 2005 -0700
        
-       int main(int argc, char ⋆⋆argv)   
-       {   
-       - printf("hello, world!∖n");   
-       + printf("hello, world!∖");   
-       return 0;   
-       }   
+           Introduce a typo into hello.c.
        
-
-### 2.5  All about command options
-
-Let’s take a brief break from exploring Mercurial commands to discuss
+       diff --git a/hello.c b/hello.c
+       index ed55ec0..80b260c 100644
+       --- a/hello.c
+       +++ b/hello.c
+       @@ -11,6 +11,6 @@
+        
+        int main(int argc, char **argv)
+        {
+       -       printf("hello, world!\n");
+       +       printf("hello, world!\");
+               return 0;
+        }
+
+### 2.5 All about command options
+
+Let’s take a brief break from exploring git commands to discuss
 a pattern in the way that they work; you may find this useful to keep
 in mind as we continue our tour.
 
-Mercurial has a consistent and straightforward approach to dealing
+Git has a consistent and straightforward approach to dealing
 with the options that you can pass to commands. It follows the
 conventions for options that are common to modern Linux and Unix
 systems.
 
-  * Every option has a long name. For example, as we’ve already seen,
-    the “hg log” command accepts a --rev option.
-  * Most options have short names, too. Instead of --rev, we can use
-    -r. (The reason that some options don’t have short names is that
-    the options in question are rarely used.)
-  * Long options start with two dashes (e.g. --rev), while short
-    options start with one (e.g. -r).
+  * Most options have long names. For example, as we’ve already seen,
+    the “git log" command accepts a `--max-count=<number>` option.
+  * Some options have short, single-character names. Often these are
+    aliases for long commands, (such as `-n <number>` instead of
+    `--max-count=<number>`), but sometimes the option exists in
+    short-form with no long-form equivalent, (such as `-p`). [XXX: It
+    wouldn't hurt to fix this by adding `--patch`, etc. right?]
+  * Long options start with two dashes (e.g. `--max-count`), while short
+    options start with one (e.g. `-n`).
+
   * Option naming and usage is consistent across commands. For
-    example, every command that lets you specify a changeset ID or
-    revision number accepts both -r and --rev arguments.
-
-In the examples throughout this book, I use short options instead of
-long. This just reflects my own preference, so don’t read anything
-significant into it.
-
-Most commands that print output of some kind will print more output
-when passed a -v (or --verbose) option, and less when passed -q (or
---quiet).
-
-### 2.6  Making and reviewing changes
-
-Now that we have a grasp of viewing history in Mercurial, let’s take a
-look at making some changes and examining them.
-
-The first thing we’ll do is isolate our experiment in a repository of
-its own. We use the “hg clone” command, but we don’t need to clone a
-copy of the remote repository. Since we already have a copy of it
-locally, we can just clone that instead. This is much faster than
-cloning over the network, and cloning a local repository uses less
-disk space in most cases, too.
-
-       $ cd ..   
-       $ hg clone hello my-hello   
-       2 files updated, 0 files merged, 0 files removed, 0 files unresolved   
-       $ cd my-hello
-
-As an aside, it’s often good practice to keep a “pristine” copy of a
-remote repository around, which you can then make temporary clones of
-to create sandboxes for each task you want to work on. This lets you
-work on multiple tasks in parallel, each isolated from the others
-until it’s complete and you’re ready to integrate it back. Because
-local clones are so cheap, there’s almost no overhead to cloning and
-destroying repositories whenever you want.
-
-In our my-hello repository, we have a file hello.c that contains the
-classic “hello, world” program. Let’s use the ancient and venerable
-sed command to edit this file so that it prints a second line of
-output. (I’m only using sed to do this because it’s easy to write a
-scripted example this way. Since you’re not under the same constraint,
-you probably won’t want to use sed; simply use your preferred text
-editor to do the same thing.)
-
-       $ sed -i '/printf/a∖∖tprintf("hello again!∖∖n");' hello.c
-
-Mercurial’s “hg status” command will tell us what Mercurial knows
-about the files in the repository.
-
-       $ ls   
-       Makefile  hello.c   
-       $ hg status   
-       M hello.c
-
-The “hg status” command prints no output for some files, but a line
-starting with “M” for hello.c. Unless you tell it to, “hg status” will
-not print any output for files that have not been modified.
-
-The “M” indicates that Mercurial has noticed that we modified
-hello.c. We didn’t need to inform Mercurial that we were going to
-modify the file before we started, or that we had modified the file
-after we were done; it was able to figure this out itself.
+    example, every command that lets you specify a commit identifier
+    or range will accept the same expressions, (HEAD~3,
+    origin..master, 72d4f10e, etc), while any command that can be
+    limited by paths will accept the same expressions ("-- doc/
+    some-file.c"), etc.
+
+Many commands that print output of some kind can be made more quiet by
+passing the -q or --quiet options.
+
+### 2.6 Making and reviewing changes
+
+Now that we have a grasp of viewing history in git, let’s take a look
+at making some changes and examining them. You should be working
+within the "hello" directory that we originally cloned.
+
+In the repository, we have a file hello.c that contains the classic
+“hello, world” program. But this program currently has a syntax error
+and won't compile, (there's a missing 'n' between the '\' and the '"'
+on the line containing printf). Let's fix that now. You can use a text
+editor to correct the file, or you can copy-and-paste the sed command
+below:
+
+       $ sed -i '/printf/s/\\"/\\n"/' hello.c
+
+After you've made that change, the “git status” command will tell you
+what git knows about the files in the repository.
+
+       $ ls 
+       hello.c  Makefile
+       $ git status
+       # On branch master
+       # Changed but not updated:
+       #   (use "git add <file>..." to update what will be committed)
+       #
+       #       modified:   hello.c
+       #
+       no changes added to commit (use "git add" and/or "git commit -a")
+
+First "git status" tells us that the current branch is "master". This
+means that the master branch is what will be updated when we create a
+new commit.
+
+Note: In git a branch is a very simple notion---it's simply a name
+that points to a particular commit, (literally nothing more than a
+pointer---look at the contents of .git/refs/heads/master if you're
+curious). The fact that a branch is so light is what makes the
+creation of new branches an instantaneous operation in git. Together
+with the ease of merging, git makes branches a joy to work with. But
+we'll delay talk of branching and merging to a future chapter.
+
+Next “git status” prints a line with "modified" for each modified
+file---in this case just hello.c. The “git status” command will not
+print any output for files that have not been modified.
+
+Notice that we didn’t need to inform git that we were going to modify
+the file before we started, or that we had modified the file after we
+were done; it was able to figure this out itself.
 
 It’s a little bit helpful to know that we’ve modified hello.c, but we
 might prefer to know exactly what changes we’ve made to it. To do
-this, we use the “hg diff” command.
-
-       $ hg diff   
-       diff -r b57f9a090b62 hello.c   
-       --- a/hello.c Tue Sep 06 15:43:07 2005 -0700   
-       +++ b/hello.c Sun Jun 17 18:05:50 2007 +0000   
-       @@ -8,5 +8,6 @@ int main(int argc, char ⋆⋆argv)   
-       int main(int argc, char ⋆⋆argv)   
-       {   
-       printf("hello, world!∖");   
-       + printf("hello again!∖n");   
-       return 0;   
-       }
-
-### 2.7  Recording changes in a new changeset
-
-We can modify files, build and test our changes, and use “hg status”
-and “hg diff” to review our changes, until we’re satisfied with what
+this, we use the “git diff” command.
+
+       $ git diff
+       diff --git a/hello.c b/hello.c
+       index 9a3ff79..ea364d3 100644
+       --- a/hello.c
+       +++ b/hello.c
+       @@ -7,6 +7,6 @@
+        
+        int main(int argc, char **argv)
+        {
+       -       printf("hello, world!\");
+       +       printf("hello, world!\n");
+               return 0;
+        }
+
+### 2.7 Recording changes in a new commit
+
+We can modify files, build and test our changes, and use “git status”
+and “git diff” to review our changes, until we’re satisfied with what
 we’ve done and arrive at a natural stopping point where we want to
-record our work in a new changeset.
-
-The “hg commit” command lets us create a new changeset; we’ll usually
-refer to this as “making a commit” or “committing”.
-
-#### 2.7.1  Setting up a username
-
-When you try to run “hg commit” for the first time, it is not
-guaranteed to succeed. Mercurial records your name and address with
-each change that you commit, so that you and others will later be able
-to tell who made each change. Mercurial tries to automatically figure
-out a sensible username to commit the change with. It will attempt
-each of the following methods, in order:
-
-  1. If you specify a -u option to the “hg commit” command on the
-     command line, followed by a username, this is always given the
-     highest precedence.
-  2. If you have set the HGUSER environment variable, this is checked next. 
-  3. If you create a file in your home directory called .hgrc, with a
-     username entry, that will be used next. To see what the contents
-     of this file should look like, refer to section [2.7.1][11]
-     below.
-  4. If you have set the EMAIL environment variable, this will be used
-     next.
-  5. Mercurial will query your system to find out your local user name
-     and host name, and construct a username from these
-     components. Since this often results in a username that is not
-     very useful, it will print a warning if it has to do this.
-
-If all of these mechanisms fail, Mercurial will fail, printing an
-error message. In this case, it will not let you commit until you set
-up a username.
-
-You should think of the HGUSER environment variable and the -u option
-to the “hg commit” command as ways to override Mercurial’s default
-selection of username. For normal use, the simplest and most robust
-way to set a username for yourself is by creating a .hgrc file; see
-below for details.
-
-##### Creating a Mercurial configuration file
-
-To set a user name, use your favourite editor to create a file called
-.hgrc in your home directory. Mercurial will use this file to look up
-your personalised configuration settings. The initial contents of your
-.hgrc should look like this.
-
-       # This is a Mercurial configuration file.   
-       [ui]   
-       username = Firstname Lastname <email.address@domain.net>
-
-The “[ui]” line begins a section of the config file, so you can read
-the “username = ...” line as meaning “set the value of the username
-item in the ui section”. A section continues until a new section
-begins, or the end of the file. Mercurial ignores empty lines and
-treats any text from “#” to the end of a line as a comment.
-
-##### Choosing a user name
-
-You can use any text you like as the value of the username config
-item, since this information is for reading by other people, but for
-interpreting by Mercurial. The convention that most people follow is
-to use their name and email address, as in the example above.
-
-Note: Mercurial’s built-in web server obfuscates email addresses, to
-make it more difficult for the email harvesting tools that spammers
-use. This reduces the likelihood that you’ll start receiving more junk
-email if you publish a Mercurial repository on the web.
-
-#### 2.7.2  Writing a commit message
-
-When we commit a change, Mercurial drops us into a text editor, to
+record our work in a new commit.
+
+If you'd like, go ahead and build the program now with "make" and run
+it to ensure it works. Everything should look good so we're just about
+ready to make a commit. Unsurprisingly, we'll be using "git commit" to
+do this.
+
+#### 2.7.1 Introducing yourself to git
+
+Before you run "git commit" though, you should introduce yourself to
+git.  Git records your name and email address with each change that
+you commit, (as both author and committer unless you tell it
+otherwise), so that you and others will later be able to tell who made
+each change.
+
+Git tries to automatically figure out a sensible name and address to
+attribute to both author and committer if you haven't explicitly told
+it a name and address. And it tries a lot, (detailed below). If you're
+not interested in these details, you might want to skip to the next
+section which explains how to avoid all this guesswork and tell git
+what your name and email address are.
+
+Here is a list of all the guessing that git will attempt. It will
+attempt each of the following methods, in order, (stopping for each of
+the author and committer name and email as soon as a value is found):
+
+  1. If you specify a --author option to the “git commit” command on
+     the command line, followed by a `"Real Name <email@example.com>"`
+     string, then this name and addresss will be used for the author
+     fields. The committer fields will still be determined as
+     below. This option is very helpful for when applying a commit
+     originally authored by someone other than yourself.
+  2. If any of the `GIT_AUTHOR_NAME`, `GIT_AUTHOR_EMAIL`,
+     `GIT_COMMITTER`_NAME, or `GIT_COMMITER_EMAIL` environment variables
+     are set, then those values will be used for the corresponding
+     fields.
+  3. If you have a file in your home directory called .gitconfig, with
+     name or email settings in the [user] section, then these values
+     will be used to set any remaining author and committer
+     fields. For more details on the contents of this file, refer to
+     section 2.7.1 below.
+  4. If you have a file in the local repository called .git/config,
+     again with name or email settings in the [user] section, then
+     these values will be used to set any remaining author and
+     committer fields.
+  5. If you have set the `EMAIL` environment variable, this will be used
+     to set author and committer email addresses if still unset.
+  6. git will query your system to find out your real name from
+     available GECOS field and your username, hostname, and domain to
+     construct an email address, (or at least an identifier resembling
+     an email address).
+
+If all of these mechanisms fail, "git commit" will fail, printing an
+error message instructing you how to use "git config" to tell git your
+name and email address.
+
+You should think of the `GIT_AUTHOR`/`COMMITER_NAME`/`EMAIL` environment
+variables and the --author option to the “git commit” command as ways
+to override git’s default selection. For normal use, the simplest and
+most robust way to set your information is by creating a .gitconfig
+file, (either manually or with the "git config" command); see below
+for details.
+
+##### Creating a git configuration file
+
+To set your name and email address, just use the following commands:
+
+       git config --global user.name "Your Name"
+       git config --global user.email "you@example.com"
+
+The --global option means that this command will set global
+information, (affecting all repositories on this machine), in the
+.gitconfig file in your home directory. Alternately, you could omit
+the --global which would make the change take effect only in the local
+repository. This is convenient if you want to have different email
+addresses associated with different projects, for example.
+
+Of course, git's configuration file is a simple-to-edit plain-text
+file, so instead of using the above commands, you can also just edit
+the files directly. Use your favorite editor to create a file called
+.gitconfig in your home directory, (or if you ran the above commands
+then it will be there already). The initial contents of your
+.gitconfig should look like this.
+
+       # This is a git configuration file. 
+       [user]
+               name = Your Name
+               email = you@example.com
+
+Similarly, you can make a repository-specific configuration by editing
+.git/config in the local repository. It will already have some
+sections present, (created by the "git clone"), just add a [user]
+section as above.
+
+The “[user]” line begins a section of the config file, so you can read
+the “name = ...” line as meaning “set the value of the name item in
+the user section”. This is the same notion expressed with the
+"user.name" syntax on the git-config command line.  A section
+continues until a new section begins, or the end of the file. Git
+ignores empty lines and treats any text from “#” to the end of a line
+as a comment.
+
+##### Choosing your name and email
+
+You can use any text you like as the value of the name and email
+configuration items, since this information is for reading by other
+people, not for interpreting by git. It is conventional to use your
+actual name as well as a valid email address. But some people, (notably
+Linus Torvalds, the original author of git), actually like the default
+username@hostname convention that git falls back on without any
+additional information about an email address. There's no requirement
+that the email address actually be valid, and perhaps it's useful to
+be reminded which machine was used to create particular commits. So
+choose the name and email you wish, or follow a particular project's
+conventions.
+
+#### 2.7.2 Writing a commit message
+
+When we commit a change, git drops us into a text editor to
 enter a message that will describe the modifications we’ve made in
-this changeset. This is called the commit message. It will be a record
-for readers of what we did and why, and it will be printed by “hg log”
+this commit. This is called the commit message. It will be a record
+for readers of what we did and why, and it will be printed by “git log”
 after we’ve finished committing.
 
-       $ hg commit
-
-The editor that the “hg commit” command drops us into will contain an
-empty line, followed by a number of lines starting with “HG:”.
+       $ git commit -a
+
+Note: The -a on the command-line instructs git to commit the new
+content of *all* tracked files that have been modified. This is a
+convenience over explicitly listing filenames to be committed on the
+`git commit` command line. It is useful to use `git commit <files>`
+when there is a need to commit only some subset of the files that have
+been modified.
+
+If new files need to be committed for the first time, just use `git
+add <file>` before `git commit -a`. If a file needs to be removed,
+just remove it as normal before committing and `git commit -a` will
+notice that---it does not need to be explicitly told about the
+removal.
+
+The editor that the `git commit` command drops us into will contain an
+empty line, followed by a number of lines starting with “#”. These
+lines contain the same information as seen in `git status` before:
+
+       empty line
+       # Please enter the commit message for your changes.
+       # (Comment lines starting with '#' will not be included)
+       # On branch master
+       # Changes to be committed:
+       #   (use "git reset HEAD <file>..." to unstage)
+       #
+       #       modified:   hello.c
+       #
+       # Untracked files:
+       #   (use "git add <file>..." to include in what will be committed)
+       #
+       #       hello
+       #       hello.o
+
+Notice that two untracked files (hello and hello.o) have now appeared
+from the build process. Git is reminding us of these in case we
+intended to commit them as well, (in which case we would need to "git
+add" them). We don't actually want to commit these files so we will
+ignore them for now, (and we could tell git to ignore them as well by
+listing them in a .gitignore file).
+
+Git will ignore all lines in the commit message that start with “#”;
+it uses them only to give us information on the commit. Modifying or
+deleting these lines has no effect.
 
-       empty line   
-       HG: changed hello.c
+#### 2.7.3 Writing a good commit message
 
-Mercurial ignores the lines that start with “HG:”; it uses them only
-to tell us which files it’s recording changes to. Modifying or
-deleting these lines has no effect.
+A good commit message will generally have a single line that
+summarizes the commit, a blank line, and then one or more pargraphs
+with supporting detail. Since many tools only print the first line of
+a commit message by default, it’s important that the first line stands
+alone.
 
-#### 2.7.3  Writing a good commit message
+One example of a first-line-only viewer is "git log
+--pretty=short". Other examples include graphical history viewers such
+as gitk and gitview, and web-based viewers such as gitweb and cgit.
 
-Since “hg log” only prints the first line of a commit message by
-default, it’s best to write a commit message whose first line stands
-alone. Here’s a real example of a commit message that doesn’t follow
+Here’s a real example of a commit message that doesn’t follow
 this guideline, and hence has a summary that is not readable.
 
-       changeset:   73:584af0e231be   
-       user:        Censored Person <censored.person@example.org>   
-       date:        Tue Sep 26 21:37:07 2006 -0700   
-       summary:     include buildmeister/commondefs.   Add an exports and install
+       $ git log --pretty=short
+       commit 3ef5535144da88a854f7930503845cd44506c2e2
+       Author: Censored Person <censored.person@example.org>
+       
+           include buildmeister/commondefs.   Add an exports and install
 
 As far as the remainder of the contents of the commit message are
-concerned, there are no hard-and-fast rules. Mercurial itself doesn’t
+concerned, there are no hard-and-fast rules. git itself doesn’t
 interpret or care about the contents of the commit message, though
 your project may have policies that dictate a certain kind of
 formatting.
 
 My personal preference is for short, but informative, commit messages
 that tell me something that I can’t figure out with a quick glance at
-the output of “hg log --patch”.
+the output of "git log --stat" or “git log -p", (so repeating the list
+of all modified files is not useful, for example).
 
-#### 2.7.4  Aborting a commit
+#### 2.7.4 Aborting a commit
 
 If you decide that you don’t want to commit while in the middle of
 editing a commit message, simply exit from your editor without saving
 the file that it’s editing. This will cause nothing to happen to
 either the repository or the working directory.
 
-If we run the “hg commit” command without any arguments, it records
-all of the changes we’ve made, as reported by “hg status” and “hg
-diff”.
-
-#### 2.7.5  Admiring our new handiwork
-
-Once we’ve finished the commit, we can use the “hg tip” command to
-display the changeset we just created. This command produces output
-that is identical to “hg log”, but it only displays the newest
-revision in the repository.
-
-       $ hg tip -vp   
-       changeset:   5:fa1321bf0c80   
-       tag:         tip   
-       user:        Bryan O'Sullivan <bos@serpentine.com>   
-       date:        Sun Jun 17 18:05:50 2007 +0000   
-       files:       hello.c   
-       description:   
-       Added an extra line of output   
+#### 2.7.5 Admiring our new handiwork
+
+Once we’ve finished the commit, we can use the “git show” command to
+display the commit we just created. As discussed previously, this
+command produces output that is identical to “git log -p”, but for
+only a single revision, (and the most recent revision by default):
+
+       $ git show
+       commit fd21e5d6c5eedee70137229ebf348c25181812ab
+       Author: Carl Worth <cworth@cworth.org>
+       Date:   Fri Sep 28 12:50:16 2007 -0700
+       
+           Fixed the typo so the program actuall complies now.
        
+       diff --git a/hello.c b/hello.c
+       index 9a3ff79..ea364d3 100644
+       --- a/hello.c
+       +++ b/hello.c
+       @@ -7,6 +7,6 @@
+        
+        int main(int argc, char **argv)
+        {
+       -       printf("hello, world!\");
+       +       printf("hello, world!\n");
+               return 0;
+        }
+
+Note that you will not see the same commit identifier for your commit,
+even if the change you made is identical to mine. The commit
+identifier incorporates not only the contents of the files, but commit
+message, the author and committer names and emails, and the author and
+commit dates. (OK, so now you probably know enough to be able to guess
+the right command to produce a commit with exactly the commit
+identifier shown above. Can you do it?)
+
+#### 2.7.6 Fixing up a broken commit (before anyone else sees it)
+
+So now that we've cloned a local repository, made a change to the
+code, setup our name and email address, and made a careful commit,
+we're just about ready to share our change with the world. But wait,
+that commit message has some really embarrassing misspellings in
+it. Wouldn't it be nice to touch those up before I post this commit
+with a never-to-be-changed again commit identifier?
+
+This is the exact situation for which "git commit --amend" was
+invented. So I can just run that now and fix the broken commit
+message:
+
+       $ git commit --amend
+
+Here's the final result:
+
+       $ git show
+       commit 3c54ac672ec1130b36837f1b708054a7a1d402de
+       Author: Carl Worth <cworth@cworth.org>
+       Date:   Fri Sep 28 12:50:16 2007 -0700
        
-       diff -r b57f9a090b62 -r fa1321bf0c80 hello.c   
-       --- a/hello.c Tue Sep 06 15:43:07 2005 -0700   
-       +++ b/hello.c Sun Jun 17 18:05:50 2007 +0000   
-       @@ -8,5 +8,6 @@ int main(int argc, char ⋆⋆argv)   
-       int main(int argc, char ⋆⋆argv)   
-       {   
-       printf("hello, world!∖");   
-       + printf("hello again!∖n");   
-       return 0;   
-       }   
+           Fixed the typo so the program actually compiles now.
        
+       diff --git a/hello.c b/hello.c
+       index 9a3ff79..ea364d3 100644
+       --- a/hello.c
+       +++ b/hello.c
+       @@ -7,6 +7,6 @@
+        
+        int main(int argc, char **argv)
+        {
+       -       printf("hello, world!\");
+       +       printf("hello, world!\n");
+               return 0;
+        }
+
+Note that we didn't use "commit -a" this time. This means that "git
+commit --amend" will amend only the commit message and not any of the
+actual files being tracked, (even if some of them had been modified
+between the commits).
+
+It's also possible to use "git commit -a --amend" to similarly fix up
+mistakes noticed in code. That will replace the most recent commit
+with a different commit based on any new changes to files.
+
+I do feel a little hesitant to mention "git commit -a --amend". It's a
+handy command for fixing up something like a misspelling in a comment
+in the code. But if there is anything more significant than that, then
+it would generally be better to create an additional commit rather
+than amending an existing commit. This is important for several
+reasons:
+
+  * The amend operation will destroy a state that was previously saved
+    in a commit. If it's just the commit message being changed, then
+    that's no big deal. But if the contents are being amended, then a
+    mistake could eliminate something valuable.
+
+  * All commits should be logically independent and as small as
+    possible. Abusing "git commit -a --amend" can cause a small commit
+    to grow and acquire unrelated changes.
+
+It's worth emphasizing the value of minimal, independent commits. The
+smaller the changes are the more useful the history will be when
+actually using the history, not just viewing it. This is particularly
+important when doing "git bisect"---that's a powerful tool for
+isolating a single commit that introduces a bug. And it's much more
+helpful when the commit it isolates is as small as possible.
+
+One advantage of using git over some other systems is that the commit
+speed is blazingly fast. The tool doesn't punish you at all for
+committing as often as you get our project into a state that is worth
+saving. "Commit early, commit often" is a well-supported mode of
+operation with git.
+
+### 2.8 Sharing changes
+
+We mentioned earlier that repositories in git are
+self-contained. This means that the commit we just created exists
+only in our hello repository. Let’s look at a few ways that we can
+propagate this change into other repositories.
 
-We refer to the newest revision in the repository as the tip revision,
-or simply the tip.
+#### 2.8.1 Pulling changes from the original repository
 
-### 2.8  Sharing changes
+Recall that in Section 2.3.2 we made several local clones of the hello
+repository before we made any commits. This allows us to simulate what
+happens when upstream changes have been committed after you originally
+cloned.
 
-We mentioned earlier that repositories in Mercurial are
-self-contained. This means that the changeset we just created exists
-only in our my-hello repository. Let’s look at a few ways that we can
-propagate this change into other repositories.
+The simplest, (and quite common), scenario is that you inherently
+trust any changes in the original repository and you want to pull
+these directly into your clone. This might be the case if you are
+using git simply to track the progress of a project without making any
+changes.
 
-#### 2.8.1  Pulling changes from another repository
-
-To get started, let’s clone our original hello repository, which does
-not contain the change we just committed. We’ll call our temporary
-repository hello-pull.
-
-       $ cd ..   
-       $ hg clone hello hello-pull   
-       2 files updated, 0 files merged, 0 files removed, 0 files unresolved
-
-We’ll use the “hg pull” command to bring changes from my-hello into
-hello-pull. However, blindly pulling unknown changes into a repository
-is a somewhat scary prospect. Mercurial provides the “hg incoming”
-command to tell us what changes the “hg pull” command would pull into
-the repository, without actually pulling the changes in.
-
-       $ cd hello-pull   
-       $ hg incoming ../my-hello   
-       comparing with ../my-hello   
-       searching for changes   
-       changeset:   5:fa1321bf0c80   
-       tag:         tip   
-       user:        Bryan O'Sullivan <bos@serpentine.com>   
-       date:        Sun Jun 17 18:05:50 2007 +0000   
-       summary:     Added an extra line of output   
+In this case, the operation is as simple as just calling "git pull":
+
+       $ cd ../hello-pull
+       $ git pull
+       remote: Generating pack...
+       Unpacking 3 objects...
+        100% (3/3) done
+       remote: Done counting 5 objects.
+       Result has 3 objects.
+       Deltifying 3 objects...
+        100% remote: (3/3) done
+       Total 3 (delta 1), reused 0 (delta 0)
+       * refs/remotes/origin/master: fast forward to branch 'master' of /tmp/hello
+         old..new: a1a0e8b..3c54ac6
+       Updating a1a0e8b..3c54ac6
+       Fast forward
+        hello.c |    2 +-
+        1 files changed, 1 insertions(+), 1 deletions(-)
+
+XXX: Git is fairly noisy here, but a user has little need to care
+about the several stages of operation involved here. As a tutorial
+writer I'd like to say "ignore all that progress stuff, and look at
+where the stat information starts" but it's hard for a new user to
+even be able to understand that. I think it would be ideal if all of
+the progress-tracking spew were reduced to a single line. Something
+like "Computing (100%) Transferring (100%)" or whatever.
+
+After (lots!) of progresss indication, git gives a report of which
+files were modified, (which is very useful for getting a quick feel
+for what happened). If you would like more details on what changes
+came in, git provides a range that is perfect for examining. Let's
+take a look (again, the commit identifiers will be different for you
+--- just copy-and-paste the range that git prints):
+
+       $ git log a1a0e8b..3c54ac6
+       commit 3c54ac672ec1130b36837f1b708054a7a1d402de
+       Author: Carl Worth <cworth@cworth.org>
+       Date:   Fri Sep 28 12:50:16 2007 -0700
        
+           Fixed the typo so the program actually compiles now.
 
-(Of course, someone could cause more changesets to appear in the
-repository that we ran “hg incoming” in, before we get a chance to “hg
-pull” the changes, so that we could end up pulling changes that we
-didn’t expect.)
+As expected, we received just the one commit.
 
-Bringing changes into a repository is a simple matter of running the
-“hg pull” command, and telling it which repository to pull from.
+So that's all that's needed in the common case. Just run "git pull"
+everytime you want to pull in new changes that have landed in the
+upstream repository.
 
-       $ hg tip   
-       changeset:   4:b57f9a090b62   
-       tag:         tip   
-       user:        Bryan O'Sullivan <bos@serpentine.com>   
-       date:        Tue Sep 06 15:43:07 2005 -0700   
-       summary:     Trim comments.   
-       
-       $ hg pull ../my-hello   
-       pulling from ../my-hello   
-       searching for changes   
-       adding changesets   
-       adding manifests   
-       adding file changes   
-       added 1 changesets with 1 changes to 1 files   
-       (run 'hg update' to get a working copy)   
-       $ hg tip   
-       changeset:   5:fa1321bf0c80   
-       tag:         tip   
-       user:        Bryan O'Sullivan <bos@serpentine.com>   
-       date:        Sun Jun 17 18:05:50 2007 +0000   
-       summary:     Added an extra line of output   
-       
+Note: Mercurial users who are reading this might wonder if there's a
+need for the equivalent of "hg update" after doing a "git pull". And
+the answer is no. Unlike mercurial, "git pull", (and "git merge") will
+automatically update the working-directory files as necessary.
 
-As you can see from the before-and-after output of “hg tip”, we have
-successfully pulled changes into our repository. There remains one
-step before we can see these changes in the working directory.
-
-#### 2.8.2  Updating the working directory
-
-We have so far glossed over the relationship between a repository and
-its working directory. The “hg pull” command that we ran in
-section [2.8.1][12] brought changes into the repository, but if we
-check, there’s no sign of those changes in the working directory. This
-is because “hg pull” does not (by default) touch the working
-directory. Instead, we use the “hg update” command to do this.
-
-       $ grep printf hello.c   
-       printf("hello, world!∖");   
-       $ hg update tip   
-       1 files updated, 0 files merged, 0 files removed, 0 files unresolved   
-       $ grep printf hello.c   
-       printf("hello, world!∖");   
-       printf("hello again!∖n");
-
-It might seem a bit strange that “hg pull” doesn’t update the working
-directory automatically. There’s actually a good reason for this: you
-can use “hg update” to update the working directory to the state it
-was in at any revision in the history of the repository. If you had
-the working directory updated to an old revision—to hunt down the
-origin of a bug, say—and ran a “hg pull” which automatically updated
-the working directory to a new revision, you might not be terribly
-happy.
-
-However, since pull-then-update is such a common thing to do,
-Mercurial lets you combine the two by passing the -u option to “hg
-pull”.
-
-       hg pull -u
-
-If you look back at the output of “hg pull” in section [2.8.1][12]
-when we ran it without -u, you can see that it printed a helpful
-reminder that we’d have to take an explicit step to update the working
-directory:
-
-       (run 'hg update' to get a working copy)
-
-To find out what revision the working directory is at, use the “hg
-parents” command.
-
-       $ hg parents   
-       changeset:   5:fa1321bf0c80   
-       tag:         tip   
-       user:        Bryan O'Sullivan <bos@serpentine.com>   
-       date:        Sun Jun 17 18:05:50 2007 +0000   
-       summary:     Added an extra line of output   
-       
-
-If you look back at figure [2.1][8], you’ll see arrows connecting each
-changeset. The node that the arrow leads from in each case is a
-parent, and the node that the arrow leads to is its child. The working
-directory has a parent in just the same way; this is the changeset
-that the working directory currently contains.
-
-To update the working directory to a particular revision, give a
-revision number or changeset ID to the “hg update” command.
-
-       $ hg update 2   
-       2 files updated, 0 files merged, 0 files removed, 0 files unresolved   
-       $ hg parents   
-       changeset:   2:057d3c2d823c   
-       user:        Bryan O'Sullivan <bos@serpentine.com>   
-       date:        Tue Sep 06 13:15:43 2005 -0700   
-       summary:     Introduce a typo into hello.c.   
-       
-       $ hg update   
-       2 files updated, 0 files merged, 0 files removed, 0 files unresolved
-
-If you omit an explicit revision, “hg update” will update to the tip
-revision, as shown by the second call to “hg update” in the example
-above.
-
-#### 2.8.3  Pushing changes to another repository
-
-Mercurial lets us push changes to another repository, from the
-repository we’re currently visiting. As with the example of “hg pull”
-above, we’ll create a temporary repository to push our changes into.
-
-       $ cd ..   
-       $ hg clone hello hello-push   
-       2 files updated, 0 files merged, 0 files removed, 0 files unresolved
-
-The “hg outgoing” command tells us what changes would be pushed into
-another repository.
-
-       $ cd my-hello   
-       $ hg outgoing ../hello-push   
-       comparing with ../hello-push   
-       searching for changes   
-       changeset:   5:fa1321bf0c80   
-       tag:         tip   
-       user:        Bryan O'Sullivan <bos@serpentine.com>   
-       date:        Sun Jun 17 18:05:50 2007 +0000   
-       summary:     Added an extra line of output   
-       
+#### 2.8.2 Using fetch and merge separately to pull
 
-And the “hg push” command does the actual push. 
+Sometimes you may not know if you want to pull in the changes from the
+remote repository or not. It's useful to be able to examine them
+before accepting them into our branch. The "git pull" command shown in
+the previous section is conceptually the combination of two command,
+"git fetch" and "git merge". We can use these commands separately to
+examine the change before accepting it.
 
-       $ hg push ../hello-push   
-       pushing to ../hello-push   
-       searching for changes   
-       adding changesets   
-       adding manifests   
-       adding file changes   
-       added 1 changesets with 1 changes to 1 files
+So let's do that within the hello-fetch clone we made earlier. First
+we will do the fetch:
 
-As with “hg pull”, the “hg push” command does not update the working
-directory in the repository that it’s pushing changes into. (Unlike
-“hg pull”, “hg push” does not provide a -u option that updates the
-other repository’s working directory.)
+       $ cd ../hello-fetch
+       $ git fetch
+       remote: Generating pack...
+       Unpacking 3 objects...
+       remote: Done counting 5 objects.
+       Result has 3 objects.
+       Deltifying 3 objects...
+        100% remote: (3/3) done
+       Total 3 (delta 1), reused 0 (delta 0)
+        100% (3/3) done
+       * refs/remotes/origin/master: fast forward to branch 'master' of /tmp/hello/
+         old..new: a1a0e8b..3c54ac6
+
+You may notice that the output here looks very much like the first
+portion of the output from "git pull". This is no coincidence.  The
+new changes have been "fetched" into the current repository and are
+stored into "origin/master" and have not been into the current
+"master" branch. Remember that "master" is our current branch. So now,
+"origin/master" is the state of the master branch that exists in the
+"origin" repository, (the one we cloned from).
+
+The most convenient way to examine the fetched changes is with the
+"master..origin" range notation:
+
+       $ git log master..origin
+       commit 3c54ac672ec1130b36837f1b708054a7a1d402de
+       Author: Carl Worth <cworth@cworth.org>
+       Date:   Fri Sep 28 12:50:16 2007 -0700
+       
+           Fixed the typo so the program actually compiles now.
+
+Another helpful way of visualizing what happened with "git fetch" here
+is to run "gitk --all", which gives a graphical representation of all
+branches. Here is what it would look like:
+
+[[img gitk-fetch.png]]
+
+Notice that origin/master points to a single commit that was committed
+on top of the state pointed to by the "master" branch.
+
+Let's assume we are happy with the changes and we want to include them
+into our master branch. To do this we simply run "git merge origin":
+
+       $ git merge origin
+       Updating a1a0e8b..3c54ac6
+       Fast forward
+        hello.c |    2 +-
+        1 files changed, 1 insertions(+), 1 deletions(-)
+
+Again, you'll see that this precisely matches the final portion of the
+output from "git pull". Using "git fetch" and "git merge" let us
+achieve exactly what "git pull" did, but we were able to stop in the
+middle to examine the situation, (and we could have decided to reject
+the changes and not merge them---leaving our master branch unchanged).
+
+##### On merges and "fast forward"
+
+You'll notice that we've been seeing the phrase "fast forward" several
+times. This is a special-case operation performed by "git merge" where
+a branch can be advanced along a linear sequence. This happens
+whenever you pull changes that build directly on top of the same
+commit you have as your most recent commit. In other words, there was
+never any divergence or simultaneous commits created in parallel in
+multiple repositories. If there had been parallel commits, then "git
+merge" would actually introduce a new merge commit to tie the two
+commits together.
+
+When a non-fast-forward merge occurs, there is always the possibility
+that a conflict occurs. In this case, "git merge" will leave conflict
+markers in the files and instruct you to resolve the conflicts. When
+you are finished, you would issue a "git commit -a" to create the
+merge commit.
+
+#### 2.8.3 Using "git remote" to pull changes from other repositories
+
+We've already described how "git pull" will pull in changes from the
+repository which was the origin of the clone operation. Git also
+provides excellent support for pulling changes from any other
+repository as well, (distributed, rather than centralized
+development).
+
+If you have a situation where you want to pull a single time from some
+repository, then you can simply give the path or URL of the repository
+on the "git pull" command line. However, it's often the case that if
+you want to pull changes from a repository once, you'll want to pull
+changes from that same repository again in the future. This is where
+the "git remote" notion is extremely useful---it allows you to
+associate simple names, (and behaviors), with remote repository URLs
+
+We've already seen one instance of "git remote" which is the creation
+of the "origin" remote which happens automatically during "git
+clone". Let's now create another. Let's assume you are going to be
+working in the hello-remote repository and you'd like to pull changes
+from the hello-pull repository, where your friend "fred" has been
+making changes. Here's how to setup the new remote:
+
+       $ cd ../hello-remote
+       $ git remote add fred ../hello-pull
+
+So that's a "git remote add" command line followed by an arbitrary
+name you'd like for the new remote (fred) and the URL of the remote
+(../hello-pull). Obviously, the URL could be a git:// URL or any other
+git-supported URL in addition to a local path.
+
+The "git remote" command is really just a helper for adding some
+entries to the .git/config file. You might find it more convenient to
+edit that file directly once you get comfortable with things.
+
+At this point the name "fred" will work much like the name "origin"
+has worked in previous examples. For example, we can fetch the changes
+fred has made with "git fetch fred":
+
+       $ git fetch fred
+       remote: Generating pack...
+       Unpacking 3 objects...
+       remote: Done counting 5 objects.
+       Result has 3 objects.
+       Deltifying 3 objects...
+        100% remote: (3/3) done
+       Total 3 (delta 1), reused 0 (delta 0)
+        100% (3/3) done
+       * refs/remotes/fred/master: storing branch 'master' of ../hello-pull
+         commit: 3c54ac6
+
+Notice that this command-line only differs from the "git fetch" we did
+previously by explicitly naming which remote should be fetched. We
+could have explicitly said "git fetch origin" earlier.
+
+We can also list all known remote-tracking branches with "git branch
+-r":
+
+       $ git branch -r
+         fred/master
+         origin/HEAD
+         origin/master
+
+These remote-tracking branches make it very easy to collaborate with
+people as they are working on experimental features not yet ready for
+upstream inclusion. For example, if fred's latest code is still
+trashing filesystems then he might not want to push it out the the
+project's primary repository. But he may still want my help with
+it. So he can push it to a branch in his own repository for which I've
+got a remote. Then on my next "git fetch fred" I might notice a new
+branch called fred/trashes-filesystems and I can examine his code with
+a command such as "git log ..fred/trashed-filesystems".
+
+So lots of side collaboration can go on easily, and people working
+only with the primary repository never even have to see this dangerous
+code. It's distributed development at its finest.
+
+#### 2.8.4 Checking out previous revisions
+
+It's often useful to examine the working-tree state of some specific
+revision other than the tip of some branch. For example, maybe you
+would like to build a particular tagged version, or maybe you'd like
+to test the behavior of the code before a particular change was
+introduced. To do this, use "git checkout" and pass it the name of any
+revision, (with a branch name, a tag name, or any other commit
+identifier). For example, to examine our project before the original
+typo was introduced:
+
+       $ git checkout 0a633bf5
+       Note: moving to "0a633bf5" which isn't a local branch
+       If you want to create a new branch from this checkout, you may do so
+       (now or later) by using -b with the checkout command again. Example:
+         git checkout -b <new_branch_name>
+       HEAD is now at 0a633bf... Create a makefile
+
+The note that git gives us is to indicate that we are checking out a
+non-branch revision. This is perfectly fine if we are just exploring
+history, but if we actually wanted to use this revision as the basis
+for new commits, we would first have to create a new branch name as it
+describes.
+
+If we were to use "git checkout" with a branch name, then that would
+change the current branch, (meaning that any new commits would advance
+that branch pointer).
+
+For now, let's return back to the tip of the master branch by just
+checking it out again:
+
+       $ git checkout master
+       Previous HEAD position was 0a633bf... Create a makefile
+       Switched to branch "master"
+
+#### 2.8.5 Pushing changes to another repository
+
+As an unsurprising parallel to "git pull", git also provides "git
+push" for pushing changes to another repository. Now, generally the
+purpose of pushing to a repository is to have some "collaboration
+point" where potentially multiple people might be pushing or
+pulling. Because there might be multiple people pushing into the
+repository at any point, it wouldn't make sense to have a
+working-directory associated with this repository.
+
+For this, git has the notion of a "bare" repository, which is simply a
+repository with no working directory. Let's create a new bare
+repository and push some changes into it:
+
+       $ cd ..
+       $ mkdir hello-bare
+       $ cd hello-bare
+       $ git --bare init --shared
+
+The --shared option sets up the necessary group file permissions so
+that other users in my group will be able to push into this repository
+as well.
+
+Now lets return to our hello repository and push some changes to this
+new repository. Since this is our very first push into this repository
+we need to tell git which branches to push. The easiest way to do this
+is to use --all to indicate all branches:
+
+       $ cd ../hello
+       $ git push ../hello-bare --all
+       updating 'refs/heads/master'
+         from 0000000000000000000000000000000000000000
+         to   3c54ac672ec1130b36837f1b708054a7a1d402de
+       Generating pack...
+       Done counting 18 objects.
+       Deltifying 18 objects...
+        100% (18/18) done
+       Writing 18 objects...
+        100% (18/18) done
+       Total 18 (delta 3), reused 15 (delta 2)
+       Unpacking 18 objects...
+        100% (18/18) done
+       refs/heads/master: 0000000000000000000000000000000000000000 -> 3c54ac672ec1130b36837f1b708054a7a1d402de
+
+For subsequent pushes we don't need to specify --all as "git push" by
+default pushes all branches that exist in both the local and remote
+repositories. Also, as with pull, instead of explicitly specifying a
+URL, you may also specify a remote to push to. And by default, after
+cloning a repository, "git push" with no other arguments will attempt
+to push back to the same origin repository. As this is often exactly
+what is wanted, you may find that "git push" alone is often exactly
+what you need.
 
 What happens if we try to pull or push changes and the receiving
 repository already has those changes? Nothing too exciting.
 
-       $ hg push ../hello-push   
-       pushing to ../hello-push   
-       searching for changes   
-       no changes found
-
-#### 2.8.4  Sharing changes over a network
-
-The commands we have covered in the previous few sections are not
-limited to working with local repositories. Each works in exactly the
-same fashion over a network connection; simply pass in a URL instead
-of a local path.
-
-       $ hg outgoing http://hg.serpentine.com/tutorial/hello   
-       comparing with http://hg.serpentine.com/tutorial/hello   
-       searching for changes   
-       changeset:   5:fa1321bf0c80   
-       tag:         tip   
-       user:        Bryan O'Sullivan <bos@serpentine.com>   
-       date:        Sun Jun 17 18:05:50 2007 +0000   
-       summary:     Added an extra line of output   
-       
+       $ git push ../hello-bare
+       Everything up-to-date
 
-In this example, we can see what changes we could push to the remote
-repository, but the repository is understandably not set up to let
-anonymous users push to it.
-
-       $ hg push http://hg.serpentine.com/tutorial/hello   
-       pushing to http://hg.serpentine.com/tutorial/hello   
-       searching for changes   
-       ssl required
-
-   [1]: http://hgbook.red-bean.com/hgbookch3.html
-   [2]: http://hgbook.red-bean.com/hgbookch1.html
-   [3]: http://hgbook.red-bean.com/hgbookch1.html#tailhgbookch1.html
-   [4]: #tailhgbookch2.html
-   [5]: http://hgbook.red-bean.com/hgbook.html#hgbookch2.html
-   [6]: http://mercurial.berkwood.com/
-   [7]: http://hgbook.red-bean.com/hgbookli4.html#Xweb:macpython
-   [8]: #x6-340581
-   [9]: hgbookch2_files/tour-history.png
-   [10]: http://hgbook.red-bean.com/hgbookch12.html#x16-27100012.4
-   [11]: #x6-420002.7.1
-   [12]: #x6-490002.8.1
-   [13]: http://hgbook.red-bean.com/hgbookch2.html
-
-## Appendix D  
+## Appendix D
 Open Publication License
 
 Version 1.0, 8 June 1999 
 
-### D.1  Requirements on both unmodified and modified versions
+### D.1 Requirements on both unmodified and modified versions
 
 The Open Publication works may be reproduced and distributed in whole
 or in part, in any medium physical or electronic, provided that the
@@ -945,12 +1301,12 @@ outer surfaces of the book the original publisher’s name shall be as
 large as the title of the work and cited as possessive with respect to
 the title.
 
-### D.2  Copyright
+### D.2 Copyright
 
 The copyright to each Open Publication is owned by its author(s) or
 designee.
 
-### D.3  Scope of license
+### D.3 Scope of license
 
 The following license terms apply to all Open Publication works,
 unless otherwise explicitly stated in the document.
@@ -970,7 +1326,7 @@ without warranty of any kind, express or implied, including, but not
 limited to, the implied warranties of merchantability and fitness for
 a particular purpose or a warranty of non-infringement.
 
-### D.4  Requirements on modified works
+### D.4 Requirements on modified works
 
 All modified versions of documents covered by this license, including
 translations, anthologies, compilations and partial documents, must
@@ -987,7 +1343,7 @@ meet the following requirements:
      assert or imply endorsement of the resulting document without the
      original author’s (or authors’) permission.
 
-### D.5  Good-practice recommendations
+### D.5 Good-practice recommendations
 
 In addition to the requirements of this license, it is requested from
 and strongly recommended of redistributors that:
@@ -1006,7 +1362,7 @@ and strongly recommended of redistributors that:
      CD-ROM expression of an Open Publication-licensed work to its
      author(s).
 
-### D.6  License options
+### D.6 License options
 
 The author(s) and/or publisher of an Open Publication-licensed
 document may elect certain options by appending language to the