+ 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
+
+ Introduce a typo into hello.c.
+
+ 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.
+
+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.
+
+ * 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 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 “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 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 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.
+
+ $ 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.
+
+#### 2.7.3 Writing a good commit message
+
+A good commit message will generally have a single line that
+summarizes the commit, a blank line, and then one or more paragraphs
+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.
+
+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.
+
+Here’s a real example of a commit message that doesn’t follow
+this guideline, and hence has a summary that is not readable.
+
+ $ 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. 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 "git log --stat" or “git log -p", (so repeating the list
+of all modified files is not useful, for example).
+
+To follow along with the example here, go ahead and type something
+like the following sentence into the editor. The misspelling here is
+intentional. You'll see how to fix that up after the fact in just a
+moment:
+
+ Fixed the typo so the program actuall complies now.
+
+Then save the file, and exit from the editor. When you do that, git
+will create the 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.
+
+#### 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 that embarrassing misspelling in
+it. Wouldn't it be nice to touch that up before we 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 you can just run that now and fix the broken commit
+message in the editor:
+
+ $ 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
+
+ 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 every time your project is in a state 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.
+
+#### 2.8.1 Pulling changes from the original repository
+
+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.
+
+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.
+
+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 progress 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.
+
+As expected, we received just the one commit.
+
+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.
+
+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.
+
+#### 2.8.2 Using fetch and merge separately to pull
+
+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 commands,
+"git fetch" and "git merge". We can use these commands separately to
+examine the change before accepting it.
+
+So let's do that within the hello-fetch clone we made earlier. First
+we will do the fetch:
+
+ $ 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 to 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.
+
+ $ git push ../hello-bare
+ Everything up-to-date
+
+## Appendix D
+Open Publication License
+
+Version 1.0, 8 June 1999
+
+### 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
+terms of this license are adhered to, and that this license or an
+incorporation of it by reference (with any options elected by the
+author(s) and/or publisher) is displayed in the reproduction.
+
+Proper form for an incorporation by reference is as follows:
+
+Copyright (c) year by author’s name or designee. This material may be
+distributed only subject to the terms and conditions set forth in the
+Open Publication License, vx.y or later (the latest version is
+presently available at
+[http://www.opencontent.org/openpub/][http://www.opencontent.org/openpub/]).
+
+The reference must be immediately followed with any options elected by
+the author(s) and/or publisher of the document (see section D.6).
+
+Commercial redistribution of Open Publication-licensed material is
+permitted.
+
+Any publication in standard (paper) book form shall require the
+citation of the original publisher and author. The publisher and
+author’s names shall appear on all outer surfaces of the book. On all
+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
+
+The copyright to each Open Publication is owned by its author(s) or
+designee.
+
+### D.3 Scope of license
+
+The following license terms apply to all Open Publication works,
+unless otherwise explicitly stated in the document.
+
+Mere aggregation of Open Publication works or a portion of an Open
+Publication work with other works or programs on the same media shall
+not cause this license to apply to those other works. The aggregate
+work shall contain a notice specifying the inclusion of the Open
+Publication material and appropriate copyright notice.
+
+Severability. If any part of this license is found to be unenforceable
+in any jurisdiction, the remaining portions of the license remain in
+force.
+
+No warranty. Open Publication works are licensed and provided “as is”
+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
+
+All modified versions of documents covered by this license, including
+translations, anthologies, compilations and partial documents, must
+meet the following requirements:
+
+ 1. The modified version must be labeled as such.
+ 2. The person making the modifications must be identified and the
+ modifications dated.
+ 3. Acknowledgement of the original author and publisher if
+ applicable must be retained according to normal academic citation
+ practices.
+ 4. The location of the original unmodified document must be identified.
+ 5. The original author’s (or authors’) name(s) may not be used to
+ assert or imply endorsement of the resulting document without the
+ original author’s (or authors’) permission.
+
+### D.5 Good-practice recommendations
+
+In addition to the requirements of this license, it is requested from
+and strongly recommended of redistributors that:
+
+ 1. If you are distributing Open Publication works on hardcopy or
+ CD-ROM, you provide email notification to the authors of your
+ intent to redistribute at least thirty days before your
+ manuscript or media freeze, to give the authors time to provide
+ updated documents. This notification should describe
+ modifications, if any, made to the document.
+ 2. All substantive modifications (including deletions) be either
+ clearly marked up in the document or else described in an
+ attachment to the document.
+ 3. Finally, while it is not mandatory under this license, it is
+ considered good form to offer a free copy of any hardcopy and
+ CD-ROM expression of an Open Publication-licensed work to its
+ author(s).
+
+### 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
+reference to or copy of the license. These options are considered part
+of the license instance and must be included with the license (or its
+incorporation by reference) in derived works.
+
+ 1. To prohibit distribution of substantively modified versions
+ without the explicit permission of the author(s). “Substantive
+ modification” is defined as a change to the semantic content of
+ the document, and excludes mere changes in format or
+ typographical corrections.
+
+ To accomplish this, add the phrase “Distribution of substantively
+ modified versions of this document is prohibited without the
+ explicit permission of the copyright holder.” to the license
+ reference or copy.
+
+ 2. To prohibit any publication of this work or derivative works in
+ whole or in part in standard (paper) book form for commercial
+ purposes is prohibited unless prior permission is obtained from
+ the copyright holder.
+
+ To accomplish this, add the phrase “Distribution of the work or
+ derivative of the work in any standard (paper) book form is
+ prohibited unless prior permission is obtained from the copyright
+ holder.” to the license reference or copy.