Code

Merge branch 'np/delta'
[git.git] / Documentation / user-manual.txt
index 55d4d37b210e7f43d67a6d4d4991e5ca3640e727..4fabb8e2a9e601c82b55ac25b1b9d8cfb9a06d3a 100644 (file)
@@ -1,6 +1,9 @@
 Git User's Manual (for version 1.5.1 or newer)
 ______________________________________________
 
 Git User's Manual (for version 1.5.1 or newer)
 ______________________________________________
 
+
+Git is a fast distributed revision control system.
+
 This manual is designed to be readable by someone with basic unix
 command-line skills, but no previous knowledge of git.
 
 This manual is designed to be readable by someone with basic unix
 command-line skills, but no previous knowledge of git.
 
@@ -690,6 +693,25 @@ may be any path to a file tracked by git.
 Examples
 --------
 
 Examples
 --------
 
+[[counting-commits-on-a-branch]]
+Counting the number of commits on a branch
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Suppose you want to know how many commits you've made on "mybranch"
+since it diverged from "origin":
+
+-------------------------------------------------
+$ git log --pretty=oneline origin..mybranch | wc -l
+-------------------------------------------------
+
+Alternatively, you may often see this sort of thing done with the
+lower-level command gitlink:git-rev-list[1], which just lists the SHA1's
+of all the given commits:
+
+-------------------------------------------------
+$ git rev-list origin..mybranch | wc -l
+-------------------------------------------------
+
 [[checking-for-equal-branches]]
 Check whether two branches point at the same history
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 [[checking-for-equal-branches]]
 Check whether two branches point at the same history
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -808,6 +830,54 @@ available
 Which shows that e05db0fd is reachable from itself, from v1.5.0-rc1, and
 from v1.5.0-rc2, but not from v1.5.0-rc0.
 
 Which shows that e05db0fd is reachable from itself, from v1.5.0-rc1, and
 from v1.5.0-rc2, but not from v1.5.0-rc0.
 
+[[showing-commits-unique-to-a-branch]]
+Showing commits unique to a given branch
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Suppose you would like to see all the commits reachable from the branch
+head named "master" but not from any other head in your repository.
+
+We can list all the heads in this repository with
+gitlink:git-show-ref[1]:
+
+-------------------------------------------------
+$ git show-ref --heads
+bf62196b5e363d73353a9dcf094c59595f3153b7 refs/heads/core-tutorial
+db768d5504c1bb46f63ee9d6e1772bd047e05bf9 refs/heads/maint
+a07157ac624b2524a059a3414e99f6f44bebc1e7 refs/heads/master
+24dbc180ea14dc1aebe09f14c8ecf32010690627 refs/heads/tutorial-2
+1e87486ae06626c2f31eaa63d26fc0fd646c8af2 refs/heads/tutorial-fixes
+-------------------------------------------------
+
+We can get just the branch-head names, and remove "master", with
+the help of the standard utilities cut and grep:
+
+-------------------------------------------------
+$ git show-ref --heads | cut -d' ' -f2 | grep -v '^refs/heads/master'
+refs/heads/core-tutorial
+refs/heads/maint
+refs/heads/tutorial-2
+refs/heads/tutorial-fixes
+-------------------------------------------------
+
+And then we can ask to see all the commits reachable from master
+but not from these other heads:
+
+-------------------------------------------------
+$ gitk master --not $( git show-ref --heads | cut -d' ' -f2 |
+                               grep -v '^refs/heads/master' )
+-------------------------------------------------
+
+Obviously, endless variations are possible; for example, to see all
+commits reachable from some head but not from any tag in the repository:
+
+-------------------------------------------------
+$ gitk $( git show-ref --heads ) --not  $( git show-ref --tags )
+-------------------------------------------------
+
+(See gitlink:git-rev-parse[1] for explanations of commit-selecting
+syntax such as `--not`.)
+
 [[making-a-release]]
 Creating a changelog and tarball for a software release
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 [[making-a-release]]
 Creating a changelog and tarball for a software release
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -851,6 +921,22 @@ echo "git diff --stat --summary -M v$last v$new > ../diffstat-$new"
 and then he just cut-and-pastes the output commands after verifying that
 they look OK.
 
 and then he just cut-and-pastes the output commands after verifying that
 they look OK.
 
