X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;ds=sidebyside;f=tour.mdwn;h=e9e02776d86cddd7b8a19c9bd8815303584cfc4c;hb=5bbd7299aa73ba64a701912203c84c733697efcb;hp=7ff65f635f2d5f665232672d5354f581ffa72f93;hpb=44d0c1f81ac57725e18f56431bf37609a68778b2;p=hgbook-git
diff --git a/tour.mdwn b/tour.mdwn
index 7ff65f6..e9e0277 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,6 +29,16 @@ Changes made by Carl include the following:
* Eliminate line numbers from examples
* Modified to describe git instead of mercurial
+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
@@ -50,25 +60,25 @@ 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
@@ -90,7 +100,7 @@ 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
@@ -100,7 +110,7 @@ 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
@@ -257,7 +267,7 @@ 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 commit.
-The fields in a record of output from âgit logâ are as follows.
+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.
@@ -279,20 +289,6 @@ The fields in a record of output from âgit logâ are as follows.
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 Commits, revisions, and talking to other people
As English is a notoriously sloppy language, and computer science has
@@ -343,7 +339,7 @@ in the current branch, "HEAD~", refers to the previous commit, and
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.
+committed to master since it diverged from origin.
#### 2.4.3 Viewing specific revisions
@@ -399,7 +395,7 @@ created:
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
+#### 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
@@ -529,7 +525,7 @@ disk space in most cases, too.
$ cd ..
$ git clone hello my-hello
- Initialized empty Git repository in /home/cworth/src/hgbook-git/my-hello/.git/
+ Initialized empty Git repository in /tmp/my-hello/.git/
0 blocks
[XXX We say "empty" here, (presumably from the git-init part),
@@ -564,7 +560,7 @@ 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
+ $ sed -i '/printf/a\\tprintf("hello again!\\n");' hello.c
The âgit statusâ command will tell us what git knows about the files
in the repository.
@@ -683,7 +679,7 @@ the files directly. Use your favorite editor to create a file called
then it will be there already). The initial contents of your
.gitconfig should look like this.
- # This is a git configuration file.
+ # This is a git configuration file.
[user]
name = Your Name
email = you@example.com
@@ -911,8 +907,8 @@ Bryan's original chapter. -Carl]
### 2.8 Sharing changes
-We mentioned earlier that repositories in Mercurial are
-self-contained. This means that the changeset we just created exists
+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.
@@ -922,224 +918,206 @@ 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.
+ $ cd ..
+ $ git clone hello hello-pull
+ Initialized empty Git repository in /tmp/hello-pull/.git/
+ 0 blocks
- $ 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
-
+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:
-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
+ $ 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
+ Added an extra line of output and fixed the typo bug.
-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
+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:
-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.
+ $ 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).]
+
+#### 2.8.2 Checking out previous revisions
+
+If any users of mercurial are reading this, they 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.
+
+But there's another function provided by "hg update" which is to
+update the working-directory files to a particular revision. In git,
+this functionality is provided by the "git checkout" command. To
+checkout a particular branch, tag, or an arbitrary revions, simply
+give the appropriate name to the "git checkout" command. For example,
+to examine the files as they existed before the original typo
+introduction, we could do:
+
+ $ 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.
+
+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
-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
-
-
-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
+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.
-As with âhg pullâ, the âhg pushâ command does not update the working
-directory in the repository that itâs pushing changes into. (Unlike
-âhg pullâ, âhg pushâ does not provide a -u option that updates the
-other repositoryâs working directory.)
+ $ cd ..
+ $ 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
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