remote: Done counting 15 objects.
remote: Deltifying 15 objects...
remote: 100% (15/15) done
- remote: Total 15 (delta 2), reused 0 (delta 0)
+ remote: Total 15 (delta 2), reused 15 (delta remote: 2)
Indexing 15 objects...
100% (15/15) done
Resolving 2 deltas...
$ git clone http://cworth.org/git/hello
Initialized empty Git repository in /tmp/hello/.git/
- got 8e5536eaf0c9313cfcfd3bb915c7ebb63d6f7a91
- walk 8e5536eaf0c9313cfcfd3bb915c7ebb63d6f7a91
- got e4c1447f272c0f90e0a80e55f495ec377863f6f5
- got d884386a016f03bdd6c2c72ceba5621568cc0329
- got 350a36688de4ee9dfeba52f09bf02385cb967bb2
- walk d884386a016f03bdd6c2c72ceba5621568cc0329
- got 9a3ff79a7c30a4b990d49fe7c9095d6bd2eab6c0
- got ab82c5460482579faae7841e8da3b98fbb34a41c
- got e19aeb100a31497481bba401cea42a39fac230ae
- walk e19aeb100a31497481bba401cea42a39fac230ae
- got 80b260cae9cec3cd52d27c46741ff59c321b852c
- got 23f952d3dccd5524c3c1b48b3558a5b7393286c2
- got 9fa6a8464b692252de9a3a20c9e579700d613b17
- walk 9fa6a8464b692252de9a3a20c9e579700d613b17
- got b8937ca165a312157658a67e7d413dd59e6ad377
- got b3f85f210ff86d334575f64cb01c5bf49895b63e
- got 556e69f96b04bff82857ddd7f7c08b2f3231d664
- walk 556e69f96b04bff82857ddd7f7c08b2f3231d664
- got ed55ec04ebc1736a91997a6ce7d7091010647c3d
- got 43d727f2f3f2f7cb3b098ddad1d7038464a4cee2
+ Getting alternates list for http://cworth.org/git/hello
+ Getting pack list for http://cworth.org/git/hello
+ Getting index for pack 04ecb061314ecbd60fa0610ecf55a1cbf85ea294
+ Getting pack 04ecb061314ecbd60fa0610ecf55a1cbf85ea294
+ which contains a1a0e8b392b17caf50325498df54802fe3c03710
+ walk a1a0e8b392b17caf50325498df54802fe3c03710
+ walk 72d4f10e4a27dbb09ace1503c20dbac1912ee451
+ walk 13ed136b983a9c439eddeea8a1c2076cffbb685f
+ walk 0a633bf58b45fcf1a8299d3c82cd1fd26d3f48f2
+ walk db7117a9dd9a6e57e8632ea5848e1101eee0fbde
If our clone succeeded, we should now have a local directory called
hello. This directory will contain some files.
### 2.4 A tour through history
One of the first things we might want to do with a new, unfamiliar
-repository is understand its history. The “hg log” command gives us a
+repository is understand its history. The “git log” command gives us a
view of history.
- $ hg log
- changeset: 4:b57f9a090b62
- tag: tip
- user: Bryan O'Sullivan <bos@serpentine.com>
- date: Tue Sep 06 15:43:07 2005 -0700
- summary: Trim comments.
+ $ git log
+ commit a1a0e8b392b17caf50325498df54802fe3c03710
+ Author: Bryan O'Sullivan <bos@serpentine.com>
+ Date: Tue Sep 6 15:43:07 2005 -0700
- changeset: 3:ff5d7b70a2a9
- user: Bryan O'Sullivan <bos@serpentine.com>
- date: Tue Sep 06 13:15:58 2005 -0700
- summary: Get make to generate the final binary from a .o file.
+ Trim comments.
- changeset: 2:057d3c2d823c
- user: Bryan O'Sullivan <bos@serpentine.com>
- date: Tue Sep 06 13:15:43 2005 -0700
- summary: Introduce a typo into hello.c.
+ commit 72d4f10e4a27dbb09ace1503c20dbac1912ee451
+ Author: Bryan O'Sullivan <bos@serpentine.com>
+ Date: Tue Sep 6 13:15:58 2005 -0700
+
+ Get make to generate the final binary from a .o file.
+
+ commit 13ed136b983a9c439eddeea8a1c2076cffbb685f
+ Author: Bryan O'Sullivan <bos@serpentine.com>
+ Date: Tue Sep 6 13:15:43 2005 -0700
- changeset: 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 <mpm@selenic.com>
+ Date: Fri Aug 26 01:21:28 2005 -0700
+ Create a makefile
+
+ commit db7117a9dd9a6e57e8632ea5848e1101eee0fbde
+ Author: Bryan O'Sullivan <mpm@selenic.com>
+ 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
* * *
-#### 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 <bos@serpentine.com>
- 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 derived from origin.
+
+#### 2.4.3 Viewing specific revisions
+
+You can use "git log" to explore the range syntax just introduced. For
+example, to see a list of the most recent 3 revisions you can use
+"HEAD~3..", (the destination of the range is implicitly HEAD in this
+case):
+
+ $ git log HEAD~3..
+ commit a1a0e8b392b17caf50325498df54802fe3c03710
+ Author: Bryan O'Sullivan <bos@serpentine.com>
+ Date: Tue Sep 6 15:43:07 2005 -0700
- $ hg log -r ff5d7b70a2a9
- changeset: 3:ff5d7b70a2a9
- user: Bryan O'Sullivan <bos@serpentine.com>
- date: Tue Sep 06 13:15:58 2005 -0700
- summary: Get make to generate the final binary from a .o file.
+ Trim comments.
- $ 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
+ commit 72d4f10e4a27dbb09ace1503c20dbac1912ee451
+ Author: Bryan O'Sullivan <bos@serpentine.com>
+ Date: Tue Sep 6 13:15:58 2005 -0700
- changeset: 4:b57f9a090b62
- tag: tip
- user: Bryan O'Sullivan <bos@serpentine.com>
- date: Tue Sep 06 15:43:07 2005 -0700
- summary: Trim comments.
+ Get make to generate the final binary from a .o file.
+
+ commit 13ed136b983a9c439eddeea8a1c2076cffbb685f
+ Author: Bryan O'Sullivan <bos@serpentine.com>
+ Date: Tue Sep 6 13:15:43 2005 -0700
+ Introduce a typo into hello.c.
-If you want to see 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 <bos@serpentine.com>
- 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 "--" wihch is necessary to distinguish
+commit names from file names:
+
+ $ git log -- Makefile
+ commit 72d4f10e4a27dbb09ace1503c20dbac1912ee451
+ Author: Bryan O'Sullivan <bos@serpentine.com>
+ Date: Tue Sep 6 13:15:58 2005 -0700
- changeset: 3:ff5d7b70a2a9
- user: Bryan O'Sullivan <bos@serpentine.com>
- date: Tue Sep 06 13:15:58 2005 -0700
- summary: Get make to generate the final binary from a .o file.
+ Get make to generate the final binary from a .o file.
- changeset: 4:b57f9a090b62
- tag: tip
- user: Bryan O'Sullivan <bos@serpentine.com>
- date: Tue Sep 06 15:43:07 2005 -0700
- summary: Trim comments.
+ commit 0a633bf58b45fcf1a8299d3c82cd1fd26d3f48f2
+ Author: Bryan O'Sullivan <mpm@selenic.com>
+ Date: Fri Aug 26 01:21:28 2005 -0700
+ Create a makefile
-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.
+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.
#### 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.
+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:
- $ hg log -v -r 3
- changeset: 3:ff5d7b70a2a9
- user: Bryan O'Sullivan <bos@serpentine.com>
- date: Tue Sep 06 13:15:58 2005 -0700
- files: Makefile
- description:
- Get make to generate the final binary from a .o file.
+ $ git log --stat --max-count=3
+ commit a1a0e8b392b17caf50325498df54802fe3c03710
+ Author: Bryan O'Sullivan <bos@serpentine.com>
+ 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 <bos@serpentine.com>
- 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 <bos@serpentine.com>
+ 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(-)
+
+ commit 13ed136b983a9c439eddeea8a1c2076cffbb685f
+ Author: Bryan O'Sullivan <bos@serpentine.com>
+ 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 <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;
+ }
+
+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 Mercurial commands to discuss
+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.
-
-In the examples throughout this book, I use short options instead of
-long. This just reflects my own preference, so don’t read anything
-significant into it.
+ * Most 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).
-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).
+ * 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