+Finding commits referencing a file with given content
+-----------------------------------------------------
+
+Somebody hands you a copy of a file, and asks which commits modified a
+file such that it contained the given content either before or after the
+commit.  You can find out with this:
+
+-------------------------------------------------
+$  git log --raw -r --abbrev=40 --pretty=oneline -- filename |
+       grep -B 1 `git hash-object filename`
+-------------------------------------------------
+
+Figuring out why this works is left as an exercise to the (advanced)
+student.  The gitlink:git-log[1], gitlink:git-diff-tree[1], and
+gitlink:git-hash-object[1] man pages may prove helpful.
+
 [[Developing-with-git]]
 Developing with git
 ===================
 [[Developing-with-git]]
 Developing with git
 ===================
@@ -1003,6 +1089,75 @@ description.  Tools that turn commits into email, for example, use
 the first line on the Subject line and the rest of the commit in the
 body.
 
 the first line on the Subject line and the rest of the commit in the
 body.
 
+[[ignoring-files]]
+Ignoring files
+--------------
+
+A project will often generate files that you do 'not' want to track with git.
+This typically includes files generated by a build process or temporary
+backup files made by your editor. Of course, 'not' tracking files with git
+is just a matter of 'not' calling "`git add`" on them. But it quickly becomes
+annoying to have these untracked files lying around; e.g. they make
+"`git add .`" and "`git commit -a`" practically useless, and they keep
+showing up in the output of "`git status`", etc.
+
+Git therefore provides "exclude patterns" for telling git which files to
+actively ignore. Exclude patterns are thoroughly explained in the
+"Exclude Patterns" section of the gitlink:git-ls-files[1] manual page,
+but the heart of the concept is simply a list of files which git should
+ignore. Entries in the list may contain globs to specify multiple files,
+or may be prefixed by "`!`" to explicitly include (un-ignore) a previously
+excluded (ignored) file (i.e. later exclude patterns override earlier ones).
+The following example should illustrate such patterns:
+
+-------------------------------------------------
+# Lines starting with '#' are considered comments.
+# Ignore foo.txt.
+foo.txt
+# Ignore (generated) html files,
+*.html
+# except foo.html which is maintained by hand.
+!foo.html
+# Ignore objects and archives.
+*.[oa]
+-------------------------------------------------
+
+The next question is where to put these exclude patterns so that git can
+find them. Git looks for exclude patterns in the following files:
+
+`.gitignore` files in your working tree:::
+          You may store multiple `.gitignore` files at various locations in your
+          working tree. Each `.gitignore` file is applied to the directory where
+          it's located, including its subdirectories. Furthermore, the
+          `.gitignore` files can be tracked like any other files in your working
+          tree; just do a "`git add .gitignore`" and commit. `.gitignore` is
+          therefore the right place to put exclude patterns that are meant to
+          be shared between all project participants, such as build output files
+          (e.g. `\*.o`), etc.
+`.git/info/exclude` in your repo:::
+          Exclude patterns in this file are applied to the working tree as a
+          whole. Since the file is not located in your working tree, it does
+          not follow push/pull/clone like `.gitignore` can do. This is therefore
+          the place to put exclude patterns that are local to your copy of the
+          repo (i.e. 'not' shared between project participants), such as
+          temporary backup files made by your editor (e.g. `\*~`), etc.
+The file specified by the `core.excludesfile` config directive:::
+          By setting the `core.excludesfile` config directive you can tell git
+          where to find more exclude patterns (see gitlink:git-config[1] for
+          more information on configuration options). This config directive
+          can be set in the per-repo `.git/config` file, in which case the
+          exclude patterns will apply to that repo only. Alternatively, you
+          can set the directive in the global `~/.gitconfig` file to apply
+          the exclude pattern to all your git repos. As with the above
+          `.git/info/exclude` (and, indeed, with git config directives in
+          general), this directive does not follow push/pull/clone, but remain
+          local to your repo(s).
+
+[NOTE]
+In addition to the above alternatives, there are git commands that can take
+exclude patterns directly on the command line. See gitlink:git-ls-files[1]
+for an example of this.
+
 [[how-to-merge]]
 How to merge
 ------------
 [[how-to-merge]]
 How to merge
 ------------
@@ -1604,31 +1759,30 @@ The final result will be a series of commits, one for each patch in
 the original mailbox, with authorship and commit log message each
 taken from the message containing each patch.
 
 the original mailbox, with authorship and commit log message each
 taken from the message containing each patch.
 
