-#### 2.8.1 Pulling changes from another repository
-
-To get started, let’s clone our original hello repository, which does
-not contain the change we just committed. We’ll call our temporary
-repository hello-pull.
-
- $ cd ..
- $ hg clone hello hello-pull
- 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
-
-We’ll use the “hg pull” command to bring changes from my-hello into
-hello-pull. However, blindly pulling unknown changes into a repository
-is a somewhat scary prospect. Mercurial provides the “hg incoming”
-command to tell us what changes the “hg pull” command would pull into
-the repository, without actually pulling the changes in.
-
- $ cd hello-pull
- $ hg incoming ../my-hello
- comparing with ../my-hello
- searching for changes
- changeset: 5:fa1321bf0c80
- tag: tip
- user: Bryan O'Sullivan <bos@serpentine.com>
- date: Sun Jun 17 18:05:50 2007 +0000
- summary: Added an extra line of output
-
-
-(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 <bos@serpentine.com>
- date: Tue Sep 06 15:43:07 2005 -0700
- summary: Trim comments.
-
- $ hg pull ../my-hello
- pulling from ../my-hello
- searching for changes
- adding changesets
- adding manifests
- adding file changes
- added 1 changesets with 1 changes to 1 files
- (run 'hg update' to get a working copy)
- $ hg tip
- changeset: 5:fa1321bf0c80
- tag: tip
- user: Bryan O'Sullivan <bos@serpentine.com>
- date: Sun Jun 17 18:05:50 2007 +0000
- summary: Added an extra line of output
-
-
-As you can see from the before-and-after output of “hg tip”, we have
-successfully pulled changes into our repository. There remains one
-step before we can see these changes in the working directory.
-
-#### 2.8.2 Updating the working directory
-
-We have so far glossed over the relationship between a repository and
-its working directory. The “hg pull” command that we ran in
-section [2.8.1][12] brought changes into the repository, but if we
-check, there’s no sign of those changes in the working directory. This
-is because “hg pull” does not (by default) touch the working
-directory. Instead, we use the “hg update” command to do this.
-
- $ grep printf hello.c
- printf("hello, world!∖");
- $ hg update tip
- 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
- $ grep printf hello.c
- printf("hello, world!∖");
- printf("hello again!∖n");
-
-It might seem a bit strange that “hg pull” doesn’t update the working
-directory automatically. There’s actually a good reason for this: you
-can use “hg update” to update the working directory to the state it
-was in at any revision in the history of the repository. If you had
-the working directory updated to an old revision—to hunt down the
-origin of a bug, say—and ran a “hg pull” which automatically updated
-the working directory to a new revision, you might not be terribly
-happy.
-
-However, since pull-then-update is such a common thing to do,
-Mercurial lets you combine the two by passing the -u option to “hg
-pull”.
-
- hg pull -u
-
-If you look back at the output of “hg pull” in section [2.8.1][12]
-when we ran it without -u, you can see that it printed a helpful
-reminder that we’d have to take an explicit step to update the working
-directory:
-
- (run 'hg update' to get a working copy)
-
-To find out what revision the working directory is at, use the “hg
-parents” command.
-
- $ hg parents
- changeset: 5:fa1321bf0c80
- tag: tip
- user: Bryan O'Sullivan <bos@serpentine.com>
- date: Sun Jun 17 18:05:50 2007 +0000
- summary: Added an extra line of output
-
-
-If you look back at figure [2.1][8], you’ll see arrows connecting each
-changeset. The node that the arrow leads from in each case is a
-parent, and the node that the arrow leads to is its child. The working
-directory has a parent in just the same way; this is the changeset
-that the working directory currently contains.
-
-To update the working directory to a particular revision, give a
-revision number or changeset ID to the “hg update” command.
-
- $ hg update 2
- 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
- $ hg parents
- changeset: 2:057d3c2d823c
- user: Bryan O'Sullivan <bos@serpentine.com>
- date: Tue Sep 06 13:15:43 2005 -0700
- summary: Introduce a typo into hello.c.
-
- $ hg update
- 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
-
-If you omit an explicit revision, “hg update” will update to the tip
-revision, as shown by the second call to “hg update” in the example
-above.
-
-#### 2.8.3 Pushing changes to another repository
-
-Mercurial lets us push changes to another repository, from the
-repository we’re currently visiting. As with the example of “hg pull”
-above, we’ll create a temporary repository to push our changes into.
-
- $ cd ..
- $ hg clone hello hello-push
- 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
-
-The “hg outgoing” command tells us what changes would be pushed into
-another repository.
-
- $ cd my-hello
- $ hg outgoing ../hello-push
- comparing with ../hello-push
- searching for changes
- changeset: 5:fa1321bf0c80
- tag: tip
- user: Bryan O'Sullivan <bos@serpentine.com>
- date: Sun Jun 17 18:05:50 2007 +0000
- summary: Added an extra line of output
-
-
-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.)
+#### 2.8.1 Pulling changes from the original repository
+
+Recall that in Section 2.3.2 we made several local clones of the hello
+repository before we made any commits. This allows us to simulate what
+happens when upstream changes have been committed after you originally
+cloned.
+
+The simplest, (and quite common), scenario is that you inherently
+trust any changes in the original repository and you want to pull
+these directly into your clone. This might be the case if you are
+using git simply to track the progress of a project without making any
+changes.
+
+In this case, the operation is as simple as just calling "git pull":
+
+ $ cd ../hello-pull
+ $ git pull
+ remote: Generating pack...
+ Unpacking 3 objects...
+ 100% (3/3) done
+ remote: Done counting 5 objects.
+ Result has 3 objects.
+ Deltifying 3 objects...
+ 100% remote: (3/3) done
+ Total 3 (delta 1), reused 0 (delta 0)
+ * refs/remotes/origin/master: fast forward to branch 'master' of /tmp/hello
+ old..new: a1a0e8b..3c54ac6
+ Updating a1a0e8b..3c54ac6
+ Fast forward
+ hello.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+XXX: Git is fairly noisy here, but a user has little need to care
+about the several stages of operation involved here. As a tutorial
+writer I'd like to say "ignore all that progress stuff, and look at
+where the stat information starts" but it's hard for a new user to
+even be able to understand that. I think it would be ideal if all of
+the progress-tracking spew were reduced to a single line. Something
+like "Computing (100%) Transferring (100%)" or whatever.
+
+After (lots!) of progress indication, git gives a report of which
+files were modified, (which is very useful for getting a quick feel
+for what happened). If you would like more details on what changes
+came in, git provides a range that is perfect for examining. Let's
+take a look (again, the commit identifiers will be different for you
+--- just copy-and-paste the range that git prints):
+
+ $ git log a1a0e8b..3c54ac6
+ commit 3c54ac672ec1130b36837f1b708054a7a1d402de
+ Author: Carl Worth <cworth@cworth.org>
+ Date: Fri Sep 28 12:50:16 2007 -0700
+
+ Fixed the typo so the program actually compiles now.
+
+As expected, we received just the one commit.
+
+So that's all that's needed in the common case. Just run "git pull"
+everytime you want to pull in new changes that have landed in the
+upstream repository.
+
+Note: Mercurial users who are reading this might wonder if there's a
+need for the equivalent of "hg update" after doing a "git pull". And
+the answer is no. Unlike mercurial, "git pull", (and "git merge") will
+automatically update the working-directory files as necessary.
+
+#### 2.8.2 Using fetch and merge separately to pull
+
+Sometimes you may not know if you want to pull in the changes from the
+remote repository or not. It's useful to be able to examine them
+before accepting them into our branch. The "git pull" command shown in
+the previous section is conceptually the combination of two commands,
+"git fetch" and "git merge". We can use these commands separately to
+examine the change before accepting it.
+
+So let's do that within the hello-fetch clone we made earlier. First
+we will do the fetch:
+
+ $ cd ../hello-fetch
+ $ git fetch
+ remote: Generating pack...
+ Unpacking 3 objects...
+ remote: Done counting 5 objects.
+ Result has 3 objects.
+ Deltifying 3 objects...
+ 100% remote: (3/3) done
+ Total 3 (delta 1), reused 0 (delta 0)
+ 100% (3/3) done
+ * refs/remotes/origin/master: fast forward to branch 'master' of /tmp/hello/
+ old..new: a1a0e8b..3c54ac6
+
+You may notice that the output here looks very much like the first
+portion of the output from "git pull". This is no coincidence. The
+new changes have been "fetched" into the current repository and are
+stored into "origin/master" and have not been into the current
+"master" branch. Remember that "master" is our current branch. So now,
+"origin/master" is the state of the master branch that exists in the
+"origin" repository, (the one we cloned from).
+
+The most convenient way to examine the fetched changes is with the
+"master..origin" range notation:
+
+ $ git log master..origin
+ commit 3c54ac672ec1130b36837f1b708054a7a1d402de
+ Author: Carl Worth <cworth@cworth.org>
+ Date: Fri Sep 28 12:50:16 2007 -0700
+
+ Fixed the typo so the program actually compiles now.
+
+Another helpful way of visualizing what happened with "git fetch" here
+is to run "gitk --all", which gives a graphical representation of all
+branches. Here is what it would look like:
+
+[[img gitk-fetch.png]]
+
+Notice that origin/master points to a single commit that was committed
+on top of the state pointed to by the "master" branch.
+
+Let's assume we are happy with the changes and we want to include them
+into our master branch. To do this we simply run "git merge origin":
+
+ $ git merge origin
+ Updating a1a0e8b..3c54ac6
+ Fast forward
+ hello.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+Again, you'll see that this precisely matches the final portion of the
+output from "git pull". Using "git fetch" and "git merge" let us
+achieve exactly what "git pull" did, but we were able to stop in the
+middle to examine the situation, (and we could have decided to reject
+the changes and not merge them---leaving our master branch unchanged).
+
+##### On merges and "fast forward"
+
+You'll notice that we've been seeing the phrase "fast forward" several
+times. This is a special-case operation performed by "git merge" where
+a branch can be advanced along a linear sequence. This happens
+whenever you pull changes that build directly on top of the same
+commit you have as your most recent commit. In other words, there was
+never any divergence or simultaneous commits created in parallel in
+multiple repositories. If there had been parallel commits, then "git
+merge" would actually introduce a new merge commit to tie the two
+commits together.
+
+When a non-fast-forward merge occurs, there is always the possibility
+that a conflict occurs. In this case, "git merge" will leave conflict
+markers in the files and instruct you to resolve the conflicts. When
+you are finished, you would issue a "git commit -a" to create the
+merge commit.
+
+#### 2.8.3 Using "git remote" to pull changes from other repositories
+
+We've already described how "git pull" will pull in changes from the
+repository which was the origin of the clone operation. Git also
+provides excellent support for pulling changes from any other
+repository as well, (distributed, rather than centralized
+development).
+
+If you have a situation where you want to pull a single time from some
+repository, then you can simply give the path or URL of the repository
+on the "git pull" command line. However, it's often the case that if
+you want to pull changes from a repository once, you'll want to pull
+changes from that same repository again in the future. This is where
+the "git remote" notion is extremely useful---it allows you to
+associate simple names, (and behaviors), with remote repository URLs
+
+We've already seen one instance of "git remote" which is the creation
+of the "origin" remote which happens automatically during "git
+clone". Let's now create another. Let's assume you are going to be
+working in the hello-remote repository and you'd like to pull changes
+from the hello-pull repository, where your friend "fred" has been
+making changes. Here's how to setup the new remote:
+
+ $ cd ../hello-remote
+ $ git remote add fred ../hello-pull
+
+So that's a "git remote add" command line followed by an arbitrary
+name you'd like for the new remote (fred) and the URL of the remote
+(../hello-pull). Obviously, the URL could be a git:// URL or any other
+git-supported URL in addition to a local path.
+
+The "git remote" command is really just a helper for adding some
+entries to the .git/config file. You might find it more convenient to
+edit that file directly once you get comfortable with things.
+
+At this point the name "fred" will work much like the name "origin"
+has worked in previous examples. For example, we can fetch the changes
+fred has made with "git fetch fred":
+
+ $ git fetch fred
+ remote: Generating pack...
+ Unpacking 3 objects...
+ remote: Done counting 5 objects.
+ Result has 3 objects.
+ Deltifying 3 objects...
+ 100% remote: (3/3) done
+ Total 3 (delta 1), reused 0 (delta 0)
+ 100% (3/3) done
+ * refs/remotes/fred/master: storing branch 'master' of ../hello-pull
+ commit: 3c54ac6
+
+Notice that this command-line only differs from the "git fetch" we did
+previously by explicitly naming which remote should be fetched. We
+could have explicitly said "git fetch origin" earlier.
+
+We can also list all known remote-tracking branches with "git branch
+-r":
+
+ $ git branch -r
+ fred/master
+ origin/HEAD
+ origin/master
+
+These remote-tracking branches make it very easy to collaborate with
+people as they are working on experimental features not yet ready for
+upstream inclusion. For example, if fred's latest code is still
+trashing filesystems then he might not want to push it out to the
+project's primary repository. But he may still want my help with
+it. So he can push it to a branch in his own repository for which I've
+got a remote. Then on my next "git fetch fred" I might notice a new
+branch called fred/trashes-filesystems and I can examine his code with
+a command such as "git log ..fred/trashed-filesystems".
+
+So lots of side collaboration can go on easily, and people working
+only with the primary repository never even have to see this dangerous
+code. It's distributed development at its finest.
+
+#### 2.8.4 Checking out previous revisions
+
+It's often useful to examine the working-tree state of some specific
+revision other than the tip of some branch. For example, maybe you
+would like to build a particular tagged version, or maybe you'd like
+to test the behavior of the code before a particular change was
+introduced. To do this, use "git checkout" and pass it the name of any
+revision, (with a branch name, a tag name, or any other commit
+identifier). For example, to examine our project before the original
+typo was introduced:
+
+ $ git checkout 0a633bf5
+ Note: moving to "0a633bf5" which isn't a local branch
+ If you want to create a new branch from this checkout, you may do so
+ (now or later) by using -b with the checkout command again. Example:
+ git checkout -b <new_branch_name>
+ HEAD is now at 0a633bf... Create a makefile
+
+The note that git gives us is to indicate that we are checking out a
+non-branch revision. This is perfectly fine if we are just exploring
+history, but if we actually wanted to use this revision as the basis
+for new commits, we would first have to create a new branch name as it
+describes.
+
+If we were to use "git checkout" with a branch name, then that would
+change the current branch, (meaning that any new commits would advance
+that branch pointer).
+
+For now, let's return back to the tip of the master branch by just
+checking it out again:
+
+ $ git checkout master
+ Previous HEAD position was 0a633bf... Create a makefile
+ Switched to branch "master"
+
+#### 2.8.5 Pushing changes to another repository
+
+As an unsurprising parallel to "git pull", git also provides "git
+push" for pushing changes to another repository. Now, generally the
+purpose of pushing to a repository is to have some "collaboration
+point" where potentially multiple people might be pushing or
+pulling. Because there might be multiple people pushing into the
+repository at any point, it wouldn't make sense to have a
+working-directory associated with this repository.
+
+For this, git has the notion of a "bare" repository, which is simply a
+repository with no working directory. Let's create a new bare
+repository and push some changes into it:
+
+ $ cd ..
+ $ mkdir hello-bare
+ $ cd hello-bare
+ $ git --bare init --shared
+
+The --shared option sets up the necessary group file permissions so
+that other users in my group will be able to push into this repository
+as well.
+
+Now lets return to our hello repository and push some changes to this
+new repository. Since this is our very first push into this repository
+we need to tell git which branches to push. The easiest way to do this
+is to use --all to indicate all branches:
+
+ $ cd ../hello
+ $ git push ../hello-bare --all
+ updating 'refs/heads/master'
+ from 0000000000000000000000000000000000000000
+ to 3c54ac672ec1130b36837f1b708054a7a1d402de
+ Generating pack...
+ Done counting 18 objects.
+ Deltifying 18 objects...
+ 100% (18/18) done
+ Writing 18 objects...
+ 100% (18/18) done
+ Total 18 (delta 3), reused 15 (delta 2)
+ Unpacking 18 objects...
+ 100% (18/18) done
+ refs/heads/master: 0000000000000000000000000000000000000000 -> 3c54ac672ec1130b36837f1b708054a7a1d402de
+
+For subsequent pushes we don't need to specify --all as "git push" by
+default pushes all branches that exist in both the local and remote
+repositories. Also, as with pull, instead of explicitly specifying a
+URL, you may also specify a remote to push to. And by default, after
+cloning a repository, "git push" with no other arguments will attempt
+to push back to the same origin repository. As this is often exactly
+what is wanted, you may find that "git push" alone is often exactly
+what you need.