X-Git-Url: https://git.notmuchmail.org/git?a=blobdiff_plain;f=tour.mdwn;h=c72bffe0a030a68ea92daf4b706fe8f9503d98b7;hb=ebde7f61f24c82c958387da2db72093555507717;hp=d697f90d9467c2a2132bd4f1f523675f91076a7f;hpb=47fad19bcfb3906a582fb958e8a11dc8e0969ee9;p=hgbook-git
diff --git a/tour.mdwn b/tour.mdwn
index d697f90..c72bffe 100644
--- 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
.
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
- * 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,10 +110,10 @@ 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
@@ -125,7 +135,7 @@ present and just call out to "man git-"?]
available for git-? 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,18 @@ 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 local copy of a remote repository
+
+As suggested, a repository can be copied through normal file-copying
+commands. But git also provides a "git clone" tool for copying a
+repository. This provides a means of copying a repository over the
+network, and is also useful with a local repository since it is much
+more efficient than creating a normal copy, (creating a local clones
+is blazingly fast).
-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 +210,7 @@ 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 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,261 +231,312 @@ 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
- date: Tue Sep 06 15:43:07 2005 -0700
- summary: Trim comments.
+ $ git log
+ commit a1a0e8b392b17caf50325498df54802fe3c03710
+ Author: Bryan O'Sullivan
+ Date: Tue Sep 6 15:43:07 2005 -0700
+
+ Trim comments.
+
+ commit 72d4f10e4a27dbb09ace1503c20dbac1912ee451
+ Author: Bryan O'Sullivan
+ Date: Tue Sep 6 13:15:58 2005 -0700
- changeset: 3:ff5d7b70a2a9
- user: Bryan O'Sullivan
- 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: 2:057d3c2d823c
- user: Bryan O'Sullivan
- date: Tue Sep 06 13:15:43 2005 -0700
- summary: Introduce a typo into hello.c.
+ commit 13ed136b983a9c439eddeea8a1c2076cffbb685f
+ Author: Bryan O'Sullivan
+ Date: Tue Sep 6 13:15:43 2005 -0700
- changeset: 1:82e55d328c8c
- user: mpm@selenic.com
- date: Fri Aug 26 01:21:28 2005 -0700
- summary: Create a makefile
+ Introduce a typo into hello.c.
- changeset: 0:0a04b987be5a
- user: mpm@selenic.com
- date: Fri Aug 26 01:20:50 2005 -0700
- summary: Create a standard "hello, world" program
+ commit 0a633bf58b45fcf1a8299d3c82cd1fd26d3f48f2
+ Author: Bryan O'Sullivan
+ Date: Fri Aug 26 01:21:28 2005 -0700
+ Create a makefile
+
+ commit db7117a9dd9a6e57e8632ea5848e1101eee0fbde
+ Author: Bryan O'Sullivan
+ Date: Fri Aug 26 01:20:50 2005 -0700
+
+ Create a standard "hello, world" program
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.
-
-The fields in a record of output from âhg logâ are as follows.
-
- * 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.
-
-The default output printed by âhg logâ is purely a summary; it is
+call each of these recorded events a commit.
+
+The 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
+ 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). The "git log" command doesn't display
+ the Committer, but other git tools do.
+ * 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 default output printed by âgit logâ is purely a summary; it is
missing a lot of detail.
-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.
-
-* * *
-
-![PIC][9]
-
-Figure 2.1:
-Graphical history of the hello repository
-
-* * *
-
-#### 2.4.1 Changesets, revisions, and talking to other people
+#### 2.4.1 Commits, revisions, and talking to other people
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
- date: Tue Sep 06 13:15:58 2005 -0700
- summary: Get make to generate the final binary from a .o file.
+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
+ Date: Tue Sep 6 15:43:07 2005 -0700
+
+ Trim comments.
- $ hg log -r ff5d7b70a2a9
- changeset: 3:ff5d7b70a2a9
- user: Bryan O'Sullivan
- date: Tue Sep 06 13:15:58 2005 -0700
- summary: Get make to generate the final binary from a .o file.
+ commit 72d4f10e4a27dbb09ace1503c20dbac1912ee451
+ Author: Bryan O'Sullivan
+ Date: Tue Sep 6 13:15:58 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
+ Get make to generate the final binary from a .o file.
- changeset: 4:b57f9a090b62
- tag: tip
- user: Bryan O'Sullivan
- date: Tue Sep 06 15:43:07 2005 -0700
- summary: Trim comments.
+ commit 13ed136b983a9c439eddeea8a1c2076cffbb685f
+ Author: Bryan O'Sullivan
+ Date: Tue Sep 6 13:15:43 2005 -0700
+ Introduce a typo into hello.c.
-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â.
+#### 2.4.4 Other log filters
- $ hg log -r 2:4
- changeset: 2:057d3c2d823c
- user: Bryan O'Sullivan
- date: Tue Sep 06 13:15:43 2005 -0700
- summary: Introduce a typo into hello.c.
+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:
+
+ $ git log -- Makefile
+ commit 72d4f10e4a27dbb09ace1503c20dbac1912ee451
+ Author: Bryan O'Sullivan
+ Date: Tue Sep 6 13:15:58 2005 -0700
- changeset: 3:ff5d7b70a2a9
- user: Bryan O'Sullivan
- 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
- date: Tue Sep 06 15:43:07 2005 -0700
- summary: Trim comments.
+ commit 0a633bf58b45fcf1a8299d3c82cd1fd26d3f48f2
+ Author: Bryan O'Sullivan
+ Date: Fri Aug 26 01:21:28 2005 -0700
+ Create a makefile
+
+And "git log" can also filter based on the dates at which commits were
+created:
+
+ $ git log --since="2 weeks ago" --until="yesterday"
+
+Another useful option is -n or --max-count which, unsurprisingly,
+limits the maximum number of commits to be displayed.
-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
- date: Tue Sep 06 13:15:58 2005 -0700
- files: Makefile
- description:
- Get make to generate the final binary from a .o file.
+#### 2.4.5 More detailed information
+
+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:
+
+ $ git log --stat --max-count=3
+ commit a1a0e8b392b17caf50325498df54802fe3c03710
+ Author: Bryan O'Sullivan
+ Date: Tue Sep 6 15:43:07 2005 -0700
+ Trim comments.
-
-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
- date: Tue Sep 06 13:15:43 2005 -0700
- files: hello.c
- description:
- Introduce a typo into hello.c.
+ hello.c | 8 ++------
+ 1 files changed, 2 insertions(+), 6 deletions(-)
+ commit 72d4f10e4a27dbb09ace1503c20dbac1912ee451
+ Author: Bryan O'Sullivan
+ Date: Tue Sep 6 13:15:58 2005 -0700
- 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 @@
+ Get make to generate the final binary from a .o file.
- int main(int argc, char ââargv)
- {
- - printf("hello, world!ân");
- + printf("hello, world!â");
- return 0;
- }
+ Makefile | 2 ++
+ 1 files changed, 2 insertions(+), 0 deletions(-)
-
-### 2.5 All about command options
-
-Letâs take a brief break from exploring Mercurial commands to discuss
+ commit 13ed136b983a9c439eddeea8a1c2076cffbb685f
+ Author: Bryan O'Sullivan
+ Date: Tue Sep 6 13:15:43 2005 -0700
+
+ 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
+ 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;
+ }
+
+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
+ 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.
-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).
- * 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.
+ * Most options have long names. For example, as weâve already seen,
+ the âgit log" command accepts a --max-count= option.
+ * Some options have short, single-character names. Often these are
+ aliases for long commands, (such as "-n " instead of
+ --max-count=), 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).
-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.
+ * 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.
-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).
+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
+### 2.6 Making and reviewing changes
-Now that we have a grasp of viewing history in Mercurial, letâs take a
+Now that we have a grasp of viewing history in git, 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
+its own. We use the âgit 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
+ $ cd ..
+ $ git clone hello my-hello
+ Initialized empty Git repository in /tmp/my-hello/.git/
+ 0 blocks
+
+ [XXX We say "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?]
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
@@ -480,6 +546,17 @@ 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.
+Alternatively, you can achieve much the same effect by creating
+multiple branches in a single repository, (but we won't go into detail
+on how to do that in this chapter). Some people greatly appreciate
+having multiple branches in a single repository rather than having
+many repositories cluttering up their filesystem. Other people prefer
+the ability to have working-tree changes, and intermediate build
+files, etc. each isolated in a separate repository per branch. Both
+modes are very well-supported by git, so it's really a matter of which
+you find most appropriate at any time given your tastes and project
+workflows.
+
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
@@ -488,435 +565,579 @@ 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
+ $ sed -i '/printf/a\\tprintf("hello again!\\n");' 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 âgit statusâ command will tell us what git knows about the files
+in the repository.
-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.
+ $ ls
+ hello.c Makefile
+ $ git status
+ # On branch master
+ # Changed but not updated:
+ # (use "git add ..." to update what will be committed)
+ #
+ # modified: hello.c
+ #
+ no changes added to commit (use "git add" and/or "git commit -a")
+
+We see that âgit statusâ command prints a line with "modified" for
+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..6d28887 100644
+ --- a/hello.c
+ +++ b/hello.c
+ @@ -8,5 +8,6 @@
+ int main(int argc, char **argv)
+ {
+ printf("hello, world!\");
+ + printf("hello again!\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.
+record our work in a new commit.
-The âhg commitâ command lets us create a new changeset; weâll usually
+The âgit 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
-
-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.
+#### 2.7.1 Setting up a username
+
+When you try to run âgit commitâ for the first time, it might not do
+exactly what you want. Git records your name and 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. It will
+attempt each of the following methods, in order, (stopping for each field 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 "
+ 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 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.
+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 a valid
+email address, but some, (notably Linus Torvalds, the original author
+of git), actually like the default user@hostname convention that git
+falls back on without any additional information. 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.
-#### 2.7.2 Writing a commit message
+#### 2.7.2 Writing a commit message
-When we commit a change, Mercurial drops us into a text editor, to
+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:â.
-
- empty line
- HG: changed hello.c
-
-Mercurial ignores the lines that start with âHG:â; it uses them only
+ $ 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 "
+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 " 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 â#â.
+
+ 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 ..." to unstage)
+ #
+ # modified: hello.c
+ #
+
+git ignores the lines that start with â#â; it uses them only
to tell us which files itâs recording changes to. Modifying or
deleting these lines has no effect.
-#### 2.7.3 Writing a good commit message
+#### 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 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.
-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
+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.
- changeset: 73:584af0e231be
- user: Censored Person
- 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
+
+ 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 -p".
-#### 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
- 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 018cfb742be6176443ffddac454e593e802ddf3e
+ Author: Carl Worth
+ Date: Thu Sep 27 23:55:00 2007 -0700
+ Added an extra line of output.
+
+ If I would have been clever I would have fixed that old typo
+ while I was at it...
- 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;
- }
+ diff --git a/hello.c b/hello.c
+ index 9a3ff79..6d28887 100644
+ --- a/hello.c
+ +++ b/hello.c
+ @@ -8,5 +8,6 @@
+ int main(int argc, char **argv)
+ {
+ printf("hello, world!\");
+ + printf("hello again!\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 commit with a
+careful message, we're just about ready to share our change with the
+world. But wait, we forgot to try to compile it didn't we?
+
+ $ make
+ cc -c -o hello.o hello.c
+ hello.c:10:9: warning: missing terminating " character
+ hello.c:10:9: warning: missing terminating " character
+ hello.c: In function âmainâ:
+ hello.c:10: error: missing terminating " character
+ hello.c:11: error: expected â)â before â;â token
+ hello.c:13: warning: passing argument 1 of âprintfâ makes pointer from integer without a cast
+ hello.c:13: error: expected â;â before â}â token
+ make: *** [hello.o] Error 1
+
+Oh look. The code's broken and doesn't compile. We don't want to share
+code in this state. For situations where you notice one tiny detail
+that got left out of the last commit, (a silly syntax error, a
+misspelling in a comment or commit messsage), git provides a very
+handy tool for just changing the last commit.
+
+So fix that typo, (a missing 'n' between the '\' and the '"'), with
+your editor or with something like this:
+
+ sed -i 's/\\"/\\n"/' hello.c
+
+And then you can just amend the previous commit rather than creating a
+new one with the --amend option to "git commit":
+
+ $ git commit -a --amend
+
+Note that we use -a to include the code change here. And that helps
+point out a situation where "git commit" is useful without the -a
+option, "git commit --amend" is a useful command for amend just the
+last commit message, without committing any new code changes, even if
+some files have been modified in the working tree.
+
+And here's the final result:
+
+ $ git show
+ commit 839b58d021c618bd0e1d336d4d5878a0082672e6
+ Author: Carl Worth
+ Date: Thu Sep 27 23:55:00 2007 -0700
-
-We refer to the newest revision in the repository as the tip revision,
-or simply the tip.
-
-### 2.8 Sharing changes
-
-We mentioned earlier that repositories in Mercurial are
-self-contained. This means that the changeset we just created exists
+ Added an extra line of output and fixed the typo bug.
+
+ diff --git a/hello.c b/hello.c
+ index 9a3ff79..ca750e0 100644
+ --- a/hello.c
+ +++ b/hello.c
+ @@ -7,6 +7,7 @@
+
+ int main(int argc, char **argv)
+ {
+ - printf("hello, world!\");
+ + printf("hello, world!\n");
+ + printf("hello again!\n");
+ return 0;
+ }
+
+I can't help but point out that this really was a poor example for
+--amend. The end result is a single commit that does two independent
+things, (fixes one bug and adds one new feature). It's much better to
+create a code history where each commit makes an independent change,
+(and as small as possible). This is important for several reasons:
+
+ * Small changes are easier to review
+
+ * Independent changes are easier to split up if only part of the
+ series gets accepted "upstream" for one reason or another.
+
+ * 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 the single commit that introduces a bug. And
+ it's much more powerful if the commit it isolates is as small as
+ possible.
+
+So it's a good thing this document is available under a license that
+allows for distribution of modified versions. Someone should clean up
+the --amend example to not teach bad habits like I did above. [Note:
+All this bad-habit stuff was introduced by me, and was not present in
+Bryan's original chapter. -Carl]
+
+### 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 my-hello repository. Letâs look at a few ways that we can
propagate this change into other repositories.
-#### 2.8.1 Pulling changes from another repository
+#### 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
- date: Sun Jun 17 18:05:50 2007 +0000
- summary: Added an extra line of output
-
-
-(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.)
-
-Bringing changes into a repository is a simple matter of running the
-âhg pullâ command, and telling it which repository to pull from.
-
- $ hg tip
- changeset: 4:b57f9a090b62
- tag: tip
- user: Bryan O'Sullivan
- 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
- date: Sun Jun 17 18:05:50 2007 +0000
- summary: Added an extra line of output
-
+ $ cd ..
+ $ git clone hello hello-pull
+ Initialized empty Git repository in /tmp/hello-pull/.git/
+ 0 blocks
-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
- date: Sun Jun 17 18:05:50 2007 +0000
- summary: Added an extra line of output
-
+We could use the âgit pullâ command to apply changes from my-hello to
+our master branch in hello-pull. However, blindly pulling unknown
+changes into a repository is a somewhat scary prospect. The "git pull"
+command is coneptually the combination of two commands, "git fetch"
+and "git merge"; we can run those separately to examine the changes
+before applying them locally. First we do the fetch:
-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
- 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
- date: Sun Jun 17 18:05:50 2007 +0000
- summary: Added an extra line of output
+ $ cd hello-pull
+ $ git fetch ../my-hello
+ 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)
+
+The fetched commits (or commit in this case) are available as the name
+FETCH_HEAD. [XXX: Shouldn't git-fetch print that name out to the user
+if the user didn't provide a specific branch name to fetch into.] And
+the difference between what we had before and what exists on
+FETCH_HEAD can easily be examined with the ..FETCH_HEAD range
+notation:
+
+ $ git log ..FETCH_HEAD
+ commit 839b58d021c618bd0e1d336d4d5878a0082672e6
+ Author: Carl Worth
+ Date: Thu Sep 27 23:55:00 2007 -0700
-
-And the âhg pushâ command does the actual push.
-
- $ 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
-
-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.)
+ Added an extra line of output and fixed the typo bug.
+
+Since these commits actually exist in the local repository now, we
+don't need to fetch or pull them from the remote repository again---we
+can now use "git merge" to apply the previously fetched commits. (A
+mercurial user might notice here that git does not have the race
+condition between "hg incoming" and "hg pull" that mercurial has since
+the commits are fetched only once.)
+
+ $ git merge FETCH_HEAD
+ Updating a1a0e8b..839b58d
+ Fast forward
+ hello.c | 3 ++-
+ 1 files changed, 2 insertions(+), 1 deletions(-)
+
+Notice that "git merge" reports that our branch pointer has been
+updated from a1a0e8b to 839b58d. Also, this is a "fast forward"
+meaning that the new commits are a linear sequence on top of the
+commit we already hand. In other words, there wasn't any divergence
+between these two repositories so no actual "merge" commit was
+created.
+
+This separation of fetch and merge is useful when you need to
+carefully review some changes before applying them. But often you're
+in a situation where you know you trust the remote repository and you
+simply want to pull those changes as conveniently as possible, (no
+extra commands, no typing a magic name like FETCH_HEAD). This is the
+case when the tracking upstream development of a project with git. And
+in that case, the above steps are as simple as just executing "git
+pull". So let's repeat all that the simpler way:
+
+ $ cd ..
+ $ git clone hello hello-tracking
+ Initialized empty Git repository in /tmp/hello-tracking/.git/
+ 0 blocks
+ $ cd hello-tracking
+ $ git pull ../my-hello
+ remote: Generating pack...
+ remote: Done counting 5 objects.
+ Result has 3 objects.
+ Deltifying 3 objects...
+ Unpacking 3 objects...
+ remote: 100% (3/3) done
+ Total 3 (delta 1), reused 0 (delta 0)
+ 100% (3/3) done
+ Updating a1a0e8b..839b58d
+ Fast forward
+ hello.c | 3 ++-
+ 1 files changed, 2 insertions(+), 1 deletions(-)
+
+It should be plain to see that the "git pull" command really did the
+combined sequence of "git fetch" and "git merge". Also, if you want to
+pull from the same repository you cloned from originally, (which is
+the common case for the upstream-tracking scenario), then "git pull"
+with no explicit repository is suffcient, and it will default to
+pulling from the same repository as the original clone.
+
+[XXX: The structure of the preceding section follows that of the
+original hgbook. But an alternate structure that arranged to pull from
+the originally cloned repository (as would be common) would allow for
+more straightforward use of git's features. For example, instead of
+the silly FETCH_HEAD stuff it would allow for "git fetch" and "git log
+master..origin" to be a very nice replacement for "hg
+incoming". Similarly, below, "git log origin..master" would make a
+nice replacement for "hg outgoing" which is something I didn't offer
+at all. One could also use git's remotes with the myriad repositories
+as used here, but it would require doing things like "git remote add
+ ../hello-pull" and that seems like a bit much to introduce
+for a turorial of this level. If nothing else, if the above section
+seems a little intimidating, understand that it's because things are
+not presented in the most natural "git way", (and I'm a little too
+tired to fix it tonight).]
+
+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 workind-directory files as necessary.
+
+#### 2.8.2 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
+ 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.3 Pushing changes to another repository
+
+Git lets us push changes to another repository, from the repository
+weâre currently visiting. As with previous examples, above, weâll
+first create a temporary repository to push our changes into. But
+instead of using "git clone", this time we'll use "git init" to make a
+repository from an empty directory. We do this to create a "bare"
+repository which is simply a repository that has no working-directory
+files associated with it. In general, you should only push to bare
+repositories.
+
+ $ cd ..
+ $ mkdir hello-push
+ $ cd hello-push
+ $ git --bare init
+ Initialized empty Git repository in /tmp/hello-push/
+
+And then we'll go back to our my-hello repository to perform the
+push. 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 ../my-hello
+ $ git push ../hello-push --all
+ updating 'refs/heads/master'
+ from 0000000000000000000000000000000000000000
+ to 839b58d021c618bd0e1d336d4d5878a0082672e6
+ 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 0 (delta 0)
+ Unpacking 18 objects...
+ 100% (18/18) done
+ refs/heads/master: 0000000000000000000000000000000000000000 -> 839b58d021c618bd0e1d336d4d5878a0082672e6
+
+For subsequent pushes we don't need to specify --all as "git push"
+will push all branches that exist in both the local and remote
+repositories.
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
+ $ git push ../hello-push
+ Everything up-to-date
-#### 2.8.4 Sharing changes over a network
+#### 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
- date: Sun Jun 17 18:05:50 2007 +0000
- summary: Added an extra line of output
-
+same fashion over a network connection; simply pass in a URL or an ssh
+host:/path/name specification instead of a local path.
-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 +1166,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 +1191,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 +1208,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 +1227,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