-[[setting-up-a-public-repository]]
-Setting up a public repository
-------------------------------
+[[public-repositories]]
+Public git repositories
+-----------------------
 
 
-Another way to submit changes to a project is to simply tell the
-maintainer of that project to pull from your repository, exactly as
-you did in the section "<<getting-updates-with-git-pull, Getting
-updates with git pull>>".
+Another way to submit changes to a project is to tell the maintainer of
+that project to pull the changes from your repository using git-pull[1].
+In the section "<<getting-updates-with-git-pull, Getting updates with
+git pull>>" we described this as a way to get updates from the "main"
+repository, but it works just as well in the other direction.
 
 
-If you and maintainer both have accounts on the same machine, then
-then you can just pull changes from each other's repositories
-directly; note that all of the commands (gitlink:git-clone[1],
-git-fetch[1], git-pull[1], etc.) that accept a URL as an argument
-will also accept a local directory name; so, for example, you can
-use
+If you and the maintainer both have accounts on the same machine, then
+you can just pull changes from each other's repositories directly;
+commands that accepts repository URLs as arguments will also accept a
+local directory name:
 
 -------------------------------------------------
 $ git clone /path/to/repository
 $ git pull /path/to/other/repository
 -------------------------------------------------
 
 
 -------------------------------------------------
 $ git clone /path/to/repository
 $ git pull /path/to/other/repository
 -------------------------------------------------
 
-If this sort of setup is inconvenient or impossible, another (more
-common) option is to set up a public repository on a public server.
-This also allows you to cleanly separate private work in progress
-from publicly visible work.
+However, the more common way to do this is to maintain a separate public
+repository (usually on a different host) for others to pull changes
+from.  This is usually more convenient, and allows you to cleanly
+separate private work in progress from publicly visible work.
 
 You will continue to do your day-to-day work in your personal
 repository, but periodically "push" changes from your personal
 
 You will continue to do your day-to-day work in your personal
 repository, but periodically "push" changes from your personal
@@ -1647,32 +1801,52 @@ like this:
         |               they push             V
   their public repo <------------------- their repo
 
         |               they push             V
   their public repo <------------------- their repo
 
-Now, assume your personal repository is in the directory ~/proj.  We
-first create a new clone of the repository:
+[[setting-up-a-public-repository]]
+Setting up a public repository
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Assume your personal repository is in the directory ~/proj.  We
+first create a new clone of the repository and tell git-daemon that it
+is meant to be public:
 
 -------------------------------------------------
 $ git clone --bare ~/proj proj.git
 
 -------------------------------------------------
 $ git clone --bare ~/proj proj.git
+$ touch proj.git/git-daemon-export-ok
 -------------------------------------------------
 
 The resulting directory proj.git contains a "bare" git repository--it is
 -------------------------------------------------
 
 The resulting directory proj.git contains a "bare" git repository--it is
-just the contents of the ".git" directory, without a checked-out copy of
-a working directory.
+just the contents of the ".git" directory, without any files checked out
+around it.
 
 Next, copy proj.git to the server where you plan to host the
 public repository.  You can use scp, rsync, or whatever is most
 convenient.
 
 
 Next, copy proj.git to the server where you plan to host the
 public repository.  You can use scp, rsync, or whatever is most
 convenient.
 
-If somebody else maintains the public server, they may already have
-set up a git service for you, and you may skip to the section
+[[exporting-via-git]]
+Exporting a git repository via the git protocol
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This is the preferred method.
+
+If someone else administers the server, they should tell you what
+directory to put the repository in, and what git:// url it will appear
+at.  You can then skip to the section
 "<<pushing-changes-to-a-public-repository,Pushing changes to a public
 repository>>", below.
 
 "<<pushing-changes-to-a-public-repository,Pushing changes to a public
 repository>>", below.
 
-Otherwise, the following sections explain how to export your newly
-created public repository:
+Otherwise, all you need to do is start gitlink:git-daemon[1]; it will
+listen on port 9418.  By default, it will allow access to any directory
+that looks like a git directory and contains the magic file
+git-daemon-export-ok.  Passing some directory paths as git-daemon
+arguments will further restrict the exports to those paths.
+
+You can also run git-daemon as an inetd service; see the
+gitlink:git-daemon[1] man page for details.  (See especially the
+examples section.)
 
 [[exporting-via-http]]
 Exporting a git repository via http
 
 [[exporting-via-http]]
 Exporting a git repository via http
------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 The git protocol gives better performance and reliability, but on a
 host with a web server set up, http exports may be simpler to set up.
 
 The git protocol gives better performance and reliability, but on a
 host with a web server set up, http exports may be simpler to set up.
@@ -1690,7 +1864,7 @@ $ chmod a+x hooks/post-update
 
 (For an explanation of the last two lines, see
 gitlink:git-update-server-info[1], and the documentation
 
 (For an explanation of the last two lines, see
 gitlink:git-update-server-info[1], and the documentation
-link:hooks.txt[Hooks used by git].)
+link:hooks.html[Hooks used by git].)
 
 Advertise the url of proj.git.  Anybody else should then be able to
 clone or pull from that url, for example with a commandline like:
 
 Advertise the url of proj.git.  Anybody else should then be able to
 clone or pull from that url, for example with a commandline like:
@@ -1704,20 +1878,11 @@ link:howto/setup-git-server-over-http.txt[setup-git-server-over-http]
 for a slightly more sophisticated setup using WebDAV which also
 allows pushing over http.)
 
 for a slightly more sophisticated setup using WebDAV which also
 allows pushing over http.)
 
-[[exporting-via-git]]
-Exporting a git repository via the git protocol
------------------------------------------------
-
-This is the preferred method.
-
-For now, we refer you to the gitlink:git-daemon[1] man page for
-instructions.  (See especially the examples section.)
-
 [[pushing-changes-to-a-public-repository]]
 Pushing changes to a public repository
 [[pushing-changes-to-a-public-repository]]
 Pushing changes to a public repository
---------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 
-Note that the two techniques outline above (exporting via
+Note that the two techniques outlined above (exporting via
 <<exporting-via-http,http>> or <<exporting-via-git,git>>) allow other
 maintainers to fetch your latest changes, but they do not allow write
 access, which you will need to update the public repository with the
 <<exporting-via-http,http>> or <<exporting-via-git,git>>) allow other
 maintainers to fetch your latest changes, but they do not allow write
 access, which you will need to update the public repository with the
@@ -1769,17 +1934,38 @@ details.
 
 [[setting-up-a-shared-repository]]
 Setting up a shared repository
 
 [[setting-up-a-shared-repository]]
 Setting up a shared repository
-------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Another way to collaborate is by using a model similar to that
 commonly used in CVS, where several developers with special rights
 all push to and pull from a single shared repository.  See
 
 Another way to collaborate is by using a model similar to that
 commonly used in CVS, where several developers with special rights
 all push to and pull from a single shared repository.  See
-link:cvs-migration.txt[git for CVS users] for instructions on how to
+link:cvs-migration.html[git for CVS users] for instructions on how to
 set this up.
 
 set this up.
 
+However, while there is nothing wrong with git's support for shared
+repositories, this mode of operation is not generally recommended,
+simply because the mode of collaboration that git supports--by
+exchanging patches and pulling from public repositories--has so many
+advantages over the central shared repository:
+
+       - Git's ability to quickly import and merge patches allows a
+         single maintainer to process incoming changes even at very
+         high rates.  And when that becomes too much, git-pull provides
+         an easy way for that maintainer to delegate this job to other
+         maintainers while still allowing optional review of incoming
+         changes.
+       - Since every developer's repository has the same complete copy
+         of the project history, no repository is special, and it is
+         trivial for another developer to take over maintenance of a
+         project, either by mutual agreement, or because a maintainer
+         becomes unresponsive or difficult to work with.
+       - The lack of a central group of "committers" means there is
+         less need for formal decisions about who is "in" and who is
+         "out".
+
 [[setting-up-gitweb]]
 [[setting-up-gitweb]]
-Allow web browsing of a repository
-----------------------------------
+Allowing web browsing of a repository
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 The gitweb cgi script provides users an easy way to browse your
 project's files and history without having to install git; see the file
 
 The gitweb cgi script provides users an easy way to browse your
 project's files and history without having to install git; see the file
@@ -1789,7 +1975,302 @@ gitweb/INSTALL in the git source tree for instructions on setting it up.
 Examples
 --------
 
 Examples
 --------
 
-TODO: topic branches, typical roles as in everyday.txt, ?
+[[maintaining-topic-branches]]
+Maintaining topic branches for a Linux subsystem maintainer
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This describes how Tony Luck uses git in his role as maintainer of the
+IA64 architecture for the Linux kernel.
+
+He uses two public branches:
+
+ - A "test" tree into which patches are initially placed so that they
+   can get some exposure when integrated with other ongoing development.
+   This tree is available to Andrew for pulling into -mm whenever he
+   wants.
+
+ - A "release" tree into which tested patches are moved for final sanity
+   checking, and as a vehicle to send them upstream to Linus (by sending
+   him a "please pull" request.)
+
+He also uses a set of temporary branches ("topic branches"), each
+containing a logical grouping of patches.
+
+To set this up, first create your work tree by cloning Linus's public
+tree:
+
+-------------------------------------------------
+$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git work
+$ cd work
+-------------------------------------------------
+
+Linus's tree will be stored in the remote branch named origin/master,
+and can be updated using gitlink:git-fetch[1]; you can track other
+public trees using gitlink:git-remote[1] to set up a "remote" and
+git-fetch[1] to keep them up-to-date; see <<repositories-and-branches>>.
+
+Now create the branches in which you are going to work; these start out
+at the current tip of origin/master branch, and should be set up (using
+the --track option to gitlink:git-branch[1]) to merge changes in from
+Linus by default.
+
+-------------------------------------------------
+$ git branch --track test origin/master
+$ git branch --track release origin/master
+-------------------------------------------------
+
+These can be easily kept up to date using gitlink:git-pull[1]
+
+-------------------------------------------------
+$ git checkout test && git pull
+$ git checkout release && git pull
+-------------------------------------------------
+
+Important note!  If you have any local changes in these branches, then
+this merge will create a commit object in the history (with no local
+changes git will simply do a "Fast forward" merge).  Many people dislike
+the "noise" that this creates in the Linux history, so you should avoid
+doing this capriciously in the "release" branch, as these noisy commits
+will become part of the permanent history when you ask Linus to pull
+from the release branch.
+
+A few configuration variables (see gitlink:git-config[1]) can
+make it easy to push both branches to your public tree.  (See
+<<setting-up-a-public-repository>>.)
+
+-------------------------------------------------
+$ cat >> .git/config <<EOF
+[remote "mytree"]
+       url =  master.kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git
+       push = release
+       push = test
+EOF
+-------------------------------------------------
+
+Then you can push both the test and release trees using
+gitlink:git-push[1]:
+
+-------------------------------------------------
+$ git push mytree
+-------------------------------------------------
+
+or push just one of the test and release branches using:
+
+-------------------------------------------------
+$ git push mytree test
+-------------------------------------------------
+
+or
+
+-------------------------------------------------
+$ git push mytree release
+-------------------------------------------------
+
+Now to apply some patches from the community.  Think of a short
+snappy name for a branch to hold this patch (or related group of
+patches), and create a new branch from the current tip of Linus's
+branch:
+
+-------------------------------------------------
+$ git checkout -b speed-up-spinlocks origin
+-------------------------------------------------
+
+Now you apply the patch(es), run some tests, and commit the change(s).  If
+the patch is a multi-part series, then you should apply each as a separate
+commit to this branch.
+
+-------------------------------------------------
+$ ... patch ... test  ... commit [ ... patch ... test ... commit ]*
+-------------------------------------------------
+
+When you are happy with the state of this change, you can pull it into the
+"test" branch in preparation to make it public:
+
+-------------------------------------------------
+$ git checkout test && git pull . speed-up-spinlocks
+-------------------------------------------------
+
+It is unlikely that you would have any conflicts here ... but you might if you
+spent a while on this step and had also pulled new versions from upstream.
+
+Some time later when enough time has passed and testing done, you can pull the
+same branch into the "release" tree ready to go upstream.  This is where you
+see the value of keeping each patch (or patch series) in its own branch.  It
+means that the patches can be moved into the "release" tree in any order.
+
+-------------------------------------------------
+$ git checkout release && git pull . speed-up-spinlocks
+-------------------------------------------------
+
+After a while, you will have a number of branches, and despite the
+well chosen names you picked for each of them, you may forget what
+they are for, or what status they are in.  To get a reminder of what
+changes are in a specific branch, use:
+
+-------------------------------------------------
+$ git log linux..branchname | git-shortlog
+-------------------------------------------------
+
+To see whether it has already been merged into the test or release branches
+use:
+
+-------------------------------------------------
+$ git log test..branchname
+-------------------------------------------------
+
+or
+
+-------------------------------------------------
+$ git log release..branchname
+-------------------------------------------------
+
+(If this branch has not yet been merged you will see some log entries.
+If it has been merged, then there will be no output.)
+
+Once a patch completes the great cycle (moving from test to release,
+then pulled by Linus, and finally coming back into your local
+"origin/master" branch) the branch for this change is no longer needed.
+You detect this when the output from:
+
+-------------------------------------------------
+$ git log origin..branchname
+-------------------------------------------------
+
+is empty.  At this point the branch can be deleted:
+
+-------------------------------------------------
+$ git branch -d branchname
+-------------------------------------------------
+
+Some changes are so trivial that it is not necessary to create a separate
+branch and then merge into each of the test and release branches.  For
+these changes, just apply directly to the "release" branch, and then
+merge that into the "test" branch.
+
+To create diffstat and shortlog summaries of changes to include in a "please
+pull" request to Linus you can use:
+
+-------------------------------------------------
+$ git diff --stat origin..release
+-------------------------------------------------
+
+and
+
+-------------------------------------------------
+$ git log -p origin..release | git shortlog
+-------------------------------------------------
+
+Here are some of the scripts that simplify all this even further.
+
+-------------------------------------------------
+==== update script ====
+# Update a branch in my GIT tree.  If the branch to be updated
+# is origin, then pull from kernel.org.  Otherwise merge
+# origin/master branch into test|release branch
+
+case "$1" in
+test|release)
+       git checkout $1 && git pull . origin
+       ;;
+origin)
+       before=$(cat .git/refs/remotes/origin/master)
+       git fetch origin
+       after=$(cat .git/refs/remotes/origin/master)
+       if [ $before != $after ]
+       then
+               git log $before..$after | git shortlog
+       fi
+       ;;
+*)
+       echo "Usage: $0 origin|test|release" 1>&2
+       exit 1
+       ;;
+esac
+-------------------------------------------------
+
+-------------------------------------------------
+==== merge script ====
+# Merge a branch into either the test or release branch
+
+pname=$0
+
+usage()
+{
+       echo "Usage: $pname branch test|release" 1>&2
+       exit 1
+}
+
+if [ ! -f .git/refs/heads/"$1" ]
+then
+       echo "Can't see branch <$1>" 1>&2
+       usage
+fi
+
+case "$2" in
+test|release)
+       if [ $(git log $2..$1 | wc -c) -eq 0 ]
+       then
+               echo $1 already merged into $2 1>&2
+               exit 1
+       fi
+       git checkout $2 && git pull . $1
+       ;;
+*)
+       usage
+       ;;
+esac
+-------------------------------------------------
+
+-------------------------------------------------
+==== status script ====
+# report on status of my ia64 GIT tree
+
+gb=$(tput setab 2)
+rb=$(tput setab 1)
+restore=$(tput setab 9)
+
+if [ `git rev-list test..release | wc -c` -gt 0 ]
+then
+       echo $rb Warning: commits in release that are not in test $restore
+       git log test..release
+fi
+
+for branch in `ls .git/refs/heads`
+do
+       if [ $branch = test -o $branch = release ]
+       then
+               continue
+       fi
+
+       echo -n $gb ======= $branch ====== $restore " "
+       status=
+       for ref in test release origin/master
+       do
+               if [ `git rev-list $ref..$branch | wc -c` -gt 0 ]
+               then
+                       status=$status${ref:0:1}
+               fi
+       done
+       case $status in
+       trl)
+               echo $rb Need to pull into test $restore
+               ;;
+       rl)
+               echo "In test"
+               ;;
+       l)
+               echo "Waiting for linus"
+               ;;
+       "")
+               echo $rb All done $restore
+               ;;
+       *)
+               echo $rb "<$status>" $restore
+               ;;
+       esac
+       git log origin/master..$branch | git shortlog
+done
+-------------------------------------------------
 
 
 [[cleaning-up-history]]
 
 
 [[cleaning-up-history]]
@@ -3441,8 +3922,6 @@ Think about how to create a clear chapter dependency graph that will
 allow people to get to important topics without necessarily reading
 everything in between.
 
 allow people to get to important topics without necessarily reading
 everything in between.
 
-Say something about .gitignore.
-
 Scan Documentation/ for other stuff left out; in particular:
        howto's
        some of technical/?
 Scan Documentation/ for other stuff left out; in particular:
        howto's
        some of technical/?