GIT 1.6.0.6

Signed-off-by: Junio C Hamano <gitster@pobox.com>
diff --git a/.gitignore b/.gitignore
index 4ff2fec..a213e8e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -75,7 +75,6 @@
 git-merge-ours
 git-merge-recursive
 git-merge-resolve
-git-merge-stupid
 git-merge-subtree
 git-mergetool
 git-mktag
@@ -142,7 +141,6 @@
 git-core-*/?*
 gitk-wish
 gitweb/gitweb.cgi
-test-absolute-path
 test-chmtime
 test-date
 test-delta
@@ -150,6 +148,7 @@
 test-genrandom
 test-match-trees
 test-parse-options
+test-path-utils
 test-sha1
 common-cmds.h
 *.tar.gz
diff --git a/.mailmap b/.mailmap
index f88ae77..373476b 100644
--- a/.mailmap
+++ b/.mailmap
@@ -5,22 +5,28 @@
 # same person appearing not to be so.
 #
 
+Alexander Gavrilov <angavrilov@gmail.com>
 Aneesh Kumar K.V <aneesh.kumar@gmail.com>
 Brian M. Carlson <sandals@crustytoothpaste.ath.cx>
 Chris Shoemaker <c.shoemaker@cox.net>
 Dana L. How <danahow@gmail.com>
 Dana L. How <how@deathvalley.cswitch.com>
 Daniel Barkalow <barkalow@iabervon.org>
+David D. Kilzer <ddkilzer@kilzer.net>
 David Kågedal <davidk@lysator.liu.se>
+David S. Miller <davem@davemloft.net>
+Dirk Süsserott <newsletter@dirk.my1.cc>
 Fredrik Kuivinen <freku045@student.liu.se>
 H. Peter Anvin <hpa@bonde.sc.orionmulti.com>
 H. Peter Anvin <hpa@tazenda.sc.orionmulti.com>
 H. Peter Anvin <hpa@trantor.hos.anvin.org>
 Horst H. von Brand <vonbrand@inf.utfsm.cl>
+İsmail Dönmez <ismail@pardus.org.tr>
 Jay Soffian <jaysoffian+git@gmail.com>
 Joachim Berdal Haga <cjhaga@fys.uio.no>
 Jon Loeliger <jdl@freescale.com>
 Jon Seymour <jon@blackcubes.dyndns.org>
+Jonathan Nieder <jrnieder@uchicago.edu>
 Junio C Hamano <junio@twinsun.com>
 Karl Hasselström <kha@treskal.com>
 Kent Engstrom <kent@lysator.liu.se>
@@ -30,9 +36,12 @@
 Lukas Sandström <lukass@etek.chalmers.se>
 Martin Langhoff <martin@catalyst.net.nz>
 Michael Coleman <tutufan@gmail.com>
+Michael W. Olson <mwolson@gnu.org>
 Michele Ballabio <barra_cuda@katamail.com>
 Nanako Shiraishi <nanako3@bluebottle.com>
+Nanako Shiraishi <nanako3@lavabit.com>
 Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
+Philippe Bruhat <book@cpan.org>
 Ramsay Allan Jones <ramsay@ramsay1.demon.co.uk>
 René Scharfe <rene.scharfe@lsrfire.ath.cx>
 Robert Fitzsimons <robfitz@273k.net>
diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines
index d2a0a76..f628c1f 100644
--- a/Documentation/CodingGuidelines
+++ b/Documentation/CodingGuidelines
@@ -105,7 +105,7 @@
 
  - Use the API.  No, really.  We have a strbuf (variable length
    string), several arrays with the ALLOC_GROW() macro, a
-   path_list for sorted string lists, a hash map (mapping struct
+   string_list for sorted string lists, a hash map (mapping struct
    objects) named "struct decorate", amongst other things.
 
  - When you come up with an API, document it.
diff --git a/Documentation/RelNotes-1.6.0.1.txt b/Documentation/RelNotes-1.6.0.1.txt
new file mode 100644
index 0000000..49d7a1c
--- /dev/null
+++ b/Documentation/RelNotes-1.6.0.1.txt
@@ -0,0 +1,36 @@
+GIT v1.6.0.1 Release Notes
+==========================
+
+Fixes since v1.6.0
+------------------
+
+* "git diff --cc" did not honor content mangling specified by
+  gitattributes and core.autocrlf when reading from the work tree.
+
+* "git diff --check" incorrectly detected new trailing blank lines when
+  whitespace check was in effect.
+
+* "git for-each-ref" tried to dereference NULL when asked for '%(body)" on
+  a tag with a single incomplete line as its payload.
+
+* "git format-patch" peeked before the beginning of a string when
+  "format.headers" variable is empty (a misconfiguration).
+
+* "git help help" did not work correctly.
+
+* "git mailinfo" (hence "git am") was unhappy when MIME multipart message
+  contained garbage after the finishing boundary.
+
+* "git mailinfo" also was unhappy when the "From: " line only had a bare
+  e-mail address.
+
+* "git merge" did not refresh the index correctly when a merge resulted in
+  a fast-forward.
+
+* "git merge" did not resolve a truly trivial merges that can be done
+  without content level merges.
+
+* "git svn dcommit" to a repository with URL that has embedded usernames
+  did not work correctly.
+
+Contains other various documentation fixes.
diff --git a/Documentation/RelNotes-1.6.0.2.txt b/Documentation/RelNotes-1.6.0.2.txt
new file mode 100644
index 0000000..7a9646f
--- /dev/null
+++ b/Documentation/RelNotes-1.6.0.2.txt
@@ -0,0 +1,87 @@
+GIT v1.6.0.2 Release Notes
+==========================
+
+Fixes since v1.6.0.1
+--------------------
+
+* Installation on platforms that needs .exe suffix to git-* programs were
+  broken in 1.6.0.1.
+
+* Installation on filesystems without symbolic links support did nto
+  work well.
+
+* In-tree documentations and test scripts now use "git foo" form to set a
+  better example, instead of the "git-foo" form (which is an acceptable
+  form if you have "PATH=$(git --exec-path):$PATH" in your script)
+
+* Many commands did not use the correct working tree location when used
+  with GIT_WORK_TREE environment settings.
+
+* Some systems needs to use compatibility fnmach and regex libraries
+  independent from each other; the compat/ area has been reorganized to
+  allow this.
+
+
+* "git apply --unidiff-zero" incorrectly applied a -U0 patch that inserts
+  a new line before the second line.
+
+* "git blame -c" did not exactly work like "git annotate" when range
+  boundaries are involved.
+
+* "git checkout file" when file is still unmerged checked out contents from
+  a random high order stage, which was confusing.
+
+* "git clone $there $here/" with extra trailing slashes after explicit
+  local directory name $here did not work as expected.
+
+* "git diff" on tracked contents with CRLF line endings did not drive "less"
+  intelligently when showing added or removed lines.
+
+* "git diff --dirstat -M" did not add changes in subdirectories up
+  correctly for renamed paths.
+
+* "git diff --cumulative" did not imply "--dirstat".
+
+* "git for-each-ref refs/heads/" did not work as expected.
+
+* "git gui" allowed users to feed patch without any context to be applied.
+
+* "git gui" botched parsing "diff" output when a line that begins with two
+  dashes and a space gets removed or a line that begins with two pluses
+  and a space gets added.
+
+* "git gui" translation updates and i18n fixes.
+
+* "git index-pack" is more careful against disk corruption while completing
+  a thin pack.
+
+* "git log -i --grep=pattern" did not ignore case; neither "git log -E
+  --grep=pattern" triggered extended regexp.
+
+* "git log --pretty="%ad" --date=short" did not use short format when
+  showing the timestamp.
+
+* "git log --author=author" match incorrectly matched with the
+  timestamp part of "author " line in commit objects.
+
+* "git log -F --author=author" did not work at all.
+
+* Build procedure for "git shell" that used stub versions of some
+  functions and globals was not understood by linkers on some platforms.
+
+* "git stash" was fooled by a stat-dirty but otherwise unmodified paths
+  and refused to work until the user refreshed the index.
+
+* "git svn" was broken on Perl before 5.8 with recent fixes to reduce
+  use of temporary files.
+
+* "git verify-pack -v" did not work correctly when given more than one
+  packfile.
+
+Also contains many documentation updates.
+
+--
+exec >/var/tmp/1
+O=v1.6.0.1-78-g3632cfc
+echo O=$(git describe maint)
+git shortlog --no-merges $O..maint
diff --git a/Documentation/RelNotes-1.6.0.3.txt b/Documentation/RelNotes-1.6.0.3.txt
new file mode 100644
index 0000000..ae05778
--- /dev/null
+++ b/Documentation/RelNotes-1.6.0.3.txt
@@ -0,0 +1,117 @@
+GIT v1.6.0.3 Release Notes
+==========================
+
+Fixes since v1.6.0.2
+--------------------
+
+* "git archive --format=zip" did not honor core.autocrlf while
+  --format=tar did.
+
+* Continuing "git rebase -i" was very confused when the user left modified
+  files in the working tree while resolving conflicts.
+
+* Continuing "git rebase -i" was also very confused when the user left
+  some staged changes in the index after "edit".
+
+* "git rebase -i" now honors the pre-rebase hook, just like the
+  other rebase implementations "git rebase" and "git rebase -m".
+
+* "git rebase -i" incorrectly aborted when there is no commit to replay.
+
+* Behaviour of "git diff --quiet" was inconsistent with "diff --exit-code"
+  with the output redirected to /dev/null.
+
+* "git diff --no-index" on binary files no longer outputs a bogus
+  "diff --git" header line.
+
+* "git diff" hunk header patterns with multiple elements separated by LF
+  were not used correctly.
+
+* Hunk headers in "git diff" default to using extended regular
+  expressions, fixing some of the internal patterns on non-GNU
+  platforms.
+
+* New config "diff.*.xfuncname" exposes extended regular expressions
+  for user specified hunk header patterns.
+
+* "git gc" when ejecting otherwise unreachable objects from packfiles into
+  loose form leaked memory.
+
+* "git index-pack" was recently broken and mishandled objects added by
+  thin-pack completion processing under memory pressure.
+
+* "git index-pack" was recently broken and misbehaved when run from inside
+  .git/objects/pack/ directory.
+
+* "git stash apply sash@{1}" was fixed to error out.  Prior versions
+  would have applied stash@{0} incorrectly.
+
+* "git stash apply" now offers a better suggestion on how to continue
+  if the working tree is currently dirty.
+
+* "git for-each-ref --format=%(subject)" fixed for commits with no
+  no newline in the message body.
+
+* "git remote" fixed to protect printf from user input.
+
+* "git remote show -v" now displays all URLs of a remote.
+
+* "git checkout -b branch" was confused when branch already existed.
+
+* "git checkout -q" once again suppresses the locally modified file list.
+
+* "git clone -q", "git fetch -q" asks remote side to not send
+  progress messages, actually making their output quiet.
+
+* Cross-directory renames are no longer used when creating packs.  This
+  allows more graceful behavior on filesystems like sshfs.
+
+* Stale temporary files under $GIT_DIR/objects/pack are now cleaned up
+  automatically by "git prune".
+
+* "git merge" once again removes directories after the last file has
+  been removed from it during the merge.
+
+* "git merge" did not allocate enough memory for the structure itself when
+  enumerating the parents of the resulting commit.
+
+* "git blame -C -C" no longer segfaults while trying to pass blame if
+   it encounters a submodule reference.
+
+* "git rm" incorrectly claimed that you have local modifications when a
+  path was merely stat-dirty.
+
+* "git svn" fixed to display an error message when 'set-tree' failed,
+   instead of a Perl compile error.
+
+* "git submodule" fixed to handle checking out a different commit
+  than HEAD after initializing the submodule.
+
+* The "git commit" error message when there are still unmerged
+  files present was clarified to match "git write-tree".
+
+* "git init" was confused when core.bare or core.sharedRepository are set
+  in system or user global configuration file by mistake.  When --bare or
+  --shared is given from the command line, these now override such
+  settings made outside the repositories.
+
+* Some segfaults due to uncaught NULL pointers were fixed in multiple
+  tools such as apply, reset, update-index.
+
+* Solaris builds now default to OLD_ICONV=1 to avoid compile warnings;
+  Solaris 8 does not define NEEDS_LIBICONV by default.
+
+* "Git.pm" tests relied on unnecessarily more recent version of Perl.
+
+* "gitweb" triggered undef warning on commits without log messages.
+
+* "gitweb" triggered undef warnings on missing trees.
+
+* "gitweb" now removes PATH_INFO from its URLs so users don't have
+  to manually set the URL in the gitweb configuration.
+
+* Bash completion removed support for legacy "git-fetch", "git-push"
+  and "git-pull" as these are no longer installed.  Dashless form
+  ("git fetch") is still however supported.
+
+Many other documentation updates.
diff --git a/Documentation/RelNotes-1.6.0.4.txt b/Documentation/RelNotes-1.6.0.4.txt
new file mode 100644
index 0000000..d522661
--- /dev/null
+++ b/Documentation/RelNotes-1.6.0.4.txt
@@ -0,0 +1,39 @@
+GIT v1.6.0.4 Release Notes
+==========================
+
+Fixes since v1.6.0.3
+--------------------
+
+* 'git add -p' said "No changes" when only binary files were changed.
+
+* 'git archive' did not work correctly in bare repositories.
+
+* 'git checkout -t -b newbranch' when you are on detached HEAD was broken.
+
+* when we refuse to detect renames because there are too many new or
+  deleted files, 'git diff' did not say how many there are.
+
+* 'git push --mirror' tried and failed to push the stash; there is no
+  point in sending it to begin with.
+
+* 'git push' did not update the remote tracking reference if the corresponding
+  ref on the remote end happened to be already up to date.
+
+* 'git pull $there $branch:$current_branch' did not work when you were on
+  a branch yet to be born.
+
+* when giving up resolving a conflicted merge, 'git reset --hard' failed
+  to remove new paths from the working tree.
+
+* 'git send-email' had a small fd leak while scanning directory.
+
+* 'git status' incorrectly reported a submodule directory as an untracked
+  directory.
+
+* 'git svn' used deprecated 'git-foo' form of subcommand invocation.
+
+* 'git update-ref -d' to remove a reference did not honor --no-deref option.
+
+* Plugged small memleaks here and there.
+
+* Also contains many documentation updates.
diff --git a/Documentation/RelNotes-1.6.0.5.txt b/Documentation/RelNotes-1.6.0.5.txt
new file mode 100644
index 0000000..a08bb96
--- /dev/null
+++ b/Documentation/RelNotes-1.6.0.5.txt
@@ -0,0 +1,56 @@
+GIT v1.6.0.5 Release Notes
+==========================
+
+Fixes since v1.6.0.4
+--------------------
+
+* "git checkout" used to crash when your HEAD was pointing at a deleted
+  branch.
+
+* "git checkout" from an un-checked-out state did not allow switching out
+  of the current branch.
+
+* "git diff" always allowed GIT_EXTERNAL_DIFF and --no-ext-diff was no-op for
+  the command.
+
+* Giving 3 or more tree-ish to "git diff" is supposed to show the combined
+  diff from second and subsequent trees to the first one, but the order was
+  screwed up.
+
+* "git fast-export" did not export all tags.
+
+* "git ls-files --with-tree=<tree>" did not work with options other
+  than -c, most notably with -m.
+
+* "git pack-objects" did not make its best effort to honor --max-pack-size
+  option when a single first object already busted the given limit and
+  placed many objects in a single pack.
+
+* "git-p4" fast import frontend was too eager to trigger its keyword expansion
+  logic, even on a keyword-looking string that does not have closing '$' on the
+  same line.
+
+* "git push $there" when the remote $there is defined in $GIT_DIR/branches/$there
+  behaves more like what cg-push from Cogito used to work.
+
+* when giving up resolving a conflicted merge, "git reset --hard" failed
+  to remove new paths from the working tree.
+
+* "git tag" did not complain when given mutually incompatible set of options.
+
+* The message constructed in the internal editor was discarded when "git
+  tag -s" failed to sign the message, which was often caused by the user
+  not configuring GPG correctly.
+
+* "make check" cannot be run without sparse; people may have meant to say
+  "make test" instead, so suggest that.
+
+* Internal diff machinery had a corner case performance bug that choked on
+  a large file with many repeated contents.
+
+* "git repack" used to grab objects out of packs marked with .keep
+  into a new pack.
+
+* Many unsafe call to sprintf() style varargs functions are corrected.
+
+* Also contains quite a few documentation updates.
diff --git a/Documentation/RelNotes-1.6.0.6.txt b/Documentation/RelNotes-1.6.0.6.txt
new file mode 100644
index 0000000..64ece1f
--- /dev/null
+++ b/Documentation/RelNotes-1.6.0.6.txt
@@ -0,0 +1,33 @@
+GIT v1.6.0.6 Release Notes
+==========================
+
+Fixes since 1.6.0.5
+-------------------
+
+ * "git fsck" had a deep recursion that wasted stack space.
+
+ * "git fast-export" and "git fast-import" choked on an old style
+   annotated tag that lack the tagger information.
+
+ * "git mergetool -- file" did not correctly skip "--" marker that
+   signals the end of options list.
+
+ * "git show $tag" segfaulted when an annotated $tag pointed at a
+   nonexistent object.
+
+ * "git show 2>error" when the standard output is automatically redirected
+   to the pager redirected the standard error to the pager as well; there
+   was no need to.
+
+ * "git send-email" did not correctly handle list of addresses when
+   they had quoted comma (e.g. "Lastname, Givenname" <mail@addre.ss>).
+
+ * Logic to discover branch ancestry in "git svn" was unreliable when
+   the process to fetch history was interrupted.
+
+ * Removed support for an obsolete gitweb request URI, whose
+   implementation ran "git diff" Porcelain, instead of using plumbing,
+   which would have run an external diff command specified in the
+   repository configuration as the gitweb user.
+
+Also contains numerous documentation typofixes.
diff --git a/Documentation/RelNotes-1.6.0.txt b/Documentation/RelNotes-1.6.0.txt
new file mode 100644
index 0000000..de7ef16
--- /dev/null
+++ b/Documentation/RelNotes-1.6.0.txt
@@ -0,0 +1,258 @@
+GIT v1.6.0 Release Notes
+========================
+
+User visible changes
+--------------------
+
+With the default Makefile settings, most of the programs are now
+installed outside your $PATH, except for "git", "gitk" and
+some server side programs that need to be accessible for technical
+reasons.  Invoking a git subcommand as "git-xyzzy" from the command
+line has been deprecated since early 2006 (and officially announced in
+1.5.4 release notes); use of them from your scripts after adding
+output from "git --exec-path" to the $PATH is still supported in this
+release, but users are again strongly encouraged to adjust their
+scripts to use "git xyzzy" form, as we will stop installing
+"git-xyzzy" hardlinks for built-in commands in later releases.
+
+An earlier change to page "git status" output was overwhelmingly unpopular
+and has been reverted.
+
+Source changes needed for porting to MinGW environment are now all in the
+main git.git codebase.
+
+By default, packfiles created with this version uses delta-base-offset
+encoding introduced in v1.4.4.  Pack idx files are using version 2 that
+allows larger packs and added robustness thanks to its CRC checking,
+introduced in v1.5.2 and v1.4.4.5.  If you want to keep your repositories
+backwards compatible past these versions, set repack.useDeltaBaseOffset
+to false or pack.indexVersion to 1, respectively.
+
+We used to prevent sample hook scripts shipped in templates/ from
+triggering by default by relying on the fact that we install them as
+unexecutable, but on some filesystems, this approach does not work.
+They are now shipped with ".sample" suffix.  If you want to activate
+any of these samples as-is, rename them to drop the ".sample" suffix,
+instead of running "chmod +x" on them.  For example, you can rename
+hooks/post-update.sample to hooks/post-update to enable the sample
+hook that runs update-server-info, in order to make repositories
+friendly to dumb protocols (i.e. HTTP).
+
+GIT_CONFIG, which was only documented as affecting "git config", but
+actually affected all git commands, now only affects "git config".
+GIT_LOCAL_CONFIG, also only documented as affecting "git config" and
+not different from GIT_CONFIG in a useful way, is removed.
+
+The ".dotest" temporary area "git am" and "git rebase" use is now moved
+inside the $GIT_DIR, to avoid mistakes of adding it to the project by
+accident.
+
+An ancient merge strategy "stupid" has been removed.
+
+
+Updates since v1.5.6
+--------------------
+
+(subsystems)
+
+* git-p4 in contrib learned "allowSubmit" configuration to control on
+  which branch to allow "submit" subcommand.
+
+* git-gui learned to stage changes per-line.
+
+(portability)
+
+* Changes for MinGW port have been merged, thanks to Johannes Sixt and
+  gangs.
+
+* Sample hook scripts shipped in templates/ are now suffixed with
+  *.sample.
+
+* perl's in-place edit (-i) does not work well without backup files on Windows;
+  some tests are rewritten to cope with this.
+
+(documentation)
+
+* Updated howto/update-hook-example
+
+* Got rid of usage of "git-foo" from the tutorial and made typography
+  more consistent.
+
+* Disambiguating "--" between revs and paths is finally documented.
+
+(performance, robustness, sanity etc.)
+
+* index-pack used too much memory when dealing with a deep delta chain.
+  This has been optimized.
+
+* reduced excessive inlining to shrink size of the "git" binary.
+
+* verify-pack checks the object CRC when using version 2 idx files.
+
+* When an object is corrupt in a pack, the object became unusable even
+  when the same object is available in a loose form,  We now try harder to
+  fall back to these redundant objects when able.  In particular, "git
+  repack -a -f" can be used to fix such a corruption as long as necessary
+  objects are available.
+
+* Performance of "git-blame -C -C" operation is vastly improved.
+
+* git-clone does not create refs in loose form anymore (it behaves as
+  if you immediately ran git-pack-refs after cloning).  This will help
+  repositories with insanely large number of refs.
+
+* core.fsyncobjectfiles configuration can be used to ensure that the loose
+  objects created will be fsync'ed (this is only useful on filesystems
+  that does not order data writes properly).
+
+* "git commit-tree" plumbing can make Octopus with more than 16 parents.
+  "git commit" has been capable of this for quite some time.
+
+(usability, bells and whistles)
+
+* even more documentation pages are now accessible via "man" and "git help".
+
+* A new environment variable GIT_CEILING_DIRECTORIES can be used to stop
+  the discovery process of the toplevel of working tree; this may be useful
+  when you are working in a slow network disk and are outside any working tree,
+  as bash-completion and "git help" may still need to run in these places.
+
+* By default, stash entries never expire.  Set reflogexpire in [gc
+  "refs/stash"] to a reasonable value to get traditional auto-expiration
+  behaviour back
+
+* Longstanding latency issue with bash completion script has been
+  addressed.  This will need to be backmerged to 'maint' later.
+
+* pager.<cmd> configuration variable can be used to enable/disable the
+  default paging behaviour per command.
+
+* "git-add -i" has a new action 'e/dit' to allow you edit the patch hunk
+  manually.
+
+* git-am records the original tip of the branch in ORIG_HEAD before it
+  starts applying patches.
+
+* git-apply can handle a patch that touches the same path more than once
+  much better than before.
+
+* git-apply can be told not to trust the line counts recorded in the input
+  patch but recount, with the new --recount option.
+
+* git-apply can be told to apply a patch to a path deeper than what the
+  patch records with --directory option.
+
+* git-archive can be told to omit certain paths from its output using
+  export-ignore attributes.
+
+* git-archive uses the zlib default compression level when creating
+  zip archive.
+
+* git-archive's command line options --exec and --remote can take their
+  parameters as separate command line arguments, similar to other commands.
+  IOW, both "--exec=path" and "--exec path" are now supported.
+
+* With -v option, git-branch describes the remote tracking statistics
+  similar to the way git-checkout reports by how many commits your branch
+  is ahead/behind.
+
+* git-branch's --contains option used to always require a commit parameter
+  to limit the branches with; it now defaults to list branches that
+  contains HEAD if this parameter is omitted.
+
+* git-branch's --merged and --no-merged option used to always limit the
+  branches relative to the HEAD, but they can now take an optional commit
+  argument that is used in place of HEAD.
+
+* git-bundle can read the revision arguments from the standard input.
+
+* git-cherry-pick can replay a root commit now.
+
+* git-clone can clone from a remote whose URL would be rewritten by
+  configuration stored in $HOME/.gitconfig now.
+
+* "git-clone --mirror" is a handy way to set up a bare mirror repository.
+
+* git-cvsserver learned to respond to "cvs co -c".
+
+* git-diff --check now checks leftover merge conflict markers.
+
+* "git-diff -p" learned to grab a better hunk header lines in
+  BibTex, Pascal/Delphi, and Ruby files and also pays attention to
+  chapter and part boundary in TeX documents.
+
+* When remote side used to have branch 'foo' and git-fetch finds that now
+  it has branch 'foo/bar', it refuses to lose the existing remote tracking
+  branch and its reflog.  The error message has been improved to suggest
+  pruning the remote if the user wants to proceed and get the latest set
+  of branches from the remote, including such 'foo/bar'.
+
+* fast-export learned to export and import marks file; this can be used to
+  interface with fast-import incrementally.
+
+* fast-import and fast-export learned to export and import gitlinks.
+
+* "gitk" left background process behind after being asked to dig very deep
+  history and the user killed the UI; the process is killed when the UI goes
+  away now.
+
+* git-rebase records the original tip of branch in ORIG_HEAD before it is
+  rewound.
+
+* "git rerere" can be told to update the index with auto-reused resolution
+  with rerere.autoupdate configuration variable.
+
+* git-rev-parse learned $commit^! and $commit^@ notations used in "log"
+  family.  These notations are available in gitk as well, because the gitk
+  command internally uses rev-parse to interpret its arguments.
+
+* git-rev-list learned --children option to show child commits it
+  encountered during the traversal, instead of showing parent commits.
+
+* git-send-mail can talk not just over SSL but over TLS now.
+
+* git-shortlog honors custom output format specified with "--pretty=format:".
+
+* "git-stash save" learned --keep-index option.  This lets you stash away the
+  local changes and bring the changes staged in the index to your working
+  tree for examination and testing.
+
+* git-stash also learned branch subcommand to create a new branch out of
+  stashed changes.
+
+* git-status gives the remote tracking statistics similar to the way
+  git-checkout reports by how many commits your branch is ahead/behind.
+
+* "git-svn dcommit" is now aware of auto-props setting the subversion user
+  has.
+
+* You can tell "git status -u" to even more aggressively omit checking
+  untracked files with --untracked-files=no.
+
+* Original SHA-1 value for "update-ref -d" is optional now.
+
+* Error codes from gitweb are made more descriptive where possible, rather
+  than "403 forbidden" as we used to issue everywhere.
+
+(internal)
+
+* git-merge has been reimplemented in C.
+
+
+Fixes since v1.5.6
+------------------
+
+All of the fixes in v1.5.6 maintenance series are included in
+this release, unless otherwise noted.
+
+ * git-clone ignored its -u option; the fix needs to be backported to
+   'maint';
+
+ * git-mv used to lose the distinction between changes that are staged
+   and that are only in the working tree, by staging both in the index
+   after moving such a path.
+
+ * "git-rebase -i -p" rewrote the parents to wrong ones when amending
+   (either edit or squash) was involved, and did not work correctly
+   when fast forwarding.
+
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 0e155c9..34fdc83 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -222,6 +222,9 @@
 place an in-body "From: " line at the beginning to properly attribute
 the change to its true author (see (2) above).
 
+Also notice that a real name is used in the Signed-off-by: line. Please
+don't hide your real name.
+
 Some people also put extra tags at the end.
 
 "Acked-by:" says that the patch was reviewed by the person who
@@ -301,7 +304,7 @@
   patch appropriately.
 
 * Your MUA corrupted your patch; "am" would complain that
-  the patch does not apply.  Look at .dotest/ subdirectory and
+  the patch does not apply.  Look at .git/rebase-apply/ subdirectory and
   see what 'patch' file contains and check for the common
   corruption patterns mentioned above.
 
@@ -419,6 +422,11 @@
 	mail.identity.default.compose_html	=> false
 	mail.identity.id?.compose_html		=> false
 
+(Lukas Sandström)
+
+There is a script in contrib/thunderbird-patch-inline which can help
+you include patches with Thunderbird in an easy way. To use it, do the
+steps above and then use the script as the external editor.
 
 Gnus
 ----
@@ -451,3 +459,30 @@
 
 5) Back in the compose window: add whatever other text you wish to the
 message, complete the addressing and subject fields, and press send.
+
+
+Gmail
+-----
+
+Submitting properly formatted patches via Gmail is simple now that
+IMAP support is available. First, edit your ~/.gitconfig to specify your
+account settings:
+
+[imap]
+	folder = "[Gmail]/Drafts"
+	host = imaps://imap.gmail.com
+	user = user@gmail.com
+	pass = p4ssw0rd
+	port = 993
+	sslverify = false
+
+Next, ensure that your Gmail settings are correct. In "Settings" the
+"Use Unicode (UTF-8) encoding for outgoing messages" should be checked.
+
+Once your commits are ready to send to the mailing list, run the following
+command to send the patch emails to your Gmail Drafts folder.
+
+	$ git format-patch -M --stdout origin/master | git imap-send
+
+Go to your Gmail account, open the Drafts folder, find the patch email, fill
+in the To: and CC: fields and send away!
diff --git a/Documentation/asciidoc.conf b/Documentation/asciidoc.conf
index 10c1a15..2da867d 100644
--- a/Documentation/asciidoc.conf
+++ b/Documentation/asciidoc.conf
@@ -8,6 +8,7 @@
 # the command.
 
 [attributes]
+asterisk=&#42;
 plus=&#43;
 caret=&#94;
 startsb=&#91;
@@ -39,6 +40,26 @@
 </literallayout>
 {title#}</example>
 endif::docbook-xsl-172[]
+
+ifdef::docbook-xsl-172[]
+ifdef::doctype-manpage[]
+# The following two small workarounds insert a simple paragraph after screen
+[listingblock]
+<example><title>{title}</title>
+<screen>
+|
+</screen><simpara></simpara>
+{title#}</example>
+
+[verseblock]
+<formalpara{id? id="{id}"}><title>{title}</title><para>
+{title%}<literallayout{id? id="{id}"}>
+{title#}<literallayout>
+|
+</literallayout><simpara></simpara>
+{title#}</para></formalpara>
+endif::doctype-manpage[]
+endif::docbook-xsl-172[]
 endif::backend-docbook[]
 
 ifdef::doctype-manpage[]
diff --git a/Documentation/config.txt b/Documentation/config.txt
index da2cb3f..113d9d1 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -63,7 +63,7 @@
 a string, an integer, or a boolean.  Boolean values may be given as yes/no,
 0/1 or true/false.  Case is not significant in boolean values, when
 converting value to the canonical form using '--bool' type specifier;
-`git-config` will ensure that the output is "true" or "false".
+'git-config' will ensure that the output is "true" or "false".
 
 String values may be entirely or partially enclosed in double quotes.
 You need to enclose variable value in double quotes if you want to
@@ -117,9 +117,16 @@
 	the working copy are ignored; useful on broken filesystems like FAT.
 	See linkgit:git-update-index[1]. True by default.
 
+core.trustctime::
+	If false, the ctime differences between the index and the
+	working copy are ignored; useful when the inode change time
+	is regularly modified by something outside Git (file system
+	crawlers and some backup systems).
+	See linkgit:git-update-index[1]. True by default.
+
 core.quotepath::
-	The commands that output paths (e.g. `ls-files`,
-	`diff`), when not given the `-z` option, will quote
+	The commands that output paths (e.g. 'ls-files',
+	'diff'), when not given the `-z` option, will quote
 	"unusual" characters in the pathname by enclosing the
 	pathname in a double-quote pair and with backslashes the
 	same way strings in C source code are quoted.  If this
@@ -351,14 +358,29 @@
 	`EDITOR` environment variables and then finally `vi`.
 
 core.pager::
-	The command that git will use to paginate output.  Can be overridden
-	with the `GIT_PAGER` environment variable.
+	The command that git will use to paginate output.  Can
+	be overridden with the `GIT_PAGER` environment
+	variable.  Note that git sets the `LESS` environment
+	variable to `FRSX` if it is unset when it runs the
+	pager.  One can change these settings by setting the
+	`LESS` variable to some other value.  Alternately,
+	these settings can be overridden on a project or
+	global basis by setting the `core.pager` option.
+	Setting `core.pager` has no affect on the `LESS`
+	environment variable behaviour above, so if you want
+	to override git's default settings this way, you need
+	to be explicit.  For example, to disable the S option
+	in a backward compatible manner, set `core.pager`
+	to "`less -+$LESS -FRX`".  This will be passed to the
+	shell by git, which will translate the final command to
+	"`LESS=FRSX less -+FRSX -FRX`".
 
 core.whitespace::
 	A comma separated list of common whitespace problems to
-	notice.  `git diff` will use `color.diff.whitespace` to
-	highlight them, and `git apply --whitespace=error` will
-	consider them as errors:
+	notice.  'git-diff' will use `color.diff.whitespace` to
+	highlight them, and 'git-apply --whitespace=error' will
+	consider them as errors.  You can prefix `-` to disable
+	any of them (e.g. `-trailing-space`):
 +
 * `trailing-space` treats trailing whitespaces at the end of the line
   as an error (enabled by default).
@@ -396,11 +418,11 @@
 "gitk --all --not ORIG_HEAD".
 
 apply.whitespace::
-	Tells `git-apply` how to handle whitespaces, in the same way
+	Tells 'git-apply' how to handle whitespaces, in the same way
 	as the '--whitespace' option. See linkgit:git-apply[1].
 
 branch.autosetupmerge::
-	Tells `git-branch` and `git-checkout` to setup new branches
+	Tells 'git-branch' and 'git-checkout' to setup new branches
 	so that linkgit:git-pull[1] will appropriately merge from the
 	starting point branch. Note that even if this option is not set,
 	this behavior can be chosen per-branch using the `--track`
@@ -411,7 +433,7 @@
 	branch. This option defaults to true.
 
 branch.autosetuprebase::
-	When a new branch is created with `git-branch` or `git-checkout`
+	When a new branch is created with 'git-branch' or 'git-checkout'
 	that tracks another branch, this variable tells git to set
 	up pull to rebase instead of merge (see "branch.<name>.rebase").
 	When `never`, rebase is never automatically set to true.
@@ -426,20 +448,20 @@
 	This option defaults to never.
 
 branch.<name>.remote::
-	When in branch <name>, it tells `git fetch` which remote to fetch.
-	If this option is not given, `git fetch` defaults to remote "origin".
+	When in branch <name>, it tells 'git-fetch' which remote to fetch.
+	If this option is not given, 'git-fetch' defaults to remote "origin".
 
 branch.<name>.merge::
-	When in branch <name>, it tells `git fetch` the default
+	When in branch <name>, it tells 'git-fetch' the default
 	refspec to be marked for merging in FETCH_HEAD. The value is
 	handled like the remote part of a refspec, and must match a
 	ref which is fetched from the remote given by
 	"branch.<name>.remote".
-	The merge information is used by `git pull` (which at first calls
-	`git fetch`) to lookup the default branch for merging. Without
-	this option, `git pull` defaults to merge the first refspec fetched.
+	The merge information is used by 'git-pull' (which at first calls
+	'git-fetch') to lookup the default branch for merging. Without
+	this option, 'git-pull' defaults to merge the first refspec fetched.
 	Specify multiple values to get an octopus merge.
-	If you wish to setup `git pull` so that it merges into <name> from
+	If you wish to setup 'git-pull' so that it merges into <name> from
 	another branch in the local repository, you can point
 	branch.<name>.merge to the desired branch, and use the special setting
 	`.` (a period) for branch.<name>.remote.
@@ -508,12 +530,12 @@
 
 color.interactive::
 	When set to `always`, always use colors for interactive prompts
-	and displays (such as those used by "git add --interactive").
+	and displays (such as those used by "git-add --interactive").
 	When false (or `never`), never.  When set to `true` or `auto`, use
 	colors only when the output is to the terminal. Defaults to false.
 
 color.interactive.<slot>::
-	Use customized color for `git add --interactive`
+	Use customized color for 'git-add --interactive'
 	output. `<slot>` may be `prompt`, `header`, or `help`, for
 	three distinct types of normal output from interactive
 	programs.  The values of these variables may be specified as
@@ -539,9 +561,6 @@
 	to red). The values of these variables may be specified as in
 	color.branch.<slot>.
 
-commit.template::
-	Specify a file to use as the template for new commit messages.
-
 color.ui::
 	When set to `always`, always use colors in all git commands which
 	are capable of colored output. When false (or `never`), never. When
@@ -549,15 +568,18 @@
 	terminal. When more specific variables of color.* are set, they always
 	take precedence over this setting. Defaults to false.
 
+commit.template::
+	Specify a file to use as the template for new commit messages.
+
 diff.autorefreshindex::
-	When using `git diff` to compare with work tree
+	When using 'git-diff' to compare with work tree
 	files, do not consider stat-only change as changed.
 	Instead, silently run `git update-index --refresh` to
 	update the cached stat information for paths whose
 	contents in the work tree match the contents in the
 	index.  This option defaults to true.  Note that this
-	affects only `git diff` Porcelain, and not lower level
-	`diff` commands, such as `git diff-files`.
+	affects only 'git-diff' Porcelain, and not lower level
+	'diff' commands, such as 'git-diff-files'.
 
 diff.external::
 	If this config variable is set, diff generation is not
@@ -570,7 +592,7 @@
 
 diff.renameLimit::
 	The number of files to consider when performing the copy/rename
-	detection; equivalent to the git diff option '-l'.
+	detection; equivalent to the 'git-diff' option '-l'.
 
 diff.renames::
 	Tells git to detect renames.  If set to any boolean value, it
@@ -610,7 +632,7 @@
 
 gc.aggressiveWindow::
 	The window size parameter used in the delta compression
-	algorithm used by 'git gc --aggressive'.  This defaults
+	algorithm used by 'git-gc --aggressive'.  This defaults
 	to 10.
 
 gc.auto::
@@ -627,46 +649,39 @@
 	default	value is 50.  Setting this to 0 disables it.
 
 gc.packrefs::
-	`git gc` does not run `git pack-refs` in a bare repository by
+	'git-gc' does not run `git pack-refs` in a bare repository by
 	default so that older dumb-transport clients can still fetch
-	from the repository.  Setting this to `true` lets `git
-	gc` to run `git pack-refs`.  Setting this to `false` tells
-	`git gc` never to run `git pack-refs`. The default setting is
+	from the repository.  Setting this to `true` lets 'git-gc'
+	to run `git pack-refs`.  Setting this to `false` tells
+	'git-gc' never to run `git pack-refs`. The default setting is
 	`notbare`. Enable it only when you know you do not have to
 	support such clients.  The default setting will change to `true`
 	at some stage, and setting this to `false` will continue to
-	prevent `git pack-refs` from being run from `git gc`.
+	prevent `git pack-refs` from being run from 'git-gc'.
 
 gc.pruneexpire::
-	When `git gc` is run, it will call `prune --expire 2.weeks.ago`.
+	When 'git-gc' is run, it will call 'prune --expire 2.weeks.ago'.
 	Override the grace period with this config variable.
 
 gc.reflogexpire::
-	`git reflog expire` removes reflog entries older than
+	'git-reflog expire' removes reflog entries older than
 	this time; defaults to 90 days.
 
 gc.reflogexpireunreachable::
-	`git reflog expire` removes reflog entries older than
+	'git-reflog expire' removes reflog entries older than
 	this time and are not reachable from the current tip;
 	defaults to 30 days.
 
 gc.rerereresolved::
 	Records of conflicted merge you resolved earlier are
-	kept for this many days when `git rerere gc` is run.
+	kept for this many days when 'git-rerere gc' is run.
 	The default is 60 days.  See linkgit:git-rerere[1].
 
 gc.rerereunresolved::
 	Records of conflicted merge you have not resolved are
-	kept for this many days when `git rerere gc` is run.
+	kept for this many days when 'git-rerere gc' is run.
 	The default is 15 days.  See linkgit:git-rerere[1].
 
-rerere.enabled::
-	Activate recording of resolved conflicts, so that identical
-	conflict hunks can be resolved automatically, should they
-	be encountered again.  linkgit:git-rerere[1] command is by
-	default enabled if you create `rr-cache` directory under
-	`$GIT_DIR`, but can be disabled by setting this option to false.
-
 gitcvs.enabled::
 	Whether the CVS server interface is enabled for this repository.
 	See linkgit:git-cvsserver[1].
@@ -675,14 +690,14 @@
 	Path to a log file where the CVS server interface well... logs
 	various stuff. See linkgit:git-cvsserver[1].
 
-gitcvs.usecrlfattr
+gitcvs.usecrlfattr::
 	If true, the server will look up the `crlf` attribute for
 	files to determine the '-k' modes to use. If `crlf` is set,
 	the '-k' mode will be left blank, so cvs clients will
 	treat it as text. If `crlf` is explicitly unset, the file
-	will be set with '-kb' mode, which supresses any newline munging
+	will be set with '-kb' mode, which suppresses any newline munging
 	the client might otherwise do. If `crlf` is not specified,
-	then 'gitcvs.allbinary' is used. See linkgit:gitattribute[5].
+	then 'gitcvs.allbinary' is used. See linkgit:gitattributes[5].
 
 gitcvs.allbinary::
 	This is used if 'gitcvs.usecrlfattr' does not resolve
@@ -823,7 +838,11 @@
 
 i18n.logOutputEncoding::
 	Character encoding the commit messages are converted to when
-	running `git-log` and friends.
+	running 'git-log' and friends.
+
+imap::
+	The configuration variables in the 'imap' section are described
+	in linkgit:git-imap-send[1].
 
 instaweb.browser::
 	Specify the program that will be used to browse your working
@@ -846,7 +865,7 @@
 
 log.date::
 	Set default date-time mode for the log command. Setting log.date
-	value is similar to using git log's --date option. The value is one of
+	value is similar to using 'git-log'\'s --date option. The value is one of the
 	following alternatives: {relative,local,default,iso,rfc,short}.
 	See linkgit:git-log[1].
 
@@ -860,8 +879,6 @@
 	Specify the programs that may be used to display help in the
 	'man' format. See linkgit:git-help[1].
 
-include::merge-config.txt[]
-
 man.<tool>.cmd::
 	Specify the command to invoke the specified man viewer. The
 	specified command is evaluated in shell with the man page
@@ -871,6 +888,8 @@
 	Override the path for the given tool that may be used to
 	display help in the 'man' format. See linkgit:git-help[1].
 
+include::merge-config.txt[]
+
 mergetool.<tool>.path::
 	Override the path for the given tool.  This is useful in case
 	your tool is not in the PATH.
@@ -947,9 +966,17 @@
 	legacy pack index used by Git versions prior to 1.5.2, and 2 for
 	the new pack index with capabilities for packs larger than 4 GB
 	as well as proper protection against the repacking of corrupted
-	packs.  Version 2 is selected and this config option ignored
-	whenever the corresponding pack is larger than 2 GB.  Otherwise
-	the default is 1.
+	packs.  Version 2 is the default.  Note that version 2 is enforced
+	and this config option ignored whenever the corresponding pack is
+	larger than 2 GB.
++
+If you have an old git that does not understand the version 2 `{asterisk}.idx` file,
+cloning or fetching over a non native protocol (e.g. "http" and "rsync")
+that will copy both `{asterisk}.pack` file and corresponding `{asterisk}.idx` file from the
+other side may give you a repository that cannot be accessed with your
+older version of git. If the `{asterisk}.pack` file is smaller than 2 GB, however,
+you can use linkgit:git-index-pack[1] on the *.pack file to regenerate
+the `{asterisk}.idx` file.
 
 pack.packSizeLimit::
 	The default maximum size of a pack.  This setting only affects
@@ -957,6 +984,13 @@
 	can be overridden by the `\--max-pack-size` option of
 	linkgit:git-repack[1].
 
+pager.<cmd>::
+	Allows turning on or off pagination of the output of a
+	particular git subcommand when writing to a tty.  If
+	`\--paginate` or `\--no-pager` is specified on the command line,
+	it takes precedence over this option.  To disable pagination for
+	all commands, set `core.pager` or 'GIT_PAGER' to "`cat`".
+
 pull.octopus::
 	The default merge strategy to use when pulling multiple branches
 	at once.
@@ -964,6 +998,28 @@
 pull.twohead::
 	The default merge strategy to use when pulling a single branch.
 
+receive.fsckObjects::
+	If it is set to true, git-receive-pack will check all received
+	objects. It will abort in the case of a malformed object or a
+	broken link. The result of an abort are only dangling objects.
+	Defaults to false.
+
+receive.unpackLimit::
+	If the number of objects received in a push is below this
+	limit then the objects will be unpacked into loose object
+	files. However if the number of received objects equals or
+	exceeds this limit then the received pack will be stored as
+	a pack, after adding any missing delta bases.  Storing the
+	pack from a push can make the push operation complete faster,
+	especially on slow filesystems.  If not set, the value of
+	`transfer.unpackLimit` is used instead.
+
+receive.denyNonFastForwards::
+	If set to true, git-receive-pack will deny a ref update which is
+	not a fast forward. Use this to prevent such an update via a push,
+	even if that push is forced. This configuration variable is
+	set when initializing a shared repository.
+
 remote.<name>.url::
 	The URL of a remote repository.  See linkgit:git-fetch[1] or
 	linkgit:git-push[1].
@@ -1006,12 +1062,24 @@
 	<group>".  See linkgit:git-remote[1].
 
 repack.usedeltabaseoffset::
-	Allow linkgit:git-repack[1] to create packs that uses
-	delta-base offset.  Defaults to false.
+	By default, linkgit:git-repack[1] creates packs that use
+	delta-base offset. If you need to share your repository with
+	git older than version 1.4.4, either directly or via a dumb
+	protocol such as http, then you need to set this option to
+	"false" and repack. Access from old git versions over the
+	native protocol are unaffected by this option.
 
-show.difftree::
-	The default linkgit:git-diff-tree[1] arguments to be used
-	for linkgit:git-show[1].
+rerere.autoupdate::
+	When set to true, `git-rerere` updates the index with the
+	resulting contents after it cleanly resolves conflicts using
+	previously recorded resolution.  Defaults to false.
+
+rerere.enabled::
+	Activate recording of resolved conflicts, so that identical
+	conflict hunks can be resolved automatically, should they
+	be encountered again.  linkgit:git-rerere[1] command is by
+	default enabled if you create `rr-cache` directory under
+	`$GIT_DIR`, but can be disabled by setting this option to false.
 
 showbranch.default::
 	The default set of branches for linkgit:git-show-branch[1].
@@ -1023,6 +1091,25 @@
 	relative to the repository root (this was the default for git
 	prior to v1.5.4).
 
+status.showUntrackedFiles::
+	By default, linkgit:git-status[1] and linkgit:git-commit[1] show
+	files which are not currently tracked by Git. Directories which
+	contain only untracked files, are shown with the directory name
+	only. Showing untracked files means that Git needs to lstat() all
+	all the files in the whole repository, which might be slow on some
+	systems. So, this variable controls how the commands displays
+	the untracked files. Possible values are:
++
+--
+	- 'no'     - Show no untracked files
+	- 'normal' - Shows untracked files and directories
+	- 'all'    - Shows also individual files in untracked directories.
+--
++
+If this variable is not specified, it defaults to 'normal'.
+This variable can be overridden with the -u|--untracked-files option
+of linkgit:git-status[1] and linkgit:git-commit[1].
+
 tar.umask::
 	This variable can be used to restrict the permission bits of
 	tar archive entries.  The default is 0002, which turns off the
@@ -1030,6 +1117,11 @@
 	archiving user's umask will be used instead.  See umask(2) and
 	linkgit:git-archive[1].
 
+transfer.unpackLimit::
+	When `fetch.unpackLimit` or `receive.unpackLimit` are
+	not set, the value of this variable is used instead.
+	The default value is 100.
+
 url.<base>.insteadOf::
 	Any URL that starts with this value will be rewritten to
 	start, instead, with <base>. In cases where some site serves a
@@ -1058,41 +1150,6 @@
 	unchanged to gpg's --local-user parameter, so you may specify a key
 	using any method that gpg supports.
 
-whatchanged.difftree::
-	The default linkgit:git-diff-tree[1] arguments to be used
-	for linkgit:git-whatchanged[1].
-
-imap::
-	The configuration variables in the 'imap' section are described
-	in linkgit:git-imap-send[1].
-
-receive.fsckObjects::
-	If it is set to true, git-receive-pack will check all received
-	objects. It will abort in the case of a malformed object or a
-	broken link. The result of an abort are only dangling objects.
-	Defaults to false.
-
-receive.unpackLimit::
-	If the number of objects received in a push is below this
-	limit then the objects will be unpacked into loose object
-	files. However if the number of received objects equals or
-	exceeds this limit then the received pack will be stored as
-	a pack, after adding any missing delta bases.  Storing the
-	pack from a push can make the push operation complete faster,
-	especially on slow filesystems.  If not set, the value of
-	`transfer.unpackLimit` is used instead.
-
-receive.denyNonFastForwards::
-	If set to true, git-receive-pack will deny a ref update which is
-	not a fast forward. Use this to prevent such an update via a push,
-	even if that push is forced. This configuration variable is
-	set when initializing a shared repository.
-
-transfer.unpackLimit::
-	When `fetch.unpackLimit` or `receive.unpackLimit` are
-	not set, the value of this variable is used instead.
-	The default value is 100.
-
 web.browser::
 	Specify a web browser that may be used by some commands.
 	Currently only linkgit:git-instaweb[1] and linkgit:git-help[1]
diff --git a/Documentation/diff-format.txt b/Documentation/diff-format.txt
index 400cbb3..1eeb1c7 100644
--- a/Documentation/diff-format.txt
+++ b/Documentation/diff-format.txt
@@ -46,6 +46,22 @@
 . path for "dst"; only exists for C or R.
 . an LF or a NUL when '-z' option is used, to terminate the record.
 
+Possible status letters are:
+
+- A: addition of a file
+- C: copy of a file into a new one
+- D: deletion of a file
+- M: modification of the contents or mode of a file
+- R: renaming of a file
+- T: change in the type of the file
+- U: file is unmerged (you must complete the merge before it can
+be committed)
+- X: "unknown" change type (most probably a bug, please report it)
+
+Status letters C and R are always followed by a score (denoting the
+percentage of similarity between the source and target of the move or
+copy), and are the only ones to be so.
+
 <sha1> is shown as all 0's if a file is new on the filesystem
 and it is out of sync with the index.
 
diff --git a/Documentation/diff-generate-patch.txt b/Documentation/diff-generate-patch.txt
index 517e1eb..0f25ba7 100644
--- a/Documentation/diff-generate-patch.txt
+++ b/Documentation/diff-generate-patch.txt
@@ -143,15 +143,15 @@
 
 A `-` character in the column N means that the line appears in
 fileN but it does not appear in the result.  A `+` character
-in the column N means that the line appears in the last file,
+in the column N means that the line appears in the result,
 and fileN does not have that line (in other words, the line was
 added, from the point of view of that parent).
 
 In the above example output, the function signature was changed
 from both files (hence two `-` removals from both file1 and
 file2, plus `++` to mean one line that was added does not appear
-in either file1 nor file2).  Also two other lines are the same
-from file1 but do not appear in file2 (hence prefixed with ` +`).
+in either file1 nor file2).  Also eight other lines are the same
+from file1 but do not appear in file2 (hence prefixed with `{plus}`).
 
 When shown by `git diff-tree -c`, it compares the parents of a
 merge commit with the merge result (i.e. file1..fileN are the
diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
index 5721548..45885bb 100644
--- a/Documentation/diff-options.txt
+++ b/Documentation/diff-options.txt
@@ -59,12 +59,11 @@
 	lines.
 
 --dirstat[=limit]::
-	Output only the sub-directories that are impacted by a diff,
-	and to what degree they are impacted.  You can override the
-	default cut-off in percent (3) by "--dirstat=limit".  If you
-	want to enable "cumulative" directory statistics, you can use
-	the "--cumulative" flag, which adds up percentages recursively
-	even when they have been already reported for a sub-directory.
+	Output the distribution of relative amount of changes (number of lines added or
+	removed) for each sub-directory. Directories with changes below
+	a cut-off percent (3% by default) are not shown. The cut-off percent
+	can be set with "--dirstat=limit". Changes in a child directory is not
+	counted for the parent directory, unless "--cumulative" is used.
 
 --summary::
 	Output a condensed summary of extended header information
@@ -135,7 +134,8 @@
 --diff-filter=[ACDMRTUXB*]::
 	Select only files that are Added (`A`), Copied (`C`),
 	Deleted (`D`), Modified (`M`), Renamed (`R`), have their
-	type (mode) changed (`T`), are Unmerged (`U`), are
+	type (i.e. regular file, symlink, submodule, ...) changed (`T`),
+	are Unmerged (`U`), are
 	Unknown (`X`), or have had their pairing Broken (`B`).
 	Any combination of the filter characters may be used.
 	When `*` (All-or-none) is added to the combination, all
@@ -241,4 +241,4 @@
 	Do not show any source or destination prefix.
 
 For more detailed explanation on these common options, see also
-linkgit:gitdiffcore[7][diffcore documentation].
+linkgit:gitdiffcore[7].
diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index 85c8718..d313795 100644
--- a/Documentation/fetch-options.txt
+++ b/Documentation/fetch-options.txt
@@ -21,7 +21,7 @@
 
 -f::
 --force::
-	When `git-fetch` is used with `<rbranch>:<lbranch>`
+	When 'git-fetch' is used with `<rbranch>:<lbranch>`
 	refspec, it refuses to update the local branch
 	`<lbranch>` unless the remote branch `<rbranch>` it
 	fetches is a descendant of `<lbranch>`.  This option
@@ -53,10 +53,10 @@
 
 -u::
 --update-head-ok::
-	By default `git-fetch` refuses to update the head which
+	By default 'git-fetch' refuses to update the head which
 	corresponds to the current branch.  This flag disables the
-	check.  This is purely for the internal use for `git-pull`
-	to communicate with `git-fetch`, and unless you are
+	check.  This is purely for the internal use for 'git-pull'
+	to communicate with 'git-fetch', and unless you are
 	implementing your own Porcelain you are not supposed to
 	use it.
 
diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt
index 815864c..2b6d6c8 100644
--- a/Documentation/git-add.txt
+++ b/Documentation/git-add.txt
@@ -8,8 +8,8 @@
 SYNOPSIS
 --------
 [verse]
-'git-add' [-n] [-v] [--force | -f] [--interactive | -i] [--patch | -p]
-	  [--update | -u] [--refresh] [--ignore-errors] [--]
+'git add' [-n] [-v] [--force | -f] [--interactive | -i] [--patch | -p]
+	  [--all | [--update | -u]] [--refresh] [--ignore-errors] [--]
 	  <filepattern>...
 
 DESCRIPTION
@@ -86,6 +86,12 @@
 	command line. If no paths are specified, all tracked files in the
 	current directory and its subdirectories are updated.
 
+-A::
+--all::
+	Update files that git already knows about (same as '\--update')
+	and add all untracked files that are not ignored by '.gitignore'
+	mechanism.
+
 --refresh::
 	Don't add the file(s), but only refresh their stat()
 	information in the index.
@@ -107,7 +113,7 @@
 The optional configuration variable 'core.excludesfile' indicates a path to a
 file containing patterns of file names to exclude from git-add, similar to
 $GIT_DIR/info/exclude.  Patterns in the exclude file are used in addition to
-those in info/exclude.  See linkgit:gitrepository-layout[5][repository layout].
+those in info/exclude.  See linkgit:gitrepository-layout[5].
 
 
 EXAMPLES
@@ -237,6 +243,7 @@
        k - leave this hunk undecided, see previous undecided hunk
        K - leave this hunk undecided, see previous hunk
        s - split the current hunk into smaller hunks
+       e - manually edit the current hunk
        ? - print help
 +
 After deciding the fate for all hunks, if there is any hunk
diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt
index 5622971..b9c6fac 100644
--- a/Documentation/git-am.txt
+++ b/Documentation/git-am.txt
@@ -9,11 +9,11 @@
 SYNOPSIS
 --------
 [verse]
-'git-am' [--signoff] [--keep] [--utf8 | --no-utf8]
-         [--3way] [--interactive] [--binary]
+'git am' [--signoff] [--keep] [--utf8 | --no-utf8]
+	 [--3way] [--interactive]
          [--whitespace=<option>] [-C<n>] [-p<n>]
-         <mbox>|<Maildir>...
-'git-am' [--skip | --resolved]
+	 [<mbox> | <Maildir>...]
+'git am' (--skip | --resolved | --abort)
 
 DESCRIPTION
 -----------
@@ -35,11 +35,11 @@
 
 -k::
 --keep::
-	Pass `-k` flag to `git-mailinfo` (see linkgit:git-mailinfo[1]).
+	Pass `-k` flag to 'git-mailinfo' (see linkgit:git-mailinfo[1]).
 
 -u::
 --utf8::
-	Pass `-u` flag to `git-mailinfo` (see linkgit:git-mailinfo[1]).
+	Pass `-u` flag to 'git-mailinfo' (see linkgit:git-mailinfo[1]).
 	The proposed commit log message taken from the e-mail
 	is re-coded into UTF-8 encoding (configuration variable
 	`i18n.commitencoding` can be used to specify project's
@@ -49,7 +49,7 @@
 default.   You could use `--no-utf8` to override this.
 
 --no-utf8::
-	Pass `-n` flag to `git-mailinfo` (see
+	Pass `-n` flag to 'git-mailinfo' (see
 	linkgit:git-mailinfo[1]).
 
 -3::
@@ -59,19 +59,14 @@
 	it is supposed to apply to, and we have those blobs
 	available locally.
 
--b::
---binary::
-	Pass `--allow-binary-replacement` flag to `git-apply`
-	(see linkgit:git-apply[1]).
-
 --whitespace=<option>::
-	This flag is passed to the `git-apply` (see linkgit:git-apply[1])
+	This flag is passed to the 'git-apply' (see linkgit:git-apply[1])
 	program that applies
 	the patch.
 
 -C<n>::
 -p<n>::
-	These flags are passed to the `git-apply` (see linkgit:git-apply[1])
+	These flags are passed to the 'git-apply' (see linkgit:git-apply[1])
 	program that applies
 	the patch.
 
@@ -97,7 +92,10 @@
 	to the screen before exiting.  This overrides the
 	standard message informing you to use `--resolved`
 	or `--skip` to handle the failure.  This is solely
-	for internal use between `git-rebase` and `git-am`.
+	for internal use between 'git-rebase' and 'git-am'.
+
+--abort::
+	Restore the original branch and abort the patching operation.
 
 DISCUSSION
 ----------
@@ -140,11 +138,17 @@
   the index file to bring it in a state that the patch should
   have produced.  Then run the command with '--resolved' option.
 
-The command refuses to process new mailboxes while `.dotest`
+The command refuses to process new mailboxes while `.git/rebase-apply`
 directory exists, so if you decide to start over from scratch,
-run `rm -f -r .dotest` before running the command with mailbox
+run `rm -f -r .git/rebase-apply` before running the command with mailbox
 names.
 
+Before any patches are applied, ORIG_HEAD is set to the tip of the
+current branch.  This is useful if you have problems with multiple
+commits, like running 'git am' on the wrong branch or an error in the
+commits that is more easily fixed by changing the mailbox (e.g.
+errors in the "From:" lines).
+
 
 SEE ALSO
 --------
diff --git a/Documentation/git-annotate.txt b/Documentation/git-annotate.txt
index da15379..0aba022 100644
--- a/Documentation/git-annotate.txt
+++ b/Documentation/git-annotate.txt
@@ -7,13 +7,18 @@
 
 SYNOPSIS
 --------
-git-annotate [options] file [revision]
+'git annotate' [options] file [revision]
 
 DESCRIPTION
 -----------
 Annotates each line in the given file with information from the commit
 which introduced the line. Optionally annotate from a given revision.
 
+The only difference between this command and linkgit:git-blame[1] is that
+they use slightly different output formats, and this command exists only
+for backward compatibility to support existing scripts, and provide more
+familiar command name for people coming from other SCM systems.
+
 OPTIONS
 -------
 include::blame-options.txt[]
diff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt
index c834763..feb51f1 100644
--- a/Documentation/git-apply.txt
+++ b/Documentation/git-apply.txt
@@ -9,16 +9,16 @@
 SYNOPSIS
 --------
 [verse]
-'git-apply' [--stat] [--numstat] [--summary] [--check] [--index]
+'git apply' [--stat] [--numstat] [--summary] [--check] [--index]
 	  [--apply] [--no-add] [--build-fake-ancestor <file>] [-R | --reverse]
 	  [--allow-binary-replacement | --binary] [--reject] [-z]
-	  [-pNUM] [-CNUM] [--inaccurate-eof] [--cached]
+	  [-pNUM] [-CNUM] [--inaccurate-eof] [--recount] [--cached]
 	  [--whitespace=<nowarn|warn|fix|error|error-all>]
-	  [--exclude=PATH] [--verbose] [<patch>...]
+	  [--exclude=PATH] [--directory=<root>] [--verbose] [<patch>...]
 
 DESCRIPTION
 -----------
-Reads supplied diff output and applies it on a git index file
+Reads supplied 'diff' output and applies it on a git index file
 and a work tree.
 
 OPTIONS
@@ -64,7 +64,7 @@
 	without using the working tree. This implies '--index'.
 
 --build-fake-ancestor <file>::
-	Newer git-diff output has embedded 'index information'
+	Newer 'git-diff' output has embedded 'index information'
 	for each blob to help identify the original version that
 	the patch applies to.  When this flag is given, and if
 	the original versions of the blobs is available locally,
@@ -78,7 +78,7 @@
 	Apply the patch in reverse.
 
 --reject::
-	For atomicity, linkgit:git-apply[1] by default fails the whole patch and
+	For atomicity, 'git-apply' by default fails the whole patch and
 	does not touch the working tree when some of the hunks
 	do not apply.  This option makes it apply
 	the parts of the patch that are applicable, and leave the
@@ -102,7 +102,7 @@
 	ever ignored.
 
 --unidiff-zero::
-	By default, linkgit:git-apply[1] expects that the patch being
+	By default, 'git-apply' expects that the patch being
 	applied is a unified diff with at least one line of context.
 	This provides good safety measures, but breaks down when
 	applying a diff generated with --unified=0. To bypass these
@@ -113,7 +113,7 @@
 
 --apply::
 	If you use any of the options marked "Turns off
-	'apply'" above, linkgit:git-apply[1] reads and outputs the
+	'apply'" above, 'git-apply' reads and outputs the
 	information you asked without actually applying the
 	patch.  Give this flag after those flags to also apply
 	the patch.
@@ -121,7 +121,7 @@
 --no-add::
 	When applying a patch, ignore additions made by the
 	patch.  This can be used to extract the common part between
-	two files by first running `diff` on them and applying
+	two files by first running 'diff' on them and applying
 	the result with this option, which would apply the
 	deletion part but not addition part.
 
@@ -147,7 +147,7 @@
 	considered whitespace errors.
 +
 By default, the command outputs warning messages but applies the patch.
-When linkgit:git-apply[1] is used for statistics and not applying a
+When `git-apply is used for statistics and not applying a
 patch, it defaults to `nowarn`.
 +
 You can use different `<action>` to control this
@@ -165,9 +165,9 @@
 * `error-all` is similar to `error` but shows all errors.
 
 --inaccurate-eof::
-	Under certain circumstances, some versions of diff do not correctly
+	Under certain circumstances, some versions of 'diff' do not correctly
 	detect a missing new-line at the end of the file. As a result, patches
-	created by such diff programs do not record incomplete lines
+	created by such 'diff' programs do not record incomplete lines
 	correctly. This option adds support for applying such patches by
 	working around this bug.
 
@@ -177,6 +177,19 @@
 	current patch being applied will be printed. This option will cause
 	additional information to be reported.
 
+--recount::
+	Do not trust the line counts in the hunk headers, but infer them
+	by inspecting the patch (e.g. after editing the patch without
+	adjusting the hunk headers appropriately).
+
+--directory=<root>::
+	Prepend <root> to all filenames.  If a "-p" argument was passed, too,
+	it is applied before prepending the new root.
++
+For example, a patch that talks about updating `a/git-gui.sh` to `b/git-gui.sh`
+can be applied to the file in the working tree `modules/git-gui/git-gui.sh` by
+running `git apply --directory=modules/git-gui`.
+
 Configuration
 -------------
 
@@ -186,7 +199,7 @@
 
 Submodules
 ----------
-If the patch contains any changes to submodules then linkgit:git-apply[1]
+If the patch contains any changes to submodules then 'git-apply'
 treats these changes as follows.
 
 If --index is specified (explicitly or implicitly), then the submodule
diff --git a/Documentation/git-archimport.txt b/Documentation/git-archimport.txt
index 603117c..c7a6e3e 100644
--- a/Documentation/git-archimport.txt
+++ b/Documentation/git-archimport.txt
@@ -9,7 +9,7 @@
 SYNOPSIS
 --------
 [verse]
-'git-archimport' [-h] [-v] [-o] [-a] [-f] [-T] [-D depth] [-t tempdir]
+'git archimport' [-h] [-v] [-o] [-a] [-f] [-T] [-D depth] [-t tempdir]
                <archive/branch>[:<git-branch>] ...
 
 DESCRIPTION
@@ -29,17 +29,17 @@
 edit your <archive/branch> parameters to define clearly the scope of the
 import.
 
-`git-archimport` uses `tla` extensively in the background to access the
+'git-archimport' uses `tla` extensively in the background to access the
 Arch repository.
 Make sure you have a recent version of `tla` available in the path. `tla` must
-know about the repositories you pass to `git-archimport`.
+know about the repositories you pass to 'git-archimport'.
 
-For the initial import `git-archimport` expects to find itself in an empty
+For the initial import, 'git-archimport' expects to find itself in an empty
 directory. To follow the development of a project that uses Arch, rerun
-`git-archimport` with the same parameters as the initial import to perform
+'git-archimport' with the same parameters as the initial import to perform
 incremental imports.
 
-While git-archimport will try to create sensible branch names for the
+While 'git-archimport' will try to create sensible branch names for the
 archives that it imports, it is also possible to specify git branch names
 manually.  To do so, write a git branch name after each <archive/branch>
 parameter, separated by a colon.  This way, you can shorten the Arch
@@ -84,7 +84,7 @@
 
 -o::
 	Use this for compatibility with old-style branch names used by
-	earlier versions of git-archimport.  Old-style branch names
+	earlier versions of 'git-archimport'.  Old-style branch names
 	were category--branch, whereas new-style branch names are
 	archive,category--branch--version.  In both cases, names given
 	on the command-line will override the automatically-generated
diff --git a/Documentation/git-archive.txt b/Documentation/git-archive.txt
index 9b5f3ae..41cbf9c 100644
--- a/Documentation/git-archive.txt
+++ b/Documentation/git-archive.txt
@@ -9,7 +9,7 @@
 SYNOPSIS
 --------
 [verse]
-'git-archive' --format=<fmt> [--list] [--prefix=<prefix>/] [<extra>]
+'git archive' --format=<fmt> [--list] [--prefix=<prefix>/] [<extra>]
 	      [--remote=<repo> [--exec=<git-upload-archive>]] <tree-ish>
 	      [path...]
 
@@ -57,7 +57,7 @@
 
 --exec=<git-upload-archive>::
 	Used with --remote to specify the path to the
-	git-upload-archive executable on the remote side.
+	'git-upload-archive' on the remote side.
 
 <tree-ish>::
 	The tree or commit to produce an archive for.
diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt
index 3ca0d33..39034ec 100644
--- a/Documentation/git-bisect.txt
+++ b/Documentation/git-bisect.txt
@@ -26,7 +26,7 @@
  git bisect log
  git bisect run <cmd>...
 
-This command uses 'git-rev-list --bisect' option to help drive the
+This command uses 'git rev-list --bisect' to help drive the
 binary search process to find which change introduced a bug, given an
 old "good" commit object name and a later "bad" commit object name.
 
@@ -98,10 +98,10 @@
 $ git bisect visualize
 ------------
 
-to see the currently remaining suspects in `gitk`.  `visualize` is a bit
+to see the currently remaining suspects in 'gitk'.  `visualize` is a bit
 too long to type and `view` is provided as a synonym.
 
-If `DISPLAY` environment variable is not set, `git log` is used
+If 'DISPLAY' environment variable is not set, 'git log' is used
 instead.  You can even give command line options such as `-p` and
 `--stat`.
 
@@ -215,13 +215,13 @@
 work around other problem this bisection is not interested in")
 applied to the revision being tested.
 
-To cope with such a situation, after the inner git-bisect finds the
+To cope with such a situation, after the inner 'git bisect' finds the
 next revision to test, with the "run" script, you can apply that tweak
 before compiling, run the real test, and after the test decides if the
 revision (possibly with the needed tweaks) passed the test, rewind the
 tree to the pristine state.  Finally the "run" script can exit with
-the status of the real test to let "git bisect run" command loop to
-know the outcome.
+the status of the real test to let the "git bisect run" command loop to
+determine the outcome.
 
 EXAMPLES
 --------
diff --git a/Documentation/git-blame.txt b/Documentation/git-blame.txt
index 0e0196e..fba374d 100644
--- a/Documentation/git-blame.txt
+++ b/Documentation/git-blame.txt
@@ -8,7 +8,7 @@
 SYNOPSIS
 --------
 [verse]
-'git-blame' [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-p] [-w] [--incremental] [-L n,m]
+'git blame' [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-p] [-w] [--incremental] [-L n,m]
             [-S <revs-file>] [-M] [-C] [-C] [--since=<date>]
             [<rev> | --contents <file>] [--] <file>
 
@@ -21,7 +21,7 @@
 Also it can limit the range of lines annotated.
 
 This report doesn't tell you anything about lines which have been deleted or
-replaced; you need to use a tool such as linkgit:git-diff[1] or the "pickaxe"
+replaced; you need to use a tool such as 'git-diff' or the "pickaxe"
 interface briefly mentioned in the following paragraph.
 
 Apart from supporting file annotation, git also supports searching the
@@ -49,7 +49,7 @@
 	file (see `-M`).  The first number listed is the score.
 	This is the number of alphanumeric characters detected
 	to be moved between or within files.  This must be above
-	a certain threshold for git-blame to consider those lines
+	a certain threshold for 'git-blame' to consider those lines
 	of code to have been moved.
 
 -f::
@@ -100,7 +100,7 @@
 SPECIFYING RANGES
 -----------------
 
-Unlike `git-blame` and `git-annotate` in older git, the extent
+Unlike 'git-blame' and 'git-annotate' in older git, the extent
 of annotation can be limited to both line ranges and revision
 ranges.  When you are interested in finding the origin for
 ll. 40-60 for file `foo`, you can use `-L` option like these
@@ -118,7 +118,7 @@
 
 When you are not interested in changes older than the version
 v2.6.18, or changes older than 3 weeks, you can use revision
-range specifiers  similar to `git-rev-list`:
+range specifiers  similar to 'git-rev-list':
 
 	git blame v2.6.18.. -- foo
 	git blame --since=3.weeks -- foo
diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index 39cd5d9..6103d62 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -8,24 +8,27 @@
 SYNOPSIS
 --------
 [verse]
-'git-branch' [--color | --no-color] [-r | -a] [--merged | --no-merged]
-	   [-v [--abbrev=<length> | --no-abbrev]]
-	   [--contains <commit>]
-'git-branch' [--track | --no-track] [-l] [-f] <branchname> [<start-point>]
-'git-branch' (-m | -M) [<oldbranch>] <newbranch>
-'git-branch' (-d | -D) [-r] <branchname>...
+'git branch' [--color | --no-color] [-r | -a]
+	[-v [--abbrev=<length> | --no-abbrev]]
+	[(--merged | --no-merged | --contains) [<commit>]]
+'git branch' [--track | --no-track] [-l] [-f] <branchname> [<start-point>]
+'git branch' (-m | -M) [<oldbranch>] <newbranch>
+'git branch' (-d | -D) [-r] <branchname>...
 
 DESCRIPTION
 -----------
-With no arguments given a list of existing branches
-will be shown, the current branch will be highlighted with an asterisk.
-Option `-r` causes the remote-tracking branches to be listed,
-and option `-a` shows both.
-With `--contains <commit>`, shows only the branches that
-contains the named commit (in other words, the branches whose
-tip commits are descendant of the named commit).
-With `--merged`, only branches merged into HEAD will be listed, and
-with `--no-merged` only branches not merged into HEAD will be listed.
+
+With no arguments, existing branches are listed, the current branch will
+be highlighted with an asterisk.  Option `-r` causes the remote-tracking
+branches to be listed, and option `-a` shows both.
+
+With `--contains`, shows only the branches that contains the named commit
+(in other words, the branches whose tip commits are descendant of the
+named commit).  With `--merged`, only branches merged into the named
+commit (i.e. the branches whose tip commits are reachable from the named
+commit) will be listed.  With `--no-merged` only branches not merged into
+the named commit will be listed.  Missing <commit> argument defaults to
+'HEAD' (i.e. the tip of the current branch).
 
 In its second form, a new branch named <branchname> will be created.
 It will start out with a head equal to the one given as <start-point>.
@@ -37,7 +40,7 @@
 new branch.
 
 When a local branch is started off a remote branch, git sets up the
-branch so that linkgit:git-pull[1] will appropriately merge from
+branch so that 'git-pull' will appropriately merge from
 the remote branch. This behavior may be changed via the global
 `branch.autosetupmerge` configuration flag. That setting can be
 overridden by using the `--track` and `--no-track` options.
@@ -54,7 +57,7 @@
 
 Use -r together with -d to delete remote-tracking branches. Note, that it
 only makes sense to delete remote-tracking branches if they no longer exist
-in remote repository or if linkgit:git-fetch[1] was configured not to fetch
+in remote repository or if 'git-fetch' was configured not to fetch
 them again. See also 'prune' subcommand of linkgit:git-remote[1] for way to
 clean up all obsolete remote-tracking branches.
 
@@ -107,14 +110,14 @@
 	Display the full sha1s in output listing rather than abbreviating them.
 
 --track::
-	When creating a new branch, set up configuration so that git-pull
+	When creating a new branch, set up configuration so that 'git-pull'
 	will automatically retrieve data from the start point, which must be
 	a branch. Use this if you always pull from the same upstream branch
 	into the new branch, and if you don't want to use "git pull
 	<repository> <refspec>" explicitly. This behavior is the default
 	when the start point is a remote branch. Set the
 	branch.autosetupmerge configuration variable to `false` if you want
-	git-checkout and git-branch to always behave as if '--no-track' were
+	'git-checkout' and 'git-branch' to always behave as if '--no-track' were
 	given. Set it to `always` if you want this behavior when the
 	start-point is either a local or remote branch.
 
diff --git a/Documentation/git-bundle.txt b/Documentation/git-bundle.txt
index f6a0612..1b66ab7 100644
--- a/Documentation/git-bundle.txt
+++ b/Documentation/git-bundle.txt
@@ -9,10 +9,10 @@
 SYNOPSIS
 --------
 [verse]
-'git-bundle' create <file> <git-rev-list args>
-'git-bundle' verify <file>
-'git-bundle' list-heads <file> [refname...]
-'git-bundle' unbundle <file> [refname...]
+'git bundle' create <file> <git-rev-list args>
+'git bundle' verify <file>
+'git bundle' list-heads <file> [refname...]
+'git bundle' unbundle <file> [refname...]
 
 DESCRIPTION
 -----------
@@ -21,9 +21,9 @@
 machine be replicated on another machine, but the two machines cannot
 be directly connected so the interactive git protocols (git, ssh,
 rsync, http) cannot be used.  This command provides support for
-git-fetch and git-pull to operate by packaging objects and references
+'git-fetch' and 'git-pull' to operate by packaging objects and references
 in an archive at the originating machine, then importing those into
-another repository using linkgit:git-fetch[1] and linkgit:git-pull[1]
+another repository using 'git-fetch' and 'git-pull'
 after moving the archive by some means (i.e., by sneakernet).  As no
 direct connection between repositories exists, the user must specify a
 basis for the bundle that is held by the destination repository: the
@@ -35,14 +35,14 @@
 
 create <file>::
        Used to create a bundle named 'file'.  This requires the
-       git-rev-list arguments to define the bundle contents.
+       'git-rev-list' arguments to define the bundle contents.
 
 verify <file>::
        Used to check that a bundle file is valid and will apply
        cleanly to the current repository.  This includes checks on the
        bundle format itself as well as checking that the prerequisite
        commits exist and are fully linked in the current repository.
-       git-bundle prints a list of missing commits, if any, and exits
+       'git-bundle' prints a list of missing commits, if any, and exits
        with non-zero status.
 
 list-heads <file>::
@@ -51,16 +51,15 @@
        printed out.
 
 unbundle <file>::
-       Passes the objects in the bundle to linkgit:git-index-pack[1]
+       Passes the objects in the bundle to 'git-index-pack'
        for storage in the repository, then prints the names of all
        defined references. If a reflist is given, only references
        matching those in the given list are printed. This command is
-       really plumbing, intended to be called only by
-       linkgit:git-fetch[1].
+       really plumbing, intended to be called only by 'git-fetch'.
 
 [git-rev-list-args...]::
-       A list of arguments, acceptable to git-rev-parse and
-       git-rev-list, that specify the specific objects and references
+       A list of arguments, acceptable to 'git-rev-parse' and
+       'git-rev-list', that specify the specific objects and references
        to transport.  For example, "master~10..master" causes the
        current master reference to be packaged along with all objects
        added since its 10th ancestor commit.  There is no explicit
@@ -70,16 +69,16 @@
 
 [refname...]::
        A list of references used to limit the references reported as
-       available. This is principally of use to git-fetch, which
+       available. This is principally of use to 'git-fetch', which
        expects to receive only those references asked for and not
-       necessarily everything in the pack (in this case, git-bundle is
-       acting like linkgit:git-fetch-pack[1]).
+       necessarily everything in the pack (in this case, 'git-bundle' is
+       acting like 'git-fetch-pack').
 
 SPECIFYING REFERENCES
 ---------------------
 
-git-bundle will only package references that are shown by
-git-show-ref: this includes heads, tags, and remote heads.  References
+'git-bundle' will only package references that are shown by
+'git-show-ref': this includes heads, tags, and remote heads.  References
 such as master~1 cannot be packaged, but are perfectly suitable for
 defining the basis.  More than one reference may be packaged, and more
 than one basis can be specified.  The objects packaged are those not
@@ -116,7 +115,7 @@
 and move it afterwards to help build the bundle.
 
 ------------
-$ git-bundle create mybundle master ^lastR2bundle
+$ git bundle create mybundle master ^lastR2bundle
 $ git tag -f lastR2bundle master
 ------------
 
@@ -141,8 +140,8 @@
 Then you move mybundle from A to B, and in R2 on B:
 
 ------------
-$ git-bundle verify mybundle
-$ git-fetch mybundle master:localRef
+$ git bundle verify mybundle
+$ git fetch mybundle master:localRef
 ------------
 
 With something like this in the config in R2:
diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt
index f58013c..668f697 100644
--- a/Documentation/git-cat-file.txt
+++ b/Documentation/git-cat-file.txt
@@ -9,8 +9,8 @@
 SYNOPSIS
 --------
 [verse]
-'git-cat-file' [-t | -s | -e | -p | <type>] <object>
-'git-cat-file' [--batch | --batch-check] < <list-of-objects>
+'git cat-file' [-t | -s | -e | -p | <type>] <object>
+'git cat-file' [--batch | --batch-check] < <list-of-objects>
 
 DESCRIPTION
 -----------
@@ -81,7 +81,7 @@
 ------------
 
 If '--batch-check' is specified, output of the following form is printed for
-each object specified fon stdin:
+each object specified on stdin:
 
 ------------
 <sha1> SP <type> SP <size> LF
diff --git a/Documentation/git-check-attr.txt b/Documentation/git-check-attr.txt
index f8e1bd5..043274b 100644
--- a/Documentation/git-check-attr.txt
+++ b/Documentation/git-check-attr.txt
@@ -3,12 +3,12 @@
 
 NAME
 ----
-git-check-attr - Display gitattributes information.
+git-check-attr - Display gitattributes information
 
 
 SYNOPSIS
 --------
-'git-check-attr' attr... [--] pathname...
+'git check-attr' attr... [--] pathname...
 
 DESCRIPTION
 -----------
@@ -22,6 +22,56 @@
 	arguments as path names. If not supplied, only the first argument will
 	be treated as an attribute.
 
+OUTPUT
+------
+
+The output is of the form:
+<path> COLON SP <attribute> COLON SP <info> LF
+
+Where <path> is the path of a file being queried, <attribute> is an attribute
+being queried and <info> can be either:
+
+'unspecified';; when the attribute is not defined for the path.
+'unset';;	when the attribute is defined to false.
+'set';;		when the attribute is defined to true.
+<value>;;	when a value has been assigned to the attribute.
+
+EXAMPLES
+--------
+
+In the examples, the following '.gitattributes' file is used:
+---------------
+*.java diff=java -crlf myAttr
+NoMyAttr.java !myAttr
+README caveat=unspecified
+---------------
+
+* Listing a single attribute:
+---------------
+$ git check-attr diff org/example/MyClass.java
+org/example/MyClass.java: diff: java
+---------------
+
+* Listing multiple attributes for a file:
+---------------
+$ git check-attr crlf diff myAttr -- org/example/MyClass.java
+org/example/MyClass.java: crlf: unset
+org/example/MyClass.java: diff: java
+org/example/MyClass.java: myAttr: set
+---------------
+
+* Listing attribute for multiple files:
+---------------
+$ git check-attr myAttr -- org/example/MyClass.java org/example/NoMyAttr.java
+org/example/MyClass.java: myAttr: set
+org/example/NoMyAttr.java: myAttr: unspecified
+---------------
+
+* Not all values are equally unambiguous:
+---------------
+$ git check-attr caveat README
+README: caveat: unspecified
+---------------
 
 SEE ALSO
 --------
diff --git a/Documentation/git-check-ref-format.txt b/Documentation/git-check-ref-format.txt
index c560c0a..034223c 100644
--- a/Documentation/git-check-ref-format.txt
+++ b/Documentation/git-check-ref-format.txt
@@ -7,7 +7,7 @@
 
 SYNOPSIS
 --------
-'git-check-ref-format' <refname>
+'git check-ref-format' <refname>
 
 DESCRIPTION
 -----------
@@ -47,7 +47,7 @@
 . colon `:` is used as in `srcref:dstref` to mean "use srcref\'s
   value and store it in dstref" in fetch and push operations.
   It may also be used to select a specific object such as with
-  linkgit:git-cat-file[1] "git-cat-file blob v1.3.3:refs.c".
+  'git-cat-file': "git cat-file blob v1.3.3:refs.c".
 
 
 GIT
diff --git a/Documentation/git-checkout-index.txt b/Documentation/git-checkout-index.txt
index 676203b..62d8483 100644
--- a/Documentation/git-checkout-index.txt
+++ b/Documentation/git-checkout-index.txt
@@ -9,7 +9,7 @@
 SYNOPSIS
 --------
 [verse]
-'git-checkout-index' [-u] [-q] [-a] [-f] [-n] [--prefix=<string>]
+'git checkout-index' [-u] [-q] [-a] [-f] [-n] [--prefix=<string>]
 		   [--stage=<number>|all]
 		   [--temp]
 		   [-z] [--stdin]
@@ -73,25 +73,25 @@
 
 The order of the flags used to matter, but not anymore.
 
-Just doing `git-checkout-index` does nothing. You probably meant
-`git-checkout-index -a`. And if you want to force it, you want
-`git-checkout-index -f -a`.
+Just doing `git checkout-index` does nothing. You probably meant
+`git checkout-index -a`. And if you want to force it, you want
+`git checkout-index -f -a`.
 
 Intuitiveness is not the goal here. Repeatability is. The reason for
 the "no arguments means no work" behavior is that from scripts you are
 supposed to be able to do:
 
 ----------------
-$ find . -name '*.h' -print0 | xargs -0 git-checkout-index -f --
+$ find . -name '*.h' -print0 | xargs -0 git checkout-index -f --
 ----------------
 
 which will force all existing `*.h` files to be replaced with their
 cached copies. If an empty command line implied "all", then this would
 force-refresh everything in the index, which was not the point.  But
-since git-checkout-index accepts --stdin it would be faster to use:
+since 'git-checkout-index' accepts --stdin it would be faster to use:
 
 ----------------
-$ find . -name '*.h' -print0 | git-checkout-index -f -z --stdin
+$ find . -name '*.h' -print0 | git checkout-index -f -z --stdin
 ----------------
 
 The `--` is just a good idea when you know the rest will be filenames;
@@ -102,7 +102,7 @@
 Using --temp or --stage=all
 ---------------------------
 When `--temp` is used (or implied by `--stage=all`)
-`git-checkout-index` will create a temporary file for each index
+'git-checkout-index' will create a temporary file for each index
 entry being checked out.  The index will not be updated with stat
 information.  These options can be useful if the caller needs all
 stages of all unmerged entries so that the unmerged files can be
@@ -144,19 +144,19 @@
 To update and refresh only the files already checked out::
 +
 ----------------
-$ git-checkout-index -n -f -a && git-update-index --ignore-missing --refresh
+$ git checkout-index -n -f -a && git update-index --ignore-missing --refresh
 ----------------
 
-Using `git-checkout-index` to "export an entire tree"::
+Using 'git-checkout-index' to "export an entire tree"::
 	The prefix ability basically makes it trivial to use
-	`git-checkout-index` as an "export as tree" function.
+	'git-checkout-index' as an "export as tree" function.
 	Just read the desired tree into the index, and do:
 +
 ----------------
-$ git-checkout-index --prefix=git-export-dir/ -a
+$ git checkout-index --prefix=git-export-dir/ -a
 ----------------
 +
-`git-checkout-index` will "export" the index into the specified
+`git checkout-index` will "export" the index into the specified
 directory.
 +
 The final "/" is important. The exported name is literally just
@@ -166,7 +166,7 @@
 Export files with a prefix::
 +
 ----------------
-$ git-checkout-index --prefix=.merged- Makefile
+$ git checkout-index --prefix=.merged- Makefile
 ----------------
 +
 This will check out the currently cached copy of `Makefile`
diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index 3ad9760..5aa69c0 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -8,8 +8,8 @@
 SYNOPSIS
 --------
 [verse]
-'git-checkout' [-q] [-f] [[--track | --no-track] -b <new_branch> [-l]] [-m] [<branch>]
-'git-checkout' [<tree-ish>] <paths>...
+'git checkout' [-q] [-f] [[--track | --no-track] -b <new_branch> [-l]] [-m] [<branch>]
+'git checkout' [<tree-ish>] [--] <paths>...
 
 DESCRIPTION
 -----------
@@ -23,7 +23,7 @@
 
 When <paths> are given, this command does *not* switch
 branches.  It updates the named paths in the working tree from
-the index file (i.e. it runs `git-checkout-index -f -u`), or
+the index file (i.e. it runs `git checkout-index -f -u`), or
 from a named commit.  In
 this case, the `-f` and `-b` options are meaningless and giving
 either of them results in an error.  <tree-ish> argument can be
@@ -49,14 +49,14 @@
 
 -t::
 --track::
-	When creating a new branch, set up configuration so that git-pull
+	When creating a new branch, set up configuration so that 'git-pull'
 	will automatically retrieve data from the start point, which must be
 	a branch. Use this if you always pull from the same upstream branch
 	into the new branch, and if you don't want to use "git pull
 	<repository> <refspec>" explicitly. This behavior is the default
 	when the start point is a remote branch. Set the
 	branch.autosetupmerge configuration variable to `false` if you want
-	git-checkout and git-branch to always behave as if '--no-track' were
+	'git-checkout' and 'git-branch' to always behave as if '--no-track' were
 	given. Set it to `always` if you want this behavior when the
 	start-point is either a local or remote branch.
 
@@ -112,7 +112,7 @@
 (`v2.6.18` in the above example).
 
 You can use usual git commands while in this state.  You can use
-`git-reset --hard $othercommit` to further move around, for
+`git reset --hard $othercommit` to further move around, for
 example.  You can make changes and create a new commit on top of
 a detached HEAD.  You can even create a merge by using `git
 merge $othercommit`.
diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt
index 44e7749..b764130 100644
--- a/Documentation/git-cherry-pick.txt
+++ b/Documentation/git-cherry-pick.txt
@@ -7,7 +7,7 @@
 
 SYNOPSIS
 --------
-'git-cherry-pick' [--edit] [-n] [-m parent-number] [-s] [-x] <commit>
+'git cherry-pick' [--edit] [-n] [-m parent-number] [-s] [-x] <commit>
 
 DESCRIPTION
 -----------
@@ -19,12 +19,12 @@
 -------
 <commit>::
 	Commit to cherry-pick.
-	For a more complete list of ways to spell commits, see
+	For a more complete list of ways to spell commits, see the
 	"SPECIFYING REVISIONS" section in linkgit:git-rev-parse[1].
 
 -e::
 --edit::
-	With this option, `git-cherry-pick` will let you edit the commit
+	With this option, 'git-cherry-pick' will let you edit the commit
 	message prior to committing.
 
 -x::
@@ -55,13 +55,12 @@
 
 -n::
 --no-commit::
-	Usually the command automatically creates a commit with
-	a commit log message stating which commit was
-	cherry-picked.  This flag applies the change necessary
-	to cherry-pick the named commit to your working tree
-	and the index, but does not make the commit.  In addition,
-	when this option is used, your index does not have to match
-	the HEAD commit.  The cherry-pick is done against the
+	Usually the command automatically creates a commit.
+	This flag applies the change necessary to cherry-pick
+	the named commit to your working tree and the index,
+	but does not make the commit.  In addition, when this
+	option is used, your index does not have to match the
+	HEAD commit.  The cherry-pick is done against the
 	beginning state of your index.
 +
 This is useful when cherry-picking more than one commits'
diff --git a/Documentation/git-cherry.txt b/Documentation/git-cherry.txt
index 9126011..74d14c4 100644
--- a/Documentation/git-cherry.txt
+++ b/Documentation/git-cherry.txt
@@ -7,14 +7,14 @@
 
 SYNOPSIS
 --------
-'git-cherry' [-v] <upstream> [<head>] [<limit>]
+'git cherry' [-v] <upstream> [<head>] [<limit>]
 
 DESCRIPTION
 -----------
 The changeset (or "diff") of each commit between the fork-point and <head>
 is compared against each commit between the fork-point and <upstream>.
-The commits are compared with their 'patch id', obtained from linkgit:git-patch-id[1]
-program.
+The commits are compared with their 'patch id', obtained from
+the 'git-patch-id' program.
 
 Every commit that doesn't exist in the <upstream> branch
 has its id (sha1) reported, prefixed by a symbol.  The ones that have
@@ -37,8 +37,8 @@
               \__*__*__<limit>__-__+__> <head>
 
 
-Because git-cherry compares the changeset rather than the commit id
-(sha1), you can use git-cherry to find out if a commit you made locally
+Because 'git-cherry' compares the changeset rather than the commit id
+(sha1), you can use 'git-cherry' to find out if a commit you made locally
 has been applied <upstream> under a different commit id.  For example,
 this will happen if you're feeding patches <upstream> via email rather
 than pushing or pulling commits directly.
diff --git a/Documentation/git-citool.txt b/Documentation/git-citool.txt
index 09108d0..670cb02 100644
--- a/Documentation/git-citool.txt
+++ b/Documentation/git-citool.txt
@@ -14,9 +14,9 @@
 A Tcl/Tk based graphical interface to review modified files, stage
 them into the index, enter a commit message and record the new
 commit onto the current branch.  This interface is an alternative
-to the less interactive linkgit:git-commit[1] program.
+to the less interactive 'git-commit' program.
 
-git-citool is actually a standard alias for 'git gui citool'.
+'git-citool' is actually a standard alias for `git gui citool`.
 See linkgit:git-gui[1] for more details.
 
 Author
diff --git a/Documentation/git-clean.txt b/Documentation/git-clean.txt
index 37a82ee..8a11450 100644
--- a/Documentation/git-clean.txt
+++ b/Documentation/git-clean.txt
@@ -8,7 +8,7 @@
 SYNOPSIS
 --------
 [verse]
-'git-clean' [-d] [-f] [-n] [-q] [-x | -X] [--] <paths>...
+'git clean' [-d] [-f] [-n] [-q] [-x | -X] [--] <path>...
 
 DESCRIPTION
 -----------
@@ -16,8 +16,8 @@
 from files that are not under version control.  If the '-x' option is
 specified, ignored files are also removed, allowing to remove all
 build products.
-When optional `<paths>...` arguments are given, the paths
-affected are further limited to those that match them.
+If any optional `<path>...` arguments are given, only those paths
+are affected.
 
 
 OPTIONS
@@ -27,7 +27,7 @@
 
 -f::
 	If the git configuration specifies clean.requireForce as true,
-	git-clean will refuse to run unless given -f or -n.
+	'git-clean' will refuse to run unless given -f or -n.
 
 -n::
 --dry-run::
@@ -41,7 +41,7 @@
 -x::
 	Don't use the ignore rules.  This allows removing all untracked
 	files, including build products.  This can be used (possibly in
-	conjunction with linkgit:git-reset[1]) to create a pristine
+	conjunction with 'git-reset') to create a pristine
 	working directory to test a clean build.
 
 -X::
diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index 7973e6a..0e14e73 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -9,8 +9,8 @@
 SYNOPSIS
 --------
 [verse]
-'git-clone' [--template=<template_directory>]
-	  [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare]
+'git clone' [--template=<template_directory>]
+	  [-l] [-s] [--no-hardlinks] [-q] [-n] [--bare] [--mirror]
 	  [-o <name>] [-u <upload-pack>] [--reference <repository>]
 	  [--depth <depth>] [--] <repository> [<directory>]
 
@@ -68,10 +68,10 @@
 repository using this option and then delete branches (or use any
 other git command that makes any existing commit unreferenced) in the
 source repository, some objects may become unreferenced (or dangling).
-These objects may be removed by normal git operations (such as git-commit[1])
-which automatically call git-gc[1]. If these objects are removed and
-were referenced by the cloned repository, then the cloned repository
-will become corrupt.
+These objects may be removed by normal git operations (such as 'git-commit')
+which automatically call `git gc --auto`. (See linkgit:git-gc[1].)
+If these objects are removed and were referenced by the cloned repository,
+then the cloned repository will become corrupt.
 
 
 
@@ -87,8 +87,8 @@
 
 --quiet::
 -q::
-	Operate quietly.  This flag is passed to "rsync" and
-	"git-fetch-pack" commands when given.
+	Operate quietly.  This flag is also passed to the `rsync'
+	command when given.
 
 --no-checkout::
 -n::
@@ -106,6 +106,9 @@
 	used, neither remote-tracking branches nor the related
 	configuration variables are created.
 
+--mirror::
+	Set up a mirror of the remote repository.  This implies --bare.
+
 --origin <name>::
 -o <name>::
 	Instead of using the remote name 'origin' to keep track
@@ -113,9 +116,8 @@
 
 --upload-pack <upload-pack>::
 -u <upload-pack>::
-	When given, and the repository to clone from is handled
-	by 'git-fetch-pack', '--exec=<upload-pack>' is passed to
-	the command to specify non-default path for the command
+	When given, and the repository to clone from is accessed
+	via ssh, this specifies a non-default path for the command
 	run on the other end.
 
 --template=<template_directory>::
diff --git a/Documentation/git-commit-tree.txt b/Documentation/git-commit-tree.txt
index 728c2fa..b8834ba 100644
--- a/Documentation/git-commit-tree.txt
+++ b/Documentation/git-commit-tree.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-commit-tree' <tree> [-p <parent commit>]\* < changelog
+'git commit-tree' <tree> [-p <parent commit>]\* < changelog
 
 DESCRIPTION
 -----------
@@ -16,12 +16,12 @@
 linkgit:git-commit[1] instead.
 
 Creates a new commit object based on the provided tree object and
-emits the new commit object id on stdout. If no parent is given then
-it is considered to be an initial tree.
+emits the new commit object id on stdout.
 
-A commit object usually has 1 parent (a commit after a change) or up
-to 16 parents.  More than one parent represents a merge of branches
-that led to them.
+A commit object may have any number of parents. With exactly one
+parent, it is an ordinary commit. Having more than one parent makes
+the commit a merge between several lines of history. Initial (root)
+commits have no parents.
 
 While a tree represents a particular directory state of a working
 directory, a commit represents that state in "time", and explains how
@@ -70,7 +70,7 @@
 present, system user name and fully qualified hostname.
 
 A commit comment is read from stdin. If a changelog
-entry is not provided via "<" redirection, "git-commit-tree" will just wait
+entry is not provided via "<" redirection, 'git-commit-tree' will just wait
 for one to be entered and terminated with ^D.
 
 
@@ -79,9 +79,9 @@
 You don't exist. Go away!::
     The passwd(5) gecos field couldn't be read
 Your parents must have hated you!::
-    The password(5) gecos field is longer than a giant static buffer.
+    The passwd(5) gecos field is longer than a giant static buffer.
 Your sysadmin must hate you!::
-    The password(5) name field is longer than a giant static buffer.
+    The passwd(5) name field is longer than a giant static buffer.
 
 Discussion
 ----------
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index 861ce93..5cce3a3 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -8,23 +8,23 @@
 SYNOPSIS
 --------
 [verse]
-'git-commit' [-a | --interactive] [-s] [-v] [-u] [--amend]
+'git commit' [-a | --interactive] [-s] [-v] [-u<mode>] [--amend]
 	   [(-c | -C) <commit>] [-F <file> | -m <msg>]
 	   [--allow-empty] [--no-verify] [-e] [--author=<author>]
 	   [--cleanup=<mode>] [--] [[-i | -o ]<file>...]
 
 DESCRIPTION
 -----------
-Use 'git commit' to store the current contents of the index in a new
-commit along with a log message describing the changes you have made.
+Stores the current contents of the index in a new commit along
+with a log message from the user describing the changes.
 
 The content to be added can be specified in several ways:
 
-1. by using linkgit:git-add[1] to incrementally "add" changes to the
+1. by using 'git-add' to incrementally "add" changes to the
    index before using the 'commit' command (Note: even modified
    files must be "added");
 
-2. by using linkgit:git-rm[1] to remove files from the working tree
+2. by using 'git-rm' to remove files from the working tree
    and the index, again before using the 'commit' command;
 
 3. by listing files as arguments to the 'commit' command, in which
@@ -39,15 +39,15 @@
 
 5. by using the --interactive switch with the 'commit' command to decide one
    by one which files should be part of the commit, before finalizing the
-   operation.  Currently, this is done by invoking `git-add --interactive`.
+   operation.  Currently, this is done by invoking 'git-add --interactive'.
 
-The linkgit:git-status[1] command can be used to obtain a
+The 'git-status' command can be used to obtain a
 summary of what is included by any of the above for the next
 commit by giving the same set of parameters you would give to
 this command.
 
-If you make a commit and then found a mistake immediately after
-that, you can recover from it with linkgit:git-reset[1].
+If you make a commit and then find a mistake immediately after
+that, you can recover from it with 'git-reset'.
 
 
 OPTIONS
@@ -92,12 +92,13 @@
 
 -s::
 --signoff::
-	Add Signed-off-by line at the end of the commit message.
+	Add Signed-off-by line by the committer at the end of the commit
+	log message.
 
 -n::
 --no-verify::
 	This option bypasses the pre-commit and commit-msg hooks.
-	See also linkgit:githooks[5][hooks].
+	See also linkgit:githooks[5].
 
 --allow-empty::
 	Usually recording a commit that has the exact same tree as its
@@ -155,20 +156,29 @@
 	Make a commit only from the paths specified on the
 	command line, disregarding any contents that have been
 	staged so far. This is the default mode of operation of
-	'git commit' if any paths are given on the command line,
+	'git-commit' if any paths are given on the command line,
 	in which case this option can be omitted.
 	If this option is specified together with '--amend', then
-	no paths need be specified, which can be used to amend
+	no paths need to be specified, which can be used to amend
 	the last commit without committing changes that have
 	already been staged.
 
--u::
---untracked-files::
-	Show all untracked files, also those in uninteresting
-	directories, in the "Untracked files:" section of commit
-	message template.  Without this option only its name and
-	a trailing slash are displayed for each untracked
-	directory.
+-u[<mode>]::
+--untracked-files[=<mode>]::
+	Show untracked files (Default: 'all').
++
+The mode parameter is optional, and is used to specify
+the handling of untracked files. The possible options are:
++
+--
+	- 'no'     - Show no untracked files
+	- 'normal' - Shows untracked files and directories
+	- 'all'    - Also shows individual files in untracked directories.
+--
++
+See linkgit:git-config[1] for configuration variable
+used to change the default for when the option is not
+specified.
 
 -v::
 --verbose::
@@ -196,10 +206,10 @@
 --------
 When recording your own work, the contents of modified files in
 your working tree are temporarily stored to a staging area
-called the "index" with linkgit:git-add[1].  A file can be
+called the "index" with 'git-add'.  A file can be
 reverted back, only in the index but not in the working tree,
-to that of the last commit with `git-reset HEAD -- <file>`,
-which effectively reverts `git-add` and prevents the changes to
+to that of the last commit with `git reset HEAD -- <file>`,
+which effectively reverts 'git-add' and prevents the changes to
 this file from participating in the next commit.  After building
 the state to be committed incrementally with these commands,
 `git commit` (without any pathname parameter) is used to record what
@@ -255,13 +265,13 @@
 this second commit would record the changes to `hello.c` and
 `hello.h` as expected.
 
-After a merge (initiated by either linkgit:git-merge[1] or
-linkgit:git-pull[1]) stops because of conflicts, cleanly merged
+After a merge (initiated by 'git-merge' or 'git-pull') stops
+because of conflicts, cleanly merged
 paths are already staged to be committed for you, and paths that
 conflicted are left in unmerged state.  You would have to first
-check which paths are conflicting with linkgit:git-status[1]
+check which paths are conflicting with 'git-status'
 and after fixing them manually in your working tree, you would
-stage the result as usual with linkgit:git-add[1]:
+stage the result as usual with 'git-add':
 
 ------------
 $ git status | grep unmerged
@@ -307,7 +317,7 @@
 HOOKS
 -----
 This command can run `commit-msg`, `prepare-commit-msg`, `pre-commit`,
-and `post-commit` hooks.  See linkgit:githooks[5][hooks] for more
+and `post-commit` hooks.  See linkgit:githooks[5] for more
 information.
 
 
diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
index b0f20e2..19a8917 100644
--- a/Documentation/git-config.txt
+++ b/Documentation/git-config.txt
@@ -9,19 +9,19 @@
 SYNOPSIS
 --------
 [verse]
-'git-config' [<file-option>] [type] [-z|--null] name [value [value_regex]]
-'git-config' [<file-option>] [type] --add name value
-'git-config' [<file-option>] [type] --replace-all name [value [value_regex]]
-'git-config' [<file-option>] [type] [-z|--null] --get name [value_regex]
-'git-config' [<file-option>] [type] [-z|--null] --get-all name [value_regex]
-'git-config' [<file-option>] [type] [-z|--null] --get-regexp name_regex [value_regex]
-'git-config' [<file-option>] --unset name [value_regex]
-'git-config' [<file-option>] --unset-all name [value_regex]
-'git-config' [<file-option>] --rename-section old_name new_name
-'git-config' [<file-option>] --remove-section name
-'git-config' [<file-option>] [-z|--null] -l | --list
-'git-config' [<file-option>] --get-color name [default]
-'git-config' [<file-option>] --get-colorbool name [stdout-is-tty]
+'git config' [<file-option>] [type] [-z|--null] name [value [value_regex]]
+'git config' [<file-option>] [type] --add name value
+'git config' [<file-option>] [type] --replace-all name [value [value_regex]]
+'git config' [<file-option>] [type] [-z|--null] --get name [value_regex]
+'git config' [<file-option>] [type] [-z|--null] --get-all name [value_regex]
+'git config' [<file-option>] [type] [-z|--null] --get-regexp name_regex [value_regex]
+'git config' [<file-option>] --unset name [value_regex]
+'git config' [<file-option>] --unset-all name [value_regex]
+'git config' [<file-option>] --rename-section old_name new_name
+'git config' [<file-option>] --remove-section name
+'git config' [<file-option>] [-z|--null] -l | --list
+'git config' [<file-option>] --get-color name [default]
+'git config' [<file-option>] --get-colorbool name [stdout-is-tty]
 
 DESCRIPTION
 -----------
@@ -122,10 +122,10 @@
 	List all variables set in config file.
 
 --bool::
-	git-config will ensure that the output is "true" or "false"
+	'git-config' will ensure that the output is "true" or "false"
 
 --int::
-	git-config will ensure that the output is a simple
+	'git-config' will ensure that the output is a simple
 	decimal number.  An optional value suffix of 'k', 'm', or 'g'
 	in the config file will cause the value to be multiplied
 	by 1024, 1048576, or 1073741824 prior to output.
@@ -162,7 +162,7 @@
 -----
 
 If not set explicitly with '--file', there are three files where
-git-config will search for configuration options:
+'git-config' will search for configuration options:
 
 $GIT_DIR/config::
 	Repository specific configuration file. (The filename is
@@ -179,23 +179,18 @@
 If no further options are given, all reading options will read all of these
 files that are available. If the global or the system-wide configuration
 file are not available they will be ignored. If the repository configuration
-file is not available or readable, git-config will exit with a non-zero
+file is not available or readable, 'git-config' will exit with a non-zero
 error code. However, in neither case will an error message be issued.
 
 All writing options will per default write to the repository specific
 configuration file. Note that this also affects options like '--replace-all'
-and '--unset'. *git-config will only ever change one file at a time*.
+and '--unset'. *'git-config' will only ever change one file at a time*.
 
 You can override these rules either by command line options or by environment
 variables. The '--global' and the '--system' options will limit the file used
 to the global or system-wide file respectively. The GIT_CONFIG environment
 variable has a similar effect, but you can specify any filename you want.
 
-The GIT_CONFIG_LOCAL environment variable on the other hand only changes
-the name used instead of the repository configuration file. The global and
-the system-wide configuration files will still be read. (For writing options
-this will obviously result in the same behavior as using GIT_CONFIG.)
-
 
 ENVIRONMENT
 -----------
@@ -205,10 +200,6 @@
 	Using the "--global" option forces this to ~/.gitconfig. Using the
 	"--system" option forces this to $(prefix)/etc/gitconfig.
 
-GIT_CONFIG_LOCAL::
-	Take the configuration from the given file instead if .git/config.
-	Still read the global and the system-wide configuration files, though.
-
 See also <<FILES>>.
 
 
@@ -288,7 +279,7 @@
 % git config --get-all core.gitproxy
 ------------
 
-If you like to live dangerous, you can replace *all* core.gitproxy by a
+If you like to live dangerously, you can replace *all* core.gitproxy by a
 new one with
 
 ------------
diff --git a/Documentation/git-count-objects.txt b/Documentation/git-count-objects.txt
index 4a9dcd7..75a8da1 100644
--- a/Documentation/git-count-objects.txt
+++ b/Documentation/git-count-objects.txt
@@ -7,7 +7,7 @@
 
 SYNOPSIS
 --------
-'git-count-objects' [-v]
+'git count-objects' [-v]
 
 DESCRIPTION
 -----------
@@ -22,7 +22,7 @@
 	In addition to the number of loose objects and disk
 	space consumed, it reports the number of in-pack
 	objects, number of packs, and number of objects that can be
-	removed by running `git-prune-packed`.
+	removed by running `git prune-packed`.
 
 
 Author
diff --git a/Documentation/git-cvsexportcommit.txt b/Documentation/git-cvsexportcommit.txt
index 5fa91e5..2da8588 100644
--- a/Documentation/git-cvsexportcommit.txt
+++ b/Documentation/git-cvsexportcommit.txt
@@ -8,7 +8,8 @@
 
 SYNOPSIS
 --------
-'git-cvsexportcommit' [-h] [-u] [-v] [-c] [-P] [-p] [-a] [-d cvsroot] [-w cvsworkdir] [-W] [-f] [-m msgprefix] [PARENTCOMMIT] COMMITID
+'git cvsexportcommit' [-h] [-u] [-v] [-c] [-P] [-p] [-a] [-d cvsroot]
+	[-w cvsworkdir] [-W] [-f] [-m msgprefix] [PARENTCOMMIT] COMMITID
 
 
 DESCRIPTION
@@ -26,8 +27,8 @@
 
 Supports file additions, removals, and commits that affect binary files.
 
-If the commit is a merge commit, you must tell git-cvsexportcommit what parent
-should the changeset be done against.
+If the commit is a merge commit, you must tell 'git-cvsexportcommit' what
+parent the changeset should be done against.
 
 OPTIONS
 -------
@@ -89,14 +90,14 @@
 ------------
 $ export GIT_DIR=~/project/.git
 $ cd ~/project_cvs_checkout
-$ git-cvsexportcommit -v <commit-sha1>
+$ git cvsexportcommit -v <commit-sha1>
 $ cvs commit -F .msg <files>
 ------------
 
 Merge one patch into CVS (-c and -w options). The working directory is within the Git Repo::
 +
 ------------
-	$ git-cvsexportcommit -v -c -w ~/project_cvs_checkout <commit-sha1>
+	$ git cvsexportcommit -v -c -w ~/project_cvs_checkout <commit-sha1>
 ------------
 
 Merge pending patches into CVS automatically -- only if you really know what you are doing::
@@ -104,7 +105,7 @@
 ------------
 $ export GIT_DIR=~/project/.git
 $ cd ~/project_cvs_checkout
-$ git-cherry cvshead myhead | sed -n 's/^+ //p' | xargs -l1 git-cvsexportcommit -c -p -v
+$ git cherry cvshead myhead | sed -n 's/^+ //p' | xargs -l1 git cvsexportcommit -c -p -v
 ------------
 
 Author
diff --git a/Documentation/git-cvsimport.txt b/Documentation/git-cvsimport.txt
index 93b7d2d..b7a8c10 100644
--- a/Documentation/git-cvsimport.txt
+++ b/Documentation/git-cvsimport.txt
@@ -9,7 +9,7 @@
 SYNOPSIS
 --------
 [verse]
-'git-cvsimport' [-o <branch-for-HEAD>] [-h] [-v] [-d <CVSROOT>]
+'git cvsimport' [-o <branch-for-HEAD>] [-h] [-v] [-d <CVSROOT>]
 	      [-A <author-conv-file>] [-p <options-for-cvsps>] [-P <file>]
 	      [-C <git_repository>] [-z <fuzz>] [-i] [-k] [-u] [-s <subst>]
 	      [-a] [-m] [-M <regex>] [-S <regex>] [-L <commitlimit>]
@@ -25,9 +25,9 @@
 At least version 2.1 is required.
 
 You should *never* do any work of your own on the branches that are
-created by git-cvsimport.  By default initial import will create and populate a
+created by 'git-cvsimport'.  By default initial import will create and populate a
 "master" branch from the CVS repository's main branch which you're free
-to work with; after that, you need to 'git merge' incremental imports, or
+to work with; after that, you need to 'git-merge' incremental imports, or
 any CVS branches, yourself.  It is advisable to specify a named remote via
 -r to separate and protect the incoming branches.
 
@@ -46,13 +46,13 @@
 -d <CVSROOT>::
 	The root of the CVS archive. May be local (a simple path) or remote;
 	currently, only the :local:, :ext: and :pserver: access methods
-	are supported. If not given, git-cvsimport will try to read it
+	are supported. If not given, 'git-cvsimport' will try to read it
 	from `CVS/Root`. If no such file exists, it checks for the
 	`CVSROOT` environment variable.
 
 <CVS_module>::
 	The CVS module you want to import. Relative to <CVSROOT>.
-	If not given, git-cvsimport tries to read it from
+	If not given, 'git-cvsimport' tries to read it from
 	`CVS/Repository`.
 
 -C <target-dir>::
@@ -62,14 +62,14 @@
 -r <remote>::
 	The git remote to import this CVS repository into.
 	Moves all CVS branches into remotes/<remote>/<branch>
-	akin to the git-clone --use-separate-remote option.
+	akin to the 'git-clone' "--use-separate-remote" option.
 
 -o <branch-for-HEAD>::
 	When no remote is specified (via -r) the 'HEAD' branch
 	from CVS is imported to the 'origin' branch within the git
 	repository, as 'HEAD' already has a special meaning for git.
 	When a remote is specified the 'HEAD' branch is named
-	remotes/<remote>/master mirroring git-clone behaviour.
+	remotes/<remote>/master mirroring 'git-clone' behaviour.
 	Use this option if you want to import into a different
 	branch.
 +
@@ -142,17 +142,17 @@
 
 ---------
 +
-git-cvsimport will make it appear as those authors had
+'git-cvsimport' will make it appear as those authors had
 their GIT_AUTHOR_NAME and GIT_AUTHOR_EMAIL set properly
 all along.
 +
 For convenience, this data is saved to `$GIT_DIR/cvs-authors`
 each time the '-A' option is provided and read from that same
-file each time git-cvsimport is run.
+file each time 'git-cvsimport' is run.
 +
 It is not recommended to use this feature if you intend to
 export changes back to CVS again later with
-linkgit:git-cvsexportcommit[1].
+'git-cvsexportcommit'.
 
 -h::
 	Print a short usage message and exit.
diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt
index 19da87e..785779e 100644
--- a/Documentation/git-cvsserver.txt
+++ b/Documentation/git-cvsserver.txt
@@ -11,7 +11,7 @@
 SSH:
 
 [verse]
-export CVS_SERVER=git-cvsserver
+export CVS_SERVER="git cvsserver"
 'cvs' -d :ext:user@server/path/repo.git co <HEAD_name>
 
 pserver (/etc/inetd.conf):
@@ -22,7 +22,7 @@
 Usage:
 
 [verse]
-'git-cvsserver' [options] [pserver|server] [<directory> ...]
+'git cvsserver' [options] [pserver|server] [<directory> ...]
 
 OPTIONS
 -------
@@ -77,7 +77,7 @@
 
 CVS clients cannot tag, branch or perform GIT merges.
 
-git-cvsserver maps GIT branches to CVS modules. This is very different
+'git-cvsserver' maps GIT branches to CVS modules. This is very different
 from what most CVS users would expect since in CVS modules usually represent
 one or more directories.
 
@@ -103,19 +103,19 @@
 ------
 No special setup is needed for SSH access, other than having GIT tools
 in the PATH. If you have clients that do not accept the CVS_SERVER
-environment variable, you can rename git-cvsserver to cvs.
+environment variable, you can rename 'git-cvsserver' to `cvs`.
 
 Note: Newer CVS versions (>= 1.12.11) also support specifying
 CVS_SERVER directly in CVSROOT like
 
 ------
-cvs -d ":ext;CVS_SERVER=git-cvsserver:user@server/path/repo.git" co <HEAD_name>
+cvs -d ":ext;CVS_SERVER=git cvsserver:user@server/path/repo.git" co <HEAD_name>
 ------
 This has the advantage that it will be saved in your 'CVS/Root' files and
 you don't need to worry about always setting the correct environment
-variable.  SSH users restricted to git-shell don't need to override the default
-with CVS_SERVER (and shouldn't) as git-shell understands `cvs` to mean
-git-cvsserver and pretends that the other end runs the real cvs better.
+variable.  SSH users restricted to 'git-shell' don't need to override the default
+with CVS_SERVER (and shouldn't) as 'git-shell' understands `cvs` to mean
+'git-cvsserver' and pretends that the other end runs the real 'cvs' better.
 --
 2. For each repo that you want accessible from CVS you need to edit config in
    the repo and add the following section.
@@ -128,7 +128,7 @@
         logfile=/path/to/logfile
 
 ------
-Note: you need to ensure each user that is going to invoke git-cvsserver has
+Note: you need to ensure each user that is going to invoke 'git-cvsserver' has
 write access to the log file and to the database (see
 <<dbbackend,Database Backend>>. If you want to offer write access over
 SSH, the users of course also need write access to the git repository itself.
@@ -153,12 +153,12 @@
    automatically saving it in your 'CVS/Root' files, then you need to set them
    explicitly in your environment.  CVSROOT should be set as per normal, but the
    directory should point at the appropriate git repo.  As above, for SSH clients
-   _not_ restricted to git-shell, CVS_SERVER should be set to git-cvsserver.
+   _not_ restricted to 'git-shell', CVS_SERVER should be set to 'git-cvsserver'.
 +
 --
 ------
      export CVSROOT=:ext:user@server:/var/git/project.git
-     export CVS_SERVER=git-cvsserver
+     export CVS_SERVER="git cvsserver"
 ------
 --
 4. For SSH clients that will make commits, make sure their server-side
@@ -181,27 +181,27 @@
 Database Backend
 ----------------
 
-git-cvsserver uses one database per git head (i.e. CVS module) to
+'git-cvsserver' uses one database per git head (i.e. CVS module) to
 store information about the repository for faster access. The
 database doesn't contain any persistent data and can be completely
 regenerated from the git repository at any time. The database
 needs to be updated (i.e. written to) after every commit.
 
-If the commit is done directly by using git (as opposed to
-using git-cvsserver) the update will need to happen on the
-next repository access by git-cvsserver, independent of
+If the commit is done directly by using `git` (as opposed to
+using 'git-cvsserver') the update will need to happen on the
+next repository access by 'git-cvsserver', independent of
 access method and requested operation.
 
 That means that even if you offer only read access (e.g. by using
-the pserver method), git-cvsserver should have write access to
+the pserver method), 'git-cvsserver' should have write access to
 the database to work reliably (otherwise you need to make sure
-that the database is up-to-date any time git-cvsserver is executed).
+that the database is up-to-date any time 'git-cvsserver' is executed).
 
 By default it uses SQLite databases in the git directory, named
 `gitcvs.<module_name>.sqlite`. Note that the SQLite backend creates
 temporary files in the same directory as the database file on
 write so it might not be enough to grant the users using
-git-cvsserver write access to the database file without granting
+'git-cvsserver' write access to the database file without granting
 them write access to the directory, too.
 
 You can configure the database backend with the following
@@ -210,7 +210,7 @@
 Configuring database backend
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-git-cvsserver uses the Perl DBI module. Please also read
+'git-cvsserver' uses the Perl DBI module. Please also read
 its documentation if changing these variables, especially
 about `DBI->connect()`.
 
@@ -262,7 +262,7 @@
 %a::
 	access method (one of "ext" or "pserver")
 %u::
-	Name of the user running git-cvsserver.
+	Name of the user running 'git-cvsserver'.
 	If no name can be determined, the
 	numeric uid is used.
 
@@ -283,13 +283,13 @@
 Protocol notes: If you are using anonymous access via pserver, just select that.
 Those using SSH access should choose the 'ext' protocol, and configure 'ext'
 access on the Preferences->Team->CVS->ExtConnection pane. Set CVS_SERVER to
-'git-cvsserver'. Note that password support is not good when using 'ext',
+"'git cvsserver'". Note that password support is not good when using 'ext',
 you will definitely want to have SSH keys setup.
 
 Alternatively, you can just use the non-standard extssh protocol that Eclipse
 offer. In that case CVS_SERVER is ignored, and you will have to replace
-the cvs utility on the server with git-cvsserver or manipulate your `.bashrc`
-so that calling 'cvs' effectively calls git-cvsserver.
+the cvs utility on the server with 'git-cvsserver' or manipulate your `.bashrc`
+so that calling 'cvs' effectively calls 'git-cvsserver'.
 
 Clients known to work
 ---------------------
@@ -331,14 +331,13 @@
 the correct '-k' mode will be guessed based on the contents of
 the file.
 
-For best consistency with cvs, it is probably best to override the
+For best consistency with 'cvs', it is probably best to override the
 defaults by setting `gitcvs.usecrlfattr` to true,
 and `gitcvs.allbinary` to "guess".
 
 Dependencies
 ------------
-
-git-cvsserver depends on DBD::SQLite.
+'git-cvsserver' depends on DBD::SQLite.
 
 Copyright and Authors
 ---------------------
diff --git a/Documentation/git-daemon.txt b/Documentation/git-daemon.txt
index 344f24e..4ba4b75 100644
--- a/Documentation/git-daemon.txt
+++ b/Documentation/git-daemon.txt
@@ -8,12 +8,12 @@
 SYNOPSIS
 --------
 [verse]
-'git-daemon' [--verbose] [--syslog] [--export-all]
-             [--timeout=n] [--init-timeout=n] [--strict-paths]
-             [--base-path=path] [--user-path | --user-path=path]
-             [--interpolated-path=pathtemplate]
-             [--reuseaddr] [--detach] [--pid-file=file]
-             [--enable=service] [--disable=service]
+'git daemon' [--verbose] [--syslog] [--export-all]
+	     [--timeout=n] [--init-timeout=n] [--strict-paths]
+	     [--base-path=path] [--user-path | --user-path=path]
+	     [--interpolated-path=pathtemplate]
+	     [--reuseaddr] [--detach] [--pid-file=file]
+	     [--enable=service] [--disable=service]
 	     [--allow-override=service] [--forbid-override=service]
 	     [--inetd | [--listen=host_or_ipaddr] [--port=n] [--user=user [--group=group]]
 	     [directory...]
@@ -31,32 +31,32 @@
 the offers to a whitelist comprising of those.
 
 By default, only `upload-pack` service is enabled, which serves
-`git-fetch-pack` and `git-ls-remote` clients, which are invoked
-from `git-fetch`, `git-pull`, and `git-clone`.
+'git-fetch-pack' and 'git-ls-remote' clients, which are invoked
+from 'git-fetch', 'git-pull', and 'git-clone'.
 
 This is ideally suited for read-only updates, i.e., pulling from
 git repositories.
 
-An `upload-archive` also exists to serve `git-archive`.
+An `upload-archive` also exists to serve 'git-archive'.
 
 OPTIONS
 -------
 --strict-paths::
 	Match paths exactly (i.e. don't allow "/foo/repo" when the real path is
 	"/foo/repo.git" or "/foo/repo/.git") and don't do user-relative paths.
-	git-daemon will refuse to start when this option is enabled and no
+	'git-daemon' will refuse to start when this option is enabled and no
 	whitelist is specified.
 
 --base-path::
 	Remap all the path requests as relative to the given path.
-	This is sort of "GIT root" - if you run git-daemon with
+	This is sort of "GIT root" - if you run 'git-daemon' with
 	'--base-path=/srv/git' on example.com, then if you later try to pull
-	'git://example.com/hello.git', `git-daemon` will interpret the path
+	'git://example.com/hello.git', 'git-daemon' will interpret the path
 	as '/srv/git/hello.git'.
 
 --base-path-relaxed::
 	If --base-path is enabled and repo lookup fails, with this option
-	`git-daemon` will attempt to lookup without prefixing the base path.
+	'git-daemon' will attempt to lookup without prefixing the base path.
 	This is useful for switching to --base-path usage, while still
 	allowing the old paths.
 
@@ -138,7 +138,7 @@
 +
 Giving these options is an error when used with `--inetd`; use
 the facility of inet daemon to achieve the same before spawning
-`git-daemon` if needed.
+'git-daemon' if needed.
 
 --enable=service::
 --disable=service::
@@ -164,24 +164,24 @@
 
 These services can be globally enabled/disabled using the
 command line options of this command.  If a finer-grained
-control is desired (e.g. to allow `git-archive` to be run
+control is desired (e.g. to allow 'git-archive' to be run
 against only in a few selected repositories the daemon serves),
 the per-repository configuration file can be used to enable or
 disable them.
 
 upload-pack::
-	This serves `git-fetch-pack` and `git-ls-remote`
+	This serves 'git-fetch-pack' and 'git-ls-remote'
 	clients.  It is enabled by default, but a repository can
 	disable it by setting `daemon.uploadpack` configuration
 	item to `false`.
 
 upload-archive::
-	This serves `git-archive --remote`.  It is disabled by
+	This serves 'git-archive --remote'.  It is disabled by
 	default, but a repository can enable it by setting
 	`daemon.uploadarch` configuration item to `true`.
 
 receive-pack::
-	This serves `git-send-pack` clients, allowing anonymous
+	This serves 'git-send-pack' clients, allowing anonymous
 	push.  It is disabled by default, as there is _no_
 	authentication in the protocol (in other words, anybody
 	can push anything into the repository, including removal
@@ -199,28 +199,28 @@
 git		9418/tcp		# Git Version Control System
 ------------
 
-git-daemon as inetd server::
-	To set up `git-daemon` as an inetd service that handles any
+'git-daemon' as inetd server::
+	To set up 'git-daemon' as an inetd service that handles any
 	repository under the whitelisted set of directories, /pub/foo
 	and /pub/bar, place an entry like the following into
 	/etc/inetd all on one line:
 +
 ------------------------------------------------
-	git stream tcp nowait nobody  /usr/bin/git-daemon
-		git-daemon --inetd --verbose --export-all
+	git stream tcp nowait nobody  /usr/bin/git
+		git daemon --inetd --verbose --export-all
 		/pub/foo /pub/bar
 ------------------------------------------------
 
 
-git-daemon as inetd server for virtual hosts::
-	To set up `git-daemon` as an inetd service that handles
+'git-daemon' as inetd server for virtual hosts::
+	To set up 'git-daemon' as an inetd service that handles
 	repositories for different virtual hosts, `www.example.com`
 	and `www.example.org`, place an entry like the following into
 	`/etc/inetd` all on one line:
 +
 ------------------------------------------------
-	git stream tcp nowait nobody /usr/bin/git-daemon
-		git-daemon --inetd --verbose --export-all
+	git stream tcp nowait nobody /usr/bin/git
+		git daemon --inetd --verbose --export-all
 		--interpolated-path=/pub/%H%D
 		/pub/www.example.org/software
 		/pub/www.example.com/software
@@ -235,13 +235,13 @@
 default repository could be made as well.
 
 
-git-daemon as regular daemon for virtual hosts::
-	To set up `git-daemon` as a regular, non-inetd service that
+'git-daemon' as regular daemon for virtual hosts::
+	To set up 'git-daemon' as a regular, non-inetd service that
 	handles repositories for multiple virtual hosts based on
 	their IP addresses, start the daemon like this:
 +
 ------------------------------------------------
-	git-daemon --verbose --export-all
+	git daemon --verbose --export-all
 		--interpolated-path=/pub/%IP/%D
 		/pub/192.168.1.200/software
 		/pub/10.10.220.23/software
@@ -253,7 +253,7 @@
 they correspond to these IP addresses.
 
 selectively enable/disable services per repository::
-	To enable `git-archive --remote` and disable `git-fetch` against
+	To enable 'git-archive --remote' and disable 'git-fetch' against
 	a repository, have the following in the configuration file in the
 	repository (that is the file 'config' next to 'HEAD', 'refs' and
 	'objects').
diff --git a/Documentation/git-describe.txt b/Documentation/git-describe.txt
index 44aaa40..c4dbc2a 100644
--- a/Documentation/git-describe.txt
+++ b/Documentation/git-describe.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-describe' [--all] [--tags] [--contains] [--abbrev=<n>] <committish>...
+'git describe' [--all] [--tags] [--contains] [--abbrev=<n>] <committish>...
 
 DESCRIPTION
 -----------
@@ -21,8 +21,8 @@
 
 OPTIONS
 -------
-<committish>::
-	The object name of the committish.
+<committish>...::
+	Committish object names to describe.
 
 --all::
 	Instead of using only the annotated tags, use any ref
@@ -78,7 +78,7 @@
 
 With something like git.git current tree, I get:
 
-	[torvalds@g5 git]$ git-describe parent
+	[torvalds@g5 git]$ git describe parent
 	v1.0.4-14-g2414721
 
 i.e. the current head of my "parent" branch is based on v1.0.4,
@@ -92,9 +92,9 @@
 The hash suffix is "-g" + 7-char abbreviation for the tip commit
 of parent (which was `2414721b194453f058079d897d13c4e377f92dc6`).
 
-Doing a "git-describe" on a tag-name will just show the tag name:
+Doing a 'git-describe' on a tag-name will just show the tag name:
 
-	[torvalds@g5 git]$ git-describe v1.0.4
+	[torvalds@g5 git]$ git describe v1.0.4
 	v1.0.4
 
 With --all, the command can use branch heads as references, so
@@ -115,13 +115,13 @@
 SEARCH STRATEGY
 ---------------
 
-For each committish supplied "git describe" will first look for
+For each committish supplied, 'git-describe' will first look for
 a tag which tags exactly that commit.  Annotated tags will always
 be preferred over lightweight tags, and tags with newer dates will
 always be preferred over tags with older dates.  If an exact match
 is found, its name will be output and searching will stop.
 
-If an exact match was not found "git describe" will walk back
+If an exact match was not found, 'git-describe' will walk back
 through the commit history to locate an ancestor commit which
 has been tagged.  The ancestor's tag will be output along with an
 abbreviation of the input committish's SHA1.
@@ -129,7 +129,7 @@
 If multiple tags were found during the walk then the tag which
 has the fewest commits different from the input committish will be
 selected and output.  Here fewest commits different is defined as
-the number of commits which would be shown by "git log tag..input"
+the number of commits which would be shown by `git log tag..input`
 will be the smallest number of commits possible.
 
 
diff --git a/Documentation/git-diff-files.txt b/Documentation/git-diff-files.txt
index 8a64869..5c8c1d9 100644
--- a/Documentation/git-diff-files.txt
+++ b/Documentation/git-diff-files.txt
@@ -8,14 +8,14 @@
 
 SYNOPSIS
 --------
-'git-diff-files' [-q] [-0|-1|-2|-3|-c|--cc] [<common diff options>] [<path>...]
+'git diff-files' [-q] [-0|-1|-2|-3|-c|--cc] [<common diff options>] [<path>...]
 
 DESCRIPTION
 -----------
 Compares the files in the working tree and the index.  When paths
 are specified, compares only those named paths.  Otherwise all
 entries in the index are compared.  The output format is the
-same as "git-diff-index" and "git-diff-tree".
+same as for 'git-diff-index' and 'git-diff-tree'.
 
 OPTIONS
 -------
diff --git a/Documentation/git-diff-index.txt b/Documentation/git-diff-index.txt
index f6e844f..26920d4 100644
--- a/Documentation/git-diff-index.txt
+++ b/Documentation/git-diff-index.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-diff-index' [-m] [--cached] [<common diff options>] <tree-ish> [<path>...]
+'git diff-index' [-m] [--cached] [<common diff options>] <tree-ish> [<path>...]
 
 DESCRIPTION
 -----------
@@ -31,7 +31,7 @@
 -m::
 	By default, files recorded in the index but not checked
 	out are reported as deleted.  This flag makes
-	"git-diff-index" say that all non-checked-out files are up
+	'git-diff-index' say that all non-checked-out files are up
 	to date.
 
 Output format
@@ -50,31 +50,31 @@
 If '--cached' is specified, it allows you to ask:
 
 	show me the differences between HEAD and the current index
-	contents (the ones I'd write with a "git-write-tree")
+	contents (the ones I'd write using 'git-write-tree')
 
 For example, let's say that you have worked on your working directory, updated
 some files in the index and are ready to commit. You want to see exactly
 *what* you are going to commit, without having to write a new tree
 object and compare it that way, and to do that, you just do
 
-	git-diff-index --cached HEAD
+	git diff-index --cached HEAD
 
 Example: let's say I had renamed `commit.c` to `git-commit.c`, and I had
-done an "git-update-index" to make that effective in the index file.
-"git-diff-files" wouldn't show anything at all, since the index file
-matches my working directory. But doing a "git-diff-index" does:
+done an `update-index` to make that effective in the index file.
+`git diff-files` wouldn't show anything at all, since the index file
+matches my working directory. But doing a 'git-diff-index' does:
 
-  torvalds@ppc970:~/git> git-diff-index --cached HEAD
+  torvalds@ppc970:~/git> git diff-index --cached HEAD
   -100644 blob    4161aecc6700a2eb579e842af0b7f22b98443f74        commit.c
   +100644 blob    4161aecc6700a2eb579e842af0b7f22b98443f74        git-commit.c
 
 You can see easily that the above is a rename.
 
-In fact, "git-diff-index --cached" *should* always be entirely equivalent to
-actually doing a "git-write-tree" and comparing that. Except this one is much
+In fact, `git diff-index --cached` *should* always be entirely equivalent to
+actually doing a 'git-write-tree' and comparing that. Except this one is much
 nicer for the case where you just want to check where you are.
 
-So doing a "git-diff-index --cached" is basically very useful when you are
+So doing a 'git-diff-index --cached' is basically very useful when you are
 asking yourself "what have I already marked for being committed, and
 what's the difference to a previous tree".
 
@@ -82,23 +82,23 @@
 ---------------
 The "non-cached" mode takes a different approach, and is potentially
 the more useful of the two in that what it does can't be emulated with
-a "git-write-tree" + "git-diff-tree". Thus that's the default mode.
+a 'git-write-tree' + 'git-diff-tree'. Thus that's the default mode.
 The non-cached version asks the question:
 
   show me the differences between HEAD and the currently checked out
   tree - index contents _and_ files that aren't up-to-date
 
 which is obviously a very useful question too, since that tells you what
-you *could* commit. Again, the output matches the "git-diff-tree -r"
+you *could* commit. Again, the output matches the 'git-diff-tree -r'
 output to a tee, but with a twist.
 
 The twist is that if some file doesn't match the index, we don't have
 a backing store thing for it, and we use the magic "all-zero" sha1 to
 show that. So let's say that you have edited `kernel/sched.c`, but
-have not actually done a "git-update-index" on it yet - there is no
+have not actually done a 'git-update-index' on it yet - there is no
 "object" associated with the new state, and you get:
 
-  torvalds@ppc970:~/v2.6/linux> git-diff-index HEAD
+  torvalds@ppc970:~/v2.6/linux> git diff-index HEAD
   *100644->100664 blob    7476bb......->000000......      kernel/sched.c
 
 i.e., it shows that the tree has changed, and that `kernel/sched.c` has is
@@ -106,11 +106,11 @@
 get the real diff, you need to look at the object in the working directory
 directly rather than do an object-to-object diff.
 
-NOTE: As with other commands of this type, "git-diff-index" does not
+NOTE: As with other commands of this type, 'git-diff-index' does not
 actually look at the contents of the file at all. So maybe
 `kernel/sched.c` hasn't actually changed, and it's just that you
 touched it. In either case, it's a note that you need to
-"git-update-index" it to make the index be in sync.
+'git-update-index' it to make the index be in sync.
 
 NOTE: You can have a mixture of files show up as "has been updated"
 and "is still dirty in the working directory" together. You can always
diff --git a/Documentation/git-diff-tree.txt b/Documentation/git-diff-tree.txt
index 5d23985..4e83067 100644
--- a/Documentation/git-diff-tree.txt
+++ b/Documentation/git-diff-tree.txt
@@ -9,7 +9,7 @@
 SYNOPSIS
 --------
 [verse]
-'git-diff-tree' [--stdin] [-m] [-s] [-v] [--no-commit-id] [--pretty]
+'git diff-tree' [--stdin] [-m] [-s] [-v] [--no-commit-id] [--pretty]
 	      [-t] [-r] [-c | --cc] [--root] [<common diff options>]
 	      <tree-ish> [<tree-ish>] [<path>...]
 
@@ -20,7 +20,7 @@
 If there is only one <tree-ish> given, the commit is compared with its parents
 (see --stdin below).
 
-Note that "git-diff-tree" can use the tree encapsulated in a commit object.
+Note that 'git-diff-tree' can use the tree encapsulated in a commit object.
 
 OPTIONS
 -------
@@ -43,7 +43,7 @@
 	show tree entry itself as well as subtrees.  Implies -r.
 
 --root::
-	When '--root' is specified the initial commit will be showed as a big
+	When '--root' is specified the initial commit will be shown as a big
 	creation event. This is equivalent to a diff against the NULL tree.
 
 --stdin::
@@ -58,25 +58,25 @@
 parents of the first commit.
 
 -m::
-	By default, "git-diff-tree --stdin" does not show
+	By default, 'git-diff-tree --stdin' does not show
 	differences for merge commits.  With this flag, it shows
 	differences to that commit from all of its parents. See
 	also '-c'.
 
 -s::
-	By default, "git-diff-tree --stdin" shows differences,
+	By default, 'git-diff-tree --stdin' shows differences,
 	either in machine-readable form (without '-p') or in patch
 	form (with '-p').  This output can be suppressed.  It is
 	only useful with '-v' flag.
 
 -v::
-	This flag causes "git-diff-tree --stdin" to also show
+	This flag causes 'git-diff-tree --stdin' to also show
 	the commit message before the differences.
 
 include::pretty-options.txt[]
 
 --no-commit-id::
-	git-diff-tree outputs a line with the commit ID when
+	'git-diff-tree' outputs a line with the commit ID when
 	applicable.  This flag suppressed the commit ID output.
 
 -c::
@@ -112,13 +112,13 @@
 If you're only interested in differences in a subset of files, for
 example some architecture-specific files, you might do:
 
-	git-diff-tree -r <tree-ish> <tree-ish> arch/ia64 include/asm-ia64
+	git diff-tree -r <tree-ish> <tree-ish> arch/ia64 include/asm-ia64
 
 and it will only show you what changed in those two directories.
 
 Or if you are searching for what changed in just `kernel/sched.c`, just do
 
-	git-diff-tree -r <tree-ish> <tree-ish> kernel/sched.c
+	git diff-tree -r <tree-ish> <tree-ish> kernel/sched.c
 
 and it will ignore all differences to other files.
 
@@ -129,7 +129,7 @@
 
 An example of normal usage is:
 
-  torvalds@ppc970:~/git> git-diff-tree 5319e4......
+  torvalds@ppc970:~/git> git diff-tree 5319e4......
   *100664->100664 blob    ac348b.......->a01513.......      git-fsck-objects.c
 
 which tells you that the last commit changed just one file (it's from
diff --git a/Documentation/git-diff.txt b/Documentation/git-diff.txt
index 7acd428..c53eba5 100644
--- a/Documentation/git-diff.txt
+++ b/Documentation/git-diff.txt
@@ -8,14 +8,14 @@
 
 SYNOPSIS
 --------
-'git-diff' [<common diff options>] <commit>{0,2} [--] [<path>...]
+'git diff' [<common diff options>] <commit>{0,2} [--] [<path>...]
 
 DESCRIPTION
 -----------
 Show changes between two trees, a tree and the working tree, a
 tree and the index file, or the index file and the working tree.
 
-'git-diff' [--options] [--] [<path>...]::
+'git diff' [--options] [--] [<path>...]::
 
 	This form is to view the changes you made relative to
 	the index (staging area for the next commit).  In other
@@ -27,14 +27,14 @@
 compare the two files / directories. This behavior can be
 forced by --no-index.
 
-'git-diff' [--options] --cached [<commit>] [--] [<path>...]::
+'git diff' [--options] --cached [<commit>] [--] [<path>...]::
 
 	This form is to view the changes you staged for the next
 	commit relative to the named <commit>.  Typically you
 	would want comparison with the latest commit, so if you
 	do not give <commit>, it defaults to HEAD.
 
-'git-diff' [--options] <commit> [--] [<path>...]::
+'git diff' [--options] <commit> [--] [<path>...]::
 
 	This form is to view the changes you have in your
 	working tree relative to the named <commit>.  You can
@@ -42,23 +42,23 @@
 	branch name to compare with the tip of a different
 	branch.
 
-'git-diff' [--options] <commit> <commit> [--] [<path>...]::
+'git diff' [--options] <commit> <commit> [--] [<path>...]::
 
 	This is to view the changes between two arbitrary
 	<commit>.
 
-'git-diff' [--options] <commit>..<commit> [--] [<path>...]::
+'git diff' [--options] <commit>..<commit> [--] [<path>...]::
 
 	This is synonymous to the previous form.  If <commit> on
 	one side is omitted, it will have the same effect as
 	using HEAD instead.
 
-'git-diff' [--options] <commit>\...<commit> [--] [<path>...]::
+'git diff' [--options] <commit>\...<commit> [--] [<path>...]::
 
 	This form is to view the changes on the branch containing
 	and up to the second <commit>, starting at a common ancestor
-	of both <commit>.  "git-diff A\...B" is equivalent to
-	"git-diff $(git-merge-base A B) B".  You can omit any one
+	of both <commit>.  "git diff A\...B" is equivalent to
+	"git diff $(git-merge-base A B) B".  You can omit any one
 	of <commit>, which has the same effect as using HEAD instead.
 
 Just in case if you are doing something exotic, it should be
diff --git a/Documentation/git-fast-export.txt b/Documentation/git-fast-export.txt
index 332346c..539decb 100644
--- a/Documentation/git-fast-export.txt
+++ b/Documentation/git-fast-export.txt
@@ -8,23 +8,23 @@
 
 SYNOPSIS
 --------
-'git-fast-export [options]' | 'git-fast-import'
+'git fast-export [options]' | 'git fast-import'
 
 DESCRIPTION
 -----------
 This program dumps the given revisions in a form suitable to be piped
-into linkgit:git-fast-import[1].
+into 'git-fast-import'.
 
 You can use it as a human readable bundle replacement (see
 linkgit:git-bundle[1]), or as a kind of an interactive
-linkgit:git-filter-branch[1].
+'git-filter-branch'.
 
 
 OPTIONS
 -------
 --progress=<n>::
 	Insert 'progress' statements every <n> objects, to be shown by
-	linkgit:git-fast-import[1] during import.
+	'git-fast-import' during import.
 
 --signed-tags=(verbatim|warn|strip|abort)::
 	Specify how to handle signed tags.  Since any transformation
@@ -36,6 +36,41 @@
 unsigned, with 'verbatim', they will be silently exported
 and with 'warn', they will be exported, but you will see a warning.
 
+-M::
+-C::
+	Perform move and/or copy detection, as described in the
+	linkgit:git-diff[1] manual page, and use it to generate
+	rename and copy commands in the output dump.
++
+Note that earlier versions of this command did not complain and
+produced incorrect results if you gave these options.
+
+--export-marks=<file>::
+	Dumps the internal marks table to <file> when complete.
+	Marks are written one per line as `:markid SHA-1`. Only marks
+	for revisions are dumped; marks for blobs are ignored.
+	Backends can use this file to validate imports after they
+	have been completed, or to save the marks table across
+	incremental runs.  As <file> is only opened and truncated
+	at completion, the same path can also be safely given to
+	\--import-marks.
+
+--import-marks=<file>::
+	Before processing any input, load the marks specified in
+	<file>.  The input file must exist, must be readable, and
+	must use the same format as produced by \--export-marks.
++
+Any commits that have already been marked will not be exported again.
+If the backend uses a similar \--import-marks file, this allows for
+incremental bidirectional exporting of the repository by keeping the
+marks the same across runs.
+
+--fake-missing-tagger::
+	Some old repositories have tags without a tagger.  The
+	fast-import protocol was pretty strict about that, and did not
+	allow that.  So fake a tagger to be able to fast-import the
+	output.
+
 
 EXAMPLES
 --------
@@ -65,7 +100,7 @@
 Limitations
 -----------
 
-Since linkgit:git-fast-import[1] cannot tag trees, you will not be
+Since 'git-fast-import' cannot tag trees, you will not be
 able to export the linux-2.6.git repository completely, as it contains
 a tag referencing a tree instead of a commit.
 
diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt
index 395c055..c2f483a 100644
--- a/Documentation/git-fast-import.txt
+++ b/Documentation/git-fast-import.txt
@@ -8,14 +8,14 @@
 
 SYNOPSIS
 --------
-frontend | 'git-fast-import' [options]
+frontend | 'git fast-import' [options]
 
 DESCRIPTION
 -----------
 This program is usually not what the end user wants to run directly.
 Most end users want to use one of the existing frontend programs,
 which parses a specific type of foreign source and feeds the contents
-stored there to git-fast-import.
+stored there to 'git-fast-import'.
 
 fast-import reads a mixed command/data stream from standard input and
 writes one or more packfiles directly into the current repository.
@@ -24,7 +24,7 @@
 with the newly imported data.
 
 The fast-import backend itself can import into an empty repository (one that
-has already been initialized by linkgit:git-init[1]) or incrementally
+has already been initialized by 'git-init') or incrementally
 update an existing populated repository.  Whether or not incremental
 imports are supported from a particular foreign source depends on
 the frontend program in use.
@@ -82,11 +82,11 @@
 	This information may be useful after importing projects
 	whose total object set exceeds the 4 GiB packfile limit,
 	as these commits can be used as edge points during calls
-	to linkgit:git-pack-objects[1].
+	to 'git-pack-objects'.
 
 --quiet::
 	Disable all non-fatal output, making fast-import silent when it
-	is successful.	This option disables the output shown by
+	is successful.  This option disables the output shown by
 	\--stats.
 
 --stats::
@@ -124,9 +124,9 @@
 
 Parallel Operation
 ------------------
-Like `git-push` or `git-fetch`, imports handled by fast-import are safe to
+Like 'git-push' or 'git-fetch', imports handled by fast-import are safe to
 run alongside parallel `git repack -a -d` or `git gc` invocations,
-or any other Git operation (including `git prune`, as loose objects
+or any other Git operation (including 'git-prune', as loose objects
 are never used by fast-import).
 
 fast-import does not lock the branch or tag refs it is actively importing.
@@ -220,7 +220,7 @@
 +
 An example value is ``Tue Feb 6 11:22:18 2007 -0500''.  The Git
 parser is accurate, but a little on the lenient side.  It is the
-same parser used by linkgit:git-am[1] when applying patches
+same parser used by 'git-am' when applying patches
 received from email.
 +
 Some malformed strings may be accepted as valid dates.  In some of
@@ -256,7 +256,7 @@
 This particular format is supplied as its short to implement and
 may be useful to a process that wants to create a new commit
 right now, without needing to use a working directory or
-linkgit:git-update-index[1].
+'git-update-index'.
 +
 If separate `author` and `committer` commands are used in a `commit`
 the timestamps may not match, as the system clock will be polled
@@ -481,6 +481,9 @@
   what you want.
 * `100755` or `755`: A normal, but executable, file.
 * `120000`: A symlink, the content of the file will be the link target.
+* `160000`: A gitlink, SHA-1 of the object refers to a commit in
+  another repository. Git links can only be specified by SHA or through
+  a commit mark. They are used to implement submodules.
 
 In both formats `<path>` is the complete path of the file to be added
 (if not already existing) or modified (if already existing).
@@ -654,7 +657,7 @@
 complete set of bytes which normally goes into such a signature.
 If signing is required, create lightweight tags from within fast-import with
 `reset`, then create the annotated versions of those tags offline
-with the standard linkgit:git-tag[1] process.
+with the standard 'git-tag' process.
 
 `reset`
 ~~~~~~~
@@ -803,7 +806,7 @@
 remove the leading part of the line, for example:
 
 ====
-	frontend | git-fast-import | sed 's/^progress //'
+	frontend | git fast-import | sed 's/^progress //'
 ====
 
 Placing a `progress` command immediately after a `checkpoint` will
@@ -851,7 +854,7 @@
 	M 777 inline bob
 	END_OF_INPUT
 
-	$ git-fast-import <in
+	$ git fast-import <in
 	fatal: Corrupt mode: M 777 inline bob
 	fast-import: dumping crash report to .git/fast_import_crash_8434
 
@@ -955,7 +958,7 @@
 
 When committing fixups, consider using `merge` to connect the
 commit(s) which are supplying file revisions to the fixup branch.
-Doing so will allow tools such as linkgit:git-blame[1] to track
+Doing so will allow tools such as 'git-blame' to track
 through the real commit history and properly annotate the source
 files.
 
@@ -984,7 +987,7 @@
 ~~~~~~~~~~~~~~~~~~~~~~~~~
 If you are repacking very old imported data (e.g. older than the
 last year), consider expending some extra CPU time and supplying
-\--window=50 (or higher) when you run linkgit:git-repack[1].
+\--window=50 (or higher) when you run 'git-repack'.
 This will take longer, but will also produce a smaller packfile.
 You only need to expend the effort once, and everyone using your
 project will benefit from the smaller repository.
diff --git a/Documentation/git-fetch-pack.txt b/Documentation/git-fetch-pack.txt
index 282fcaf..47448da 100644
--- a/Documentation/git-fetch-pack.txt
+++ b/Documentation/git-fetch-pack.txt
@@ -8,14 +8,14 @@
 
 SYNOPSIS
 --------
-'git-fetch-pack' [--all] [--quiet|-q] [--keep|-k] [--thin] [--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] [--no-progress] [-v] [<host>:]<directory> [<refs>...]
+'git fetch-pack' [--all] [--quiet|-q] [--keep|-k] [--thin] [--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] [--no-progress] [-v] [<host>:]<directory> [<refs>...]
 
 DESCRIPTION
 -----------
-Usually you would want to use linkgit:git-fetch[1] which is a
-higher level wrapper of this command instead.
+Usually you would want to use 'git-fetch', which is a
+higher level wrapper of this command, instead.
 
-Invokes 'git-upload-pack' on a potentially remote repository,
+Invokes 'git-upload-pack' on a possibly remote repository
 and asks it to send objects missing from this repository, to
 update the named heads.  The list of commits available locally
 is found out by scanning local $GIT_DIR/refs/ and sent to
diff --git a/Documentation/git-fetch.txt b/Documentation/git-fetch.txt
index 4fae7fb..d3164c5 100644
--- a/Documentation/git-fetch.txt
+++ b/Documentation/git-fetch.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-fetch' <options> <repository> <refspec>...
+'git fetch' <options> <repository> <refspec>...
 
 
 DESCRIPTION
@@ -18,7 +18,7 @@
 
 The ref names and their object names of fetched refs are stored
 in `.git/FETCH_HEAD`.  This information is left for a later merge
-operation done by "git merge".
+operation done by 'git-merge'.
 
 When <refspec> stores the fetched result in tracking branches,
 the tags that point at these branches are automatically
diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt
index ea77f1f..b0e710d 100644
--- a/Documentation/git-filter-branch.txt
+++ b/Documentation/git-filter-branch.txt
@@ -8,12 +8,12 @@
 SYNOPSIS
 --------
 [verse]
-'git-filter-branch' [--env-filter <command>] [--tree-filter <command>]
+'git filter-branch' [--env-filter <command>] [--tree-filter <command>]
 	[--index-filter <command>] [--parent-filter <command>]
 	[--msg-filter <command>] [--commit-filter <command>]
 	[--tag-name-filter <command>] [--subdirectory-filter <directory>]
 	[--original <namespace>] [-d <directory>] [-f | --force]
-	[<rev-list options>...]
+	[--] [<rev-list options>...]
 
 DESCRIPTION
 -----------
@@ -95,7 +95,7 @@
 	This is the filter for rewriting the commit's parent list.
 	It will receive the parent string on stdin and shall output
 	the new parent string on stdout.  The parent string is in
-	a format accepted by linkgit:git-commit-tree[1]: empty for
+	the format described in linkgit:git-commit-tree[1]: empty for
 	the initial commit, "-p parent" for a normal commit and
 	"-p parent1 -p parent2 -p parent3 ..." for a merge commit.
 
@@ -108,7 +108,7 @@
 --commit-filter <command>::
 	This is the filter for performing the commit.
 	If this filter is specified, it will be called instead of the
-	linkgit:git-commit-tree[1] command, with arguments of the form
+	'git-commit-tree' command, with arguments of the form
 	"<TREE_ID> [-p <PARENT_COMMIT_ID>]..." and the log message on
 	stdin.  The commit id is expected on stdout.
 +
@@ -119,7 +119,7 @@
 You can use the 'map' convenience function in this filter, and other
 convenience functions, too.  For example, calling 'skip_commit "$@"'
 will leave out the current commit (but not its changes! If you want
-that, use linkgit:git-rebase[1] instead).
+that, use 'git-rebase' instead).
 
 --tag-name-filter <command>::
 	This is the filter for rewriting tag names. When passed,
@@ -163,15 +163,15 @@
 
 -f::
 --force::
-	`git filter-branch` refuses to start with an existing temporary
+	'git-filter-branch' refuses to start with an existing temporary
 	directory or when there are already refs starting with
 	'refs/original/', unless forced.
 
-<rev-list-options>::
-	When options are given after the new branch name, they will
-	be passed to linkgit:git-rev-list[1].  Only commits in the resulting
-	output will be filtered, although the filtered commits can still
-	reference parents which are outside of that set.
+<rev-list options>...::
+	Arguments for 'git-rev-list'.  All positive refs included by
+	these options are rewritten.  You may also specify options
+	such as '--all', but you must use '--' to separate them from
+	the 'git-filter-branch' options.
 
 
 Examples
@@ -191,11 +191,22 @@
 A significantly faster version:
 
 --------------------------------------------------------------------------
-git filter-branch --index-filter 'git update-index --remove filename' HEAD
+git filter-branch --index-filter 'git rm --cached filename' HEAD
 --------------------------------------------------------------------------
 
 Now, you will get the rewritten history saved in HEAD.
 
+To rewrite the repository to look as if `foodir/` had been its project
+root, and discard all other history:
+
+-------------------------------------------------------
+git filter-branch --subdirectory-filter foodir -- --all
+-------------------------------------------------------
+
+Thus you can, e.g., turn a library subdirectory into a repository of
+its own.  Note the `\--` that separates 'filter-branch' options from
+revision options, and the `\--all` to rewrite all branches and tags.
+
 To set a commit (which typically is at the tip of another
 history) to be the parent of the current initial commit, in
 order to paste the other history behind the current history:
@@ -255,7 +266,7 @@
 as their parents instead of the merge commit.
 
 You can rewrite the commit log messages using `--msg-filter`.  For
-example, `git-svn-id` strings in a repository created by `git-svn` can
+example, 'git-svn-id' strings in a repository created by 'git-svn' can
 be removed this way:
 
 -------------------------------------------------------
@@ -266,13 +277,13 @@
 
 To restrict rewriting to only part of the history, specify a revision
 range in addition to the new branch name.  The new branch name will
-point to the top-most revision that a 'git rev-list' of this range
+point to the top-most revision that a 'git-rev-list' of this range
 will print.
 
 *NOTE* the changes introduced by the commits, and which are not reverted
 by subsequent commits, will still be in the rewritten branch. If you want
 to throw out _changes_ together with the commits, you should use the
-interactive mode of linkgit:git-rebase[1].
+interactive mode of 'git-rebase'.
 
 
 Consider this history:
diff --git a/Documentation/git-fmt-merge-msg.txt b/Documentation/git-fmt-merge-msg.txt
index 222052f..1c24796 100644
--- a/Documentation/git-fmt-merge-msg.txt
+++ b/Documentation/git-fmt-merge-msg.txt
@@ -9,17 +9,17 @@
 SYNOPSIS
 --------
 [verse]
-git-fmt-merge-msg [--log | --no-log] <$GIT_DIR/FETCH_HEAD
-git-fmt-merge-msg [--log | --no-log] -F <file>
+'git fmt-merge-msg' [--log | --no-log] <$GIT_DIR/FETCH_HEAD
+'git fmt-merge-msg' [--log | --no-log] -F <file>
 
 DESCRIPTION
 -----------
 Takes the list of merged objects on stdin and produces a suitable
 commit message to be used for the merge commit, usually to be
-passed as the '<merge-message>' argument of `git-merge`.
+passed as the '<merge-message>' argument of 'git-merge'.
 
 This script is intended mostly for internal use by scripts
-automatically invoking `git-merge`.
+automatically invoking 'git-merge'.
 
 OPTIONS
 -------
diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt
index b347bfb..ebd7c5f 100644
--- a/Documentation/git-for-each-ref.txt
+++ b/Documentation/git-for-each-ref.txt
@@ -8,7 +8,7 @@
 SYNOPSIS
 --------
 [verse]
-'git-for-each-ref' [--count=<count>] [--shell|--perl|--python|--tcl]
+'git for-each-ref' [--count=<count>] [--shell|--perl|--python|--tcl]
 		   [--sort=<key>]\* [--format=<format>] [<pattern>...]
 
 DESCRIPTION
@@ -16,7 +16,7 @@
 
 Iterate over all refs that match `<pattern>` and show them
 according to the given `<format>`, after sorting them according
-to the given set of `<key>`.  If `<max>` is given, stop after
+to the given set of `<key>`.  If `<count>` is given, stop after
 showing that many refs.  The interpolated values in `<format>`
 can optionally be quoted as string literals in the specified
 host language allowing their direct evaluation in that language.
@@ -47,9 +47,9 @@
 	`xx`; for example `%00` interpolates to `\0` (NUL),
 	`%09` to `\t` (TAB) and `%0a` to `\n` (LF).
 
-<pattern>::
+<pattern>...::
 	If one or more patterns are given, only refs are shown that
-	match againt at least one pattern, either using fnmatch(3) or
+	match against at least one pattern, either using fnmatch(3) or
 	literally, in the latter case matching completely or from the
 	beginning up to a slash.
 
@@ -79,7 +79,7 @@
 	The type of the object (`blob`, `tree`, `commit`, `tag`).
 
 objectsize::
-	The size of the object (the same as `git-cat-file -s` reports).
+	The size of the object (the same as 'git-cat-file -s' reports).
 
 objectname::
 	The object name (aka SHA-1).
@@ -119,7 +119,7 @@
 ------------
 #!/bin/sh
 
-git-for-each-ref --count=3 --sort='-*authordate' \
+git for-each-ref --count=3 --sort='-*authordate' \
 --format='From: %(*authorname) %(*authoremail)
 Subject: %(*subject)
 Date: %(*authordate)
@@ -135,7 +135,7 @@
 ------------
 #!/bin/sh
 
-git-for-each-ref --shell --format="ref=%(refname)" refs/heads | \
+git for-each-ref --shell --format="ref=%(refname)" refs/heads | \
 while read entry
 do
 	eval "$entry"
@@ -189,7 +189,7 @@
 	fi
 '
 
-eval=`git-for-each-ref --shell --format="$fmt" \
+eval=`git for-each-ref --shell --format="$fmt" \
 	--sort='*objecttype' \
 	--sort=-taggerdate \
 	refs/tags`
diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt
index ee27eff..7426109 100644
--- a/Documentation/git-format-patch.txt
+++ b/Documentation/git-format-patch.txt
@@ -9,7 +9,7 @@
 SYNOPSIS
 --------
 [verse]
-'git-format-patch' [-k] [-o <dir> | --stdout] [--thread]
+'git format-patch' [-k] [-o <dir> | --stdout] [--thread]
 		   [--attach[=<boundary>] | --inline[=<boundary>]]
 		   [-s | --signoff] [<common diff options>]
 		   [-n | --numbered | -N | --no-numbered]
@@ -27,7 +27,7 @@
 Prepare each commit with its patch in
 one file per commit, formatted to resemble UNIX mailbox format.
 The output of this command is convenient for e-mail submission or
-for use with linkgit:git-am[1].
+for use with 'git-am'.
 
 There are two ways to specify which commits to operate on.
 
@@ -46,7 +46,8 @@
 since the beginning of the time".  If you want to format
 everything since project inception to one commit, say "git
 format-patch \--root <commit>" to make it clear that it is the
-latter case.
+latter case.  If you want to format a single commit, you can do
+this with "git format-patch -1 <commit>".
 
 By default, each output file is numbered sequentially from 1, and uses the
 first line of the commit message (massaged for pathname safety) as
@@ -61,7 +62,7 @@
 If -n is specified, instead of "[PATCH] Subject", the first line
 is formatted as "[PATCH n/m] Subject".
 
-If given --thread, git-format-patch will generate In-Reply-To and
+If given --thread, 'git-format-patch' will generate In-Reply-To and
 References headers to make the second and subsequent patch mails appear
 as replies to the first mail; this also generates a Message-Id header to
 reference.
@@ -147,9 +148,9 @@
 	to any configured headers, and may be used multiple times.
 
 --cover-letter::
-	Generate a cover letter template.  You still have to fill in
-	a description, but the shortlog and the diffstat will be
-	generated for you.
+	In addition to the patches, generate a cover letter file
+	containing the shortlog and the overall diffstat.  You can
+	fill in a description in the file before sending it out.
 
 --suffix=.<sfx>::
 	Instead of using `.patch` as the suffix for generated
@@ -175,10 +176,10 @@
 
 ------------
 [format]
-        headers = "Organization: git-foo\n"
-        subjectprefix = CHANGE
-        suffix = .txt
-        numbered = auto
+	headers = "Organization: git-foo\n"
+	subjectprefix = CHANGE
+	suffix = .txt
+	numbered = auto
 	cc = <email>
 ------------
 
@@ -187,10 +188,10 @@
 --------
 
 * Extract commits between revisions R1 and R2, and apply them on top of
-the current branch using `git-am` to cherry-pick them:
+the current branch using 'git-am' to cherry-pick them:
 +
 ------------
-$ git format-patch -k --stdout R1..R2 | git-am -3 -k
+$ git format-patch -k --stdout R1..R2 | git am -3 -k
 ------------
 
 * Extract all commits which are in the current branch but not in the
@@ -206,7 +207,7 @@
 project:
 +
 ------------
-$ git format-patch \--root origin
+$ git format-patch --root origin
 ------------
 
 * The same as the previous one:
diff --git a/Documentation/git-fsck-objects.txt b/Documentation/git-fsck-objects.txt
index 6e9f717..965a827 100644
--- a/Documentation/git-fsck-objects.txt
+++ b/Documentation/git-fsck-objects.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-fsck-objects' ...
+'git fsck-objects' ...
 
 DESCRIPTION
 -----------
diff --git a/Documentation/git-fsck.txt b/Documentation/git-fsck.txt
index 9846c85..d5a7647 100644
--- a/Documentation/git-fsck.txt
+++ b/Documentation/git-fsck.txt
@@ -9,7 +9,7 @@
 SYNOPSIS
 --------
 [verse]
-'git-fsck' [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]
+'git fsck' [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]
 	 [--full] [--strict] [--verbose] [--lost-found] [<object>*]
 
 DESCRIPTION
@@ -21,7 +21,7 @@
 <object>::
 	An object to treat as the head of an unreachability trace.
 +
-If no objects are given, git-fsck defaults to using the
+If no objects are given, 'git-fsck' defaults to using the
 index file, all SHA1 references in .git/refs/*, and all reflogs (unless
 --no-reflogs is given) as heads.
 
@@ -79,15 +79,15 @@
 
 So for example
 
-	git-fsck --unreachable HEAD $(cat .git/refs/heads/*)
+	git fsck --unreachable HEAD $(cat .git/refs/heads/*)
 
 will do quite a _lot_ of verification on the tree. There are a few
 extra validity tests to be added (make sure that tree objects are
-sorted properly etc), but on the whole if "git-fsck" is happy, you
+sorted properly etc), but on the whole if 'git-fsck' is happy, you
 do have a valid tree.
 
 Any corrupt objects you will have to find in backups or other archives
-(i.e., you can just remove them and do an "rsync" with some other site in
+(i.e., you can just remove them and do an 'rsync' with some other site in
 the hopes that somebody else has the object you have corrupted).
 
 Of course, "valid tree" doesn't mean that it wasn't generated by some
diff --git a/Documentation/git-gc.txt b/Documentation/git-gc.txt
index 6ace615..7086eea 100644
--- a/Documentation/git-gc.txt
+++ b/Documentation/git-gc.txt
@@ -8,20 +8,20 @@
 
 SYNOPSIS
 --------
-'git-gc' [--aggressive] [--auto] [--quiet]
+'git gc' [--aggressive] [--auto] [--quiet]
 
 DESCRIPTION
 -----------
 Runs a number of housekeeping tasks within the current repository,
 such as compressing file revisions (to reduce disk space and increase
 performance) and removing unreachable objects which may have been
-created from prior invocations of linkgit:git-add[1].
+created from prior invocations of 'git-add'.
 
 Users are encouraged to run this task on a regular basis within
 each repository to maintain good disk space utilization and good
 operating performance.
 
-Some git commands may automatically run `git-gc`; see the `--auto` flag
+Some git commands may automatically run 'git-gc'; see the `--auto` flag
 below for details. If you know what you're doing and all you want is to
 disable this behavior permanently without further considerations, just do:
 
@@ -35,13 +35,13 @@
 --aggressive::
 	Usually 'git-gc' runs very quickly while providing good disk
 	space utilization and performance.  This option will cause
-	git-gc to more aggressively optimize the repository at the expense
+	'git-gc' to more aggressively optimize the repository at the expense
 	of taking much more time.  The effects of this optimization are
 	persistent, so this option only needs to be used occasionally; every
 	few hundred changesets or so.
 
 --auto::
-	With this option, `git gc` checks whether any housekeeping is
+	With this option, 'git-gc' checks whether any housekeeping is
 	required; if not, it exits without performing any work.
 	Some git commands run `git gc --auto` after performing
 	operations that could create many loose objects.
@@ -50,13 +50,13 @@
 too many packs in the repository. If the number of loose objects
 exceeds the value of the `gc.auto` configuration variable, then
 all loose objects are combined into a single pack using
-`git-repack -d -l`.  Setting the value of `gc.auto` to 0
+'git-repack -d -l'.  Setting the value of `gc.auto` to 0
 disables automatic packing of loose objects.
 +
 If the number of packs exceeds the value of `gc.autopacklimit`,
 then existing packs (except those marked with a `.keep` file)
 are consolidated into a single pack by using the `-A` option of
-`git-repack`. Setting `gc.autopacklimit` to 0 disables
+'git-repack'. Setting `gc.autopacklimit` to 0 disables
 automatic consolidation of packs.
 
 --quiet::
@@ -89,7 +89,7 @@
 kept.  This defaults to 15 days.
 
 The optional configuration variable 'gc.packrefs' determines if
-`git gc` runs `git-pack-refs`. This can be set to "nobare" to enable
+'git-gc' runs 'git-pack-refs'. This can be set to "nobare" to enable
 it within all non-bare repos or it can be set to a boolean value.
 This defaults to true.
 
@@ -108,10 +108,10 @@
 Notes
 -----
 
-git-gc tries very hard to be safe about the garbage it collects. In
+'git-gc' tries very hard to be safe about the garbage it collects. In
 particular, it will keep not only objects referenced by your current set
 of branches and tags, but also objects referenced by the index, remote
-tracking branches, refs saved by linkgit:git-filter-branch[1] in
+tracking branches, refs saved by 'git-filter-branch' in
 refs/original/, or reflogs (which may references commits in branches
 that were later amended or rewound).
 
diff --git a/Documentation/git-get-tar-commit-id.txt b/Documentation/git-get-tar-commit-id.txt
index c13bf98..84f23ee 100644
--- a/Documentation/git-get-tar-commit-id.txt
+++ b/Documentation/git-get-tar-commit-id.txt
@@ -8,18 +8,18 @@
 
 SYNOPSIS
 --------
-'git-get-tar-commit-id' < <tarfile>
+'git get-tar-commit-id' < <tarfile>
 
 
 DESCRIPTION
 -----------
 Acts as a filter, extracting the commit ID stored in archives created by
-linkgit:git-archive[1].  It reads only the first 1024 bytes of input, thus its
+'git-archive'.  It reads only the first 1024 bytes of input, thus its
 runtime is not influenced by the size of <tarfile> very much.
 
-If no commit ID is found, git-get-tar-commit-id quietly exists with a
+If no commit ID is found, 'git-get-tar-commit-id' quietly exists with a
 return code of 1.  This can happen if <tarfile> had not been created
-using git-archive or if the first parameter of git-archive had been
+using 'git-archive' or if the first parameter of 'git-archive' had been
 a tree ID instead of a commit ID or tag.
 
 
diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt
index 1b646b7..fa4d133 100644
--- a/Documentation/git-grep.txt
+++ b/Documentation/git-grep.txt
@@ -9,7 +9,7 @@
 SYNOPSIS
 --------
 [verse]
-'git-grep' [--cached]
+'git grep' [--cached]
 	   [-a | --text] [-I] [-i | --ignore-case] [-w | --word-regexp]
 	   [-v | --invert-match] [-h|-H] [--full-name]
 	   [-E | --extended-regexp] [-G | --basic-regexp]
@@ -91,7 +91,7 @@
 --files-without-match::
 	Instead of showing every matched line, show only the
 	names of files that contain (or do not contain) matches.
-	For better compatibility with git-diff, --name-only is a
+	For better compatibility with 'git-diff', --name-only is a
 	synonym for --files-with-matches.
 
 -c::
diff --git a/Documentation/git-gui.txt b/Documentation/git-gui.txt
index 105397f..0e650f4 100644
--- a/Documentation/git-gui.txt
+++ b/Documentation/git-gui.txt
@@ -11,19 +11,19 @@
 
 DESCRIPTION
 -----------
-A Tcl/Tk based graphical user interface to Git.  git-gui focuses
+A Tcl/Tk based graphical user interface to Git.  'git-gui' focuses
 on allowing users to make changes to their repository by making
 new commits, amending existing ones, creating branches, performing
 local merges, and fetching/pushing to remote repositories.
 
-Unlike linkgit:gitk[1], git-gui focuses on commit generation
-and single file annotation, and does not show project history.
-It does however supply menu actions to start a gitk session from
-within git-gui.
+Unlike 'gitk', 'git-gui' focuses on commit generation
+and single file annotation and does not show project history.
+It does however supply menu actions to start a 'gitk' session from
+within 'git-gui'.
 
-git-gui is known to work on all popular UNIX systems, Mac OS X,
+'git-gui' is known to work on all popular UNIX systems, Mac OS X,
 and Windows (under both Cygwin and MSYS).  To the extent possible
-OS specific user interface guidelines are followed, making git-gui
+OS specific user interface guidelines are followed, making 'git-gui'
 a fairly native interface for users.
 
 COMMANDS
@@ -34,17 +34,17 @@
 
 browser::
 	Start a tree browser showing all files in the specified
-	commit (or 'HEAD' by default).	Files selected through the
+	commit (or 'HEAD' by default).  Files selected through the
 	browser are opened in the blame viewer.
 
 citool::
-	Start git-gui and arrange to make exactly one commit before
+	Start 'git-gui' and arrange to make exactly one commit before
 	exiting and returning to the shell.  The interface is limited
 	to only commit actions, slightly reducing the application's
 	startup time and simplifying the menubar.
 
 version::
-	Display the currently running version of git-gui.
+	Display the currently running version of 'git-gui'.
 
 
 Examples
@@ -61,7 +61,7 @@
 git gui blame v0.99.8 Makefile::
 
 	Show the contents of 'Makefile' in revision 'v0.99.8'
-	and provide annotations for each line.	Unlike the above
+	and provide annotations for each line.  Unlike the above
 	example the file is read from the object database and not
 	the working directory.
 
@@ -71,7 +71,7 @@
 
 git citool::
 
-	Same as 'git gui citool' (above).
+	Same as `git gui citool` (above).
 
 git gui browser maint::
 
@@ -84,15 +84,15 @@
 linkgit:gitk[1]::
 	The git repository browser.  Shows branches, commit history
 	and file differences.  gitk is the utility started by
-	git-gui's Repository Visualize actions.
+	'git-gui''s Repository Visualize actions.
 
 Other
 -----
-git-gui is actually maintained as an independent project, but stable
+'git-gui' is actually maintained as an independent project, but stable
 versions are distributed as part of the Git suite for the convenience
 of end users.
 
-A git-gui development repository can be obtained from:
+A 'git-gui' development repository can be obtained from:
 
   git clone git://repo.or.cz/git-gui.git
 
diff --git a/Documentation/git-hash-object.txt b/Documentation/git-hash-object.txt
index 1abcd96..ac928e1 100644
--- a/Documentation/git-hash-object.txt
+++ b/Documentation/git-hash-object.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-hash-object' [-t <type>] [-w] [--stdin | --stdin-paths] [--] <file>...
+'git hash-object' [-t <type>] [-w] [--stdin | --stdin-paths] [--] <file>...
 
 DESCRIPTION
 -----------
@@ -16,7 +16,7 @@
 with the contents of the named file (which can be outside of the
 work tree), and optionally writes the resulting object into the
 object database.  Reports its object ID to its standard output.
-This is used by "git-cvsimport" to update the index
+This is used by 'git-cvsimport' to update the index
 without modifying files in the work tree.  When <type> is not
 specified, it defaults to "blob".
 
diff --git a/Documentation/git-help.txt b/Documentation/git-help.txt
index faecd6b..f414583 100644
--- a/Documentation/git-help.txt
+++ b/Documentation/git-help.txt
@@ -23,7 +23,7 @@
 up. The 'man' program is used by default for this purpose, but this
 can be overridden by other options or configuration variables.
 
-Note that 'git --help ...' is identical as 'git help ...' because the
+Note that `git --help ...` is identical to `git help ...` because the
 former is internally converted into the latter.
 
 OPTIONS
@@ -120,7 +120,7 @@
 You can explicitly provide a full path to your preferred man viewer by
 setting the configuration variable 'man.<tool>.path'. For example, you
 can configure the absolute path to konqueror by setting
-'man.konqueror.path'. Otherwise, 'git help' assumes the tool is
+'man.konqueror.path'. Otherwise, 'git-help' assumes the tool is
 available in PATH.
 
 man.<tool>.cmd
diff --git a/Documentation/git-http-fetch.txt b/Documentation/git-http-fetch.txt
index 70fb635..e7c7961 100644
--- a/Documentation/git-http-fetch.txt
+++ b/Documentation/git-http-fetch.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-http-fetch' [-c] [-t] [-a] [-d] [-v] [-w filename] [--recover] [--stdin] <commit> <url>
+'git http-fetch' [-c] [-t] [-a] [-d] [-v] [-w filename] [--recover] [--stdin] <commit> <url>
 
 DESCRIPTION
 -----------
diff --git a/Documentation/git-http-push.txt b/Documentation/git-http-push.txt
index d69b205..aef383e 100644
--- a/Documentation/git-http-push.txt
+++ b/Documentation/git-http-push.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-http-push' [--all] [--dry-run] [--force] [--verbose] <url> <ref> [<ref>...]
+'git http-push' [--all] [--dry-run] [--force] [--verbose] <url> <ref> [<ref>...]
 
 DESCRIPTION
 -----------
diff --git a/Documentation/git-imap-send.txt b/Documentation/git-imap-send.txt
index f4fdc24..b3d8da3 100644
--- a/Documentation/git-imap-send.txt
+++ b/Documentation/git-imap-send.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-imap-send'
+'git imap-send'
 
 
 DESCRIPTION
@@ -20,13 +20,13 @@
 
 Typical usage is something like:
 
-git-format-patch --signoff --stdout --attach origin | git-imap-send
+git format-patch --signoff --stdout --attach origin | git imap-send
 
 
 CONFIGURATION
 -------------
 
-git-imap-send requires the following values in the repository
+'git-imap-send' requires the following values in the repository
 configuration file (shown with examples):
 
 ..........................
diff --git a/Documentation/git-index-pack.txt b/Documentation/git-index-pack.txt
index 6409363..4b5c743 100644
--- a/Documentation/git-index-pack.txt
+++ b/Documentation/git-index-pack.txt
@@ -9,8 +9,8 @@
 SYNOPSIS
 --------
 [verse]
-'git-index-pack' [-v] [-o <index-file>] <pack-file>
-'git-index-pack' --stdin [--fix-thin] [--keep] [-v] [-o <index-file>]
+'git index-pack' [-v] [-o <index-file>] <pack-file>
+'git index-pack' --stdin [--fix-thin] [--keep] [-v] [-o <index-file>]
                  [<pack-file>]
 
 
@@ -43,10 +43,10 @@
 	a default name determined from the pack content.  If
 	<pack-file> is not specified consider using --keep to
 	prevent a race condition between this process and
-	linkgit:git-repack[1].
+	'git-repack'.
 
 --fix-thin::
-	It is possible for linkgit:git-pack-objects[1] to build
+	It is possible for 'git-pack-objects' to build
 	"thin" pack, which records objects in deltified form based on
 	objects not included in the pack to reduce network traffic.
 	Those objects are expected to be present on the receiving end
@@ -59,7 +59,7 @@
 	Before moving the index into its final destination
 	create an empty .keep file for the associated pack file.
 	This option is usually necessary with --stdin to prevent a
-	simultaneous linkgit:git-repack[1] process from deleting
+	simultaneous 'git-repack' process from deleting
 	the newly constructed pack and index before refs can be
 	updated to use objects contained in the pack.
 
@@ -86,7 +86,7 @@
 and the SHA1 hash of that list is printed to stdout. If --stdin was
 also used then this is prefixed by either "pack\t", or "keep\t" if a
 new .keep file was successfully created. This is useful to remove a
-.keep file used as a lock to prevent the race with linkgit:git-repack[1]
+.keep file used as a lock to prevent the race with 'git-repack'
 mentioned above.
 
 
diff --git a/Documentation/git-init-db.txt b/Documentation/git-init-db.txt
index 439cabb..1fd0ff2 100644
--- a/Documentation/git-init-db.txt
+++ b/Documentation/git-init-db.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-init-db' [-q | --quiet] [--template=<template_directory>] [--shared[=<permissions>]]
+'git init-db' [-q | --quiet] [--template=<template_directory>] [--shared[=<permissions>]]
 
 
 DESCRIPTION
diff --git a/Documentation/git-init.txt b/Documentation/git-init.txt
index 792643c..71749c0 100644
--- a/Documentation/git-init.txt
+++ b/Documentation/git-init.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-init' [-q | --quiet] [--bare] [--template=<template_directory>] [--shared[=<permissions>]]
+'git init' [-q | --quiet] [--bare] [--template=<template_directory>] [--shared[=<permissions>]]
 
 
 OPTIONS
@@ -86,11 +86,11 @@
 environment variable then the sha1 directories are created underneath -
 otherwise the default `$GIT_DIR/objects` directory is used.
 
-Running `git-init` in an existing repository is safe. It will not overwrite
-things that are already there. The primary reason for rerunning `git-init`
+Running 'git-init' in an existing repository is safe. It will not overwrite
+things that are already there. The primary reason for rerunning 'git-init'
 is to pick up newly added templates.
 
-Note that `git-init` is the same as `git-init-db`.  The command
+Note that 'git-init' is the same as 'git-init-db'.  The command
 was primarily meant to initialize the object database, but over
 time it has become responsible for setting up the other aspects
 of the repository, such as installing the default hooks and
@@ -105,8 +105,8 @@
 +
 ----------------
 $ cd /path/to/my/codebase
-$ git-init      <1>
-$ git-add .     <2>
+$ git init      <1>
+$ git add .     <2>
 ----------------
 +
 <1> prepare /path/to/my/codebase/.git directory
diff --git a/Documentation/git-instaweb.txt b/Documentation/git-instaweb.txt
index 7da5b8d..22da21a 100644
--- a/Documentation/git-instaweb.txt
+++ b/Documentation/git-instaweb.txt
@@ -8,13 +8,13 @@
 SYNOPSIS
 --------
 [verse]
-'git-instaweb' [--local] [--httpd=<httpd>] [--port=<port>]
+'git instaweb' [--local] [--httpd=<httpd>] [--port=<port>]
                [--browser=<browser>]
-'git-instaweb' [--start] [--stop] [--restart]
+'git instaweb' [--start] [--stop] [--restart]
 
 DESCRIPTION
 -----------
-A simple script to setup gitweb and a web server for browsing the local
+A simple script to set up `gitweb` and a web server for browsing the local
 repository.
 
 OPTIONS
diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt
index db61bc9..93a2a22 100644
--- a/Documentation/git-log.txt
+++ b/Documentation/git-log.txt
@@ -8,15 +8,15 @@
 
 SYNOPSIS
 --------
-'git-log' <option>...
+'git log' [<options>] [<since>..<until>] [[\--] <path>...]
 
 DESCRIPTION
 -----------
 Shows the commit logs.
 
-The command takes options applicable to the linkgit:git-rev-list[1]
+The command takes options applicable to the 'git-rev-list'
 command to control what is shown and how, and options applicable to
-the linkgit:git-diff-tree[1] commands to control how the changes
+the 'git-diff-*' commands to control how the changes
 each commit introduces are shown.
 
 
@@ -41,10 +41,10 @@
 	Print out the ref names of any commits that are shown.
 
 --full-diff::
-	Without this flag, "git log -p <paths>..." shows commits that
+	Without this flag, "git log -p <path>..." shows commits that
 	touch the specified paths, and diffs about the same specified
 	paths.  With this, the full diff is shown for commits that touch
-	the specified paths; this means that "<paths>..." limits only
+	the specified paths; this means that "<path>..." limits only
 	commits, and doesn't limit diff for those commits.
 
 --follow::
@@ -57,8 +57,11 @@
 	Note that only message is considered, if also a diff is shown
 	its size is not included.
 
-<paths>...::
-	Show only commits that affect the specified paths.
+[\--] <path>...::
+	Show only commits that affect any of the specified paths. To
+	prevent confusion with options and branch names, paths may need
+	to be prefixed with "\-- " to separate them from options or
+	refnames.
 
 
 include::rev-list-options.txt[]
diff --git a/Documentation/git-lost-found.txt b/Documentation/git-lost-found.txt
index 4dc475e..602b8d5 100644
--- a/Documentation/git-lost-found.txt
+++ b/Documentation/git-lost-found.txt
@@ -7,7 +7,7 @@
 
 SYNOPSIS
 --------
-'git-lost-found'
+'git lost-found'
 
 DESCRIPTION
 -----------
diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt
index 560594e..9f85d60 100644
--- a/Documentation/git-ls-files.txt
+++ b/Documentation/git-ls-files.txt
@@ -9,7 +9,7 @@
 SYNOPSIS
 --------
 [verse]
-'git-ls-files' [-z] [-t] [-v]
+'git ls-files' [-z] [-t] [-v]
 		(--[cached|deleted|others|ignored|stage|unmerged|killed|modified])\*
 		(-[c|d|o|i|s|u|k|m])\*
 		[-x <pattern>|--exclude=<pattern>]
@@ -53,7 +53,7 @@
 
 -s::
 --stage::
-	Show stage files in the output
+	Show staged contents' object name, mode bits and stage number in the output.
 
 --directory::
 	If a whole directory is classified as "other", show just its
@@ -143,14 +143,14 @@
 
         [<tag> ]<mode> <object> <stage> <file>
 
-"git-ls-files --unmerged" and "git-ls-files --stage" can be used to examine
+'git-ls-files --unmerged' and 'git-ls-files --stage' can be used to examine
 detailed information on unmerged paths.
 
 For an unmerged path, instead of recording a single mode/SHA1 pair,
 the index records up to three such pairs; one from tree O in stage
 1, A in stage 2, and B in stage 3.  This information can be used by
 the user (or the porcelain) to see what should eventually be recorded at the
-path. (see git-read-tree for more information on state)
+path. (see linkgit:git-read-tree[1] for more information on state)
 
 When `-z` option is not used, TAB, LF, and backslash characters
 in pathnames are represented as `\t`, `\n`, and `\\`,
diff --git a/Documentation/git-ls-remote.txt b/Documentation/git-ls-remote.txt
index f282164..abe7bf9 100644
--- a/Documentation/git-ls-remote.txt
+++ b/Documentation/git-ls-remote.txt
@@ -9,7 +9,7 @@
 SYNOPSIS
 --------
 [verse]
-'git-ls-remote' [--heads] [--tags]  [-u <exec> | --upload-pack <exec>]
+'git ls-remote' [--heads] [--tags]  [-u <exec> | --upload-pack <exec>]
 	      <repository> <refs>...
 
 DESCRIPTION
@@ -31,7 +31,7 @@
 
 -u <exec>::
 --upload-pack=<exec>::
-	Specify the full path of linkgit:git-upload-pack[1] on the remote
+	Specify the full path of 'git-upload-pack' on the remote
 	host. This allows listing references from repositories accessed via
 	SSH and where the SSH daemon does not use the PATH configured by the
 	user.
diff --git a/Documentation/git-ls-tree.txt b/Documentation/git-ls-tree.txt
index 8955b71..4c7262f 100644
--- a/Documentation/git-ls-tree.txt
+++ b/Documentation/git-ls-tree.txt
@@ -9,17 +9,27 @@
 SYNOPSIS
 --------
 [verse]
-'git-ls-tree' [-d] [-r] [-t] [-l] [-z]
+'git ls-tree' [-d] [-r] [-t] [-l] [-z]
 	    [--name-only] [--name-status] [--full-name] [--abbrev=[<n>]]
 	    <tree-ish> [paths...]
 
 DESCRIPTION
 -----------
 Lists the contents of a given tree object, like what "/bin/ls -a" does
-in the current working directory. Note that the usage is subtly different,
-though - 'paths' denote just a list of patterns to match, e.g. so specifying
-directory name (without '-r') will behave differently, and order of the
-arguments does not matter.
+in the current working directory.  Note that:
+
+ - the behaviour is slightly different from that of "/bin/ls" in that the
+   'paths' denote just a list of patterns to match, e.g. so specifying
+   directory name (without '-r') will behave differently, and order of the
+   arguments does not matter.
+
+ - the behaviour is similar to that of "/bin/ls" in that the 'paths' is
+   taken as relative to the current working directory.  E.g. when you are
+   in a directory 'sub' that has a directory 'dir', you can run 'git
+   ls-tree -r HEAD dir' to list the contents of the tree (that is
+   'sub/dir' in 'HEAD').  You don't want to give a tree that is not at the
+   root level (e.g. 'git ls-tree -r HEAD:sub dir') in this case, as that
+   would result in asking for 'sub/sub/dir' in the 'HEAD' commit.
 
 OPTIONS
 -------
diff --git a/Documentation/git-mailinfo.txt b/Documentation/git-mailinfo.txt
index 0b23fae..8d95aaa 100644
--- a/Documentation/git-mailinfo.txt
+++ b/Documentation/git-mailinfo.txt
@@ -8,15 +8,15 @@
 
 SYNOPSIS
 --------
-'git-mailinfo' [-k] [-u | --encoding=<encoding> | -n] <msg> <patch>
+'git mailinfo' [-k] [-u | --encoding=<encoding> | -n] <msg> <patch>
 
 
 DESCRIPTION
 -----------
-Reading a single e-mail message from the standard input, and
+Reads a single e-mail message from the standard input, and
 writes the commit log message in <msg> file, and the patches in
 <patch> file.  The author name, e-mail and e-mail subject are
-written out to the standard output to be used by git-am
+written out to the standard output to be used by 'git-am'
 to create a commit.  It is usually not necessary to use this
 command directly.  See linkgit:git-am[1] instead.
 
@@ -29,8 +29,8 @@
 	among which (1) remove 'Re:' or 're:', (2) leading
 	whitespaces, (3) '[' up to ']', typically '[PATCH]', and
 	then prepends "[PATCH] ".  This flag forbids this
-	munging, and is most useful when used to read back 'git
-	format-patch -k' output.
+	munging, and is most useful when used to read back
+	'git-format-patch -k' output.
 
 -u::
 	The commit log message, author name and author email are
diff --git a/Documentation/git-mailsplit.txt b/Documentation/git-mailsplit.txt
index 1a0df38..5cc94ec 100644
--- a/Documentation/git-mailsplit.txt
+++ b/Documentation/git-mailsplit.txt
@@ -7,7 +7,7 @@
 
 SYNOPSIS
 --------
-'git-mailsplit' [-b] [-f<nn>] [-d<prec>] -o<directory> [--] [<mbox>|<Maildir>...]
+'git mailsplit' [-b] [-f<nn>] [-d<prec>] -o<directory> [--] [<mbox>|<Maildir>...]
 
 DESCRIPTION
 -----------
diff --git a/Documentation/git-merge-base.txt b/Documentation/git-merge-base.txt
index bbe8512..1a7ecbf 100644
--- a/Documentation/git-merge-base.txt
+++ b/Documentation/git-merge-base.txt
@@ -8,20 +8,20 @@
 
 SYNOPSIS
 --------
-'git-merge-base' [--all] <commit> <commit>
+'git merge-base' [--all] <commit> <commit>
 
 DESCRIPTION
 -----------
 
-"git-merge-base" finds as good a common ancestor as possible between
-the two commits. That is, given two commits A and B 'git-merge-base A
-B' will output a commit which is reachable from both A and B through
+'git-merge-base' finds as good a common ancestor as possible between
+the two commits. That is, given two commits A and B, `git merge-base A
+B` will output a commit which is reachable from both A and B through
 the parent relationship.
 
 Given a selection of equally good common ancestors it should not be
 relied on to decide in any particular way.
 
-The "git-merge-base" algorithm is still in flux - use the source...
+The 'git-merge-base' algorithm is still in flux - use the source...
 
 OPTIONS
 -------
diff --git a/Documentation/git-merge-file.txt b/Documentation/git-merge-file.txt
index 149f131..024ec01 100644
--- a/Documentation/git-merge-file.txt
+++ b/Documentation/git-merge-file.txt
@@ -9,21 +9,21 @@
 SYNOPSIS
 --------
 [verse]
-'git-merge-file' [-L <current-name> [-L <base-name> [-L <other-name>]]]
+'git merge-file' [-L <current-name> [-L <base-name> [-L <other-name>]]]
 	[-p|--stdout] [-q|--quiet] <current-file> <base-file> <other-file>
 
 
 DESCRIPTION
 -----------
-git-file-merge incorporates all changes that lead from the `<base-file>`
+'git-file-merge' incorporates all changes that lead from the `<base-file>`
 to `<other-file>` into `<current-file>`. The result ordinarily goes into
-`<current-file>`. git-merge-file is useful for combining separate changes
+`<current-file>`. 'git-merge-file' is useful for combining separate changes
 to an original. Suppose `<base-file>` is the original, and both
 `<current-file>` and `<other-file>` are modifications of `<base-file>`.
-Then git-merge-file combines both changes.
+Then 'git-merge-file' combines both changes.
 
 A conflict occurs if both `<current-file>` and `<other-file>` have changes
-in a common segment of lines. If a conflict is found, git-merge-file
+in a common segment of lines. If a conflict is found, 'git-merge-file'
 normally outputs a warning and brackets the conflict with <<<<<<< and
 >>>>>>> lines. A typical conflict will look like this:
 
@@ -39,8 +39,8 @@
 The exit value of this program is negative on error, and the number of
 conflicts otherwise. If the merge was clean, the exit value is 0.
 
-git-merge-file is designed to be a minimal clone of RCS merge, that is, it
-implements all of RCS merge's functionality which is needed by
+'git-merge-file' is designed to be a minimal clone of RCS 'merge'; that is, it
+implements all of RCS 'merge''s functionality which is needed by
 linkgit:git[1].
 
 
@@ -51,7 +51,7 @@
 	This option may be given up to three times, and
 	specifies labels to be used in place of the
 	corresponding file names in conflict reports. That is,
-	`git-merge-file -L x -L y -L z a b c` generates output that
+	`git merge-file -L x -L y -L z a b c` generates output that
 	looks like it came from files x, y and z instead of
 	from files a, b and c.
 
@@ -85,7 +85,7 @@
 Documentation
 --------------
 Documentation by Johannes Schindelin and the git-list <git@vger.kernel.org>,
-with parts copied from the original documentation of RCS merge.
+with parts copied from the original documentation of RCS 'merge'.
 
 GIT
 ---
diff --git a/Documentation/git-merge-index.txt b/Documentation/git-merge-index.txt
index a0ead2b..ff088c5 100644
--- a/Documentation/git-merge-index.txt
+++ b/Documentation/git-merge-index.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-merge-index' [-o] [-q] <merge-program> (-a | [--] <file>\*)
+'git merge-index' [-o] [-q] <merge-program> (-a | [--] <file>\*)
 
 DESCRIPTION
 -----------
@@ -36,24 +36,24 @@
 	failure usually indicates conflicts during merge). This is for
 	porcelains which might want to emit custom messages.
 
-If "git-merge-index" is called with multiple <file>s (or -a) then it
+If 'git-merge-index' is called with multiple <file>s (or -a) then it
 processes them in turn only stopping if merge returns a non-zero exit
 code.
 
 Typically this is run with a script calling git's imitation of
-the merge command from the RCS package.
+the 'merge' command from the RCS package.
 
-A sample script called "git-merge-one-file" is included in the
+A sample script called 'git-merge-one-file' is included in the
 distribution.
 
 ALERT ALERT ALERT! The git "merge object order" is different from the
-RCS "merge" program merge object order. In the above ordering, the
+RCS 'merge' program merge object order. In the above ordering, the
 original is first. But the argument order to the 3-way merge program
-"merge" is to have the original in the middle. Don't ask me why.
+'merge' is to have the original in the middle. Don't ask me why.
 
 Examples:
 
-  torvalds@ppc970:~/merge-test> git-merge-index cat MM
+  torvalds@ppc970:~/merge-test> git merge-index cat MM
   This is MM from the original tree.			# original
   This is modified MM in the branch A.			# merge1
   This is modified MM in the branch B.			# merge2
@@ -61,17 +61,17 @@
 
 or
 
-  torvalds@ppc970:~/merge-test> git-merge-index cat AA MM
+  torvalds@ppc970:~/merge-test> git merge-index cat AA MM
   cat: : No such file or directory
   This is added AA in the branch A.
   This is added AA in the branch B.
   This is added AA in the branch B.
   fatal: merge program failed
 
-where the latter example shows how "git-merge-index" will stop trying to
-merge once anything has returned an error (i.e., "cat" returned an error
+where the latter example shows how 'git-merge-index' will stop trying to
+merge once anything has returned an error (i.e., `cat` returned an error
 for the AA file, because it didn't exist in the original, and thus
-"git-merge-index" didn't even try to merge the MM thing).
+'git-merge-index' didn't even try to merge the MM thing).
 
 Author
 ------
diff --git a/Documentation/git-merge-one-file.txt b/Documentation/git-merge-one-file.txt
index 546ebe8..dc8a96a 100644
--- a/Documentation/git-merge-one-file.txt
+++ b/Documentation/git-merge-one-file.txt
@@ -12,8 +12,8 @@
 
 DESCRIPTION
 -----------
-This is the standard helper program to use with "git-merge-index"
-to resolve a merge after the trivial merge done with "git-read-tree -m".
+This is the standard helper program to use with 'git-merge-index'
+to resolve a merge after the trivial merge done with 'git-read-tree -m'.
 
 Author
 ------
diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt
index b785e0f..dbb0c18 100644
--- a/Documentation/git-merge-tree.txt
+++ b/Documentation/git-merge-tree.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-merge-tree' <base-tree> <branch1> <branch2>
+'git merge-tree' <base-tree> <branch1> <branch2>
 
 DESCRIPTION
 -----------
diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt
index b05e0ce..17a15ac 100644
--- a/Documentation/git-merge.txt
+++ b/Documentation/git-merge.txt
@@ -9,9 +9,9 @@
 SYNOPSIS
 --------
 [verse]
-'git-merge' [-n] [--stat] [--no-commit] [--squash] [-s <strategy>]...
+'git merge' [-n] [--stat] [--no-commit] [--squash] [-s <strategy>]...
 	[-m <msg>] <remote> <remote>...
-'git-merge' <msg> HEAD <remote>...
+'git merge' <msg> HEAD <remote>...
 
 DESCRIPTION
 -----------
@@ -29,11 +29,11 @@
 
 -m <msg>::
 	The commit message to be used for the merge commit (in case
-	it is created). The `git-fmt-merge-msg` script can be used
-	to give a good default for automated `git-merge` invocations.
+	it is created). The 'git-fmt-merge-msg' script can be used
+	to give a good default for automated 'git-merge' invocations.
 
-<remote>::
-	Other branch head merged into our branch.  You need at
+<remote>...::
+	Other branch heads to merge into our branch.  You need at
 	least one <remote>.  Specifying more than one <remote>
 	obviously means you are trying an Octopus.
 
@@ -41,8 +41,7 @@
 
 
 If you tried a merge which resulted in a complex conflicts and
-would want to start over, you can recover with
-linkgit:git-reset[1].
+would want to start over, you can recover with 'git-reset'.
 
 CONFIGURATION
 -------------
@@ -50,7 +49,7 @@
 
 branch.<name>.mergeoptions::
 	Sets default options for merging into branch <name>. The syntax and
-	supported options are equal to that of git-merge, but option values
+	supported options are equal to that of 'git-merge', but option values
 	containing whitespace characters are currently not supported.
 
 HOW MERGE WORKS
@@ -58,48 +57,31 @@
 
 A merge is always between the current `HEAD` and one or more
 commits (usually, branch head or tag), and the index file must
-exactly match the
-tree of `HEAD` commit (i.e. the contents of the last commit) when
-it happens.  In other words, `git-diff --cached HEAD` must
-report no changes.
+match the tree of `HEAD` commit (i.e. the contents of the last commit)
+when it starts out.  In other words, `git diff --cached HEAD` must
+report no changes.  (One exception is when the changed index
+entries are already in the same state that would result from
+the merge anyway.)
 
-[NOTE]
-This is a bit of a lie.  In certain special cases, your index is
-allowed to be different from the tree of the `HEAD` commit.  The most
-notable case is when your `HEAD` commit is already ahead of what
-is being merged, in which case your index can have arbitrary
-differences from your `HEAD` commit.  Also, your index entries
-may have differences from your `HEAD` commit that match
-the result of a trivial merge (e.g. you received the same patch
-from an external source to produce the same result as what you are
-merging).  For example, if a path did not exist in the common
-ancestor and your head commit but exists in the tree you are
-merging into your repository, and if you already happen to have
-that path exactly in your index, the merge does not have to
-fail.
+Three kinds of merge can happen:
 
-Otherwise, merge will refuse to do any harm to your repository
-(that is, it may fetch the objects from remote, and it may even
-update the local branch used to keep track of the remote branch
-with `git pull remote rbranch:lbranch`, but your working tree,
-`.git/HEAD` pointer and index file are left intact).
+* The merged commit is already contained in `HEAD`. This is the
+  simplest case, called "Already up-to-date."
 
-You may have local modifications in the working tree files.  In
-other words, `git-diff` is allowed to report changes.
-However, the merge uses your working tree as the working area,
-and in order to prevent the merge operation from losing such
-changes, it makes sure that they do not interfere with the
-merge. Those complex tables in read-tree documentation define
-what it means for a path to "interfere with the merge".  And if
-your local modifications interfere with the merge, again, it
-stops before touching anything.
+* `HEAD` is already contained in the merged commit. This is the
+  most common case especially when involved through 'git pull':
+  you are tracking an upstream repository, committed no local
+  changes and now you want to update to a newer upstream revision.
+  Your `HEAD` (and the index) is updated to at point the merged
+  commit, without creating an extra merge commit.  This is
+  called "Fast-forward".
 
-So in the above two "failed merge" case, you do not have to
-worry about loss of data --- you simply were not ready to do
-a merge, so no merge happened at all.  You may want to finish
-whatever you were in the middle of doing, and retry the same
-pull after you are done and ready.
+* Both the merged commit and `HEAD` are independent and must be
+  tied together by a merge commit that has them both as its parents.
+  The rest of this section describes this "True merge" case.
 
+The chosen merge strategy merges the two commits into a single
+new source tree.
 When things cleanly merge, these things happen:
 
 1. The results are updated both in the index file and in your
@@ -128,7 +110,7 @@
 3. For conflicting paths, the index file records up to three
    versions; stage1 stores the version from the common ancestor,
    stage2 from `HEAD`, and stage3 from the remote branch (you
-   can inspect the stages with `git-ls-files -u`).  The working
+   can inspect the stages with `git ls-files -u`).  The working
    tree files have the result of "merge" program; i.e. 3-way
    merge result with familiar conflict markers `<<< === >>>`.
 
@@ -141,21 +123,25 @@
 
  * Decide not to merge.  The only clean-up you need are to reset
    the index file to the `HEAD` commit to reverse 2. and to clean
-   up working tree changes made by 2. and 3.; `git-reset` can
+   up working tree changes made by 2. and 3.; 'git-reset --hard' can
    be used for this.
 
- * Resolve the conflicts.  `git-diff` would report only the
-   conflicting paths because of the above 2. and 3..  Edit the
-   working tree files into a desirable shape, `git-add` or `git-rm`
+ * Resolve the conflicts.  `git diff` would report only the
+   conflicting paths because of the above 2. and 3.
+   Edit the working tree files into a desirable shape
+   ('git mergetool' can ease this task), 'git-add' or 'git-rm'
    them, to make the index file contain what the merge result
-   should be, and run `git-commit` to commit the result.
+   should be, and run 'git-commit' to commit the result.
 
 
 SEE ALSO
 --------
 linkgit:git-fmt-merge-msg[1], linkgit:git-pull[1],
-linkgit:gitattributes[5]
-
+linkgit:gitattributes[5],
+linkgit:git-reset[1],
+linkgit:git-diff[1], linkgit:git-ls-files[1],
+linkgit:git-add[1], linkgit:git-rm[1],
+linkgit:git-mergetool[1]
 
 Author
 ------
diff --git a/Documentation/git-mergetool.txt b/Documentation/git-mergetool.txt
index 8352560..e0b2703 100644
--- a/Documentation/git-mergetool.txt
+++ b/Documentation/git-mergetool.txt
@@ -7,17 +7,17 @@
 
 SYNOPSIS
 --------
-'git-mergetool' [--tool=<tool>] [<file>]...
+'git mergetool' [--tool=<tool>] [<file>]...
 
 DESCRIPTION
 -----------
 
 Use `git mergetool` to run one of several merge utilities to resolve
-merge conflicts.  It is typically run after linkgit:git-merge[1].
+merge conflicts.  It is typically run after 'git-merge'.
 
 If one or more <file> parameters are given, the merge tool program will
 be run to resolve differences on each file.  If no <file> names are
-specified, `git mergetool` will run the merge tool program on every file
+specified, 'git-mergetool' will run the merge tool program on every file
 with merge conflicts.
 
 OPTIONS
@@ -27,23 +27,23 @@
 	Valid merge tools are:
 	kdiff3, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff, ecmerge, and opendiff
 +
-If a merge resolution program is not specified, `git mergetool`
+If a merge resolution program is not specified, 'git-mergetool'
 will use the configuration variable `merge.tool`.  If the
-configuration variable `merge.tool` is not set, `git mergetool`
+configuration variable `merge.tool` is not set, 'git-mergetool'
 will pick a suitable default.
 +
 You can explicitly provide a full path to the tool by setting the
 configuration variable `mergetool.<tool>.path`. For example, you
 can configure the absolute path to kdiff3 by setting
-`mergetool.kdiff3.path`. Otherwise, `git mergetool` assumes the
+`mergetool.kdiff3.path`. Otherwise, 'git-mergetool' assumes the
 tool is available in PATH.
 +
 Instead of running one of the known merge tool programs
-`git mergetool` can be customized to run an alternative program
-by specifying the command line to invoke in a configration
+'git-mergetool' can be customized to run an alternative program
+by specifying the command line to invoke in a configuration
 variable `mergetool.<tool>.cmd`.
 +
-When `git mergetool` is invoked with this tool (either through the
+When 'git-mergetool' is invoked with this tool (either through the
 `-t` or `--tool` option or the `merge.tool` configuration
 variable) the configured command line will be invoked with `$BASE`
 set to the name of a temporary file containing the common base for
@@ -57,7 +57,7 @@
 If the custom merge tool correctly indicates the success of a
 merge resolution with its exit code then the configuration
 variable `mergetool.<tool>.trustExitCode` can be set to `true`.
-Otherwise, `git mergetool` will prompt the user to indicate the
+Otherwise, 'git-mergetool' will prompt the user to indicate the
 success of the resolution after the custom tool has exited.
 
 Author
diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt
index 232bc1a..8bcc114 100644
--- a/Documentation/git-mktag.txt
+++ b/Documentation/git-mktag.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-mktag' < signature_file
+'git mktag' < signature_file
 
 DESCRIPTION
 -----------
diff --git a/Documentation/git-mktree.txt b/Documentation/git-mktree.txt
index 6927eb9..af19f06 100644
--- a/Documentation/git-mktree.txt
+++ b/Documentation/git-mktree.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-mktree' [-z]
+'git mktree' [-z]
 
 DESCRIPTION
 -----------
diff --git a/Documentation/git-mv.txt b/Documentation/git-mv.txt
index 3391906..9c56602 100644
--- a/Documentation/git-mv.txt
+++ b/Documentation/git-mv.txt
@@ -8,14 +8,14 @@
 
 SYNOPSIS
 --------
-'git-mv' <options>... <args>...
+'git mv' <options>... <args>...
 
 DESCRIPTION
 -----------
 This script is used to move or rename a file, directory or symlink.
 
- git-mv [-f] [-n] <source> <destination>
- git-mv [-f] [-n] [-k] <source> ... <destination directory>
+ git mv [-f] [-n] <source> <destination>
+ git mv [-f] [-n] [-k] <source> ... <destination directory>
 
 In the first form, it renames <source>, which must exist and be either
 a file, symlink or directory, to <destination>.
diff --git a/Documentation/git-name-rev.txt b/Documentation/git-name-rev.txt
index 83d8e4a..7ca8a7b 100644
--- a/Documentation/git-name-rev.txt
+++ b/Documentation/git-name-rev.txt
@@ -9,13 +9,13 @@
 SYNOPSIS
 --------
 [verse]
-'git-name-rev' [--tags] [--refs=<pattern>]
+'git name-rev' [--tags] [--refs=<pattern>]
 	       ( --all | --stdin | <committish>... )
 
 DESCRIPTION
 -----------
 Finds symbolic names suitable for human digestion for revisions given in any
-format parsable by git-rev-parse.
+format parsable by 'git-rev-parse'.
 
 
 OPTIONS
@@ -38,7 +38,7 @@
 	Instead of printing both the SHA-1 and the name, print only
 	the name.  If given with --tags the usual tag prefix of
 	"tags/" is also omitted from the name, matching the output
-	of linkgit:git-describe[1] more closely.
+	of `git-describe` more closely.
 
 --no-undefined::
 	Die with error code != 0 when a reference is undefined,
@@ -55,11 +55,11 @@
 Of course, you look into the commit, but that only tells you what happened, but
 not the context.
 
-Enter git-name-rev:
+Enter 'git-name-rev':
 
 ------------
 % git name-rev 33db5f4d9027a10e477ccf054b2c1ab94f74c85a
-33db5f4d9027a10e477ccf054b2c1ab94f74c85a tags/v0.99^0~940
+33db5f4d9027a10e477ccf054b2c1ab94f74c85a tags/v0.99~940
 ------------
 
 Now you are wiser, because you know that it happened 940 revisions before v0.99.
diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt
index f4d8d68..7d4c1a7 100644
--- a/Documentation/git-pack-objects.txt
+++ b/Documentation/git-pack-objects.txt
@@ -9,7 +9,7 @@
 SYNOPSIS
 --------
 [verse]
-'git-pack-objects' [-q] [--no-reuse-delta] [--delta-base-offset] [--non-empty]
+'git pack-objects' [-q] [--no-reuse-delta] [--delta-base-offset] [--non-empty]
 	[--local] [--incremental] [--window=N] [--depth=N] [--all-progress]
 	[--revs [--unpacked | --all]*] [--stdout | base-name] < object-list
 
@@ -30,7 +30,7 @@
 any of the directories on $GIT_ALTERNATE_OBJECT_DIRECTORIES)
 enables git to read from such an archive.
 
-'git-unpack-objects' command can read the packed archive and
+The 'git-unpack-objects' command can read the packed archive and
 expand the objects contained in the pack into "one-file
 one-object" format; this is typically done by the smart-pull
 commands when a pack is created on-the-fly for efficient network
@@ -59,7 +59,7 @@
 --revs::
 	Read the revision arguments from the standard input, instead of
 	individual object names.  The revision arguments are processed
-	the same way as linkgit:git-rev-list[1] with `--objects` flag
+	the same way as 'git-rev-list' with the `--objects` flag
 	uses its `commit` arguments to build the list of objects it
 	outputs.  The objects on the resulting list are packed.
 
@@ -109,6 +109,11 @@
 	The default is unlimited, unless the config variable
 	`pack.packSizeLimit` is set.
 
+--honor-pack-keep::
+	This flag causes an object already in a local pack that
+	has a .keep file to be ignored, even if it appears in the
+	standard input.
+
 --incremental::
 	This flag causes an object already in a pack ignored
 	even if it appears in the standard input.
@@ -116,7 +121,7 @@
 --local::
 	This flag is similar to `--incremental`; instead of
 	ignoring all packed objects, it only ignores objects
-	that are packed and not in the local object store
+	that are packed and/or not in the local object store
 	(i.e. borrowed from an alternate).
 
 --non-empty::
@@ -163,14 +168,14 @@
 	generated pack.  If not specified,  pack compression level is
 	determined first by pack.compression,  then by core.compression,
 	and defaults to -1,  the zlib default,  if neither is set.
-	Add \--no-reuse-object if you want to force a uniform compression
+	Add --no-reuse-object if you want to force a uniform compression
 	level on all data no matter the source.
 
 --delta-base-offset::
 	A packed archive can express base object of a delta as
 	either 20-byte object name or as an offset in the
 	stream, but older version of git does not understand the
-	latter.  By default, git-pack-objects only uses the
+	latter.  By default, 'git-pack-objects' only uses the
 	former format for better compatibility.  This option
 	allows the command to use the latter format for
 	compactness.  Depending on the average delta chain
diff --git a/Documentation/git-pack-redundant.txt b/Documentation/git-pack-redundant.txt
index 6737326..5f9435e 100644
--- a/Documentation/git-pack-redundant.txt
+++ b/Documentation/git-pack-redundant.txt
@@ -8,21 +8,21 @@
 
 SYNOPSIS
 --------
-'git-pack-redundant' [ --verbose ] [ --alt-odb ] < --all | .pack filename ... >
+'git pack-redundant' [ --verbose ] [ --alt-odb ] < --all | .pack filename ... >
 
 DESCRIPTION
 -----------
 This program computes which packs in your repository
 are redundant. The output is suitable for piping to
-'xargs rm' if you are in the root of the repository.
+`xargs rm` if you are in the root of the repository.
 
-git-pack-redundant accepts a list of objects on standard input. Any objects
+'git-pack-redundant' accepts a list of objects on standard input. Any objects
 given will be ignored when checking which packs are required. This makes the
 following command useful when wanting to remove packs which contain unreachable
 objects.
 
-git-fsck --full --unreachable | cut -d ' ' -f3 | \
-git-pack-redundant --all | xargs rm
+git fsck --full --unreachable | cut -d ' ' -f3 | \
+git pack-redundant --all | xargs rm
 
 OPTIONS
 -------
diff --git a/Documentation/git-pack-refs.txt b/Documentation/git-pack-refs.txt
index c071846..a5244d3 100644
--- a/Documentation/git-pack-refs.txt
+++ b/Documentation/git-pack-refs.txt
@@ -7,7 +7,7 @@
 
 SYNOPSIS
 --------
-'git-pack-refs' [--all] [--no-prune]
+'git pack-refs' [--all] [--no-prune]
 
 DESCRIPTION
 -----------
@@ -31,7 +31,7 @@
 
 A recommended practice to deal with a repository with too many
 refs is to pack its refs with `--all --prune` once, and
-occasionally run `git-pack-refs \--prune`.  Tags are by
+occasionally run `git pack-refs \--prune`.  Tags are by
 definition stationary and are not expected to change.  Branch
 heads will be packed with the initial `pack-refs --all`, but
 only the currently active branch heads will become unpacked,
diff --git a/Documentation/git-parse-remote.txt b/Documentation/git-parse-remote.txt
index 951dbd6..cd43069 100644
--- a/Documentation/git-parse-remote.txt
+++ b/Documentation/git-parse-remote.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'. git-parse-remote'
+'. "$(git --exec-path)/git-parse-remote"'
 
 DESCRIPTION
 -----------
@@ -32,7 +32,7 @@
 get_remote_refs_for_push::
 	Given the list of user-supplied `<repo> <refspec>...`,
 	return the list of refs to push in a form suitable to be
-	fed to the `git-send-pack` command.  When `<refspec>...`
+	fed to the 'git-send-pack' command.  When `<refspec>...`
 	is empty the returned list of refs consists of the
 	defaults for the given `<repo>`, if specified in
 	`$GIT_DIR/remotes/`.
diff --git a/Documentation/git-patch-id.txt b/Documentation/git-patch-id.txt
index bb8a079..477785e 100644
--- a/Documentation/git-patch-id.txt
+++ b/Documentation/git-patch-id.txt
@@ -7,7 +7,7 @@
 
 SYNOPSIS
 --------
-'git-patch-id' < <patch>
+'git patch-id' < <patch>
 
 DESCRIPTION
 -----------
@@ -18,7 +18,7 @@
 
 IOW, you can use this thing to look for likely duplicate commits.
 
-When dealing with git-diff-tree output, it takes advantage of
+When dealing with 'git-diff-tree' output, it takes advantage of
 the fact that the patch is prefixed with the object name of the
 commit, and outputs two 40-byte hexadecimal string.  The first
 string is the patch ID, and the second string is the commit ID.
diff --git a/Documentation/git-peek-remote.txt b/Documentation/git-peek-remote.txt
index 3fb17f9..8282a5e 100644
--- a/Documentation/git-peek-remote.txt
+++ b/Documentation/git-peek-remote.txt
@@ -8,11 +8,11 @@
 
 SYNOPSIS
 --------
-'git-peek-remote' [--upload-pack=<git-upload-pack>] [<host>:]<directory>
+'git peek-remote' [--upload-pack=<git-upload-pack>] [<host>:]<directory>
 
 DESCRIPTION
 -----------
-This command is deprecated; use `git-ls-remote` instead.
+This command is deprecated; use 'git-ls-remote' instead.
 
 OPTIONS
 -------
diff --git a/Documentation/git-prune-packed.txt b/Documentation/git-prune-packed.txt
index f330b8a..b5f26ce 100644
--- a/Documentation/git-prune-packed.txt
+++ b/Documentation/git-prune-packed.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-prune-packed' [-n] [-q]
+'git prune-packed' [-n] [-q]
 
 
 DESCRIPTION
diff --git a/Documentation/git-prune.txt b/Documentation/git-prune.txt
index ec335d6..54f1dab 100644
--- a/Documentation/git-prune.txt
+++ b/Documentation/git-prune.txt
@@ -13,16 +13,16 @@
 DESCRIPTION
 -----------
 
-NOTE: In most cases, users should run linkgit:git-gc[1], which calls
-git-prune. See the section "NOTES", below.
+NOTE: In most cases, users should run 'git-gc', which calls
+'git-prune'. See the section "NOTES", below.
 
-This runs `git-fsck --unreachable` using all the refs
+This runs 'git-fsck --unreachable' using all the refs
 available in `$GIT_DIR/refs`, optionally with additional set of
 objects specified on the command line, and prunes all unpacked
 objects unreachable from any of these head objects from the object database.
 In addition, it
 prunes the unpacked objects that are also found in packs by
-running `git prune-packed`.
+running 'git-prune-packed'.
 
 Note that unreachable, packed objects will remain.  If this is
 not desired, see linkgit:git-repack[1].
@@ -53,18 +53,18 @@
 `.git/objects/info/alternates`:
 
 ------------
-$ git prune $(cd ../another && $(git-rev-parse --all))
+$ git prune $(cd ../another && $(git rev-parse --all))
 ------------
 
 Notes
 -----
 
-In most cases, users will not need to call git-prune directly, but
-should instead call linkgit:git-gc[1], which handles pruning along with
+In most cases, users will not need to call 'git-prune' directly, but
+should instead call 'git-gc', which handles pruning along with
 many other housekeeping tasks.
 
 For a description of which objects are considered for pruning, see
-git-fsck's --unreachable option.
+'git-fsck''s --unreachable option.
 
 SEE ALSO
 --------
diff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt
index c731bdc..7578623 100644
--- a/Documentation/git-pull.txt
+++ b/Documentation/git-pull.txt
@@ -8,21 +8,21 @@
 
 SYNOPSIS
 --------
-'git-pull' <options> <repository> <refspec>...
+'git pull' <options> <repository> <refspec>...
 
 
 DESCRIPTION
 -----------
-Runs `git-fetch` with the given parameters, and calls `git-merge`
+Runs 'git-fetch' with the given parameters, and calls 'git-merge'
 to merge the retrieved head(s) into the current branch.
-With `--rebase`, calls `git-rebase` instead of `git-merge`.
+With `--rebase`, calls 'git-rebase' instead of 'git-merge'.
 
 Note that you can use `.` (current directory) as the
 <repository> to pull from the local repository -- this is useful
 when merging local branches into the current branch.
 
-Also note that options meant for `git-pull` itself and underlying
-`git-merge` must be given before the options meant for `git-fetch`.
+Also note that options meant for 'git-pull' itself and underlying
+'git-merge' must be given before the options meant for 'git-fetch'.
 
 OPTIONS
 -------
@@ -182,8 +182,7 @@
 
 
 If you tried a pull which resulted in a complex conflicts and
-would want to start over, you can recover with
-linkgit:git-reset[1].
+would want to start over, you can recover with 'git-reset'.
 
 
 SEE ALSO
diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index 60d5339..6150b1b 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -9,8 +9,9 @@
 SYNOPSIS
 --------
 [verse]
-'git-push' [--all] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>]
-           [--repo=all] [-f | --force] [-v | --verbose] [<repository> <refspec>...]
+'git push' [--all | --mirror] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>]
+	   [--repo=<repository>] [-f | --force] [-v | --verbose]
+	   [<repository> <refspec>...]
 
 DESCRIPTION
 -----------
@@ -29,7 +30,7 @@
 	The "remote" repository that is destination of a push
 	operation.  See the section <<URLS,GIT URLS>> below.
 
-<refspec>::
+<refspec>...::
 	The canonical format of a <refspec> parameter is
 	`+?<src>:<dst>`; that is, an optional plus `{plus}`, followed
 	by the source ref, followed by a colon `:`, followed by
@@ -67,7 +68,8 @@
 
 --mirror::
 	Instead of naming each ref to push, specifies that all
-	refs under `$GIT_DIR/refs/heads/` and `$GIT_DIR/refs/tags/`
+	refs under `$GIT_DIR/refs/` (which includes but is not
+	limited to `refs/heads/`, `refs/remotes/`, and `refs/tags/`)
 	be mirrored to the remote repository.  Newly created local
 	refs will be pushed to the remote end, locally updated refs
 	will be force updated on the remote end, and deleted refs
@@ -99,13 +101,27 @@
 	This flag disables the check.  This can cause the
 	remote repository to lose commits; use it with care.
 
---repo=<repo>::
-	When no repository is specified the command defaults to
-	"origin"; this overrides it.
+--repo=<repository>::
+	This option is only relevant if no <repository> argument is
+	passed in the invocation. In this case, 'git-push' derives the
+	remote name from the current branch: If it tracks a remote
+	branch, then that remote repository is pushed to. Otherwise,
+	the name "origin" is used. For this latter case, this option
+	can be used to override the name "origin". In other words,
+	the difference between these two commands
++
+--------------------------
+git push public         #1
+git push --repo=public  #2
+--------------------------
++
+is that #1 always pushes to "public" whereas #2 pushes to "public"
+only if the current branch does not track a remote branch. This is
+useful if you write an alias or script around 'git-push'.
 
 --thin::
 --no-thin::
-	These options are passed to `git-send-pack`.  Thin
+	These options are passed to 'git-send-pack'.  Thin
 	transfer spends extra cycles to minimize the number of
 	objects to be sent and meant to be used on slower connection.
 
@@ -179,11 +195,11 @@
 	Find a ref that matches `experimental` in the `origin` repository
 	(e.g. `refs/heads/experimental`), and delete it.
 
-git push origin master:satellite/master::
-	Find a ref that matches `master` in the source repository
-	(most likely, it would find `refs/heads/master`), and update
-	the ref that matches `satellite/master` (most likely, it would
-	be `refs/remotes/satellite/master`) in `origin` repository with it.
+git push origin master:satellite/master dev:satellite/dev::
+	Use the source ref that matches `master` (e.g. `refs/heads/master`)
+	to update the ref that matches `satellite/master` (most probably
+	`refs/remotes/satellite/master`) in the `origin` repository, then
+	do the same for `dev` and `satellite/dev`.
 
 git push origin master:refs/heads/experimental::
 	Create the branch `experimental` in the `origin` repository
diff --git a/Documentation/git-quiltimport.txt b/Documentation/git-quiltimport.txt
index 0600379..d4037de 100644
--- a/Documentation/git-quiltimport.txt
+++ b/Documentation/git-quiltimport.txt
@@ -9,7 +9,7 @@
 SYNOPSIS
 --------
 [verse]
-'git-quiltimport' [--dry-run] [--author <author>] [--patches <dir>]
+'git quiltimport' [--dry-run] [--author <author>] [--patches <dir>]
 
 
 DESCRIPTION
diff --git a/Documentation/git-read-tree.txt b/Documentation/git-read-tree.txt
index 58fb906..309deac 100644
--- a/Documentation/git-read-tree.txt
+++ b/Documentation/git-read-tree.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-read-tree' (<tree-ish> | [[-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>] [-u | -i]] [--exclude-per-directory=<gitignore>] [--index-output=<file>] <tree-ish1> [<tree-ish2> [<tree-ish3>]])
+'git read-tree' (<tree-ish> | [[-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>] [-u | -i]] [--exclude-per-directory=<gitignore>] [--index-output=<file>] <tree-ish1> [<tree-ish2> [<tree-ish3>]])
 
 
 DESCRIPTION
@@ -22,8 +22,8 @@
 flag.  When used with `-m`, the `-u` flag causes it to also update
 the files in the work tree with the result of the merge.
 
-Trivial merges are done by `git-read-tree` itself.  Only conflicting paths
-will be in unmerged state when `git-read-tree` returns.
+Trivial merges are done by 'git-read-tree' itself.  Only conflicting paths
+will be in unmerged state when 'git-read-tree' returns.
 
 OPTIONS
 -------
@@ -54,13 +54,13 @@
 	Show the progress of checking files out.
 
 --trivial::
-	Restrict three-way merge by `git-read-tree` to happen
+	Restrict three-way merge by 'git-read-tree' to happen
 	only if there is no file-level merging required, instead
 	of resolving merge for trivial cases and leaving
 	conflicting files unresolved in the index.
 
 --aggressive::
-	Usually a three-way merge by `git-read-tree` resolves
+	Usually a three-way merge by 'git-read-tree' resolves
 	the merge for really trivial cases and leaves other
 	cases unresolved in the index, so that Porcelains can
 	implement different merge policies.  This flag makes the
@@ -113,7 +113,7 @@
 
 Merging
 -------
-If `-m` is specified, `git-read-tree` can perform 3 kinds of
+If `-m` is specified, 'git-read-tree' can perform 3 kinds of
 merge, a single tree merge if only 1 tree is given, a
 fast-forward merge with 2 trees, or a 3-way merge if 3 trees are
 provided.
@@ -121,29 +121,29 @@
 
 Single Tree Merge
 ~~~~~~~~~~~~~~~~~
-If only 1 tree is specified, git-read-tree operates as if the user did not
+If only 1 tree is specified, 'git-read-tree' operates as if the user did not
 specify `-m`, except that if the original index has an entry for a
 given pathname, and the contents of the path matches with the tree
 being read, the stat info from the index is used. (In other words, the
 index's stat()s take precedence over the merged tree's).
 
-That means that if you do a `git-read-tree -m <newtree>` followed by a
-`git-checkout-index -f -u -a`, the `git-checkout-index` only checks out
+That means that if you do a `git read-tree -m <newtree>` followed by a
+`git checkout-index -f -u -a`, the 'git-checkout-index' only checks out
 the stuff that really changed.
 
-This is used to avoid unnecessary false hits when `git-diff-files` is
-run after `git-read-tree`.
+This is used to avoid unnecessary false hits when 'git-diff-files' is
+run after 'git-read-tree'.
 
 
 Two Tree Merge
 ~~~~~~~~~~~~~~
 
-Typically, this is invoked as `git-read-tree -m $H $M`, where $H
+Typically, this is invoked as `git read-tree -m $H $M`, where $H
 is the head commit of the current repository, and $M is the head
 of a foreign tree, which is simply ahead of $H (i.e. we are in a
 fast forward situation).
 
-When two trees are specified, the user is telling git-read-tree
+When two trees are specified, the user is telling 'git-read-tree'
 the following:
 
      1. The current index and work tree is derived from $H, but
@@ -151,7 +151,7 @@
 
      2. The user wants to fast-forward to $M.
 
-In this case, the `git-read-tree -m $H $M` command makes sure
+In this case, the `git read-tree -m $H $M` command makes sure
 that no local change is lost as the result of this "merge".
 Here are the "carry forward" rules:
 
@@ -160,7 +160,10 @@
       0 nothing             nothing  nothing  (does not happen)
       1 nothing             nothing  exists   use M
       2 nothing             exists   nothing  remove path from index
-      3 nothing             exists   exists   use M
+      3 nothing             exists   exists,  use M if "initial checkout"
+				     H == M   keep index otherwise
+				     exists   fail
+				     H != M
 
         clean I==H  I==M
        ------------------
@@ -193,33 +196,39 @@
 
 In all "keep index" cases, the index entry stays as in the
 original index file.  If the entry were not up to date,
-git-read-tree keeps the copy in the work tree intact when
+'git-read-tree' keeps the copy in the work tree intact when
 operating under the -u flag.
 
-When this form of git-read-tree returns successfully, you can
+When this form of 'git-read-tree' returns successfully, you can
 see what "local changes" you made are carried forward by running
-`git-diff-index --cached $M`.  Note that this does not
-necessarily match `git-diff-index --cached $H` would have
+`git diff-index --cached $M`.  Note that this does not
+necessarily match `git diff-index --cached $H` would have
 produced before such a two tree merge.  This is because of cases
 18 and 19 --- if you already had the changes in $M (e.g. maybe
-you picked it up via e-mail in a patch form), `git-diff-index
+you picked it up via e-mail in a patch form), `git diff-index
 --cached $H` would have told you about the change before this
-merge, but it would not show in `git-diff-index --cached $M`
+merge, but it would not show in `git diff-index --cached $M`
 output after two-tree merge.
 
+Case #3 is slightly tricky and needs explanation.  The result from this
+rule logically should be to remove the path if the user staged the removal
+of the path and then swiching to a new branch.  That however will prevent
+the initial checkout from happening, so the rule is modified to use M (new
+tree) only when the contents of the index is empty.  Otherwise the removal
+of the path is kept as long as $H and $M are the same.
 
 3-Way Merge
 ~~~~~~~~~~~
 Each "index" entry has two bits worth of "stage" state. stage 0 is the
 normal one, and is the only one you'd see in any kind of normal use.
 
-However, when you do `git-read-tree` with three trees, the "stage"
+However, when you do 'git-read-tree' with three trees, the "stage"
 starts out at 1.
 
 This means that you can do
 
 ----------------
-$ git-read-tree -m <tree1> <tree2> <tree3>
+$ git read-tree -m <tree1> <tree2> <tree3>
 ----------------
 
 and you will end up with an index with all of the <tree1> entries in
@@ -229,7 +238,7 @@
 as <tree1>, the current branch head as <tree2>, and the other
 branch head as <tree3>.
 
-Furthermore, `git-read-tree` has special-case logic that says: if you see
+Furthermore, 'git-read-tree' has special-case logic that says: if you see
 a file that matches in all respects in the following states, it
 "collapses" back to "stage0":
 
@@ -245,7 +254,7 @@
    - stage 1 and stage 3 are the same and stage 2 is different take
      stage 2 (we did something while they did nothing)
 
-The `git-write-tree` command refuses to write a nonsensical tree, and it
+The 'git-write-tree' command refuses to write a nonsensical tree, and it
 will complain about unmerged entries if it sees a single entry that is not
 stage 0.
 
@@ -261,7 +270,7 @@
 populated.  Here is an outline of how the algorithm works:
 
 - if a file exists in identical format in all three trees, it will
-  automatically collapse to "merged" state by git-read-tree.
+  automatically collapse to "merged" state by 'git-read-tree'.
 
 - a file that has _any_ difference what-so-ever in the three trees
   will stay as separate entries in the index. It's up to "porcelain
@@ -285,8 +294,8 @@
     matching "stage1" entry if it exists too.  .. all the normal
     trivial rules ..
 
-You would normally use `git-merge-index` with supplied
-`git-merge-one-file` to do this last step.  The script updates
+You would normally use 'git-merge-index' with supplied
+'git-merge-one-file' to do this last step.  The script updates
 the files in the working tree as it merges each path and at the
 end of a successful merge.
 
@@ -304,16 +313,16 @@
 committed last to your repository:
 
 ----------------
-$ JC=`git-rev-parse --verify "HEAD^0"`
-$ git-checkout-index -f -u -a $JC
+$ JC=`git rev-parse --verify "HEAD^0"`
+$ git checkout-index -f -u -a $JC
 ----------------
 
-You do random edits, without running git-update-index.  And then
+You do random edits, without running 'git-update-index'.  And then
 you notice that the tip of your "upstream" tree has advanced
 since you pulled from him:
 
 ----------------
-$ git-fetch git://.... linus
+$ git fetch git://.... linus
 $ LT=`cat .git/FETCH_HEAD`
 ----------------
 
@@ -323,10 +332,10 @@
 then does the right thing.  So with the following sequence:
 
 ----------------
-$ git-read-tree -m -u `git-merge-base $JC $LT` $JC $LT
-$ git-merge-index git-merge-one-file -a
+$ git read-tree -m -u `git merge-base $JC $LT` $JC $LT
+$ git merge-index git-merge-one-file -a
 $ echo "Merge with Linus" | \
-  git-commit-tree `git-write-tree` -p $JC -p $LT
+  git commit-tree `git write-tree` -p $JC -p $LT
 ----------------
 
 what you would commit is a pure merge between $JC and $LT without
@@ -334,14 +343,14 @@
 updated to the result of the merge.
 
 However, if you have local changes in the working tree that
-would be overwritten by this merge,`git-read-tree` will refuse
+would be overwritten by this merge, 'git-read-tree' will refuse
 to run to prevent your changes from being lost.
 
 In other words, there is no need to worry about what exists only
 in the working tree.  When you have local changes in a part of
 the project that is not involved in the merge, your changes do
 not interfere with the merge, and are kept intact.  When they
-*do* interfere, the merge does not even start (`git-read-tree`
+*do* interfere, the merge does not even start ('git-read-tree'
 complains loudly and fails without modifying anything).  In such
 a case, you can simply continue doing what you were in the
 middle of doing, and when your working tree is ready (i.e. you
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index b7e1da0..59c1b02 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -8,15 +8,15 @@
 SYNOPSIS
 --------
 [verse]
-'git-rebase' [-i | --interactive] [-v | --verbose] [-m | --merge]
+'git rebase' [-i | --interactive] [-v | --verbose] [-m | --merge]
 	[-s <strategy> | --strategy=<strategy>]
 	[-C<n>] [ --whitespace=<option>] [-p | --preserve-merges]
 	[--onto <newbase>] <upstream> [<branch>]
-'git-rebase' --continue | --skip | --abort
+'git rebase' --continue | --skip | --abort
 
 DESCRIPTION
 -----------
-If <branch> is specified, git-rebase will perform an automatic
+If <branch> is specified, 'git-rebase' will perform an automatic
 `git checkout <branch>` before doing anything else.  Otherwise
 it remains on the current branch.
 
@@ -26,7 +26,8 @@
 
 The current branch is reset to <upstream>, or <newbase> if the
 --onto option was supplied.  This has the exact same effect as
-`git reset --hard <upstream>` (or <newbase>).
+`git reset --hard <upstream>` (or <newbase>).  ORIG_HEAD is set
+to point at the tip of the branch before the reset.
 
 The commits that were previously saved into the temporary area are
 then reapplied to the current branch, one by one, in order. Note that
@@ -38,8 +39,8 @@
 completely automatic.  You will have to resolve any such merge failure
 and run `git rebase --continue`.  Another option is to bypass the commit
 that caused the merge failure with `git rebase --skip`.  To restore the
-original <branch> and remove the .dotest working files, use the command
-`git rebase --abort` instead.
+original <branch> and remove the .git/rebase-apply working files, use the
+command `git rebase --abort` instead.
 
 Assume the following history exists and the current branch is "topic":
 
@@ -52,8 +53,8 @@
 From this point, the result of either of the following commands:
 
 
-    git-rebase master
-    git-rebase master topic
+    git rebase master
+    git rebase master topic
 
 would be:
 
@@ -68,7 +69,7 @@
 
 If the upstream branch already contains a change you have made (e.g.,
 because you mailed a patch which was applied upstream), then that commit
-will be skipped. For example, running `git-rebase master` on the
+will be skipped. For example, running `git rebase master` on the
 following history (in which A' and A introduce the same set of changes,
 but have different committer information):
 
@@ -116,7 +117,7 @@
 
 We can get this using the following command:
 
-    git-rebase --onto master next topic
+    git rebase --onto master next topic
 
 
 Another example of --onto option is to rebase part of a
@@ -132,7 +133,7 @@
 
 then the command
 
-    git-rebase --onto master topicA topicB
+    git rebase --onto master topicA topicB
 
 would result in:
 
@@ -155,7 +156,7 @@
 
 then the command
 
-    git-rebase --onto topicA~5 topicA~3 topicA
+    git rebase --onto topicA~5 topicA~3 topicA
 
 would result in the removal of commits F and G:
 
@@ -167,8 +168,8 @@
 part of topicA.  Note that the argument to --onto and the <upstream>
 parameter can be any valid commit-ish.
 
-In case of conflict, git-rebase will stop at the first problematic commit
-and leave conflict markers in the tree.  You can use git diff to locate
+In case of conflict, 'git-rebase' will stop at the first problematic commit
+and leave conflict markers in the tree.  You can use 'git-diff' to locate
 the markers (<<<<<<) and make edits to resolve the conflict.  For each
 file you edit, you need to tell git that the conflict has been resolved,
 typically this would be done with
@@ -184,7 +185,7 @@
     git rebase --continue
 
 
-Alternatively, you can undo the git-rebase with
+Alternatively, you can undo the 'git-rebase' with
 
 
     git rebase --abort
@@ -224,8 +225,8 @@
 	Use the given merge strategy; can be supplied more than
 	once to specify them in the order they should be tried.
 	If there is no `-s` option, a built-in list of strategies
-	is used instead (`git-merge-recursive` when merging a single
-	head, `git-merge-octopus` otherwise).  This implies --merge.
+	is used instead ('git-merge-recursive' when merging a single
+	head, 'git-merge-octopus' otherwise).  This implies --merge.
 
 -v::
 --verbose::
@@ -238,7 +239,7 @@
 	ever ignored.
 
 --whitespace=<nowarn|warn|error|error-all|strip>::
-	This flag is passed to the `git-apply` program
+	This flag is passed to the 'git-apply' program
 	(see linkgit:git-apply[1]) that applies the patch.
 
 -i::
@@ -259,10 +260,10 @@
 When you rebase a branch, you are changing its history in a way that
 will cause problems for anyone who already has a copy of the branch
 in their repository and tries to pull updates from you.  You should
-understand the implications of using 'git rebase' on a repository that
+understand the implications of using 'git-rebase' on a repository that
 you share.
 
-When the git rebase command is run, it will first execute a "pre-rebase"
+When the git-rebase command is run, it will first execute a "pre-rebase"
 hook if one exists.  You can use this hook to do sanity checks and
 reject the rebase if it isn't appropriate.  Please see the template
 pre-rebase hook script for an example.
@@ -314,12 +315,12 @@
 ...
 -------------------------------------------
 
-The oneline descriptions are purely for your pleasure; `git-rebase` will
+The oneline descriptions are purely for your pleasure; 'git-rebase' will
 not look at them but at the commit names ("deadbee" and "fa1afe1" in this
 example), so do not delete or edit the names.
 
 By replacing the command "pick" with the command "edit", you can tell
-`git-rebase` to stop after applying that commit, so that you can edit
+'git-rebase' to stop after applying that commit, so that you can edit
 the files and/or the commit message, amend the commit, and continue
 rebasing.
 
@@ -334,7 +335,7 @@
 
 For example, if you want to reorder the last 5 commits, such that what
 was HEAD~4 becomes the new HEAD. To achieve that, you would call
-`git-rebase` like this:
+'git-rebase' like this:
 
 ----------------------
 $ git rebase -i HEAD~5
@@ -364,34 +365,34 @@
 -----------------
 
 In interactive mode, you can mark commits with the action "edit".  However,
-this does not necessarily mean that 'git rebase' expects the result of this
+this does not necessarily mean that 'git-rebase' expects the result of this
 edit to be exactly one commit.  Indeed, you can undo the commit, or you can
 add other commits.  This can be used to split a commit into two:
 
-- Start an interactive rebase with 'git rebase -i <commit>^', where
+- Start an interactive rebase with `git rebase -i <commit>^`, where
   <commit> is the commit you want to split.  In fact, any commit range
   will do, as long as it contains that commit.
 
 - Mark the commit you want to split with the action "edit".
 
-- When it comes to editing that commit, execute 'git reset HEAD^'.  The
+- When it comes to editing that commit, execute `git reset HEAD^`.  The
   effect is that the HEAD is rewound by one, and the index follows suit.
   However, the working tree stays the same.
 
 - Now add the changes to the index that you want to have in the first
-  commit.  You can use linkgit:git-add[1] (possibly interactively) and/or
-  linkgit:git-gui[1] to do that.
+  commit.  You can use `git add` (possibly interactively) or
+  'git-gui' (or both) to do that.
 
 - Commit the now-current index with whatever commit message is appropriate
   now.
 
 - Repeat the last two steps until your working tree is clean.
 
-- Continue the rebase with 'git rebase --continue'.
+- Continue the rebase with `git rebase --continue`.
 
 If you are not absolutely sure that the intermediate revisions are
 consistent (they compile, pass the testsuite, etc.) you should use
-linkgit:git-stash[1] to stash away the not-yet-committed changes
+'git-stash' to stash away the not-yet-committed changes
 after each commit, test, and amend the commit if fixes are necessary.
 
 
diff --git a/Documentation/git-receive-pack.txt b/Documentation/git-receive-pack.txt
index a70c716..514f03c 100644
--- a/Documentation/git-receive-pack.txt
+++ b/Documentation/git-receive-pack.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-receive-pack' <directory>
+'git receive-pack' <directory>
 
 DESCRIPTION
 -----------
@@ -18,17 +18,17 @@
 This command is usually not invoked directly by the end user.
 The UI for the protocol is on the 'git-send-pack' side, and the
 program pair is meant to be used to push updates to remote
-repository.  For pull operations, see 'git-fetch-pack'.
+repository.  For pull operations, see linkgit:git-fetch-pack[1].
 
 The command allows for creation and fast forwarding of sha1 refs
 (heads/tags) on the remote end (strictly speaking, it is the
-local end receive-pack runs, but to the user who is sitting at
+local end 'git-receive-pack' runs, but to the user who is sitting at
 the send-pack end, it is updating the remote.  Confused?)
 
 There are other real-world examples of using update and
 post-update hooks found in the Documentation/howto directory.
 
-git-receive-pack honours the receive.denyNonFastForwards config
+'git-receive-pack' honours the receive.denyNonFastForwards config
 option, which tells it if updates to a ref should be denied if they
 are not fast-forwards.
 
@@ -86,7 +86,7 @@
 -----------------
 After all refs were updated (or attempted to be updated), if any
 ref update was successful, and if $GIT_DIR/hooks/post-receive
-file exists and is executable, it will be invoke once with no
+file exists and is executable, it will be invoked once with no
 parameters.  The standard input of the hook will be one line
 for each successfully updated ref:
 
@@ -111,10 +111,10 @@
 		if expr "$oval" : '0*$' >/dev/null
 		then
 			echo "Created a new ref, with the following commits:"
-			git-rev-list --pretty "$nval"
+			git rev-list --pretty "$nval"
 		else
 			echo "New commits:"
-			git-rev-list --pretty "$nval" "^$oval"
+			git rev-list --pretty "$nval" "^$oval"
 		fi |
 		mail -s "Changes to ref $ref" commit-list@mydomain
 	done
@@ -125,7 +125,7 @@
 
 Note that it is possible for refname to not have sha1-new when this
 hook runs.  This can easily occur if another user modifies the ref
-after it was updated by receive-pack, but before the hook was able
+after it was updated by 'git-receive-pack', but before the hook was able
 to evaluate it.  It is recommended that hooks rely on sha1-new
 rather than the current value of refname.
 
@@ -133,18 +133,18 @@
 ----------------
 After all other processing, if at least one ref was updated, and
 if $GIT_DIR/hooks/post-update file exists and is executable, then
-post-update will called with the list of refs that have been updated.
+post-update will be called with the list of refs that have been updated.
 This can be used to implement any repository wide cleanup tasks.
 
 The exit code from this hook invocation is ignored; the only thing
-left for git-receive-pack to do at that point is to exit itself
+left for 'git-receive-pack' to do at that point is to exit itself
 anyway.
 
-This hook can be used, for example, to run "git-update-server-info"
+This hook can be used, for example, to run `git update-server-info`
 if the repository is packed and is served via a dumb transport.
 
 	#!/bin/sh
-	exec git-update-server-info
+	exec git update-server-info
 
 
 SEE ALSO
diff --git a/Documentation/git-reflog.txt b/Documentation/git-reflog.txt
index c9c25f3..7f7a544 100644
--- a/Documentation/git-reflog.txt
+++ b/Documentation/git-reflog.txt
@@ -16,19 +16,19 @@
 depending on the subcommand:
 
 [verse]
-git reflog expire [--dry-run] [--stale-fix] [--verbose]
+'git reflog expire' [--dry-run] [--stale-fix] [--verbose]
 	[--expire=<time>] [--expire-unreachable=<time>] [--all] <refs>...
-
-git reflog delete ref@\{specifier\}...
-
-git reflog [show] [log-options] [<ref>]
++
+'git reflog delete' ref@\{specifier\}...
++
+'git reflog' ['show'] [log-options] [<ref>]
 
 Reflog is a mechanism to record when the tip of branches are
 updated.  This command is to manage the information recorded in it.
 
 The subcommand "expire" is used to prune older reflog entries.
 Entries older than `expire` time, or entries older than
-`expire-unreachable` time and are not reachable from the current
+`expire-unreachable` time and not reachable from the current
 tip, are removed from the reflog.  This is typically not used
 directly by the end users -- instead, see linkgit:git-gc[1].
 
@@ -36,7 +36,7 @@
 subcommands) will take all the normal log options, and show the log of
 the reference provided in the command-line (or `HEAD`, by default).
 The reflog will cover all recent actions (HEAD reflog records branch switching
-as well).  It is an alias for 'git log -g --abbrev-commit --pretty=oneline';
+as well).  It is an alias for `git log -g --abbrev-commit --pretty=oneline`;
 see linkgit:git-log[1].
 
 The reflog is useful in various git commands, to specify the old value
@@ -46,7 +46,7 @@
 more details.
 
 To delete single entries from the reflog, use the subcommand "delete"
-and specify the _exact_ entry (e.g. ``git reflog delete master@\{2\}'').
+and specify the _exact_ entry (e.g. "`git reflog delete master@\{2\}`").
 
 
 OPTIONS
@@ -60,7 +60,7 @@
 	refs.
 +
 This computation involves traversing all the reachable objects, i.e. it
-has the same cost as 'git prune'.  Fortunately, once this is run, we
+has the same cost as 'git-prune'.  Fortunately, once this is run, we
 should not have to ever worry about missing objects, because the current
 prune and pack-objects know about reflogs and protect objects referred by
 them.
@@ -71,7 +71,7 @@
 	which in turn defaults to 90 days.
 
 --expire-unreachable=<time>::
-	Entries older than this time and are not reachable from
+	Entries older than this time and not reachable from
 	the current tip of the branch are pruned.  Without the
 	option it is taken from configuration
 	`gc.reflogExpireUnreachable`, which in turn defaults to
diff --git a/Documentation/git-relink.txt b/Documentation/git-relink.txt
index f6dafd4..25ff8f9 100644
--- a/Documentation/git-relink.txt
+++ b/Documentation/git-relink.txt
@@ -7,7 +7,7 @@
 
 SYNOPSIS
 --------
-'git-relink' [--safe] <dir> [<dir>]\* <master_dir>
+'git relink' [--safe] <dir> [<dir>]\* <master_dir>
 
 DESCRIPTION
 -----------
diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt
index 345943a..bb99810 100644
--- a/Documentation/git-remote.txt
+++ b/Documentation/git-remote.txt
@@ -9,12 +9,12 @@
 SYNOPSIS
 --------
 [verse]
-'git-remote' [-v | --verbose]
-'git-remote' add [-t <branch>] [-m <master>] [-f] [--mirror] <name> <url>
-'git-remote' rm <name>
-'git-remote' show [-n] <name>
-'git-remote' prune [-n | --dry-run] <name>
-'git-remote' update [group]
+'git remote' [-v | --verbose]
+'git remote add' [-t <branch>] [-m <master>] [-f] [--mirror] <name> <url>
+'git remote rm' <name>
+'git remote show' [-n] <name>
+'git remote prune' [-n | --dry-run] <name>
+'git remote update' [group]
 
 DESCRIPTION
 -----------
@@ -124,7 +124,7 @@
 ...
 ------------
 
-* Imitate 'git clone' but track only selected branches
+* Imitate 'git-clone' but track only selected branches
 +
 ------------
 $ mkdir project.git
diff --git a/Documentation/git-repack.txt b/Documentation/git-repack.txt
index 04d6f1f..aaa8852 100644
--- a/Documentation/git-repack.txt
+++ b/Documentation/git-repack.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-repack' [-a] [-A] [-d] [-f] [-l] [-n] [-q] [--window=N] [--depth=N]
+'git repack' [-a] [-A] [-d] [-f] [-l] [-n] [-q] [--window=N] [--depth=N]
 
 DESCRIPTION
 -----------
@@ -38,40 +38,40 @@
 	dangling.
 
 -A::
-	Same as `-a`, but any unreachable objects in a previous
-	pack become loose, unpacked objects, instead of being
-	left in the old pack.  Unreachable objects are never
-	intentionally added to a pack, even when repacking.
-	When used with '-d', this option
-	prevents unreachable objects from being immediately
+	Same as `-a`, unless '-d' is used.  Then any unreachable
+	objects in a previous pack become loose, unpacked objects,
+	instead of being left in the old pack.  Unreachable objects
+	are never intentionally added to a pack, even when repacking.
+	This option prevents unreachable objects from being immediately
 	deleted by way of being left in the old pack and then
 	removed.  Instead, the loose unreachable objects
 	will be pruned according to normal expiry rules
-	with the next linkgit:git-gc[1].
+	with the next 'git-gc' invocation. See linkgit:git-gc[1].
 
 -d::
 	After packing, if the newly created packs make some
 	existing packs redundant, remove the redundant packs.
-	Also runs linkgit:git-prune-packed[1].
+	Also run  'git-prune-packed' to remove redundant
+	loose object files.
 
 -l::
-        Pass the `--local` option to `git pack-objects`, see
+	Pass the `--local` option to 'git-pack-objects'. See
 	linkgit:git-pack-objects[1].
 
 -f::
-        Pass the `--no-reuse-delta` option to `git pack-objects`, see
+	Pass the `--no-reuse-object` option to `git-pack-objects`, see
 	linkgit:git-pack-objects[1].
 
 -q::
-        Pass the `-q` option to `git pack-objects`, see
+	Pass the `-q` option to 'git-pack-objects'. See
 	linkgit:git-pack-objects[1].
 
 -n::
 	Do not update the server information with
-	`git update-server-info`.  This option skips
+	'git-update-server-info'.  This option skips
 	updating local catalog files needed to publish
 	this repository (or a direct copy of it)
-	over HTTP or FTP.  See gitlink:git-update-server-info[1].
+	over HTTP or FTP.  See linkgit:git-update-server-info[1].
 
 --window=[N]::
 --depth=[N]::
@@ -106,7 +106,7 @@
 
 When configuration variable `repack.UseDeltaBaseOffset` is set
 for the repository, the command passes `--delta-base-offset`
-option to `git-pack-objects`; this typically results in slightly
+option to 'git-pack-objects'; this typically results in slightly
 smaller packs, but the generated packs are incompatible with
 versions of git older than (and including) v1.4.3; do not set
 the variable in a repository that older version of git needs to
diff --git a/Documentation/git-repo-config.txt b/Documentation/git-repo-config.txt
index 2ca3994..e5bdb55 100644
--- a/Documentation/git-repo-config.txt
+++ b/Documentation/git-repo-config.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-repo-config' ...
+'git repo-config' ...
 
 
 DESCRIPTION
diff --git a/Documentation/git-request-pull.txt b/Documentation/git-request-pull.txt
index 70810c0..19335fd 100644
--- a/Documentation/git-request-pull.txt
+++ b/Documentation/git-request-pull.txt
@@ -7,7 +7,7 @@
 
 SYNOPSIS
 --------
-'git-request-pull' <start> <url> [<end>]
+'git request-pull' <start> <url> [<end>]
 
 DESCRIPTION
 -----------
diff --git a/Documentation/git-rerere.txt b/Documentation/git-rerere.txt
index 8f12dc9..64715c1 100644
--- a/Documentation/git-rerere.txt
+++ b/Documentation/git-rerere.txt
@@ -7,7 +7,7 @@
 
 SYNOPSIS
 --------
-'git-rerere' [clear|diff|status|gc]
+'git rerere' ['clear'|'diff'|'status'|'gc']
 
 DESCRIPTION
 -----------
@@ -30,26 +30,26 @@
 COMMANDS
 --------
 
-Normally, git-rerere is run without arguments or user-intervention.
+Normally, 'git-rerere' is run without arguments or user-intervention.
 However, it has several commands that allow it to interact with
 its working state.
 
 'clear'::
 
 This resets the metadata used by rerere if a merge resolution is to be
-is aborted.  Calling linkgit:git-am[1] --skip or linkgit:git-rebase[1]
-[--skip|--abort] will automatically invoke this command.
+aborted.  Calling 'git-am [--skip|--abort]' or 'git-rebase [--skip|--abort]'
+will automatically invoke this command.
 
 'diff'::
 
 This displays diffs for the current state of the resolution.  It is
 useful for tracking what has changed while the user is resolving
 conflicts.  Additional arguments are passed directly to the system
-diff(1) command installed in PATH.
+'diff' command installed in PATH.
 
 'status'::
 
-Like diff, but this only prints the filenames that will be tracked
+Like 'diff', but this only prints the filenames that will be tracked
 for resolutions.
 
 'gc'::
@@ -142,33 +142,33 @@
 would require you to resolve the conflict, introduced by the
 commits marked with `*`.  However, often this conflict is the
 same conflict you resolved when you created the test merge you
-blew away.  `git-rerere` command helps you to resolve this final
+blew away.  'git-rerere' command helps you to resolve this final
 conflicted merge using the information from your earlier hand
 resolve.
 
-Running `git-rerere` command immediately after a conflicted
+Running the 'git-rerere' command immediately after a conflicted
 automerge records the conflicted working tree files, with the
 usual conflict markers `<<<<<<<`, `=======`, and `>>>>>>>` in
 them.  Later, after you are done resolving the conflicts,
-running `git-rerere` again records the resolved state of these
+running 'git-rerere' again records the resolved state of these
 files.  Suppose you did this when you created the test merge of
 master into the topic branch.
 
-Next time, running `git-rerere` after seeing a conflicted
+Next time, running 'git-rerere' after seeing a conflicted
 automerge, if the conflict is the same as the earlier one
 recorded, it is noticed and a three-way merge between the
 earlier conflicted automerge, the earlier manual resolution, and
 the current conflicted automerge is performed by the command.
 If this three-way merge resolves cleanly, the result is written
 out to your working tree file, so you would not have to manually
-resolve it.  Note that `git-rerere` leaves the index file alone,
+resolve it.  Note that 'git-rerere' leaves the index file alone,
 so you still need to do the final sanity checks with `git diff`
-(or `git diff -c`) and `git add` when you are satisfied.
+(or `git diff -c`) and 'git-add' when you are satisfied.
 
-As a convenience measure, `git-merge` automatically invokes
-`git-rerere` when it exits with a failed automerge, which
+As a convenience measure, 'git-merge' automatically invokes
+'git-rerere' when it exits with a failed automerge, which
 records it if it is a new conflict, or reuses the earlier hand
-resolve when it is not.  `git-commit` also invokes `git-rerere`
+resolve when it is not.  'git-commit' also invokes 'git-rerere'
 when recording a merge result.  What this means is that you do
 not have to do anything special yourself (Note: you still have
 to set the config variable rerere.enabled to enable this command).
@@ -178,8 +178,8 @@
 actual merge later with updated master and topic branch, as long
 as the earlier resolution is still applicable.
 
-The information `git-rerere` records is also used when running
-`git-rebase`.  After blowing away the test merge and continuing
+The information 'git-rerere' records is also used when running
+'git-rebase'.  After blowing away the test merge and continuing
 development on the topic branch:
 
 ------------
@@ -198,7 +198,7 @@
 up-to-date even before your topic is ready to be sent upstream.
 This would result in falling back to three-way merge, and it
 would conflict the same way the test merge you resolved earlier.
-`git-rerere` is run by `git rebase` to help you resolve this
+'git-rerere' is run by 'git-rebase' to help you resolve this
 conflict.
 
 
diff --git a/Documentation/git-reset.txt b/Documentation/git-reset.txt
index 0b368b3..6abaeac 100644
--- a/Documentation/git-reset.txt
+++ b/Documentation/git-reset.txt
@@ -37,7 +37,7 @@
 --soft::
 	Does not touch the index file nor the working tree at all, but
 	requires them to be in a good order. This leaves all your changed
-	files "Changes to be committed", as linkgit:git-status[1] would
+	files "Changes to be committed", as 'git-status' would
 	put it.
 
 --hard::
diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt
index c9b0950..1c9cc28 100644
--- a/Documentation/git-rev-list.txt
+++ b/Documentation/git-rev-list.txt
@@ -32,9 +32,9 @@
 	     [ \--cherry-pick ]
 	     [ \--encoding[=<encoding>] ]
 	     [ \--(author|committer|grep)=<pattern> ]
-	     [ \--regexp-ignore-case | \-i ]
-	     [ \--extended-regexp | \-E ]
-	     [ \--fixed-strings | \-F ]
+	     [ \--regexp-ignore-case | -i ]
+	     [ \--extended-regexp | -E ]
+	     [ \--fixed-strings | -F ]
 	     [ \--date={local|relative|default|iso|rfc|short} ]
 	     [ [\--objects | \--objects-edge] [ \--unpacked ] ]
 	     [ \--pretty | \--header ]
@@ -59,7 +59,7 @@
 command:
 
 -----------------------------------------------------------------------
-	$ git-rev-list foo bar ^baz
+	$ git rev-list foo bar ^baz
 -----------------------------------------------------------------------
 
 means "list all the commits which are included in 'foo' and 'bar', but
@@ -70,8 +70,8 @@
 the following may be used interchangeably:
 
 -----------------------------------------------------------------------
-	$ git-rev-list origin..HEAD
-	$ git-rev-list HEAD ^origin
+	$ git rev-list origin..HEAD
+	$ git rev-list HEAD ^origin
 -----------------------------------------------------------------------
 
 Another special notation is "'<commit1>'...'<commit2>'" which is useful
@@ -79,15 +79,15 @@
 between the two operands.  The following two commands are equivalent:
 
 -----------------------------------------------------------------------
-	$ git-rev-list A B --not $(git-merge-base --all A B)
-	$ git-rev-list A...B
+	$ git rev-list A B --not $(git merge-base --all A B)
+	$ git rev-list A...B
 -----------------------------------------------------------------------
 
-linkgit:git-rev-list[1] is a very essential git program, since it
+'git-rev-list' is a very essential git program, since it
 provides the ability to build and traverse commit ancestry graphs. For
 this reason, it has a lot of different options that enables it to be
-used by commands as different as linkgit:git-bisect[1] and
-linkgit:git-repack[1].
+used by commands as different as 'git-bisect' and
+'git-repack'.
 
 OPTIONS
 -------
diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt
index 9082fc9..2921da3 100644
--- a/Documentation/git-rev-parse.txt
+++ b/Documentation/git-rev-parse.txt
@@ -8,23 +8,23 @@
 
 SYNOPSIS
 --------
-'git-rev-parse' [ --option ] <args>...
+'git rev-parse' [ --option ] <args>...
 
 DESCRIPTION
 -----------
 
 Many git porcelainish commands take mixture of flags
 (i.e. parameters that begin with a dash '-') and parameters
-meant for underlying `git-rev-list` command they use internally
-and flags and parameters for other commands they use as the
-downstream of `git-rev-list`.  This command is used to
+meant for the underlying 'git-rev-list' command they use internally
+and flags and parameters for the other commands they use
+downstream of 'git-rev-list'.  This command is used to
 distinguish between them.
 
 
 OPTIONS
 -------
 --parseopt::
-	Use `git-rev-parse` in option parsing mode (see PARSEOPT section below).
+	Use 'git-rev-parse' in option parsing mode (see PARSEOPT section below).
 
 --keep-dash-dash::
 	Only meaningful in `--parseopt` mode. Tells the option parser to echo
@@ -32,11 +32,11 @@
 
 --revs-only::
 	Do not output flags and parameters not meant for
-	`git-rev-list` command.
+	'git-rev-list' command.
 
 --no-revs::
 	Do not output flags and parameters meant for
-	`git-rev-list` command.
+	'git-rev-list' command.
 
 --flags::
 	Do not output non-flag parameters.
@@ -64,7 +64,7 @@
 	properly quoted for consumption by shell.  Useful when
 	you expect your parameter to contain whitespaces and
 	newlines (e.g. when using pickaxe `-S` with
-	`git-diff-\*`).
+	'git-diff-\*').
 
 --not::
 	When showing object names, prefix them with '{caret}' and
@@ -128,13 +128,13 @@
 
 --since=datestring::
 --after=datestring::
-	Parses the date string, and outputs corresponding
-	--max-age= parameter for git-rev-list command.
+	Parse the date string, and output the corresponding
+	--max-age= parameter for 'git-rev-list'.
 
 --until=datestring::
 --before=datestring::
-	Parses the date string, and outputs corresponding
-	--min-age= parameter for git-rev-list command.
+	Parse the date string, and output the corresponding
+	--min-age= parameter for 'git-rev-list'.
 
 <args>...::
 	Flags and parameters to be parsed.
@@ -155,8 +155,9 @@
   name the same commit object if there are no other object in
   your repository whose object name starts with dae86e.
 
-* An output from `git-describe`; i.e. a closest tag, followed by a
-  dash, a `g`, and an abbreviated object name.
+* An output from 'git-describe'; i.e. a closest tag, optionally
+  followed by a dash and a number of commits, followed by a dash, a
+  `g`, and an abbreviated object name.
 
 * A symbolic ref name.  E.g. 'master' typically means the commit
   object referenced by $GIT_DIR/refs/heads/master.  If you
@@ -166,7 +167,7 @@
   first match in the following rules:
 
   . if `$GIT_DIR/<name>` exists, that is what you mean (this is usually
-    useful only for `HEAD`, `FETCH_HEAD` and `MERGE_HEAD`);
+    useful only for `HEAD`, `FETCH_HEAD`, `ORIG_HEAD` and `MERGE_HEAD`);
 
   . otherwise, `$GIT_DIR/refs/<name>` if exists;
 
@@ -177,6 +178,16 @@
   . otherwise, `$GIT_DIR/refs/remotes/<name>` if exists;
 
   . otherwise, `$GIT_DIR/refs/remotes/<name>/HEAD` if exists.
++
+HEAD names the commit your changes in the working tree is based on.
+FETCH_HEAD records the branch you fetched from a remote repository
+with your last 'git-fetch' invocation.
+ORIG_HEAD is created by commands that moves your HEAD in a drastic
+way, to record the position of the HEAD before their operation, so that
+you can change the tip of the branch back to the state before you ran
+them easily.
+MERGE_HEAD records the commit(s) you are merging into your branch
+when you run 'git-merge'.
 
 * A ref followed by the suffix '@' with a date specification
   enclosed in a brace
@@ -278,7 +289,7 @@
 SPECIFYING RANGES
 -----------------
 
-History traversing commands such as `git-log` operate on a set
+History traversing commands such as 'git-log' operate on a set
 of commits, not just a single commit.  To these commands,
 specifying a single revision with the notation described in the
 previous section means the set of commits reachable from that
@@ -289,14 +300,14 @@
 from `r2` but exclude the ones reachable from `r1`.
 
 This set operation appears so often that there is a shorthand
-for it.  "`r1..r2`" is equivalent to "`{caret}r1 r2`".  It is
-the difference of two sets (subtract the set of commits
-reachable from `r1` from the set of commits reachable from
-`r2`).
+for it.  When you have two commits `r1` and `r2` (named according
+to the syntax explained in SPECIFYING REVISIONS above), you can ask
+for commits that are reachable from r2 excluding those that are reachable
+from r1 by "`{caret}r1 r2`" and it can be written as "`r1..r2`".
 
 A similar notation "`r1\...r2`" is called symmetric difference
 of `r1` and `r2` and is defined as
-"`r1 r2 --not $(git-merge-base --all r1 r2)`".
+"`r1 r2 --not $(git merge-base --all r1 r2)`".
 It is the set of commits that are reachable from either one of
 `r1` or `r2` but not from both.
 
@@ -319,7 +330,7 @@
 PARSEOPT
 --------
 
-In `--parseopt` mode, `git-rev-parse` helps massaging options to bring to shell
+In `--parseopt` mode, 'git-rev-parse' helps massaging options to bring to shell
 scripts the same facilities C builtins have. It works as an option normalizer
 (e.g. splits single switches aggregate values), a bit like `getopt(1)` does.
 
@@ -331,7 +342,7 @@
 Input Format
 ~~~~~~~~~~~~
 
-`git-rev-parse --parseopt` input format is fully text based. It has two parts,
+'git-rev-parse --parseopt' input format is fully text based. It has two parts,
 separated by a line that contains only `--`. The lines before the separator
 (should be more than one) are used for the usage.
 The lines after the separator describe the options.
@@ -384,7 +395,7 @@
   An option group Header
 C?        option C with an optional argument"
 
-eval `echo "$OPTS_SPEC" | git-rev-parse --parseopt -- "$@" || echo exit $?`
+eval `echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?`
 ------------
 
 EXAMPLES
diff --git a/Documentation/git-revert.txt b/Documentation/git-revert.txt
index 5fdeaff..caa0729 100644
--- a/Documentation/git-revert.txt
+++ b/Documentation/git-revert.txt
@@ -7,7 +7,7 @@
 
 SYNOPSIS
 --------
-'git-revert' [--edit | --no-edit] [-n] [-m parent-number] [-s] <commit>
+'git revert' [--edit | --no-edit] [-n] [-m parent-number] [-s] <commit>
 
 DESCRIPTION
 -----------
@@ -15,6 +15,15 @@
 new commit that records it.  This requires your working tree to be clean (no
 modifications from the HEAD commit).
 
+Note: 'git revert' is used to record a new commit to reverse the
+effect of an earlier commit (often a faulty one).  If you want to
+throw away all uncommitted changes in your working directory, you
+should see linkgit:git-reset[1], particularly the '--hard' option.  If
+you want to extract specific files as they were in another commit, you
+should see linkgit:git-checkout[1], specifically the 'git checkout
+<commit> -- <filename>' syntax.  Take care with these alternatives as
+both will discard uncommitted changes in your working directory.
+
 OPTIONS
 -------
 <commit>::
@@ -24,7 +33,7 @@
 
 -e::
 --edit::
-	With this option, `git-revert` will let you edit the commit
+	With this option, 'git-revert' will let you edit the commit
 	message prior to committing the revert. This is the default if
 	you run the command from a terminal.
 
@@ -37,7 +46,7 @@
 	relative to the specified parent.
 
 --no-edit::
-	With this option, `git-revert` will not start the commit
+	With this option, 'git-revert' will not start the commit
 	message editor.
 
 -n::
diff --git a/Documentation/git-rm.txt b/Documentation/git-rm.txt
index d88554b..5afb1e7 100644
--- a/Documentation/git-rm.txt
+++ b/Documentation/git-rm.txt
@@ -7,12 +7,12 @@
 
 SYNOPSIS
 --------
-'git-rm' [-f] [-n] [-r] [--cached] [--ignore-unmatch] [--quiet] [--] <file>...
+'git rm' [-f | --force] [-n] [-r] [--cached] [--ignore-unmatch] [--quiet] [--] <file>...
 
 DESCRIPTION
 -----------
 Remove files from the index, or from the working tree and the index.
-`git rm` will not remove a file from just your working directory.
+'git-rm' will not remove a file from just your working directory.
 (There is no option to remove a file only from the work tree
 and yet keep it in the index; use `/bin/rm` if you want to do that.)
 The files being removed have to be identical to the tip of the branch,
@@ -36,6 +36,7 @@
 	but this requires the `-r` option to be explicitly given.
 
 -f::
+--force::
 	Override the up-to-date check.
 
 -n::
@@ -63,7 +64,7 @@
 
 -q::
 --quiet::
-	git-rm normally outputs one line (in the form of an "rm" command)
+	'git-rm' normally outputs one line (in the form of an "rm" command)
 	for each file removed. This option suppresses that output.
 
 
@@ -82,7 +83,7 @@
 
 EXAMPLES
 --------
-git-rm Documentation/\\*.txt::
+git rm Documentation/\\*.txt::
 	Removes all `\*.txt` files from the index that are under the
 	`Documentation` directory and any of its subdirectories.
 +
@@ -90,7 +91,7 @@
 example; this lets git, and not the shell, expand the pathnames
 of files and subdirectories under the `Documentation/` directory.
 
-git-rm -f git-*.sh::
+git rm -f git-*.sh::
 	Because this example lets the shell expand the asterisk
 	(i.e. you are listing the files explicitly), it
 	does not remove `subdir/git-foo.sh`.
diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt
index 251d661..3c3e1b0 100644
--- a/Documentation/git-send-email.txt
+++ b/Documentation/git-send-email.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-send-email' [options] <file|directory> [... file|directory]
+'git send-email' [options] <file|directory> [... file|directory]
 
 
 
@@ -56,7 +56,7 @@
 
 --from::
 	Specify the sender of the emails.  This will default to
-	the value GIT_COMMITTER_IDENT, as returned by "git-var -l".
+	the value GIT_COMMITTER_IDENT, as returned by "git var -l".
 	The user will still be prompted to confirm this entry.
 
 --in-reply-to::
@@ -133,10 +133,13 @@
 specified (with --smtp-pass or a configuration variable), then the
 user is prompted for a password while the input is masked for privacy.
 
+--smtp-encryption::
+	Specify the encryption to use, either 'ssl' or 'tls'.  Any other
+	value reverts to plain SMTP.  Default is the value of
+	'sendemail.smtpencryption'.
+
 --smtp-ssl::
-	If set, connects to the SMTP server using SSL.
-	Default is the value of the 'sendemail.smtpssl' configuration value;
-	if that is unspecified, does not use SSL.
+	Legacy alias for '--smtp-encryption=ssl'.
 
 --subject::
 	Specify the initial subject of the email thread.
@@ -176,6 +179,9 @@
 	This is useful if your default address is not the address that is
 	subscribed to a list. If you use the sendmail binary, you must have
 	suitable privileges for the -f parameter.
+	Default is the value of the 'sendemail.envelopesender' configuration
+	variable; if that is unspecified, choosing the envelope sender is left
+	to your MTA.
 
 --to::
 	Specify the primary recipient of the emails generated.
@@ -229,8 +235,13 @@
 sendemail.smtppass::
 	Default SMTP-AUTH password.
 
+sendemail.smtpencryption::
+	Default encryption method.  Use 'ssl' for SSL (and specify an
+	appropriate port), or 'tls' for TLS.  Takes precedence over
+	'smtpssl' if both are specified.
+
 sendemail.smtpssl::
-	Boolean value specifying the default to the '--smtp-ssl' parameter.
+	Legacy boolean that sets 'smtpencryption=ssl' if enabled.
 
 Author
 ------
diff --git a/Documentation/git-send-pack.txt b/Documentation/git-send-pack.txt
index ba2fdae..3998218 100644
--- a/Documentation/git-send-pack.txt
+++ b/Documentation/git-send-pack.txt
@@ -8,12 +8,12 @@
 
 SYNOPSIS
 --------
-'git-send-pack' [--all] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]
+'git send-pack' [--all] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]
 
 DESCRIPTION
 -----------
-Usually you would want to use linkgit:git-push[1] which is a
-higher level wrapper of this command instead.
+Usually you would want to use 'git-push', which is a
+higher-level wrapper of this command, instead. See linkgit:git-push[1].
 
 Invokes 'git-receive-pack' on a possibly remote repository, and
 updates it from the current repository, sending named refs.
@@ -86,8 +86,8 @@
 pushed is determined by finding a match that matches the source
 side, and where it is pushed is determined by using the
 destination side. The rules used to match a ref are the same
-rules used by linkgit:git-rev-parse[1] to resolve a symbolic ref
-name.
+rules used by 'git-rev-parse' to resolve a symbolic ref
+name. See linkgit:git-rev-parse[1].
 
  - It is an error if <src> does not match exactly one of the
    local refs.
diff --git a/Documentation/git-sh-setup.txt b/Documentation/git-sh-setup.txt
index c543170..18f14b5 100644
--- a/Documentation/git-sh-setup.txt
+++ b/Documentation/git-sh-setup.txt
@@ -7,7 +7,7 @@
 
 SYNOPSIS
 --------
-'git-sh-setup'
+'. "$(git --exec-path)/git-sh-setup"'
 
 DESCRIPTION
 -----------
@@ -16,7 +16,7 @@
 This documentation is meant for people who are studying the
 Porcelain-ish scripts and/or are writing new ones.
 
-The `git-sh-setup` scriptlet is designed to be sourced (using
+The 'git-sh-setup' scriptlet is designed to be sourced (using
 `.`) by other shell scripts to set up some variables pointing at
 the normal git directories and a few helper shell functions.
 
diff --git a/Documentation/git-shell.txt b/Documentation/git-shell.txt
index bd09196..ff420f8 100644
--- a/Documentation/git-shell.txt
+++ b/Documentation/git-shell.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-shell' -c <command> <argument>
+'$(git --exec-path)/git-shell' -c <command> <argument>
 
 DESCRIPTION
 -----------
@@ -18,7 +18,7 @@
 The commands can be executed only by the '-c' option; the shell is not
 interactive.
 
-Currently, only the `git-receive-pack` and `git-upload-pack` commands
+Currently, only the 'git-receive-pack' and 'git-upload-pack' commands
 are permitted to be called, with a single required argument.
 
 Author
diff --git a/Documentation/git-shortlog.txt b/Documentation/git-shortlog.txt
index daa64d4..7ccf31c 100644
--- a/Documentation/git-shortlog.txt
+++ b/Documentation/git-shortlog.txt
@@ -3,17 +3,17 @@
 
 NAME
 ----
-git-shortlog - Summarize 'git log' output
+git-shortlog - Summarize 'git-log' output
 
 SYNOPSIS
 --------
 [verse]
-git-log --pretty=short | 'git-shortlog' [-h] [-n] [-s] [-e] [-w]
-git-shortlog [-n|--numbered] [-s|--summary] [-e|--email] [-w[<width>[,<indent1>[,<indent2>]]]] [<committish>...]
+git log --pretty=short | 'git shortlog' [-h] [-n] [-s] [-e] [-w]
+git shortlog [-n|--numbered] [-s|--summary] [-e|--email] [-w[<width>[,<indent1>[,<indent2>]]]] [<committish>...]
 
 DESCRIPTION
 -----------
-Summarizes 'git log' output in a format suitable for inclusion
+Summarizes 'git-log' output in a format suitable for inclusion
 in release announcements. Each commit will be grouped by author and
 the first line of the commit message will be shown.
 
diff --git a/Documentation/git-show-branch.txt b/Documentation/git-show-branch.txt
index 6f4a2c4..fb269ff 100644
--- a/Documentation/git-show-branch.txt
+++ b/Documentation/git-show-branch.txt
@@ -8,10 +8,10 @@
 SYNOPSIS
 --------
 [verse]
-'git-show-branch' [--all] [--remotes] [--topo-order] [--current]
+'git show-branch' [--all] [--remotes] [--topo-order] [--current]
 		[--more=<n> | --list | --independent | --merge-base]
 		[--no-name | --sha1-name] [--topics] [<rev> | <glob>]...
-'git-show-branch' (-g|--reflog)[=<n>[,<base>]] [--list] [<ref>]
+'git show-branch' (-g|--reflog)[=<n>[,<base>]] [--list] [<ref>]
 
 DESCRIPTION
 -----------
@@ -29,8 +29,8 @@
 OPTIONS
 -------
 <rev>::
-	Arbitrary extended SHA1 expression (see `git-rev-parse`)
-	that typically names a branch HEAD or a tag.
+	Arbitrary extended SHA1 expression (see linkgit:git-rev-parse[1])
+	that typically names a branch head or a tag.
 
 <glob>::
 	A glob pattern that matches branch or tag names under
diff --git a/Documentation/git-show-index.txt b/Documentation/git-show-index.txt
index 891f0ef..e3285aa 100644
--- a/Documentation/git-show-index.txt
+++ b/Documentation/git-show-index.txt
@@ -8,13 +8,13 @@
 
 SYNOPSIS
 --------
-'git-show-index' < idx-file
+'git show-index' < idx-file
 
 
 DESCRIPTION
 -----------
 Reads given idx file for packed git archive created with
-git-pack-objects command, and dumps its contents.
+'git-pack-objects' command, and dumps its contents.
 
 The information it outputs is subset of what you can get from
 'git-verify-pack -v'; this command only shows the packfile
diff --git a/Documentation/git-show-ref.txt b/Documentation/git-show-ref.txt
index 6b99529..2f173ff 100644
--- a/Documentation/git-show-ref.txt
+++ b/Documentation/git-show-ref.txt
@@ -8,9 +8,9 @@
 SYNOPSIS
 --------
 [verse]
-'git-show-ref' [-q|--quiet] [--verify] [-h|--head] [-d|--dereference]
+'git show-ref' [-q|--quiet] [--verify] [-h|--head] [-d|--dereference]
 	     [-s|--hash] [--abbrev] [--tags] [--heads] [--] <pattern>...
-'git-show-ref' --exclude-existing[=pattern]
+'git show-ref' --exclude-existing[=pattern]
 
 DESCRIPTION
 -----------
@@ -74,7 +74,7 @@
 --exclude-existing::
 --exclude-existing=pattern::
 
-	Make git-show-ref act as a filter that reads refs from stdin of the
+	Make 'git-show-ref' act as a filter that reads refs from stdin of the
 	form "^(?:<anything>\s)?<refname>(?:\^\{\})?$" and performs the
 	following actions on each:
 	(1) strip "^{}" at the end of line if any;
@@ -84,7 +84,7 @@
 	(5) otherwise output the line.
 
 
-<pattern>::
+<pattern>...::
 
 	Show references matching one or more patterns.
 
@@ -137,14 +137,14 @@
 
 will only match the exact branch called "master".
 
-If nothing matches, linkgit:git-show-ref[1] will return an error code of 1,
+If nothing matches, 'git-show-ref' will return an error code of 1,
 and in the case of verification, it will show an error message.
 
 For scripting, you can ask it to be quiet with the "--quiet" flag, which
 allows you to do things like
 
 -----------------------------------------------------------------------------
-	git-show-ref --quiet --verify -- "refs/heads/$headname" ||
+	git show-ref --quiet --verify -- "refs/heads/$headname" ||
 		echo "$headname is not a valid branch"
 -----------------------------------------------------------------------------
 
diff --git a/Documentation/git-show.txt b/Documentation/git-show.txt
index 1017391..48b612e 100644
--- a/Documentation/git-show.txt
+++ b/Documentation/git-show.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-show' [options] <object>...
+'git show' [options] <object>...
 
 DESCRIPTION
 -----------
@@ -20,12 +20,12 @@
 
 For tags, it shows the tag message and the referenced objects.
 
-For trees, it shows the names (equivalent to linkgit:git-ls-tree[1]
+For trees, it shows the names (equivalent to 'git-ls-tree'
 with \--name-only).
 
 For plain blobs, it shows the plain contents.
 
-The command takes options applicable to the linkgit:git-diff-tree[1] command to
+The command takes options applicable to the 'git-diff-tree' command to
 control how the changes the commit introduces are shown.
 
 This manual page describes only the most frequently used options.
@@ -33,8 +33,8 @@
 
 OPTIONS
 -------
-<object>::
-	The name of the object to show.
+<object>...::
+	The names of objects to show.
 	For a more complete list of ways to spell object names, see
 	"SPECIFYING REVISIONS" section in linkgit:git-rev-parse[1].
 
diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt
index baa4f55..051f94d 100644
--- a/Documentation/git-stash.txt
+++ b/Documentation/git-stash.txt
@@ -8,22 +8,27 @@
 SYNOPSIS
 --------
 [verse]
-'git-stash' (list | show [<stash>] | apply [<stash>] | clear | drop [<stash>] | pop [<stash>])
-'git-stash' [save [<message>]]
+'git stash' list [<options>]
+'git stash' (show | drop | pop ) [<stash>]
+'git stash' apply [--index] [<stash>]
+'git stash' branch <branchname> [<stash>]
+'git stash' [save [--keep-index] [<message>]]
+'git stash' clear
+'git stash' create
 
 DESCRIPTION
 -----------
 
-Use 'git-stash' when you want to record the current state of the
+Use 'git stash' when you want to record the current state of the
 working directory and the index, but want to go back to a clean
 working directory.  The command saves your local modifications away
 and reverts the working directory to match the `HEAD` commit.
 
 The modifications stashed away by this command can be listed with
-`git-stash list`, inspected with `git-stash show`, and restored
-(potentially on top of a different commit) with `git-stash apply`.
-Calling git-stash without any arguments is equivalent to `git-stash
-save`.  A stash is by default listed as "WIP on 'branchname' ...", but
+`git stash list`, inspected with `git stash show`, and restored
+(potentially on top of a different commit) with `git stash apply`.
+Calling `git stash` without any arguments is equivalent to `git stash save`.
+A stash is by default listed as "WIP on 'branchname' ...", but
 you can give a more descriptive message on the command line when
 you create one.
 
@@ -36,12 +41,15 @@
 OPTIONS
 -------
 
-save [<message>]::
+save [--keep-index] [<message>]::
 
-	Save your local modifications to a new 'stash', and run `git-reset
+	Save your local modifications to a new 'stash', and run `git reset
 	--hard` to revert them.  This is the default action when no
 	subcommand is given. The <message> part is optional and gives
 	the description along with the stashed state.
++
+If the `--keep-index` option is used, all changes already added to the
+index are left intact.
 
 list [<options>]::
 
@@ -56,15 +64,15 @@
 stash@{1}: On master: 9cc0589... Add git-stash
 ----------------------------------------------------------------
 +
-The command takes options applicable to the linkgit:git-log[1]
-command to control what is shown and how.
+The command takes options applicable to the 'git-log'
+command to control what is shown and how. See linkgit:git-log[1].
 
 show [<stash>]::
 
 	Show the changes recorded in the stash as a diff between the
 	stashed state and its original parent. When no `<stash>` is given,
 	shows the latest one. By default, the command shows the diffstat, but
-	it will accept any format known to `git-diff` (e.g., `git-stash show
+	it will accept any format known to 'git-diff' (e.g., `git stash show
 	-p stash@\{1}` to view the second most recent stash in patch form).
 
 apply [--index] [<stash>]::
@@ -81,6 +89,20 @@
 have conflicts (which are stored in the index, where you therefore can no
 longer apply the changes as they were originally).
 
+branch <branchname> [<stash>]::
+
+	Creates and checks out a new branch named `<branchname>` starting from
+	the commit at which the `<stash>` was originally created, applies the
+	changes recorded in `<stash>` to the new working tree and index, then
+	drops the `<stash>` if that completes successfully. When no `<stash>`
+	is given, applies the latest one.
++
+This is useful if the branch on which you ran `git stash save` has
+changed enough that `git stash apply` fails due to conflicts. Since
+the stash is applied on top of the commit that was HEAD at the time
+`git stash` was run, it restores the originally stashed state with
+no conflicts.
+
 clear::
 	Remove all the stashed states. Note that those states will then
 	be subject to pruning, and may be difficult or impossible to recover.
@@ -96,6 +118,11 @@
 	of the current working tree state. When no `<stash>` is given,
 	`stash@\{0}` is assumed. See also `apply`.
 
+create::
+
+	Create a stash (which is a regular commit object) and return its
+	object name, without storing it anywhere in the ref namespace.
+
 
 DISCUSSION
 ----------
@@ -132,7 +159,7 @@
 +
 ----------------------------------------------------------------
 $ git pull
-...
+ ...
 file foobar not up to date, cannot merge.
 $ git stash
 $ git pull
@@ -147,7 +174,7 @@
 return to your original branch to make the emergency fix, like this:
 +
 ----------------------------------------------------------------
-... hack hack hack ...
+# ... hack hack hack ...
 $ git checkout -b my_wip
 $ git commit -a -m "WIP"
 $ git checkout master
@@ -155,18 +182,36 @@
 $ git commit -a -m "Fix in a hurry"
 $ git checkout my_wip
 $ git reset --soft HEAD^
-... continue hacking ...
+# ... continue hacking ...
 ----------------------------------------------------------------
 +
-You can use `git-stash` to simplify the above, like this:
+You can use 'git-stash' to simplify the above, like this:
 +
 ----------------------------------------------------------------
-... hack hack hack ...
+# ... hack hack hack ...
 $ git stash
 $ edit emergency fix
 $ git commit -a -m "Fix in a hurry"
 $ git stash apply
-... continue hacking ...
+# ... continue hacking ...
+----------------------------------------------------------------
+
+Testing partial commits::
+
+You can use `git stash save --keep-index` when you want to make two or
+more commits out of the changes in the work tree, and you want to test
+each change before committing:
++
+----------------------------------------------------------------
+# ... hack hack hack ...
+$ git add --patch foo            # add just first part to the index
+$ git stash save --keep-index    # save all other changes to the stash
+$ edit/build/test first part
+$ git commit -m 'First part'     # commit fully tested change
+$ git stash pop                  # prepare to work on all other changes
+# ... repeat above five steps until one commit remains ...
+$ edit/build/test remaining parts
+$ git commit foo -m 'Remaining parts'
 ----------------------------------------------------------------
 
 SEE ALSO
diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt
index 6026e8b..84f60f3 100644
--- a/Documentation/git-status.txt
+++ b/Documentation/git-status.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-status' <options>...
+'git status' <options>...
 
 DESCRIPTION
 -----------
@@ -17,16 +17,16 @@
 tree and the index file, and paths in the working tree that are not
 tracked by git (and are not ignored by linkgit:gitignore[5]). The first
 are what you _would_ commit by running `git commit`; the second and
-third are what you _could_ commit by running `git add` before running
+third are what you _could_ commit by running 'git-add' before running
 `git commit`.
 
-The command takes the same set of options as `git-commit`; it
+The command takes the same set of options as 'git-commit'; it
 shows what would be committed if the same options are given to
-`git-commit`.
+'git-commit'.
 
 If there is no path that is different between the index file and
 the current HEAD commit (i.e., there is nothing to commit by running
-`git-commit`), the command exits with non-zero status.
+`git commit`), the command exits with non-zero status.
 
 
 OUTPUT
diff --git a/Documentation/git-stripspace.txt b/Documentation/git-stripspace.txt
index 8421a39..7508c0e 100644
--- a/Documentation/git-stripspace.txt
+++ b/Documentation/git-stripspace.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-stripspace' [-s | --strip-comments] < <stream>
+'git stripspace' [-s | --strip-comments] < <stream>
 
 DESCRIPTION
 -----------
diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index 441ae14..e6652a7 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -9,40 +9,104 @@
 SYNOPSIS
 --------
 [verse]
-'git-submodule' [--quiet] add [-b branch] [--] <repository> [<path>]
-'git-submodule' [--quiet] status [--cached] [--] [<path>...]
-'git-submodule' [--quiet] init [--] [<path>...]
-'git-submodule' [--quiet] update [--init] [--] [<path>...]
-'git-submodule' [--quiet] summary [--summary-limit <n>] [commit] [--] [<path>...]
+'git submodule' [--quiet] add [-b branch] [--] <repository> <path>
+'git submodule' [--quiet] status [--cached] [--] [<path>...]
+'git submodule' [--quiet] init [--] [<path>...]
+'git submodule' [--quiet] update [--init] [--] [<path>...]
+'git submodule' [--quiet] summary [--summary-limit <n>] [commit] [--] [<path>...]
+
+
+DESCRIPTION
+-----------
+Submodules allow foreign repositories to be embedded within
+a dedicated subdirectory of the source tree, always pointed
+at a particular commit.
+
+They are not to be confused with remotes, which are meant mainly
+for branches of the same project; submodules are meant for
+different projects you would like to make part of your source tree,
+while the history of the two projects still stays completely
+independent and you cannot modify the contents of the submodule
+from within the main project.
+If you want to merge the project histories and want to treat the
+aggregated whole as a single project from then on, you may want to
+add a remote for the other project and use the 'subtree' merge strategy,
+instead of treating the other project as a submodule. Directories
+that come from both projects can be cloned and checked out as a whole
+if you choose to go that route.
+
+Submodules are composed from a so-called `gitlink` tree entry
+in the main repository that refers to a particular commit object
+within the inner repository that is completely separate.
+A record in the `.gitmodules` file at the root of the source
+tree assigns a logical name to the submodule and describes
+the default URL the submodule shall be cloned from.
+The logical name can be used for overriding this URL within your
+local repository configuration (see 'submodule init').
+
+This command will manage the tree entries and contents of the
+gitmodules file for you, as well as inspect the status of your
+submodules and update them.
+When adding a new submodule to the tree, the 'add' subcommand
+is to be used.  However, when pulling a tree containing submodules,
+these will not be checked out by default;
+the 'init' and 'update' subcommands will maintain submodules
+checked out and at appropriate revision in your working tree.
+You can briefly inspect the up-to-date status of your submodules
+using the 'status' subcommand and get a detailed overview of the
+difference between the index and checkouts using the 'summary'
+subcommand.
 
 
 COMMANDS
 --------
 add::
 	Add the given repository as a submodule at the given path
-	to the changeset to be committed next.  If path is a valid
-	repository within the project, it is added as is. Otherwise,
-	repository is cloned at the specified path. path is added to the
-	changeset and registered in .gitmodules.   If no path is
-	specified, the path is deduced from the repository specification.
-	If the repository url begins with ./ or ../, it is stored as
-	given but resolved as a relative path from the main project's
-	url when cloning.
+	to the changeset to be committed next to the current
+	project: the current project is termed the "superproject".
++
+This requires two arguments: <repository> and <path>.
++
+<repository> is the URL of the new submodule's origin repository.
+This may be either an absolute URL, or (if it begins with ./
+or ../), the location relative to the superproject's origin
+repository.
++
+<path> is the relative location for the cloned submodule to
+exist in the superproject. If <path> does not exist, then the
+submodule is created by cloning from the named URL. If <path> does
+exist and is already a valid git repository, then this is added
+to the changeset without cloning. This second form is provided
+to ease creating a new submodule from scratch, and presumes
+the user will later push the submodule to the given URL.
++
+In either case, the given URL is recorded into .gitmodules for
+use by subsequent users cloning the superproject. If the URL is
+given relative to the superproject's repository, the presumption
+is the superproject and submodule repositories will be kept
+together in the same relative location, and only the
+superproject's URL needs to be provided: git-submodule will correctly
+locate the submodule using the relative URL in .gitmodules.
 
 status::
 	Show the status of the submodules. This will print the SHA-1 of the
 	currently checked out commit for each submodule, along with the
-	submodule path and the output of linkgit:git-describe[1] for the
+	submodule path and the output of 'git-describe' for the
 	SHA-1. Each SHA-1 will be prefixed with `-` if the submodule is not
 	initialized and `+` if the currently checked out submodule commit
 	does not match the SHA-1 found in the index of the containing
-	repository. This command is the default command for git-submodule.
+	repository. This command is the default command for 'git-submodule'.
 
 init::
-	Initialize the submodules, i.e. register in .git/config each submodule
-	name and url found in .gitmodules. The key used in .git/config is
-	`submodule.$name.url`. This command does not alter existing information
-	in .git/config.
+	Initialize the submodules, i.e. register each submodule name
+	and url found in .gitmodules into .git/config.
+	The key used in .git/config is `submodule.$name.url`.
+	This command does not alter existing information in .git/config.
+	You can then customize the submodule clone URLs in .git/config
+	for your local setup and proceed to 'git submodule update';
+	you can also just use 'git submodule update --init' without
+	the explicit 'init' step if you do not intend to customize
+	any submodule locations.
 
 update::
 	Update the registered submodules, i.e. clone missing submodules and
@@ -82,9 +146,10 @@
 	(the default). This limit only applies to modified submodules. The
 	size is always limited to 1 for added/deleted/typechanged submodules.
 
-<path>::
-	Path to submodule(s). When specified this will restrict the command
+<path>...::
+	Paths to submodule(s). When specified this will restrict the command
 	to only operate on the submodules found at the specified paths.
+	(This argument is required with add).
 
 FILES
 -----
diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index c350ad0..5d6d30f 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -7,23 +7,23 @@
 
 SYNOPSIS
 --------
-'git-svn' <command> [options] [arguments]
+'git svn' <command> [options] [arguments]
 
 DESCRIPTION
 -----------
-git-svn is a simple conduit for changesets between Subversion and git.
-It is not to be confused with linkgit:git-svnimport[1], which is
-read-only.
+'git-svn' is a simple conduit for changesets between Subversion and git.
+It provides a bidirectional flow of changes between a Subversion and a git
+repository.
 
-git-svn was originally designed for an individual developer who wants a
-bidirectional flow of changesets between a single branch in Subversion
-and an arbitrary number of branches in git.  Since its inception,
-git-svn has gained the ability to track multiple branches in a manner
-similar to git-svnimport.
+'git-svn' can track a single Subversion branch simply by using a
+URL to the branch, follow branches laid out in the Subversion recommended
+method (trunk, branches, tags directories) with the --stdlayout option, or
+follow branches in any layout with the -T/-t/-b options (see options to
+'init' below, and also the 'clone' command).
 
-git-svn is especially useful when it comes to tracking repositories
-not organized in the way Subversion developers recommend (trunk,
-branches, tags directories).
+Once tracking a Subversion branch (with any of the above methods), the git
+repository can be updated from Subversion by the 'fetch' command and
+Subversion updated from git by the 'dcommit' command.
 
 COMMANDS
 --------
@@ -31,7 +31,7 @@
 
 'init'::
 	Initializes an empty git repository with additional
-	metadata directories for git-svn.  The Subversion URL
+	metadata directories for 'git-svn'.  The Subversion URL
 	may be specified as a command-line argument, or as full
 	URL arguments to -T/-t/-b.  Optionally, the target
 	directory to operate on can be specified as a second
@@ -107,12 +107,12 @@
 	This fetches revisions from the SVN parent of the current HEAD
 	and rebases the current (uncommitted to SVN) work against it.
 
-This works similarly to 'svn update' or 'git-pull' except that
+This works similarly to `svn update` or 'git-pull' except that
 it preserves linear history with 'git-rebase' instead of
-'git-merge' for ease of dcommiting with git-svn.
+'git-merge' for ease of dcommitting with 'git-svn'.
 
 This accepts all options that 'git-svn fetch' and 'git-rebase'
-accepts.  However '--fetch-all' only fetches from the current
+accept.  However, '--fetch-all' only fetches from the current
 [svn-remote], and not all [svn-remote] definitions.
 
 Like 'git-rebase'; this requires that the working tree be clean
@@ -128,7 +128,7 @@
 	repository, and then rebase or reset (depending on whether or
 	not there is a diff between SVN and head).  This will create
 	a revision in SVN for each commit in git.
-	It is recommended that you run git-svn fetch and rebase (not
+	It is recommended that you run 'git-svn' fetch and rebase (not
 	pull or merge) your commits against the latest changes in the
 	SVN repository.
 	An optional command-line argument may be specified as an
@@ -138,6 +138,15 @@
 +
 --no-rebase;;
 	After committing, do not rebase or reset.
+--commit-url <URL>;;
+	Commit to this SVN URL (the full path).  This is intended to
+	allow existing git-svn repositories created with one transport
+	method (e.g. `svn://` or `http://` for anonymous read) to be
+	reused if a user is later given access to an alternate transport
+	method (e.g. `svn+ssh://` or `https://`) for commit.
+
+	Using this option for any other purpose (don't ask)
+	is very strongly discouraged.
 --
 
 'log'::
@@ -173,7 +182,7 @@
 client converts the UTC time to the local time (or based on the TZ=
 environment). This command has the same behaviour.
 +
-Any other arguments are passed directly to `git log'
+Any other arguments are passed directly to 'git-log'
 
 'blame'::
        Show what revision and author last modified each line of a file. The
@@ -181,10 +190,10 @@
        `svn blame' by default. Like the SVN blame command,
        local uncommitted changes in the working copy are ignored;
        the version of the file in the HEAD revision is annotated. Unknown
-       arguments are passed directly to git-blame.
+       arguments are passed directly to 'git-blame'.
 +
 --git-format;;
-	Produce output in the same format as `git blame', but with
+	Produce output in the same format as 'git-blame', but with
 	SVN revision numbers instead of git commit hashes. In this mode,
 	changes that haven't been committed to SVN (including local
 	working-copy edits) are shown as revision 0.
@@ -203,13 +212,13 @@
 	absolutely no attempts to do patching when committing to SVN, it
 	simply overwrites files with those specified in the tree or
 	commit.  All merging is assumed to have taken place
-	independently of git-svn functions.
+	independently of 'git-svn' functions.
 
 'create-ignore'::
 	Recursively finds the svn:ignore property on directories and
 	creates matching .gitignore files. The resulting files are staged to
 	be committed, but are not committed. Use -r/--revision to refer to a
-	specfic revision.
+	specific revision.
 
 'show-ignore'::
 	Recursively finds and lists the svn:ignore property on
@@ -218,13 +227,12 @@
 
 'commit-diff'::
 	Commits the diff of two tree-ish arguments from the
-	command-line.  This command is intended for interoperability with
-	git-svnimport and does not rely on being inside an git-svn
-	init-ed repository.  This command takes three arguments, (a) the
+	command-line.  This command does not rely on being inside an `git-svn
+	init`-ed repository.  This command takes three arguments, (a) the
 	original tree to diff against, (b) the new tree result, (c) the
 	URL of the target Subversion repository.  The final argument
-	(URL) may be omitted if you are working from a git-svn-aware
-	repository (that has been init-ed with git-svn).
+	(URL) may be omitted if you are working from a 'git-svn'-aware
+	repository (that has been `init`-ed with 'git-svn').
 	The -r<revision> option is required for this.
 
 'info'::
@@ -255,7 +263,7 @@
 --shared[={false|true|umask|group|all|world|everybody}]::
 --template=<template_directory>::
 	Only used with the 'init' command.
-	These are passed directly to linkgit:git-init[1].
+	These are passed directly to 'git-init'.
 
 -r <ARG>::
 --revision <ARG>::
@@ -277,7 +285,7 @@
 
 Read a list of commits from stdin and commit them in reverse
 order.  Only the leading sha1 is read from each line, so
-git-rev-list --pretty=oneline output can be used.
+'git-rev-list --pretty=oneline' output can be used.
 
 --rmdir::
 
@@ -307,7 +315,7 @@
 
 Only used with the 'dcommit', 'set-tree' and 'commit-diff' commands.
 
-They are both passed directly to git-diff-tree see
+They are both passed directly to 'git-diff-tree'; see
 linkgit:git-diff-tree[1] for more information.
 
 [verse]
@@ -317,24 +325,23 @@
 -A<filename>::
 --authors-file=<filename>::
 
-Syntax is compatible with the files used by git-svnimport and
-git-cvsimport:
+Syntax is compatible with the file used by 'git-cvsimport':
 
 ------------------------------------------------------------------------
 	loginname = Joe User <user@example.com>
 ------------------------------------------------------------------------
 
-If this option is specified and git-svn encounters an SVN
-committer name that does not exist in the authors-file, git-svn
+If this option is specified and 'git-svn' encounters an SVN
+committer name that does not exist in the authors-file, 'git-svn'
 will abort operation. The user will then have to add the
-appropriate entry.  Re-running the previous git-svn command
+appropriate entry.  Re-running the previous 'git-svn' command
 after the authors-file is modified should continue operation.
 
 config key: svn.authorsfile
 
 -q::
 --quiet::
-	Make git-svn less verbose.
+	Make 'git-svn' less verbose.
 
 --repack[=<n>]::
 --repack-flags=<flags>::
@@ -346,7 +353,7 @@
 to fetch before repacking.  This defaults to repacking every
 1000 commits fetched if no argument is specified.
 
---repack-flags are passed directly to linkgit:git-repack[1].
+--repack-flags are passed directly to 'git-repack'.
 
 [verse]
 config key: svn.repack
@@ -359,8 +366,8 @@
 
 These are only used with the 'dcommit' and 'rebase' commands.
 
-Passed directly to git-rebase when using 'dcommit' if a
-'git-reset' cannot be used (see dcommit).
+Passed directly to 'git-rebase' when using 'dcommit' if a
+'git-reset' cannot be used (see 'dcommit').
 
 -n::
 --dry-run::
@@ -411,9 +418,9 @@
 svn.noMetadata::
 svn-remote.<name>.noMetadata::
 
-This gets rid of the git-svn-id: lines at the end of every commit.
+This gets rid of the 'git-svn-id:' lines at the end of every commit.
 
-If you lose your .git/svn/git-svn/.rev_db file, git-svn will not
+If you lose your .git/svn/git-svn/.rev_db file, 'git-svn' will not
 be able to rebuild it and you won't be able to fetch again,
 either.  This is fine for one-shot imports.
 
@@ -424,7 +431,7 @@
 svn.useSvmProps::
 svn-remote.<name>.useSvmProps::
 
-This allows git-svn to re-map repository URLs and UUIDs from
+This allows 'git-svn' to re-map repository URLs and UUIDs from
 mirrors created using SVN::Mirror (or svk) for metadata.
 
 If an SVN revision has a property, "svm:headrev", it is likely
@@ -443,7 +450,7 @@
 
 svn-remote.<name>.rewriteRoot::
 	This allows users to create repositories from alternate
-	URLs.  For example, an administrator could run git-svn on the
+	URLs.  For example, an administrator could run 'git-svn' on the
 	server locally (accessing via file://) but wish to distribute
 	the repository with a public http:// or svn:// URL in the
 	metadata so users of it will see the public URL.
@@ -451,7 +458,7 @@
 --
 
 Since the noMetadata, rewriteRoot, useSvnsyncProps and useSvmProps
-options all affect the metadata generated and used by git-svn; they
+options all affect the metadata generated and used by 'git-svn'; they
 *must* be set in the configuration file before any history is imported
 and these settings should never be changed once they are set.
 
@@ -466,7 +473,7 @@
 
 ------------------------------------------------------------------------
 # Clone a repo (like git clone):
-	git-svn clone http://svn.foo.org/project/trunk
+	git svn clone http://svn.example.com/project/trunk
 # Enter the newly cloned directory:
 	cd trunk
 # You should be on master branch, double-check with git-branch
@@ -475,12 +482,12 @@
 	git commit ...
 # Something is committed to SVN, rebase your local changes against the
 # latest changes in SVN:
-	git-svn rebase
+	git svn rebase
 # Now commit your changes (that were committed previously using git) to SVN,
 # as well as automatically updating your working HEAD:
-	git-svn dcommit
+	git svn dcommit
 # Append svn:ignore settings to the default git exclude file:
-	git-svn show-ignore >> .git/info/exclude
+	git svn show-ignore >> .git/info/exclude
 ------------------------------------------------------------------------
 
 Tracking and contributing to an entire Subversion-managed project
@@ -488,7 +495,7 @@
 
 ------------------------------------------------------------------------
 # Clone a repo (like git clone):
-	git-svn clone http://svn.foo.org/project -T trunk -b branches -t tags
+	git svn clone http://svn.example.com/project -T trunk -b branches -t tags
 # View all branches and tags you have cloned:
 	git branch -r
 # Reset your master to trunk (or any other branch, replacing 'trunk'
@@ -501,45 +508,47 @@
 The initial 'git-svn clone' can be quite time-consuming
 (especially for large Subversion repositories). If multiple
 people (or one person with multiple machines) want to use
-git-svn to interact with the same Subversion repository, you can
+'git-svn' to interact with the same Subversion repository, you can
 do the initial 'git-svn clone' to a repository on a server and
-have each person clone that repository with 'git clone':
+have each person clone that repository with 'git-clone':
 
 ------------------------------------------------------------------------
 # Do the initial import on a server
-	ssh server "cd /pub && git-svn clone http://svn.foo.org/project
+	ssh server "cd /pub && git svn clone http://svn.example.com/project
 # Clone locally - make sure the refs/remotes/ space matches the server
 	mkdir project
 	cd project
-	git-init
+	git init
 	git remote add origin server:/pub/project
 	git config --add remote.origin.fetch '+refs/remotes/*:refs/remotes/*'
 	git fetch
+# Create a local branch from one of the branches just fetched
+	git checkout -b master FETCH_HEAD
 # Initialize git-svn locally (be sure to use the same URL and -T/-b/-t options as were used on server)
-	git-svn init http://svn.foo.org/project
+	git svn init http://svn.example.com/project
 # Pull the latest changes from Subversion
-	git-svn rebase
+	git svn rebase
 ------------------------------------------------------------------------
 
 REBASE VS. PULL/MERGE
 ---------------------
 
-Originally, git-svn recommended that the remotes/git-svn branch be
+Originally, 'git-svn' recommended that the 'remotes/git-svn' branch be
 pulled or merged from.  This is because the author favored
-'git-svn set-tree B' to commit a single head rather than the
-'git-svn set-tree A..B' notation to commit multiple commits.
+`git svn set-tree B` to commit a single head rather than the
+`git svn set-tree A..B` notation to commit multiple commits.
 
-If you use 'git-svn set-tree A..B' to commit several diffs and you do
+If you use `git svn set-tree A..B` to commit several diffs and you do
 not have the latest remotes/git-svn merged into my-branch, you should
-use 'git-svn rebase' to update your work branch instead of 'git pull' or
-'git merge'.  'pull/merge' can cause non-linear history to be flattened
+use `git svn rebase` to update your work branch instead of `git pull` or
+`git merge`.  `pull`/`merge' can cause non-linear history to be flattened
 when committing into SVN, which can lead to merge commits reversing
 previous commits in SVN.
 
 DESIGN PHILOSOPHY
 -----------------
 Merge tracking in Subversion is lacking and doing branched development
-with Subversion can be cumbersome as a result.  While git-svn can track
+with Subversion can be cumbersome as a result.  While 'git-svn' can track
 copy history (including branches and tags) for repositories adopting a
 standard layout, it cannot yet represent merge history that happened
 inside git back upstream to SVN users.  Therefore it is advised that
@@ -550,30 +559,30 @@
 -------
 
 For the sake of simplicity and interoperating with a less-capable system
-(SVN), it is recommended that all git-svn users clone, fetch and dcommit
-directly from the SVN server, and avoid all git-clone/pull/merge/push
+(SVN), it is recommended that all 'git-svn' users clone, fetch and dcommit
+directly from the SVN server, and avoid all 'git-clone'/'pull'/'merge'/'push'
 operations between git repositories and branches.  The recommended
 method of exchanging code between git branches and users is
-git-format-patch and git-am, or just dcommiting to the SVN repository.
+'git-format-patch' and 'git-am', or just 'dcommit'ing to the SVN repository.
 
 Running 'git-merge' or 'git-pull' is NOT recommended on a branch you
-plan to dcommit from.  Subversion does not represent merges in any
+plan to 'dcommit' from.  Subversion does not represent merges in any
 reasonable or useful fashion; so users using Subversion cannot see any
 merges you've made.  Furthermore, if you merge or pull from a git branch
-that is a mirror of an SVN branch, dcommit may commit to the wrong
+that is a mirror of an SVN branch, 'dcommit' may commit to the wrong
 branch.
 
 'git-clone' does not clone branches under the refs/remotes/ hierarchy or
-any git-svn metadata, or config.  So repositories created and managed with
-using git-svn should use rsync(1) for cloning, if cloning is to be done
+any 'git-svn' metadata, or config.  So repositories created and managed with
+using 'git-svn' should use 'rsync' for cloning, if cloning is to be done
 at all.
 
-Since 'dcommit' uses rebase internally, any git branches you git-push to
-before dcommit on will require forcing an overwrite of the existing ref
+Since 'dcommit' uses rebase internally, any git branches you 'git-push' to
+before 'dcommit' on will require forcing an overwrite of the existing ref
 on the remote repository.  This is generally considered bad practice,
-see the git-push(1) documentation for details.
+see the linkgit:git-push[1] documentation for details.
 
-Do not use the --amend option of git-commit(1) on a change you've
+Do not use the --amend option of linkgit:git-commit[1] on a change you've
 already dcommitted.  It is considered bad practice to --amend commits
 you've already pushed to a remote repository for other users, and
 dcommit with SVN is analogous to that.
@@ -594,7 +603,7 @@
 CONFIGURATION
 -------------
 
-git-svn stores [svn-remote] configuration information in the
+'git-svn' stores [svn-remote] configuration information in the
 repository .git/config file.  It is similar the core git
 [remote] sections except 'fetch' keys do not accept glob
 arguments; but they are instead handled by the 'branches'
@@ -615,8 +624,7 @@
 however the remote wildcard may be anywhere as long as it's own
 independent path component (surrounded by '/' or EOL).   This
 type of configuration is not automatically created by 'init' and
-should be manually entered with a text-editor or using
-linkgit:git-config[1]
+should be manually entered with a text-editor or using 'git-config'.
 
 SEE ALSO
 --------
diff --git a/Documentation/git-symbolic-ref.txt b/Documentation/git-symbolic-ref.txt
index 5709dee..210fde0 100644
--- a/Documentation/git-symbolic-ref.txt
+++ b/Documentation/git-symbolic-ref.txt
@@ -7,7 +7,7 @@
 
 SYNOPSIS
 --------
-'git-symbolic-ref' [-q] [-m <reason>] <name> [<ref>]
+'git symbolic-ref' [-q] [-m <reason>] <name> [<ref>]
 
 DESCRIPTION
 -----------
@@ -49,7 +49,7 @@
 advertised (horrors).  Therefore symbolic links are now deprecated
 and symbolic refs are used by default.
 
-git-symbolic-ref will exit with status 0 if the contents of the
+'git-symbolic-ref' will exit with status 0 if the contents of the
 symbolic ref were printed correctly, with status 1 if the requested
 name is not a symbolic ref, or 128 if another error occurs.
 
diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt
index 6cf11ce..046ab35 100644
--- a/Documentation/git-tag.txt
+++ b/Documentation/git-tag.txt
@@ -9,10 +9,11 @@
 SYNOPSIS
 --------
 [verse]
-'git-tag' [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>]  <name> [<head>]
-'git-tag' -d <name>...
-'git-tag' [-n[<num>]] -l [<pattern>]
-'git-tag' -v <name>...
+'git tag' [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>]
+	<name> [<commit> | <object>]
+'git tag' -d <name>...
+'git tag' [-n[<num>]] -l [<pattern>]
+'git tag' -v <name>...
 
 DESCRIPTION
 -----------
@@ -82,7 +83,7 @@
 
 CONFIGURATION
 -------------
-By default, git-tag in sign-with-default mode (-s) will use your
+By default, 'git-tag' in sign-with-default mode (-s) will use your
 committer identity (of the form "Your Name <your@email.address>") to
 find a key.  If you want to use a different default key, you can specify
 it in the repository configuration as follows:
@@ -118,12 +119,12 @@
 
 . The insane thing.
 You really want to call the new version "X" too, 'even though'
-others have already seen the old one. So just use "git tag -f"
+others have already seen the old one. So just use 'git-tag -f'
 again, as if you hadn't already published the old one.
 
 However, Git does *not* (and it should not) change tags behind
-users back. So if somebody already got the old tag, doing a "git
-pull" on your tree shouldn't just make them overwrite the old
+users back. So if somebody already got the old tag, doing a
+'git-pull' on your tree shouldn't just make them overwrite the old
 one.
 
 If somebody got a release tag from you, you cannot just change
@@ -177,7 +178,7 @@
 
 You would notice "please pull" messages on the mailing list says
 repo URL and branch name alone.  This is designed to be easily
-cut&pasted to "git fetch" command line:
+cut&pasted to a 'git-fetch' command line:
 
 ------------
 Linus, please pull from
diff --git a/Documentation/git-tar-tree.txt b/Documentation/git-tar-tree.txt
index 74ed065..a5d9558 100644
--- a/Documentation/git-tar-tree.txt
+++ b/Documentation/git-tar-tree.txt
@@ -8,23 +8,23 @@
 
 SYNOPSIS
 --------
-'git-tar-tree' [--remote=<repo>] <tree-ish> [ <base> ]
+'git tar-tree' [--remote=<repo>] <tree-ish> [ <base> ]
 
 DESCRIPTION
 -----------
-THIS COMMAND IS DEPRECATED.  Use `git-archive` with `--format=tar`
+THIS COMMAND IS DEPRECATED.  Use 'git-archive' with `--format=tar`
 option instead (and move the <base> argument to `--prefix=base/`).
 
 Creates a tar archive containing the tree structure for the named tree.
 When <base> is specified it is added as a leading path to the files in the
 generated tar archive.
 
-git-tar-tree behaves differently when given a tree ID versus when given
+'git-tar-tree' behaves differently when given a tree ID versus when given
 a commit ID or tag ID.  In the first case the current time is used as
 modification time of each file in the archive.  In the latter case the
 commit time as recorded in the referenced commit object is used instead.
 Additionally the commit ID is stored in a global extended pax header.
-It can be extracted using git-get-tar-commit-id.
+It can be extracted using 'git-get-tar-commit-id'.
 
 OPTIONS
 -------
diff --git a/Documentation/git-unpack-file.txt b/Documentation/git-unpack-file.txt
index d0552b2..995db9f 100644
--- a/Documentation/git-unpack-file.txt
+++ b/Documentation/git-unpack-file.txt
@@ -9,7 +9,7 @@
 
 SYNOPSIS
 --------
-'git-unpack-file' <blob>
+'git unpack-file' <blob>
 
 DESCRIPTION
 -----------
diff --git a/Documentation/git-unpack-objects.txt b/Documentation/git-unpack-objects.txt
index b9c4279..36d1038 100644
--- a/Documentation/git-unpack-objects.txt
+++ b/Documentation/git-unpack-objects.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-unpack-objects' [-n] [-q] [-r] [--strict] <pack-file
+'git unpack-objects' [-n] [-q] [-r] [--strict] <pack-file
 
 
 DESCRIPTION
@@ -21,7 +21,7 @@
 from the pack-file.  Therefore, nothing will be unpacked if you use
 this command on a pack-file that exists within the target repository.
 
-Please see the `git-repack` documentation for options to generate
+See linkgit:git-repack[1] for options to generate
 new packs and replace existing ones.
 
 OPTIONS
diff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.txt
index bbb0a6a..25e0bbe 100644
--- a/Documentation/git-update-index.txt
+++ b/Documentation/git-update-index.txt
@@ -9,7 +9,7 @@
 SYNOPSIS
 --------
 [verse]
-'git-update-index'
+'git update-index'
 	     [--add] [--remove | --force-remove] [--replace]
 	     [--refresh] [-q] [--unmerged] [--ignore-missing]
 	     [--cacheinfo <mode> <object> <file>]\*
@@ -31,7 +31,7 @@
 See also linkgit:git-add[1] for a more user-friendly way to do some of
 the most common operations on the index.
 
-The way "git-update-index" handles files it is told about can be modified
+The way 'git-update-index' handles files it is told about can be modified
 using the various options:
 
 OPTIONS
@@ -53,15 +53,15 @@
 -q::
         Quiet.  If --refresh finds that the index needs an update, the
         default behavior is to error out.  This option makes
-        git-update-index continue anyway.
+	'git-update-index' continue anyway.
 
---ignore-submodules:
+--ignore-submodules::
 	Do not try to update submodules.  This option is only respected
 	when passed before --refresh.
 
 --unmerged::
         If --refresh finds unmerged changes in the index, the default
-        behavior is to error out.  This option makes git-update-index
+	behavior is to error out.  This option makes 'git-update-index'
         continue anyway.
 
 --ignore-missing::
@@ -78,9 +78,9 @@
 
 --assume-unchanged::
 --no-assume-unchanged::
-	When these flags are specified, the object name recorded
+	When these flags are specified, the object names recorded
 	for the paths are not updated.  Instead, these options
-	sets and unsets the "assume unchanged" bit for the
+	set and unset the "assume unchanged" bit for the
 	paths.  When the "assume unchanged" bit is on, git stops
 	checking the working tree files for possible
 	modifications, so you need to manually unset the bit to
@@ -88,10 +88,20 @@
 	sometimes helpful when working with a big project on a
 	filesystem that has very slow lstat(2) system call
 	(e.g. cifs).
++
+This option can be also used as a coarse file-level mechanism
+to ignore uncommitted changes in tracked files (akin to what
+`.gitignore` does for untracked files).
+You should remember that an explicit 'git add' operation will
+still cause the file to be refreshed from the working tree.
+Git will fail (gracefully) in case it needs to modify this file
+in the index e.g. when merging in a commit;
+thus, in case the assumed-untracked file is changed upstream,
+you will need to handle the situation manually.
 
 -g::
 --again::
-	Runs `git-update-index` itself on the paths whose index
+	Runs 'git-update-index' itself on the paths whose index
 	entries are different from those from the `HEAD` commit.
 
 --unresolve::
@@ -109,10 +119,10 @@
 
 --replace::
 	By default, when a file `path` exists in the index,
-	git-update-index refuses an attempt to add `path/file`.
+	'git-update-index' refuses an attempt to add `path/file`.
 	Similarly if a file `path/file` exists, a file `path`
 	cannot be added.  With --replace flag, existing entries
-	that conflicts with the entry being added are
+	that conflict with the entry being added are
 	automatically removed with warning messages.
 
 --stdin::
@@ -145,7 +155,7 @@
 can refresh the index for a file that hasn't been changed but where
 the stat entry is out of date.
 
-For example, you'd want to do this after doing a "git-read-tree", to link
+For example, you'd want to do this after doing a 'git-read-tree', to link
 up the stat index details with the proper files.
 
 Using --cacheinfo or --info-only
@@ -157,7 +167,7 @@
 To pretend you have a file with mode and sha1 at path, say:
 
 ----------------
-$ git-update-index --cacheinfo mode sha1 path
+$ git update-index --cacheinfo mode sha1 path
 ----------------
 
 '--info-only' is used to register files without placing them in the object
@@ -186,13 +196,13 @@
 
     . mode SP type SP sha1          TAB path
 +
-The second format is to stuff git-ls-tree output
+The second format is to stuff 'git-ls-tree' output
 into the index file.
 
     . mode         SP sha1 SP stage TAB path
 +
 This format is to put higher order stages into the
-index file and matches git-ls-files --stage output.
+index file and matches 'git-ls-files --stage' output.
 
 To place a higher stage entry to the index, the path should
 first be removed by feeding a mode=0 entry for the path, and
@@ -247,13 +257,13 @@
 option.  To unset, use `--no-assume-unchanged`.
 
 The command looks at `core.ignorestat` configuration variable.  When
-this is true, paths updated with `git-update-index paths...` and
+this is true, paths updated with `git update-index paths...` and
 paths updated with other git commands that update both index and
-working tree (e.g. `git-apply --index`, `git-checkout-index -u`,
-and `git-read-tree -u`) are automatically marked as "assume
+working tree (e.g. 'git-apply --index', 'git-checkout-index -u',
+and 'git-read-tree -u') are automatically marked as "assume
 unchanged".  Note that "assume unchanged" bit is *not* set if
-`git-update-index --refresh` finds the working tree file matches
-the index (use `git-update-index --really-refresh` if you want
+`git update-index --refresh` finds the working tree file matches
+the index (use `git update-index --really-refresh` if you want
 to mark them as "assume unchanged").
 
 
@@ -262,7 +272,7 @@
 To update and refresh only the files already checked out:
 
 ----------------
-$ git-checkout-index -n -f -a && git-update-index --ignore-missing --refresh
+$ git checkout-index -n -f -a && git update-index --ignore-missing --refresh
 ----------------
 
 On an inefficient filesystem with `core.ignorestat` set::
@@ -303,7 +313,7 @@
 This causes the command to ignore differences in file modes recorded
 in the index and the file mode on the filesystem if they differ only on
 executable bit.   On such an unfortunate filesystem, you may
-need to use `git-update-index --chmod=`.
+need to use 'git-update-index --chmod='.
 
 Quite similarly, if `core.symlinks` configuration variable is set
 to 'false' (see linkgit:git-config[1]), symbolic links are checked out
@@ -313,6 +323,11 @@
 The command looks at `core.ignorestat` configuration variable.  See
 'Using "assume unchanged" bit' section above.
 
+The command also looks at `core.trustctime` configuration variable.
+It can be useful when the inode change time is regularly modified by
+something outside Git (file system crawlers and backup systems use
+ctime for marking files processed) (see linkgit:git-config[1]).
+
 
 SEE ALSO
 --------
diff --git a/Documentation/git-update-ref.txt b/Documentation/git-update-ref.txt
index 7f7e3d1..9639f70 100644
--- a/Documentation/git-update-ref.txt
+++ b/Documentation/git-update-ref.txt
@@ -7,18 +7,18 @@
 
 SYNOPSIS
 --------
-'git-update-ref' [-m <reason>] (-d <ref> <oldvalue> | [--no-deref] <ref> <newvalue> [<oldvalue>])
+'git update-ref' [-m <reason>] (-d <ref> [<oldvalue>] | [--no-deref] <ref> <newvalue> [<oldvalue>])
 
 DESCRIPTION
 -----------
 Given two arguments, stores the <newvalue> in the <ref>, possibly
-dereferencing the symbolic refs.  E.g. `git-update-ref HEAD
+dereferencing the symbolic refs.  E.g. `git update-ref HEAD
 <newvalue>` updates the current branch head to the new object.
 
 Given three arguments, stores the <newvalue> in the <ref>,
 possibly dereferencing the symbolic refs, after verifying that
 the current value of the <ref> matches <oldvalue>.
-E.g. `git-update-ref refs/heads/master <newvalue> <oldvalue>`
+E.g. `git update-ref refs/heads/master <newvalue> <oldvalue>`
 updates the master branch head to <newvalue> only if its current
 value is <oldvalue>.  You can specify 40 "0" or an empty string
 as <oldvalue> to make sure that the ref you are creating does
@@ -41,7 +41,7 @@
 
 In general, using
 
-	git-update-ref HEAD "$head"
+	git update-ref HEAD "$head"
 
 should be a _lot_ safer than doing
 
@@ -61,7 +61,7 @@
 Logging Updates
 ---------------
 If config parameter "core.logAllRefUpdates" is true or the file
-"$GIT_DIR/logs/<ref>" exists then `git-update-ref` will append
+"$GIT_DIR/logs/<ref>" exists then `git update-ref` will append
 a line to the log file "$GIT_DIR/logs/<ref>" (dereferencing all
 symbolic refs before creating the log name) describing the change
 in ref value.  Log lines are formatted as:
diff --git a/Documentation/git-update-server-info.txt b/Documentation/git-update-server-info.txt
index 4fd7b5e..35d27b0 100644
--- a/Documentation/git-update-server-info.txt
+++ b/Documentation/git-update-server-info.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-update-server-info' [--force]
+'git update-server-info' [--force]
 
 DESCRIPTION
 -----------
@@ -31,7 +31,7 @@
 ------
 
 Currently the command updates the following files.  Please see
-linkgit:gitrepository-layout[5][repository-layout] for description of
+linkgit:gitrepository-layout[5] for description of
 what they are for:
 
 * objects/info/packs
diff --git a/Documentation/git-upload-archive.txt b/Documentation/git-upload-archive.txt
index e49f68f..bbd7617 100644
--- a/Documentation/git-upload-archive.txt
+++ b/Documentation/git-upload-archive.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-upload-archive' <directory>
+'git upload-archive' <directory>
 
 DESCRIPTION
 -----------
diff --git a/Documentation/git-upload-pack.txt b/Documentation/git-upload-pack.txt
index bac465e..b8e49dc 100644
--- a/Documentation/git-upload-pack.txt
+++ b/Documentation/git-upload-pack.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-upload-pack' [--strict] [--timeout=<n>] <directory>
+'git upload-pack' [--strict] [--timeout=<n>] <directory>
 
 DESCRIPTION
 -----------
diff --git a/Documentation/git-var.txt b/Documentation/git-var.txt
index 67e8e1f..e2f4c09 100644
--- a/Documentation/git-var.txt
+++ b/Documentation/git-var.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-var' [ -l | <variable> ]
+'git var' [ -l | <variable> ]
 
 DESCRIPTION
 -----------
@@ -20,11 +20,11 @@
 	Cause the logical variables to be listed. In addition, all the
 	variables of the git configuration file .git/config are listed
 	as well. (However, the configuration variables listing functionality
-	is deprecated in favor of `git-config -l`.)
+	is deprecated in favor of 'git config -l'.)
 
 EXAMPLE
 --------
-	$ git-var GIT_AUTHOR_IDENT
+	$ git var GIT_AUTHOR_IDENT
 	Eric W. Biederman <ebiederm@lnxi.com> 1121223278 -0600
 
 
@@ -41,9 +41,9 @@
 You don't exist. Go away!::
     The passwd(5) gecos field couldn't be read
 Your parents must have hated you!::
-    The password(5) gecos field is longer than a giant static buffer.
+    The passwd(5) gecos field is longer than a giant static buffer.
 Your sysadmin must hate you!::
-    The password(5) name field is longer than a giant static buffer.
+    The passwd(5) name field is longer than a giant static buffer.
 
 SEE ALSO
 --------
diff --git a/Documentation/git-verify-pack.txt b/Documentation/git-verify-pack.txt
index ff704bd..c861163 100644
--- a/Documentation/git-verify-pack.txt
+++ b/Documentation/git-verify-pack.txt
@@ -8,13 +8,13 @@
 
 SYNOPSIS
 --------
-'git-verify-pack' [-v] [--] <pack>.idx ...
+'git verify-pack' [-v] [--] <pack>.idx ...
 
 
 DESCRIPTION
 -----------
-Reads given idx file for packed git archive created with
-git-pack-objects command and verifies idx file and the
+Reads given idx file for packed git archive created with the
+'git-pack-objects' command and verifies idx file and the
 corresponding pack file.
 
 OPTIONS
diff --git a/Documentation/git-verify-tag.txt b/Documentation/git-verify-tag.txt
index dffba89..84e70a0 100644
--- a/Documentation/git-verify-tag.txt
+++ b/Documentation/git-verify-tag.txt
@@ -7,16 +7,16 @@
 
 SYNOPSIS
 --------
-'git-verify-tag' <tag>...
+'git verify-tag' <tag>...
 
 DESCRIPTION
 -----------
-Validates the gpg signature created by git-tag.
+Validates the gpg signature created by 'git-tag'.
 
 OPTIONS
 -------
-<tag>::
-	SHA1 identifier of a git tag object.
+<tag>...::
+	SHA1 identifiers of git tag objects.
 
 Author
 ------
diff --git a/Documentation/git-web--browse.txt b/Documentation/git-web--browse.txt
index e80a7c1..7f7a45b 100644
--- a/Documentation/git-web--browse.txt
+++ b/Documentation/git-web--browse.txt
@@ -7,7 +7,7 @@
 
 SYNOPSIS
 --------
-'git-web--browse' [OPTIONS] URL/FILE ...
+'git web--browse' [OPTIONS] URL/FILE ...
 
 DESCRIPTION
 -----------
@@ -70,14 +70,14 @@
 When the browser, specified by options or configuration variables, is
 not among the supported ones, then the corresponding
 'browser.<tool>.cmd' configuration variable will be looked up. If this
-variable exists then "git web--browse" will treat the specified tool
+variable exists then 'git-web--browse' will treat the specified tool
 as a custom command and will use a shell eval to run the command with
 the URLs passed as arguments.
 
 Note about konqueror
 --------------------
 
-When 'konqueror' is specified by the a command line option or a
+When 'konqueror' is specified by a command line option or a
 configuration variable, we launch 'kfmclient' to try to open the HTML
 man page on an already opened konqueror in a new tab if possible.
 
@@ -96,7 +96,7 @@
 		cmd = A_PATH_TO/konqueror
 ------------------------------------------------
 
-Note about git config --global
+Note about git-config --global
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Note that these configuration variables should probably be set using
@@ -112,7 +112,7 @@
 Author
 ------
 Written by Christian Couder <chriscool@tuxfamily.org> and the git-list
-<git@vger.kernel.org>, based on git-mergetool by Theodore Y. Ts'o.
+<git@vger.kernel.org>, based on 'git-mergetool' by Theodore Y. Ts'o.
 
 Documentation
 -------------
diff --git a/Documentation/git-whatchanged.txt b/Documentation/git-whatchanged.txt
index fb672ea..cadfbd9 100644
--- a/Documentation/git-whatchanged.txt
+++ b/Documentation/git-whatchanged.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-whatchanged' <option>...
+'git whatchanged' <option>...
 
 DESCRIPTION
 -----------
@@ -52,12 +52,12 @@
 
 Examples
 --------
-git-whatchanged -p v2.6.12.. include/scsi drivers/scsi::
+git whatchanged -p v2.6.12.. include/scsi drivers/scsi::
 
 	Show as patches the commits since version 'v2.6.12' that changed
 	any file in the include/scsi or drivers/scsi subdirectories
 
-git-whatchanged --since="2 weeks ago" \-- gitk::
+git whatchanged --since="2 weeks ago" \-- gitk::
 
 	Show the changes during the last two weeks to the file 'gitk'.
 	The "--" is necessary to avoid confusion with the *branch* named
diff --git a/Documentation/git-write-tree.txt b/Documentation/git-write-tree.txt
index 8744f65..26d3850 100644
--- a/Documentation/git-write-tree.txt
+++ b/Documentation/git-write-tree.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git-write-tree' [--missing-ok] [--prefix=<prefix>/]
+'git write-tree' [--missing-ok] [--prefix=<prefix>/]
 
 DESCRIPTION
 -----------
@@ -16,17 +16,17 @@
 
 The index must be in a fully merged state.
 
-Conceptually, `git-write-tree` sync()s the current index contents
+Conceptually, 'git-write-tree' sync()s the current index contents
 into a set of tree files.
 In order to have that match what is actually in your directory right
-now, you need to have done a `git-update-index` phase before you did the
-`git-write-tree`.
+now, you need to have done a 'git-update-index' phase before you did the
+'git-write-tree'.
 
 
 OPTIONS
 -------
 --missing-ok::
-	Normally `git-write-tree` ensures that the objects referenced by the
+	Normally 'git-write-tree' ensures that the objects referenced by the
 	directory exist in the object database.  This option disables this
 	check.
 
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 0f55f80..df420ae 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -20,11 +20,11 @@
 unusually rich command set that provides both high-level operations
 and full access to internals.
 
-See this linkgit:gittutorial[7][tutorial] to get started, then see
+See linkgit:gittutorial[7] to get started, then see
 link:everyday.html[Everyday Git] for a useful minimum set of commands, and
 "man git-commandname" for documentation of each command.  CVS users may
-also want to read linkgit:gitcvs-migration[7][CVS migration].  See
-link:user-manual.html[Git User's Manual] for a more in-depth
+also want to read linkgit:gitcvs-migration[7].  See
+the link:user-manual.html[Git User's Manual] for a more in-depth
 introduction.
 
 The COMMAND is either a name of a Git command (see below) or an alias
@@ -43,6 +43,13 @@
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
+* link:v1.6.0.2/git.html[documentation for release 1.6.0.2]
+
+* release notes for
+  link:RelNotes-1.6.0.2.txt[1.6.0.2],
+  link:RelNotes-1.6.0.1.txt[1.6.0.1],
+  link:RelNotes-1.6.0.txt[1.6.0].
+
 * link:v1.5.6.5/git.html[documentation for release 1.5.6.5]
 
 * release notes for
@@ -139,13 +146,13 @@
 +
 Other options are available to control how the manual page is
 displayed. See linkgit:git-help[1] for more information,
-because 'git --help ...' is converted internally into 'git
-help ...'.
+because `git --help ...` is converted internally into `git
+help ...`.
 
 --exec-path::
 	Path to wherever your core git programs are installed.
 	This can also be controlled by setting the GIT_EXEC_PATH
-	environment variable. If no path is given 'git' will print
+	environment variable. If no path is given, 'git' will print
 	the current setting and then exit.
 
 -p::
@@ -186,13 +193,14 @@
 probably more detail than necessary for a first-time user.
 
 The link:user-manual.html#git-concepts[git concepts chapter of the
-user-manual] and the linkgit:gitcore-tutorial[7][Core tutorial] both provide
+user-manual] and linkgit:gitcore-tutorial[7] both provide
 introductions to the underlying git architecture.
 
 See also the link:howto-index.html[howto] documents for some useful
 examples.
 
-The internals are documented link:technical/api-index.html[here].
+The internals are documented in the
+link:technical/api-index.html[GIT API documentation].
 
 GIT COMMANDS
 ------------
@@ -376,10 +384,9 @@
 File/Directory Structure
 ------------------------
 
-Please see the linkgit:gitrepository-layout[5][repository layout]
-document.
+Please see the linkgit:gitrepository-layout[5] document.
 
-Read linkgit:githooks[5][hooks] for more details about each hook.
+Read linkgit:githooks[5] for more details about each hook.
 
 Higher level SCMs may provide and manage additional information in the
 `$GIT_DIR`.
@@ -387,7 +394,7 @@
 
 Terminology
 -----------
-Please see the linkgit:gitglossary[7][glossary] document.
+Please see linkgit:gitglossary[7].
 
 
 Environment Variables
@@ -414,9 +421,9 @@
 'GIT_ALTERNATE_OBJECT_DIRECTORIES'::
 	Due to the immutable nature of git objects, old objects can be
 	archived into shared, read-only directories. This variable
-	specifies a ":" separated list of git object directories which
-	can be used to search for git objects. New objects will not be
-	written to these directories.
+	specifies a ":" separated (on Windows ";" separated) list
+	of git object directories which can be used to search for git
+	objects. New objects will not be written to these directories.
 
 'GIT_DIR'::
 	If the 'GIT_DIR' environment variable is set then it
@@ -430,6 +437,14 @@
 	This can also be controlled by the '--work-tree' command line
 	option and the core.worktree configuration variable.
 
+'GIT_CEILING_DIRECTORIES'::
+	This should be a colon-separated list of absolute paths.
+	If set, it is a list of directories that git should not chdir
+	up into while looking for a repository directory.
+	It will not exclude the current working directory or
+	a GIT_DIR set on the command line or in the environment.
+	(Useful for excluding slow-loading network directories.)
+
 git Commits
 ~~~~~~~~~~~
 'GIT_AUTHOR_NAME'::
@@ -484,13 +499,14 @@
 'GIT_PAGER'::
 	This environment variable overrides `$PAGER`. If it is set
 	to an empty string or to the value "cat", git will not launch
-	a pager.
+	a pager.  See also the `core.pager` option in
+	linkgit:git-config[1].
 
 'GIT_SSH'::
-	If this environment variable is set then linkgit:git-fetch[1]
-	and linkgit:git-push[1] will use this command instead
-	of `ssh` when they need to connect to a remote system.
-	The 'GIT_SSH' command will be given exactly two arguments:
+	If this environment variable is set then 'git-fetch'
+	and 'git-push' will use this command instead
+	of 'ssh' when they need to connect to a remote system.
+	The '$GIT_SSH' command will be given exactly two arguments:
 	the 'username@host' (or just 'host') from the URL and the
 	shell command to execute on that remote system.
 +
@@ -504,8 +520,8 @@
 
 'GIT_FLUSH'::
 	If this environment variable is set to "1", then commands such
-	as git-blame (in incremental mode), git-rev-list, git-log,
-	git-whatchanged, etc., will force a flush of the output stream
+	as 'git-blame' (in incremental mode), 'git-rev-list', 'git-log',
+	and 'git-whatchanged' will force a flush of the output stream
 	after each commit-oriented record have been flushed.   If this
 	variable is set to "0", the output of these commands will be done
 	using completely buffered I/O.   If this environment variable is
@@ -531,7 +547,7 @@
 
 More detail on the following is available from the
 link:user-manual.html#git-concepts[git concepts chapter of the
-user-manual] and the linkgit:gitcore-tutorial[7][Core tutorial].
+user-manual] and linkgit:gitcore-tutorial[7].
 
 A git project normally consists of a working directory with a ".git"
 subdirectory at the top level.  The .git directory contains, among other
@@ -595,9 +611,9 @@
 SEE ALSO
 --------
 linkgit:gittutorial[7], linkgit:gittutorial-2[7],
-linkgit:giteveryday[7], linkgit:gitcvs-migration[7],
+link:everyday.html[Everyday Git], linkgit:gitcvs-migration[7],
 linkgit:gitglossary[7], linkgit:gitcore-tutorial[7],
-link:user-manual.html[The Git User's Manual]
+linkgit:gitcli[7], link:user-manual.html[The Git User's Manual]
 
 GIT
 ---
diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt
index ef06d94..37fff20 100644
--- a/Documentation/gitattributes.txt
+++ b/Documentation/gitattributes.txt
@@ -7,7 +7,7 @@
 
 SYNOPSIS
 --------
-$GIT_DIR/info/attributes, gitattributes
+$GIT_DIR/info/attributes, .gitattributes
 
 
 DESCRIPTION
@@ -87,9 +87,9 @@
 
 These attributes affect how the contents stored in the
 repository are copied to the working tree files when commands
-such as `git checkout` and `git merge` run.  They also affect how
+such as 'git-checkout' and 'git-merge' run.  They also affect how
 git stores the contents you prepare in the working tree in the
-repository upon `git add` and `git commit`.
+repository upon 'git-add' and 'git-commit'.
 
 `crlf`
 ^^^^^^
@@ -105,9 +105,8 @@
 
 Unset::
 
-	Unsetting the `crlf` attribute on a path is meant to
-	mark the path as a "binary" file.  The path never goes
-	through line endings conversion upon checkin/checkout.
+	Unsetting the `crlf` attribute on a path tells git not to
+	attempt any end-of-line conversion upon checkin or checkout.
 
 Unspecified::
 
@@ -148,24 +147,24 @@
 a conversion done to the files in the work tree, but there are a
 few exceptions.  Even though...
 
-- "git add" itself does not touch the files in the work tree, the
+- 'git-add' itself does not touch the files in the work tree, the
   next checkout would, so the safety triggers;
 
-- "git apply" to update a text file with a patch does touch the files
+- 'git-apply' to update a text file with a patch does touch the files
   in the work tree, but the operation is about text files and CRLF
   conversion is about fixing the line ending inconsistencies, so the
   safety does not trigger;
 
-- "git diff" itself does not touch the files in the work tree, it is
-  often run to inspect the changes you intend to next "git add".  To
+- 'git-diff' itself does not touch the files in the work tree, it is
+  often run to inspect the changes you intend to next 'git-add'.  To
   catch potential problems early, safety triggers.
 
 
 `ident`
 ^^^^^^^
 
-When the attribute `ident` is set to a path, git replaces
-`$Id$` in the blob object with `$Id:`, followed by
+When the attribute `ident` is set for a path, git replaces
+`$Id$` in the blob object with `$Id:`, followed by the
 40-character hexadecimal blob object name, followed by a dollar
 sign `$` upon checkout.  Any byte sequence that begins with
 `$Id:` and ends with `$` in the worktree file is replaced
@@ -214,7 +213,10 @@
 Generating diff text
 ~~~~~~~~~~~~~~~~~~~~
 
-The attribute `diff` affects if `git diff` generates textual
+`diff`
+^^^^^^
+
+The attribute `diff` affects if 'git-diff' generates textual
 patch for the path or just says `Binary files differ`.  It also
 can affect what line is shown on the hunk header `@@ -k,l +n,m @@`
 line.
@@ -271,31 +273,31 @@
 Defining a custom hunk-header
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-Each group of changes (called "hunk") in the textual diff output
+Each group of changes (called a "hunk") in the textual diff output
 is prefixed with a line of the form:
 
 	@@ -k,l +n,m @@ TEXT
 
-The text is called 'hunk header', and by default a line that
-begins with an alphabet, an underscore or a dollar sign is used,
-which matches what GNU `diff -p` output uses.  This default
-selection however is not suited for some contents, and you can
-use customized pattern to make a selection.
+This is called a 'hunk header'.  The "TEXT" portion is by default a line
+that begins with an alphabet, an underscore or a dollar sign; this
+matches what GNU 'diff -p' output uses.  This default selection however
+is not suited for some contents, and you can use a customized pattern
+to make a selection.
 
-First in .gitattributes, you would assign the `diff` attribute
+First, in .gitattributes, you would assign the `diff` attribute
 for paths.
 
 ------------------------
 *.tex	diff=tex
 ------------------------
 
-Then, you would define "diff.tex.funcname" configuration to
+Then, you would define a "diff.tex.xfuncname" configuration to
 specify a regular expression that matches a line that you would
-want to appear as the hunk header, like this:
+want to appear as the hunk header "TEXT", like this:
 
 ------------------------
 [diff "tex"]
-	funcname = "^\\(\\\\\\(sub\\)*section{.*\\)$"
+	xfuncname = "^(\\\\(sub)*section\\{.*)$"
 ------------------------
 
 Note.  A single level of backslashes are eaten by the
@@ -307,14 +309,26 @@
 There are a few built-in patterns to make this easier, and `tex`
 is one of them, so you do not have to write the above in your
 configuration file (you still need to enable this with the
-attribute mechanism, via `.gitattributes`).  Another built-in
-pattern is defined for `java` that defines a pattern suitable
-for program text in Java language.
+attribute mechanism, via `.gitattributes`).  The following built in
+patterns are available:
+
+- `bibtex` suitable for files with BibTeX coded references.
+
+- `java` suitable for source code in the Java language.
+
+- `pascal` suitable for source code in the Pascal/Delphi language.
+
+- `ruby` suitable for source code in the Ruby language.
+
+- `tex` suitable for source code for LaTeX documents.
 
 
 Performing a three-way merge
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+`merge`
+^^^^^^^
+
 The attribute `merge` affects how three versions of a file is
 merged when a file-level merge is necessary during `git merge`,
 and other programs such as `git revert` and `git cherry-pick`.
@@ -322,7 +336,7 @@
 Set::
 
 	Built-in 3-way merge driver is used to merge the
-	contents in a way similar to `merge` command of `RCS`
+	contents in a way similar to 'merge' command of `RCS`
 	suite.  This is suitable for ordinary text files.
 
 Unset::
@@ -426,7 +440,7 @@
 ^^^^^^^^^^^^
 
 The `core.whitespace` configuration variable allows you to define what
-`diff` and `apply` should consider whitespace errors for all paths in
+'diff' and 'apply' should consider whitespace errors for all paths in
 the project (See linkgit:git-config[1]).  This attribute gives you finer
 control per path.
 
@@ -453,12 +467,18 @@
 Creating an archive
 ~~~~~~~~~~~~~~~~~~~
 
+`export-ignore`
+^^^^^^^^^^^^^^^
+
+Files and directories with the attribute `export-ignore` won't be added to
+archive files.
+
 `export-subst`
 ^^^^^^^^^^^^^^
 
 If the attribute `export-subst` is set for a file then git will expand
 several placeholders when adding this file to an archive.  The
-expansion depends on the availability of a commit ID, i.e. if
+expansion depends on the availability of a commit ID, i.e., if
 linkgit:git-archive[1] has been given a tree instead of a commit or a
 tag then no replacement will be done.  The placeholders are the same
 as those for the option `--pretty=format:` of linkgit:git-log[1],
@@ -467,6 +487,41 @@
 commit hash.
 
 
+USING ATTRIBUTE MACROS
+----------------------
+
+You do not want any end-of-line conversions applied to, nor textual diffs
+produced for, any binary file you track.  You would need to specify e.g.
+
+------------
+*.jpg -crlf -diff
+------------
+
+but that may become cumbersome, when you have many attributes.  Using
+attribute macros, you can specify groups of attributes set or unset at
+the same time.  The system knows a built-in attribute macro, `binary`:
+
+------------
+*.jpg binary
+------------
+
+which is equivalent to the above.  Note that the attribute macros can only
+be "Set" (see the above example that sets "binary" macro as if it were an
+ordinary attribute --- setting it in turn unsets "crlf" and "diff").
+
+
+DEFINING ATTRIBUTE MACROS
+-------------------------
+
+Custom attribute macros can be defined only in the `.gitattributes` file
+at the toplevel (i.e. not in any subdirectory).  The built-in attribute
+macro "binary" is equivalent to:
+
+------------
+[attr]binary -diff -crlf
+------------
+
+
 EXAMPLE
 -------
 
diff --git a/Documentation/gitcli.txt b/Documentation/gitcli.txt
index 8fb5d88..29e5929 100644
--- a/Documentation/gitcli.txt
+++ b/Documentation/gitcli.txt
@@ -13,8 +13,37 @@
 DESCRIPTION
 -----------
 
-This manual describes best practice in how to use git CLI.  Here are
-the rules that you should follow when you are scripting git:
+This manual describes the convention used throughout git CLI.
+
+Many commands take revisions (most often "commits", but sometimes
+"tree-ish", depending on the context and command) and paths as their
+arguments.  Here are the rules:
+
+ * Revisions come first and then paths.
+   E.g. in `git diff v1.0 v2.0 arch/x86 include/asm-x86`,
+   `v1.0` and `v2.0` are revisions and `arch/x86` and `include/asm-x86`
+   are paths.
+
+ * When an argument can be misunderstood as either a revision or a path,
+   they can be disambiguated by placing `\--` between them.
+   E.g. `git diff \-- HEAD` is, "I have a file called HEAD in my work
+   tree.  Please show changes between the version I staged in the index
+   and what I have in the work tree for that file". not "show difference
+   between the HEAD commit and the work tree as a whole".  You can say
+   `git diff HEAD \--` to ask for the latter.
+
+ * Without disambiguating `\--`, git makes a reasonable guess, but errors
+   out and asking you to disambiguate when ambiguous.  E.g. if you have a
+   file called HEAD in your work tree, `git diff HEAD` is ambiguous, and
+   you have to say either `git diff HEAD \--` or `git diff \-- HEAD` to
+   disambiguate.
+
+When writing a script that is expected to handle random user-input, it is
+a good practice to make it explicit which arguments are which by placing
+disambiguating `\--` at appropriate places.
+
+Here are the rules regarding the "flags" that you should follow when you are
+scripting git:
 
  * it's preferred to use the non dashed form of git commands, which means that
    you should prefer `"git foo"` to `"git-foo"`.
@@ -34,8 +63,8 @@
    if you happen to have a file called `HEAD` in the work tree.
 
 
-ENHANCED CLI
-------------
+ENHANCED OPTION PARSER
+----------------------
 From the git 1.5.4 series and further, many git commands (not all of them at the
 time of the writing though) come with an enhanced option parser.
 
@@ -104,9 +133,45 @@
 ----------------------------
 
 
+NOTES ON FREQUENTLY CONFUSED OPTIONS
+------------------------------------
+
+Many commands that can work on files in the working tree
+and/or in the index can take `--cached` and/or `--index`
+options.  Sometimes people incorrectly think that, because
+the index was originally called cache, these two are
+synonyms.  They are *not* -- these two options mean very
+different things.
+
+ * The `--cached` option is used to ask a command that
+   usually works on files in the working tree to *only* work
+   with the index.  For example, `git grep`, when used
+   without a commit to specify from which commit to look for
+   strings in, usually works on files in the working tree,
+   but with the `--cached` option, it looks for strings in
+   the index.
+
+ * The `--index` option is used to ask a command that
+   usually works on files in the working tree to *also*
+   affect the index.  For example, `git stash apply` usually
+   merges changes recorded in a stash to the working tree,
+   but with the `--index` option, it also merges changes to
+   the index as well.
+
+`git apply` command can be used with `--cached` and
+`--index` (but not at the same time).  Usually the command
+only affects the files in the working tree, but with
+`--index`, it patches both the files and their index
+entries, and with `--cached`, it modifies only the index
+entries.
+
+See also http://marc.info/?l=git&m=116563135620359 and
+http://marc.info/?l=git&m=119150393620273 for further
+information.
+
 Documentation
 -------------
-Documentation by Pierre Habouzit.
+Documentation by Pierre Habouzit and the git-list <git@vger.kernel.org>.
 
 GIT
 ---
diff --git a/Documentation/gitcore-tutorial.txt b/Documentation/gitcore-tutorial.txt
index cb4ec40..896cbdf 100644
--- a/Documentation/gitcore-tutorial.txt
+++ b/Documentation/gitcore-tutorial.txt
@@ -16,8 +16,8 @@
 work with a git repository.
 
 If you just need to use git as a revision control system you may prefer
-to start with linkgit:gittutorial[7][a tutorial introduction to git] or
-link:user-manual.html[the git user manual].
+to start with "A Tutorial Introduction to GIT" (linkgit:gittutorial[7]) or
+link:user-manual.html[the GIT User Manual].
 
 However, an understanding of these low-level tools can be helpful if
 you want to understand git's internals.
@@ -42,14 +42,14 @@
 to import into git.
 
 For our first example, we're going to start a totally new repository from
-scratch, with no pre-existing files, and we'll call it `git-tutorial`.
+scratch, with no pre-existing files, and we'll call it 'git-tutorial'.
 To start up, create a subdirectory for it, change into that
-subdirectory, and initialize the git infrastructure with `git-init`:
+subdirectory, and initialize the git infrastructure with 'git-init':
 
 ------------------------------------------------
 $ mkdir git-tutorial
 $ cd git-tutorial
-$ git-init
+$ git init
 ------------------------------------------------
 
 to which git will reply
@@ -61,7 +61,7 @@
 which is just git's way of saying that you haven't been doing anything
 strange, and that it will have created a local `.git` directory setup for
 your new project. You will now have a `.git` directory, and you can
-inspect that with `ls`. For your new empty project, it should show you
+inspect that with 'ls'. For your new empty project, it should show you
 three entries, among other things:
 
  - a file called `HEAD`, that has `ref: refs/heads/master` in it.
@@ -108,8 +108,7 @@
 populating your tree.
 
 [NOTE]
-An advanced user may want to take a look at the
-linkgit:gitrepository-layout[5][repository layout] document
+An advanced user may want to take a look at linkgit:gitrepository-layout[5]
 after finishing this tutorial.
 
 You have now created your first git repository. Of course, since it's
@@ -140,7 +139,7 @@
  - commit that index file as an object.
 
 The first step is trivial: when you want to tell git about any changes
-to your working tree, you use the `git-update-index` program. That
+to your working tree, you use the 'git-update-index' program. That
 program normally just takes a list of filenames you want to update, but
 to avoid trivial mistakes, it refuses to add new entries to the index
 (or remove existing ones) unless you explicitly tell it that you're
@@ -150,7 +149,7 @@
 So to populate the index with the two files you just created, you can do
 
 ------------------------------------------------
-$ git-update-index --add hello example
+$ git update-index --add hello example
 ------------------------------------------------
 
 and you have now told git to track those two files.
@@ -174,19 +173,19 @@
 which correspond with the objects with names of `557db...` and
 `f24c7...` respectively.
 
-If you want to, you can use `git-cat-file` to look at those objects, but
+If you want to, you can use 'git-cat-file' to look at those objects, but
 you'll have to use the object name, not the filename of the object:
 
 ----------------
-$ git-cat-file -t 557db03de997c86a4a028e1ebd3a1ceb225be238
+$ git cat-file -t 557db03de997c86a4a028e1ebd3a1ceb225be238
 ----------------
 
-where the `-t` tells `git-cat-file` to tell you what the "type" of the
+where the `-t` tells 'git-cat-file' to tell you what the "type" of the
 object is. git will tell you that you have a "blob" object (i.e., just a
 regular file), and you can see the contents with
 
 ----------------
-$ git-cat-file "blob" 557db03
+$ git cat-file "blob" 557db03
 ----------------
 
 which will print out "Hello World". The object `557db03` is nothing
@@ -206,7 +205,7 @@
 Anyway, as we mentioned previously, you normally never actually take a
 look at the objects themselves, and typing long 40-character hex
 names is not something you'd normally want to do. The above digression
-was just to show that `git-update-index` did something magical, and
+was just to show that 'git-update-index' did something magical, and
 actually saved away the contents of your files into the git object
 database.
 
@@ -229,22 +228,22 @@
 
 and you can now, since you told git about the previous state of `hello`, ask
 git what has changed in the tree compared to your old index, using the
-`git-diff-files` command:
+'git-diff-files' command:
 
 ------------
-$ git-diff-files
+$ git diff-files
 ------------
 
 Oops. That wasn't very readable. It just spit out its own internal
-version of a `diff`, but that internal version really just tells you
+version of a 'diff', but that internal version really just tells you
 that it has noticed that "hello" has been modified, and that the old object
 contents it had have been replaced with something else.
 
-To make it readable, we can tell git-diff-files to output the
+To make it readable, we can tell 'git-diff-files' to output the
 differences as a patch, using the `-p` flag:
 
 ------------
-$ git-diff-files -p
+$ git diff-files -p
 diff --git a/hello b/hello
 index 557db03..263414f 100644
 --- a/hello
@@ -256,11 +255,11 @@
 
 i.e. the diff of the change we caused by adding another line to `hello`.
 
-In other words, `git-diff-files` always shows us the difference between
+In other words, 'git-diff-files' always shows us the difference between
 what is recorded in the index, and what is currently in the working
 tree. That's very useful.
 
-A common shorthand for `git-diff-files -p` is to just write `git
+A common shorthand for `git diff-files -p` is to just write `git
 diff`, which will do the same thing.
 
 ------------
@@ -284,15 +283,15 @@
 object as a 'commit' object together with an explanation of what the
 tree was all about, along with information of how we came to that state.
 
-Creating a tree object is trivial, and is done with `git-write-tree`.
-There are no options or other input: git-write-tree will take the
+Creating a tree object is trivial, and is done with 'git-write-tree'.
+There are no options or other input: `git write-tree` will take the
 current index state, and write an object that describes that whole
 index. In other words, we're now tying together all the different
 filenames with their contents (and their permissions), and we're
 creating the equivalent of a git "directory" object:
 
 ------------------------------------------------
-$ git-write-tree
+$ git write-tree
 ------------------------------------------------
 
 and this will just output the name of the resulting tree, in this case
@@ -303,34 +302,34 @@
 ----------------
 
 which is another incomprehensible object name. Again, if you want to,
-you can use `git-cat-file -t 8988d\...` to see that this time the object
+you can use `git cat-file -t 8988d\...` to see that this time the object
 is not a "blob" object, but a "tree" object (you can also use
-`git-cat-file` to actually output the raw object contents, but you'll see
+`git cat-file` to actually output the raw object contents, but you'll see
 mainly a binary mess, so that's less interesting).
 
-However -- normally you'd never use `git-write-tree` on its own, because
+However -- normally you'd never use 'git-write-tree' on its own, because
 normally you always commit a tree into a commit object using the
-`git-commit-tree` command. In fact, it's easier to not actually use
-`git-write-tree` on its own at all, but to just pass its result in as an
-argument to `git-commit-tree`.
+'git-commit-tree' command. In fact, it's easier to not actually use
+'git-write-tree' on its own at all, but to just pass its result in as an
+argument to 'git-commit-tree'.
 
-`git-commit-tree` normally takes several arguments -- it wants to know
+'git-commit-tree' normally takes several arguments -- it wants to know
 what the 'parent' of a commit was, but since this is the first commit
 ever in this new repository, and it has no parents, we only need to pass in
-the object name of the tree. However, `git-commit-tree` also wants to get a
+the object name of the tree. However, 'git-commit-tree' also wants to get a
 commit message on its standard input, and it will write out the resulting
 object name for the commit to its standard output.
 
 And this is where we create the `.git/refs/heads/master` file
 which is pointed at by `HEAD`. This file is supposed to contain
 the reference to the top-of-tree of the master branch, and since
-that's exactly what `git-commit-tree` spits out, we can do this
+that's exactly what 'git-commit-tree' spits out, we can do this
 all with a sequence of simple shell commands:
 
 ------------------------------------------------
-$ tree=$(git-write-tree)
-$ commit=$(echo 'Initial commit' | git-commit-tree $tree)
-$ git-update-ref HEAD $commit
+$ tree=$(git write-tree)
+$ commit=$(echo 'Initial commit' | git commit-tree $tree)
+$ git update-ref HEAD $commit
 ------------------------------------------------
 
 In this case this creates a totally new commit that is not related to
@@ -346,37 +345,37 @@
 Making a change
 ---------------
 
-Remember how we did the `git-update-index` on file `hello` and then we
+Remember how we did the 'git-update-index' on file `hello` and then we
 changed `hello` afterward, and could compare the new state of `hello` with the
 state we saved in the index file?
 
-Further, remember how I said that `git-write-tree` writes the contents
+Further, remember how I said that 'git-write-tree' writes the contents
 of the *index* file to the tree, and thus what we just committed was in
 fact the *original* contents of the file `hello`, not the new ones. We did
 that on purpose, to show the difference between the index state, and the
 state in the working tree, and how they don't have to match, even
 when we commit things.
 
-As before, if we do `git-diff-files -p` in our git-tutorial project,
+As before, if we do `git diff-files -p` in our git-tutorial project,
 we'll still see the same difference we saw last time: the index file
 hasn't changed by the act of committing anything. However, now that we
 have committed something, we can also learn to use a new command:
-`git-diff-index`.
+'git-diff-index'.
 
-Unlike `git-diff-files`, which showed the difference between the index
-file and the working tree, `git-diff-index` shows the differences
+Unlike 'git-diff-files', which showed the difference between the index
+file and the working tree, 'git-diff-index' shows the differences
 between a committed *tree* and either the index file or the working
-tree. In other words, `git-diff-index` wants a tree to be diffed
+tree. In other words, 'git-diff-index' wants a tree to be diffed
 against, and before we did the commit, we couldn't do that, because we
 didn't have anything to diff against.
 
 But now we can do
 
 ----------------
-$ git-diff-index -p HEAD
+$ git diff-index -p HEAD
 ----------------
 
-(where `-p` has the same meaning as it did in `git-diff-files`), and it
+(where `-p` has the same meaning as it did in 'git-diff-files'), and it
 will show us the same difference, but for a totally different reason.
 Now we're comparing the working tree not against the index file,
 but against the tree we just wrote. It just so happens that those two
@@ -391,16 +390,16 @@
 
 which ends up doing the above for you.
 
-In other words, `git-diff-index` normally compares a tree against the
+In other words, 'git-diff-index' normally compares a tree against the
 working tree, but when given the `\--cached` flag, it is told to
 instead compare against just the index cache contents, and ignore the
 current working tree state entirely. Since we just wrote the index
-file to HEAD, doing `git-diff-index \--cached -p HEAD` should thus return
+file to HEAD, doing `git diff-index \--cached -p HEAD` should thus return
 an empty set of differences, and that's exactly what it does.
 
 [NOTE]
 ================
-`git-diff-index` really always uses the index for its
+'git-diff-index' really always uses the index for its
 comparisons, and saying that it compares a tree against the working
 tree is thus not strictly accurate. In particular, the list of
 files to compare (the "meta-data") *always* comes from the index file,
@@ -423,17 +422,17 @@
 update the index cache:
 
 ------------------------------------------------
-$ git-update-index hello
+$ git update-index hello
 ------------------------------------------------
 
 (note how we didn't need the `\--add` flag this time, since git knew
 about the file already).
 
-Note what happens to the different `git-diff-\*` versions here. After
-we've updated `hello` in the index, `git-diff-files -p` now shows no
-differences, but `git-diff-index -p HEAD` still *does* show that the
+Note what happens to the different 'git-diff-\*' versions here. After
+we've updated `hello` in the index, `git diff-files -p` now shows no
+differences, but `git diff-index -p HEAD` still *does* show that the
 current state is different from the state we committed. In fact, now
-`git-diff-index` shows the same difference whether we use the `--cached`
+'git-diff-index' shows the same difference whether we use the `--cached`
 flag or not, since now the index is coherent with the working tree.
 
 Now, since we've updated `hello` in the index, we can commit the new
@@ -461,7 +460,7 @@
 looking at what `git commit` really does, feel free to investigate:
 it's a few very simple shell scripts to generate the helpful (?) commit
 message headers, and a few one-liners that actually do the
-commit itself (`git-commit`).
+commit itself ('git-commit').
 
 
 Inspecting Changes
@@ -469,16 +468,16 @@
 
 While creating changes is useful, it's even more useful if you can tell
 later what changed. The most useful command for this is another of the
-`diff` family, namely `git-diff-tree`.
+'diff' family, namely 'git-diff-tree'.
 
-`git-diff-tree` can be given two arbitrary trees, and it will tell you the
+'git-diff-tree' can be given two arbitrary trees, and it will tell you the
 differences between them. Perhaps even more commonly, though, you can
 give it just a single commit object, and it will figure out the parent
 of that commit itself, and show the difference directly. Thus, to get
 the same diff that we've already seen several times, we can now do
 
 ----------------
-$ git-diff-tree -p HEAD
+$ git diff-tree -p HEAD
 ----------------
 
 (again, `-p` means to show the difference as a human-readable patch),
@@ -519,15 +518,15 @@
                     +-----------+
 ============
 
-More interestingly, you can also give `git-diff-tree` the `--pretty` flag,
+More interestingly, you can also give 'git-diff-tree' the `--pretty` flag,
 which tells it to also show the commit message and author and date of the
 commit, and you can tell it to show a whole series of diffs.
 Alternatively, you can tell it to be "silent", and not show the diffs at
 all, but just show the actual commit message.
 
-In fact, together with the `git-rev-list` program (which generates a
-list of revisions), `git-diff-tree` ends up being a veritable fount of
-changes. A trivial (but very useful) script called `git-whatchanged` is
+In fact, together with the 'git-rev-list' program (which generates a
+list of revisions), 'git-diff-tree' ends up being a veritable fount of
+changes. A trivial (but very useful) script called 'git-whatchanged' is
 included with git which does exactly this, and shows a log of recent
 activities.
 
@@ -543,7 +542,7 @@
 powerful)
 
 ----------------
-$ git-whatchanged -p
+$ git whatchanged -p
 ----------------
 
 and you will see exactly what has changed in the repository over its
@@ -554,14 +553,14 @@
 If this is a problem because it is huge, you can hide it by setting
 the log.showroot configuration variable to false. Having this, you
 can still show it for each command just adding the `\--root` option,
-which is a flag for `git-diff-tree` accepted by both commands.
+which is a flag for 'git-diff-tree' accepted by both commands.
 
 With that, you should now be having some inkling of what git does, and
 can explore on your own.
 
 [NOTE]
 Most likely, you are not directly using the core
-git Plumbing commands, but using Porcelain such as `git-add`, `git-rm'
+git Plumbing commands, but using Porcelain such as 'git-add', `git-rm'
 and `git-commit'.
 
 
@@ -596,7 +595,7 @@
 message, along with optionally a PGP signature that says that yes,
 you really did
 that tag. You create these annotated tags with either the `-a` or
-`-s` flag to `git tag`:
+`-s` flag to 'git-tag':
 
 ----------------
 $ git tag -s <tagname>
@@ -643,7 +642,7 @@
 history outside the project you created.
 
  - if you want to move or duplicate a git repository, you can do so. There
-   is `git clone` command, but if all you want to do is just to
+   is 'git-clone' command, but if all you want to do is just to
    create a copy of your repository (with all the full history that
    went along with it), you can do so with a regular
    `cp -a git-tutorial new-git-tutorial`.
@@ -654,31 +653,31 @@
 So after you do a `cp -a` to create a new copy, you'll want to do
 +
 ----------------
-$ git-update-index --refresh
+$ git update-index --refresh
 ----------------
 +
 in the new repository to make sure that the index file is up-to-date.
 
 Note that the second point is true even across machines. You can
 duplicate a remote git repository with *any* regular copy mechanism, be it
-`scp`, `rsync` or `wget`.
+'scp', 'rsync' or 'wget'.
 
 When copying a remote repository, you'll want to at a minimum update the
 index cache when you do this, and especially with other peoples'
 repositories you often want to make sure that the index cache is in some
 known state (you don't know *what* they've done and not yet checked in),
-so usually you'll precede the `git-update-index` with a
+so usually you'll precede the 'git-update-index' with a
 
 ----------------
-$ git-read-tree --reset HEAD
-$ git-update-index --refresh
+$ git read-tree --reset HEAD
+$ git update-index --refresh
 ----------------
 
 which will force a total index re-build from the tree pointed to by `HEAD`.
-It resets the index contents to `HEAD`, and then the `git-update-index`
+It resets the index contents to `HEAD`, and then the 'git-update-index'
 makes sure to match up all index entries with the checked-out files.
 If the original repository had uncommitted changes in its
-working tree, `git-update-index --refresh` notices them and
+working tree, `git update-index --refresh` notices them and
 tells you they need to be updated.
 
 The above can also be written as simply
@@ -690,8 +689,8 @@
 and in fact a lot of the common git command combinations can be scripted
 with the `git xyz` interfaces.  You can learn things by just looking
 at what the various git scripts do.  For example, `git reset` used to be
-the above two lines implemented in `git-reset`, but some things like
-`git status` and `git commit` are slightly more complex scripts around
+the above two lines implemented in 'git-reset', but some things like
+'git-status' and 'git-commit' are slightly more complex scripts around
 the basic git commands.
 
 Many (most?) public remote repositories will not contain any of
@@ -714,7 +713,7 @@
 followed by
 
 ----------------
-$ git-read-tree HEAD
+$ git read-tree HEAD
 ----------------
 
 to populate the index. However, now you have populated the index, and
@@ -723,14 +722,14 @@
 those, you'd check them out with
 
 ----------------
-$ git-checkout-index -u -a
+$ git checkout-index -u -a
 ----------------
 
 where the `-u` flag means that you want the checkout to keep the index
 up-to-date (so that you don't have to refresh it afterward), and the
 `-a` flag means "check out all files" (if you have a stale copy or an
 older version of a checked out tree you may also need to add the `-f`
-flag first, to tell git-checkout-index to *force* overwriting of any old
+flag first, to tell 'git-checkout-index' to *force* overwriting of any old
 files).
 
 Again, this can all be simplified with
@@ -777,7 +776,7 @@
 ================================================
 If you make the decision to start your new branch at some
 other point in the history than the current `HEAD`, you can do so by
-just telling `git checkout` what the base of the checkout would be.
+just telling 'git-checkout' what the base of the checkout would be.
 In other words, if you have an earlier tag or branch, you'd just do
 
 ------------
@@ -820,7 +819,7 @@
 
 which will simply _create_ the branch, but will not do anything further.
 You can then later -- once you decide that you want to actually develop
-on that branch -- switch to that branch with a regular `git checkout`
+on that branch -- switch to that branch with a regular 'git-checkout'
 with the branchname as the argument.
 
 
@@ -840,7 +839,7 @@
 ------------------------------------------------
 
 Here, we just added another line to `hello`, and we used a shorthand for
-doing both `git-update-index hello` and `git commit` by just giving the
+doing both `git update-index hello` and `git commit` by just giving the
 filename directly to `git commit`, with an `-i` flag (it tells
 git to 'include' that file in addition to what you have done to
 the index file so far when making the commit).  The `-m` flag is to give the
@@ -879,10 +878,10 @@
 histories. You can also see exactly how they came to be from a common
 source.
 
-Anyway, let's exit `gitk` (`^Q` or the File menu), and decide that we want
+Anyway, let's exit 'gitk' (`^Q` or the File menu), and decide that we want
 to merge the work we did on the `mybranch` branch into the `master`
 branch (which is currently our `HEAD` too). To do that, there's a nice
-script called `git merge`, which wants to know which branches you want
+script called 'git-merge', which wants to know which branches you want
 to resolve and what the merge is all about:
 
 ------------
@@ -926,7 +925,7 @@
 
 which will very loudly warn you that you're now committing a merge
 (which is correct, so never mind), and you can write a small merge
-message about your adventures in git-merge-land.
+message about your adventures in 'git-merge'-land.
 
 After you're done, start up `gitk \--all` to see graphically what the
 history looks like. Notice that `mybranch` still exists, and you can
@@ -939,7 +938,7 @@
 environment, is `git show-branch`.
 
 ------------------------------------------------
-$ git-show-branch --topo-order --more=1 master mybranch
+$ git show-branch --topo-order --more=1 master mybranch
 * [master] Merge work in mybranch
  ! [mybranch] Some work.
 --
@@ -964,14 +963,14 @@
 before the commit log message is a short name you can use to
 name the commit.  In the above example, 'master' and 'mybranch'
 are branch heads.  'master^' is the first parent of 'master'
-branch head.  Please see 'git-rev-parse' documentation if you
+branch head.  Please see linkgit:git-rev-parse[1] if you want to
 see more complex cases.
 
 [NOTE]
 Without the '--more=1' option, 'git-show-branch' would not output the
 '[master^]' commit, as '[mybranch]' commit is a common ancestor of
-both 'master' and 'mybranch' tips.  Please see 'git-show-branch'
-documentation for details.
+both 'master' and 'mybranch' tips.  Please see linkgit:git-show-branch[1]
+for details.
 
 [NOTE]
 If there were more commits on the 'master' branch after the merge, the
@@ -982,7 +981,7 @@
 Now, let's pretend you are the one who did all the work in
 `mybranch`, and the fruit of your hard work has finally been merged
 to the `master` branch. Let's go back to `mybranch`, and run
-`git merge` to get the "upstream changes" back to your branch.
+'git-merge' to get the "upstream changes" back to your branch.
 
 ------------
 $ git checkout mybranch
@@ -1000,14 +999,14 @@
  2 files changed, 2 insertions(+), 0 deletions(-)
 ----------------
 
-Because your branch did not contain anything more than what are
-already merged into the `master` branch, the merge operation did
+Because your branch did not contain anything more than what had
+already been merged into the `master` branch, the merge operation did
 not actually do a merge. Instead, it just updated the top of
 the tree of your branch to that of the `master` branch. This is
 often called 'fast forward' merge.
 
 You can run `gitk \--all` again to see how the commit ancestry
-looks like, or run `show-branch`, which tells you this.
+looks like, or run 'show-branch', which tells you this.
 
 ------------------------------------------------
 $ git show-branch master mybranch
@@ -1024,12 +1023,12 @@
 It's usually much more common that you merge with somebody else than
 merging with your own branches, so it's worth pointing out that git
 makes that very easy too, and in fact, it's not that different from
-doing a `git merge`. In fact, a remote merge ends up being nothing
+doing a 'git-merge'. In fact, a remote merge ends up being nothing
 more than "fetch the work from a remote repository into a temporary tag"
-followed by a `git merge`.
+followed by a 'git-merge'.
 
 Fetching from a remote repository is done by, unsurprisingly,
-`git fetch`:
+'git-fetch':
 
 ----------------
 $ git fetch <remote-repository>
@@ -1067,9 +1066,9 @@
 Local directory::
 	`/path/to/repo.git/`
 +
-This transport is the same as SSH transport but uses `sh` to run
+This transport is the same as SSH transport but uses 'sh' to run
 both ends on the local machine instead of running other end on
-the remote machine via `ssh`.
+the remote machine via 'ssh'.
 
 git Native::
 	`git://remote.machine/path/to/repo.git/`
@@ -1096,7 +1095,7 @@
 transports', because they do not require any git aware smart
 server like git Native transport does.  Any stock HTTP server
 that does not even support directory index would suffice.  But
-you must prepare your repository with `git-update-server-info`
+you must prepare your repository with 'git-update-server-info'
 to help dumb transport downloaders.
 
 Once you fetch from the remote repository, you `merge` that
@@ -1116,7 +1115,7 @@
 [NOTE]
 You could do without using any branches at all, by
 keeping as many local repositories as you would like to have
-branches, and merging between them with `git pull`, just like
+branches, and merging between them with 'git-pull', just like
 you merge between branches. The advantage of this approach is
 that it lets you keep a set of files for each `branch` checked
 out and you may find it easier to switch back and forth if you
@@ -1133,7 +1132,7 @@
 $ git config remote.linus.url http://www.kernel.org/pub/scm/git/git.git/
 ------------------------------------------------
 
-and use the "linus" keyword with `git pull` instead of the full URL.
+and use the "linus" keyword with 'git-pull' instead of the full URL.
 
 Examples.
 
@@ -1169,7 +1168,7 @@
 +* [master^] Some fun.
 ------------
 
-Remember, before running `git merge`, our `master` head was at
+Remember, before running 'git-merge', our `master` head was at
 "Some fun." commit, while our `mybranch` head was at "Some
 work." commit.
 
@@ -1196,10 +1195,10 @@
 
 `git merge` command, when merging two branches, uses 3-way merge
 algorithm.  First, it finds the common ancestor between them.
-The command it uses is `git-merge-base`:
+The command it uses is 'git-merge-base':
 
 ------------
-$ mb=$(git-merge-base HEAD mybranch)
+$ mb=$(git merge-base HEAD mybranch)
 ------------
 
 The command writes the commit object name of the common ancestor
@@ -1209,7 +1208,7 @@
 tell it by:
 
 ------------
-$ git-name-rev $mb
+$ git name-rev $mb
 my-first-tag
 ------------
 
@@ -1217,10 +1216,10 @@
 this:
 
 ------------
-$ git-read-tree -m -u $mb HEAD mybranch
+$ git read-tree -m -u $mb HEAD mybranch
 ------------
 
-This is the same `git-read-tree` command we have already seen,
+This is the same 'git-read-tree' command we have already seen,
 but it takes three trees, unlike previous examples.  This reads
 the contents of each tree into different 'stage' in the index
 file (the first tree goes to stage 1, the second to stage 2,
@@ -1236,7 +1235,7 @@
 inspect the index file with this command:
 
 ------------
-$ git-ls-files --stage
+$ git ls-files --stage
 100644 7f8b141b65fdcee47321e399a2598a235a032422 0	example
 100644 263414f423d0e4d70dae8fe53fa34614ff3e2860 1	hello
 100644 06fa6a24256dc7e560efa5687fa84b51f0263c3a 2	hello
@@ -1253,7 +1252,7 @@
 To look at only non-zero stages, use `\--unmerged` flag:
 
 ------------
-$ git-ls-files --unmerged
+$ git ls-files --unmerged
 100644 263414f423d0e4d70dae8fe53fa34614ff3e2860 1	hello
 100644 06fa6a24256dc7e560efa5687fa84b51f0263c3a 2	hello
 100644 cc44c73eb783565da5831b4d820c962954019b69 3	hello
@@ -1261,29 +1260,29 @@
 
 The next step of merging is to merge these three versions of the
 file, using 3-way merge.  This is done by giving
-`git-merge-one-file` command as one of the arguments to
-`git-merge-index` command:
+'git-merge-one-file' command as one of the arguments to
+'git-merge-index' command:
 
 ------------
-$ git-merge-index git-merge-one-file hello
+$ git merge-index git-merge-one-file hello
 Auto-merging hello.
 merge: warning: conflicts during merge
 ERROR: Merge conflict in hello.
 fatal: merge program failed
 ------------
 
-`git-merge-one-file` script is called with parameters to
+'git-merge-one-file' script is called with parameters to
 describe those three versions, and is responsible to leave the
 merge results in the working tree.
 It is a fairly straightforward shell script, and
-eventually calls `merge` program from RCS suite to perform a
-file-level 3-way merge.  In this case, `merge` detects
+eventually calls 'merge' program from RCS suite to perform a
+file-level 3-way merge.  In this case, 'merge' detects
 conflicts, and the merge result with conflict marks is left in
 the working tree..  This can be seen if you run `ls-files
 --stage` again at this point:
 
 ------------
-$ git-ls-files --stage
+$ git ls-files --stage
 100644 7f8b141b65fdcee47321e399a2598a235a032422 0	example
 100644 263414f423d0e4d70dae8fe53fa34614ff3e2860 1	hello
 100644 06fa6a24256dc7e560efa5687fa84b51f0263c3a 2	hello
@@ -1291,9 +1290,9 @@
 ------------
 
 This is the state of the index file and the working file after
-`git merge` returns control back to you, leaving the conflicting
+'git-merge' returns control back to you, leaving the conflicting
 merge for you to resolve.  Notice that the path `hello` is still
-unmerged, and what you see with `git diff` at this point is
+unmerged, and what you see with 'git-diff' at this point is
 differences since stage 2 (i.e. your version).
 
 
@@ -1321,7 +1320,7 @@
 Publishing the changes from your local (private) repository to
 your remote (public) repository requires a write privilege on
 the remote machine. You need to have an SSH account there to
-run a single command, `git-receive-pack`.
+run a single command, 'git-receive-pack'.
 
 First, you need to create an empty repository on the remote
 machine that will house your public repository. This empty
@@ -1330,8 +1329,8 @@
 done only once.
 
 [NOTE]
-`git push` uses a pair of programs,
-`git-send-pack` on your local machine, and `git-receive-pack`
+'git-push' uses a pair of programs,
+'git-send-pack' on your local machine, and 'git-receive-pack'
 on the remote machine. The communication between the two over
 the network internally uses an SSH connection.
 
@@ -1346,30 +1345,31 @@
 ------------
 
 Then, make that directory into a git repository by running
-`git init`, but this time, since its name is not the usual
+'git-init', but this time, since its name is not the usual
 `.git`, we do things slightly differently:
 
 ------------
-$ GIT_DIR=my-git.git git-init
+$ GIT_DIR=my-git.git git init
 ------------
 
 Make sure this directory is available for others you want your
-changes to be pulled by via the transport of your choice. Also
-you need to make sure that you have the `git-receive-pack`
+changes to be pulled via the transport of your choice. Also
+you need to make sure that you have the 'git-receive-pack'
 program on the `$PATH`.
 
 [NOTE]
 Many installations of sshd do not invoke your shell as the login
 shell when you directly run programs; what this means is that if
-your login shell is `bash`, only `.bashrc` is read and not
+your login shell is 'bash', only `.bashrc` is read and not
 `.bash_profile`. As a workaround, make sure `.bashrc` sets up
-`$PATH` so that you can run `git-receive-pack` program.
+`$PATH` so that you can run 'git-receive-pack' program.
 
 [NOTE]
 If you plan to publish this repository to be accessed over http,
-you should do `chmod +x my-git.git/hooks/post-update` at this
-point.  This makes sure that every time you push into this
-repository, `git-update-server-info` is run.
+you should do `mv my-git.git/hooks/post-update.sample
+my-git.git/hooks/post-update` at this point.
+This makes sure that every time you push into this
+repository, `git update-server-info` is run.
 
 Your "public repository" is now ready to accept your changes.
 Come back to the machine you have your private repository. From
@@ -1408,7 +1408,7 @@
 
 will do it for you. If you followed the tutorial examples, you
 would have accumulated about 17 objects in `.git/objects/??/`
-directories by now. `git repack` tells you how many objects it
+directories by now. 'git-repack' tells you how many objects it
 packed, and stores the packed file in `.git/objects/pack`
 directory.
 
@@ -1421,7 +1421,7 @@
 in the pack, and the latter holds the index for random
 access.
 
-If you are paranoid, running `git-verify-pack` command would
+If you are paranoid, running 'git-verify-pack' command would
 detect if you have a corrupt pack, but do not worry too much.
 Our programs are always perfect ;-).
 
@@ -1487,18 +1487,18 @@
 If other people are pulling from your repository over dumb
 transport protocols (HTTP), you need to keep this repository
 'dumb transport friendly'.  After `git init`,
-`$GIT_DIR/hooks/post-update` copied from the standard templates
-would contain a call to `git-update-server-info` but the
-`post-update` hook itself is disabled by default -- enable it
-with `chmod +x post-update`.  This makes sure `git-update-server-info`
-keeps the necessary files up-to-date.
+`$GIT_DIR/hooks/post-update.sample` copied from the standard templates
+would contain a call to 'git-update-server-info'
+but you need to manually enable the hook with
+`mv post-update.sample post-update`.  This makes sure
+'git-update-server-info' keeps the necessary files up-to-date.
 
 3. Push into the public repository from your primary
    repository.
 
-4. `git repack` the public repository. This establishes a big
+4. 'git-repack' the public repository. This establishes a big
    pack that contains the initial set of objects as the
-   baseline, and possibly `git prune` if the transport
+   baseline, and possibly 'git-prune' if the transport
    used for pulling from your repository supports packed
    repositories.
 
@@ -1512,14 +1512,14 @@
 6. Push your changes to the public repository, and announce it
    to the public.
 
-7. Every once in a while, "git repack" the public repository.
+7. Every once in a while, 'git-repack' the public repository.
    Go back to step 5. and continue working.
 
 
 A recommended work cycle for a "subsystem maintainer" who works
 on that project and has an own "public repository" goes like this:
 
-1. Prepare your work repository, by `git clone` the public
+1. Prepare your work repository, by 'git-clone' the public
    repository of the "project lead". The URL used for the
    initial cloning is stored in the remote.origin.url
    configuration variable.
@@ -1534,7 +1534,7 @@
    point at the repository you are borrowing from.
 
 4. Push into the public repository from your primary
-   repository. Run `git repack`, and possibly `git prune` if the
+   repository. Run 'git-repack', and possibly 'git-prune' if the
    transport used for pulling from your repository supports
    packed repositories.
 
@@ -1551,7 +1551,7 @@
    "project lead" and possibly your "sub-subsystem
    maintainers" to pull from it.
 
-7. Every once in a while, `git repack` the public repository.
+7. Every once in a while, 'git-repack' the public repository.
    Go back to step 5. and continue working.
 
 
@@ -1559,7 +1559,7 @@
 not have a "public" repository is somewhat different. It goes
 like this:
 
-1. Prepare your work repository, by `git clone` the public
+1. Prepare your work repository, by 'git-clone' the public
    repository of the "project lead" (or a "subsystem
    maintainer", if you work on a subsystem). The URL used for
    the initial cloning is stored in the remote.origin.url
@@ -1589,7 +1589,7 @@
 have to worry. git supports "shared public repository" style of
 cooperation you are probably more familiar with as well.
 
-See linkgit:gitcvs-migration[7][git for CVS users] for the details.
+See linkgit:gitcvs-migration[7] for the details.
 
 Bundling your work together
 ---------------------------
@@ -1656,9 +1656,9 @@
 $ git reset --hard master~2
 ------------
 
-You can make sure 'git show-branch' matches the state before
-those two 'git merge' you just did.  Then, instead of running
-two 'git merge' commands in a row, you would merge these two
+You can make sure `git show-branch` matches the state before
+those two 'git-merge' you just did.  Then, instead of running
+two 'git-merge' commands in a row, you would merge these two
 branch heads (this is known as 'making an Octopus'):
 
 ------------
@@ -1690,8 +1690,10 @@
 
 SEE ALSO
 --------
-linkgit:gittutorial[7], linkgit:gittutorial-2[7],
-linkgit:giteveryday[7], linkgit:gitcvs-migration[7],
+linkgit:gittutorial[7],
+linkgit:gittutorial-2[7],
+linkgit:gitcvs-migration[7],
+link:everyday.html[Everyday git],
 link:user-manual.html[The Git User's Manual]
 
 GIT
diff --git a/Documentation/gitcvs-migration.txt b/Documentation/gitcvs-migration.txt
index 0325d67..aaa7ef7 100644
--- a/Documentation/gitcvs-migration.txt
+++ b/Documentation/gitcvs-migration.txt
@@ -18,9 +18,9 @@
 designating a single shared repository which people can synchronize with;
 this document explains how to do that.
 
-Some basic familiarity with git is required.  This
-linkgit:gittutorial[7][tutorial introduction to git] and the
-linkgit:gitglossary[7][git glossary] should be sufficient.
+Some basic familiarity with git is required. Having gone through
+linkgit:gittutorial[7] and
+linkgit:gitglossary[7] should be sufficient.
 
 Developing against a shared repository
 --------------------------------------
@@ -34,7 +34,7 @@
 $ cd my-project
 ------------------------------------------------
 
-and hack away.  The equivalent of `cvs update` is
+and hack away.  The equivalent of 'cvs update' is
 
 ------------------------------------------------
 $ git pull origin
@@ -46,28 +46,28 @@
 
 [NOTE]
 ================================
-The `pull` command knows where to get updates from because of certain
-configuration variables that were set by the first `git clone`
+The 'pull' command knows where to get updates from because of certain
+configuration variables that were set by the first 'git-clone'
 command; see `git config -l` and the linkgit:git-config[1] man
 page for details.
 ================================
 
 You can update the shared repository with your changes by first committing
-your changes, and then using the linkgit:git-push[1] command:
+your changes, and then using the 'git-push' command:
 
 ------------------------------------------------
 $ git push origin master
 ------------------------------------------------
 
 to "push" those commits to the shared repository.  If someone else has
-updated the repository more recently, `git push`, like `cvs commit`, will
+updated the repository more recently, 'git-push', like 'cvs commit', will
 complain, in which case you must pull any changes before attempting the
 push again.
 
-In the `git push` command above we specify the name of the remote branch
-to update (`master`).  If we leave that out, `git push` tries to update
+In the 'git-push' command above we specify the name of the remote branch
+to update (`master`).  If we leave that out, 'git-push' tries to update
 any branches in the remote repository that have the same name as a branch
-in the local repository.  So the last `push` can be done with either of:
+in the local repository.  So the last 'push' can be done with either of:
 
 ------------
 $ git push origin
@@ -81,8 +81,8 @@
 ------------------------------
 
 We assume you have already created a git repository for your project,
-possibly created from scratch or from a tarball (see the
-linkgit:gittutorial[7][tutorial]), or imported from an already existing CVS
+possibly created from scratch or from a tarball (see
+linkgit:gittutorial[7]), or imported from an already existing CVS
 repository (see the next section).
 
 Assume your existing repo is at /home/alice/myproject.  Create a new "bare"
@@ -118,7 +118,7 @@
 First, install version 2.1 or higher of cvsps from
 link:http://www.cobite.com/cvsps/[http://www.cobite.com/cvsps/] and make
 sure it is in your path.  Then cd to a checked out CVS working directory
-of the project you are interested in and run linkgit:git-cvsimport[1]:
+of the project you are interested in and run 'git-cvsimport':
 
 -------------------------------------------
 $ git cvsimport -C <destination> <module>
@@ -153,7 +153,7 @@
 
 Git allows you to specify scripts called "hooks" to be run at certain
 points.  You can use these, for example, to send all commits to the shared
-repository to a mailing list.  See linkgit:githooks[5][Hooks used by git].
+repository to a mailing list.  See linkgit:githooks[5].
 
 You can enforce finer grained permissions using update hooks.  See
 link:howto/update-hook-example.txt[Controlling access to branches using
diff --git a/Documentation/gitdiffcore.txt b/Documentation/gitdiffcore.txt
index 4d56c85..e8041bc 100644
--- a/Documentation/gitdiffcore.txt
+++ b/Documentation/gitdiffcore.txt
@@ -7,40 +7,54 @@
 
 SYNOPSIS
 --------
-git diff *
+'git diff' *
 
 DESCRIPTION
 -----------
 
-The diff commands git-diff-index, git-diff-files, and git-diff-tree
+The diff commands 'git-diff-index', 'git-diff-files', and 'git-diff-tree'
 can be told to manipulate differences they find in
-unconventional ways before showing diff(1) output.  The manipulation
+unconventional ways before showing 'diff' output.  The manipulation
 is collectively called "diffcore transformation".  This short note
-describes what they are and how to use them to produce diff outputs
-that are easier to understand than the conventional kind.
+describes what they are and how to use them to produce 'diff' output
+that is easier to understand than the conventional kind.
 
 
 The chain of operation
 ----------------------
 
-The git-diff-* family works by first comparing two sets of
+The 'git-diff-{asterisk}' family works by first comparing two sets of
 files:
 
- - git-diff-index compares contents of a "tree" object and the
+ - 'git-diff-index' compares contents of a "tree" object and the
    working directory (when '\--cached' flag is not used) or a
    "tree" object and the index file (when '\--cached' flag is
    used);
 
- - git-diff-files compares contents of the index file and the
+ - 'git-diff-files' compares contents of the index file and the
    working directory;
 
- - git-diff-tree compares contents of two "tree" objects;
+ - 'git-diff-tree' compares contents of two "tree" objects;
 
-In all of these cases, the commands themselves compare
-corresponding paths in the two sets of files.  The result of
-comparison is passed from these commands to what is internally
-called "diffcore", in a format similar to what is output when
-the -p option is not used.  E.g.
+In all of these cases, the commands themselves first optionally limit
+the two sets of files by any pathspecs given on their command-lines,
+and compare corresponding paths in the two resulting sets of files.
+
+The pathspecs are used to limit the world diff operates in.  They remove
+the filepairs outside the specified sets of pathnames.  E.g. If the
+input set of filepairs included:
+
+------------------------------------------------
+:100644 100644 bcd1234... 0123456... M junkfile
+------------------------------------------------
+
+but the command invocation was `git diff-files myfile`, then the
+junkfile entry would be removed from the list because only "myfile"
+is under consideration.
+
+The result of comparison is passed from these commands to what is
+internally called "diffcore", in a format similar to what is output
+when the -p option is not used.  E.g.
 
 ------------------------------------------------
 in-place edit  :100644 100644 bcd1234... 0123456... M file0
@@ -52,53 +66,28 @@
 The diffcore mechanism is fed a list of such comparison results
 (each of which is called "filepair", although at this point each
 of them talks about a single file), and transforms such a list
-into another list.  There are currently 6 such transformations:
+into another list.  There are currently 5 such transformations:
 
-- diffcore-pathspec
 - diffcore-break
 - diffcore-rename
 - diffcore-merge-broken
 - diffcore-pickaxe
 - diffcore-order
 
-These are applied in sequence.  The set of filepairs git-diff-\*
-commands find are used as the input to diffcore-pathspec, and
-the output from diffcore-pathspec is used as the input to the
+These are applied in sequence.  The set of filepairs 'git-diff-{asterisk}'
+commands find are used as the input to diffcore-break, and
+the output from diffcore-break is used as the input to the
 next transformation.  The final result is then passed to the
 output routine and generates either diff-raw format (see Output
-format sections of the manual for git-diff-\* commands) or
+format sections of the manual for 'git-diff-{asterisk}' commands) or
 diff-patch format.
 
 
-diffcore-pathspec: For Ignoring Files Outside Our Consideration
----------------------------------------------------------------
-
-The first transformation in the chain is diffcore-pathspec, and
-is controlled by giving the pathname parameters to the
-git-diff-* commands on the command line.  The pathspec is used
-to limit the world diff operates in.  It removes the filepairs
-outside the specified set of pathnames.  E.g. If the input set
-of filepairs included:
-
-------------------------------------------------
-:100644 100644 bcd1234... 0123456... M junkfile
-------------------------------------------------
-
-but the command invocation was "git-diff-files myfile", then the
-junkfile entry would be removed from the list because only "myfile"
-is under consideration.
-
-Implementation note.  For performance reasons, git-diff-tree
-uses the pathname parameters on the command line to cull set of
-filepairs it feeds the diffcore mechanism itself, and does not
-use diffcore-pathspec, but the end result is the same.
-
-
 diffcore-break: For Splitting Up "Complete Rewrites"
 ----------------------------------------------------
 
 The second transformation in the chain is diffcore-break, and is
-controlled by the -B option to the git-diff-* commands.  This is
+controlled by the -B option to the 'git-diff-{asterisk}' commands.  This is
 used to detect a filepair that represents "complete rewrite" and
 break such filepair into two filepairs that represent delete and
 create.  E.g.  If the input contained this filepair:
@@ -134,7 +123,7 @@
 
 This transformation is used to detect renames and copies, and is
 controlled by the -M option (to detect renames) and the -C option
-(to detect copies as well) to the git-diff-* commands.  If the
+(to detect copies as well) to the 'git-diff-{asterisk}' commands.  If the
 input contained these filepairs:
 
 ------------------------------------------------
@@ -179,11 +168,11 @@
 8/10 = 80%).
 
 Note.  When the "-C" option is used with `\--find-copies-harder`
-option, git-diff-\* commands feed unmodified filepairs to
+option, 'git-diff-{asterisk}' commands feed unmodified filepairs to
 diffcore mechanism as well as modified ones.  This lets the copy
 detector consider unmodified files as copy source candidates at
 the expense of making it slower.  Without `\--find-copies-harder`,
-git-diff-\* commands can detect copies only if the file that was
+'git-diff-{asterisk}' commands can detect copies only if the file that was
 copied happened to have been modified in the same changeset.
 
 
@@ -234,7 +223,7 @@
 
 This transformation is used to find filepairs that represent
 changes that touch a specified string, and is controlled by the
--S option and the `\--pickaxe-all` option to the git-diff-*
+-S option and the `\--pickaxe-all` option to the 'git-diff-{asterisk}'
 commands.
 
 When diffcore-pickaxe is in use, it checks if there are
@@ -257,7 +246,7 @@
 
 This is used to reorder the filepairs according to the user's
 (or project's) taste, and is controlled by the -O option to the
-git-diff-* commands.
+'git-diff-{asterisk}' commands.
 
 This takes a text file each of whose lines is a shell glob
 pattern.  Filepairs that match a glob pattern on an earlier line
diff --git a/Documentation/gitglossary.txt b/Documentation/gitglossary.txt
index 5c5c31d..d77a45a 100644
--- a/Documentation/gitglossary.txt
+++ b/Documentation/gitglossary.txt
@@ -16,8 +16,10 @@
 
 SEE ALSO
 --------
-linkgit:gittutorial[7], linkgit:gittutorial-2[7],
-linkgit:giteveryday[7], linkgit:gitcvs-migration[7],
+linkgit:gittutorial[7],
+linkgit:gittutorial-2[7],
+linkgit:gitcvs-migration[7],
+link:everyday.html[Everyday git],
 link:user-manual.html[The Git User's Manual]
 
 GIT
diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt
index 4f06ae0..5faaaa5 100644
--- a/Documentation/githooks.txt
+++ b/Documentation/githooks.txt
@@ -15,19 +15,20 @@
 
 Hooks are little scripts you can place in `$GIT_DIR/hooks`
 directory to trigger action at certain points.  When
-`git-init` is run, a handful example hooks are copied in the
+'git-init' is run, a handful example hooks are copied in the
 `hooks` directory of the new repository, but by default they are
-all disabled.  To enable a hook, make it executable with `chmod +x`.
+all disabled.  To enable a hook, rename it by removing its `.sample`
+suffix.
 
 This document describes the currently defined hooks.
 
 applypatch-msg
 --------------
 
-This hook is invoked by `git-am` script.  It takes a single
+This hook is invoked by 'git-am' script.  It takes a single
 parameter, the name of the file that holds the proposed commit
 log message.  Exiting with non-zero status causes
-`git-am` to abort before applying the patch.
+'git-am' to abort before applying the patch.
 
 The hook is allowed to edit the message file in place, and can
 be used to normalize the message into some project standard
@@ -40,7 +41,7 @@
 pre-applypatch
 --------------
 
-This hook is invoked by `git-am`.  It takes no parameter, and is
+This hook is invoked by 'git-am'.  It takes no parameter, and is
 invoked after the patch is applied, but before a commit is made.
 
 If it exits with non-zero status, then the working tree will not be
@@ -55,45 +56,45 @@
 post-applypatch
 ---------------
 
-This hook is invoked by `git-am`.  It takes no parameter,
+This hook is invoked by 'git-am'.  It takes no parameter,
 and is invoked after the patch is applied and a commit is made.
 
 This hook is meant primarily for notification, and cannot affect
-the outcome of `git-am`.
+the outcome of 'git-am'.
 
 pre-commit
 ----------
 
-This hook is invoked by `git-commit`, and can be bypassed
+This hook is invoked by 'git-commit', and can be bypassed
 with `\--no-verify` option.  It takes no parameter, and is
 invoked before obtaining the proposed commit log message and
 making a commit.  Exiting with non-zero status from this script
-causes the `git-commit` to abort.
+causes the 'git-commit' to abort.
 
 The default 'pre-commit' hook, when enabled, catches introduction
 of lines with trailing whitespaces and aborts the commit when
 such a line is found.
 
-All the `git-commit` hooks are invoked with the environment
+All the 'git-commit' hooks are invoked with the environment
 variable `GIT_EDITOR=:` if the command will not bring up an editor
 to modify the commit message.
 
 prepare-commit-msg
 ------------------
 
-This hook is invoked by `git-commit` right after preparing the
+This hook is invoked by 'git-commit' right after preparing the
 default log message, and before the editor is started.
 
 It takes one to three parameters.  The first is the name of the file
 that the commit log message.  The second is the source of the commit
-message, and can be: `message` (if a `\-m` or `\-F` option was
-given); `template` (if a `\-t` option was given or the
+message, and can be: `message` (if a `-m` or `-F` option was
+given); `template` (if a `-t` option was given or the
 configuration option `commit.template` is set); `merge` (if the
 commit is a merge or a `.git/MERGE_MSG` file exists); `squash`
 (if a `.git/SQUASH_MSG` file exists); or `commit`, followed by
-a commit SHA1 (if a `\-c`, `\-C` or `\--amend` option was given).
+a commit SHA1 (if a `-c`, `-C` or `\--amend` option was given).
 
-If the exit status is non-zero, `git-commit` will abort.
+If the exit status is non-zero, 'git-commit' will abort.
 
 The purpose of the hook is to edit the message file in place, and
 it is not suppressed by the `\--no-verify` option.  A non-zero exit
@@ -106,10 +107,10 @@
 commit-msg
 ----------
 
-This hook is invoked by `git-commit`, and can be bypassed
+This hook is invoked by 'git-commit', and can be bypassed
 with `\--no-verify` option.  It takes a single parameter, the
 name of the file that holds the proposed commit log message.
-Exiting with non-zero status causes the `git-commit` to
+Exiting with non-zero status causes the 'git-commit' to
 abort.
 
 The hook is allowed to edit the message file in place, and can
@@ -123,21 +124,28 @@
 post-commit
 -----------
 
-This hook is invoked by `git-commit`.  It takes no
+This hook is invoked by 'git-commit'.  It takes no
 parameter, and is invoked after a commit is made.
 
 This hook is meant primarily for notification, and cannot affect
-the outcome of `git-commit`.
+the outcome of 'git-commit'.
+
+pre-rebase
+----------
+
+This hook is called by 'git-rebase' and can be used to prevent a branch
+from getting rebased.
+
 
 post-checkout
 -----------
 
-This hook is invoked when a `git-checkout` is run after having updated the
+This hook is invoked when a 'git-checkout' is run after having updated the
 worktree.  The hook is given three parameters: the ref of the previous HEAD,
 the ref of the new HEAD (which may or may not have changed), and a flag
 indicating whether the checkout was a branch checkout (changing branches,
 flag=1) or a file checkout (retrieving a file from the index, flag=0).
-This hook cannot affect the outcome of `git-checkout`.
+This hook cannot affect the outcome of 'git-checkout'.
 
 This hook can be used to perform repository validity checks, auto-display
 differences from the previous HEAD if different, or set working dir metadata
@@ -146,10 +154,10 @@
 post-merge
 -----------
 
-This hook is invoked by `git-merge`, which happens when a `git pull`
+This hook is invoked by 'git-merge', which happens when a 'git-pull'
 is done on a local repository.  The hook takes a single parameter, a status
 flag specifying whether or not the merge being done was a squash merge.
-This hook cannot affect the outcome of `git-merge` and is not executed,
+This hook cannot affect the outcome of 'git-merge' and is not executed,
 if the merge failed due to conflicts.
 
 This hook can be used in conjunction with a corresponding pre-commit hook to
@@ -161,8 +169,8 @@
 pre-receive
 -----------
 
-This hook is invoked by `git-receive-pack` on the remote repository,
-which happens when a `git push` is done on a local repository.
+This hook is invoked by 'git-receive-pack' on the remote repository,
+which happens when a 'git-push' is done on a local repository.
 Just before starting to update refs on the remote repository, the
 pre-receive hook is invoked.  Its exit status determines the success
 or failure of the update.
@@ -183,15 +191,15 @@
 still be prevented by the <<update,'update'>> hook.
 
 Both standard output and standard error output are forwarded to
-`git-send-pack` on the other end, so you can simply `echo` messages
+'git-send-pack' on the other end, so you can simply `echo` messages
 for the user.
 
 [[update]]
 update
 ------
 
-This hook is invoked by `git-receive-pack` on the remote repository,
-which happens when a `git push` is done on a local repository.
+This hook is invoked by 'git-receive-pack' on the remote repository,
+which happens when a 'git-push' is done on a local repository.
 Just before updating the ref on the remote repository, the update hook
 is invoked.  Its exit status determines the success or failure of
 the ref update.
@@ -204,7 +212,7 @@
  - and the new objectname to be stored in the ref.
 
 A zero exit from the update hook allows the ref to be updated.
-Exiting with a non-zero status prevents `git-receive-pack`
+Exiting with a non-zero status prevents 'git-receive-pack'
 from updating that ref.
 
 This hook can be used to prevent 'forced' update on certain refs by
@@ -222,7 +230,7 @@
 based on filesystem group.
 
 Both standard output and standard error output are forwarded to
-`git-send-pack` on the other end, so you can simply `echo` messages
+'git-send-pack' on the other end, so you can simply `echo` messages
 for the user.
 
 The default 'update' hook, when enabled--and with
@@ -233,8 +241,8 @@
 post-receive
 ------------
 
-This hook is invoked by `git-receive-pack` on the remote repository,
-which happens when a `git push` is done on a local repository.
+This hook is invoked by 'git-receive-pack' on the remote repository,
+which happens when a 'git-push' is done on a local repository.
 It executes on the remote repository once after all the refs have
 been updated.
 
@@ -243,7 +251,7 @@
 <<pre-receive,'pre-receive'>>
 hook does on its standard input.
 
-This hook does not affect the outcome of `git-receive-pack`, as it
+This hook does not affect the outcome of 'git-receive-pack', as it
 is called after the real work is done.
 
 This supersedes the <<post-update,'post-update'>> hook in that it gets
@@ -251,7 +259,7 @@
 names.
 
 Both standard output and standard error output are forwarded to
-`git-send-pack` on the other end, so you can simply `echo` messages
+'git-send-pack' on the other end, so you can simply `echo` messages
 for the user.
 
 The default 'post-receive' hook is empty, but there is
@@ -263,8 +271,8 @@
 post-update
 -----------
 
-This hook is invoked by `git-receive-pack` on the remote repository,
-which happens when a `git push` is done on a local repository.
+This hook is invoked by 'git-receive-pack' on the remote repository,
+which happens when a 'git-push' is done on a local repository.
 It executes on the remote repository once after all the refs have
 been updated.
 
@@ -272,7 +280,7 @@
 name of ref that was actually updated.
 
 This hook is meant primarily for notification, and cannot affect
-the outcome of `git-receive-pack`.
+the outcome of 'git-receive-pack'.
 
 The 'post-update' hook can tell what are the heads that were pushed,
 but it does not know what their original and updated values are,
@@ -282,20 +290,20 @@
 them.
 
 When enabled, the default 'post-update' hook runs
-`git-update-server-info` to keep the information used by dumb
+'git-update-server-info' to keep the information used by dumb
 transports (e.g., HTTP) up-to-date.  If you are publishing
 a git repository that is accessible via HTTP, you should
 probably enable this hook.
 
 Both standard output and standard error output are forwarded to
-`git-send-pack` on the other end, so you can simply `echo` messages
+'git-send-pack' on the other end, so you can simply `echo` messages
 for the user.
 
 pre-auto-gc
 -----------
 
-This hook is invoked by `git-gc --auto`. It takes no parameter, and
-exiting with non-zero status from this script causes the `git-gc --auto`
+This hook is invoked by 'git-gc --auto'. It takes no parameter, and
+exiting with non-zero status from this script causes the 'git-gc --auto'
 to abort.
 
 GIT
diff --git a/Documentation/gitignore.txt b/Documentation/gitignore.txt
index 2881c9c..59321a2 100644
--- a/Documentation/gitignore.txt
+++ b/Documentation/gitignore.txt
@@ -13,9 +13,14 @@
 -----------
 
 A `gitignore` file specifies intentionally untracked files that
-git should ignore.  Each line in a `gitignore` file specifies a
-pattern.
+git should ignore.
+Note that all the `gitignore` files really concern only files
+that are not already tracked by git;
+in order to ignore uncommitted changes in already tracked files,
+please refer to the 'git update-index --assume-unchanged'
+documentation.
 
+Each line in a `gitignore` file specifies a pattern.
 When deciding whether to ignore a path, git normally checks
 `gitignore` patterns from multiple sources, with the following
 order of precedence, from highest to lowest (within one level of
@@ -51,10 +56,10 @@
 `core.excludesfile` in the user's `~/.gitconfig`.
 
 The underlying git plumbing tools, such as
-linkgit:git-ls-files[1] and linkgit:git-read-tree[1], read
+'git-ls-files' and 'git-read-tree', read
 `gitignore` patterns specified by command-line options, or from
 files specified by command-line options.  Higher-level git
-tools, such as linkgit:git-status[1] and linkgit:git-add[1],
+tools, such as 'git-status' and 'git-add',
 use patterns from the sources specified above.
 
 Patterns have the following format:
@@ -92,7 +97,7 @@
 An example:
 
 --------------------------------------------------------------
-    $ git-status
+    $ git status
     [...]
     # Untracked files:
     [...]
@@ -110,7 +115,7 @@
     *.html
     # except foo.html which is maintained by hand
     !foo.html
-    $ git-status
+    $ git status
     [...]
     # Untracked files:
     [...]
diff --git a/Documentation/gitk.txt b/Documentation/gitk.txt
index f843f39..5ef3687 100644
--- a/Documentation/gitk.txt
+++ b/Documentation/gitk.txt
@@ -21,8 +21,9 @@
 
 OPTIONS
 -------
-To control which revisions to shown, the command takes options applicable to
-the linkgit:git-rev-list[1] command. This manual page describes only the most
+To control which revisions to show, the command takes options applicable to
+the 'git-rev-list' command (see linkgit:git-rev-list[1]).
+This manual page describes only the most
 frequently used options.
 
 -n <number>::
@@ -48,6 +49,13 @@
 	the history between two branches (i.e. the HEAD and the MERGE_HEAD)
 	that modify the conflicted files.
 
+--argscmd=<command>::
+	Command to be run each time gitk has to determine the list of
+	<revs> to show.  The command is expected to print on its standard
+	output a list of additional revs to be shown, one per line.
+	Use this instead of explicitly specifying <revs> if the set of
+	commits to show may vary between refreshes.
+
 <revs>::
 
 	Limit the revisions to show. This can be either a single revision
@@ -57,7 +65,7 @@
 	For a more complete list of ways to spell object names, see
 	"SPECIFYING REVISIONS" section in linkgit:git-rev-parse[1].
 
-<path>::
+<path>...::
 
 	Limit commits to the ones touching files in the given paths. Note, to
 	avoid ambiguity wrt. revision names use "--" to separate the paths
@@ -67,7 +75,7 @@
 --------
 gitk v2.6.12.. include/scsi drivers/scsi::
 
-	Show as the changes since version 'v2.6.12' that changed any
+	Show the changes since version 'v2.6.12' that changed any
 	file in the include/scsi or drivers/scsi subdirectories
 
 gitk --since="2 weeks ago" \-- gitk::
diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt
index f8d122a..d1a17e2 100644
--- a/Documentation/gitmodules.txt
+++ b/Documentation/gitmodules.txt
@@ -7,7 +7,7 @@
 
 SYNOPSIS
 --------
-gitmodules
+$GIT_WORK_DIR/.gitmodules
 
 
 DESCRIPTION
diff --git a/Documentation/gitrepository-layout.txt b/Documentation/gitrepository-layout.txt
index 03c52ff..a969b3f 100644
--- a/Documentation/gitrepository-layout.txt
+++ b/Documentation/gitrepository-layout.txt
@@ -64,7 +64,7 @@
 	are available in this object store.  Whenever a pack is
 	added or removed, `git update-server-info` should be run
 	to keep this file up-to-date if the repository is
-	published for dumb transports.  `git repack` does this
+	published for dumb transports.  'git-repack' does this
 	by default.
 
 objects/info/alternates::
@@ -85,7 +85,7 @@
 
 refs::
 	References are stored in subdirectories of this
-	directory.  The `git prune` command knows to keep
+	directory.  The 'git-prune' command knows to keep
 	objects reachable from refs found in this directory and
 	its subdirectories.
 
@@ -125,7 +125,7 @@
 
 branches::
 	A slightly deprecated way to store shorthands to be used
-	to specify URL to `git fetch`, `git pull` and `git push`
+	to specify URL to 'git-fetch', 'git-pull' and 'git-push'
 	commands is to store a file in `branches/<name>` and
 	give 'name' to these commands in place of 'repository'
 	argument.
@@ -133,9 +133,9 @@
 hooks::
 	Hooks are customization scripts used by various git
 	commands.  A handful of sample hooks are installed when
-	`git init` is run, but all of them are disabled by
+	'git-init' is run, but all of them are disabled by
 	default.  To enable, they need to be made executable.
-	Read linkgit:githooks[5][hooks] for more details about
+	Read linkgit:githooks[5] for more details about
 	each hook.
 
 index::
@@ -150,10 +150,10 @@
 	This file helps dumb transports discover what refs are
 	available in this repository.  If the repository is
 	published for dumb transports, this file should be
-	regenerated by `git update-server-info` every time a tag
+	regenerated by 'git-update-server-info' every time a tag
 	or branch is created or modified.  This is normally done
 	from the `hooks/update` hook, which is run by the
-	`git-receive-pack` command when you `git push` into the
+	'git-receive-pack' command when you 'git-push' into the
 	repository.
 
 info/grafts::
@@ -167,18 +167,18 @@
 info/exclude::
 	This file, by convention among Porcelains, stores the
 	exclude pattern list. `.gitignore` is the per-directory
-	ignore file.  `git status`, `git add`, `git rm` and `git
-	clean` look at it but the core git commands do not look
+	ignore file.  'git-status', 'git-add', 'git-rm' and
+	'git-clean' look at it but the core git commands do not look
 	at it.  See also: linkgit:gitignore[5].
 
 remotes::
 	Stores shorthands to be used to give URL and default
-	refnames to interact with remote repository to `git
-	fetch`, `git pull` and `git push` commands.
+	refnames to interact with remote repository to
+	'git-fetch', 'git-pull' and 'git-push' commands.
 
 logs::
 	Records of changes made to refs are stored in this
-	directory.  See the documentation on git-update-ref
+	directory.  See linkgit:git-update-ref[1]
 	for more information.
 
 logs/refs/heads/`name`::
diff --git a/Documentation/gittutorial-2.txt b/Documentation/gittutorial-2.txt
index e3d5c1f..6609046 100644
--- a/Documentation/gittutorial-2.txt
+++ b/Documentation/gittutorial-2.txt
@@ -12,8 +12,7 @@
 DESCRIPTION
 -----------
 
-You should work through linkgit:gittutorial[7][A tutorial introduction to
-git] before reading this tutorial.
+You should work through linkgit:gittutorial[7] before reading this tutorial.
 
 The goal of this tutorial is to introduce two fundamental pieces of
 git's architecture--the object database and the index file--and to
@@ -55,15 +54,15 @@
 the one shown above because the commit object records the time when
 it was created and the name of the person performing the commit.
 
-We can ask git about this particular object with the cat-file
+We can ask git about this particular object with the `cat-file`
 command. Don't copy the 40 hex digits from this example but use those
 from your own version. Note that you can shorten it to only a few
 characters to save yourself typing all 40 hex digits:
 
 ------------------------------------------------
-$ git-cat-file -t 54196cc2
+$ git cat-file -t 54196cc2
 commit
-$ git-cat-file commit 54196cc2
+$ git cat-file commit 54196cc2
 tree 92b8b694ffb1675e5975148e1121810081dbdffe
 author J. Bruce Fields <bfields@puzzle.fieldses.org> 1143414668 -0500
 committer J. Bruce Fields <bfields@puzzle.fieldses.org> 1143414668 -0500
@@ -166,7 +165,7 @@
 and the "parent" object refers to the previous commit:
 
 ------------------------------------------------
-$ git-cat-file commit 54196cc2
+$ git cat-file commit 54196cc2
 tree 92b8b694ffb1675e5975148e1121810081dbdffe
 author J. Bruce Fields <bfields@puzzle.fieldses.org> 1143414668 -0500
 committer J. Bruce Fields <bfields@puzzle.fieldses.org> 1143414668 -0500
@@ -213,8 +212,8 @@
 The index file
 --------------
 
-The primary tool we've been using to create commits is "git commit
--a", which creates a commit including every change you've made to
+The primary tool we've been using to create commits is `git-commit
+-a`, which creates a commit including every change you've made to
 your working tree.  But what if you want to commit changes only to
 certain files?  Or only certain changes to certain files?
 
@@ -246,7 +245,7 @@
 head still doesn't contain the new line:
 
 ------------------------------------------------
-$ git-diff HEAD
+$ git diff HEAD
 diff --git a/file.txt b/file.txt
 index a042389..513feba 100644
 --- a/file.txt
@@ -256,7 +255,7 @@
 +hello world, again
 ------------------------------------------------
 
-So "git diff" is comparing against something other than the head.
+So 'git-diff' is comparing against something other than the head.
 The thing that it's comparing against is actually the index file,
 which is stored in .git/index in a binary format, but whose contents
 we can examine with ls-files:
@@ -271,9 +270,9 @@
 hello world, again
 ------------------------------------------------
 
-So what our "git add" did was store a new blob and then put
+So what our 'git-add' did was store a new blob and then put
 a reference to it in the index file.  If we modify the file again,
-we'll see that the new modifications are reflected in the "git-diff"
+we'll see that the new modifications are reflected in the 'git-diff'
 output:
 
 ------------------------------------------------
@@ -288,7 +287,7 @@
 +again?
 ------------------------------------------------
 
-With the right arguments, git diff can also show us the difference
+With the right arguments, 'git-diff' can also show us the difference
 between the working directory and the last commit, or between the
 index and the last commit:
 
@@ -312,8 +311,8 @@
 +hello world, again
 ------------------------------------------------
 
-At any time, we can create a new commit using "git commit" (without
-the -a option), and verify that the state committed only includes the
+At any time, we can create a new commit using 'git-commit' (without
+the "-a" option), and verify that the state committed only includes the
 changes stored in the index file, not the additional change that is
 still only in our working tree:
 
@@ -330,11 +329,11 @@
 +again?
 ------------------------------------------------
 
-So by default "git commit" uses the index to create the commit, not
-the working tree; the -a option to commit tells it to first update
+So by default 'git-commit' uses the index to create the commit, not
+the working tree; the "-a" option to commit tells it to first update
 the index with all changes in the working tree.
 
-Finally, it's worth looking at the effect of "git add" on the index
+Finally, it's worth looking at the effect of 'git-add' on the index
 file:
 
 ------------------------------------------------
@@ -342,7 +341,7 @@
 $ git add closing.txt
 ------------------------------------------------
 
-The effect of the "git add" was to add one entry to the index file:
+The effect of the 'git-add' was to add one entry to the index file:
 
 ------------------------------------------------
 $ git ls-files --stage
@@ -383,14 +382,14 @@
 commit" would create a commit that added closing.txt (with its new
 contents), but that didn't modify file.txt.
 
-Also, note that a bare "git diff" shows the changes to file.txt, but
+Also, note that a bare `git diff` shows the changes to file.txt, but
 not the addition of closing.txt, because the version of closing.txt
 in the index file is identical to the one in the working directory.
 
 In addition to being the staging area for new commits, the index file
 is also populated from the object database when checking out a
 branch, and is used to hold the trees involved in a merge operation.
-See the linkgit:gitcore-tutorial[7][core tutorial] and the relevant man
+See linkgit:gitcore-tutorial[7] and the relevant man
 pages for details.
 
 What next?
@@ -399,20 +398,19 @@
 At this point you should know everything necessary to read the man
 pages for any of the git commands; one good place to start would be
 with the commands mentioned in link:everyday.html[Everyday git].  You
-should be able to find any unknown jargon in the
-linkgit:gitglossary[7][Glossary].
+should be able to find any unknown jargon in linkgit:gitglossary[7].
 
 The link:user-manual.html[Git User's Manual] provides a more
 comprehensive introduction to git.
 
-The linkgit:gitcvs-migration[7][CVS migration] document explains how to
+linkgit:gitcvs-migration[7] explains how to
 import a CVS repository into git, and shows how to use git in a
 CVS-like way.
 
 For some interesting examples of git use, see the
 link:howto-index.html[howtos].
 
-For git developers, the linkgit:gitcore-tutorial[7][Core tutorial] goes
+For git developers, linkgit:gitcore-tutorial[7] goes
 into detail on the lower-level git mechanisms involved in, for
 example, creating a new commit.
 
diff --git a/Documentation/gittutorial.txt b/Documentation/gittutorial.txt
index d465aab..384972c 100644
--- a/Documentation/gittutorial.txt
+++ b/Documentation/gittutorial.txt
@@ -19,11 +19,11 @@
 for example, to test the latest version, you may prefer to start with
 the first two chapters of link:user-manual.html[The Git User's Manual].
 
-First, note that you can get documentation for a command such as "git
-diff" with:
+First, note that you can get documentation for a command such as
+`git log --graph` with:
 
 ------------------------------------------------
-$ man git-diff
+$ man git-log
 ------------------------------------------------
 
 It is a good idea to introduce yourself to git with your name and
@@ -58,7 +58,7 @@
 directory created, named ".git".
 
 Next, tell git to take a snapshot of the contents of all files under the
-current directory (note the '.'), with linkgit:git-add[1]:
+current directory (note the '.'), with 'git-add':
 
 ------------------------------------------------
 $ git add .
@@ -66,7 +66,7 @@
 
 This snapshot is now stored in a temporary staging area which git calls
 the "index".  You can permanently store the contents of the index in the
-repository with linkgit:git-commit[1]:
+repository with 'git-commit':
 
 ------------------------------------------------
 $ git commit
@@ -85,15 +85,15 @@
 ------------------------------------------------
 
 You are now ready to commit.  You can see what is about to be committed
-using linkgit:git-diff[1] with the --cached option:
+using 'git-diff' with the --cached option:
 
 ------------------------------------------------
 $ git diff --cached
 ------------------------------------------------
 
-(Without --cached, linkgit:git-diff[1] will show you any changes that
+(Without --cached, 'git-diff' will show you any changes that
 you've made but not yet added to the index.)  You can also get a brief
-summary of the situation with linkgit:git-status[1]:
+summary of the situation with 'git-status':
 
 ------------------------------------------------
 $ git status
@@ -117,7 +117,7 @@
 This will again prompt you for a message describing the change, and then
 record a new version of the project.
 
-Alternatively, instead of running `git add` beforehand, you can use
+Alternatively, instead of running 'git-add' beforehand, you can use
 
 ------------------------------------------------
 $ git commit -a
@@ -136,9 +136,9 @@
 Git tracks content not files
 ----------------------------
 
-Many revision control systems provide an "add" command that tells the
-system to start tracking changes to a new file.  Git's "add" command
-does something simpler and more powerful: `git add` is used both for new
+Many revision control systems provide an `add` command that tells the
+system to start tracking changes to a new file.  Git's `add` command
+does something simpler and more powerful: 'git-add' is used both for new
 and newly modified files, and in both cases it takes a snapshot of the
 given files and stages that content in the index, ready for inclusion in
 the next commit.
@@ -274,7 +274,7 @@
 Bob begins with:
 
 ------------------------------------------------
-$ git clone /home/alice/project myrepo
+bob$ git clone /home/alice/project myrepo
 ------------------------------------------------
 
 This creates a new directory "myrepo" containing a clone of Alice's
@@ -285,7 +285,7 @@
 
 ------------------------------------------------
 (edit files)
-$ git commit -a
+bob$ git commit -a
 (repeat as necessary)
 ------------------------------------------------
 
@@ -293,8 +293,8 @@
 at /home/bob/myrepo.  She does this with:
 
 ------------------------------------------------
-$ cd /home/alice/project
-$ git pull /home/bob/myrepo master
+alice$ cd /home/alice/project
+alice$ git pull /home/bob/myrepo master
 ------------------------------------------------
 
 This merges the changes from Bob's "master" branch into Alice's
@@ -306,30 +306,83 @@
 The "pull" command thus performs two operations: it fetches changes
 from a remote branch, then merges them into the current branch.
 
+Note that in general, Alice would want her local changes committed before
+initiating this "pull".  If Bob's work conflicts with what Alice did since
+their histories forked, Alice will use her working tree and the index to
+resolve conflicts, and existing local changes will interfere with the
+conflict resolution process (git will still perform the fetch but will
+refuse to merge --- Alice will have to get rid of her local changes in
+some way and pull again when this happens).
+
+Alice can peek at what Bob did without merging first, using the "fetch"
+command; this allows Alice to inspect what Bob did, using a special
+symbol "FETCH_HEAD", in order to determine if he has anything worth
+pulling, like this:
+
+------------------------------------------------
+alice$ git fetch /home/bob/myrepo master
+alice$ git log -p HEAD..FETCH_HEAD
+------------------------------------------------
+
+This operation is safe even if Alice has uncommitted local changes.
+The range notation HEAD..FETCH_HEAD" means "show everything that is reachable
+from the FETCH_HEAD but exclude anything that is reachable from HEAD.
+Alice already knows everything that leads to her current state (HEAD),
+and reviewing what Bob has in his state (FETCH_HEAD) that she has not
+seen with this command
+
+If Alice wants to visualize what Bob did since their histories forked
+she can issue the following command:
+
+------------------------------------------------
+$ gitk HEAD..FETCH_HEAD
+------------------------------------------------
+
+This uses the same two-dot range notation we saw earlier with 'git log'.
+
+Alice may want to view what both of them did since they forked.
+She can use three-dot form instead of the two-dot form:
+
+------------------------------------------------
+$ gitk HEAD...FETCH_HEAD
+------------------------------------------------
+
+This means "show everything that is reachable from either one, but
+exclude anything that is reachable from both of them".
+
+Please note that these range notation can be used with both gitk
+and "git log".
+
+After inspecting what Bob did, if there is nothing urgent, Alice may
+decide to continue working without pulling from Bob.  If Bob's history
+does have something Alice would immediately need, Alice may choose to
+stash her work-in-progress first, do a "pull", and then finally unstash
+her work-in-progress on top of the resulting history.
+
 When you are working in a small closely knit group, it is not
 unusual to interact with the same repository over and over
 again.  By defining 'remote' repository shorthand, you can make
 it easier:
 
 ------------------------------------------------
-$ git remote add bob /home/bob/myrepo
+alice$ git remote add bob /home/bob/myrepo
 ------------------------------------------------
 
-With this, Alice can perform the first operation alone using the
-"git fetch" command without merging them with her own branch,
+With this, Alice can perform the first part of the "pull" operation alone using the
+'git-fetch' command without merging them with her own branch,
 using:
 
 -------------------------------------
-$ git fetch bob
+alice$ git fetch bob
 -------------------------------------
 
 Unlike the longhand form, when Alice fetches from Bob using a
-remote repository shorthand set up with `git remote`, what was
+remote repository shorthand set up with 'git-remote', what was
 fetched is stored in a remote tracking branch, in this case
 `bob/master`.  So after this:
 
 -------------------------------------
-$ git log -p master..bob/master
+alice$ git log -p master..bob/master
 -------------------------------------
 
 shows a list of all the changes that Bob made since he branched from
@@ -339,14 +392,14 @@
 could merge the changes into her master branch:
 
 -------------------------------------
-$ git merge bob/master
+alice$ git merge bob/master
 -------------------------------------
 
 This `merge` can also be done by 'pulling from her own remote
 tracking branch', like this:
 
 -------------------------------------
-$ git pull . remotes/bob/master
+alice$ git pull . remotes/bob/master
 -------------------------------------
 
 Note that git pull always merges into the current branch,
@@ -355,7 +408,7 @@
 Later, Bob can update his repo with Alice's latest changes using
 
 -------------------------------------
-$ git pull
+bob$ git pull
 -------------------------------------
 
 Note that he doesn't need to give the path to Alice's repository;
@@ -364,19 +417,19 @@
 used for pulls:
 
 -------------------------------------
-$ git config --get remote.origin.url
+bob$ git config --get remote.origin.url
 /home/alice/project
 -------------------------------------
 
-(The complete configuration created by git-clone is visible using
-"git config -l", and the linkgit:git-config[1] man page
+(The complete configuration created by 'git-clone' is visible using
+`git config -l`, and the linkgit:git-config[1] man page
 explains the meaning of each option.)
 
 Git also keeps a pristine copy of Alice's master branch under the
 name "origin/master":
 
 -------------------------------------
-$ git branch -r
+bob$ git branch -r
   origin/master
 -------------------------------------
 
@@ -384,7 +437,7 @@
 perform clones and pulls using the ssh protocol:
 
 -------------------------------------
-$ git clone alice.org:/home/alice/project myrepo
+bob$ git clone alice.org:/home/alice/project myrepo
 -------------------------------------
 
 Alternatively, git has a native protocol, or can use rsync or http;
@@ -392,13 +445,13 @@
 
 Git can also be used in a CVS-like mode, with a central repository
 that various users push changes to; see linkgit:git-push[1] and
-linkgit:gitcvs-migration[7][git for CVS users].
+linkgit:gitcvs-migration[7].
 
 Exploring history
 -----------------
 
 Git history is represented as a series of interrelated commits.  We
-have already seen that the git log command can list those commits.
+have already seen that the 'git-log' command can list those commits.
 Note that first line of each git log entry also gives a name for the
 commit:
 
@@ -411,7 +464,7 @@
     merge-base: Clarify the comments on post processing.
 -------------------------------------
 
-We can give this name to git show to see the details about this
+We can give this name to 'git-show' to see the details about this
 commit.
 
 -------------------------------------
@@ -447,7 +500,7 @@
 You can also give commits names of your own; after running
 
 -------------------------------------
-$ git-tag v2.5 1b2e1d63ff
+$ git tag v2.5 1b2e1d63ff
 -------------------------------------
 
 you can refer to 1b2e1d63ff by the name "v2.5".  If you intend to
@@ -469,13 +522,13 @@
 Be careful with that last command: in addition to losing any changes
 in the working directory, it will also remove all later commits from
 this branch.  If this branch is the only branch containing those
-commits, they will be lost.  Also, don't use "git reset" on a
+commits, they will be lost.  Also, don't use 'git-reset' on a
 publicly-visible branch that other developers pull from, as it will
 force needless merges on other developers to clean up the history.
-If you need to undo changes that you have pushed, use linkgit:git-revert[1]
+If you need to undo changes that you have pushed, use 'git-revert'
 instead.
 
-The git grep command can search for strings in any version of your
+The 'git-grep' command can search for strings in any version of your
 project, so
 
 -------------------------------------
@@ -484,7 +537,7 @@
 
 searches for all occurrences of "hello" in v2.5.
 
-If you leave out the commit name, git grep will search any of the
+If you leave out the commit name, 'git-grep' will search any of the
 files it manages in your current directory.  So
 
 -------------------------------------
@@ -494,7 +547,7 @@
 is a quick way to search just the files that are tracked by git.
 
 Many git commands also take sets of commits, which can be specified
-in a number of ways.  Here are some examples with git log:
+in a number of ways.  Here are some examples with 'git-log':
 
 -------------------------------------
 $ git log v2.5..v2.6            # commits between v2.5 and v2.6
@@ -504,7 +557,7 @@
 				# Makefile
 -------------------------------------
 
-You can also give git log a "range" of commits where the first is not
+You can also give 'git-log' a "range" of commits where the first is not
 necessarily an ancestor of the second; for example, if the tips of
 the branches "stable-release" and "master" diverged from a common
 commit some time ago, then
@@ -523,13 +576,13 @@
 will show the list of commits made on the stable branch but not
 the experimental branch.
 
-The "git log" command has a weakness: it must present commits in a
+The 'git-log' command has a weakness: it must present commits in a
 list.  When the history has lines of development that diverged and
-then merged back together, the order in which "git log" presents
+then merged back together, the order in which 'git-log' presents
 those commits is meaningless.
 
 Most projects with multiple contributors (such as the linux kernel,
-or git itself) have frequent merges, and gitk does a better job of
+or git itself) have frequent merges, and 'gitk' does a better job of
 visualizing their history.  For example,
 
 -------------------------------------
@@ -549,7 +602,7 @@
 $ git diff v2.5:Makefile HEAD:Makefile.in
 -------------------------------------
 
-You can also use "git show" to see any such file:
+You can also use 'git-show' to see any such file:
 
 -------------------------------------
 $ git show v2.5:Makefile
@@ -571,9 +624,9 @@
     used to create commits, check out working directories, and
     hold the various trees involved in a merge.
 
-linkgit:gittutorial-2[7][Part two of this tutorial] explains the object
+Part two of this tutorial explains the object
 database, the index file, and a few other odds and ends that you'll
-need to make the most of git.
+need to make the most of git. You can find it at linkgit:gittutorial-2[7].
 
 If you don't want to continue with that right away, a few other
 digressions that may be interesting at this point are:
@@ -592,7 +645,7 @@
 
   * link:everyday.html[Everyday GIT with 20 Commands Or So]
 
-  * linkgit:gitcvs-migration[7][git for CVS users].
+  * linkgit:gitcvs-migration[7]: Git for CVS users.
 
 SEE ALSO
 --------
diff --git a/Documentation/howto/update-hook-example.txt b/Documentation/howto/update-hook-example.txt
index 3ef7c0d..697d918 100644
--- a/Documentation/howto/update-hook-example.txt
+++ b/Documentation/howto/update-hook-example.txt
@@ -65,7 +65,7 @@
 
 # Implement generic branch and tag policies.
 # - Tags should not be updated once created.
-# - Branches should only be fast-forwarded.
+# - Branches should only be fast-forwarded unless their pattern starts with '+'
 case "$1" in
   refs/tags/*)
     git rev-parse --verify -q "$1" &&
@@ -80,7 +80,7 @@
       mb=$(git-merge-base "$2" "$3")
       case "$mb,$2" in
         "$2,$mb") info "Update is fast-forward" ;;
-        *)        deny >/dev/null  "This is not a fast-forward update." ;;
+	*)	  noff=y; info "This is not a fast-forward update.";;
       esac
     fi
     ;;
@@ -95,21 +95,30 @@
 username=$(id -u -n)
 info "The user is: '$username'"
 
-if [ -f "$allowed_users_file" ]; then
+if test -f "$allowed_users_file"
+then
   rc=$(cat $allowed_users_file | grep -v '^#' | grep -v '^$' |
-    while read head_pattern user_patterns; do
-      matchlen=$(expr "$1" : "$head_pattern")
-      if [ "$matchlen" == "${#1}" ]; then
-        info "Found matching head pattern: '$head_pattern'"
-        for user_pattern in $user_patterns; do
-          info "Checking user: '$username' against pattern: '$user_pattern'"
-          matchlen=$(expr "$username" : "$user_pattern")
-          if [ "$matchlen" == "${#username}" ]; then
-            grant "Allowing user: '$username' with pattern: '$user_pattern'"
-          fi
-        done
-        deny "The user is not in the access list for this branch"
-      fi
+    while read heads user_patterns
+    do
+      # does this rule apply to us?
+      head_pattern=${heads#+}
+      matchlen=$(expr "$1" : "${head_pattern#+}")
+      test "$matchlen" = ${#1} || continue
+
+      # if non-ff, $heads must be with the '+' prefix
+      test -n "$noff" &&
+      test "$head_pattern" = "$heads" && continue
+
+      info "Found matching head pattern: '$head_pattern'"
+      for user_pattern in $user_patterns; do
+	info "Checking user: '$username' against pattern: '$user_pattern'"
+	matchlen=$(expr "$username" : "$user_pattern")
+	if test "$matchlen" = "${#username}"
+	then
+	  grant "Allowing user: '$username' with pattern: '$user_pattern'"
+	fi
+      done
+      deny "The user is not in the access list for this branch"
     done
   )
   case "$rc" in
@@ -124,23 +133,32 @@
 info "The user belongs to the following groups:"
 info "'$groups'"
 
-if [ -f "$allowed_groups_file" ]; then
+if test -f "$allowed_groups_file"
+then
   rc=$(cat $allowed_groups_file | grep -v '^#' | grep -v '^$' |
-    while read head_pattern group_patterns; do
-      matchlen=$(expr "$1" : "$head_pattern")
-      if [ "$matchlen" == "${#1}" ]; then
-        info "Found matching head pattern: '$head_pattern'"
-        for group_pattern in $group_patterns; do
-          for groupname in $groups; do
-            info "Checking group: '$groupname' against pattern: '$group_pattern'"
-            matchlen=$(expr "$groupname" : "$group_pattern")
-            if [ "$matchlen" == "${#groupname}" ]; then
-              grant "Allowing group: '$groupname' with pattern: '$group_pattern'"
-            fi
-          done
+    while read heads group_patterns
+    do
+      # does this rule apply to us?
+      head_pattern=${heads#+}
+      matchlen=$(expr "$1" : "${head_pattern#+}")
+      test "$matchlen" = ${#1} || continue
+
+      # if non-ff, $heads must be with the '+' prefix
+      test -n "$noff" &&
+      test "$head_pattern" = "$heads" && continue
+
+      info "Found matching head pattern: '$head_pattern'"
+      for group_pattern in $group_patterns; do
+	for groupname in $groups; do
+	  info "Checking group: '$groupname' against pattern: '$group_pattern'"
+	  matchlen=$(expr "$groupname" : "$group_pattern")
+	  if test "$matchlen" = "${#groupname}"
+	  then
+	    grant "Allowing group: '$groupname' with pattern: '$group_pattern'"
+	  fi
         done
-        deny "None of the user's groups are in the access list for this branch"
-      fi
+      done
+      deny "None of the user's groups are in the access list for this branch"
     done
   )
   case "$rc" in
@@ -159,6 +177,7 @@
 whom.  The format of each file would look like this:
 
         refs/heads/master	junio
+	+refs/heads/pu		junio
         refs/heads/cogito$	pasky
         refs/heads/bw/.*	linus
         refs/heads/tmp/.*	.*
@@ -166,7 +185,8 @@
 
 With this, Linus can push or create "bw/penguin" or "bw/zebra"
 or "bw/panda" branches, Pasky can do only "cogito", and JC can
-do master branch and make versioned tags.  And anybody can do
-tmp/blah branches.
+do master and pu branches and make versioned tags.  And anybody
+can do tmp/blah branches. The '+' sign at the pu record means
+that JC can make non-fast-forward pushes on it.
 
 ------------
diff --git a/Documentation/i18n.txt b/Documentation/i18n.txt
index 1e188e6..c673966 100644
--- a/Documentation/i18n.txt
+++ b/Documentation/i18n.txt
@@ -7,11 +7,11 @@
    to be what lstat(2) and creat(2) accepts.  There is no such
    thing as pathname encoding translation.
 
- - The contents of the blob objects are uninterpreted sequence
+ - The contents of the blob objects are uninterpreted sequences
    of bytes.  There is no encoding translation at the core
    level.
 
- - The commit log messages are uninterpreted sequence of non-NUL
+ - The commit log messages are uninterpreted sequences of non-NUL
    bytes.
 
 Although we encourage that the commit log messages are encoded
@@ -21,7 +21,7 @@
 does not forbid it.  However, there are a few things to keep in
 mind.
 
-. `git-commit-tree` (hence, `git-commit` which uses it) issues
+. 'git-commit' and 'git-commit-tree' issues
   a warning if the commit log message given to it does not look
   like a valid UTF-8 string, unless you explicitly say your
   project uses a legacy encoding.  The way to say this is to
@@ -37,7 +37,7 @@
 help other people who look at them later.  Lack of this header
 implies that the commit log message is encoded in UTF-8.
 
-. `git-log`, `git-show` and friends looks at the `encoding`
+. 'git-log', 'git-show' and friends looks at the `encoding`
   header of a commit object, and tries to re-code the log
   message into UTF-8 unless otherwise specified.  You can
   specify the desired output encoding with
diff --git a/Documentation/install-doc-quick.sh b/Documentation/install-doc-quick.sh
index 5433cf8..35f4408 100755
--- a/Documentation/install-doc-quick.sh
+++ b/Documentation/install-doc-quick.sh
@@ -6,7 +6,7 @@
 mandir="$2"
 SUBDIRECTORY_OK=t
 USAGE='<refname> <target directory>'
-. git-sh-setup
+. "$(git --exec-path)"/git-sh-setup
 cd_to_toplevel
 
 test -z "$mandir" && usage
diff --git a/Documentation/merge-config.txt b/Documentation/merge-config.txt
index 48ce747..c735788 100644
--- a/Documentation/merge-config.txt
+++ b/Documentation/merge-config.txt
@@ -1,5 +1,5 @@
 merge.stat::
-	Whether to print the diffstat berween ORIG_HEAD and merge result
+	Whether to print the diffstat between ORIG_HEAD and the merge result
 	at the end of the merge.  True by default.
 
 merge.log::
@@ -16,7 +16,7 @@
 	linkgit:git-mergetool[1].  Valid built-in values are: "kdiff3",
 	"tkdiff", "meld", "xxdiff", "emerge", "vimdiff", "gvimdiff", and
 	"opendiff".  Any other value is treated is custom merge tool
-	and there must be a corresponing mergetool.<tool>.cmd option.
+	and there must be a corresponding mergetool.<tool>.cmd option.
 
 merge.verbosity::
 	Controls the amount of output shown by the recursive merge
diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt
index ffbc6e9..007909a 100644
--- a/Documentation/merge-options.txt
+++ b/Documentation/merge-options.txt
@@ -56,5 +56,5 @@
 	Use the given merge strategy; can be supplied more than
 	once to specify them in the order they should be tried.
 	If there is no `-s` option, a built-in list of strategies
-	is used instead (`git-merge-recursive` when merging a single
-	head, `git-merge-octopus` otherwise).
+	is used instead ('git-merge-recursive' when merging a single
+	head, 'git-merge-octopus' otherwise).
diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index c11d495..388d492 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -103,7 +103,7 @@
 - '%an': author name
 - '%aN': author name (respecting .mailmap)
 - '%ae': author email
-- '%ad': author date
+- '%ad': author date (format respects --date= option)
 - '%aD': author date, RFC2822 style
 - '%ar': author date, relative
 - '%at': author date, UNIX timestamp
diff --git a/Documentation/pull-fetch-param.txt b/Documentation/pull-fetch-param.txt
index f157738..ebdd948 100644
--- a/Documentation/pull-fetch-param.txt
+++ b/Documentation/pull-fetch-param.txt
@@ -32,7 +32,7 @@
 [NOTE]
 You never do your own development on branches that appear
 on the right hand side of a <refspec> colon on `Pull:` lines;
-they are to be updated by `git-fetch`.  If you intend to do
+they are to be updated by 'git-fetch'.  If you intend to do
 development derived from a remote branch `B`, have a `Pull:`
 line to track it (i.e. `Pull: B:remote-B`), and have a separate
 branch `my-B` to do your development on top of it.  The latter
@@ -44,13 +44,13 @@
 +
 [NOTE]
 There is a difference between listing multiple <refspec>
-directly on `git-pull` command line and having multiple
+directly on 'git-pull' command line and having multiple
 `Pull:` <refspec> lines for a <repository> and running
-`git-pull` command without any explicit <refspec> parameters.
+'git-pull' command without any explicit <refspec> parameters.
 <refspec> listed explicitly on the command line are always
 merged into the current branch after fetching.  In other words,
 if you list more than one remote refs, you would be making
-an Octopus.  While `git-pull` run without any explicit <refspec>
+an Octopus.  While 'git-pull' run without any explicit <refspec>
 parameter takes default <refspec>s from `Pull:` lines, it
 merges only the first <refspec> found into the current branch,
 after fetching all the remote refs.  This is because making an
diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt
index abf3420..1023ac2 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -43,7 +43,13 @@
 
 --parents::
 
-	Print the parents of the commit.
+	Print the parents of the commit.  Also enables parent
+	rewriting, see 'History Simplification' below.
+
+--children::
+
+	Print the children of the commit.  Also enables parent
+	rewriting, see 'History Simplification' below.
 
 ifdef::git-rev-list[]
 --timestamp::
@@ -67,7 +73,7 @@
          o---x---a---a  branch A
 -----------------------------------------------------------------------
 +
-you would get an output line this:
+you would get an output like this:
 +
 -----------------------------------------------------------------------
 	$ git rev-list --left-right --boundary --pretty=oneline A...B
@@ -168,6 +174,10 @@
 	Limit the commits output to ones with log message that
 	matches the specified pattern (regular expression).
 
+--all-match::
+	Limit the commits output to ones that match all given --grep,
+	--author and --committer instead of ones that match at least one.
+
 -i::
 --regexp-ignore-case::
 
@@ -189,14 +199,6 @@
 
 	Stop when a given path disappears from the tree.
 
---full-history::
-
-	Show also parts of history irrelevant to current state of a given
-	path. This turns off history simplification, which removed merges
-	which didn't change anything at all at some child. It will still actually
-	simplify away merges that didn't change anything at all into either
-	child.
-
 --no-merges::
 
 	Do not print commits with more than one parent.
@@ -278,32 +280,158 @@
 	Output uninteresting commits at the boundary, which are usually
 	not shown.
 
+--
+
+History Simplification
+~~~~~~~~~~~~~~~~~~~~~~
+
+When optional paths are given, 'git rev-list' simplifies commits with
+various strategies, according to the options you have selected.
+
+Suppose you specified `foo` as the <paths>.  We shall call commits
+that modify `foo` !TREESAME, and the rest TREESAME.  (In a diff
+filtered for `foo`, they look different and equal, respectively.)
+
+In the following, we will always refer to the same example history to
+illustrate the differences between simplification settings.  We assume
+that you are filtering for a file `foo` in this commit graph:
+-----------------------------------------------------------------------
+	  .-A---M---N---O---P
+	 /     /   /   /   /
+	I     B   C   D   E
+	 \   /   /   /   /
+	  `-------------'
+-----------------------------------------------------------------------
+The horizontal line of history A--P is taken to be the first parent of
+each merge.  The commits are:
+
+* `I` is the initial commit, in which `foo` exists with contents
+  "asdf", and a file `quux` exists with contents "quux".  Initial
+  commits are compared to an empty tree, so `I` is !TREESAME.
+
+* In `A`, `foo` contains just "foo".
+
+* `B` contains the same change as `A`.  Its merge `M` is trivial and
+  hence TREESAME to all parents.
+
+* `C` does not change `foo`, but its merge `N` changes it to "foobar",
+  so it is not TREESAME to any parent.
+
+* `D` sets `foo` to "baz".  Its merge `O` combines the strings from
+  `N` and `D` to "foobarbaz"; i.e., it is not TREESAME to any parent.
+
+* `E` changes `quux` to "xyzzy", and its merge `P` combines the
+  strings to "quux xyzzy".  Despite appearing interesting, `P` is
+  TREESAME to all parents.
+
+'rev-list' walks backwards through history, including or excluding
+commits based on whether '\--full-history' and/or parent rewriting
+(via '\--parents' or '\--children') are used.  The following settings
+are available.
+
+Default mode::
+
+	Commits are included if they are not TREESAME to any parent
+	(though this can be changed, see '\--sparse' below).  If the
+	commit was a merge, and it was TREESAME to one parent, follow
+	only that parent.  (Even if there are several TREESAME
+	parents, follow only one of them.)  Otherwise, follow all
+	parents.
++
+This results in:
++
+-----------------------------------------------------------------------
+	  .-A---N---O
+	 /         /
+	I---------D
+-----------------------------------------------------------------------
++
+Note how the rule to only follow the TREESAME parent, if one is
+available, removed `B` from consideration entirely.  `C` was
+considered via `N`, but is TREESAME.  Root commits are compared to an
+empty tree, so `I` is !TREESAME.
++
+Parent/child relations are only visible with --parents, but that does
+not affect the commits selected in default mode, so we have shown the
+parent lines.
+
+--full-history without parent rewriting::
+
+	This mode differs from the default in one point: always follow
+	all parents of a merge, even if it is TREESAME to one of them.
+	Even if more than one side of the merge has commits that are
+	included, this does not imply that the merge itself is!  In
+	the example, we get
++
+-----------------------------------------------------------------------
+	I  A  B  N  D  O
+-----------------------------------------------------------------------
++
+`P` and `M` were excluded because they are TREESAME to a parent.  `E`,
+`C` and `B` were all walked, but only `B` was !TREESAME, so the others
+do not appear.
++
+Note that without parent rewriting, it is not really possible to talk
+about the parent/child relationships between the commits, so we show
+them disconnected.
+
+--full-history with parent rewriting::
+
+	Ordinary commits are only included if they are !TREESAME
+	(though this can be changed, see '\--sparse' below).
++
+Merges are always included.  However, their parent list is rewritten:
+Along each parent, prune away commits that are not included
+themselves.  This results in
++
+-----------------------------------------------------------------------
+	  .-A---M---N---O---P
+	 /     /   /   /   /
+	I     B   /   D   /
+	 \   /   /   /   /
+	  `-------------'
+-----------------------------------------------------------------------
++
+Compare to '\--full-history' without rewriting above.  Note that `E`
+was pruned away because it is TREESAME, but the parent list of P was
+rewritten to contain `E`'s parent `I`.  The same happened for `C` and
+`N`.  Note also that `P` was included despite being TREESAME.
+
+In addition to the above settings, you can change whether TREESAME
+affects inclusion:
+
 --dense::
+
+	Commits that are walked are included if they are not TREESAME
+	to any parent.
+
 --sparse::
 
-When optional paths are given, the default behaviour ('--dense') is to
-only output commits that changes at least one of them, and also ignore
-merges that do not touch the given paths.
+	All commits that are walked are included.
++
+Note that without '\--full-history', this still simplifies merges: if
+one of the parents is TREESAME, we follow only that one, so the other
+sides of the merge are never walked.
 
-Use the '--sparse' flag to makes the command output all eligible commits
-(still subject to count and age limitation), but apply merge
-simplification nevertheless.
 
 ifdef::git-rev-list[]
+Bisection Helpers
+~~~~~~~~~~~~~~~~~
+
 --bisect::
 
 Limit output to the one commit object which is roughly halfway between
 the included and excluded commits. Thus, if
 
 -----------------------------------------------------------------------
-	$ git-rev-list --bisect foo ^bar ^baz
+	$ git rev-list --bisect foo ^bar ^baz
 -----------------------------------------------------------------------
 
 outputs 'midpoint', the output of the two commands
 
 -----------------------------------------------------------------------
-	$ git-rev-list foo ^midpoint
-	$ git-rev-list midpoint ^bar ^baz
+	$ git rev-list foo ^midpoint
+	$ git rev-list midpoint ^bar ^baz
 -----------------------------------------------------------------------
 
 would be of roughly the same length.  Finding the change which
@@ -339,7 +467,6 @@
 `--bisect-vars` had been used alone.
 endif::git-rev-list[]
 
---
 
 Commit Ordering
 ~~~~~~~~~~~~~~~
diff --git a/Documentation/technical/api-path-list.txt b/Documentation/technical/api-path-list.txt
deleted file mode 100644
index 9dbedd0..0000000
--- a/Documentation/technical/api-path-list.txt
+++ /dev/null
@@ -1,126 +0,0 @@
-path-list API
-=============
-
-The path_list API offers a data structure and functions to handle sorted
-and unsorted string lists.
-
-The name is a bit misleading, a path_list may store not only paths but
-strings in general.
-
-The caller:
-
-. Allocates and clears a `struct path_list` variable.
-
-. Initializes the members. You might want to set the flag `strdup_paths`
-  if the strings should be strdup()ed. For example, this is necessary
-  when you add something like git_path("..."), since that function returns
-  a static buffer that will change with the next call to git_path().
-+
-If you need something advanced, you can manually malloc() the `items`
-member (you need this if you add things later) and you should set the
-`nr` and `alloc` members in that case, too.
-
-. Adds new items to the list, using `path_list_append` or `path_list_insert`.
-
-. Can check if a string is in the list using `path_list_has_path` or
-  `unsorted_path_list_has_path` and get it from the list using
-  `path_list_lookup` for sorted lists.
-
-. Can sort an unsorted list using `sort_path_list`.
-
-. Finally it should free the list using `path_list_clear`.
-
-Example:
-
-----
-struct path_list list;
-int i;
-
-memset(&list, 0, sizeof(struct path_list));
-path_list_append("foo", &list);
-path_list_append("bar", &list);
-for (i = 0; i < list.nr; i++)
-	printf("%s\n", list.items[i].path)
-----
-
-NOTE: It is more efficient to build an unsorted list and sort it
-afterwards, instead of building a sorted list (`O(n log n)` instead of
-`O(n^2)`).
-+
-However, if you use the list to check if a certain string was added
-already, you should not do that (using unsorted_path_list_has_path()),
-because the complexity would be quadratic again (but with a worse factor).
-
-Functions
----------
-
-* General ones (works with sorted and unsorted lists as well)
-
-`print_path_list`::
-
-	Dump a path_list to stdout, useful mainly for debugging purposes. It
-	can take an optional header argument and it writes out the
-	string-pointer pairs of the path_list, each one in its own line.
-
-`path_list_clear`::
-
-	Free a path_list. The `path` pointer of the items will be freed in case
-	the `strdup_paths` member of the path_list is set. The second parameter
-	controls if the `util` pointer of the items should be freed or not.
-
-* Functions for sorted lists only
-
-`path_list_has_path`::
-
-	Determine if the path_list has a given string or not.
-
-`path_list_insert`::
-
-	Insert a new element to the path_list. The returned pointer can be handy
-	if you want to write something to the `util` pointer of the
-	path_list_item containing the just added string.
-+
-Since this function uses xrealloc() (which die()s if it fails) if the
-list needs to grow, it is safe not to check the pointer. I.e. you may
-write `path_list_insert(...)->util = ...;`.
-
-`path_list_lookup`::
-
-	Look up a given string in the path_list, returning the containing
-	path_list_item. If the string is not found, NULL is returned.
-
-* Functions for unsorted lists only
-
-`path_list_append`::
-
-	Append a new string to the end of the path_list.
-
-`sort_path_list`::
-
-	Make an unsorted list sorted.
-
-`unsorted_path_list_has_path`::
-
-	It's like `path_list_has_path()` but for unsorted lists.
-+
-This function needs to look through all items, as opposed to its
-counterpart for sorted lists, which performs a binary search.
-
-Data structures
----------------
-
-* `struct path_list_item`
-
-Represents an item of the list. The `path` member is a pointer to the
-string, and you may use the `util` member for any purpose, if you want.
-
-* `struct path_list`
-
-Represents the list itself.
-
-. The array of items are available via the `items` member.
-. The `nr` member contains the number of items stored in the list.
-. The `alloc` member is used to avoid reallocating at every insertion.
-  You should not tamper with it.
-. Setting the `strdup_paths` member to 1 will strdup() the strings
-  before adding them, see above.
diff --git a/Documentation/technical/api-string-list.txt b/Documentation/technical/api-string-list.txt
new file mode 100644
index 0000000..293bb15
--- /dev/null
+++ b/Documentation/technical/api-string-list.txt
@@ -0,0 +1,128 @@
+string-list API
+===============
+
+The string_list API offers a data structure and functions to handle sorted
+and unsorted string lists.
+
+The 'string_list' struct used to be called 'path_list', but was renamed
+because it is not specific to paths.
+
+The caller:
+
+. Allocates and clears a `struct string_list` variable.
+
+. Initializes the members. You might want to set the flag `strdup_strings`
+  if the strings should be strdup()ed. For example, this is necessary
+  when you add something like git_path("..."), since that function returns
+  a static buffer that will change with the next call to git_path().
++
+If you need something advanced, you can manually malloc() the `items`
+member (you need this if you add things later) and you should set the
+`nr` and `alloc` members in that case, too.
+
+. Adds new items to the list, using `string_list_append` or
+  `string_list_insert`.
+
+. Can check if a string is in the list using `string_list_has_string` or
+  `unsorted_string_list_has_string` and get it from the list using
+  `string_list_lookup` for sorted lists.
+
+. Can sort an unsorted list using `sort_string_list`.
+
+. Finally it should free the list using `string_list_clear`.
+
+Example:
+
+----
+struct string_list list;
+int i;
+
+memset(&list, 0, sizeof(struct string_list));
+string_list_append("foo", &list);
+string_list_append("bar", &list);
+for (i = 0; i < list.nr; i++)
+	printf("%s\n", list.items[i].string)
+----
+
+NOTE: It is more efficient to build an unsorted list and sort it
+afterwards, instead of building a sorted list (`O(n log n)` instead of
+`O(n^2)`).
++
+However, if you use the list to check if a certain string was added
+already, you should not do that (using unsorted_string_list_has_string()),
+because the complexity would be quadratic again (but with a worse factor).
+
+Functions
+---------
+
+* General ones (works with sorted and unsorted lists as well)
+
+`print_string_list`::
+
+	Dump a string_list to stdout, useful mainly for debugging purposes. It
+	can take an optional header argument and it writes out the
+	string-pointer pairs of the string_list, each one in its own line.
+
+`string_list_clear`::
+
+	Free a string_list. The `string` pointer of the items will be freed in
+	case the `strdup_strings` member of the string_list is set. The second
+	parameter controls if the `util` pointer of the items should be freed
+	or not.
+
+* Functions for sorted lists only
+
+`string_list_has_string`::
+
+	Determine if the string_list has a given string or not.
+
+`string_list_insert`::
+
+	Insert a new element to the string_list. The returned pointer can be
+	handy if you want to write something to the `util` pointer of the
+	string_list_item containing the just added string.
++
+Since this function uses xrealloc() (which die()s if it fails) if the
+list needs to grow, it is safe not to check the pointer. I.e. you may
+write `string_list_insert(...)->util = ...;`.
+
+`string_list_lookup`::
+
+	Look up a given string in the string_list, returning the containing
+	string_list_item. If the string is not found, NULL is returned.
+
+* Functions for unsorted lists only
+
+`string_list_append`::
+
+	Append a new string to the end of the string_list.
+
+`sort_string_list`::
+
+	Make an unsorted list sorted.
+
+`unsorted_string_list_has_string`::
+
+	It's like `string_list_has_string()` but for unsorted lists.
++
+This function needs to look through all items, as opposed to its
+counterpart for sorted lists, which performs a binary search.
+
+Data structures
+---------------
+
+* `struct string_list_item`
+
+Represents an item of the list. The `string` member is a pointer to the
+string, and you may use the `util` member for any purpose, if you want.
+
+* `struct string_list`
+
+Represents the list itself.
+
+. The array of items are available via the `items` member.
+. The `nr` member contains the number of items stored in the list.
+. The `alloc` member is used to avoid reallocating at every insertion.
+  You should not tamper with it.
+. Setting the `strdup_strings` member to 1 will strdup() the strings
+  before adding them, see above.
diff --git a/Documentation/urls-remotes.txt b/Documentation/urls-remotes.txt
index 9975300..41ec777 100644
--- a/Documentation/urls-remotes.txt
+++ b/Documentation/urls-remotes.txt
@@ -49,8 +49,8 @@
 
 ------------
 
-`Push:` lines are used by `git-push` and
-`Pull:` lines are used by `git-pull` and `git-fetch`.
+`Push:` lines are used by 'git-push' and
+`Pull:` lines are used by 'git-pull' and 'git-fetch'.
 Multiple `Push:` and `Pull:` lines may
 be specified for additional branch mappings.
 
@@ -68,13 +68,22 @@
 ------------
 
 `<url>` is required; `#<head>` is optional.
-When you do not provide a refspec on the command line,
-git will use the following refspec, where `<head>` defaults to `master`,
-and `<repository>` is the name of this file
-you provided in the command line.
+
+Depending on the operation, git will use one of the following
+refspecs, if you don't provide one on the command line.
+`<branch>` is the name of this file in `$GIT_DIR/branches` and
+`<head>` defaults to `master`.
+
+git fetch uses:
 
 ------------
-	refs/heads/<head>:<repository>
+	refs/heads/<head>:refs/heads/<branch>
+------------
+
+git push uses:
+
+------------
+	HEAD:refs/heads/<head>
 ------------
 
 
diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt
index 49a4a89..99cb808 100644
--- a/Documentation/user-manual.txt
+++ b/Documentation/user-manual.txt
@@ -13,12 +13,12 @@
 regressions, and so on.
 
 People needing to do actual development will also want to read
-<<Developing-with-git>> and <<sharing-development>>.
+<<Developing-With-git>> and <<sharing-development>>.
 
 Further chapters cover more specialized topics.
 
 Comprehensive reference documentation is available through the man
-pages.  For a command such as "git clone", just use
+pages.  For a command such as "git clone <repo>", just use
 
 ------------------------------------------------
 $ man git-clone
@@ -178,7 +178,7 @@
 did, and why.
 
 Every commit has a 40-hexdigit id, sometimes called the "object name" or the
-"SHA1 id", shown on the first line of the "git show" output.  You can usually
+"SHA1 id", shown on the first line of the "git-show" output.  You can usually
 refer to a commit by a shorter name, such as a tag or a branch name, but this
 longer name can also be useful.  Most importantly, it is a globally unique
 name for this commit: so if you tell somebody else the object name (for
@@ -389,8 +389,8 @@
 references with the same shorthand name, see the "SPECIFYING
 REVISIONS" section of linkgit:git-rev-parse[1].
 
-[[Updating-a-repository-with-git-fetch]]
-Updating a repository with git fetch
+[[Updating-a-repository-With-git-fetch]]
+Updating a repository with git-fetch
 ------------------------------------
 
 Eventually the developer cloned from will do additional work in her
@@ -417,7 +417,7 @@
 -------------------------------------------------
 
 New remote-tracking branches will be stored under the shorthand name
-that you gave "git remote add", in this case linux-nfs:
+that you gave "git-remote add", in this case linux-nfs:
 
 -------------------------------------------------
 $ git branch -r
@@ -479,10 +479,10 @@
 -------------------------------------------------
 
 If you run "git branch" at this point, you'll see that git has
-temporarily moved you to a new branch named "bisect".  This branch
-points to a commit (with commit id 65934...) that is reachable from
-"master" but not from v2.6.18.  Compile and test it, and see whether
-it crashes.  Assume it does crash.  Then:
+temporarily moved you in "(no branch)". HEAD is now detached from any
+branch and points directly to a commit (with commit id 65934...) that
+is reachable from "master" but not from v2.6.18. Compile and test it,
+and see whether it crashes. Assume it does crash. Then:
 
 -------------------------------------------------
 $ git bisect bad
@@ -504,8 +504,7 @@
 $ git bisect reset
 -------------------------------------------------
 
-to return you to the branch you were on before and delete the
-temporary "bisect" branch.
+to return you to the branch you were on before.
 
 Note that the version which git-bisect checks out for you at each
 point is just a suggestion, and you're free to try a different
@@ -518,7 +517,7 @@
 -------------------------------------------------
 
 which will run gitk and label the commit it chose with a marker that
-says "bisect".  Chose a safe-looking commit nearby, note its commit
+says "bisect".  Choose a safe-looking commit nearby, note its commit
 id, and check it out with:
 
 -------------------------------------------------
@@ -528,6 +527,22 @@
 then test, run "bisect good" or "bisect bad" as appropriate, and
 continue.
 
+Instead of "git bisect visualize" and then "git reset --hard
+fb47ddb2db...", you might just want to tell git that you want to skip
+the current commit:
+
+-------------------------------------------------
+$ git bisect skip
+-------------------------------------------------
+
+In this case, though, git may not eventually be able to tell the first
+bad one between some first skipped commits and a later bad commit.
+
+There are also ways to automate the bisecting process if you have a
+test script that can tell a good from a bad commit. See
+linkgit:git-bisect[1] for more information about this and other "git
+bisect" features.
+
 [[naming-commits]]
 Naming commits
 --------------
@@ -930,7 +945,7 @@
 and then he just cut-and-pastes the output commands after verifying that
 they look OK.
 
-[[Finding-comments-with-given-content]]
+[[Finding-comments-With-given-Content]]
 Finding commits referencing a file with given content
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -947,7 +962,7 @@
 student.  The linkgit:git-log[1], linkgit:git-diff-tree[1], and
 linkgit:git-hash-object[1] man pages may prove helpful.
 
-[[Developing-with-git]]
+[[Developing-With-git]]
 Developing with git
 ===================
 
@@ -1048,7 +1063,7 @@
 
 shows the difference between the working tree and the index file.
 
-Note that "git add" always adds just the current contents of a file
+Note that "git-add" always adds just the current contents of a file
 to the index; further changes to the same file will be ignored unless
 you run git-add on the file again.
 
@@ -1111,10 +1126,10 @@
 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
+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`".
+"`git add .`" practically useless, and they keep showing up in the output of
+"`git status`".
 
 You can tell git to ignore certain files by creating a file called .gitignore
 in the top level of your working directory, with contents such as:
@@ -1303,7 +1318,7 @@
 $ git diff --theirs file.txt	# same as the above.
 -------------------------------------------------
 
-The linkgit:git-log[1] and gitk[1] commands also provide special help
+The linkgit:git-log[1] and linkgit:gitk[1] commands also provide special help
 for merges:
 
 -------------------------------------------------
@@ -1449,7 +1464,7 @@
 
 In the process of undoing a previous bad change, you may find it
 useful to check out an older version of a particular file using
-linkgit:git-checkout[1].  We've used git checkout before to switch
+linkgit:git-checkout[1].  We've used git-checkout before to switch
 branches, but it has quite different behavior if it is given a path
 name: the command
 
@@ -1650,15 +1665,15 @@
 Sharing development with others
 ===============================
 
-[[getting-updates-with-git-pull]]
-Getting updates with git pull
+[[getting-updates-With-git-pull]]
+Getting updates with git-pull
 -----------------------------
 
 After you clone a repository and make a few changes of your own, you
 may wish to check the original repository for updates and merge them
 into your own work.
 
-We have already seen <<Updating-a-repository-with-git-fetch,how to
+We have already seen <<Updating-a-repository-With-git-fetch,how to
 keep remote tracking branches up to date>> with linkgit:git-fetch[1],
 and how to merge two branches.  So you can merge in changes from the
 original repository's master branch with:
@@ -1769,8 +1784,8 @@
 
 Another way to submit changes to a project is to tell the maintainer
 of that project to pull the changes from your repository using
-linkgit:git-pull[1].  In the section "<<getting-updates-with-git-pull,
-Getting updates with git pull>>" we described this as a way to get
+linkgit: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.
 
@@ -1875,12 +1890,11 @@
 $ mv proj.git /home/you/public_html/proj.git
 $ cd proj.git
 $ git --bare update-server-info
-$ chmod a+x hooks/post-update
+$ mv hooks/post-update.sample hooks/post-update
 -------------------------------------------------
 
 (For an explanation of the last two lines, see
-linkgit:git-update-server-info[1], and the documentation
-linkgit:githooks[5][Hooks used by git].)
+linkgit:git-update-server-info[1] and linkgit:githooks[5].)
 
 Advertise the URL of proj.git.  Anybody else should then be able to
 clone or pull from that URL, for example with a command line like:
@@ -1964,10 +1978,10 @@
 
 This can happen, for example, if you:
 
-	- use `git reset --hard` to remove already-published commits, or
-	- use `git commit --amend` to replace already-published commits
+	- use `git-reset --hard` to remove already-published commits, or
+	- use `git-commit --amend` to replace already-published commits
 	  (as in <<fixing-a-mistake-by-rewriting-history>>), or
-	- use `git rebase` to rebase any already-published commits (as
+	- use `git-rebase` to rebase any already-published commits (as
 	  in <<using-git-rebase>>).
 
 You may force git-push to perform the update anyway by preceding the
@@ -1980,7 +1994,7 @@
 Normally whenever a branch head in a public repository is modified, it
 is modified to point to a descendant of the commit that it pointed to
 before.  By forcing a push in this situation, you break that convention.
-(See <<problems-with-rewriting-history>>.)
+(See <<problems-With-rewriting-history>>.)
 
 Nevertheless, this is a common practice for people that need a simple
 way to publish a work-in-progress patch series, and it is an acceptable
@@ -1989,10 +2003,10 @@
 
 It's also possible for a push to fail in this way when other people have
 the right to push to the same repository.  In that case, the correct
-solution is to retry the push after first updating your work by either a
-pull or a fetch followed by a rebase; see the
+solution is to retry the push after first updating your work: either by a
+pull, or by a fetch followed by a rebase; see the
 <<setting-up-a-shared-repository,next section>> and
-linkgit:gitcvs-migration[7][git for CVS users] for more.
+linkgit:gitcvs-migration[7] for more.
 
 [[setting-up-a-shared-repository]]
 Setting up a shared repository
@@ -2001,7 +2015,7 @@
 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
-linkgit:gitcvs-migration[7][git for CVS users] for instructions on how to
+linkgit:gitcvs-migration[7] for instructions on how to
 set this up.
 
 However, while there is nothing wrong with git's support for shared
@@ -2171,7 +2185,7 @@
 changes are in a specific branch, use:
 
 -------------------------------------------------
-$ git log linux..branchname | git-shortlog
+$ git log linux..branchname | git shortlog
 -------------------------------------------------
 
 To see whether it has already been merged into the test or release branches,
@@ -2432,7 +2446,7 @@
 -------------------------------------------------
 
 This will remove each of your commits from mywork, temporarily saving
-them as patches (in a directory named ".dotest"), update mywork to
+them as patches (in a directory named ".git/rebase-apply"), update mywork to
 point at the latest version of origin, then apply each of the saved
 patches to the new mywork.  The result will look like:
 
@@ -2444,8 +2458,8 @@
 ................................................
 
 In the process, it may discover conflicts.  In that case it will stop
-and allow you to fix the conflicts; after fixing conflicts, use "git
-add" to update the index with those contents, and then, instead of
+and allow you to fix the conflicts; after fixing conflicts, use "git-add"
+to update the index with those contents, and then, instead of
 running git-commit, just run
 
 -------------------------------------------------
@@ -2549,7 +2563,7 @@
 purpose of maintaining a patch series.  These are outside of the scope of
 this manual.
 
-[[problems-with-rewriting-history]]
+[[problems-With-rewriting-history]]
 Problems with rewriting history
 -------------------------------
 
@@ -2701,8 +2715,8 @@
 git fetch and fast-forwards
 ---------------------------
 
-In the previous example, when updating an existing branch, "git
-fetch" checks to make sure that the most recent commit on the remote
+In the previous example, when updating an existing branch, "git-fetch"
+checks to make sure that the most recent commit on the remote
 branch is a descendant of the most recent commit on your copy of the
 branch before updating your copy of the branch to point at the new
 commit.  Git calls this process a <<fast-forwards,fast forward>>.
@@ -2727,7 +2741,7 @@
             o--o--o <-- new head of the branch
 ................................................
 
-In this case, "git fetch" will fail, and print out a warning.
+In this case, "git-fetch" will fail, and print out a warning.
 
 In that case, you can still force git to update to the new head, as
 described in the following section.  However, note that in the
@@ -2736,7 +2750,7 @@
 them.
 
 [[forcing-fetch]]
-Forcing git fetch to do non-fast-forward updates
+Forcing git-fetch to do non-fast-forward updates
 ------------------------------------------------
 
 If git fetch fails because the new head of a branch is not a
@@ -2862,7 +2876,7 @@
 "tag".
 
 - A <<def_blob_object,"blob" object>> is used to store file data.
-- A <<def_tree_object,"tree" object>> is an object that ties one or more
+- A <<def_tree_object,"tree" object>> ties one or more
   "blob" objects into a directory structure. In addition, a tree object
   can refer to other tree objects, thus creating a directory hierarchy.
 - A <<def_commit_object,"commit" object>> ties such directory hierarchies
@@ -3037,7 +3051,7 @@
 
 A tag object contains an object, object type, tag name, the name of the
 person ("tagger") who created the tag, and a message, which may contain
-a signature, as can be seen using the linkgit:git-cat-file[1]:
+a signature, as can be seen using linkgit:git-cat-file[1]:
 
 ------------------------------------------------
 $ git cat-file tag v1.5.0
@@ -3107,7 +3121,7 @@
 
 to remove any of the "loose" objects that are now contained in the
 pack.  This will also remove any unreferenced objects (which may be
-created when, for example, you use "git reset" to remove a commit).
+created when, for example, you use "git-reset" to remove a commit).
 You can verify that the loose objects are gone by looking at the
 .git/objects directory or by running
 
@@ -3136,7 +3150,7 @@
 pointer itself just doesn't, since you replaced it with another one.
 
 There are also other situations that cause dangling objects. For
-example, a "dangling blob" may arise because you did a "git add" of a
+example, a "dangling blob" may arise because you did a "git-add" of a
 file, but then, before you actually committed it and made it part of the
 bigger picture, you changed something else in that file and committed
 that *updated* thing--the old state that you added originally ends up
@@ -3186,7 +3200,7 @@
 almost always the result of either being a half-way mergebase (the blob
 will often even have the conflict markers from a merge in it, if you
 have had conflicting merges that you fixed up by hand), or simply
-because you interrupted a "git fetch" with ^C or something like that,
+because you interrupted a "git-fetch" with ^C or something like that,
 leaving _some_ of the new objects in the object database, but just
 dangling and useless.
 
@@ -3235,7 +3249,7 @@
 Assume the output looks like this:
 
 ------------------------------------------------
-$ git-fsck --full
+$ git fsck --full
 broken link from    tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
               to    blob 4b9458b3786228369c63936db65827de3cc06200
 missing blob 4b9458b3786228369c63936db65827de3cc06200
@@ -3459,23 +3473,23 @@
 $ git init
 $ for i in a b c d
 do
-	git submodule add ~/git/$i
+	git submodule add ~/git/$i $i
 done
 -------------------------------------------------
 
 NOTE: Do not use local URLs here if you plan to publish your superproject!
 
-See what files `git submodule` created:
+See what files `git-submodule` created:
 
 -------------------------------------------------
 $ ls -a
 .  ..  .git  .gitmodules  a  b  c  d
 -------------------------------------------------
 
-The `git submodule add` command does a couple of things:
+The `git-submodule add <repo> <path>` command does a couple of things:
 
-- It clones the submodule under the current directory and by default checks out
-  the master branch.
+- It clones the submodule from <repo> to the given <path> under the
+  current directory and by default checks out the master branch.
 - It adds the submodule's clone path to the linkgit:gitmodules[5] file and
   adds this file to the index, ready to be committed.
 - It adds the submodule's current commit ID to the index, ready to be
@@ -3518,7 +3532,7 @@
 $ git submodule init
 -------------------------------------------------
 
-Now use `git submodule update` to clone the repositories and check out the
+Now use `git-submodule update` to clone the repositories and check out the
 commits specified in the superproject:
 
 -------------------------------------------------
@@ -3528,8 +3542,8 @@
 .  ..  .git  a.txt
 -------------------------------------------------
 
-One major difference between `git submodule update` and `git submodule add` is
-that `git submodule update` checks out a specific commit, rather than the tip
+One major difference between `git-submodule update` and `git-submodule add` is
+that `git-submodule update` checks out a specific commit, rather than the tip
 of a branch. It's like checking out a tag: the head is detached, so you're not
 working on a branch.
 
@@ -3695,7 +3709,7 @@
 considering a removed file to be a valid thing, and if the file really
 does not exist any more, it will update the index accordingly.
 
-As a special case, you can also do `git-update-index --refresh`, which
+As a special case, you can also do `git update-index --refresh`, which
 will refresh the "stat" information of each index to match the current
 stat information. It will 'not' update the object status itself, and
 it will only update the fields that are used to quickly test whether
@@ -3730,7 +3744,7 @@
 index.  Normal operation is just
 
 -------------------------------------------------
-$ git-read-tree <sha1 of tree>
+$ git read-tree <sha1 of tree>
 -------------------------------------------------
 
 and your index file will now be equivalent to the tree that you saved
@@ -3753,7 +3767,7 @@
 with
 
 -------------------------------------------------
-$ git-checkout-index filename
+$ git checkout-index filename
 -------------------------------------------------
 
 or, if you want to check out all of the index, use `-a`.
@@ -3771,7 +3785,7 @@
 Tying it all together
 ~~~~~~~~~~~~~~~~~~~~~
 
-To commit a tree you have instantiated with "git-write-tree", you'd
+To commit a tree you have instantiated with "git write-tree", you'd
 create a "commit" object that refers to that tree and the history
 behind it--most notably the "parent" commits that preceded it in
 history.
@@ -3790,7 +3804,7 @@
 state at the time of the commit, and a list of parents:
 
 -------------------------------------------------
-$ git-commit-tree <tree> -p <parent> [-p <parent2> ..]
+$ git commit-tree <tree> -p <parent> [-p <parent2> ..]
 -------------------------------------------------
 
 and then giving the reason for the commit on stdin (either through
@@ -3853,14 +3867,14 @@
 object:
 
 -------------------------------------------------
-$ git-cat-file -t <objectname>
+$ git cat-file -t <objectname>
 -------------------------------------------------
 
 shows the type of the object, and once you have the type (which is
 usually implicit in where you find the object), you can use
 
 -------------------------------------------------
-$ git-cat-file blob|tree|commit|tag <objectname>
+$ git cat-file blob|tree|commit|tag <objectname>
 -------------------------------------------------
 
 to show its contents. NOTE! Trees have binary content, and as a result
@@ -3874,7 +3888,7 @@
 you can do
 
 -------------------------------------------------
-$ git-cat-file commit HEAD
+$ git cat-file commit HEAD
 -------------------------------------------------
 
 to see what the top commit was.
@@ -3898,7 +3912,7 @@
 of two commits with
 
 -------------------------------------------------
-$ git-merge-base <commit1> <commit2>
+$ git merge-base <commit1> <commit2>
 -------------------------------------------------
 
 which will return you the commit they are both based on.  You should
@@ -3906,7 +3920,7 @@
 do with (for example)
 
 -------------------------------------------------
-$ git-cat-file commit <commitname> | head -1
+$ git cat-file commit <commitname> | head -1
 -------------------------------------------------
 
 since the tree object information is always the first line in a commit
@@ -3923,12 +3937,12 @@
 To do the merge, do
 
 -------------------------------------------------
-$ git-read-tree -m -u <origtree> <yourtree> <targettree>
+$ git read-tree -m -u <origtree> <yourtree> <targettree>
 -------------------------------------------------
 
 which will do all trivial merge operations for you directly in the
 index file, and you can just write the result out with
-`git-write-tree`.
+`git write-tree`.
 
 
 [[merging-multiple-trees-2]]
@@ -3942,18 +3956,18 @@
 object, and you will have to resolve any such merge clashes using
 other tools before you can write out the result.
 
-You can examine such index state with `git-ls-files --unmerged`
+You can examine such index state with `git ls-files --unmerged`
 command.  An example:
 
 ------------------------------------------------
-$ git-read-tree -m $orig HEAD $target
-$ git-ls-files --unmerged
+$ git read-tree -m $orig HEAD $target
+$ git ls-files --unmerged
 100644 263414f423d0e4d70dae8fe53fa34614ff3e2860 1	hello.c
 100644 06fa6a24256dc7e560efa5687fa84b51f0263c3a 2	hello.c
 100644 cc44c73eb783565da5831b4d820c962954019b69 3	hello.c
 ------------------------------------------------
 
-Each line of the `git-ls-files --unmerged` output begins with
+Each line of the `git ls-files --unmerged` output begins with
 the blob mode bits, blob SHA1, 'stage number', and the
 filename.  The 'stage number' is git's way to say which tree it
 came from: stage 1 corresponds to `$orig` tree, stage 2 `HEAD`
@@ -3971,9 +3985,9 @@
 the blob objects from these three stages yourself, like this:
 
 ------------------------------------------------
-$ git-cat-file blob 263414f... >hello.c~1
-$ git-cat-file blob 06fa6a2... >hello.c~2
-$ git-cat-file blob cc44c73... >hello.c~3
+$ git cat-file blob 263414f... >hello.c~1
+$ git cat-file blob 06fa6a2... >hello.c~2
+$ git cat-file blob cc44c73... >hello.c~3
 $ git merge-file hello.c~2 hello.c~1 hello.c~3
 ------------------------------------------------
 
@@ -3984,23 +3998,23 @@
 
 -------------------------------------------------
 $ mv -f hello.c~2 hello.c
-$ git-update-index hello.c
+$ git update-index hello.c
 -------------------------------------------------
 
-When a path is in unmerged state, running `git-update-index` for
+When a path is in the "unmerged" state, running `git-update-index` for
 that path tells git to mark the path resolved.
 
 The above is the description of a git merge at the lowest level,
 to help you understand what conceptually happens under the hood.
-In practice, nobody, not even git itself, uses three `git-cat-file`
-for this.  There is `git-merge-index` program that extracts the
+In practice, nobody, not even git itself, runs `git-cat-file` three times
+for this.  There is a `git-merge-index` program that extracts the
 stages to temporary files and calls a "merge" script on it:
 
 -------------------------------------------------
-$ git-merge-index git-merge-one-file hello.c
+$ git merge-index git-merge-one-file hello.c
 -------------------------------------------------
 
-and that is what higher level `git merge -s resolve` is implemented with.
+and that is what higher level `git-merge -s resolve` is implemented with.
 
 [[hacking-git]]
 Hacking git
@@ -4062,7 +4076,7 @@
 README in that revision uses the word "changeset" to describe what we
 now call a <<def_commit_object,commit>>.
 
-Also, we do not call it "cache" any more, but "index", however, the
+Also, we do not call it "cache" any more, but rather "index"; however, the
 file is still called `cache.h`.  Remark: Not much reason to change it now,
 especially since there is no good single name for it anyway, because it is
 basically _the_ header file which is included by _all_ of Git's C sources.
@@ -4096,7 +4110,7 @@
 This is just to get you into the groove for the most libified part of Git:
 the revision walker.
 
-Basically, the initial version of `git log` was a shell script:
+Basically, the initial version of `git-log` was a shell script:
 
 ----------------------------------------------------------------
 $ git-rev-list --pretty $(git-rev-parse --default HEAD "$@") | \
@@ -4128,10 +4142,10 @@
 
 If you are interested in more details of the revision walking process,
 just have a look at the first implementation of `cmd_log()`; call
-`git-show v1.3.0{tilde}155^2{tilde}4` and scroll down to that function (note that you
+`git show v1.3.0{tilde}155^2{tilde}4` and scroll down to that function (note that you
 no longer need to call `setup_pager()` directly).
 
-Nowadays, `git log` is a builtin, which means that it is _contained_ in the
+Nowadays, `git-log` is a builtin, which means that it is _contained_ in the
 command `git`.  The source side of a builtin is
 
 - a function called `cmd_<bla>`, typically defined in `builtin-<bla>.c`,
@@ -4147,7 +4161,7 @@
 _not_ named like the `.c` file in which they live have to be listed in
 `BUILT_INS` in the `Makefile`.
 
-`git log` looks more complicated in C than it does in the original script,
+`git-log` looks more complicated in C than it does in the original script,
 but that allows for a much greater flexibility and performance.
 
 Here again it is a good point to take a pause.
@@ -4158,9 +4172,9 @@
 So, think about something which you are interested in, say, "how can I
 access a blob just knowing the object name of it?".  The first step is to
 find a Git command with which you can do it.  In this example, it is either
-`git show` or `git cat-file`.
+`git-show` or `git-cat-file`.
 
-For the sake of clarity, let's stay with `git cat-file`, because it
+For the sake of clarity, let's stay with `git-cat-file`, because it
 
 - is plumbing, and
 
@@ -4219,10 +4233,10 @@
 -----------------------------------
 
 Sometimes, you do not know where to look for a feature.  In many such cases,
-it helps to search through the output of `git log`, and then `git show` the
+it helps to search through the output of `git log`, and then `git-show` the
 corresponding commit.
 
-Example: If you know that there was some test case for `git bundle`, but
+Example: If you know that there was some test case for `git-bundle`, but
 do not remember where it was (yes, you _could_ `git grep bundle t/`, but that
 does not illustrate the point!):
 
@@ -4546,4 +4560,3 @@
 More on recovery from repository corruption.  See:
 	http://marc.theaimsgroup.com/?l=git&m=117263864820799&w=2
 	http://marc.theaimsgroup.com/?l=git&m=117147855503798&w=2
-	http://marc.theaimsgroup.com/?l=git&m=117147855503798&w=2
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index 445dca3..6c7465c 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v1.5.6.5.GIT
+DEF_VER=v1.6.0.2.GIT
 
 LF='
 '
@@ -16,7 +16,8 @@
 	case "$VN" in
 	*$LF*) (exit 1) ;;
 	v[0-9]*)
-		test -z "$(git diff-index --name-only HEAD)" ||
+		git update-index -q --refresh
+		test -z "$(git diff-index --name-only HEAD --)" ||
 		VN="$VN-dirty" ;;
 	esac
 then
diff --git a/INSTALL b/INSTALL
index 4a4e13f..2bae53f 100644
--- a/INSTALL
+++ b/INSTALL
@@ -24,23 +24,15 @@
 
 Issues of note:
 
- - git normally installs a helper script wrapper called "git", which
-   conflicts with a similarly named "GNU interactive tools" program.
+ - Ancient versions of GNU Interactive Tools (pre-4.9.2) installed a
+   program "git", whose name conflicts with this program.  But with
+   version 4.9.2, after long hiatus without active maintenance (since
+   around 1997), it changed its name to gnuit and the name conflict is no
+   longer a problem.
 
-   Tough.  Either don't use the wrapper script, or delete the old GNU
-   interactive tools.  None of the core git stuff needs the wrapper,
-   it's just a convenient shorthand and while it is documented in some
-   places, you can always replace "git commit" with "git-commit"
-   instead.
-
-   But let's face it, most of us don't have GNU interactive tools, and
-   even if we had it, we wouldn't know what it does.  I don't think it
-   has been actively developed since 1997, and people have moved over to
-   graphical file managers.
-
-   NOTE: As of gnuit-4.9.2, the GNU interactive tools package has been
-         renamed. You can compile gnuit with the --disable-transition
-         option and then it will not conflict with git.
+   NOTE: When compiled with backward compatibility option, the GNU
+   Interactive Tools package still can install "git", but you can build it
+   with --disable-transition option to avoid this.
 
  - You can use git after building but without installing if you
    wanted to.  Various git commands need to find other git
@@ -81,7 +73,7 @@
 	- "ssh" is used to push and pull over the net
 
 	- "perl" and POSIX-compliant shells are needed to use most of
-	  the barebone Porcelainish scripts.
+	  the bare-bones Porcelainish scripts.
 
  - Some platform specific issues are dealt with Makefile rules,
    but depending on your specific installation, you may not
diff --git a/Makefile b/Makefile
index f13184b..186a8ef 100644
--- a/Makefile
+++ b/Makefile
@@ -170,11 +170,21 @@
 ALL_LDFLAGS = $(LDFLAGS)
 STRIP ?= strip
 
+# Among the variables below, these:
+#   gitexecdir
+#   template_dir
+#   htmldir
+#   ETC_GITCONFIG (but not sysconfdir)
+# can be specified as a relative path ../some/where/else (which must begin
+# with ../); this is interpreted as relative to $(bindir) and "git" at
+# runtime figures out where they are based on the path to the executable.
+# This can help installing the suite in a relocatable way.
+
 prefix = $(HOME)
 bindir = $(prefix)/bin
 mandir = $(prefix)/share/man
 infodir = $(prefix)/share/info
-gitexecdir = $(bindir)
+gitexecdir = $(prefix)/libexec/git-core
 sharedir = $(prefix)/share
 template_dir = $(sharedir)/git-core/templates
 htmldir=$(sharedir)/doc/git-doc
@@ -205,7 +215,7 @@
 GITWEB_SITE_HEADER =
 GITWEB_SITE_FOOTER =
 
-export prefix bindir gitexecdir sharedir template_dir htmldir sysconfdir
+export prefix bindir sharedir htmldir sysconfdir
 
 CC = gcc
 AR = ar
@@ -240,8 +250,6 @@
 SCRIPT_SH += git-merge-octopus.sh
 SCRIPT_SH += git-merge-one-file.sh
 SCRIPT_SH += git-merge-resolve.sh
-SCRIPT_SH += git-merge.sh
-SCRIPT_SH += git-merge-stupid.sh
 SCRIPT_SH += git-mergetool.sh
 SCRIPT_SH += git-parse-remote.sh
 SCRIPT_SH += git-pull.sh
@@ -273,11 +281,9 @@
 
 # ... and all the rest that could be moved out of bindir to gitexecdir
 PROGRAMS += $(EXTRA_PROGRAMS)
-PROGRAMS += git-daemon$X
 PROGRAMS += git-fast-import$X
 PROGRAMS += git-fetch-pack$X
 PROGRAMS += git-hash-object$X
-PROGRAMS += git-imap-send$X
 PROGRAMS += git-index-pack$X
 PROGRAMS += git-merge-index$X
 PROGRAMS += git-merge-tree$X
@@ -287,7 +293,6 @@
 PROGRAMS += git-patch-id$X
 PROGRAMS += git-receive-pack$X
 PROGRAMS += git-send-pack$X
-PROGRAMS += git-shell$X
 PROGRAMS += git-show-index$X
 PROGRAMS += git-unpack-file$X
 PROGRAMS += git-update-server-info$X
@@ -337,6 +342,7 @@
 LIB_H += cache.h
 LIB_H += cache-tree.h
 LIB_H += commit.h
+LIB_H += compat/mingw.h
 LIB_H += csum-file.h
 LIB_H += decorate.h
 LIB_H += delta.h
@@ -352,18 +358,21 @@
 LIB_H += ll-merge.h
 LIB_H += log-tree.h
 LIB_H += mailmap.h
+LIB_H += merge-recursive.h
 LIB_H += object.h
 LIB_H += pack.h
+LIB_H += pack-refs.h
 LIB_H += pack-revindex.h
 LIB_H += parse-options.h
 LIB_H += patch-ids.h
-LIB_H += path-list.h
+LIB_H += string-list.h
 LIB_H += pkt-line.h
 LIB_H += progress.h
 LIB_H += quote.h
 LIB_H += reflog-walk.h
 LIB_H += refs.h
 LIB_H += remote.h
+LIB_H += rerere.h
 LIB_H += revision.h
 LIB_H += run-command.h
 LIB_H += sha1-lookup.h
@@ -377,6 +386,7 @@
 LIB_H += utf8.h
 LIB_H += wt-status.h
 
+LIB_OBJS += abspath.o
 LIB_OBJS += alias.o
 LIB_OBJS += alloc.o
 LIB_OBJS += archive.o
@@ -409,6 +419,7 @@
 LIB_OBJS += diff-lib.o
 LIB_OBJS += diff.o
 LIB_OBJS += dir.o
+LIB_OBJS += editor.o
 LIB_OBJS += entry.o
 LIB_OBJS += environment.o
 LIB_OBJS += exec_cmd.o
@@ -429,13 +440,14 @@
 LIB_OBJS += name-hash.o
 LIB_OBJS += object.o
 LIB_OBJS += pack-check.o
+LIB_OBJS += pack-refs.o
 LIB_OBJS += pack-revindex.o
 LIB_OBJS += pack-write.o
 LIB_OBJS += pager.o
 LIB_OBJS += parse-options.o
 LIB_OBJS += patch-delta.o
 LIB_OBJS += patch-ids.o
-LIB_OBJS += path-list.o
+LIB_OBJS += string-list.o
 LIB_OBJS += path.o
 LIB_OBJS += pkt-line.o
 LIB_OBJS += pretty.o
@@ -446,6 +458,7 @@
 LIB_OBJS += reflog-walk.o
 LIB_OBJS += refs.o
 LIB_OBJS += remote.o
+LIB_OBJS += rerere.o
 LIB_OBJS += revision.o
 LIB_OBJS += run-command.o
 LIB_OBJS += server-info.o
@@ -467,6 +480,7 @@
 LIB_OBJS += usage.o
 LIB_OBJS += utf8.o
 LIB_OBJS += walker.o
+LIB_OBJS += wrapper.o
 LIB_OBJS += write_or_die.o
 LIB_OBJS += ws.o
 LIB_OBJS += wt-status.o
@@ -511,6 +525,7 @@
 BUILTIN_OBJS += builtin-ls-tree.o
 BUILTIN_OBJS += builtin-mailinfo.o
 BUILTIN_OBJS += builtin-mailsplit.o
+BUILTIN_OBJS += builtin-merge.o
 BUILTIN_OBJS += builtin-merge-base.o
 BUILTIN_OBJS += builtin-merge-file.o
 BUILTIN_OBJS += builtin-merge-ours.o
@@ -611,6 +626,8 @@
 	endif
 	NO_STRLCPY = YesPlease
 	NO_MEMMEM = YesPlease
+	COMPAT_CFLAGS += -Icompat/regex
+	COMPAT_OBJS += compat/regex/regex.o
 endif
 ifeq ($(uname_S),SunOS)
 	NEEDS_SOCKET = YesPlease
@@ -620,8 +637,8 @@
 	NO_MEMMEM = YesPlease
 	NO_HSTRERROR = YesPlease
 	NO_MKDTEMP = YesPlease
+	OLD_ICONV = UnfortunatelyYes
 	ifeq ($(uname_R),5.8)
-		NEEDS_LIBICONV = YesPlease
 		NO_UNSETENV = YesPlease
 		NO_SETENV = YesPlease
 		NO_C99_FORMAT = YesPlease
@@ -660,6 +677,8 @@
 	BASIC_CFLAGS += -I/usr/local/include
 	BASIC_LDFLAGS += -L/usr/local/lib
 	DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease
+	COMPAT_CFLAGS += -Icompat/regex
+	COMPAT_OBJS += compat/regex/regex.o
 endif
 ifeq ($(uname_S),OpenBSD)
 	NO_STRCASESTR = YesPlease
@@ -685,6 +704,8 @@
 	INTERNAL_QSORT = UnfortunatelyYes
 	NEEDS_LIBICONV=YesPlease
 	BASIC_CFLAGS += -D_LARGE_FILES
+	COMPAT_CFLAGS += -Icompat/regex
+	COMPAT_OBJS += compat/regex/regex.o
 endif
 ifeq ($(uname_S),GNU)
 	# GNU/Hurd
@@ -712,6 +733,38 @@
 	NO_UNSETENV = YesPlease
 	NO_HSTRERROR = YesPlease
 	NO_SYS_SELECT_H = YesPlease
+	SNPRINTF_RETURNS_BOGUS = YesPlease
+endif
+ifneq (,$(findstring MINGW,$(uname_S)))
+	NO_MMAP = YesPlease
+	NO_PREAD = YesPlease
+	NO_OPENSSL = YesPlease
+	NO_CURL = YesPlease
+	NO_SYMLINK_HEAD = YesPlease
+	NO_IPV6 = YesPlease
+	NO_SETENV = YesPlease
+	NO_UNSETENV = YesPlease
+	NO_STRCASESTR = YesPlease
+	NO_STRLCPY = YesPlease
+	NO_MEMMEM = YesPlease
+	NEEDS_LIBICONV = YesPlease
+	OLD_ICONV = YesPlease
+	NO_C99_FORMAT = YesPlease
+	NO_STRTOUMAX = YesPlease
+	NO_MKDTEMP = YesPlease
+	SNPRINTF_RETURNS_BOGUS = YesPlease
+	NO_SVN_TESTS = YesPlease
+	NO_PERL_MAKEMAKER = YesPlease
+	NO_POSIX_ONLY_PROGRAMS = YesPlease
+	COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/regex -Icompat/fnmatch
+	COMPAT_CFLAGS += -DSNPRINTF_SIZE_CORR=1
+	COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
+	COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/regex/regex.o compat/winansi.o
+	EXTLIBS += -lws2_32
+	X = .exe
+	gitexecdir = ../libexec/git-core
+	template_dir = ../share/git-core/templates/
+	ETC_GITCONFIG = ../etc/gitconfig
 endif
 ifneq (,$(findstring arm,$(uname_M)))
 	ARM_SHA1 = YesPlease
@@ -773,6 +826,11 @@
 endif
 EXTLIBS += -lz
 
+ifndef NO_POSIX_ONLY_PROGRAMS
+	PROGRAMS += git-daemon$X
+	PROGRAMS += git-imap-send$X
+	PROGRAMS += git-shell$X
+endif
 ifndef NO_OPENSSL
 	OPENSSL_LIBSSL = -lssl
 	ifdef OPENSSLDIR
@@ -1009,19 +1067,26 @@
 
 ### Build rules
 
-all:: $(ALL_PROGRAMS) $(BUILT_INS) $(OTHER_PROGRAMS) GIT-BUILD-OPTIONS
+SHELL = $(SHELL_PATH)
+
+all:: shell_compatibility_test $(ALL_PROGRAMS) $(BUILT_INS) $(OTHER_PROGRAMS) GIT-BUILD-OPTIONS
 ifneq (,$X)
-	$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), $(RM) '$p';)
+	$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), test '$p' -ef '$p$X' || $(RM) '$p';)
 endif
 
 all::
 ifndef NO_TCLTK
-	$(QUIET_SUBDIR0)git-gui $(QUIET_SUBDIR1) all
+	$(QUIET_SUBDIR0)git-gui $(QUIET_SUBDIR1) gitexecdir='$(gitexec_instdir_SQ)' all
 	$(QUIET_SUBDIR0)gitk-git $(QUIET_SUBDIR1) all
 endif
 	$(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' all
 	$(QUIET_SUBDIR0)templates $(QUIET_SUBDIR1)
 
+please_set_SHELL_PATH_to_a_more_modern_shell:
+	@$$(:)
+
+shell_compatibility_test: please_set_SHELL_PATH_to_a_more_modern_shell
+
 strip: $(PROGRAMS) git$X
 	$(STRIP) $(STRIP_OPTS) $(PROGRAMS) git$X
 
@@ -1040,7 +1105,10 @@
 		'-DGIT_INFO_PATH="$(infodir_SQ)"' $<
 
 $(BUILT_INS): git$X
-	$(QUIET_BUILT_IN)$(RM) $@ && ln git$X $@
+	$(QUIET_BUILT_IN)$(RM) $@ && \
+	ln git$X $@ 2>/dev/null || \
+	ln -s git$X $@ 2>/dev/null || \
+	cp git$X $@
 
 common-cmds.h: ./generate-cmdlist.sh command-list.txt
 
@@ -1233,7 +1301,7 @@
 
 ### Testing rules
 
-TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-absolute-path$X test-parse-options$X
+TEST_PROGRAMS = test-chmtime$X test-genrandom$X test-date$X test-delta$X test-sha1$X test-match-trees$X test-parse-options$X test-path-utils$X
 
 all:: $(TEST_PROGRAMS)
 
@@ -1261,39 +1329,68 @@
 	./test-sha1.sh
 
 check: common-cmds.h
-	for i in *.c; do sparse $(ALL_CFLAGS) $(SPARSE_FLAGS) $$i || exit; done
+	if sparse; \
+	then \
+		for i in *.c; \
+		do \
+			sparse $(ALL_CFLAGS) $(SPARSE_FLAGS) $$i || exit; \
+		done; \
+	else \
+		echo 2>&1 "Did you mean 'make test'?"; \
+		exit 1; \
+	fi
 
 remove-dashes:
-	./fixup-builtins $(BUILT_INS)
+	./fixup-builtins $(BUILT_INS) $(PROGRAMS) $(SCRIPTS)
 
 ### Installation rules
 
+ifeq ($(firstword $(subst /, ,$(template_dir))),..)
+template_instdir = $(bindir)/$(template_dir)
+else
+template_instdir = $(template_dir)
+endif
+export template_instdir
+
+ifeq ($(firstword $(subst /, ,$(gitexecdir))),..)
+gitexec_instdir = $(bindir)/$(gitexecdir)
+else
+gitexec_instdir = $(gitexecdir)
+endif
+gitexec_instdir_SQ = $(subst ','\'',$(gitexec_instdir))
+export gitexec_instdir
+
 install: all
 	$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'
-	$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(gitexecdir_SQ)'
-	$(INSTALL) $(ALL_PROGRAMS) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
-	$(INSTALL) git$X '$(DESTDIR_SQ)$(bindir_SQ)'
+	$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
+	$(INSTALL) $(ALL_PROGRAMS) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
+	$(INSTALL) git$X git-upload-pack$X git-receive-pack$X git-upload-archive$X git-shell$X git-cvsserver '$(DESTDIR_SQ)$(bindir_SQ)'
 	$(MAKE) -C templates DESTDIR='$(DESTDIR_SQ)' install
 	$(MAKE) -C perl prefix='$(prefix_SQ)' DESTDIR='$(DESTDIR_SQ)' install
 ifndef NO_TCLTK
 	$(MAKE) -C gitk-git install
-	$(MAKE) -C git-gui install
+	$(MAKE) -C git-gui gitexecdir='$(gitexec_instdir_SQ)' install
 endif
-	if test 'z$(bindir_SQ)' != 'z$(gitexecdir_SQ)'; \
-	then \
-		ln -f '$(DESTDIR_SQ)$(bindir_SQ)/git$X' \
-			'$(DESTDIR_SQ)$(gitexecdir_SQ)/git$X' || \
-		cp '$(DESTDIR_SQ)$(bindir_SQ)/git$X' \
-			'$(DESTDIR_SQ)$(gitexecdir_SQ)/git$X'; \
-	fi
-	$(foreach p,$(BUILT_INS), $(RM) '$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' && ln '$(DESTDIR_SQ)$(gitexecdir_SQ)/git$X' '$(DESTDIR_SQ)$(gitexecdir_SQ)/$p' ;)
 ifneq (,$X)
-	$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), $(RM) '$(DESTDIR_SQ)$(gitexecdir_SQ)/$p';)
+	$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), $(RM) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)/$p';)
 endif
+	bindir=$$(cd '$(DESTDIR_SQ)$(bindir_SQ)' && pwd) && \
+	execdir=$$(cd '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' && pwd) && \
+	{ $(RM) "$$execdir/git-add$X" && \
+		ln git-add$X "$$execdir/git-add$X" 2>/dev/null || \
+		cp git-add$X "$$execdir/git-add$X"; } && \
+	{ $(foreach p,$(filter-out git-add$X,$(BUILT_INS)), $(RM) "$$execdir/$p" && \
+		ln "$$execdir/git-add$X" "$$execdir/$p" 2>/dev/null || \
+		ln -s "git-add$X" "$$execdir/$p" 2>/dev/null || \
+		cp "$$execdir/git-add$X" "$$execdir/$p" || exit;) } && \
+	./check_bindir "z$$bindir" "z$$execdir" "$$bindir/git-add$X"
 
 install-doc:
 	$(MAKE) -C Documentation install
 
+install-html:
+	$(MAKE) -C Documentation install-html
+
 install-info:
 	$(MAKE) -C Documentation install-info
 
@@ -1375,6 +1472,7 @@
 	$(RM) GIT-VERSION-FILE GIT-CFLAGS GIT-GUI-VARS GIT-BUILD-OPTIONS
 
 .PHONY: all install clean strip
+.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
 .PHONY: .FORCE-GIT-VERSION-FILE TAGS tags cscope .FORCE-GIT-CFLAGS
 .PHONY: .FORCE-GIT-BUILD-OPTIONS
 
@@ -1385,7 +1483,7 @@
 	do \
 		case "$$v" in \
 		git-merge-octopus | git-merge-ours | git-merge-recursive | \
-		git-merge-resolve | git-merge-stupid | git-merge-subtree | \
+		git-merge-resolve | git-merge-subtree | \
 		git-fsck-objects | git-init-db | \
 		git-?*--?* ) continue ;; \
 		esac ; \
diff --git a/RelNotes b/RelNotes
index 6ca1d5b..009d8f0 120000
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes-1.5.6.6.txt
\ No newline at end of file
+Documentation/RelNotes-1.6.0.6.txt
\ No newline at end of file
diff --git a/abspath.c b/abspath.c
new file mode 100644
index 0000000..0d56124
--- /dev/null
+++ b/abspath.c
@@ -0,0 +1,104 @@
+#include "cache.h"
+
+/* We allow "recursive" symbolic links. Only within reason, though. */
+#define MAXDEPTH 5
+
+const char *make_absolute_path(const char *path)
+{
+	static char bufs[2][PATH_MAX + 1], *buf = bufs[0], *next_buf = bufs[1];
+	char cwd[1024] = "";
+	int buf_index = 1, len;
+
+	int depth = MAXDEPTH;
+	char *last_elem = NULL;
+	struct stat st;
+
+	if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
+		die ("Too long path: %.*s", 60, path);
+
+	while (depth--) {
+		if (stat(buf, &st) || !S_ISDIR(st.st_mode)) {
+			char *last_slash = strrchr(buf, '/');
+			if (last_slash) {
+				*last_slash = '\0';
+				last_elem = xstrdup(last_slash + 1);
+			} else {
+				last_elem = xstrdup(buf);
+				*buf = '\0';
+			}
+		}
+
+		if (*buf) {
+			if (!*cwd && !getcwd(cwd, sizeof(cwd)))
+				die ("Could not get current working directory");
+
+			if (chdir(buf))
+				die ("Could not switch to '%s'", buf);
+		}
+		if (!getcwd(buf, PATH_MAX))
+			die ("Could not get current working directory");
+
+		if (last_elem) {
+			int len = strlen(buf);
+			if (len + strlen(last_elem) + 2 > PATH_MAX)
+				die ("Too long path name: '%s/%s'",
+						buf, last_elem);
+			buf[len] = '/';
+			strcpy(buf + len + 1, last_elem);
+			free(last_elem);
+			last_elem = NULL;
+		}
+
+		if (!lstat(buf, &st) && S_ISLNK(st.st_mode)) {
+			len = readlink(buf, next_buf, PATH_MAX);
+			if (len < 0)
+				die ("Invalid symlink: %s", buf);
+			next_buf[len] = '\0';
+			buf = next_buf;
+			buf_index = 1 - buf_index;
+			next_buf = bufs[buf_index];
+		} else
+			break;
+	}
+
+	if (*cwd && chdir(cwd))
+		die ("Could not change back to '%s'", cwd);
+
+	return buf;
+}
+
+static const char *get_pwd_cwd(void)
+{
+	static char cwd[PATH_MAX + 1];
+	char *pwd;
+	struct stat cwd_stat, pwd_stat;
+	if (getcwd(cwd, PATH_MAX) == NULL)
+		return NULL;
+	pwd = getenv("PWD");
+	if (pwd && strcmp(pwd, cwd)) {
+		stat(cwd, &cwd_stat);
+		if (!stat(pwd, &pwd_stat) &&
+		    pwd_stat.st_dev == cwd_stat.st_dev &&
+		    pwd_stat.st_ino == cwd_stat.st_ino) {
+			strlcpy(cwd, pwd, PATH_MAX);
+		}
+	}
+	return cwd;
+}
+
+const char *make_nonrelative_path(const char *path)
+{
+	static char buf[PATH_MAX + 1];
+
+	if (is_absolute_path(path)) {
+		if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
+			die("Too long path: %.*s", 60, path);
+	} else {
+		const char *cwd = get_pwd_cwd();
+		if (!cwd)
+			die("Cannot determine the current working directory");
+		if (snprintf(buf, PATH_MAX, "%s/%s", cwd, path) >= PATH_MAX)
+			die("Too long path: %.*s", 60, path);
+	}
+	return buf;
+}
diff --git a/alias.c b/alias.c
index 995f3e6..ccb1108 100644
--- a/alias.c
+++ b/alias.c
@@ -21,3 +21,57 @@
 	git_config(alias_lookup_cb, NULL);
 	return alias_val;
 }
+
+int split_cmdline(char *cmdline, const char ***argv)
+{
+	int src, dst, count = 0, size = 16;
+	char quoted = 0;
+
+	*argv = xmalloc(sizeof(char*) * size);
+
+	/* split alias_string */
+	(*argv)[count++] = cmdline;
+	for (src = dst = 0; cmdline[src];) {
+		char c = cmdline[src];
+		if (!quoted && isspace(c)) {
+			cmdline[dst++] = 0;
+			while (cmdline[++src]
+					&& isspace(cmdline[src]))
+				; /* skip */
+			if (count >= size) {
+				size += 16;
+				*argv = xrealloc(*argv, sizeof(char*) * size);
+			}
+			(*argv)[count++] = cmdline + dst;
+		} else if (!quoted && (c == '\'' || c == '"')) {
+			quoted = c;
+			src++;
+		} else if (c == quoted) {
+			quoted = 0;
+			src++;
+		} else {
+			if (c == '\\' && quoted != '\'') {
+				src++;
+				c = cmdline[src];
+				if (!c) {
+					free(*argv);
+					*argv = NULL;
+					return error("cmdline ends with \\");
+				}
+			}
+			cmdline[dst++] = c;
+			src++;
+		}
+	}
+
+	cmdline[dst] = 0;
+
+	if (quoted) {
+		free(*argv);
+		*argv = NULL;
+		return error("unclosed quote");
+	}
+
+	return count;
+}
+
diff --git a/archive-tar.c b/archive-tar.c
index d7598f9..1302961 100644
--- a/archive-tar.c
+++ b/archive-tar.c
@@ -2,9 +2,7 @@
  * Copyright (c) 2005, 2006 Rene Scharfe
  */
 #include "cache.h"
-#include "commit.h"
 #include "tar.h"
-#include "builtin.h"
 #include "archive.h"
 
 #define RECORDSIZE	(512)
@@ -13,11 +11,7 @@
 static char block[BLOCKSIZE];
 static unsigned long offset;
 
-static time_t archive_time;
 static int tar_umask = 002;
-static int verbose;
-static const struct commit *commit;
-static size_t base_len;
 
 /* writes out the whole block, but only if it is full */
 static void write_if_needed(void)
@@ -114,22 +108,24 @@
 	return chksum;
 }
 
-static int get_path_prefix(const struct strbuf *path, int maxlen)
+static size_t get_path_prefix(const char *path, size_t pathlen, size_t maxlen)
 {
-	int i = path->len;
+	size_t i = pathlen;
 	if (i > maxlen)
 		i = maxlen;
 	do {
 		i--;
-	} while (i > 0 && path->buf[i] != '/');
+	} while (i > 0 && path[i] != '/');
 	return i;
 }
 
-static void write_entry(const unsigned char *sha1, struct strbuf *path,
-                        unsigned int mode, void *buffer, unsigned long size)
+static int write_tar_entry(struct archiver_args *args,
+		const unsigned char *sha1, const char *path, size_t pathlen,
+		unsigned int mode, void *buffer, unsigned long size)
 {
 	struct ustar_header header;
 	struct strbuf ext_header;
+	int err = 0;
 
 	memset(&header, 0, sizeof(header));
 	strbuf_init(&ext_header, 0);
@@ -143,8 +139,6 @@
 		mode = 0100666;
 		sprintf(header.name, "%s.paxheader", sha1_to_hex(sha1));
 	} else {
-		if (verbose)
-			fprintf(stderr, "%.*s\n", (int)path->len, path->buf);
 		if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
 			*header.typeflag = TYPEFLAG_DIR;
 			mode = (mode | 0777) & ~tar_umask;
@@ -155,24 +149,24 @@
 			*header.typeflag = TYPEFLAG_REG;
 			mode = (mode | ((mode & 0100) ? 0777 : 0666)) & ~tar_umask;
 		} else {
-			error("unsupported file mode: 0%o (SHA1: %s)",
-			      mode, sha1_to_hex(sha1));
-			return;
+			return error("unsupported file mode: 0%o (SHA1: %s)",
+					mode, sha1_to_hex(sha1));
 		}
-		if (path->len > sizeof(header.name)) {
-			int plen = get_path_prefix(path, sizeof(header.prefix));
-			int rest = path->len - plen - 1;
+		if (pathlen > sizeof(header.name)) {
+			size_t plen = get_path_prefix(path, pathlen,
+					sizeof(header.prefix));
+			size_t rest = pathlen - plen - 1;
 			if (plen > 0 && rest <= sizeof(header.name)) {
-				memcpy(header.prefix, path->buf, plen);
-				memcpy(header.name, path->buf + plen + 1, rest);
+				memcpy(header.prefix, path, plen);
+				memcpy(header.name, path + plen + 1, rest);
 			} else {
 				sprintf(header.name, "%s.data",
 				        sha1_to_hex(sha1));
 				strbuf_append_ext_header(&ext_header, "path",
-				                         path->buf, path->len);
+						path, pathlen);
 			}
 		} else
-			memcpy(header.name, path->buf, path->len);
+			memcpy(header.name, path, pathlen);
 	}
 
 	if (S_ISLNK(mode) && buffer) {
@@ -187,7 +181,7 @@
 
 	sprintf(header.mode, "%07o", mode & 07777);
 	sprintf(header.size, "%011lo", S_ISREG(mode) ? size : 0);
-	sprintf(header.mtime, "%011lo", archive_time);
+	sprintf(header.mtime, "%011lo", args->time);
 
 	sprintf(header.uid, "%07o", 0);
 	sprintf(header.gid, "%07o", 0);
@@ -202,22 +196,30 @@
 	sprintf(header.chksum, "%07o", ustar_header_chksum(&header));
 
 	if (ext_header.len > 0) {
-		write_entry(sha1, NULL, 0, ext_header.buf, ext_header.len);
+		err = write_tar_entry(args, sha1, NULL, 0, 0, ext_header.buf,
+				ext_header.len);
+		if (err)
+			return err;
 	}
 	strbuf_release(&ext_header);
 	write_blocked(&header, sizeof(header));
 	if (S_ISREG(mode) && buffer && size > 0)
 		write_blocked(buffer, size);
+	return err;
 }
 
-static void write_global_extended_header(const unsigned char *sha1)
+static int write_global_extended_header(struct archiver_args *args)
 {
+	const unsigned char *sha1 = args->commit_sha1;
 	struct strbuf ext_header;
+	int err;
 
 	strbuf_init(&ext_header, 0);
 	strbuf_append_ext_header(&ext_header, "comment", sha1_to_hex(sha1), 40);
-	write_entry(NULL, NULL, 0, ext_header.buf, ext_header.len);
+	err = write_tar_entry(args, NULL, NULL, 0, 0, ext_header.buf,
+			ext_header.len);
 	strbuf_release(&ext_header);
+	return err;
 }
 
 static int git_tar_config(const char *var, const char *value, void *cb)
@@ -234,62 +236,17 @@
 	return git_default_config(var, value, cb);
 }
 
-static int write_tar_entry(const unsigned char *sha1,
-                           const char *base, int baselen,
-                           const char *filename, unsigned mode, int stage)
-{
-	static struct strbuf path = STRBUF_INIT;
-	void *buffer;
-	enum object_type type;
-	unsigned long size;
-
-	strbuf_reset(&path);
-	strbuf_grow(&path, PATH_MAX);
-	strbuf_add(&path, base, baselen);
-	strbuf_addstr(&path, filename);
-	if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
-		strbuf_addch(&path, '/');
-		buffer = NULL;
-		size = 0;
-	} else {
-		buffer = sha1_file_to_archive(path.buf + base_len, sha1, mode,
-				&type, &size, commit);
-		if (!buffer)
-			die("cannot read %s", sha1_to_hex(sha1));
-	}
-
-	write_entry(sha1, &path, mode, buffer, size);
-	free(buffer);
-
-	return READ_TREE_RECURSIVE;
-}
-
 int write_tar_archive(struct archiver_args *args)
 {
-	int plen = args->base ? strlen(args->base) : 0;
+	int err = 0;
 
 	git_config(git_tar_config, NULL);
 
-	archive_time = args->time;
-	verbose = args->verbose;
-	commit = args->commit;
-	base_len = args->base ? strlen(args->base) : 0;
-
 	if (args->commit_sha1)
-		write_global_extended_header(args->commit_sha1);
-
-	if (args->base && plen > 0 && args->base[plen - 1] == '/') {
-		char *base = xstrdup(args->base);
-		int baselen = strlen(base);
-
-		while (baselen > 0 && base[baselen - 1] == '/')
-			base[--baselen] = '\0';
-		write_tar_entry(args->tree->object.sha1, "", 0, base, 040777, 0);
-		free(base);
-	}
-	read_tree_recursive(args->tree, args->base, plen, 0,
-			    args->pathspec, write_tar_entry);
-	write_trailer();
-
-	return 0;
+		err = write_global_extended_header(args);
+	if (!err)
+		err = write_archive_entries(args, write_tar_entry);
+	if (!err)
+		write_trailer();
+	return err;
 }
diff --git a/archive-zip.c b/archive-zip.c
index 18c0f87..cf28504 100644
--- a/archive-zip.c
+++ b/archive-zip.c
@@ -2,18 +2,10 @@
  * Copyright (c) 2006 Rene Scharfe
  */
 #include "cache.h"
-#include "commit.h"
-#include "blob.h"
-#include "tree.h"
-#include "quote.h"
-#include "builtin.h"
 #include "archive.h"
 
-static int verbose;
 static int zip_date;
 static int zip_time;
-static const struct commit *commit;
-static size_t base_len;
 
 static unsigned char *zip_dir;
 static unsigned int zip_dir_size;
@@ -96,7 +88,7 @@
 }
 
 static void *zlib_deflate(void *data, unsigned long size,
-                          unsigned long *compressed_size)
+		int compression_level, unsigned long *compressed_size)
 {
 	z_stream stream;
 	unsigned long maxsize;
@@ -104,7 +96,7 @@
 	int result;
 
 	memset(&stream, 0, sizeof(stream));
-	deflateInit(&stream, zlib_compression_level);
+	deflateInit(&stream, compression_level);
 	maxsize = deflateBound(&stream, size);
 	buffer = xmalloc(maxsize);
 
@@ -128,33 +120,9 @@
 	return buffer;
 }
 
-static char *construct_path(const char *base, int baselen,
-                            const char *filename, int isdir, int *pathlen)
-{
-	int filenamelen = strlen(filename);
-	int len = baselen + filenamelen;
-	char *path, *p;
-
-	if (isdir)
-		len++;
-	p = path = xmalloc(len + 1);
-
-	memcpy(p, base, baselen);
-	p += baselen;
-	memcpy(p, filename, filenamelen);
-	p += filenamelen;
-	if (isdir)
-		*p++ = '/';
-	*p = '\0';
-
-	*pathlen = len;
-
-	return path;
-}
-
-static int write_zip_entry(const unsigned char *sha1,
-                           const char *base, int baselen,
-                           const char *filename, unsigned mode, int stage)
+static int write_zip_entry(struct archiver_args *args,
+		const unsigned char *sha1, const char *path, size_t pathlen,
+		unsigned int mode, void *buffer, unsigned long size)
 {
 	struct zip_local_header header;
 	struct zip_dir_header dirent;
@@ -163,31 +131,20 @@
 	unsigned long uncompressed_size;
 	unsigned long crc;
 	unsigned long direntsize;
-	unsigned long size;
 	int method;
-	int result = -1;
-	int pathlen;
 	unsigned char *out;
-	char *path;
-	enum object_type type;
-	void *buffer = NULL;
 	void *deflated = NULL;
 
 	crc = crc32(0, NULL, 0);
 
-	path = construct_path(base, baselen, filename, S_ISDIR(mode), &pathlen);
-	if (verbose)
-		fprintf(stderr, "%s\n", path);
 	if (pathlen > 0xffff) {
-		error("path too long (%d chars, SHA1: %s): %s", pathlen,
-		      sha1_to_hex(sha1), path);
-		goto out;
+		return error("path too long (%d chars, SHA1: %s): %s",
+				(int)pathlen, sha1_to_hex(sha1), path);
 	}
 
 	if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
 		method = 0;
 		attr2 = 16;
-		result = (S_ISDIR(mode) ? READ_TREE_RECURSIVE : 0);
 		out = NULL;
 		uncompressed_size = 0;
 		compressed_size = 0;
@@ -195,25 +152,20 @@
 		method = 0;
 		attr2 = S_ISLNK(mode) ? ((mode | 0777) << 16) :
 			(mode & 0111) ? ((mode) << 16) : 0;
-		if (S_ISREG(mode) && zlib_compression_level != 0)
+		if (S_ISREG(mode) && args->compression_level != 0)
 			method = 8;
-		result = 0;
-		buffer = sha1_file_to_archive(path + base_len, sha1, mode,
-				&type, &size, commit);
-		if (!buffer)
-			die("cannot read %s", sha1_to_hex(sha1));
 		crc = crc32(crc, buffer, size);
 		out = buffer;
 		uncompressed_size = size;
 		compressed_size = size;
 	} else {
-		error("unsupported file mode: 0%o (SHA1: %s)", mode,
-		      sha1_to_hex(sha1));
-		goto out;
+		return error("unsupported file mode: 0%o (SHA1: %s)", mode,
+				sha1_to_hex(sha1));
 	}
 
 	if (method == 8) {
-		deflated = zlib_deflate(buffer, size, &compressed_size);
+		deflated = zlib_deflate(buffer, size, args->compression_level,
+				&compressed_size);
 		if (deflated && compressed_size - 6 < size) {
 			/* ZLIB --> raw compressed data (see RFC 1950) */
 			/* CMF and FLG ... */
@@ -276,12 +228,9 @@
 		zip_offset += compressed_size;
 	}
 
-out:
-	free(buffer);
 	free(deflated);
-	free(path);
 
-	return result;
+	return 0;
 }
 
 static void write_zip_trailer(const unsigned char *sha1)
@@ -314,43 +263,18 @@
 
 int write_zip_archive(struct archiver_args *args)
 {
-	int plen = strlen(args->base);
+	int err;
 
 	dos_time(&args->time, &zip_date, &zip_time);
 
 	zip_dir = xmalloc(ZIP_DIRECTORY_MIN_SIZE);
 	zip_dir_size = ZIP_DIRECTORY_MIN_SIZE;
-	verbose = args->verbose;
-	commit = args->commit;
-	base_len = args->base ? strlen(args->base) : 0;
 
-	if (args->base && plen > 0 && args->base[plen - 1] == '/') {
-		char *base = xstrdup(args->base);
-		int baselen = strlen(base);
-
-		while (baselen > 0 && base[baselen - 1] == '/')
-			base[--baselen] = '\0';
-		write_zip_entry(args->tree->object.sha1, "", 0, base, 040777, 0);
-		free(base);
-	}
-	read_tree_recursive(args->tree, args->base, plen, 0,
-			    args->pathspec, write_zip_entry);
-	write_zip_trailer(args->commit_sha1);
+	err = write_archive_entries(args, write_zip_entry);
+	if (!err)
+		write_zip_trailer(args->commit_sha1);
 
 	free(zip_dir);
 
-	return 0;
-}
-
-void *parse_extra_zip_args(int argc, const char **argv)
-{
-	for (; argc > 0; argc--, argv++) {
-		const char *arg = argv[0];
-
-		if (arg[0] == '-' && isdigit(arg[1]) && arg[2] == '\0')
-			zlib_compression_level = arg[1] - '0';
-		else
-			die("Unknown argument for zip format: %s", arg);
-	}
-	return NULL;
+	return err;
 }
diff --git a/archive.c b/archive.c
index 7a32c19..45d242b 100644
--- a/archive.c
+++ b/archive.c
@@ -1,6 +1,28 @@
 #include "cache.h"
 #include "commit.h"
+#include "tree-walk.h"
 #include "attr.h"
+#include "archive.h"
+#include "parse-options.h"
+
+static char const * const archive_usage[] = {
+	"git archive [options] <tree-ish> [path...]",
+	"git archive --list",
+	"git archive --remote <repo> [--exec <cmd>] [options] <tree-ish> [path...]",
+	"git archive --remote <repo> [--exec <cmd>] --list",
+	NULL
+};
+
+#define USES_ZLIB_COMPRESSION 1
+
+const struct archiver {
+	const char *name;
+	write_archive_fn_t write_archive;
+	unsigned int flags;
+} archivers[] = {
+	{ "tar", write_tar_archive },
+	{ "zip", write_zip_archive, USES_ZLIB_COMPRESSION },
+};
 
 static void format_subst(const struct commit *commit,
                          const char *src, size_t len,
@@ -26,7 +48,7 @@
 		strbuf_add(&fmt, b + 8, c - b - 8);
 
 		strbuf_add(buf, src, b - src);
-		format_commit_message(commit, fmt.buf, buf);
+		format_commit_message(commit, fmt.buf, buf, DATE_NORMAL);
 		len -= c + 1 - src;
 		src  = c + 1;
 	}
@@ -35,34 +57,9 @@
 	free(to_free);
 }
 
-static int convert_to_archive(const char *path,
-                              const void *src, size_t len,
-                              struct strbuf *buf,
-                              const struct commit *commit)
-{
-	static struct git_attr *attr_export_subst;
-	struct git_attr_check check[1];
-
-	if (!commit)
-		return 0;
-
-	if (!attr_export_subst)
-		attr_export_subst = git_attr("export-subst", 12);
-
-	check[0].attr = attr_export_subst;
-	if (git_checkattr(path, ARRAY_SIZE(check), check))
-		return 0;
-	if (!ATTR_TRUE(check[0].value))
-		return 0;
-
-	format_subst(commit, src, len, buf);
-	return 1;
-}
-
-void *sha1_file_to_archive(const char *path, const unsigned char *sha1,
-                           unsigned int mode, enum object_type *type,
-                           unsigned long *sizep,
-                           const struct commit *commit)
+static void *sha1_file_to_archive(const char *path, const unsigned char *sha1,
+		unsigned int mode, enum object_type *type,
+		unsigned long *sizep, const struct commit *commit)
 {
 	void *buffer;
 
@@ -74,7 +71,8 @@
 		strbuf_init(&buf, 0);
 		strbuf_attach(&buf, buffer, *sizep, *sizep + 1);
 		convert_to_working_tree(path, buf.buf, buf.len, &buf);
-		convert_to_archive(path, buf.buf, buf.len, &buf, commit);
+		if (commit)
+			format_subst(commit, buf.buf, buf.len, &buf);
 		buffer = strbuf_detach(&buf, &size);
 		*sizep = size;
 	}
@@ -82,3 +80,265 @@
 	return buffer;
 }
 
+static void setup_archive_check(struct git_attr_check *check)
+{
+	static struct git_attr *attr_export_ignore;
+	static struct git_attr *attr_export_subst;
+
+	if (!attr_export_ignore) {
+		attr_export_ignore = git_attr("export-ignore", 13);
+		attr_export_subst = git_attr("export-subst", 12);
+	}
+	check[0].attr = attr_export_ignore;
+	check[1].attr = attr_export_subst;
+}
+
+struct archiver_context {
+	struct archiver_args *args;
+	write_archive_entry_fn_t write_entry;
+};
+
+static int write_archive_entry(const unsigned char *sha1, const char *base,
+		int baselen, const char *filename, unsigned mode, int stage,
+		void *context)
+{
+	static struct strbuf path = STRBUF_INIT;
+	struct archiver_context *c = context;
+	struct archiver_args *args = c->args;
+	write_archive_entry_fn_t write_entry = c->write_entry;
+	struct git_attr_check check[2];
+	const char *path_without_prefix;
+	int convert = 0;
+	int err;
+	enum object_type type;
+	unsigned long size;
+	void *buffer;
+
+	strbuf_reset(&path);
+	strbuf_grow(&path, PATH_MAX);
+	strbuf_add(&path, base, baselen);
+	strbuf_addstr(&path, filename);
+	path_without_prefix = path.buf + args->baselen;
+
+	setup_archive_check(check);
+	if (!git_checkattr(path_without_prefix, ARRAY_SIZE(check), check)) {
+		if (ATTR_TRUE(check[0].value))
+			return 0;
+		convert = ATTR_TRUE(check[1].value);
+	}
+
+	if (S_ISDIR(mode) || S_ISGITLINK(mode)) {
+		strbuf_addch(&path, '/');
+		if (args->verbose)
+			fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
+		err = write_entry(args, sha1, path.buf, path.len, mode, NULL, 0);
+		if (err)
+			return err;
+		return READ_TREE_RECURSIVE;
+	}
+
+	buffer = sha1_file_to_archive(path_without_prefix, sha1, mode,
+			&type, &size, convert ? args->commit : NULL);
+	if (!buffer)
+		return error("cannot read %s", sha1_to_hex(sha1));
+	if (args->verbose)
+		fprintf(stderr, "%.*s\n", (int)path.len, path.buf);
+	err = write_entry(args, sha1, path.buf, path.len, mode, buffer, size);
+	free(buffer);
+	return err;
+}
+
+int write_archive_entries(struct archiver_args *args,
+		write_archive_entry_fn_t write_entry)
+{
+	struct archiver_context context;
+	int err;
+
+	if (args->baselen > 0 && args->base[args->baselen - 1] == '/') {
+		size_t len = args->baselen;
+
+		while (len > 1 && args->base[len - 2] == '/')
+			len--;
+		if (args->verbose)
+			fprintf(stderr, "%.*s\n", (int)len, args->base);
+		err = write_entry(args, args->tree->object.sha1, args->base,
+				len, 040777, NULL, 0);
+		if (err)
+			return err;
+	}
+
+	context.args = args;
+	context.write_entry = write_entry;
+
+	err =  read_tree_recursive(args->tree, args->base, args->baselen, 0,
+			args->pathspec, write_archive_entry, &context);
+	if (err == READ_TREE_RECURSIVE)
+		err = 0;
+	return err;
+}
+
+static const struct archiver *lookup_archiver(const char *name)
+{
+	int i;
+
+	if (!name)
+		return NULL;
+
+	for (i = 0; i < ARRAY_SIZE(archivers); i++) {
+		if (!strcmp(name, archivers[i].name))
+			return &archivers[i];
+	}
+	return NULL;
+}
+
+static void parse_pathspec_arg(const char **pathspec,
+		struct archiver_args *ar_args)
+{
+	ar_args->pathspec = get_pathspec(ar_args->base, pathspec);
+}
+
+static void parse_treeish_arg(const char **argv,
+		struct archiver_args *ar_args, const char *prefix)
+{
+	const char *name = argv[0];
+	const unsigned char *commit_sha1;
+	time_t archive_time;
+	struct tree *tree;
+	const struct commit *commit;
+	unsigned char sha1[20];
+
+	if (get_sha1(name, sha1))
+		die("Not a valid object name");
+
+	commit = lookup_commit_reference_gently(sha1, 1);
+	if (commit) {
+		commit_sha1 = commit->object.sha1;
+		archive_time = commit->date;
+	} else {
+		commit_sha1 = NULL;
+		archive_time = time(NULL);
+	}
+
+	tree = parse_tree_indirect(sha1);
+	if (tree == NULL)
+		die("not a tree object");
+
+	if (prefix) {
+		unsigned char tree_sha1[20];
+		unsigned int mode;
+		int err;
+
+		err = get_tree_entry(tree->object.sha1, prefix,
+				     tree_sha1, &mode);
+		if (err || !S_ISDIR(mode))
+			die("current working directory is untracked");
+
+		tree = parse_tree_indirect(tree_sha1);
+	}
+	ar_args->tree = tree;
+	ar_args->commit_sha1 = commit_sha1;
+	ar_args->commit = commit;
+	ar_args->time = archive_time;
+}
+
+#define OPT__COMPR(s, v, h, p) \
+	{ OPTION_SET_INT, (s), NULL, (v), NULL, (h), \
+	  PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, (p) }
+#define OPT__COMPR_HIDDEN(s, v, p) \
+	{ OPTION_SET_INT, (s), NULL, (v), NULL, "", \
+	  PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_HIDDEN, NULL, (p) }
+
+static int parse_archive_args(int argc, const char **argv,
+		const struct archiver **ar, struct archiver_args *args)
+{
+	const char *format = "tar";
+	const char *base = NULL;
+	const char *remote = NULL;
+	const char *exec = NULL;
+	int compression_level = -1;
+	int verbose = 0;
+	int i;
+	int list = 0;
+	struct option opts[] = {
+		OPT_GROUP(""),
+		OPT_STRING(0, "format", &format, "fmt", "archive format"),
+		OPT_STRING(0, "prefix", &base, "prefix",
+			"prepend prefix to each pathname in the archive"),
+		OPT__VERBOSE(&verbose),
+		OPT__COMPR('0', &compression_level, "store only", 0),
+		OPT__COMPR('1', &compression_level, "compress faster", 1),
+		OPT__COMPR_HIDDEN('2', &compression_level, 2),
+		OPT__COMPR_HIDDEN('3', &compression_level, 3),
+		OPT__COMPR_HIDDEN('4', &compression_level, 4),
+		OPT__COMPR_HIDDEN('5', &compression_level, 5),
+		OPT__COMPR_HIDDEN('6', &compression_level, 6),
+		OPT__COMPR_HIDDEN('7', &compression_level, 7),
+		OPT__COMPR_HIDDEN('8', &compression_level, 8),
+		OPT__COMPR('9', &compression_level, "compress better", 9),
+		OPT_GROUP(""),
+		OPT_BOOLEAN('l', "list", &list,
+			"list supported archive formats"),
+		OPT_GROUP(""),
+		OPT_STRING(0, "remote", &remote, "repo",
+			"retrieve the archive from remote repository <repo>"),
+		OPT_STRING(0, "exec", &exec, "cmd",
+			"path to the remote git-upload-archive command"),
+		OPT_END()
+	};
+
+	argc = parse_options(argc, argv, opts, archive_usage, 0);
+
+	if (remote)
+		die("Unexpected option --remote");
+	if (exec)
+		die("Option --exec can only be used together with --remote");
+
+	if (!base)
+		base = "";
+
+	if (list) {
+		for (i = 0; i < ARRAY_SIZE(archivers); i++)
+			printf("%s\n", archivers[i].name);
+		exit(0);
+	}
+
+	/* We need at least one parameter -- tree-ish */
+	if (argc < 1)
+		usage_with_options(archive_usage, opts);
+	*ar = lookup_archiver(format);
+	if (!*ar)
+		die("Unknown archive format '%s'", format);
+
+	args->compression_level = Z_DEFAULT_COMPRESSION;
+	if (compression_level != -1) {
+		if ((*ar)->flags & USES_ZLIB_COMPRESSION)
+			args->compression_level = compression_level;
+		else {
+			die("Argument not supported for format '%s': -%d",
+					format, compression_level);
+		}
+	}
+	args->verbose = verbose;
+	args->base = base;
+	args->baselen = strlen(base);
+
+	return argc;
+}
+
+int write_archive(int argc, const char **argv, const char *prefix,
+		int setup_prefix)
+{
+	const struct archiver *ar = NULL;
+	struct archiver_args args;
+
+	argc = parse_archive_args(argc, argv, &ar, &args);
+	if (setup_prefix && prefix == NULL)
+		prefix = setup_git_directory();
+
+	parse_treeish_arg(argv, &args, prefix);
+	parse_pathspec_arg(argv + 1, &args);
+
+	git_config(git_default_config, NULL);
+
+	return ar->write_archive(&args);
+}
diff --git a/archive.h b/archive.h
index 5791e65..0b15b35 100644
--- a/archive.h
+++ b/archive.h
@@ -1,48 +1,29 @@
 #ifndef ARCHIVE_H
 #define ARCHIVE_H
 
-#define MAX_EXTRA_ARGS	32
-#define MAX_ARGS	(MAX_EXTRA_ARGS + 32)
-
 struct archiver_args {
 	const char *base;
+	size_t baselen;
 	struct tree *tree;
 	const unsigned char *commit_sha1;
 	const struct commit *commit;
 	time_t time;
 	const char **pathspec;
 	unsigned int verbose : 1;
-	void *extra;
+	int compression_level;
 };
 
 typedef int (*write_archive_fn_t)(struct archiver_args *);
 
-typedef void *(*parse_extra_args_fn_t)(int argc, const char **argv);
+typedef int (*write_archive_entry_fn_t)(struct archiver_args *args, const unsigned char *sha1, const char *path, size_t pathlen, unsigned int mode, void *buffer, unsigned long size);
 
-struct archiver {
-	const char *name;
-	struct archiver_args args;
-	write_archive_fn_t write_archive;
-	parse_extra_args_fn_t parse_extra;
-};
-
-extern int parse_archive_args(int argc,
-			      const char **argv,
-			      struct archiver *ar);
-
-extern void parse_treeish_arg(const char **treeish,
-			      struct archiver_args *ar_args,
-			      const char *prefix);
-
-extern void parse_pathspec_arg(const char **pathspec,
-			       struct archiver_args *args);
 /*
  * Archive-format specific backends.
  */
 extern int write_tar_archive(struct archiver_args *);
 extern int write_zip_archive(struct archiver_args *);
-extern void *parse_extra_zip_args(int argc, const char **argv);
 
-extern void *sha1_file_to_archive(const char *path, const unsigned char *sha1, unsigned int mode, enum object_type *type, unsigned long *size, const struct commit *commit);
+extern int write_archive_entries(struct archiver_args *args, write_archive_entry_fn_t write_entry);
+extern int write_archive(int argc, const char **argv, const char *prefix, int setup_prefix);
 
 #endif	/* ARCHIVE_H */
diff --git a/branch.c b/branch.c
index 56e9492..6a75057 100644
--- a/branch.c
+++ b/branch.c
@@ -129,7 +129,9 @@
 			die("Cannot setup tracking information; starting point is not a branch.");
 		break;
 	case 1:
-		/* Unique completion -- good */
+		/* Unique completion -- good, only if it is a real ref */
+		if (track == BRANCH_TRACK_EXPLICIT && !strcmp(real_ref, "HEAD"))
+			die("Cannot setup tracking information; starting point is not a branch.");
 		break;
 	default:
 		die("Ambiguous object name: '%s'.", start_name);
@@ -166,7 +168,7 @@
 void remove_branch_state(void)
 {
 	unlink(git_path("MERGE_HEAD"));
-	unlink(git_path("rr-cache/MERGE_RR"));
+	unlink(git_path("MERGE_RR"));
 	unlink(git_path("MERGE_MSG"));
 	unlink(git_path("SQUASH_MSG"));
 }
diff --git a/builtin-add.c b/builtin-add.c
index 9930cf5..fc3f96e 100644
--- a/builtin-add.c
+++ b/builtin-add.c
@@ -16,7 +16,7 @@
 #include "parse-options.h"
 
 static const char * const builtin_add_usage[] = {
-	"git-add [options] [--] <filepattern>...",
+	"git add [options] [--] <filepattern>...",
 	NULL
 };
 static int patch_interactive = 0, add_interactive = 0;
@@ -140,9 +140,8 @@
 	for (specs = 0; pathspec[specs];  specs++)
 		/* nothing */;
 	seen = xcalloc(specs, 1);
-	if (read_cache() < 0)
-		die("index file corrupt");
-	refresh_index(&the_index, verbose ? 0 : REFRESH_QUIET, pathspec, seen);
+	refresh_index(&the_index, verbose ? REFRESH_SAY_CHANGED : REFRESH_QUIET,
+		      pathspec, seen);
 	for (i = 0; i < specs; i++) {
 		if (!seen[i])
 			die("pathspec '%s' did not match any files", pathspec[i]);
@@ -192,7 +191,7 @@
 "The following paths are ignored by one of your .gitignore files:\n";
 
 static int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0;
-static int ignore_add_errors;
+static int ignore_add_errors, addremove;
 
 static struct option builtin_add_options[] = {
 	OPT__DRY_RUN(&show_only),
@@ -202,6 +201,7 @@
 	OPT_BOOLEAN('p', "patch", &patch_interactive, "interactive patching"),
 	OPT_BOOLEAN('f', "force", &ignored_too, "allow adding otherwise ignored files"),
 	OPT_BOOLEAN('u', "update", &take_worktree_changes, "update tracked files"),
+	OPT_BOOLEAN('A', "all", &addremove, "add all, noticing removal of tracked files"),
 	OPT_BOOLEAN( 0 , "refresh", &refresh_only, "don't add, only refresh the index"),
 	OPT_BOOLEAN( 0 , "ignore-errors", &ignore_add_errors, "just skip files which cannot be added because of errors"),
 	OPT_END(),
@@ -216,13 +216,36 @@
 	return git_default_config(var, value, cb);
 }
 
+static int add_files(struct dir_struct *dir, int flags)
+{
+	int i, exit_status = 0;
+
+	if (dir->ignored_nr) {
+		fprintf(stderr, ignore_error);
+		for (i = 0; i < dir->ignored_nr; i++)
+			fprintf(stderr, "%s\n", dir->ignored[i]->name);
+		fprintf(stderr, "Use -f if you really want to add them.\n");
+		die("no files added");
+	}
+
+	for (i = 0; i < dir->nr; i++)
+		if (add_file_to_cache(dir->entries[i]->name, flags)) {
+			if (!ignore_add_errors)
+				die("adding files failed");
+			exit_status = 1;
+		}
+	return exit_status;
+}
+
 int cmd_add(int argc, const char **argv, const char *prefix)
 {
 	int exit_status = 0;
-	int i, newfd;
+	int newfd;
 	const char **pathspec;
 	struct dir_struct dir;
 	int flags;
+	int add_new_files;
+	int require_pathspec;
 
 	argc = parse_options(argc, argv, builtin_add_options,
 			  builtin_add_usage, 0);
@@ -233,53 +256,51 @@
 
 	git_config(add_config, NULL);
 
+	if (addremove && take_worktree_changes)
+		die("-A and -u are mutually incompatible");
+	if (addremove && !argc) {
+		static const char *here[2] = { ".", NULL };
+		argc = 1;
+		argv = here;
+	}
+
+	add_new_files = !take_worktree_changes && !refresh_only;
+	require_pathspec = !take_worktree_changes;
+
 	newfd = hold_locked_index(&lock_file, 1);
 
 	flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |
 		 (show_only ? ADD_CACHE_PRETEND : 0) |
 		 (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0));
 
-	if (take_worktree_changes) {
-		const char **pathspec;
-		if (read_cache() < 0)
-			die("index file corrupt");
-		pathspec = get_pathspec(prefix, argv);
-		exit_status = add_files_to_cache(prefix, pathspec, flags);
-		goto finish;
-	}
-
-	if (argc == 0) {
+	if (require_pathspec && argc == 0) {
 		fprintf(stderr, "Nothing specified, nothing added.\n");
 		fprintf(stderr, "Maybe you wanted to say 'git add .'?\n");
 		return 0;
 	}
 	pathspec = get_pathspec(prefix, argv);
 
+	/*
+	 * If we are adding new files, we need to scan the working
+	 * tree to find the ones that match pathspecs; this needs
+	 * to be done before we read the index.
+	 */
+	if (add_new_files)
+		fill_directory(&dir, pathspec, ignored_too);
+
+	if (read_cache() < 0)
+		die("index file corrupt");
+
 	if (refresh_only) {
 		refresh(verbose, pathspec);
 		goto finish;
 	}
 
-	fill_directory(&dir, pathspec, ignored_too);
+	if (take_worktree_changes || addremove)
+		exit_status |= add_files_to_cache(prefix, pathspec, flags);
 
-	if (read_cache() < 0)
-		die("index file corrupt");
-
-	if (dir.ignored_nr) {
-		fprintf(stderr, ignore_error);
-		for (i = 0; i < dir.ignored_nr; i++) {
-			fprintf(stderr, "%s\n", dir.ignored[i]->name);
-		}
-		fprintf(stderr, "Use -f if you really want to add them.\n");
-		die("no files added");
-	}
-
-	for (i = 0; i < dir.nr; i++)
-		if (add_file_to_cache(dir.entries[i]->name, flags)) {
-			if (!ignore_add_errors)
-				die("adding files failed");
-			exit_status = 1;
-		}
+	if (add_new_files)
+		exit_status |= add_files(&dir, flags);
 
  finish:
 	if (active_cache_changed) {
diff --git a/builtin-apply.c b/builtin-apply.c
index c497889..50b623e 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -12,6 +12,8 @@
 #include "blob.h"
 #include "delta.h"
 #include "builtin.h"
+#include "string-list.h"
+#include "dir.h"
 
 /*
  *  --check turns on checking that the working tree matches the
@@ -45,7 +47,7 @@
 static int line_termination = '\n';
 static unsigned long p_context = ULONG_MAX;
 static const char apply_usage[] =
-"git-apply [--stat] [--numstat] [--summary] [--check] [--index] [--cached] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [--reverse] [--reject] [--verbose] [-z] [-pNUM] [-CNUM] [--whitespace=<nowarn|warn|fix|error|error-all>] <patch>...";
+"git apply [--stat] [--numstat] [--summary] [--check] [--index] [--cached] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [--reverse] [--reject] [--verbose] [-z] [-pNUM] [-CNUM] [--whitespace=<nowarn|warn|fix|error|error-all>] <patch>...";
 
 static enum ws_error_action {
 	nowarn_ws_error,
@@ -57,6 +59,8 @@
 static int squelch_whitespace_errors = 5;
 static int applied_after_fixing_ws;
 static const char *patch_input_file;
+static const char *root;
+static int root_len;
 
 static void parse_whitespace_option(const char *option)
 {
@@ -153,6 +157,7 @@
 	unsigned int is_binary:1;
 	unsigned int is_copy:1;
 	unsigned int is_rename:1;
+	unsigned int recount:1;
 	struct fragment *fragments;
 	char *result;
 	size_t resultsize;
@@ -185,6 +190,13 @@
 	struct line *line;
 };
 
+/*
+ * Records filenames that have been touched, in order to handle
+ * the case where more than one patches touch the same file.
+ */
+
+static struct string_list fn_table;
+
 static uint32_t hash_line(const char *cp, size_t len)
 {
 	size_t i;
@@ -263,7 +275,7 @@
 static void read_patch_file(struct strbuf *sb, int fd)
 {
 	if (strbuf_read(sb, fd, 0) < 0)
-		die("git-apply: read returned %s", strerror(errno));
+		die("git apply: read returned %s", strerror(errno));
 
 	/*
 	 * Make sure that we have some slop in the buffer
@@ -331,6 +343,8 @@
 				 */
 				strbuf_remove(&name, 0, cp - name.buf);
 				free(def);
+				if (root)
+					strbuf_insert(&name, 0, root, root_len);
 				return strbuf_detach(&name, NULL);
 			}
 		}
@@ -369,6 +383,14 @@
 		free(def);
 	}
 
+	if (root) {
+		char *ret = xmalloc(root_len + len + 1);
+		strcpy(ret, root);
+		memcpy(ret + root_len, start, len);
+		ret[root_len + len] = '\0';
+		return ret;
+	}
+
 	return xmemdupz(start, len);
 }
 
@@ -485,17 +507,17 @@
 		name = orig_name;
 		len = strlen(name);
 		if (isnull)
-			die("git-apply: bad git-diff - expected /dev/null, got %s on line %d", name, linenr);
+			die("git apply: bad git-diff - expected /dev/null, got %s on line %d", name, linenr);
 		another = find_name(line, NULL, p_value, TERM_TAB);
 		if (!another || memcmp(another, name, len))
-			die("git-apply: bad git-diff - inconsistent %s filename on line %d", oldnew, linenr);
+			die("git apply: bad git-diff - inconsistent %s filename on line %d", oldnew, linenr);
 		free(another);
 		return orig_name;
 	}
 	else {
 		/* expect "/dev/null" */
 		if (memcmp("/dev/null", line, 9) || line[9] != '\n')
-			die("git-apply: bad git-diff - expected /dev/null on line %d", linenr);
+			die("git apply: bad git-diff - expected /dev/null on line %d", linenr);
 		return NULL;
 	}
 }
@@ -788,6 +810,13 @@
 	 * the default name from the header.
 	 */
 	patch->def_name = git_header_name(line, len);
+	if (patch->def_name && root) {
+		char *s = xmalloc(root_len + strlen(patch->def_name) + 1);
+		strcpy(s, root);
+		strcpy(s + root_len, patch->def_name);
+		free(patch->def_name);
+		patch->def_name = s;
+	}
 
 	line += len;
 	size -= len;
@@ -882,6 +911,56 @@
 	return offset + ex;
 }
 
+static void recount_diff(char *line, int size, struct fragment *fragment)
+{
+	int oldlines = 0, newlines = 0, ret = 0;
+
+	if (size < 1) {
+		warning("recount: ignore empty hunk");
+		return;
+	}
+
+	for (;;) {
+		int len = linelen(line, size);
+		size -= len;
+		line += len;
+
+		if (size < 1)
+			break;
+
+		switch (*line) {
+		case ' ': case '\n':
+			newlines++;
+			/* fall through */
+		case '-':
+			oldlines++;
+			continue;
+		case '+':
+			newlines++;
+			continue;
+		case '\\':
+			continue;
+		case '@':
+			ret = size < 3 || prefixcmp(line, "@@ ");
+			break;
+		case 'd':
+			ret = size < 5 || prefixcmp(line, "diff ");
+			break;
+		default:
+			ret = -1;
+			break;
+		}
+		if (ret) {
+			warning("recount: unexpected line: %.*s",
+				(int)linelen(line, size), line);
+			return;
+		}
+		break;
+	}
+	fragment->oldlines = oldlines;
+	fragment->newlines = newlines;
+}
+
 /*
  * Parse a unified diff fragment header of the
  * form "@@ -a,b +c,d @@"
@@ -979,8 +1058,7 @@
 static void check_whitespace(const char *line, int len, unsigned ws_rule)
 {
 	char *err;
-	unsigned result = check_and_emit_line(line + 1, len - 1, ws_rule,
-	    NULL, NULL, NULL, NULL);
+	unsigned result = ws_check(line + 1, len - 1, ws_rule);
 	if (!result)
 		return;
 
@@ -991,7 +1069,7 @@
 	else {
 		err = whitespace_error_string(result);
 		fprintf(stderr, "%s:%d: %s.\n%.*s\n",
-		     patch_input_file, linenr, err, len - 2, line + 1);
+			patch_input_file, linenr, err, len - 2, line + 1);
 		free(err);
 	}
 }
@@ -1013,6 +1091,8 @@
 	offset = parse_fragment_header(line, len, fragment);
 	if (offset < 0)
 		return -1;
+	if (offset > 0 && patch->recount)
+		recount_diff(line + offset, size - offset, fragment);
 	oldlines = fragment->oldlines;
 	newlines = fragment->newlines;
 	leading = 0;
@@ -1624,7 +1704,7 @@
 		fixlen = ws_fix_copy(buf, orig, oldlen, ws_rule, NULL);
 
 		/* Try fixing the line in the target */
-		if (sizeof(tgtfixbuf) < tgtlen)
+		if (sizeof(tgtfixbuf) > tgtlen)
 			tgtfix = tgtfixbuf;
 		else
 			tgtfix = xmalloc(tgtlen);
@@ -1924,6 +2004,8 @@
 	/*
 	 * A hunk to change lines at the beginning would begin with
 	 * @@ -1,L +N,M @@
+	 * but we need to be careful.  -U0 that inserts before the second
+	 * line also has this pattern.
 	 *
 	 * And a hunk to add to an empty file would begin with
 	 * @@ -0,0 +N,M @@
@@ -1931,7 +2013,8 @@
 	 * In other words, a hunk that is (frag->oldpos <= 1) with or
 	 * without leading context must match at the beginning.
 	 */
-	match_beginning = frag->oldpos <= 1;
+	match_beginning = (!frag->oldpos ||
+			   (frag->oldpos == 1 && !unidiff_zero));
 
 	/*
 	 * A hunk without trailing lines must match at the end.
@@ -2176,15 +2259,63 @@
 	return 0;
 }
 
+static struct patch *in_fn_table(const char *name)
+{
+	struct string_list_item *item;
+
+	if (name == NULL)
+		return NULL;
+
+	item = string_list_lookup(name, &fn_table);
+	if (item != NULL)
+		return (struct patch *)item->util;
+
+	return NULL;
+}
+
+static void add_to_fn_table(struct patch *patch)
+{
+	struct string_list_item *item;
+
+	/*
+	 * Always add new_name unless patch is a deletion
+	 * This should cover the cases for normal diffs,
+	 * file creations and copies
+	 */
+	if (patch->new_name != NULL) {
+		item = string_list_insert(patch->new_name, &fn_table);
+		item->util = patch;
+	}
+
+	/*
+	 * store a failure on rename/deletion cases because
+	 * later chunks shouldn't patch old names
+	 */
+	if ((patch->new_name == NULL) || (patch->is_rename)) {
+		item = string_list_insert(patch->old_name, &fn_table);
+		item->util = (struct patch *) -1;
+	}
+}
+
 static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *ce)
 {
 	struct strbuf buf;
 	struct image image;
 	size_t len;
 	char *img;
+	struct patch *tpatch;
 
 	strbuf_init(&buf, 0);
-	if (cached) {
+
+	if (!(patch->is_copy || patch->is_rename) &&
+	    ((tpatch = in_fn_table(patch->old_name)) != NULL)) {
+		if (tpatch == (struct patch *) -1) {
+			return error("patch %s has been renamed/deleted",
+				patch->old_name);
+		}
+		/* We have a patched copy in memory use that */
+		strbuf_add(&buf, tpatch->result, tpatch->resultsize);
+	} else if (cached) {
 		if (read_file_or_gitlink(ce, &buf))
 			return error("read of %s failed", patch->old_name);
 	} else if (patch->old_name) {
@@ -2211,6 +2342,7 @@
 		return -1; /* note with --reject this succeeds. */
 	patch->result = image.buf;
 	patch->resultsize = image.len;
+	add_to_fn_table(patch);
 	free(image.line_allocated);
 
 	if (0 < patch->is_delete && patch->resultsize)
@@ -2255,6 +2387,7 @@
 static int check_preimage(struct patch *patch, struct cache_entry **ce, struct stat *st)
 {
 	const char *old_name = patch->old_name;
+	struct patch *tpatch = NULL;
 	int stat_ret = 0;
 	unsigned st_mode = 0;
 
@@ -2268,12 +2401,20 @@
 		return 0;
 
 	assert(patch->is_new <= 0);
-	if (!cached) {
+
+	if (!(patch->is_copy || patch->is_rename) &&
+	    (tpatch = in_fn_table(old_name)) != NULL) {
+		if (tpatch == (struct patch *) -1) {
+			return error("%s: has been deleted/renamed", old_name);
+		}
+		st_mode = tpatch->new_mode;
+	} else if (!cached) {
 		stat_ret = lstat(old_name, st);
 		if (stat_ret && errno != ENOENT)
 			return error("%s: %s", old_name, strerror(errno));
 	}
-	if (check_index) {
+
+	if (check_index && !tpatch) {
 		int pos = cache_name_pos(old_name, strlen(old_name));
 		if (pos < 0) {
 			if (patch->is_new < 0)
@@ -2325,7 +2466,7 @@
 	return 0;
 }
 
-static int check_patch(struct patch *patch, struct patch *prev_patch)
+static int check_patch(struct patch *patch)
 {
 	struct stat st;
 	const char *old_name = patch->old_name;
@@ -2342,8 +2483,7 @@
 		return status;
 	old_name = patch->old_name;
 
-	if (new_name && prev_patch && 0 < prev_patch->is_delete &&
-	    !strcmp(prev_patch->old_name, new_name))
+	if (in_fn_table(new_name) == (struct patch *) -1)
 		/*
 		 * A type-change diff is always split into a patch to
 		 * delete old, immediately followed by a patch to
@@ -2393,15 +2533,14 @@
 
 static int check_patch_list(struct patch *patch)
 {
-	struct patch *prev_patch = NULL;
 	int err = 0;
 
-	for (prev_patch = NULL; patch ; patch = patch->next) {
+	while (patch) {
 		if (apply_verbosely)
 			say_patch_name(stderr,
 				       "Checking patch ", patch, "...\n");
-		err |= check_patch(patch, prev_patch);
-		prev_patch = patch;
+		err |= check_patch(patch);
+		patch = patch->next;
 	}
 	return err;
 }
@@ -2454,6 +2593,8 @@
 			sha1_ptr = sha1;
 
 		ce = make_cache_entry(patch->old_mode, sha1_ptr, name, 0, 0);
+		if (!ce)
+			die("make_cache_entry failed for path '%s'", name);
 		if (add_index_entry(&result, ce, ADD_CACHE_OK_TO_ADD))
 			die ("Could not add %s to temporary index", name);
 	}
@@ -2604,15 +2745,7 @@
 				warning("unable to remove submodule %s",
 					patch->old_name);
 		} else if (!unlink(patch->old_name) && rmdir_empty) {
-			char *name = xstrdup(patch->old_name);
-			char *end = strrchr(name, '/');
-			while (end) {
-				*end = 0;
-				if (rmdir(name))
-					break;
-				end = strrchr(name, '/');
-			}
-			free(name);
+			remove_path(patch->old_name);
 		}
 	}
 }
@@ -2717,8 +2850,8 @@
 		unsigned int nr = getpid();
 
 		for (;;) {
-			const char *newpath;
-			newpath = mkpath("%s~%u", path, nr);
+			char newpath[PATH_MAX];
+			mksnpath(newpath, sizeof(newpath), "%s~%u", path, nr);
 			if (!try_create_file(newpath, mode, buf, size)) {
 				if (!rename(newpath, path))
 					return;
@@ -2912,13 +3045,18 @@
 	}
 }
 
-static int apply_patch(int fd, const char *filename, int inaccurate_eof)
+#define INACCURATE_EOF	(1<<0)
+#define RECOUNT		(1<<1)
+
+static int apply_patch(int fd, const char *filename, int options)
 {
 	size_t offset;
 	struct strbuf buf;
 	struct patch *list = NULL, **listp = &list;
 	int skipped_patch = 0;
 
+	/* FIXME - memory leak when using multiple patch files as inputs */
+	memset(&fn_table, 0, sizeof(struct string_list));
 	strbuf_init(&buf, 0);
 	patch_input_file = filename;
 	read_patch_file(&buf, fd);
@@ -2928,7 +3066,8 @@
 		int nr;
 
 		patch = xcalloc(1, sizeof(*patch));
-		patch->inaccurate_eof = inaccurate_eof;
+		patch->inaccurate_eof = !!(options & INACCURATE_EOF);
+		patch->recount =  !!(options & RECOUNT);
 		nr = parse_chunk(buf.buf + offset, buf.len - offset, patch);
 		if (nr < 0)
 			break;
@@ -2997,7 +3136,7 @@
 {
 	int i;
 	int read_stdin = 1;
-	int inaccurate_eof = 0;
+	int options = 0;
 	int errs = 0;
 	int is_not_gitdir;
 
@@ -3015,7 +3154,7 @@
 		int fd;
 
 		if (!strcmp(arg, "-")) {
-			errs |= apply_patch(0, "<stdin>", inaccurate_eof);
+			errs |= apply_patch(0, "<stdin>", options);
 			read_stdin = 0;
 			continue;
 		}
@@ -3115,7 +3254,23 @@
 			continue;
 		}
 		if (!strcmp(arg, "--inaccurate-eof")) {
-			inaccurate_eof = 1;
+			options |= INACCURATE_EOF;
+			continue;
+		}
+		if (!strcmp(arg, "--recount")) {
+			options |= RECOUNT;
+			continue;
+		}
+		if (!prefixcmp(arg, "--directory=")) {
+			arg += strlen("--directory=");
+			root_len = strlen(arg);
+			if (root_len && arg[root_len - 1] != '/') {
+				char *new_root;
+				root = new_root = xmalloc(root_len + 2);
+				strcpy(new_root, arg);
+				strcpy(new_root + root_len++, "/");
+			} else
+				root = arg;
 			continue;
 		}
 		if (0 < prefix_length)
@@ -3126,12 +3281,12 @@
 			die("can't open patch '%s': %s", arg, strerror(errno));
 		read_stdin = 0;
 		set_default_whitespace_mode(whitespace_option);
-		errs |= apply_patch(fd, arg, inaccurate_eof);
+		errs |= apply_patch(fd, arg, options);
 		close(fd);
 	}
 	set_default_whitespace_mode(whitespace_option);
 	if (read_stdin)
-		errs |= apply_patch(0, "<stdin>", inaccurate_eof);
+		errs |= apply_patch(0, "<stdin>", options);
 	if (whitespace_error) {
 		if (squelch_whitespace_errors &&
 		    squelch_whitespace_errors < whitespace_error) {
diff --git a/builtin-archive.c b/builtin-archive.c
index c2e0c1e..5ceec43 100644
--- a/builtin-archive.c
+++ b/builtin-archive.c
@@ -5,25 +5,8 @@
 #include "cache.h"
 #include "builtin.h"
 #include "archive.h"
-#include "commit.h"
-#include "tree-walk.h"
-#include "exec_cmd.h"
 #include "pkt-line.h"
 #include "sideband.h"
-#include "attr.h"
-
-static const char archive_usage[] = \
-"git-archive --format=<fmt> [--prefix=<prefix>/] [--verbose] [<extra>] <tree-ish> [path...]";
-
-static struct archiver_desc
-{
-	const char *name;
-	write_archive_fn_t write_archive;
-	parse_extra_args_fn_t parse_extra;
-} archivers[] = {
-	{ "tar", write_tar_archive, NULL },
-	{ "zip", write_zip_archive, parse_extra_zip_args },
-};
 
 static int run_remote_archiver(const char *remote, int argc,
 			       const char **argv)
@@ -32,7 +15,7 @@
 	int fd[2], i, len, rv;
 	struct child_process *conn;
 	const char *exec = "git-upload-archive";
-	int exec_at = 0;
+	int exec_at = 0, exec_value_at = 0;
 
 	for (i = 1; i < argc; i++) {
 		const char *arg = argv[i];
@@ -41,7 +24,14 @@
 				die("multiple --exec specified");
 			exec = arg + 7;
 			exec_at = i;
-			break;
+		} else if (!strcmp(arg, "--exec")) {
+			if (exec_at)
+				die("multiple --exec specified");
+			if (i + 1 >= argc)
+				die("option --exec requires a value");
+			exec = argv[i + 1];
+			exec_at = i;
+			exec_value_at = ++i;
 		}
 	}
 
@@ -49,7 +39,7 @@
 	conn = git_connect(fd, url, exec, 0);
 
 	for (i = 1; i < argc; i++) {
-		if (i == exec_at)
+		if (i == exec_at || i == exec_value_at)
 			continue;
 		packet_write(fd[1], "argument %s\n", argv[i]);
 	}
@@ -57,18 +47,18 @@
 
 	len = packet_read_line(fd[0], buf, sizeof(buf));
 	if (!len)
-		die("git-archive: expected ACK/NAK, got EOF");
+		die("git archive: expected ACK/NAK, got EOF");
 	if (buf[len-1] == '\n')
 		buf[--len] = 0;
 	if (strcmp(buf, "ACK")) {
 		if (len > 5 && !prefixcmp(buf, "NACK "))
-			die("git-archive: NACK %s", buf + 5);
-		die("git-archive: protocol error");
+			die("git archive: NACK %s", buf + 5);
+		die("git archive: protocol error");
 	}
 
 	len = packet_read_line(fd[0], buf, sizeof(buf));
 	if (len)
-		die("git-archive: expected a flush");
+		die("git archive: expected a flush");
 
 	/* Now, start reading from fd[0] and spit it out to stdout */
 	rv = recv_sideband("archive", fd[0], 1, 2);
@@ -79,132 +69,6 @@
 	return !!rv;
 }
 
-static int init_archiver(const char *name, struct archiver *ar)
-{
-	int rv = -1, i;
-
-	for (i = 0; i < ARRAY_SIZE(archivers); i++) {
-		if (!strcmp(name, archivers[i].name)) {
-			memset(ar, 0, sizeof(*ar));
-			ar->name = archivers[i].name;
-			ar->write_archive = archivers[i].write_archive;
-			ar->parse_extra = archivers[i].parse_extra;
-			rv = 0;
-			break;
-		}
-	}
-	return rv;
-}
-
-void parse_pathspec_arg(const char **pathspec, struct archiver_args *ar_args)
-{
-	ar_args->pathspec = get_pathspec(ar_args->base, pathspec);
-}
-
-void parse_treeish_arg(const char **argv, struct archiver_args *ar_args,
-		       const char *prefix)
-{
-	const char *name = argv[0];
-	const unsigned char *commit_sha1;
-	time_t archive_time;
-	struct tree *tree;
-	const struct commit *commit;
-	unsigned char sha1[20];
-
-	if (get_sha1(name, sha1))
-		die("Not a valid object name");
-
-	commit = lookup_commit_reference_gently(sha1, 1);
-	if (commit) {
-		commit_sha1 = commit->object.sha1;
-		archive_time = commit->date;
-	} else {
-		commit_sha1 = NULL;
-		archive_time = time(NULL);
-	}
-
-	tree = parse_tree_indirect(sha1);
-	if (tree == NULL)
-		die("not a tree object");
-
-	if (prefix) {
-		unsigned char tree_sha1[20];
-		unsigned int mode;
-		int err;
-
-		err = get_tree_entry(tree->object.sha1, prefix,
-				     tree_sha1, &mode);
-		if (err || !S_ISDIR(mode))
-			die("current working directory is untracked");
-
-		tree = parse_tree_indirect(tree_sha1);
-	}
-	ar_args->tree = tree;
-	ar_args->commit_sha1 = commit_sha1;
-	ar_args->commit = commit;
-	ar_args->time = archive_time;
-}
-
-int parse_archive_args(int argc, const char **argv, struct archiver *ar)
-{
-	const char *extra_argv[MAX_EXTRA_ARGS];
-	int extra_argc = 0;
-	const char *format = "tar";
-	const char *base = "";
-	int verbose = 0;
-	int i;
-
-	for (i = 1; i < argc; i++) {
-		const char *arg = argv[i];
-
-		if (!strcmp(arg, "--list") || !strcmp(arg, "-l")) {
-			for (i = 0; i < ARRAY_SIZE(archivers); i++)
-				printf("%s\n", archivers[i].name);
-			exit(0);
-		}
-		if (!strcmp(arg, "--verbose") || !strcmp(arg, "-v")) {
-			verbose = 1;
-			continue;
-		}
-		if (!prefixcmp(arg, "--format=")) {
-			format = arg + 9;
-			continue;
-		}
-		if (!prefixcmp(arg, "--prefix=")) {
-			base = arg + 9;
-			continue;
-		}
-		if (!strcmp(arg, "--")) {
-			i++;
-			break;
-		}
-		if (arg[0] == '-') {
-			if (extra_argc > MAX_EXTRA_ARGS - 1)
-				die("Too many extra options");
-			extra_argv[extra_argc++] = arg;
-			continue;
-		}
-		break;
-	}
-
-	/* We need at least one parameter -- tree-ish */
-	if (argc - 1 < i)
-		usage(archive_usage);
-	if (init_archiver(format, ar) < 0)
-		die("Unknown archive format '%s'", format);
-
-	if (extra_argc) {
-		if (!ar->parse_extra)
-			die("'%s' format does not handle %s",
-			    ar->name, extra_argv[0]);
-		ar->args.extra = ar->parse_extra(extra_argc, extra_argv);
-	}
-	ar->args.verbose = verbose;
-	ar->args.base = base;
-
-	return i;
-}
-
 static const char *extract_remote_arg(int *ac, const char **av)
 {
 	int ix, iy, cnt = *ac;
@@ -221,6 +85,13 @@
 					die("Multiple --remote specified");
 				remote = arg + 9;
 				continue;
+			} else if (!strcmp(arg, "--remote")) {
+				if (remote)
+					die("Multiple --remote specified");
+				if (++ix >= cnt)
+					die("option --remote requires a value");
+				remote = av[ix];
+				continue;
 			}
 			if (arg[0] != '-')
 				no_more_options = 1;
@@ -238,8 +109,6 @@
 
 int cmd_archive(int argc, const char **argv, const char *prefix)
 {
-	struct archiver ar;
-	int tree_idx;
 	const char *remote = NULL;
 
 	remote = extract_remote_arg(&argc, argv);
@@ -248,14 +117,5 @@
 
 	setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
 
-	memset(&ar, 0, sizeof(ar));
-	tree_idx = parse_archive_args(argc, argv, &ar);
-	if (prefix == NULL)
-		prefix = setup_git_directory();
-
-	argv += tree_idx;
-	parse_treeish_arg(argv, &ar.args, prefix);
-	parse_pathspec_arg(argv + 1, &ar.args);
-
-	return ar.write_archive(&ar.args);
+	return write_archive(argc, argv, prefix, 1);
 }
diff --git a/builtin-blame.c b/builtin-blame.c
index b451f6c..101c416 100644
--- a/builtin-blame.c
+++ b/builtin-blame.c
@@ -16,26 +16,18 @@
 #include "quote.h"
 #include "xdiff-interface.h"
 #include "cache-tree.h"
-#include "path-list.h"
+#include "string-list.h"
 #include "mailmap.h"
+#include "parse-options.h"
 
-static char blame_usage[] =
-"git-blame [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-p] [-w] [-L n,m] [-S <revs-file>] [-M] [-C] [-C] [--contents <filename>] [--incremental] [commit] [--] file\n"
-"  -c                  Use the same output mode as git-annotate (Default: off)\n"
-"  -b                  Show blank SHA-1 for boundary commits (Default: off)\n"
-"  -l                  Show long commit SHA1 (Default: off)\n"
-"  --root              Do not treat root commits as boundaries (Default: off)\n"
-"  -t                  Show raw timestamp (Default: off)\n"
-"  -f, --show-name     Show original filename (Default: auto)\n"
-"  -n, --show-number   Show original linenumber (Default: off)\n"
-"  -s                  Suppress author name and timestamp (Default: off)\n"
-"  -p, --porcelain     Show in a format designed for machine consumption\n"
-"  -w                  Ignore whitespace differences\n"
-"  -L n,m              Process only line range n,m, counting from 1\n"
-"  -M, -C              Find line movements within and across files\n"
-"  --incremental       Show blame entries as we find them, incrementally\n"
-"  --contents file     Use <file>'s contents as the final image\n"
-"  -S revs-file        Use revisions from revs-file instead of calling git-rev-list\n";
+static char blame_usage[] = "git blame [options] [rev-opts] [rev] [--] file";
+
+static const char *blame_opt_usage[] = {
+	blame_usage,
+	"",
+	"[rev-opts] are documented in git-rev-list(1)",
+	NULL
+};
 
 static int longest_file;
 static int longest_author;
@@ -43,11 +35,11 @@
 static int max_digits;
 static int max_score_digits;
 static int show_root;
+static int reverse;
 static int blank_boundary;
 static int incremental;
-static int cmd_is_annotate;
 static int xdl_opts = XDF_NEED_MINIMAL;
-static struct path_list mailmap;
+static struct string_list mailmap;
 
 #ifndef DEBUG
 #define DEBUG 0
@@ -91,7 +83,7 @@
  * Given an origin, prepare mmfile_t structure to be used by the
  * diff machinery
  */
-static char *fill_origin_blob(struct origin *o, mmfile_t *file)
+static void fill_origin_blob(struct origin *o, mmfile_t *file)
 {
 	if (!o->file.ptr) {
 		enum object_type type;
@@ -106,7 +98,6 @@
 	}
 	else
 		*file = o->file;
-	return file->ptr;
 }
 
 /*
@@ -161,6 +152,10 @@
 	 */
 	char guilty;
 
+	/* true if the entry has been scanned for copies in the current parent
+	 */
+	char scanned;
+
 	/* the line number of the first line of this group in the
 	 * suspect's file; internally all line numbers are 0 based.
 	 */
@@ -178,7 +173,7 @@
 struct scoreboard {
 	/* the final commit (i.e. where we started digging from) */
 	struct commit *final;
-
+	struct rev_info *revs;
 	const char *path;
 
 	/*
@@ -1016,7 +1011,8 @@
 	while (made_progress) {
 		made_progress = 0;
 		for (e = sb->ent; e; e = e->next) {
-			if (e->guilty || !same_suspect(e->suspect, target))
+			if (e->guilty || !same_suspect(e->suspect, target) ||
+			    ent_score(sb, e) < blame_move_score)
 				continue;
 			find_copy_in_blob(sb, e, parent, split, &file_p);
 			if (split[1].suspect &&
@@ -1041,6 +1037,7 @@
  */
 static struct blame_list *setup_blame_list(struct scoreboard *sb,
 					   struct origin *target,
+					   int min_score,
 					   int *num_ents_p)
 {
 	struct blame_entry *e;
@@ -1048,12 +1045,16 @@
 	struct blame_list *blame_list = NULL;
 
 	for (e = sb->ent, num_ents = 0; e; e = e->next)
-		if (!e->guilty && same_suspect(e->suspect, target))
+		if (!e->scanned && !e->guilty &&
+		    same_suspect(e->suspect, target) &&
+		    min_score < ent_score(sb, e))
 			num_ents++;
 	if (num_ents) {
 		blame_list = xcalloc(num_ents, sizeof(struct blame_list));
 		for (e = sb->ent, i = 0; e; e = e->next)
-			if (!e->guilty && same_suspect(e->suspect, target))
+			if (!e->scanned && !e->guilty &&
+			    same_suspect(e->suspect, target) &&
+			    min_score < ent_score(sb, e))
 				blame_list[i++].ent = e;
 	}
 	*num_ents_p = num_ents;
@@ -1061,6 +1062,16 @@
 }
 
 /*
+ * Reset the scanned status on all entries.
+ */
+static void reset_scanned_flag(struct scoreboard *sb)
+{
+	struct blame_entry *e;
+	for (e = sb->ent; e; e = e->next)
+		e->scanned = 0;
+}
+
+/*
  * For lines target is suspected for, see if we can find code movement
  * across file boundary from the parent commit.  porigin is the path
  * in the parent we already tried.
@@ -1078,7 +1089,7 @@
 	struct blame_list *blame_list;
 	int num_ents;
 
-	blame_list = setup_blame_list(sb, target, &num_ents);
+	blame_list = setup_blame_list(sb, target, blame_copy_score, &num_ents);
 	if (!blame_list)
 		return 1; /* nothing remains for this target */
 
@@ -1125,6 +1136,8 @@
 
 			if (!DIFF_FILE_VALID(p->one))
 				continue; /* does not exist in parent */
+			if (S_ISGITLINK(p->one->mode))
+				continue; /* ignore git links */
 			if (porigin && !strcmp(p->one->path, porigin->path))
 				/* find_move already dealt with this path */
 				continue;
@@ -1152,18 +1165,21 @@
 				split_blame(sb, split, blame_list[j].ent);
 				made_progress = 1;
 			}
+			else
+				blame_list[j].ent->scanned = 1;
 			decref_split(split);
 		}
 		free(blame_list);
 
 		if (!made_progress)
 			break;
-		blame_list = setup_blame_list(sb, target, &num_ents);
+		blame_list = setup_blame_list(sb, target, blame_copy_score, &num_ents);
 		if (!blame_list) {
 			retval = 1;
 			break;
 		}
 	}
+	reset_scanned_flag(sb);
 	diff_flush(&diff_opts);
 	diff_tree_release_paths(&diff_opts);
 	return retval;
@@ -1192,18 +1208,48 @@
 	}
 }
 
-#define MAXPARENT 16
+/*
+ * We pass blame from the current commit to its parents.  We keep saying
+ * "parent" (and "porigin"), but what we mean is to find scapegoat to
+ * exonerate ourselves.
+ */
+static struct commit_list *first_scapegoat(struct rev_info *revs, struct commit *commit)
+{
+	if (!reverse)
+		return commit->parents;
+	return lookup_decoration(&revs->children, &commit->object);
+}
+
+static int num_scapegoats(struct rev_info *revs, struct commit *commit)
+{
+	int cnt;
+	struct commit_list *l = first_scapegoat(revs, commit);
+	for (cnt = 0; l; l = l->next)
+		cnt++;
+	return cnt;
+}
+
+#define MAXSG 16
 
 static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
 {
-	int i, pass;
+	struct rev_info *revs = sb->revs;
+	int i, pass, num_sg;
 	struct commit *commit = origin->commit;
-	struct commit_list *parent;
-	struct origin *parent_origin[MAXPARENT], *porigin;
+	struct commit_list *sg;
+	struct origin *sg_buf[MAXSG];
+	struct origin *porigin, **sg_origin = sg_buf;
 
-	memset(parent_origin, 0, sizeof(parent_origin));
+	num_sg = num_scapegoats(revs, commit);
+	if (!num_sg)
+		goto finish;
+	else if (num_sg < ARRAY_SIZE(sg_buf))
+		memset(sg_buf, 0, sizeof(sg_buf));
+	else
+		sg_origin = xcalloc(num_sg, sizeof(*sg_origin));
 
-	/* The first pass looks for unrenamed path to optimize for
+	/*
+	 * The first pass looks for unrenamed path to optimize for
 	 * common cases, then we look for renames in the second pass.
 	 */
 	for (pass = 0; pass < 2; pass++) {
@@ -1211,13 +1257,13 @@
 				       struct commit *, struct origin *);
 		find = pass ? find_rename : find_origin;
 
-		for (i = 0, parent = commit->parents;
-		     i < MAXPARENT && parent;
-		     parent = parent->next, i++) {
-			struct commit *p = parent->item;
+		for (i = 0, sg = first_scapegoat(revs, commit);
+		     i < num_sg && sg;
+		     sg = sg->next, i++) {
+			struct commit *p = sg->item;
 			int j, same;
 
-			if (parent_origin[i])
+			if (sg_origin[i])
 				continue;
 			if (parse_commit(p))
 				continue;
@@ -1230,24 +1276,24 @@
 				goto finish;
 			}
 			for (j = same = 0; j < i; j++)
-				if (parent_origin[j] &&
-				    !hashcmp(parent_origin[j]->blob_sha1,
+				if (sg_origin[j] &&
+				    !hashcmp(sg_origin[j]->blob_sha1,
 					     porigin->blob_sha1)) {
 					same = 1;
 					break;
 				}
 			if (!same)
-				parent_origin[i] = porigin;
+				sg_origin[i] = porigin;
 			else
 				origin_decref(porigin);
 		}
 	}
 
 	num_commits++;
-	for (i = 0, parent = commit->parents;
-	     i < MAXPARENT && parent;
-	     parent = parent->next, i++) {
-		struct origin *porigin = parent_origin[i];
+	for (i = 0, sg = first_scapegoat(revs, commit);
+	     i < num_sg && sg;
+	     sg = sg->next, i++) {
+		struct origin *porigin = sg_origin[i];
 		if (!porigin)
 			continue;
 		if (pass_blame_to_parent(sb, origin, porigin))
@@ -1258,10 +1304,10 @@
 	 * Optionally find moves in parents' files.
 	 */
 	if (opt & PICKAXE_BLAME_MOVE)
-		for (i = 0, parent = commit->parents;
-		     i < MAXPARENT && parent;
-		     parent = parent->next, i++) {
-			struct origin *porigin = parent_origin[i];
+		for (i = 0, sg = first_scapegoat(revs, commit);
+		     i < num_sg && sg;
+		     sg = sg->next, i++) {
+			struct origin *porigin = sg_origin[i];
 			if (!porigin)
 				continue;
 			if (find_move_in_parent(sb, origin, porigin))
@@ -1272,23 +1318,25 @@
 	 * Optionally find copies from parents' files.
 	 */
 	if (opt & PICKAXE_BLAME_COPY)
-		for (i = 0, parent = commit->parents;
-		     i < MAXPARENT && parent;
-		     parent = parent->next, i++) {
-			struct origin *porigin = parent_origin[i];
-			if (find_copy_in_parent(sb, origin, parent->item,
+		for (i = 0, sg = first_scapegoat(revs, commit);
+		     i < num_sg && sg;
+		     sg = sg->next, i++) {
+			struct origin *porigin = sg_origin[i];
+			if (find_copy_in_parent(sb, origin, sg->item,
 						porigin, opt))
 				goto finish;
 		}
 
  finish:
-	for (i = 0; i < MAXPARENT; i++) {
-		if (parent_origin[i]) {
-			drop_origin_blob(parent_origin[i]);
-			origin_decref(parent_origin[i]);
+	for (i = 0; i < num_sg; i++) {
+		if (sg_origin[i]) {
+			drop_origin_blob(sg_origin[i]);
+			origin_decref(sg_origin[i]);
 		}
 	}
 	drop_origin_blob(origin);
+	if (sg_buf != sg_origin)
+		free(sg_origin);
 }
 
 /*
@@ -1487,8 +1535,10 @@
  * is still unknown, pick one blame_entry, and allow its current
  * suspect to pass blames to its parents.
  */
-static void assign_blame(struct scoreboard *sb, struct rev_info *revs, int opt)
+static void assign_blame(struct scoreboard *sb, int opt)
 {
+	struct rev_info *revs = sb->revs;
+
 	while (1) {
 		struct blame_entry *ent;
 		struct commit *commit;
@@ -1509,8 +1559,9 @@
 		commit = suspect->commit;
 		if (!commit->object.parsed)
 			parse_commit(commit);
-		if (!(commit->object.flags & UNINTERESTING) &&
-		    !(revs->max_age != -1 && commit->date < revs->max_age))
+		if (reverse ||
+		    (!(commit->object.flags & UNINTERESTING) &&
+		     !(revs->max_age != -1 && commit->date < revs->max_age)))
 			pass_blame(sb, suspect, opt);
 		else {
 			commit->object.flags |= UNINTERESTING;
@@ -1636,7 +1687,7 @@
 		if (suspect->commit->object.flags & UNINTERESTING) {
 			if (blank_boundary)
 				memset(hex, ' ', length);
-			else if (!cmd_is_annotate) {
+			else if (!(opt & OUTPUT_ANNOTATE_COMPAT)) {
 				length--;
 				putchar('^');
 			}
@@ -1741,7 +1792,7 @@
 
 /*
  * Add phony grafts for use with -S; this is primarily to
- * support git-cvsserver that wants to give a linear history
+ * support git's cvsserver that wants to give a linear history
  * to its clients.
  */
 static int read_ancestry(const char *graft_file)
@@ -1876,7 +1927,7 @@
  * Used for the command line parsing; check if the path exists
  * in the working tree.
  */
-static int has_path_in_work_tree(const char *path)
+static int has_string_in_work_tree(const char *path)
 {
 	struct stat st;
 	return !lstat(path, &st);
@@ -2006,6 +2057,10 @@
 	return git_default_config(var, value, cb);
 }
 
+/*
+ * Prepare a dummy commit that represents the work tree (or staged) item.
+ * Note that annotating work tree item never works in the reverse.
+ */
 static struct commit *fake_working_tree_commit(const char *path, const char *contents_from)
 {
 	struct commit *commit;
@@ -2122,6 +2177,108 @@
 	return commit;
 }
 
+static const char *prepare_final(struct scoreboard *sb)
+{
+	int i;
+	const char *final_commit_name = NULL;
+	struct rev_info *revs = sb->revs;
+
+	/*
+	 * There must be one and only one positive commit in the
+	 * revs->pending array.
+	 */
+	for (i = 0; i < revs->pending.nr; i++) {
+		struct object *obj = revs->pending.objects[i].item;
+		if (obj->flags & UNINTERESTING)
+			continue;
+		while (obj->type == OBJ_TAG)
+			obj = deref_tag(obj, NULL, 0);
+		if (obj->type != OBJ_COMMIT)
+			die("Non commit %s?", revs->pending.objects[i].name);
+		if (sb->final)
+			die("More than one commit to dig from %s and %s?",
+			    revs->pending.objects[i].name,
+			    final_commit_name);
+		sb->final = (struct commit *) obj;
+		final_commit_name = revs->pending.objects[i].name;
+	}
+	return final_commit_name;
+}
+
+static const char *prepare_initial(struct scoreboard *sb)
+{
+	int i;
+	const char *final_commit_name = NULL;
+	struct rev_info *revs = sb->revs;
+
+	/*
+	 * There must be one and only one negative commit, and it must be
+	 * the boundary.
+	 */
+	for (i = 0; i < revs->pending.nr; i++) {
+		struct object *obj = revs->pending.objects[i].item;
+		if (!(obj->flags & UNINTERESTING))
+			continue;
+		while (obj->type == OBJ_TAG)
+			obj = deref_tag(obj, NULL, 0);
+		if (obj->type != OBJ_COMMIT)
+			die("Non commit %s?", revs->pending.objects[i].name);
+		if (sb->final)
+			die("More than one commit to dig down to %s and %s?",
+			    revs->pending.objects[i].name,
+			    final_commit_name);
+		sb->final = (struct commit *) obj;
+		final_commit_name = revs->pending.objects[i].name;
+	}
+	if (!final_commit_name)
+		die("No commit to dig down to?");
+	return final_commit_name;
+}
+
+static int blame_copy_callback(const struct option *option, const char *arg, int unset)
+{
+	int *opt = option->value;
+
+	/*
+	 * -C enables copy from removed files;
+	 * -C -C enables copy from existing files, but only
+	 *       when blaming a new file;
+	 * -C -C -C enables copy from existing files for
+	 *          everybody
+	 */
+	if (*opt & PICKAXE_BLAME_COPY_HARDER)
+		*opt |= PICKAXE_BLAME_COPY_HARDEST;
+	if (*opt & PICKAXE_BLAME_COPY)
+		*opt |= PICKAXE_BLAME_COPY_HARDER;
+	*opt |= PICKAXE_BLAME_COPY | PICKAXE_BLAME_MOVE;
+
+	if (arg)
+		blame_copy_score = parse_score(arg);
+	return 0;
+}
+
+static int blame_move_callback(const struct option *option, const char *arg, int unset)
+{
+	int *opt = option->value;
+
+	*opt |= PICKAXE_BLAME_MOVE;
+
+	if (arg)
+		blame_move_score = parse_score(arg);
+	return 0;
+}
+
+static int blame_bottomtop_callback(const struct option *option, const char *arg, int unset)
+{
+	const char **bottomtop = option->value;
+	if (!arg)
+		return -1;
+	if (*bottomtop)
+		die("More than one '-L n,m' option given");
+	*bottomtop = arg;
+	return 0;
+}
+
 int cmd_blame(int argc, const char **argv, const char *prefix)
 {
 	struct rev_info revs;
@@ -2129,102 +2286,72 @@
 	struct scoreboard sb;
 	struct origin *o;
 	struct blame_entry *ent;
-	int i, seen_dashdash, unk, opt;
-	long bottom, top, lno;
-	int output_option = 0;
-	int show_stats = 0;
-	const char *revs_file = NULL;
+	long dashdash_pos, bottom, top, lno;
 	const char *final_commit_name = NULL;
 	enum object_type type;
-	const char *bottomtop = NULL;
-	const char *contents_from = NULL;
 
-	cmd_is_annotate = !strcmp(argv[0], "annotate");
+	static const char *bottomtop = NULL;
+	static int output_option = 0, opt = 0;
+	static int show_stats = 0;
+	static const char *revs_file = NULL;
+	static const char *contents_from = NULL;
+	static const struct option options[] = {
+		OPT_BOOLEAN(0, "incremental", &incremental, "Show blame entries as we find them, incrementally"),
+		OPT_BOOLEAN('b', NULL, &blank_boundary, "Show blank SHA-1 for boundary commits (Default: off)"),
+		OPT_BOOLEAN(0, "root", &show_root, "Do not treat root commits as boundaries (Default: off)"),
+		OPT_BOOLEAN(0, "show-stats", &show_stats, "Show work cost statistics"),
+		OPT_BIT(0, "score-debug", &output_option, "Show output score for blame entries", OUTPUT_SHOW_SCORE),
+		OPT_BIT('f', "show-name", &output_option, "Show original filename (Default: auto)", OUTPUT_SHOW_NAME),
+		OPT_BIT('n', "show-number", &output_option, "Show original linenumber (Default: off)", OUTPUT_SHOW_NUMBER),
+		OPT_BIT('p', "porcelain", &output_option, "Show in a format designed for machine consumption", OUTPUT_PORCELAIN),
+		OPT_BIT('c', NULL, &output_option, "Use the same output mode as git-annotate (Default: off)", OUTPUT_ANNOTATE_COMPAT),
+		OPT_BIT('t', NULL, &output_option, "Show raw timestamp (Default: off)", OUTPUT_RAW_TIMESTAMP),
+		OPT_BIT('l', NULL, &output_option, "Show long commit SHA1 (Default: off)", OUTPUT_LONG_OBJECT_NAME),
+		OPT_BIT('s', NULL, &output_option, "Suppress author name and timestamp (Default: off)", OUTPUT_NO_AUTHOR),
+		OPT_BIT('w', NULL, &xdl_opts, "Ignore whitespace differences", XDF_IGNORE_WHITESPACE),
+		OPT_STRING('S', NULL, &revs_file, "file", "Use revisions from <file> instead of calling git-rev-list"),
+		OPT_STRING(0, "contents", &contents_from, "file", "Use <file>'s contents as the final image"),
+		{ OPTION_CALLBACK, 'C', NULL, &opt, "score", "Find line copies within and across files", PARSE_OPT_OPTARG, blame_copy_callback },
+		{ OPTION_CALLBACK, 'M', NULL, &opt, "score", "Find line movements within and across files", PARSE_OPT_OPTARG, blame_move_callback },
+		OPT_CALLBACK('L', NULL, &bottomtop, "n,m", "Process only line range n,m, counting from 1", blame_bottomtop_callback),
+		OPT_END()
+	};
+
+	struct parse_opt_ctx_t ctx;
+	int cmd_is_annotate = !strcmp(argv[0], "annotate");
 
 	git_config(git_blame_config, NULL);
+	init_revisions(&revs, NULL);
 	save_commit_buffer = 0;
+	dashdash_pos = 0;
 
-	opt = 0;
-	seen_dashdash = 0;
-	for (unk = i = 1; i < argc; i++) {
-		const char *arg = argv[i];
-		if (*arg != '-')
-			break;
-		else if (!strcmp("-b", arg))
-			blank_boundary = 1;
-		else if (!strcmp("--root", arg))
-			show_root = 1;
-		else if (!strcmp(arg, "--show-stats"))
-			show_stats = 1;
-		else if (!strcmp("-c", arg))
-			output_option |= OUTPUT_ANNOTATE_COMPAT;
-		else if (!strcmp("-t", arg))
-			output_option |= OUTPUT_RAW_TIMESTAMP;
-		else if (!strcmp("-l", arg))
-			output_option |= OUTPUT_LONG_OBJECT_NAME;
-		else if (!strcmp("-s", arg))
-			output_option |= OUTPUT_NO_AUTHOR;
-		else if (!strcmp("-w", arg))
-			xdl_opts |= XDF_IGNORE_WHITESPACE;
-		else if (!strcmp("-S", arg) && ++i < argc)
-			revs_file = argv[i];
-		else if (!prefixcmp(arg, "-M")) {
-			opt |= PICKAXE_BLAME_MOVE;
-			blame_move_score = parse_score(arg+2);
+	parse_options_start(&ctx, argc, argv, PARSE_OPT_KEEP_DASHDASH |
+			    PARSE_OPT_KEEP_ARGV0);
+	for (;;) {
+		switch (parse_options_step(&ctx, options, blame_opt_usage)) {
+		case PARSE_OPT_HELP:
+			exit(129);
+		case PARSE_OPT_DONE:
+			if (ctx.argv[0])
+				dashdash_pos = ctx.cpidx;
+			goto parse_done;
 		}
-		else if (!prefixcmp(arg, "-C")) {
-			/*
-			 * -C enables copy from removed files;
-			 * -C -C enables copy from existing files, but only
-			 *       when blaming a new file;
-			 * -C -C -C enables copy from existing files for
-			 *          everybody
-			 */
-			if (opt & PICKAXE_BLAME_COPY_HARDER)
-				opt |= PICKAXE_BLAME_COPY_HARDEST;
-			if (opt & PICKAXE_BLAME_COPY)
-				opt |= PICKAXE_BLAME_COPY_HARDER;
-			opt |= PICKAXE_BLAME_COPY | PICKAXE_BLAME_MOVE;
-			blame_copy_score = parse_score(arg+2);
+
+		if (!strcmp(ctx.argv[0], "--reverse")) {
+			ctx.argv[0] = "--children";
+			reverse = 1;
 		}
-		else if (!prefixcmp(arg, "-L")) {
-			if (!arg[2]) {
-				if (++i >= argc)
-					usage(blame_usage);
-				arg = argv[i];
-			}
-			else
-				arg += 2;
-			if (bottomtop)
-				die("More than one '-L n,m' option given");
-			bottomtop = arg;
-		}
-		else if (!strcmp("--contents", arg)) {
-			if (++i >= argc)
-				usage(blame_usage);
-			contents_from = argv[i];
-		}
-		else if (!strcmp("--incremental", arg))
-			incremental = 1;
-		else if (!strcmp("--score-debug", arg))
-			output_option |= OUTPUT_SHOW_SCORE;
-		else if (!strcmp("-f", arg) ||
-			 !strcmp("--show-name", arg))
-			output_option |= OUTPUT_SHOW_NAME;
-		else if (!strcmp("-n", arg) ||
-			 !strcmp("--show-number", arg))
-			output_option |= OUTPUT_SHOW_NUMBER;
-		else if (!strcmp("-p", arg) ||
-			 !strcmp("--porcelain", arg))
-			output_option |= OUTPUT_PORCELAIN;
-		else if (!strcmp("--", arg)) {
-			seen_dashdash = 1;
-			i++;
-			break;
-		}
-		else
-			argv[unk++] = arg;
+		parse_revision_opt(&revs, &ctx, options, blame_opt_usage);
 	}
+parse_done:
+	argc = parse_options_end(&ctx);
+
+	if (cmd_is_annotate)
+		output_option |= OUTPUT_ANNOTATE_COMPAT;
+
+	if (DIFF_OPT_TST(&revs.diffopt, FIND_COPIES_HARDER))
+		opt |= (PICKAXE_BLAME_COPY | PICKAXE_BLAME_MOVE |
+			PICKAXE_BLAME_COPY_HARDER);
 
 	if (!blame_move_score)
 		blame_move_score = BLAME_DEFAULT_MOVE_SCORE;
@@ -2238,115 +2365,59 @@
 	 *
 	 * The remaining are:
 	 *
-	 * (1) if seen_dashdash, its either
-	 *     "-options -- <path>" or
-	 *     "-options -- <path> <rev>".
-	 *     but the latter is allowed only if there is no
-	 *     options that we passed to revision machinery.
+	 * (1) if dashdash_pos != 0, its either
+	 *     "blame [revisions] -- <path>" or
+	 *     "blame -- <path> <rev>"
 	 *
-	 * (2) otherwise, we may have "--" somewhere later and
-	 *     might be looking at the first one of multiple 'rev'
-	 *     parameters (e.g. " master ^next ^maint -- path").
-	 *     See if there is a dashdash first, and give the
-	 *     arguments before that to revision machinery.
-	 *     After that there must be one 'path'.
+	 * (2) otherwise, its one of the two:
+	 *     "blame [revisions] <path>"
+	 *     "blame <path> <rev>"
 	 *
-	 * (3) otherwise, its one of the three:
-	 *     "-options <path> <rev>"
-	 *     "-options <rev> <path>"
-	 *     "-options <path>"
-	 *     but again the first one is allowed only if
-	 *     there is no options that we passed to revision
-	 *     machinery.
+	 * Note that we must strip out <path> from the arguments: we do not
+	 * want the path pruning but we may want "bottom" processing.
 	 */
-
-	if (seen_dashdash) {
-		/* (1) */
-		if (argc <= i)
-			usage(blame_usage);
-		path = add_prefix(prefix, argv[i]);
-		if (i + 1 == argc - 1) {
-			if (unk != 1)
-				usage(blame_usage);
-			argv[unk++] = argv[i + 1];
+	if (dashdash_pos) {
+		switch (argc - dashdash_pos - 1) {
+		case 2: /* (1b) */
+			if (argc != 4)
+				usage_with_options(blame_opt_usage, options);
+			/* reorder for the new way: <rev> -- <path> */
+			argv[1] = argv[3];
+			argv[3] = argv[2];
+			argv[2] = "--";
+			/* FALLTHROUGH */
+		case 1: /* (1a) */
+			path = add_prefix(prefix, argv[--argc]);
+			argv[argc] = NULL;
+			break;
+		default:
+			usage_with_options(blame_opt_usage, options);
 		}
-		else if (i + 1 != argc)
-			/* garbage at end */
-			usage(blame_usage);
-	}
-	else {
-		int j;
-		for (j = i; !seen_dashdash && j < argc; j++)
-			if (!strcmp(argv[j], "--"))
-				seen_dashdash = j;
-		if (seen_dashdash) {
-			/* (2) */
-			if (seen_dashdash + 1 != argc - 1)
-				usage(blame_usage);
-			path = add_prefix(prefix, argv[seen_dashdash + 1]);
-			for (j = i; j < seen_dashdash; j++)
-				argv[unk++] = argv[j];
+	} else {
+		if (argc < 2)
+			usage_with_options(blame_opt_usage, options);
+		path = add_prefix(prefix, argv[argc - 1]);
+		if (argc == 3 && !has_string_in_work_tree(path)) { /* (2b) */
+			path = add_prefix(prefix, argv[1]);
+			argv[1] = argv[2];
 		}
-		else {
-			/* (3) */
-			if (argc <= i)
-				usage(blame_usage);
-			path = add_prefix(prefix, argv[i]);
-			if (i + 1 == argc - 1) {
-				final_commit_name = argv[i + 1];
+		argv[argc - 1] = "--";
 
-				/* if (unk == 1) we could be getting
-				 * old-style
-				 */
-				if (unk == 1 && !has_path_in_work_tree(path)) {
-					path = add_prefix(prefix, argv[i + 1]);
-					final_commit_name = argv[i];
-				}
-			}
-			else if (i != argc - 1)
-				usage(blame_usage); /* garbage at end */
-
-			setup_work_tree();
-			if (!has_path_in_work_tree(path))
-				die("cannot stat path %s: %s",
-				    path, strerror(errno));
-		}
+		setup_work_tree();
+		if (!has_string_in_work_tree(path))
+			die("cannot stat path %s: %s", path, strerror(errno));
 	}
 
-	if (final_commit_name)
-		argv[unk++] = final_commit_name;
-
-	/*
-	 * Now we got rev and path.  We do not want the path pruning
-	 * but we may want "bottom" processing.
-	 */
-	argv[unk++] = "--"; /* terminate the rev name */
-	argv[unk] = NULL;
-
-	init_revisions(&revs, NULL);
-	setup_revisions(unk, argv, &revs, NULL);
+	setup_revisions(argc, argv, &revs, NULL);
 	memset(&sb, 0, sizeof(sb));
 
-	/*
-	 * There must be one and only one positive commit in the
-	 * revs->pending array.
-	 */
-	for (i = 0; i < revs.pending.nr; i++) {
-		struct object *obj = revs.pending.objects[i].item;
-		if (obj->flags & UNINTERESTING)
-			continue;
-		while (obj->type == OBJ_TAG)
-			obj = deref_tag(obj, NULL, 0);
-		if (obj->type != OBJ_COMMIT)
-			die("Non commit %s?",
-			    revs.pending.objects[i].name);
-		if (sb.final)
-			die("More than one commit to dig from %s and %s?",
-			    revs.pending.objects[i].name,
-			    final_commit_name);
-		sb.final = (struct commit *) obj;
-		final_commit_name = revs.pending.objects[i].name;
-	}
+	sb.revs = &revs;
+	if (!reverse)
+		final_commit_name = prepare_final(&sb);
+	else if (contents_from)
+		die("--contents and --children do not blend well.");
+	else
+		final_commit_name = prepare_initial(&sb);
 
 	if (!sb.final) {
 		/*
@@ -2425,7 +2496,7 @@
 	if (!incremental)
 		setup_pager();
 
-	assign_blame(&sb, &revs, opt);
+	assign_blame(&sb, opt);
 
 	if (incremental)
 		return 0;
diff --git a/builtin-branch.c b/builtin-branch.c
index d279702..4b4abfd 100644
--- a/builtin-branch.c
+++ b/builtin-branch.c
@@ -13,19 +13,19 @@
 #include "remote.h"
 #include "parse-options.h"
 #include "branch.h"
+#include "diff.h"
+#include "revision.h"
 
 static const char * const builtin_branch_usage[] = {
-	"git-branch [options] [-r | -a] [--merged | --no-merged]",
-	"git-branch [options] [-l] [-f] <branchname> [<start-point>]",
-	"git-branch [options] [-r] (-d | -D) <branchname>",
-	"git-branch [options] (-m | -M) [<oldbranch>] <newbranch>",
+	"git branch [options] [-r | -a] [--merged | --no-merged]",
+	"git branch [options] [-l] [-f] <branchname> [<start-point>]",
+	"git branch [options] [-r] (-d | -D) <branchname>",
+	"git branch [options] (-m | -M) [<oldbranch>] <newbranch>",
 	NULL
 };
 
-#define REF_UNKNOWN_TYPE    0x00
 #define REF_LOCAL_BRANCH    0x01
 #define REF_REMOTE_BRANCH   0x02
-#define REF_TAG             0x04
 
 static const char *head;
 static unsigned char head_sha1[20];
@@ -46,7 +46,12 @@
 	COLOR_BRANCH_CURRENT = 4,
 };
 
-static int mergefilter = -1;
+static enum merge_filter {
+	NO_FILTER = 0,
+	SHOW_NOT_MERGED,
+	SHOW_MERGED,
+} merge_filter;
+static unsigned char merge_filter_ref[20];
 
 static int parse_branch_color_slot(const char *var, int ofs)
 {
@@ -155,7 +160,7 @@
 			continue;
 		}
 
-		if (delete_ref(name, sha1)) {
+		if (delete_ref(name, sha1, 0)) {
 			error("Error deleting %sbranch '%s'", remote,
 			       argv[i]);
 			ret = 1;
@@ -176,25 +181,21 @@
 struct ref_item {
 	char *name;
 	unsigned int kind;
-	unsigned char sha1[20];
+	struct commit *commit;
 };
 
 struct ref_list {
+	struct rev_info revs;
 	int index, alloc, maxwidth;
 	struct ref_item *list;
 	struct commit_list *with_commit;
 	int kinds;
 };
 
-static int has_commit(const unsigned char *sha1, struct commit_list *with_commit)
+static int has_commit(struct commit *commit, struct commit_list *with_commit)
 {
-	struct commit *commit;
-
 	if (!with_commit)
 		return 1;
-	commit = lookup_commit_reference_gently(sha1, 1);
-	if (!commit)
-		return 0;
 	while (with_commit) {
 		struct commit *other;
 
@@ -210,9 +211,9 @@
 {
 	struct ref_list *ref_list = (struct ref_list*)(cb_data);
 	struct ref_item *newitem;
-	int kind = REF_UNKNOWN_TYPE;
+	struct commit *commit;
+	int kind;
 	int len;
-	static struct commit_list branch;
 
 	/* Detect kind */
 	if (!prefixcmp(refname, "refs/heads/")) {
@@ -221,28 +222,24 @@
 	} else if (!prefixcmp(refname, "refs/remotes/")) {
 		kind = REF_REMOTE_BRANCH;
 		refname += 13;
-	} else if (!prefixcmp(refname, "refs/tags/")) {
-		kind = REF_TAG;
-		refname += 10;
-	}
+	} else
+		return 0;
+
+	commit = lookup_commit_reference_gently(sha1, 1);
+	if (!commit)
+		return error("branch '%s' does not point at a commit", refname);
 
 	/* Filter with with_commit if specified */
-	if (!has_commit(sha1, ref_list->with_commit))
+	if (!has_commit(commit, ref_list->with_commit))
 		return 0;
 
 	/* Don't add types the caller doesn't want */
 	if ((kind & ref_list->kinds) == 0)
 		return 0;
 
-	if (mergefilter > -1) {
-		branch.item = lookup_commit_reference_gently(sha1, 1);
-		if (!branch.item)
-			die("Unable to lookup tip of branch %s", refname);
-		if (mergefilter == 0 && has_commit(head_sha1, &branch))
-			return 0;
-		if (mergefilter == 1 && !has_commit(head_sha1, &branch))
-			return 0;
-	}
+	if (merge_filter != NO_FILTER)
+		add_pending_object(&ref_list->revs,
+				   (struct object *)commit, refname);
 
 	/* Resize buffer */
 	if (ref_list->index >= ref_list->alloc) {
@@ -255,7 +252,7 @@
 	newitem = &(ref_list->list[ref_list->index++]);
 	newitem->name = xstrdup(refname);
 	newitem->kind = kind;
-	hashcpy(newitem->sha1, sha1);
+	newitem->commit = commit;
 	len = strlen(newitem->name);
 	if (len > ref_list->maxwidth)
 		ref_list->maxwidth = len;
@@ -282,12 +279,41 @@
 	return strcmp(c1->name, c2->name);
 }
 
+static void fill_tracking_info(char *stat, const char *branch_name)
+{
+	int ours, theirs;
+	struct branch *branch = branch_get(branch_name);
+
+	if (!stat_tracking_info(branch, &ours, &theirs) || (!ours && !theirs))
+		return;
+	if (!ours)
+		sprintf(stat, "[behind %d] ", theirs);
+	else if (!theirs)
+		sprintf(stat, "[ahead %d] ", ours);
+	else
+		sprintf(stat, "[ahead %d, behind %d] ", ours, theirs);
+}
+
+static int matches_merge_filter(struct commit *commit)
+{
+	int is_merged;
+
+	if (merge_filter == NO_FILTER)
+		return 1;
+
+	is_merged = !!(commit->object.flags & UNINTERESTING);
+	return (is_merged == (merge_filter == SHOW_MERGED));
+}
+
 static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
 			   int abbrev, int current)
 {
 	char c;
 	int color;
-	struct commit *commit;
+	struct commit *commit = item->commit;
+
+	if (!matches_merge_filter(commit))
+		return;
 
 	switch (item->kind) {
 	case REF_LOCAL_BRANCH:
@@ -310,19 +336,26 @@
 	if (verbose) {
 		struct strbuf subject;
 		const char *sub = " **** invalid ref ****";
+		char stat[128];
 
 		strbuf_init(&subject, 0);
+		stat[0] = '\0';
 
-		commit = lookup_commit(item->sha1);
+		commit = item->commit;
 		if (commit && !parse_commit(commit)) {
 			pretty_print_commit(CMIT_FMT_ONELINE, commit,
 					    &subject, 0, NULL, NULL, 0, 0);
 			sub = subject.buf;
 		}
-		printf("%c %s%-*s%s %s %s\n", c, branch_get_color(color),
+
+		if (item->kind == REF_LOCAL_BRANCH)
+			fill_tracking_info(stat, item->name);
+
+		printf("%c %s%-*s%s %s %s%s\n", c, branch_get_color(color),
 		       maxwidth, item->name,
 		       branch_get_color(COLOR_BRANCH_RESET),
-		       find_unique_abbrev(item->sha1, abbrev), sub);
+		       find_unique_abbrev(item->commit->object.sha1, abbrev),
+		       stat, sub);
 		strbuf_release(&subject);
 	} else {
 		printf("%c %s%s%s\n", c, branch_get_color(color), item->name,
@@ -330,26 +363,53 @@
 	}
 }
 
+static int calc_maxwidth(struct ref_list *refs)
+{
+	int i, l, w = 0;
+	for (i = 0; i < refs->index; i++) {
+		if (!matches_merge_filter(refs->list[i].commit))
+			continue;
+		l = strlen(refs->list[i].name);
+		if (l > w)
+			w = l;
+	}
+	return w;
+}
+
 static void print_ref_list(int kinds, int detached, int verbose, int abbrev, struct commit_list *with_commit)
 {
 	int i;
 	struct ref_list ref_list;
+	struct commit *head_commit = lookup_commit_reference_gently(head_sha1, 1);
 
 	memset(&ref_list, 0, sizeof(ref_list));
 	ref_list.kinds = kinds;
 	ref_list.with_commit = with_commit;
+	if (merge_filter != NO_FILTER)
+		init_revisions(&ref_list.revs, NULL);
 	for_each_ref(append_ref, &ref_list);
+	if (merge_filter != NO_FILTER) {
+		struct commit *filter;
+		filter = lookup_commit_reference_gently(merge_filter_ref, 0);
+		filter->object.flags |= UNINTERESTING;
+		add_pending_object(&ref_list.revs,
+				   (struct object *) filter, "");
+		ref_list.revs.limited = 1;
+		prepare_revision_walk(&ref_list.revs);
+		if (verbose)
+			ref_list.maxwidth = calc_maxwidth(&ref_list);
+	}
 
 	qsort(ref_list.list, ref_list.index, sizeof(struct ref_item), ref_cmp);
 
 	detached = (detached && (kinds & REF_LOCAL_BRANCH));
-	if (detached && has_commit(head_sha1, with_commit)) {
+	if (detached && head_commit && has_commit(head_commit, with_commit)) {
 		struct ref_item item;
 		item.name = xstrdup("(no branch)");
 		item.kind = REF_LOCAL_BRANCH;
-		hashcpy(item.sha1, head_sha1);
+		item.commit = head_commit;
 		if (strlen(item.name) > ref_list.maxwidth)
-			      ref_list.maxwidth = strlen(item.name);
+			ref_list.maxwidth = strlen(item.name);
 		print_ref_item(&item, ref_list.maxwidth, verbose, abbrev, 1);
 		free(item.name);
 	}
@@ -421,6 +481,20 @@
 	return 0;
 }
 
+static int opt_parse_merge_filter(const struct option *opt, const char *arg, int unset)
+{
+	merge_filter = ((opt->long_name[0] == 'n')
+			? SHOW_NOT_MERGED
+			: SHOW_MERGED);
+	if (unset)
+		merge_filter = SHOW_NOT_MERGED; /* b/c for --no-merged */
+	if (!arg)
+		arg = "HEAD";
+	if (get_sha1(arg, merge_filter_ref))
+		die("malformed object name %s", arg);
+	return 0;
+}
+
 int cmd_branch(int argc, const char **argv, const char *prefix)
 {
 	int delete = 0, rename = 0, force_create = 0;
@@ -438,13 +512,17 @@
 		OPT_BOOLEAN( 0 , "color",  &branch_use_color, "use colored output"),
 		OPT_SET_INT('r', NULL,     &kinds, "act on remote-tracking branches",
 			REF_REMOTE_BRANCH),
-		OPT_CALLBACK(0, "contains", &with_commit, "commit",
-			     "print only branches that contain the commit",
-			     opt_parse_with_commit),
+		{
+			OPTION_CALLBACK, 0, "contains", &with_commit, "commit",
+			"print only branches that contain the commit",
+			PARSE_OPT_LASTARG_DEFAULT,
+			opt_parse_with_commit, (intptr_t)"HEAD",
+		},
 		{
 			OPTION_CALLBACK, 0, "with", &with_commit, "commit",
 			"print only branches that contain the commit",
-			PARSE_OPT_HIDDEN, opt_parse_with_commit,
+			PARSE_OPT_HIDDEN | PARSE_OPT_LASTARG_DEFAULT,
+			opt_parse_with_commit, (intptr_t) "HEAD",
 		},
 		OPT__ABBREV(&abbrev),
 
@@ -457,7 +535,18 @@
 		OPT_BIT('M', NULL, &rename, "move/rename a branch, even if target exists", 2),
 		OPT_BOOLEAN('l', NULL, &reflog, "create the branch's reflog"),
 		OPT_BOOLEAN('f', NULL, &force_create, "force creation (when already exists)"),
-		OPT_SET_INT(0, "merged", &mergefilter, "list only merged branches", 1),
+		{
+			OPTION_CALLBACK, 0, "no-merged", &merge_filter_ref,
+			"commit", "print only not merged branches",
+			PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG,
+			opt_parse_merge_filter, (intptr_t) "HEAD",
+		},
+		{
+			OPTION_CALLBACK, 0, "merged", &merge_filter_ref,
+			"commit", "print only merged branches",
+			PARSE_OPT_LASTARG_DEFAULT | PARSE_OPT_NONEG,
+			opt_parse_merge_filter, (intptr_t) "HEAD",
+		},
 		OPT_END(),
 	};
 
@@ -467,9 +556,6 @@
 		branch_use_color = git_use_color_default;
 
 	track = git_branch_track;
-	argc = parse_options(argc, argv, options, builtin_branch_usage, 0);
-	if (!!delete + !!rename + !!force_create > 1)
-		usage_with_options(builtin_branch_usage, options);
 
 	head = resolve_ref("HEAD", head_sha1, 0, NULL);
 	if (!head)
@@ -482,6 +568,11 @@
 			die("HEAD not found below refs/heads!");
 		head += 11;
 	}
+	hashcpy(merge_filter_ref, head_sha1);
+
+	argc = parse_options(argc, argv, options, builtin_branch_usage, 0);
+	if (!!delete + !!rename + !!force_create > 1)
+		usage_with_options(builtin_branch_usage, options);
 
 	if (delete)
 		return delete_branches(argc, argv, delete > 1, kinds);
diff --git a/builtin-bundle.c b/builtin-bundle.c
index ac476e7..9b58152 100644
--- a/builtin-bundle.c
+++ b/builtin-bundle.c
@@ -6,10 +6,10 @@
  * Basic handler for bundle files to connect repositories via sneakernet.
  * Invocation must include action.
  * This function can create a bundle or provide information on an existing
- * bundle supporting git-fetch, git-pull, and git-ls-remote
+ * bundle supporting "fetch", "pull", and "ls-remote".
  */
 
-static const char *bundle_usage="git-bundle (create <bundle> <git-rev-list args> | verify <bundle> | list-heads <bundle> [refname]... | unbundle <bundle> [refname]... )";
+static const char *bundle_usage="git bundle (create <bundle> <git rev-list args> | verify <bundle> | list-heads <bundle> [refname]... | unbundle <bundle> [refname]... )";
 
 int cmd_bundle(int argc, const char **argv, const char *prefix)
 {
diff --git a/builtin-cat-file.c b/builtin-cat-file.c
index 880e75a..3fba6b9 100644
--- a/builtin-cat-file.c
+++ b/builtin-cat-file.c
@@ -137,11 +137,11 @@
 		break;
 
 	default:
-		die("git-cat-file: unknown option: %s\n", exp_type);
+		die("git cat-file: unknown option: %s\n", exp_type);
 	}
 
 	if (!buf)
-		die("git-cat-file %s: bad file", obj_name);
+		die("git cat-file %s: bad file", obj_name);
 
 	write_or_die(1, buf, size);
 	return 0;
@@ -202,8 +202,8 @@
 }
 
 static const char * const cat_file_usage[] = {
-	"git-cat-file [-t|-s|-e|-p|<type>] <sha1>",
-	"git-cat-file [--batch|--batch-check] < <list_of_sha1s>",
+	"git cat-file [-t|-s|-e|-p|<type>] <sha1>",
+	"git cat-file [--batch|--batch-check] < <list_of_sha1s>",
 	NULL
 };
 
diff --git a/builtin-check-attr.c b/builtin-check-attr.c
index 6afdfa1..cb783fc 100644
--- a/builtin-check-attr.c
+++ b/builtin-check-attr.c
@@ -4,7 +4,7 @@
 #include "quote.h"
 
 static const char check_attr_usage[] =
-"git-check-attr attr... [--] pathname...";
+"git check-attr attr... [--] pathname...";
 
 int cmd_check_attr(int argc, const char **argv, const char *prefix)
 {
diff --git a/builtin-check-ref-format.c b/builtin-check-ref-format.c
index fe04be7..701de43 100644
--- a/builtin-check-ref-format.c
+++ b/builtin-check-ref-format.c
@@ -9,6 +9,6 @@
 int cmd_check_ref_format(int argc, const char **argv, const char *prefix)
 {
 	if (argc != 2)
-		usage("git-check-ref-format refname");
+		usage("git check-ref-format refname");
 	return !!check_ref_format(argv[1]);
 }
diff --git a/builtin-checkout-index.c b/builtin-checkout-index.c
index eb1fc9a..55b7aaf 100644
--- a/builtin-checkout-index.c
+++ b/builtin-checkout-index.c
@@ -5,26 +5,26 @@
  *
  * Careful: order of argument flags does matter. For example,
  *
- *	git-checkout-index -a -f file.c
+ *	git checkout-index -a -f file.c
  *
  * Will first check out all files listed in the cache (but not
  * overwrite any old ones), and then force-checkout "file.c" a
  * second time (ie that one _will_ overwrite any old contents
  * with the same filename).
  *
- * Also, just doing "git-checkout-index" does nothing. You probably
- * meant "git-checkout-index -a". And if you want to force it, you
- * want "git-checkout-index -f -a".
+ * Also, just doing "git checkout-index" does nothing. You probably
+ * meant "git checkout-index -a". And if you want to force it, you
+ * want "git checkout-index -f -a".
  *
  * Intuitiveness is not the goal here. Repeatability is. The
  * reason for the "no arguments means no work" thing is that
  * from scripts you are supposed to be able to do things like
  *
- *	find . -name '*.h' -print0 | xargs -0 git-checkout-index -f --
+ *	find . -name '*.h' -print0 | xargs -0 git checkout-index -f --
  *
  * or:
  *
- *	find . -name '*.h' -print0 | git-checkout-index -f -z --stdin
+ *	find . -name '*.h' -print0 | git checkout-index -f -z --stdin
  *
  * which will force all existing *.h files to be replaced with
  * their cached copies. If an empty command line implied "all",
@@ -107,7 +107,7 @@
 	}
 
 	if (!state.quiet) {
-		fprintf(stderr, "git-checkout-index: %s ", name);
+		fprintf(stderr, "git checkout-index: %s ", name);
 		if (!has_same_name)
 			fprintf(stderr, "is not in the cache");
 		else if (checkout_stage)
@@ -154,7 +154,7 @@
 }
 
 static const char checkout_cache_usage[] =
-"git-checkout-index [-u] [-q] [-a] [-f] [-n] [--stage=[123]|all] [--prefix=<string>] [--temp] [--] <file>...";
+"git checkout-index [-u] [-q] [-a] [-f] [-n] [--stage=[123]|all] [--prefix=<string>] [--temp] [--] <file>...";
 
 static struct lock_file lock_file;
 
@@ -258,9 +258,9 @@
 		const char *p;
 
 		if (all)
-			die("git-checkout-index: don't mix '--all' and explicit filenames");
+			die("git checkout-index: don't mix '--all' and explicit filenames");
 		if (read_from_stdin)
-			die("git-checkout-index: don't mix '--stdin' and explicit filenames");
+			die("git checkout-index: don't mix '--stdin' and explicit filenames");
 		p = prefix_path(prefix, prefix_length, arg);
 		checkout_file(p, prefix_length);
 		if (p < arg || p > arg + strlen(arg))
@@ -271,7 +271,7 @@
 		struct strbuf buf, nbuf;
 
 		if (all)
-			die("git-checkout-index: don't mix '--all' and '--stdin'");
+			die("git checkout-index: don't mix '--all' and '--stdin'");
 
 		strbuf_init(&buf, 0);
 		strbuf_init(&nbuf, 0);
diff --git a/builtin-checkout.c b/builtin-checkout.c
index aec2bc6..c107fd6 100644
--- a/builtin-checkout.c
+++ b/builtin-checkout.c
@@ -32,7 +32,7 @@
 
 	memset(&proc, 0, sizeof(proc));
 	argv[0] = name;
-	argv[1] = xstrdup(sha1_to_hex(old->object.sha1));
+	argv[1] = xstrdup(sha1_to_hex(old ? old->object.sha1 : null_sha1));
 	argv[2] = xstrdup(sha1_to_hex(new->object.sha1));
 	argv[3] = changed ? "1" : "0";
 	argv[4] = NULL;
@@ -43,7 +43,7 @@
 }
 
 static int update_some(const unsigned char *sha1, const char *base, int baselen,
-		       const char *pathname, unsigned mode, int stage)
+		const char *pathname, unsigned mode, int stage, void *context)
 {
 	int len;
 	struct cache_entry *ce;
@@ -67,7 +67,7 @@
 
 static int read_tree_some(struct tree *tree, const char **pathspec)
 {
-	read_tree_recursive(tree, "", 0, 0, pathspec, update_some);
+	read_tree_recursive(tree, "", 0, 0, pathspec, update_some, NULL);
 
 	/* update the index with the given tree's info
 	 * for all args, expanding wildcards, and exit
@@ -76,6 +76,15 @@
 	return 0;
 }
 
+static int skip_same_name(struct cache_entry *ce, int pos)
+{
+	while (++pos < active_nr &&
+	       !strcmp(active_cache[pos]->name, ce->name))
+		; /* skip */
+	return pos;
+}
+
+
 static int checkout_paths(struct tree *source_tree, const char **pathspec)
 {
 	int pos;
@@ -107,6 +116,20 @@
 	if (report_path_error(ps_matched, pathspec, 0))
 		return 1;
 
+	/* Any unmerged paths? */
+	for (pos = 0; pos < active_nr; pos++) {
+		struct cache_entry *ce = active_cache[pos];
+		if (pathspec_match(pathspec, NULL, ce->name, 0)) {
+			if (!ce_stage(ce))
+				continue;
+			errs = 1;
+			error("path '%s' is unmerged", ce->name);
+			pos = skip_same_name(ce, pos) - 1;
+		}
+	}
+	if (errs)
+		return 1;
+
 	/* Now we are committed to check them out */
 	memset(&state, 0, sizeof(state));
 	state.force = 1;
@@ -114,7 +137,11 @@
 	for (pos = 0; pos < active_nr; pos++) {
 		struct cache_entry *ce = active_cache[pos];
 		if (pathspec_match(pathspec, NULL, ce->name, 0)) {
-			errs |= checkout_entry(ce, &state, NULL);
+			if (!ce_stage(ce)) {
+				errs |= checkout_entry(ce, &state, NULL);
+				continue;
+			}
+			pos = skip_same_name(ce, pos) - 1;
 		}
 	}
 
@@ -242,6 +269,7 @@
 		}
 
 		/* 2-way merge to the new branch */
+		topts.initial_checkout = is_cache_unborn();
 		topts.update = 1;
 		topts.merge = 1;
 		topts.gently = opts->merge;
@@ -299,103 +327,21 @@
 	    commit_locked_index(lock_file))
 		die("unable to write new index file");
 
-	if (!opts->force)
+	if (!opts->force && !opts->quiet)
 		show_local_changes(&new->commit->object);
 
 	return 0;
 }
 
-static void report_tracking(struct branch_info *new, struct checkout_opts *opts)
+static void report_tracking(struct branch_info *new)
 {
-	/*
-	 * We have switched to a new branch; is it building on
-	 * top of another branch, and if so does that other branch
-	 * have changes we do not have yet?
-	 */
-	char *base;
-	unsigned char sha1[20];
-	struct commit *ours, *theirs;
-	char symmetric[84];
-	struct rev_info revs;
-	const char *rev_argv[10];
-	int rev_argc;
-	int num_ours, num_theirs;
-	const char *remote_msg;
+	struct strbuf sb = STRBUF_INIT;
 	struct branch *branch = branch_get(new->name);
 
-	/*
-	 * Nothing to report unless we are marked to build on top of
-	 * somebody else.
-	 */
-	if (!branch || !branch->merge || !branch->merge[0] || !branch->merge[0]->dst)
+	if (!format_tracking_info(branch, &sb))
 		return;
-
-	/*
-	 * If what we used to build on no longer exists, there is
-	 * nothing to report.
-	 */
-	base = branch->merge[0]->dst;
-	if (!resolve_ref(base, sha1, 1, NULL))
-		return;
-
-	theirs = lookup_commit(sha1);
-	ours = new->commit;
-	if (!hashcmp(sha1, ours->object.sha1))
-		return; /* we are the same */
-
-	/* Run "rev-list --left-right ours...theirs" internally... */
-	rev_argc = 0;
-	rev_argv[rev_argc++] = NULL;
-	rev_argv[rev_argc++] = "--left-right";
-	rev_argv[rev_argc++] = symmetric;
-	rev_argv[rev_argc++] = "--";
-	rev_argv[rev_argc] = NULL;
-
-	strcpy(symmetric, sha1_to_hex(ours->object.sha1));
-	strcpy(symmetric + 40, "...");
-	strcpy(symmetric + 43, sha1_to_hex(theirs->object.sha1));
-
-	init_revisions(&revs, NULL);
-	setup_revisions(rev_argc, rev_argv, &revs, NULL);
-	prepare_revision_walk(&revs);
-
-	/* ... and count the commits on each side. */
-	num_ours = 0;
-	num_theirs = 0;
-	while (1) {
-		struct commit *c = get_revision(&revs);
-		if (!c)
-			break;
-		if (c->object.flags & SYMMETRIC_LEFT)
-			num_ours++;
-		else
-			num_theirs++;
-	}
-
-	if (!prefixcmp(base, "refs/remotes/")) {
-		remote_msg = " remote";
-		base += strlen("refs/remotes/");
-	} else {
-		remote_msg = "";
-	}
-
-	if (!num_theirs)
-		printf("Your branch is ahead of the tracked%s branch '%s' "
-		       "by %d commit%s.\n",
-		       remote_msg, base,
-		       num_ours, (num_ours == 1) ? "" : "s");
-	else if (!num_ours)
-		printf("Your branch is behind the tracked%s branch '%s' "
-		       "by %d commit%s,\n"
-		       "and can be fast-forwarded.\n",
-		       remote_msg, base,
-		       num_theirs, (num_theirs == 1) ? "" : "s");
-	else
-		printf("Your branch and the tracked%s branch '%s' "
-		       "have diverged,\nand respectively "
-		       "have %d and %d different commit(s) each.\n",
-		       remote_msg, base,
-		       num_ours, num_theirs);
+	fputs(sb.buf, stdout);
+	strbuf_release(&sb);
 }
 
 static void update_refs_for_switch(struct checkout_opts *opts,
@@ -413,10 +359,10 @@
 
 	strbuf_init(&msg, 0);
 	old_desc = old->name;
-	if (!old_desc)
+	if (!old_desc && old->commit)
 		old_desc = sha1_to_hex(old->commit->object.sha1);
 	strbuf_addf(&msg, "checkout: moving from %s to %s",
-		    old_desc, new->name);
+		    old_desc ? old_desc : "(invalid)", new->name);
 
 	if (new->path) {
 		create_symref("HEAD", new->path, msg.buf);
@@ -441,7 +387,7 @@
 	remove_branch_state();
 	strbuf_release(&msg);
 	if (!opts->quiet && (new->path || !strcmp(new->name, "HEAD")))
-		report_tracking(new, opts);
+		report_tracking(new);
 }
 
 static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
@@ -468,16 +414,14 @@
 	}
 
 	/*
-	 * If the new thing isn't a branch and isn't HEAD and we're
-	 * not starting a new branch, and we want messages, and we
-	 * weren't on a branch, and we're moving to a new commit,
-	 * describe the old commit.
+	 * If we were on a detached HEAD, but we are now moving to
+	 * a new commit, we want to mention the old commit once more
+	 * to remind the user that it might be lost.
 	 */
-	if (!new->path && strcmp(new->name, "HEAD") && !opts->new_branch &&
-	    !opts->quiet && !old.path && new->commit != old.commit)
+	if (!opts->quiet && !old.path && old.commit && new->commit != old.commit)
 		describe_detached_head("Previous HEAD position was", old.commit);
 
-	if (!old.commit) {
+	if (!old.commit && !opts->force) {
 		if (!opts->quiet) {
 			fprintf(stderr, "warning: You appear to be on a branch yet to be born.\n");
 			fprintf(stderr, "warning: Forcing checkout of %s.\n", new->name);
@@ -512,6 +456,7 @@
 		OPT_BOOLEAN('m', NULL, &opts.merge, "merge"),
 		OPT_END(),
 	};
+	int has_dash_dash;
 
 	memset(&opts, 0, sizeof(opts));
 	memset(&new, 0, sizeof(new));
@@ -522,11 +467,55 @@
 
 	argc = parse_options(argc, argv, options, checkout_usage,
 			     PARSE_OPT_KEEP_DASHDASH);
+
+	if (!opts.new_branch && (opts.track != git_branch_track))
+		die("git checkout: --track and --no-track require -b");
+
+	if (opts.force && opts.merge)
+		die("git checkout: -f and -m are incompatible");
+
+	/*
+	 * case 1: git checkout <ref> -- [<paths>]
+	 *
+	 *   <ref> must be a valid tree, everything after the '--' must be
+	 *   a path.
+	 *
+	 * case 2: git checkout -- [<paths>]
+	 *
+	 *   everything after the '--' must be paths.
+	 *
+	 * case 3: git checkout <something> [<paths>]
+	 *
+	 *   With no paths, if <something> is a commit, that is to
+	 *   switch to the branch or detach HEAD at it.
+	 *
+	 *   Otherwise <something> shall not be ambiguous.
+	 *   - If it's *only* a reference, treat it like case (1).
+	 *   - If it's only a path, treat it like case (2).
+	 *   - else: fail.
+	 *
+	 */
 	if (argc) {
+		if (!strcmp(argv[0], "--")) {       /* case (2) */
+			argv++;
+			argc--;
+			goto no_reference;
+		}
+
 		arg = argv[0];
-		if (get_sha1(arg, rev))
-			;
-		else if ((new.commit = lookup_commit_reference_gently(rev, 1))) {
+		has_dash_dash = (argc > 1) && !strcmp(argv[1], "--");
+
+		if (get_sha1(arg, rev)) {
+			if (has_dash_dash)          /* case (1) */
+				die("invalid reference: %s", arg);
+			goto no_reference;          /* case (3 -> 2) */
+		}
+
+		/* we can't end up being in (2) anymore, eat the argument */
+		argv++;
+		argc--;
+
+		if ((new.commit = lookup_commit_reference_gently(rev, 1))) {
 			new.name = arg;
 			setup_branch_path(&new);
 			if (resolve_ref(new.path, rev, 1, NULL))
@@ -535,25 +524,28 @@
 				new.path = NULL;
 			parse_commit(new.commit);
 			source_tree = new.commit->tree;
-			argv++;
-			argc--;
-		} else if ((source_tree = parse_tree_indirect(rev))) {
+		} else
+			source_tree = parse_tree_indirect(rev);
+
+		if (!source_tree)                   /* case (1): want a tree */
+			die("reference is not a tree: %s", arg);
+		if (!has_dash_dash) {/* case (3 -> 1) */
+			/*
+			 * Do not complain the most common case
+			 *	git checkout branch
+			 * even if there happen to be a file called 'branch';
+			 * it would be extremely annoying.
+			 */
+			if (argc)
+				verify_non_filename(NULL, arg);
+		}
+		else {
 			argv++;
 			argc--;
 		}
 	}
 
-	if (argc && !strcmp(argv[0], "--")) {
-		argv++;
-		argc--;
-	}
-
-	if (!opts.new_branch && (opts.track != git_branch_track))
-		die("git checkout: --track and --no-track require -b");
-
-	if (opts.force && opts.merge)
-		die("git checkout: -f and -m are incompatible");
-
+no_reference:
 	if (argc) {
 		const char **pathspec = get_pathspec(prefix, argv);
 
@@ -572,6 +564,18 @@
 		return checkout_paths(source_tree, pathspec);
 	}
 
+	if (opts.new_branch) {
+		struct strbuf buf;
+		strbuf_init(&buf, 0);
+		strbuf_addstr(&buf, "refs/heads/");
+		strbuf_addstr(&buf, opts.new_branch);
+		if (!get_sha1(buf.buf, rev))
+			die("git checkout: branch %s already exists", opts.new_branch);
+		if (check_ref_format(buf.buf))
+			die("git checkout: we do not like '%s' as a branch name.", opts.new_branch);
+		strbuf_release(&buf);
+	}
+
 	if (new.name && !new.commit) {
 		die("Cannot switch branch to a non-commit.");
 	}
diff --git a/builtin-clean.c b/builtin-clean.c
index 80a7ff9..48bf29f 100644
--- a/builtin-clean.c
+++ b/builtin-clean.c
@@ -15,7 +15,7 @@
 static int force = -1; /* unset */
 
 static const char *const builtin_clean_usage[] = {
-	"git-clean [-d] [-f] [-n] [-q] [-x | -X] [--] <paths>...",
+	"git clean [-d] [-f] [-n] [-q] [-x | -X] [--] <paths>...",
 	NULL
 };
 
diff --git a/builtin-clone.c b/builtin-clone.c
index 863b22e..5b40e07 100644
--- a/builtin-clone.c
+++ b/builtin-clone.c
@@ -18,6 +18,7 @@
 #include "transport.h"
 #include "strbuf.h"
 #include "dir.h"
+#include "pack-refs.h"
 
 /*
  * Overall FIXMEs:
@@ -28,11 +29,11 @@
  *
  */
 static const char * const builtin_clone_usage[] = {
-	"git-clone [options] [--] <repo> [<dir>]",
+	"git clone [options] [--] <repo> [<dir>]",
 	NULL
 };
 
-static int option_quiet, option_no_checkout, option_bare;
+static int option_quiet, option_no_checkout, option_bare, option_mirror;
 static int option_local, option_no_hardlinks, option_shared;
 static char *option_template, *option_reference, *option_depth;
 static char *option_origin = NULL;
@@ -44,6 +45,8 @@
 		    "don't create a checkout"),
 	OPT_BOOLEAN(0, "bare", &option_bare, "create a bare repository"),
 	OPT_BOOLEAN(0, "naked", &option_bare, "create a bare repository"),
+	OPT_BOOLEAN(0, "mirror", &option_mirror,
+		    "create a mirror repository (implies bare)"),
 	OPT_BOOLEAN('l', "local", &option_local,
 		    "to clone from a local repository"),
 	OPT_BOOLEAN(0, "no-hardlinks", &option_no_hardlinks,
@@ -55,7 +58,7 @@
 	OPT_STRING(0, "reference", &option_reference, "repo",
 		   "reference repository"),
 	OPT_STRING('o', "origin", &option_origin, "branch",
-		   "use <branch> instead or 'origin' to track upstream"),
+		   "use <branch> instead of 'origin' to track upstream"),
 	OPT_STRING('u', "upload-pack", &option_upload_pack, "path",
 		   "path to git-upload-pack on the remote"),
 	OPT_STRING(0, "depth", &option_depth, "depth",
@@ -92,37 +95,46 @@
 	return NULL;
 }
 
-static char *guess_dir_name(const char *repo, int is_bundle)
+static char *guess_dir_name(const char *repo, int is_bundle, int is_bare)
 {
-	const char *p, *start, *end, *limit;
-	int after_slash_or_colon;
+	const char *end = repo + strlen(repo), *start;
 
-	/* Guess dir name from repository: strip trailing '/',
-	 * strip trailing '[:/]*.{git,bundle}', strip leading '.*[/:]'. */
+	/*
+	 * Strip trailing slashes and /.git
+	 */
+	while (repo < end && is_dir_sep(end[-1]))
+		end--;
+	if (end - repo > 5 && is_dir_sep(end[-5]) &&
+	    !strncmp(end - 4, ".git", 4)) {
+		end -= 5;
+		while (repo < end && is_dir_sep(end[-1]))
+			end--;
+	}
 
-	after_slash_or_colon = 1;
-	limit = repo + strlen(repo);
-	start = repo;
-	end = limit;
-	for (p = repo; p < limit; p++) {
-		const char *prefix = is_bundle ? ".bundle" : ".git";
-		if (!prefixcmp(p, prefix)) {
-			if (!after_slash_or_colon)
-				end = p;
-			p += strlen(prefix) - 1;
-		} else if (!prefixcmp(p, ".bundle")) {
-			if (!after_slash_or_colon)
-				end = p;
-			p += 7;
-		} else if (*p == '/' || *p == ':') {
-			if (end == limit)
-				end = p;
-			after_slash_or_colon = 1;
-		} else if (after_slash_or_colon) {
-			start = p;
-			end = limit;
-			after_slash_or_colon = 0;
-		}
+	/*
+	 * Find last component, but be prepared that repo could have
+	 * the form  "remote.example.com:foo.git", i.e. no slash
+	 * in the directory part.
+	 */
+	start = end;
+	while (repo < start && !is_dir_sep(start[-1]) && start[-1] != ':')
+		start--;
+
+	/*
+	 * Strip .{bundle,git}.
+	 */
+	if (is_bundle) {
+		if (end - start > 7 && !strncmp(end - 7, ".bundle", 7))
+			end -= 7;
+	} else {
+		if (end - start > 4 && !strncmp(end - 4, ".git", 4))
+			end -= 4;
+	}
+
+	if (is_bare) {
+		char *result = xmalloc(end - start + 5);
+		sprintf(result, "%.*s.git", (int)(end - start), start);
+		return result;
 	}
 
 	return xstrndup(start, end - start);
@@ -135,6 +147,15 @@
 	return !stat(path, &buf) && S_ISDIR(buf.st_mode);
 }
 
+static void strip_trailing_slashes(char *dir)
+{
+	char *end = dir + strlen(dir);
+
+	while (dir < end - 1 && is_dir_sep(end[-1]))
+		end--;
+	*end = '\0';
+}
+
 static void setup_reference(const char *repo)
 {
 	const char *ref_git;
@@ -318,11 +339,15 @@
 	struct ref *r;
 
 	get_fetch_map(refs, refspec, &tail, 0);
-	get_fetch_map(refs, tag_refspec, &tail, 0);
+	if (!option_mirror)
+		get_fetch_map(refs, tag_refspec, &tail, 0);
 
 	for (r = local_refs; r; r = r->next)
-		update_ref(reflog,
-			   r->peer_ref->name, r->old_sha1, NULL, 0, DIE_ON_ERR);
+		add_extra_ref(r->peer_ref->name, r->old_sha1, 0);
+
+	pack_refs(PACK_REFS_ALL);
+	clear_extra_refs();
+
 	return local_refs;
 }
 
@@ -338,6 +363,7 @@
 	char branch_top[256], key[256], value[256];
 	struct strbuf reflog_msg;
 	struct transport *transport = NULL;
+	char *src_ref_prefix = "refs/heads/";
 
 	struct refspec refspec;
 
@@ -352,6 +378,9 @@
 	if (option_no_hardlinks)
 		use_local_hardlinks = 0;
 
+	if (option_mirror)
+		option_bare = 1;
+
 	if (option_bare) {
 		if (option_origin)
 			die("--bare and --origin %s options are incompatible.",
@@ -367,7 +396,7 @@
 
 	path = get_repo_path(repo_name, &is_bundle);
 	if (path)
-		repo = path;
+		repo = xstrdup(make_nonrelative_path(repo_name));
 	else if (!strchr(repo_name, ':'))
 		repo = xstrdup(make_absolute_path(repo_name));
 	else
@@ -376,7 +405,8 @@
 	if (argc == 2)
 		dir = xstrdup(argv[1]);
 	else
-		dir = guess_dir_name(repo_name, is_bundle);
+		dir = guess_dir_name(repo_name, is_bundle, option_bare);
+	strip_trailing_slashes(dir);
 
 	if (!stat(dir, &buf))
 		die("destination directory '%s' already exists.", dir);
@@ -402,10 +432,11 @@
 	if (!option_bare) {
 		junk_work_tree = work_tree;
 		if (safe_create_leading_directories_const(work_tree) < 0)
-			die("could not create leading directories of '%s'",
-					work_tree);
+			die("could not create leading directories of '%s': %s",
+					work_tree, strerror(errno));
 		if (mkdir(work_tree, 0755))
-			die("could not create work tree dir '%s'.", work_tree);
+			die("could not create work tree dir '%s': %s.",
+					work_tree, strerror(errno));
 		set_git_work_tree(work_tree);
 	}
 	junk_git_dir = git_dir;
@@ -433,26 +464,36 @@
 	git_config(git_default_config, NULL);
 
 	if (option_bare) {
-		strcpy(branch_top, "refs/heads/");
+		if (option_mirror)
+			src_ref_prefix = "refs/";
+		strcpy(branch_top, src_ref_prefix);
 
 		git_config_set("core.bare", "true");
 	} else {
 		snprintf(branch_top, sizeof(branch_top),
 			 "refs/remotes/%s/", option_origin);
+	}
 
+	if (option_mirror || !option_bare) {
 		/* Configure the remote */
+		if (option_mirror) {
+			snprintf(key, sizeof(key),
+					"remote.%s.mirror", option_origin);
+			git_config_set(key, "true");
+		}
+
 		snprintf(key, sizeof(key), "remote.%s.url", option_origin);
 		git_config_set(key, repo);
 
 		snprintf(key, sizeof(key), "remote.%s.fetch", option_origin);
 		snprintf(value, sizeof(value),
-				"+refs/heads/*:%s*", branch_top);
+				"+%s*:%s*", src_ref_prefix, branch_top);
 		git_config_set_multivar(key, value, "^$", 0);
 	}
 
 	refspec.force = 0;
 	refspec.pattern = 1;
-	refspec.src = "refs/heads/";
+	refspec.src = src_ref_prefix;
 	refspec.dst = branch_top;
 
 	if (path && !is_bundle)
diff --git a/builtin-commit-tree.c b/builtin-commit-tree.c
index e5e4bdb..9b84c48 100644
--- a/builtin-commit-tree.c
+++ b/builtin-commit-tree.c
@@ -24,26 +24,20 @@
 		    typename(expect));
 }
 
-/*
- * Having more than two parents is not strange at all, and this is
- * how multi-way merges are represented.
- */
-#define MAXPARENT (16)
-static unsigned char parent_sha1[MAXPARENT][20];
+static const char commit_tree_usage[] = "git commit-tree <sha1> [-p <sha1>]* < changelog";
 
-static const char commit_tree_usage[] = "git-commit-tree <sha1> [-p <sha1>]* < changelog";
-
-static int new_parent(int idx)
+static void new_parent(struct commit *parent, struct commit_list **parents_p)
 {
-	int i;
-	unsigned char *sha1 = parent_sha1[idx];
-	for (i = 0; i < idx; i++) {
-		if (!hashcmp(parent_sha1[i], sha1)) {
+	unsigned char *sha1 = parent->object.sha1;
+	struct commit_list *parents;
+	for (parents = *parents_p; parents; parents = parents->next) {
+		if (parents->item == parent) {
 			error("duplicate parent %s ignored", sha1_to_hex(sha1));
-			return 0;
+			return;
 		}
+		parents_p = &parents->next;
 	}
-	return 1;
+	commit_list_insert(parent, parents_p);
 }
 
 static const char commit_utf8_warn[] =
@@ -51,51 +45,32 @@
 "You may want to amend it after fixing the message, or set the config\n"
 "variable i18n.commitencoding to the encoding your project uses.\n";
 
-int cmd_commit_tree(int argc, const char **argv, const char *prefix)
+int commit_tree(const char *msg, unsigned char *tree,
+		struct commit_list *parents, unsigned char *ret)
 {
-	int i;
-	int parents = 0;
-	unsigned char tree_sha1[20];
-	unsigned char commit_sha1[20];
-	struct strbuf buffer;
 	int encoding_is_utf8;
+	struct strbuf buffer;
 
-	git_config(git_default_config, NULL);
-
-	if (argc < 2)
-		usage(commit_tree_usage);
-	if (get_sha1(argv[1], tree_sha1))
-		die("Not a valid object name %s", argv[1]);
-
-	check_valid(tree_sha1, OBJ_TREE);
-	for (i = 2; i < argc; i += 2) {
-		const char *a, *b;
-		a = argv[i]; b = argv[i+1];
-		if (!b || strcmp(a, "-p"))
-			usage(commit_tree_usage);
-
-		if (parents >= MAXPARENT)
-			die("Too many parents (%d max)", MAXPARENT);
-		if (get_sha1(b, parent_sha1[parents]))
-			die("Not a valid object name %s", b);
-		check_valid(parent_sha1[parents], OBJ_COMMIT);
-		if (new_parent(parents))
-			parents++;
-	}
+	check_valid(tree, OBJ_TREE);
 
 	/* Not having i18n.commitencoding is the same as having utf-8 */
 	encoding_is_utf8 = is_encoding_utf8(git_commit_encoding);
 
 	strbuf_init(&buffer, 8192); /* should avoid reallocs for the headers */
-	strbuf_addf(&buffer, "tree %s\n", sha1_to_hex(tree_sha1));
+	strbuf_addf(&buffer, "tree %s\n", sha1_to_hex(tree));
 
 	/*
 	 * NOTE! This ordering means that the same exact tree merged with a
 	 * different order of parents will be a _different_ changeset even
 	 * if everything else stays the same.
 	 */
-	for (i = 0; i < parents; i++)
-		strbuf_addf(&buffer, "parent %s\n", sha1_to_hex(parent_sha1[i]));
+	while (parents) {
+		struct commit_list *next = parents->next;
+		strbuf_addf(&buffer, "parent %s\n",
+			sha1_to_hex(parents->item->object.sha1));
+		free(parents);
+		parents = next;
+	}
 
 	/* Person/date information */
 	strbuf_addf(&buffer, "author %s\n", git_author_info(IDENT_ERROR_ON_NO_NAME));
@@ -105,14 +80,47 @@
 	strbuf_addch(&buffer, '\n');
 
 	/* And add the comment */
-	if (strbuf_read(&buffer, 0, 0) < 0)
-		die("git-commit-tree: read returned %s", strerror(errno));
+	strbuf_addstr(&buffer, msg);
 
 	/* And check the encoding */
 	if (encoding_is_utf8 && !is_utf8(buffer.buf))
 		fprintf(stderr, commit_utf8_warn);
 
-	if (!write_sha1_file(buffer.buf, buffer.len, commit_type, commit_sha1)) {
+	return write_sha1_file(buffer.buf, buffer.len, commit_type, ret);
+}
+
+int cmd_commit_tree(int argc, const char **argv, const char *prefix)
+{
+	int i;
+	struct commit_list *parents = NULL;
+	unsigned char tree_sha1[20];
+	unsigned char commit_sha1[20];
+	struct strbuf buffer = STRBUF_INIT;
+
+	git_config(git_default_config, NULL);
+
+	if (argc < 2)
+		usage(commit_tree_usage);
+	if (get_sha1(argv[1], tree_sha1))
+		die("Not a valid object name %s", argv[1]);
+
+	for (i = 2; i < argc; i += 2) {
+		unsigned char sha1[20];
+		const char *a, *b;
+		a = argv[i]; b = argv[i+1];
+		if (!b || strcmp(a, "-p"))
+			usage(commit_tree_usage);
+
+		if (get_sha1(b, sha1))
+			die("Not a valid object name %s", b);
+		check_valid(sha1, OBJ_COMMIT);
+		new_parent(lookup_commit(sha1), &parents);
+	}
+
+	if (strbuf_read(&buffer, 0, 0) < 0)
+		die("git commit-tree: read returned %s", strerror(errno));
+
+	if (!commit_tree(buffer.buf, tree_sha1, parents, commit_sha1)) {
 		printf("%s\n", sha1_to_hex(commit_sha1));
 		return 0;
 	}
diff --git a/builtin-commit.c b/builtin-commit.c
index 0c6d1f4..1e08399 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -21,16 +21,17 @@
 #include "strbuf.h"
 #include "utf8.h"
 #include "parse-options.h"
-#include "path-list.h"
+#include "string-list.h"
+#include "rerere.h"
 #include "unpack-trees.h"
 
 static const char * const builtin_commit_usage[] = {
-	"git-commit [options] [--] <filepattern>...",
+	"git commit [options] [--] <filepattern>...",
 	NULL
 };
 
 static const char * const builtin_status_usage[] = {
-	"git-status [options] [--] <filepattern>...",
+	"git status [options] [--] <filepattern>...",
 	NULL
 };
 
@@ -50,7 +51,8 @@
 static char *edit_message, *use_message;
 static char *author_name, *author_email, *author_date;
 static int all, edit_flag, also, interactive, only, amend, signoff;
-static int quiet, verbose, untracked_files, no_verify, allow_empty;
+static int quiet, verbose, no_verify, allow_empty;
+static char *untracked_files_arg;
 /*
  * The default commit message cleanup mode will remove the lines
  * beginning with # (shell comments) and leading and trailing
@@ -66,8 +68,8 @@
 static char *cleanup_arg;
 
 static int use_editor = 1, initial_commit, in_merge;
-const char *only_include_assumed;
-struct strbuf message;
+static const char *only_include_assumed;
+static struct strbuf message;
 
 static int opt_parse_m(const struct option *opt, const char *arg, int unset)
 {
@@ -76,8 +78,7 @@
 		strbuf_setlen(buf, 0);
 	else {
 		strbuf_addstr(buf, arg);
-		strbuf_addch(buf, '\n');
-		strbuf_addch(buf, '\n');
+		strbuf_addstr(buf, "\n\n");
 	}
 	return 0;
 }
@@ -103,7 +104,7 @@
 	OPT_BOOLEAN('o', "only", &only, "commit only specified files"),
 	OPT_BOOLEAN('n', "no-verify", &no_verify, "bypass pre-commit hook"),
 	OPT_BOOLEAN(0, "amend", &amend, "amend previous commit"),
-	OPT_BOOLEAN('u', "untracked-files", &untracked_files, "show all untracked files"),
+	{ OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, "mode", "show untracked files, optional modes: all, normal, no. (Default: all)", PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
 	OPT_BOOLEAN(0, "allow-empty", &allow_empty, "ok to record an empty change"),
 	OPT_STRING(0, "cleanup", &cleanup_arg, "default", "how to strip spaces and #comments from message"),
 
@@ -148,7 +149,7 @@
  * Take a union of paths in the index and the named tree (typically, "HEAD"),
  * and return the paths that match the given pattern in list.
  */
-static int list_paths(struct path_list *list, const char *with_tree,
+static int list_paths(struct string_list *list, const char *with_tree,
 		      const char *prefix, const char **pattern)
 {
 	int i;
@@ -167,24 +168,24 @@
 			continue;
 		if (!pathspec_match(pattern, m, ce->name, 0))
 			continue;
-		path_list_insert(ce->name, list);
+		string_list_insert(ce->name, list);
 	}
 
 	return report_path_error(m, pattern, prefix ? strlen(prefix) : 0);
 }
 
-static void add_remove_files(struct path_list *list)
+static void add_remove_files(struct string_list *list)
 {
 	int i;
 	for (i = 0; i < list->nr; i++) {
 		struct stat st;
-		struct path_list_item *p = &(list->items[i]);
+		struct string_list_item *p = &(list->items[i]);
 
-		if (!lstat(p->path, &st)) {
-			if (add_to_cache(p->path, &st, 0))
+		if (!lstat(p->string, &st)) {
+			if (add_to_cache(p->string, &st, 0))
 				die("updating files failed");
 		} else
-			remove_file_from_cache(p->path);
+			remove_file_from_cache(p->string);
 	}
 }
 
@@ -219,7 +220,7 @@
 static char *prepare_index(int argc, const char **argv, const char *prefix)
 {
 	int fd;
-	struct path_list partial;
+	struct string_list partial;
 	const char **pathspec = NULL;
 
 	if (interactive) {
@@ -303,7 +304,7 @@
 		die("cannot do a partial commit during a merge.");
 
 	memset(&partial, 0, sizeof(partial));
-	partial.strdup_paths = 1;
+	partial.strdup_strings = 1;
 	if (list_paths(&partial, initial_commit ? NULL : "HEAD", prefix, pathspec))
 		exit(1);
 
@@ -319,7 +320,8 @@
 		die("unable to write new_index file");
 
 	fd = hold_lock_file_for_update(&false_lock,
-				       git_path("next-index-%d", getpid()), 1);
+				       git_path("next-index-%d", getpid()),
+				       LOCK_DIE_ON_ERROR);
 
 	create_base_index();
 	add_remove_files(&partial);
@@ -348,7 +350,7 @@
 		s.reference = "HEAD^1";
 	}
 	s.verbose = verbose;
-	s.untracked = untracked_files;
+	s.untracked = (show_untracked_files == SHOW_ALL_UNTRACKED_FILES);
 	s.index_file = index_file;
 	s.fp = fp;
 	s.nowarn = nowarn;
@@ -503,7 +505,8 @@
 
 	fp = fopen(git_path(commit_editmsg), "w");
 	if (fp == NULL)
-		die("could not open %s", git_path(commit_editmsg));
+		die("could not open %s: %s",
+		    git_path(commit_editmsg), strerror(errno));
 
 	if (cleanup_mode != CLEANUP_NONE)
 		stripspace(&sb, 0);
@@ -552,13 +555,18 @@
 
 		fprintf(fp,
 			"\n"
-			"# Please enter the commit message for your changes.\n"
-			"# (Comment lines starting with '#' will ");
+			"# Please enter the commit message for your changes.");
 		if (cleanup_mode == CLEANUP_ALL)
-			fprintf(fp, "not be included)\n");
+			fprintf(fp,
+				" Lines starting\n"
+				"# with '#' will be ignored, and an empty"
+				" message aborts the commit.\n");
 		else /* CLEANUP_SPACE, that is. */
-			fprintf(fp, "be kept.\n"
-				"# You can remove them yourself if you want to)\n");
+			fprintf(fp,
+				" Lines starting\n"
+				"# with '#' will be kept; you may remove them"
+				" yourself if you want to.\n"
+				"# An empty message aborts the commit.\n");
 		if (only_include_assumed)
 			fprintf(fp, "# %s\n", only_include_assumed);
 
@@ -632,7 +640,7 @@
 		active_cache_tree = cache_tree();
 	if (cache_tree_update(active_cache_tree,
 			      active_cache, active_nr, 0, 0) < 0) {
-		error("Error building trees");
+		error("Error building trees; the index is unmerged?");
 		return 0;
 	}
 
@@ -644,7 +652,11 @@
 		char index[PATH_MAX];
 		const char *env[2] = { index, NULL };
 		snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", index_file);
-		launch_editor(git_path(commit_editmsg), NULL, env);
+		if (launch_editor(git_path(commit_editmsg), NULL, env)) {
+			fprintf(stderr,
+			"Please supply the message using either -m or -F option.\n");
+			exit(1);
+		}
 	}
 
 	if (!no_verify &&
@@ -799,6 +811,17 @@
 	else
 		die("Invalid cleanup mode %s", cleanup_arg);
 
+	if (!untracked_files_arg)
+		; /* default already initialized */
+	else if (!strcmp(untracked_files_arg, "no"))
+		show_untracked_files = SHOW_NO_UNTRACKED_FILES;
+	else if (!strcmp(untracked_files_arg, "normal"))
+		show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
+	else if (!strcmp(untracked_files_arg, "all"))
+		show_untracked_files = SHOW_ALL_UNTRACKED_FILES;
+	else
+		die("Invalid untracked files mode '%s'", untracked_files_arg);
+
 	if (all && argc > 0)
 		die("Paths with -a does not make sense.");
 	else if (interactive && argc > 0)
@@ -860,13 +883,13 @@
 
 	if (!log_tree_commit(&rev, commit)) {
 		struct strbuf buf = STRBUF_INIT;
-		format_commit_message(commit, "%h: %s", &buf);
+		format_commit_message(commit, "%h: %s", &buf, DATE_NORMAL);
 		printf("%s\n", buf.buf);
 		strbuf_release(&buf);
 	}
 }
 
-int git_commit_config(const char *k, const char *v, void *cb)
+static int git_commit_config(const char *k, const char *v, void *cb)
 {
 	if (!strcmp(k, "commit.template"))
 		return git_config_string(&template_file, k, v);
@@ -981,15 +1004,18 @@
 	}
 
 	/* Truncate the message just before the diff, if any. */
-	p = strstr(sb.buf, "\ndiff --git a/");
-	if (p != NULL)
-		strbuf_setlen(&sb, p - sb.buf + 1);
+	if (verbose) {
+		p = strstr(sb.buf, "\ndiff --git ");
+		if (p != NULL)
+			strbuf_setlen(&sb, p - sb.buf + 1);
+	}
 
 	if (cleanup_mode != CLEANUP_NONE)
 		stripspace(&sb, cleanup_mode == CLEANUP_ALL);
 	if (sb.len < header_len || message_is_empty(&sb, header_len)) {
 		rollback_index_files();
-		die("no commit message?  aborting commit.");
+		fprintf(stderr, "Aborting commit due to empty commit message.\n");
+		exit(1);
 	}
 	strbuf_addch(&sb, '\0');
 	if (is_encoding_utf8(git_commit_encoding) && !is_utf8(sb.buf))
diff --git a/builtin-config.c b/builtin-config.c
index 3a441ef..f710162 100644
--- a/builtin-config.c
+++ b/builtin-config.c
@@ -3,7 +3,7 @@
 #include "color.h"
 
 static const char git_config_set_usage[] =
-"git-config [ --global | --system | [ -f | --file ] config-file ] [ --bool | --int | --bool-or-int ] [ -z | --null ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --remove-section name | --list | --get-color var [default] | --get-colorbool name [stdout-is-tty]";
+"git config [ --global | --system | [ -f | --file ] config-file ] [ --bool | --int | --bool-or-int ] [ -z | --null ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --remove-section name | --list | --get-color var [default] | --get-colorbool name [stdout-is-tty]";
 
 static char *key;
 static regex_t *key_regexp;
@@ -81,12 +81,10 @@
 	char *global = NULL, *repo_config = NULL;
 	const char *system_wide = NULL, *local;
 
-	local = getenv(CONFIG_ENVIRONMENT);
+	local = config_exclusive_filename;
 	if (!local) {
 		const char *home = getenv("HOME");
-		local = getenv(CONFIG_LOCAL_ENVIRONMENT);
-		if (!local)
-			local = repo_config = xstrdup(git_path("config"));
+		local = repo_config = git_pathdup("config");
 		if (git_config_global() && home)
 			global = xstrdup(mkpath("%s/.gitconfig", home));
 		if (git_config_system())
@@ -147,7 +145,7 @@
 	return ret;
 }
 
-char *normalize_value(const char *key, const char *value)
+static char *normalize_value(const char *key, const char *value)
 {
 	char *normalized;
 
@@ -289,6 +287,8 @@
 	char* value;
 	const char *file = setup_git_directory_gently(&nongit);
 
+	config_exclusive_filename = getenv(CONFIG_ENVIRONMENT);
+
 	while (1 < argc) {
 		if (!strcmp(argv[1], "--int"))
 			type = T_INT;
@@ -309,14 +309,13 @@
 			char *home = getenv("HOME");
 			if (home) {
 				char *user_config = xstrdup(mkpath("%s/.gitconfig", home));
-				setenv(CONFIG_ENVIRONMENT, user_config, 1);
-				free(user_config);
+				config_exclusive_filename = user_config;
 			} else {
 				die("$HOME not set");
 			}
 		}
 		else if (!strcmp(argv[1], "--system"))
-			setenv(CONFIG_ENVIRONMENT, git_etc_gitconfig(), 1);
+			config_exclusive_filename = git_etc_gitconfig();
 		else if (!strcmp(argv[1], "--file") || !strcmp(argv[1], "-f")) {
 			if (argc < 3)
 				usage(git_config_set_usage);
@@ -325,7 +324,7 @@
 						       argv[2]);
 			else
 				file = argv[2];
-			setenv(CONFIG_ENVIRONMENT, file, 1);
+			config_exclusive_filename = file;
 			argc--;
 			argv++;
 		}
diff --git a/builtin-count-objects.c b/builtin-count-objects.c
index f00306f..91b5487 100644
--- a/builtin-count-objects.c
+++ b/builtin-count-objects.c
@@ -67,7 +67,7 @@
 }
 
 static char const * const count_objects_usage[] = {
-	"git-count-objects [-v]",
+	"git count-objects [-v]",
 	NULL
 };
 
diff --git a/builtin-describe.c b/builtin-describe.c
index e515f9c..ec404c8 100644
--- a/builtin-describe.c
+++ b/builtin-describe.c
@@ -10,7 +10,7 @@
 #define MAX_TAGS	(FLAG_BITS - 1)
 
 static const char * const describe_usage[] = {
-	"git-describe [options] <committish>*",
+	"git describe [options] <committish>*",
 	NULL
 };
 
@@ -20,7 +20,7 @@
 static int longformat;
 static int abbrev = DEFAULT_ABBREV;
 static int max_candidates = 10;
-const char *pattern = NULL;
+static const char *pattern;
 static int always;
 
 struct commit_name {
diff --git a/builtin-diff-files.c b/builtin-diff-files.c
index 384d871..2b578c7 100644
--- a/builtin-diff-files.c
+++ b/builtin-diff-files.c
@@ -10,7 +10,7 @@
 #include "builtin.h"
 
 static const char diff_files_usage[] =
-"git-diff-files [-q] [-0/-1/2/3 |-c|--cc] [<common diff options>] [<path>...]"
+"git diff-files [-q] [-0/-1/2/3 |-c|--cc] [<common diff options>] [<path>...]"
 COMMON_DIFF_OPTIONS_HELP;
 
 int cmd_diff_files(int argc, const char **argv, const char *prefix)
@@ -50,7 +50,12 @@
 	    3 < rev.max_count)
 		usage(diff_files_usage);
 
-	if (rev.max_count == -1 &&
+	/*
+	 * "diff-files --base -p" should not combine merges because it
+	 * was not asked to.  "diff-files -c -p" should not densify
+	 * (the user should ask with "diff-files --cc" explicitly).
+	 */
+	if (rev.max_count == -1 && !rev.combine_merges &&
 	    (rev.diffopt.output_format & DIFF_FORMAT_PATCH))
 		rev.combine_merges = rev.dense_combined_merges = 1;
 
diff --git a/builtin-diff-index.c b/builtin-diff-index.c
index 2f44ebf..0483749 100644
--- a/builtin-diff-index.c
+++ b/builtin-diff-index.c
@@ -5,7 +5,7 @@
 #include "builtin.h"
 
 static const char diff_cache_usage[] =
-"git-diff-index [-m] [--cached] "
+"git diff-index [-m] [--cached] "
 "[<common diff options>] <tree-ish> [<path>...]"
 COMMON_DIFF_OPTIONS_HELP;
 
@@ -39,6 +39,8 @@
 	if (rev.pending.nr != 1 ||
 	    rev.max_count != -1 || rev.min_age != -1 || rev.max_age != -1)
 		usage(diff_cache_usage);
+	if (!cached)
+		setup_work_tree();
 	if (read_cache() < 0) {
 		perror("read_cache");
 		return -1;
diff --git a/builtin-diff-tree.c b/builtin-diff-tree.c
index 9d2a48f..415cb16 100644
--- a/builtin-diff-tree.c
+++ b/builtin-diff-tree.c
@@ -53,7 +53,7 @@
 }
 
 static const char diff_tree_usage[] =
-"git-diff-tree [--stdin] [-m] [-c] [--cc] [-s] [-v] [--pretty] [-t] [-r] [--root] "
+"git diff-tree [--stdin] [-m] [-c] [--cc] [-s] [-v] [--pretty] [-t] [-r] [--root] "
 "[<common diff options>] <tree-ish> [<tree-ish>] [<path>...]\n"
 "  -r            diff recursively\n"
 "  --root        include the initial commit as diff against /dev/null\n"
diff --git a/builtin-diff.c b/builtin-diff.c
index 4c289e7..375a0d3 100644
--- a/builtin-diff.c
+++ b/builtin-diff.c
@@ -21,7 +21,7 @@
 };
 
 static const char builtin_diff_usage[] =
-"git-diff <options> <rev>{0,2} -- <path>*";
+"git diff <options> <rev>{0,2} -- <path>*";
 
 static void stuff_change(struct diff_options *opt,
 			 unsigned old_mode, unsigned new_mode,
@@ -122,6 +122,8 @@
 			usage(builtin_diff_usage);
 		argv++; argc--;
 	}
+	if (!cached)
+		setup_work_tree();
 	/*
 	 * Make sure there is one revision (i.e. pending object),
 	 * and there is no revision filtering parameters.
@@ -173,10 +175,8 @@
 	if (!revs->dense_combined_merges && !revs->combine_merges)
 		revs->dense_combined_merges = revs->combine_merges = 1;
 	parent = xmalloc(ents * sizeof(*parent));
-	/* Again, the revs are all reverse */
 	for (i = 0; i < ents; i++)
-		hashcpy((unsigned char *)(parent + i),
-			ent[ents - 1 - i].item->sha1);
+		hashcpy((unsigned char *)(parent + i), ent[i].item->sha1);
 	diff_tree_combined(parent[0], parent + 1, ents - 1,
 			   revs->dense_combined_merges, revs);
 	return 0;
@@ -221,10 +221,17 @@
 		argv++; argc--;
 	}
 
-	if (revs->max_count == -1 &&
+	/*
+	 * "diff --base" should not combine merges because it was not
+	 * asked to.  "diff -c" should not densify (if the user wants
+	 * dense one, --cc can be explicitly asked for, or just rely
+	 * on the default).
+	 */
+	if (revs->max_count == -1 && !revs->combine_merges &&
 	    (revs->diffopt.output_format & DIFF_FORMAT_PATCH))
 		revs->combine_merges = revs->dense_combined_merges = 1;
 
+	setup_work_tree();
 	if (read_cache() < 0) {
 		perror("read_cache");
 		return -1;
@@ -281,6 +288,9 @@
 	/* Otherwise, we are doing the usual "git" diff */
 	rev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index;
 
+	/* Default to let external be used */
+	DIFF_OPT_SET(&rev.diffopt, ALLOW_EXTERNAL);
+
 	if (nongit)
 		die("Not a git repository");
 	argc = setup_revisions(argc, argv, &rev, NULL);
@@ -289,14 +299,15 @@
 		if (diff_setup_done(&rev.diffopt) < 0)
 			die("diff_setup_done failed");
 	}
-	DIFF_OPT_SET(&rev.diffopt, ALLOW_EXTERNAL);
+
 	DIFF_OPT_SET(&rev.diffopt, RECURSIVE);
 
 	/*
 	 * If the user asked for our exit code then don't start a
 	 * pager or we would end up reporting its exit code instead.
 	 */
-	if (!DIFF_OPT_TST(&rev.diffopt, EXIT_WITH_STATUS))
+	if (!DIFF_OPT_TST(&rev.diffopt, EXIT_WITH_STATUS) &&
+	    check_pager_config("diff") != 0)
 		setup_pager();
 
 	/*
diff --git a/builtin-fast-export.c b/builtin-fast-export.c
index d0a462f..8386338 100644
--- a/builtin-fast-export.c
+++ b/builtin-fast-export.c
@@ -13,17 +13,18 @@
 #include "log-tree.h"
 #include "revision.h"
 #include "decorate.h"
-#include "path-list.h"
+#include "string-list.h"
 #include "utf8.h"
 #include "parse-options.h"
 
 static const char *fast_export_usage[] = {
-	"git-fast-export [rev-list-opts]",
+	"git fast-export [rev-list-opts]",
 	NULL
 };
 
 static int progress;
 static enum { VERBATIM, WARN, STRIP, ABORT } signed_tag_mode = ABORT;
+static int fake_missing_tagger;
 
 static int parse_opt_signed_tag_mode(const struct option *opt,
 				     const char *arg, int unset)
@@ -56,10 +57,24 @@
 }
 
 /* Since intptr_t is C99, we do not use it here */
-static void mark_object(struct object *object)
+static inline uint32_t *mark_to_ptr(uint32_t mark)
 {
-	last_idnum++;
-	add_decoration(&idnums, object, ((uint32_t *)NULL) + last_idnum);
+	return ((uint32_t *)NULL) + mark;
+}
+
+static inline uint32_t ptr_to_mark(void * mark)
+{
+	return (uint32_t *)mark - (uint32_t *)NULL;
+}
+
+static inline void mark_object(struct object *object, uint32_t mark)
+{
+	add_decoration(&idnums, object, mark_to_ptr(mark));
+}
+
+static inline void mark_next_object(struct object *object)
+{
+	mark_object(object, ++last_idnum);
 }
 
 static int get_object_mark(struct object *object)
@@ -67,7 +82,7 @@
 	void *decoration = lookup_decoration(&idnums, object);
 	if (!decoration)
 		return 0;
-	return (uint32_t *)decoration - (uint32_t *)NULL;
+	return ptr_to_mark(decoration);
 }
 
 static void show_progress(void)
@@ -100,9 +115,9 @@
 	if (!buf)
 		die ("Could not read blob %s", sha1_to_hex(sha1));
 
-	mark_object(object);
+	mark_next_object(object);
 
-	printf("blob\nmark :%d\ndata %lu\n", last_idnum, size);
+	printf("blob\nmark :%"PRIu32"\ndata %lu\n", last_idnum, size);
 	if (size && fwrite(buf, size, 1, stdout) != 1)
 		die ("Could not write blob %s", sha1_to_hex(sha1));
 	printf("\n");
@@ -118,13 +133,46 @@
 {
 	int i;
 	for (i = 0; i < q->nr; i++) {
+		struct diff_filespec *ospec = q->queue[i]->one;
 		struct diff_filespec *spec = q->queue[i]->two;
-		if (is_null_sha1(spec->sha1))
+
+		switch (q->queue[i]->status) {
+		case DIFF_STATUS_DELETED:
 			printf("D %s\n", spec->path);
-		else {
-			struct object *object = lookup_object(spec->sha1);
-			printf("M %06o :%d %s\n", spec->mode,
-			       get_object_mark(object), spec->path);
+			break;
+
+		case DIFF_STATUS_COPIED:
+		case DIFF_STATUS_RENAMED:
+			printf("%c \"%s\" \"%s\"\n", q->queue[i]->status,
+			       ospec->path, spec->path);
+
+			if (!hashcmp(ospec->sha1, spec->sha1) &&
+			    ospec->mode == spec->mode)
+				break;
+			/* fallthrough */
+
+		case DIFF_STATUS_TYPE_CHANGED:
+		case DIFF_STATUS_MODIFIED:
+		case DIFF_STATUS_ADDED:
+			/*
+			 * Links refer to objects in another repositories;
+			 * output the SHA-1 verbatim.
+			 */
+			if (S_ISGITLINK(spec->mode))
+				printf("M %06o %s %s\n", spec->mode,
+				       sha1_to_hex(spec->sha1), spec->path);
+			else {
+				struct object *object = lookup_object(spec->sha1);
+				printf("M %06o :%d %s\n", spec->mode,
+				       get_object_mark(object), spec->path);
+			}
+			break;
+
+		default:
+			die("Unexpected comparison status '%c' for %s, %s",
+				q->queue[i]->status,
+				ospec->path ? ospec->path : "none",
+				spec->path ? spec->path : "none");
 		}
 	}
 }
@@ -182,15 +230,17 @@
 		diff_root_tree_sha1(commit->tree->object.sha1,
 				    "", &rev->diffopt);
 
+	/* Export the referenced blobs, and remember the marks. */
 	for (i = 0; i < diff_queued_diff.nr; i++)
-		handle_object(diff_queued_diff.queue[i]->two->sha1);
+		if (!S_ISGITLINK(diff_queued_diff.queue[i]->two->mode))
+			handle_object(diff_queued_diff.queue[i]->two->sha1);
 
-	mark_object(&commit->object);
+	mark_next_object(&commit->object);
 	if (!is_encoding_utf8(encoding))
 		reencoded = reencode_string(message, "UTF-8", encoding);
 	if (!commit->parents)
 		printf("reset %s\n", (const char*)commit->util);
-	printf("commit %s\nmark :%d\n%.*s\n%.*s\ndata %u\n%s",
+	printf("commit %s\nmark :%"PRIu32"\n%.*s\n%.*s\ndata %u\n%s",
 	       (const char *)commit->util, last_idnum,
 	       (int)(author_end - author), author,
 	       (int)(committer_end - committer), committer,
@@ -248,10 +298,17 @@
 		message_size = strlen(message);
 	}
 	tagger = memmem(buf, message ? message - buf : size, "\ntagger ", 8);
-	if (!tagger)
-		die ("No tagger for tag %s", sha1_to_hex(tag->object.sha1));
-	tagger++;
-	tagger_end = strchrnul(tagger, '\n');
+	if (!tagger) {
+		if (fake_missing_tagger)
+			tagger = "tagger Unspecified Tagger "
+				"<unspecified-tagger> 0 +0000";
+		else
+			tagger = "";
+		tagger_end = tagger + strlen(tagger);
+	} else {
+		tagger++;
+		tagger_end = strchrnul(tagger, '\n');
+	}
 
 	/* handle signed tags */
 	if (message) {
@@ -277,14 +334,15 @@
 
 	if (!prefixcmp(name, "refs/tags/"))
 		name += 10;
-	printf("tag %s\nfrom :%d\n%.*s\ndata %d\n%.*s\n",
+	printf("tag %s\nfrom :%d\n%.*s%sdata %d\n%.*s\n",
 	       name, get_object_mark(tag->tagged),
 	       (int)(tagger_end - tagger), tagger,
+	       tagger == tagger_end ? "" : "\n",
 	       (int)message_size, (int)message_size, message ? message : "");
 }
 
 static void get_tags_and_duplicates(struct object_array *pending,
-				    struct path_list *extra_refs)
+				    struct string_list *extra_refs)
 {
 	struct tag *tag;
 	int i;
@@ -305,7 +363,7 @@
 		case OBJ_TAG:
 			tag = (struct tag *)e->item;
 			while (tag && tag->object.type == OBJ_TAG) {
-				path_list_insert(full_name, extra_refs)->util = tag;
+				string_list_append(full_name, extra_refs)->util = tag;
 				tag = (struct tag *)tag->tagged;
 			}
 			if (!tag)
@@ -325,19 +383,19 @@
 		}
 		if (commit->util)
 			/* more than one name for the same object */
-			path_list_insert(full_name, extra_refs)->util = commit;
+			string_list_append(full_name, extra_refs)->util = commit;
 		else
 			commit->util = full_name;
 	}
 }
 
-static void handle_tags_and_duplicates(struct path_list *extra_refs)
+static void handle_tags_and_duplicates(struct string_list *extra_refs)
 {
 	struct commit *commit;
 	int i;
 
 	for (i = extra_refs->nr - 1; i >= 0; i--) {
-		const char *name = extra_refs->items[i].path;
+		const char *name = extra_refs->items[i].string;
 		struct object *object = extra_refs->items[i].util;
 		switch (object->type) {
 		case OBJ_TAG:
@@ -354,18 +412,88 @@
 	}
 }
 
+static void export_marks(char *file)
+{
+	unsigned int i;
+	uint32_t mark;
+	struct object_decoration *deco = idnums.hash;
+	FILE *f;
+
+	f = fopen(file, "w");
+	if (!f)
+		error("Unable to open marks file %s for writing", file);
+
+	for (i = 0; i < idnums.size; i++) {
+		if (deco->base && deco->base->type == 1) {
+			mark = ptr_to_mark(deco->decoration);
+			fprintf(f, ":%"PRIu32" %s\n", mark,
+				sha1_to_hex(deco->base->sha1));
+		}
+		deco++;
+	}
+
+	if (ferror(f) || fclose(f))
+		error("Unable to write marks file %s.", file);
+}
+
+static void import_marks(char *input_file)
+{
+	char line[512];
+	FILE *f = fopen(input_file, "r");
+	if (!f)
+		die("cannot read %s: %s", input_file, strerror(errno));
+
+	while (fgets(line, sizeof(line), f)) {
+		uint32_t mark;
+		char *line_end, *mark_end;
+		unsigned char sha1[20];
+		struct object *object;
+
+		line_end = strchr(line, '\n');
+		if (line[0] != ':' || !line_end)
+			die("corrupt mark line: %s", line);
+		*line_end = '\0';
+
+		mark = strtoumax(line + 1, &mark_end, 10);
+		if (!mark || mark_end == line + 1
+			|| *mark_end != ' ' || get_sha1(mark_end + 1, sha1))
+			die("corrupt mark line: %s", line);
+
+		object = parse_object(sha1);
+		if (!object)
+			die ("Could not read blob %s", sha1_to_hex(sha1));
+
+		if (object->flags & SHOWN)
+			error("Object %s already has a mark", sha1);
+
+		mark_object(object, mark);
+		if (last_idnum < mark)
+			last_idnum = mark;
+
+		object->flags |= SHOWN;
+	}
+	fclose(f);
+}
+
 int cmd_fast_export(int argc, const char **argv, const char *prefix)
 {
 	struct rev_info revs;
 	struct object_array commits = { 0, 0, NULL };
-	struct path_list extra_refs = { NULL, 0, 0, 0 };
+	struct string_list extra_refs = { NULL, 0, 0, 0 };
 	struct commit *commit;
+	char *export_filename = NULL, *import_filename = NULL;
 	struct option options[] = {
 		OPT_INTEGER(0, "progress", &progress,
 			    "show progress after <n> objects"),
 		OPT_CALLBACK(0, "signed-tags", &signed_tag_mode, "mode",
 			     "select handling of signed tags",
 			     parse_opt_signed_tag_mode),
+		OPT_STRING(0, "export-marks", &export_filename, "FILE",
+			     "Dump marks to this file"),
+		OPT_STRING(0, "import-marks", &import_filename, "FILE",
+			     "Import marks from this file"),
+		OPT_BOOLEAN(0, "fake-missing-tagger", &fake_missing_tagger,
+			     "Fake a tagger when tags lack one"),
 		OPT_END()
 	};
 
@@ -378,6 +506,9 @@
 	if (argc > 1)
 		usage_with_options (fast_export_usage, options);
 
+	if (import_filename)
+		import_marks(import_filename);
+
 	get_tags_and_duplicates(&revs.pending, &extra_refs);
 
 	if (prepare_revision_walk(&revs))
@@ -400,5 +531,8 @@
 
 	handle_tags_and_duplicates(&extra_refs);
 
+	if (export_filename)
+		export_marks(export_filename);
+
 	return 0;
 }
diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c
index 6e98caf..22a5712 100644
--- a/builtin-fetch-pack.c
+++ b/builtin-fetch-pack.c
@@ -18,7 +18,7 @@
 };
 
 static const char fetch_pack_usage[] =
-"git-fetch-pack [--all] [--quiet|-q] [--keep|-k] [--thin] [--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] [--no-progress] [-v] [<host>:]<directory> [<refs>...]";
+"git fetch-pack [--all] [--quiet|-q] [--keep|-k] [--thin] [--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] [--no-progress] [-v] [<host>:]<directory> [<refs>...]";
 
 #define COMPLETE	(1U << 0)
 #define COMMON		(1U << 1)
@@ -520,7 +520,8 @@
 
 		if (read_pack_header(demux.out, &header))
 			die("protocol error: bad pack header");
-		snprintf(hdr_arg, sizeof(hdr_arg), "--pack_header=%u,%u",
+		snprintf(hdr_arg, sizeof(hdr_arg),
+			 "--pack_header=%"PRIu32",%"PRIu32,
 			 ntohl(header.hdr_version), ntohl(header.hdr_entries));
 		if (ntohl(header.hdr_entries) < unpack_limit)
 			do_keep = 0;
@@ -608,7 +609,7 @@
 			fprintf(stderr, "warning: no common commits\n");
 
 	if (get_pack(fd, pack_lockfile))
-		die("git-fetch-pack: fetch failed.");
+		die("git fetch-pack: fetch failed.");
 
  all_done:
 	return ref;
@@ -749,7 +750,7 @@
 	if (!ret && nr_heads) {
 		/* If the heads to pull were given, we should have
 		 * consumed all of them by matching the remote.
-		 * Otherwise, 'git-fetch remote no-such-ref' would
+		 * Otherwise, 'git fetch remote no-such-ref' would
 		 * silently succeed without issuing an error.
 		 */
 		for (i = 0; i < nr_heads; i++)
@@ -779,7 +780,8 @@
 	struct ref *ref_cpy;
 
 	fetch_pack_setup();
-	memcpy(&args, my_args, sizeof(args));
+	if (&args != my_args)
+		memcpy(&args, my_args, sizeof(args));
 	if (args.depth > 0) {
 		if (stat(git_path("shallow"), &st))
 			st.st_mtime = 0;
@@ -812,7 +814,8 @@
 			  )
 			die("shallow file was changed during fetch");
 
-		fd = hold_lock_file_for_update(&lock, shallow, 1);
+		fd = hold_lock_file_for_update(&lock, shallow,
+					       LOCK_DIE_ON_ERROR);
 		if (!write_shallow_commits(fd, 0)) {
 			unlink(shallow);
 			rollback_lock_file(&lock);
@@ -821,5 +824,6 @@
 		}
 	}
 
+	reprepare_packed_git();
 	return ref_cpy;
 }
diff --git a/builtin-fetch.c b/builtin-fetch.c
index 97fdc51..57c161d 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -5,14 +5,14 @@
 #include "refs.h"
 #include "commit.h"
 #include "builtin.h"
-#include "path-list.h"
+#include "string-list.h"
 #include "remote.h"
 #include "transport.h"
 #include "run-command.h"
 #include "parse-options.h"
 
 static const char * const builtin_fetch_usage[] = {
-	"git-fetch [options] [<repository> <refspec>...]",
+	"git fetch [options] [<repository> <refspec>...]",
 	NULL
 };
 
@@ -86,10 +86,10 @@
 		/*
 		 * Not fetched to a tracking branch?  We need to fetch
 		 * it anyway to allow this branch's "branch.$name.merge"
-		 * to be honored by git-pull, but we do not have to
+		 * to be honored by 'git pull', but we do not have to
 		 * fail if branch.$name.merge is misconfigured to point
 		 * at a nonexisting branch.  If we were indeed called by
-		 * git-pull, it will notice the misconfiguration because
+		 * 'git pull', it will notice the misconfiguration because
 		 * there is no entry in the resulting FETCH_HEAD marked
 		 * for merging.
 		 */
@@ -396,7 +396,7 @@
  * The refs we are going to fetch are in to_fetch (nr_heads in
  * total).  If running
  *
- *  $ git-rev-list --objects to_fetch[0] to_fetch[1] ... --not --all
+ *  $ git rev-list --objects to_fetch[0] to_fetch[1] ... --not --all
  *
  * does not error out, that means everything reachable from the
  * refs we are going to fetch exists and is connected to some of
@@ -465,8 +465,8 @@
 static int add_existing(const char *refname, const unsigned char *sha1,
 			int flag, void *cbdata)
 {
-	struct path_list *list = (struct path_list *)cbdata;
-	path_list_insert(refname, list);
+	struct string_list *list = (struct string_list *)cbdata;
+	string_list_insert(refname, list);
 	return 0;
 }
 
@@ -485,8 +485,8 @@
 			struct ref **head,
 			struct ref ***tail)
 {
-	struct path_list existing_refs = { NULL, 0, 0, 0 };
-	struct path_list new_refs = { NULL, 0, 0, 1 };
+	struct string_list existing_refs = { NULL, 0, 0, 0 };
+	struct string_list new_refs = { NULL, 0, 0, 1 };
 	char *ref_name;
 	int ref_name_len;
 	const unsigned char *ref_sha1;
@@ -515,11 +515,11 @@
 			}
 		}
 
-		if (!path_list_has_path(&existing_refs, ref_name) &&
-		    !path_list_has_path(&new_refs, ref_name) &&
+		if (!string_list_has_string(&existing_refs, ref_name) &&
+		    !string_list_has_string(&new_refs, ref_name) &&
 		    (has_sha1_file(ref->old_sha1) ||
 		     will_fetch(head, ref->old_sha1))) {
-			path_list_insert(ref_name, &new_refs);
+			string_list_insert(ref_name, &new_refs);
 
 			rm = alloc_ref_from_str(ref_name);
 			rm->peer_ref = alloc_ref_from_str(ref_name);
@@ -530,8 +530,21 @@
 		}
 		free(ref_name);
 	}
-	path_list_clear(&existing_refs, 0);
-	path_list_clear(&new_refs, 0);
+	string_list_clear(&existing_refs, 0);
+	string_list_clear(&new_refs, 0);
+}
+
+static void check_not_current_branch(struct ref *ref_map)
+{
+	struct branch *current_branch = branch_get(NULL);
+
+	if (is_bare_repository() || !current_branch)
+		return;
+
+	for (; ref_map; ref_map = ref_map->next)
+		if (ref_map->peer_ref && !strcmp(current_branch->refname,
+					ref_map->peer_ref->name))
+			die("Refusing to fetch into current branch");
 }
 
 static int do_fetch(struct transport *transport,
@@ -558,6 +571,8 @@
 	}
 
 	ref_map = get_ref_map(transport, refs, ref_count, tags, &autotags);
+	if (!update_head_ok)
+		check_not_current_branch(ref_map);
 
 	for (rm = ref_map; rm; rm = rm->next) {
 		if (rm->peer_ref)
diff --git a/builtin-fmt-merge-msg.c b/builtin-fmt-merge-msg.c
index b892621..df02ba7 100644
--- a/builtin-fmt-merge-msg.c
+++ b/builtin-fmt-merge-msg.c
@@ -6,7 +6,7 @@
 #include "tag.h"
 
 static const char *fmt_merge_msg_usage =
-	"git-fmt-merge-msg [--log] [--no-log] [--file <file>]";
+	"git fmt-merge-msg [--log] [--no-log] [--file <file>]";
 
 static int merge_summary;
 
@@ -159,23 +159,24 @@
 }
 
 static void print_joined(const char *singular, const char *plural,
-		struct list *list)
+		struct list *list, struct strbuf *out)
 {
 	if (list->nr == 0)
 		return;
 	if (list->nr == 1) {
-		printf("%s%s", singular, list->list[0]);
+		strbuf_addf(out, "%s%s", singular, list->list[0]);
 	} else {
 		int i;
-		printf("%s", plural);
+		strbuf_addstr(out, plural);
 		for (i = 0; i < list->nr - 1; i++)
-			printf("%s%s", i > 0 ? ", " : "", list->list[i]);
-		printf(" and %s", list->list[list->nr - 1]);
+			strbuf_addf(out, "%s%s", i > 0 ? ", " : "", list->list[i]);
+		strbuf_addf(out, " and %s", list->list[list->nr - 1]);
 	}
 }
 
 static void shortlog(const char *name, unsigned char *sha1,
-		struct commit *head, struct rev_info *rev, int limit)
+		struct commit *head, struct rev_info *rev, int limit,
+		struct strbuf *out)
 {
 	int i, count = 0;
 	struct commit *commit;
@@ -232,15 +233,15 @@
 	}
 
 	if (count > limit)
-		printf("\n* %s: (%d commits)\n", name, count);
+		strbuf_addf(out, "\n* %s: (%d commits)\n", name, count);
 	else
-		printf("\n* %s:\n", name);
+		strbuf_addf(out, "\n* %s:\n", name);
 
 	for (i = 0; i < subjects.nr; i++)
 		if (i >= limit)
-			printf("  ...\n");
+			strbuf_addf(out, "  ...\n");
 		else
-			printf("  %s\n", subjects.list[i]);
+			strbuf_addf(out, "  %s\n", subjects.list[i]);
 
 	clear_commit_marks((struct commit *)branch, flags);
 	clear_commit_marks(head, flags);
@@ -251,15 +252,105 @@
 	free_list(&subjects);
 }
 
-int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
-{
-	int limit = 20, i = 0;
+int fmt_merge_msg(int merge_summary, struct strbuf *in, struct strbuf *out) {
+	int limit = 20, i = 0, pos = 0;
 	char line[1024];
-	FILE *in = stdin;
-	const char *sep = "";
+	char *p = line, *sep = "";
 	unsigned char head_sha1[20];
 	const char *current_branch;
 
+	/* get current branch */
+	current_branch = resolve_ref("HEAD", head_sha1, 1, NULL);
+	if (!current_branch)
+		die("No current branch");
+	if (!prefixcmp(current_branch, "refs/heads/"))
+		current_branch += 11;
+
+	/* get a line */
+	while (pos < in->len) {
+		int len;
+		char *newline;
+
+		p = in->buf + pos;
+		newline = strchr(p, '\n');
+		len = newline ? newline - p : strlen(p);
+		pos += len + !!newline;
+		i++;
+		p[len] = 0;
+		if (handle_line(p))
+			die ("Error in line %d: %.*s", i, len, p);
+	}
+
+	strbuf_addstr(out, "Merge ");
+	for (i = 0; i < srcs.nr; i++) {
+		struct src_data *src_data = srcs.payload[i];
+		const char *subsep = "";
+
+		strbuf_addstr(out, sep);
+		sep = "; ";
+
+		if (src_data->head_status == 1) {
+			strbuf_addstr(out, srcs.list[i]);
+			continue;
+		}
+		if (src_data->head_status == 3) {
+			subsep = ", ";
+			strbuf_addstr(out, "HEAD");
+		}
+		if (src_data->branch.nr) {
+			strbuf_addstr(out, subsep);
+			subsep = ", ";
+			print_joined("branch ", "branches ", &src_data->branch,
+					out);
+		}
+		if (src_data->r_branch.nr) {
+			strbuf_addstr(out, subsep);
+			subsep = ", ";
+			print_joined("remote branch ", "remote branches ",
+					&src_data->r_branch, out);
+		}
+		if (src_data->tag.nr) {
+			strbuf_addstr(out, subsep);
+			subsep = ", ";
+			print_joined("tag ", "tags ", &src_data->tag, out);
+		}
+		if (src_data->generic.nr) {
+			strbuf_addstr(out, subsep);
+			print_joined("commit ", "commits ", &src_data->generic,
+					out);
+		}
+		if (strcmp(".", srcs.list[i]))
+			strbuf_addf(out, " of %s", srcs.list[i]);
+	}
+
+	if (!strcmp("master", current_branch))
+		strbuf_addch(out, '\n');
+	else
+		strbuf_addf(out, " into %s\n", current_branch);
+
+	if (merge_summary) {
+		struct commit *head;
+		struct rev_info rev;
+
+		head = lookup_commit(head_sha1);
+		init_revisions(&rev, NULL);
+		rev.commit_format = CMIT_FMT_ONELINE;
+		rev.ignore_merges = 1;
+		rev.limited = 1;
+
+		for (i = 0; i < origins.nr; i++)
+			shortlog(origins.list[i], origins.payload[i],
+					head, &rev, limit, out);
+	}
+	return 0;
+}
+
+int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
+{
+	FILE *in = stdin;
+	struct strbuf input, output;
+	int ret;
+
 	git_config(fmt_merge_msg_config, NULL);
 
 	while (argc > 1) {
@@ -288,82 +379,14 @@
 	if (argc > 1)
 		usage(fmt_merge_msg_usage);
 
-	/* get current branch */
-	current_branch = resolve_ref("HEAD", head_sha1, 1, NULL);
-	if (!current_branch)
-		die("No current branch");
-	if (!prefixcmp(current_branch, "refs/heads/"))
-		current_branch += 11;
+	strbuf_init(&input, 0);
+	if (strbuf_read(&input, fileno(in), 0) < 0)
+		die("could not read input file %s", strerror(errno));
+	strbuf_init(&output, 0);
 
-	while (fgets(line, sizeof(line), in)) {
-		i++;
-		if (line[0] == 0)
-			continue;
-		if (handle_line(line))
-			die ("Error in line %d: %s", i, line);
-	}
-
-	printf("Merge ");
-	for (i = 0; i < srcs.nr; i++) {
-		struct src_data *src_data = srcs.payload[i];
-		const char *subsep = "";
-
-		printf(sep);
-		sep = "; ";
-
-		if (src_data->head_status == 1) {
-			printf(srcs.list[i]);
-			continue;
-		}
-		if (src_data->head_status == 3) {
-			subsep = ", ";
-			printf("HEAD");
-		}
-		if (src_data->branch.nr) {
-			printf(subsep);
-			subsep = ", ";
-			print_joined("branch ", "branches ", &src_data->branch);
-		}
-		if (src_data->r_branch.nr) {
-			printf(subsep);
-			subsep = ", ";
-			print_joined("remote branch ", "remote branches ",
-					&src_data->r_branch);
-		}
-		if (src_data->tag.nr) {
-			printf(subsep);
-			subsep = ", ";
-			print_joined("tag ", "tags ", &src_data->tag);
-		}
-		if (src_data->generic.nr) {
-			printf(subsep);
-			print_joined("commit ", "commits ", &src_data->generic);
-		}
-		if (strcmp(".", srcs.list[i]))
-			printf(" of %s", srcs.list[i]);
-	}
-
-	if (!strcmp("master", current_branch))
-		putchar('\n');
-	else
-		printf(" into %s\n", current_branch);
-
-	if (merge_summary) {
-		struct commit *head;
-		struct rev_info rev;
-
-		head = lookup_commit(head_sha1);
-		init_revisions(&rev, prefix);
-		rev.commit_format = CMIT_FMT_ONELINE;
-		rev.ignore_merges = 1;
-		rev.limited = 1;
-
-		for (i = 0; i < origins.nr; i++)
-			shortlog(origins.list[i], origins.payload[i],
-					head, &rev, limit);
-	}
-
-	/* No cleanup yet; is standalone anyway */
-
+	ret = fmt_merge_msg(merge_summary, &input, &output);
+	if (ret)
+		return ret;
+	printf("%s", output.buf);
 	return 0;
 }
diff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c
index fef93d7..72c0878 100644
--- a/builtin-for-each-ref.c
+++ b/builtin-for-each-ref.c
@@ -320,9 +320,7 @@
 
 static const char *copy_line(const char *buf)
 {
-	const char *eol = strchr(buf, '\n');
-	if (!eol)
-		return "";
+	const char *eol = strchrnul(buf, '\n');
 	return xmemdupz(buf, eol - buf);
 }
 
@@ -459,8 +457,10 @@
 		return;
 	*sub = buf; /* first non-empty line */
 	buf = strchr(buf, '\n');
-	if (!buf)
+	if (!buf) {
+		*body = "";
 		return; /* no body */
+	}
 	while (*buf == '\n')
 		buf++; /* skip blank between subject and body */
 	*body = buf;
@@ -650,7 +650,8 @@
 			if ((plen <= namelen) &&
 			    !strncmp(refname, p, plen) &&
 			    (refname[plen] == '\0' ||
-			     refname[plen] == '/'))
+			     refname[plen] == '/' ||
+			     p[plen-1] == '/'))
 				break;
 			if (!fnmatch(p, refname, FNM_PATHNAME))
 				break;
@@ -809,7 +810,7 @@
 	return sort;
 }
 
-int opt_parse_sort(const struct option *opt, const char *arg, int unset)
+static int opt_parse_sort(const struct option *opt, const char *arg, int unset)
 {
 	struct ref_sort **sort_tail = opt->value;
 	struct ref_sort *s;
@@ -831,7 +832,7 @@
 }
 
 static char const * const for_each_ref_usage[] = {
-	"git-for-each-ref [options] [<pattern>]",
+	"git for-each-ref [options] [<pattern>]",
 	NULL
 };
 
diff --git a/builtin-fsck.c b/builtin-fsck.c
index 78a6e1f..30971ce 100644
--- a/builtin-fsck.c
+++ b/builtin-fsck.c
@@ -64,11 +64,11 @@
 	return (type == FSCK_WARN) ? 0 : 1;
 }
 
+static struct object_array pending;
+
 static int mark_object(struct object *obj, int type, void *data)
 {
-	struct tree *tree = NULL;
 	struct object *parent = data;
-	int result;
 
 	if (!obj) {
 		printf("broken link from %7s %s\n",
@@ -96,6 +96,20 @@
 		return 1;
 	}
 
+	add_object_array(obj, (void *) parent, &pending);
+	return 0;
+}
+
+static void mark_object_reachable(struct object *obj)
+{
+	mark_object(obj, OBJ_ANY, 0);
+}
+
+static int traverse_one_object(struct object *obj, struct object *parent)
+{
+	int result;
+	struct tree *tree = NULL;
+
 	if (obj->type == OBJ_TREE) {
 		obj->parsed = 0;
 		tree = (struct tree *)obj;
@@ -107,15 +121,22 @@
 		free(tree->buffer);
 		tree->buffer = NULL;
 	}
-	if (result < 0)
-		result = 1;
-
 	return result;
 }
 
-static void mark_object_reachable(struct object *obj)
+static int traverse_reachable(void)
 {
-	mark_object(obj, OBJ_ANY, 0);
+	int result = 0;
+	while (pending.nr) {
+		struct object_array_entry *entry;
+		struct object *obj, *parent;
+
+		entry = pending.objects + --pending.nr;
+		obj = entry->item;
+		parent = (struct object *) entry->name;
+		result |= traverse_one_object(obj, parent);
+	}
+	return !!result;
 }
 
 static int mark_used(struct object *obj, int type, void *data)
@@ -233,6 +254,9 @@
 {
 	int i, max;
 
+	/* Traverse the pending reachable objects */
+	traverse_reachable();
+
 	/* Look up all the requirements, warn about missing objects.. */
 	max = get_max_object_index();
 	if (verbose)
@@ -385,6 +409,8 @@
 			add_sha1_list(sha1, DIRENT_SORT_HINT(de));
 			continue;
 		}
+		if (!prefixcmp(de->d_name, "tmp_obj_"))
+			continue;
 		fprintf(stderr, "bad sha1 file: %s/%s\n", path, de->d_name);
 	}
 	closedir(dir);
@@ -539,7 +565,7 @@
 }
 
 static char const * const fsck_usage[] = {
-	"git-fsck [options] [<object>...]",
+	"git fsck [options] [<object>...]",
 	NULL
 };
 
@@ -585,7 +611,7 @@
 		prepare_packed_git();
 		for (p = packed_git; p; p = p->next)
 			/* verify gives error messages itself */
-			verify_pack(p, 0);
+			verify_pack(p);
 
 		for (p = packed_git; p; p = p->next) {
 			uint32_t j, num;
diff --git a/builtin-gc.c b/builtin-gc.c
index f5625bb..53a0d43 100644
--- a/builtin-gc.c
+++ b/builtin-gc.c
@@ -18,7 +18,7 @@
 #define FAILED_RUN "failed to run %s"
 
 static const char * const builtin_gc_usage[] = {
-	"git-gc [options]",
+	"git gc [options]",
 	NULL
 };
 
@@ -134,19 +134,9 @@
 
 	prepare_packed_git();
 	for (cnt = 0, p = packed_git; p; p = p->next) {
-		char path[PATH_MAX];
-		size_t len;
-		int keep;
-
 		if (!p->pack_local)
 			continue;
-		len = strlen(p->pack_name);
-		if (PATH_MAX <= len + 1)
-			continue; /* oops, give up */
-		memcpy(path, p->pack_name, len-5);
-		memcpy(path + len - 5, ".keep", 6);
-		keep = access(p->pack_name, F_OK) && (errno == ENOENT);
-		if (keep)
+		if (p->pack_keep)
 			continue;
 		/*
 		 * Perhaps check the size of the pack and count only
diff --git a/builtin-grep.c b/builtin-grep.c
index d8b06ce..3a51662 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -498,7 +498,7 @@
 }
 
 static const char builtin_grep_usage[] =
-"git-grep <option>* [-e] <pattern> <rev>* [[--] <path>...]";
+"git grep <option>* [-e] <pattern> <rev>* [[--] <path>...]";
 
 static const char emsg_invalid_context_len[] =
 "%s: invalid context length argument";
@@ -774,7 +774,7 @@
 			/* Make sure we do not get outside of paths */
 			for (i = 0; paths[i]; i++)
 				if (strncmp(prefix, paths[i], opt.prefix_length))
-					die("git-grep: cannot generate relative filenames containing '..'");
+					die("git grep: cannot generate relative filenames containing '..'");
 		}
 	}
 	else if (prefix) {
@@ -783,8 +783,11 @@
 		paths[1] = NULL;
 	}
 
-	if (!list.nr)
+	if (!list.nr) {
+		if (!cached)
+			setup_work_tree();
 		return !grep_cache(&opt, paths, cached);
+	}
 
 	if (cached)
 		die("both --cached and trees are given.");
diff --git a/builtin-http-fetch.c b/builtin-http-fetch.c
index 3a06248..03f34d7 100644
--- a/builtin-http-fetch.c
+++ b/builtin-http-fetch.c
@@ -42,7 +42,7 @@
 		arg++;
 	}
 	if (argc < arg + 2 - commits_on_stdin) {
-		usage("git-http-fetch [-c] [-t] [-a] [-v] [--recover] [-w ref] [--stdin] commit-id url");
+		usage("git http-fetch [-c] [-t] [-a] [-v] [--recover] [-w ref] [--stdin] commit-id url");
 		return 1;
 	}
 	if (commits_on_stdin) {
@@ -75,7 +75,7 @@
 		fprintf(stderr,
 "Some loose object were found to be corrupt, but they might be just\n"
 "a false '404 Not Found' error message sent with incorrect HTTP\n"
-"status code.  Suggest running git-fsck.\n");
+"status code.  Suggest running 'git fsck'.\n");
 	}
 
 	walker_free(walker);
diff --git a/builtin-init-db.c b/builtin-init-db.c
index c68a3b1..d30c3fe 100644
--- a/builtin-init-db.c
+++ b/builtin-init-db.c
@@ -17,6 +17,9 @@
 #define TEST_FILEMODE 1
 #endif
 
+static int init_is_bare_repository = 0;
+static int init_shared_repository = -1;
+
 static void safe_create_dir(const char *dir, int share)
 {
 	if (mkdir(dir, 0777) < 0) {
@@ -37,7 +40,7 @@
 
 	/* Note: if ".git/hooks" file exists in the repository being
 	 * re-initialized, /etc/core-git/templates/hooks/update would
-	 * cause git-init to fail here.  I think this is sane but
+	 * cause "git init" to fail here.  I think this is sane but
 	 * it means that the set of templates we ship by default, along
 	 * with the way the namespace under .git/ is organized, should
 	 * be really carefully chosen.
@@ -115,18 +118,8 @@
 
 	if (!template_dir)
 		template_dir = getenv(TEMPLATE_DIR_ENVIRONMENT);
-	if (!template_dir) {
-		/*
-		 * if the hard-coded template is relative, it is
-		 * interpreted relative to the exec_dir
-		 */
-		template_dir = DEFAULT_GIT_TEMPLATE_DIR;
-		if (!is_absolute_path(template_dir)) {
-			struct strbuf d = STRBUF_INIT;
-			strbuf_addf(&d, "%s/%s", git_exec_path(), template_dir);
-			template_dir = strbuf_detach(&d, NULL);
-		}
-	}
+	if (!template_dir)
+		template_dir = system_path(DEFAULT_GIT_TEMPLATE_DIR);
 	if (!template_dir[0])
 		return;
 	strcpy(template_path, template_dir);
@@ -201,6 +194,9 @@
 	copy_templates(template_path);
 
 	git_config(git_default_config, NULL);
+	is_bare_repository_cfg = init_is_bare_repository;
+	if (init_shared_repository != -1)
+		shared_repository = init_shared_repository;
 
 	/*
 	 * We would have created the above under user's umask -- under
@@ -287,6 +283,8 @@
 
 	safe_create_dir(get_git_dir(), 0);
 
+	init_is_bare_repository = is_bare_repository();
+
 	/* Check to see if the repository version is right.
 	 * Note that a newly created repository does not have
 	 * config file, so this will not fail.  What we are catching
@@ -366,7 +364,7 @@
 }
 
 static const char init_db_usage[] =
-"git-init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]]";
+"git init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]]";
 
 /*
  * If you want to, you can share the DB area with any number of branches.
@@ -391,9 +389,9 @@
 			setenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir,
 						sizeof(git_dir)), 0);
 		} else if (!strcmp(arg, "--shared"))
-			shared_repository = PERM_GROUP;
+			init_shared_repository = PERM_GROUP;
 		else if (!prefixcmp(arg, "--shared="))
-			shared_repository = git_config_perm("arg", arg+9);
+			init_shared_repository = git_config_perm("arg", arg+9);
 		else if (!strcmp(arg, "-q") || !strcmp(arg, "--quiet"))
 			flags |= INIT_DB_QUIET;
 		else
diff --git a/builtin-log.c b/builtin-log.c
index 430d876..db71e0d 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -313,7 +313,7 @@
 
 static int show_tree_object(const unsigned char *sha1,
 		const char *base, int baselen,
-		const char *pathname, unsigned mode, int stage)
+		const char *pathname, unsigned mode, int stage, void *context)
 {
 	printf("%s%s\n", pathname, S_ISDIR(mode) ? "/" : "");
 	return 0;
@@ -356,7 +356,13 @@
 					t->tag,
 					diff_get_color_opt(&rev.diffopt, DIFF_RESET));
 			ret = show_object(o->sha1, 1, &rev);
-			objects[i].item = parse_object(t->tagged->sha1);
+			if (ret)
+				break;
+			o = parse_object(t->tagged->sha1);
+			if (!o)
+				ret = error("Could not read object %s",
+					    sha1_to_hex(t->tagged->sha1));
+			objects[i].item = o;
 			i--;
 			break;
 		}
@@ -366,7 +372,7 @@
 					name,
 					diff_get_color_opt(&rev.diffopt, DIFF_RESET));
 			read_tree_recursive((struct tree *)o, "", 0, 0, NULL,
-					show_tree_object);
+					show_tree_object, NULL);
 			break;
 		case OBJ_COMMIT:
 			rev.pending.nr = rev.pending.alloc = 0;
@@ -461,7 +467,7 @@
 static void add_header(const char *value)
 {
 	int len = strlen(value);
-	while (value[len - 1] == '\n')
+	while (len && value[len - 1] == '\n')
 		len--;
 	if (!strncasecmp(value, "to: ", 4)) {
 		ALLOC_GROW(extra_to, extra_to_nr + 1, extra_to_alloc);
@@ -835,7 +841,7 @@
 			committer = git_committer_info(IDENT_ERROR_ON_NO_NAME);
 			endpos = strchr(committer, '>');
 			if (!endpos)
-				die("bogos committer info %s\n", committer);
+				die("bogus committer info %s\n", committer);
 			add_signoff = xmemdupz(committer, endpos - committer + 1);
 		}
 		else if (!strcmp(argv[i], "--attach")) {
@@ -1082,7 +1088,7 @@
 }
 
 static const char cherry_usage[] =
-"git-cherry [-v] <upstream> [<head>] [<limit>]";
+"git cherry [-v] <upstream> [<head>] [<limit>]";
 int cmd_cherry(int argc, const char **argv, const char *prefix)
 {
 	struct rev_info revs;
diff --git a/builtin-ls-files.c b/builtin-ls-files.c
index 75ba422..f72eb85 100644
--- a/builtin-ls-files.c
+++ b/builtin-ls-files.c
@@ -78,7 +78,7 @@
 	int offset = prefix_offset;
 
 	if (len >= ent->len)
-		die("git-ls-files: internal error - directory entry not superset of prefix");
+		die("git ls-files: internal error - directory entry not superset of prefix");
 
 	if (pathspec && !pathspec_match(pathspec, ps_matched, ent->name, len))
 		return;
@@ -91,39 +91,10 @@
 {
 	int i;
 
-
-	/*
-	 * Skip matching and unmerged entries for the paths,
-	 * since we want just "others".
-	 *
-	 * (Matching entries are normally pruned during
-	 * the directory tree walk, but will show up for
-	 * gitlinks because we don't necessarily have
-	 * dir->show_other_directories set to suppress
-	 * them).
-	 */
 	for (i = 0; i < dir->nr; i++) {
 		struct dir_entry *ent = dir->entries[i];
-		int len, pos;
-		struct cache_entry *ce;
-
-		/*
-		 * Remove the '/' at the end that directory
-		 * walking adds for directory entries.
-		 */
-		len = ent->len;
-		if (len && ent->name[len-1] == '/')
-			len--;
-		pos = cache_name_pos(ent->name, len);
-		if (0 <= pos)
-			continue;	/* exact match */
-		pos = -pos - 1;
-		if (pos < active_nr) {
-			ce = active_cache[pos];
-			if (ce_namelen(ce) == len &&
-			    !memcmp(ce->name, ent->name, len))
-				continue; /* Yup, this one exists unmerged */
-		}
+		if (!cache_name_is_other(ent->name, ent->len))
+			continue;
 		show_dir_entry(tag_other, ent);
 	}
 }
@@ -183,7 +154,7 @@
 	int offset = prefix_offset;
 
 	if (len >= ce_namelen(ce))
-		die("git-ls-files: internal error - cache entry not superset of prefix");
+		die("git ls-files: internal error - cache entry not superset of prefix");
 
 	if (pathspec && !pathspec_match(pathspec, ps_matched, ce->name, len))
 		return;
@@ -256,6 +227,8 @@
 			int dtype = ce_to_dtype(ce);
 			if (excluded(dir, ce->name, &dtype) != dir->show_ignored)
 				continue;
+			if (ce->ce_flags & CE_UPDATE)
+				continue;
 			err = lstat(ce->name, &st);
 			if (show_deleted && err)
 				show_ce_entry(tag_removed, ce);
@@ -319,7 +292,7 @@
 	}
 
 	if (prefix_offset > max || memcmp(prev, prefix, prefix_offset))
-		die("git-ls-files: cannot generate relative filenames containing '..'");
+		die("git ls-files: cannot generate relative filenames containing '..'");
 
 	prefix_len = max;
 	return max ? xmemdupz(prev, max) : NULL;
@@ -358,7 +331,7 @@
 	if (prefix) {
 		static const char *(matchbuf[2]);
 		matchbuf[0] = prefix;
-		matchbuf [1] = NULL;
+		matchbuf[1] = NULL;
 		match = matchbuf;
 	} else
 		match = NULL;
@@ -423,7 +396,7 @@
 }
 
 static const char ls_files_usage[] =
-	"git-ls-files [-z] [-t] [-v] (--[cached|deleted|others|stage|unmerged|killed|modified])* "
+	"git ls-files [-z] [-t] [-v] (--[cached|deleted|others|stage|unmerged|killed|modified])* "
 	"[ --ignored ] [--exclude=<pattern>] [--exclude-from=<file>] "
 	"[ --exclude-per-directory=<filename> ] [--exclude-standard] "
 	"[--full-name] [--abbrev] [--] [<file>]*";
diff --git a/builtin-ls-remote.c b/builtin-ls-remote.c
index 06ab8da..78a88f7 100644
--- a/builtin-ls-remote.c
+++ b/builtin-ls-remote.c
@@ -4,7 +4,7 @@
 #include "remote.h"
 
 static const char ls_remote_usage[] =
-"git-ls-remote [--upload-pack=<git-upload-pack>] [<host>:]<directory>";
+"git ls-remote [--heads] [--tags]  [-u <exec> | --upload-pack <exec>] <repository> <refs>...";
 
 /*
  * Is there one among the list of patterns that match the tail part
diff --git a/builtin-ls-tree.c b/builtin-ls-tree.c
index f4a75dd..cb61717 100644
--- a/builtin-ls-tree.c
+++ b/builtin-ls-tree.c
@@ -23,7 +23,7 @@
 static const char *ls_tree_prefix;
 
 static const char ls_tree_usage[] =
-	"git-ls-tree [-d] [-r] [-t] [-l] [-z] [--name-only] [--name-status] [--full-name] [--abbrev[=<n>]] <tree-ish> [path...]";
+	"git ls-tree [-d] [-r] [-t] [-l] [-z] [--name-only] [--name-status] [--full-name] [--abbrev[=<n>]] <tree-ish> [path...]";
 
 static int show_recursive(const char *base, int baselen, const char *pathname)
 {
@@ -56,7 +56,7 @@
 }
 
 static int show_tree(const unsigned char *sha1, const char *base, int baselen,
-		     const char *pathname, unsigned mode, int stage)
+		const char *pathname, unsigned mode, int stage, void *context)
 {
 	int retval = 0;
 	const char *type = blob_type;
@@ -66,17 +66,16 @@
 		/*
 		 * Maybe we want to have some recursive version here?
 		 *
-		 * Something like:
+		 * Something similar to this incomplete example:
 		 *
 		if (show_subprojects(base, baselen, pathname)) {
-			if (fork()) {
-				chdir(base);
-				exec ls-tree;
-			}
-			waitpid();
+			struct child_process ls_tree;
+
+			ls_tree.dir = base;
+			ls_tree.argv = ls-tree;
+			start_command(&ls_tree);
 		}
 		 *
-		 * ..or similar..
 		 */
 		type = commit_type;
 	} else if (S_ISDIR(mode)) {
@@ -189,7 +188,7 @@
 	tree = parse_tree_indirect(sha1);
 	if (!tree)
 		die("not a tree object");
-	read_tree_recursive(tree, "", 0, 0, pathspec, show_tree);
+	read_tree_recursive(tree, "", 0, 0, pathspec, show_tree, NULL);
 
 	return 0;
 }
diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c
index 13f0502..e890f7a 100644
--- a/builtin-mailinfo.c
+++ b/builtin-mailinfo.c
@@ -5,14 +5,15 @@
 #include "cache.h"
 #include "builtin.h"
 #include "utf8.h"
+#include "strbuf.h"
 
 static FILE *cmitmsg, *patchfile, *fin, *fout;
 
 static int keep_subject;
 static const char *metainfo_charset;
-static char line[1000];
-static char name[1000];
-static char email[1000];
+static struct strbuf line = STRBUF_INIT;
+static struct strbuf name = STRBUF_INIT;
+static struct strbuf email = STRBUF_INIT;
 
 static enum  {
 	TE_DONTCARE, TE_QP, TE_BASE64,
@@ -21,74 +22,79 @@
 	TYPE_TEXT, TYPE_OTHER,
 } message_type;
 
-static char charset[256];
+static struct strbuf charset = STRBUF_INIT;
 static int patch_lines;
-static char **p_hdr_data, **s_hdr_data;
+static struct strbuf **p_hdr_data, **s_hdr_data;
 
 #define MAX_HDR_PARSED 10
 #define MAX_BOUNDARIES 5
 
-static char *sanity_check(char *name, char *email)
+static void get_sane_name(struct strbuf *out, struct strbuf *name, struct strbuf *email)
 {
-	int len = strlen(name);
-	if (len < 3 || len > 60)
-		return email;
-	if (strchr(name, '@') || strchr(name, '<') || strchr(name, '>'))
-		return email;
-	return name;
+	struct strbuf *src = name;
+	if (name->len < 3 || 60 < name->len || strchr(name->buf, '@') ||
+		strchr(name->buf, '<') || strchr(name->buf, '>'))
+		src = email;
+	else if (name == out)
+		return;
+	strbuf_reset(out);
+	strbuf_addbuf(out, src);
 }
 
-static int bogus_from(char *line)
+static void parse_bogus_from(const struct strbuf *line)
 {
 	/* John Doe <johndoe> */
-	char *bra, *ket, *dst, *cp;
 
+	char *bra, *ket;
 	/* This is fallback, so do not bother if we already have an
 	 * e-mail address.
 	 */
-	if (*email)
-		return 0;
+	if (email.len)
+		return;
 
-	bra = strchr(line, '<');
+	bra = strchr(line->buf, '<');
 	if (!bra)
-		return 0;
+		return;
 	ket = strchr(bra, '>');
 	if (!ket)
-		return 0;
+		return;
 
-	for (dst = email, cp = bra+1; cp < ket; )
-		*dst++ = *cp++;
-	*dst = 0;
-	for (cp = line; isspace(*cp); cp++)
-		;
-	for (bra--; isspace(*bra); bra--)
-		*bra = 0;
-	cp = sanity_check(cp, email);
-	strcpy(name, cp);
-	return 1;
+	strbuf_reset(&email);
+	strbuf_add(&email, bra + 1, ket - bra - 1);
+
+	strbuf_reset(&name);
+	strbuf_add(&name, line->buf, bra - line->buf);
+	strbuf_trim(&name);
+	get_sane_name(&name, &name, &email);
 }
 
-static int handle_from(char *in_line)
+static void handle_from(const struct strbuf *from)
 {
-	char line[1000];
 	char *at;
-	char *dst;
+	size_t el;
+	struct strbuf f;
 
-	strcpy(line, in_line);
-	at = strchr(line, '@');
-	if (!at)
-		return bogus_from(line);
+	strbuf_init(&f, from->len);
+	strbuf_addbuf(&f, from);
+
+	at = strchr(f.buf, '@');
+	if (!at) {
+		parse_bogus_from(from);
+		return;
+	}
 
 	/*
 	 * If we already have one email, don't take any confusing lines
 	 */
-	if (*email && strchr(at+1, '@'))
-		return 0;
+	if (email.len && strchr(at + 1, '@')) {
+		strbuf_release(&f);
+		return;
+	}
 
 	/* Pick up the string around '@', possibly delimited with <>
-	 * pair; that is the email part.  White them out while copying.
+	 * pair; that is the email part.
 	 */
-	while (at > line) {
+	while (at > f.buf) {
 		char c = at[-1];
 		if (isspace(c))
 			break;
@@ -98,56 +104,35 @@
 		}
 		at--;
 	}
-	dst = email;
-	for (;;) {
-		unsigned char c = *at;
-		if (!c || c == '>' || isspace(c)) {
-			if (c == '>')
-				*at = ' ';
-			break;
-		}
-		*at++ = ' ';
-		*dst++ = c;
-	}
-	*dst++ = 0;
+	el = strcspn(at, " \n\t\r\v\f>");
+	strbuf_reset(&email);
+	strbuf_add(&email, at, el);
+	strbuf_remove(&f, at - f.buf, el + (at[el] ? 1 : 0));
 
 	/* The remainder is name.  It could be "John Doe <john.doe@xz>"
-	 * or "john.doe@xz (John Doe)", but we have whited out the
+	 * or "john.doe@xz (John Doe)", but we have removed the
 	 * email part, so trim from both ends, possibly removing
 	 * the () pair at the end.
 	 */
-	at = line + strlen(line);
-	while (at > line) {
-		unsigned char c = *--at;
-		if (!isspace(c)) {
-			at[(c == ')') ? 0 : 1] = 0;
-			break;
-		}
+	strbuf_trim(&f);
+	if (f.buf[0] == '(' && f.len && f.buf[f.len - 1] == ')') {
+		strbuf_remove(&f, 0, 1);
+		strbuf_setlen(&f, f.len - 1);
 	}
 
-	at = line;
-	for (;;) {
-		unsigned char c = *at;
-		if (!c || !isspace(c)) {
-			if (c == '(')
-				at++;
-			break;
-		}
-		at++;
-	}
-	at = sanity_check(at, email);
-	strcpy(name, at);
-	return 1;
+	get_sane_name(&name, &f, &email);
+	strbuf_release(&f);
 }
 
-static int handle_header(char *line, char *data, int ofs)
+static void handle_header(struct strbuf **out, const struct strbuf *line)
 {
-	if (!line || !data)
-		return 1;
+	if (!*out) {
+		*out = xmalloc(sizeof(struct strbuf));
+		strbuf_init(*out, line->len);
+	} else
+		strbuf_reset(*out);
 
-	strcpy(data, line+ofs);
-
-	return 0;
+	strbuf_addbuf(*out, line);
 }
 
 /* NOTE NOTE NOTE.  We do not claim we do full MIME.  We just attempt
@@ -156,13 +141,13 @@
  * case insensitively.
  */
 
-static int slurp_attr(const char *line, const char *name, char *attr)
+static int slurp_attr(const char *line, const char *name, struct strbuf *attr)
 {
 	const char *ends, *ap = strcasestr(line, name);
 	size_t sz;
 
 	if (!ap) {
-		*attr = 0;
+		strbuf_setlen(attr, 0);
 		return 0;
 	}
 	ap += strlen(name);
@@ -173,182 +158,172 @@
 	else
 		ends = "; \t";
 	sz = strcspn(ap, ends);
-	memcpy(attr, ap, sz);
-	attr[sz] = 0;
+	strbuf_add(attr, ap, sz);
 	return 1;
 }
 
-struct content_type {
-	char *boundary;
-	int boundary_len;
-};
+static struct strbuf *content[MAX_BOUNDARIES];
 
-static struct content_type content[MAX_BOUNDARIES];
+static struct strbuf **content_top = content;
 
-static struct content_type *content_top = content;
-
-static int handle_content_type(char *line)
+static void handle_content_type(struct strbuf *line)
 {
-	char boundary[256];
+	struct strbuf *boundary = xmalloc(sizeof(struct strbuf));
+	strbuf_init(boundary, line->len);
 
-	if (strcasestr(line, "text/") == NULL)
+	if (!strcasestr(line->buf, "text/"))
 		 message_type = TYPE_OTHER;
-	if (slurp_attr(line, "boundary=", boundary + 2)) {
-		memcpy(boundary, "--", 2);
-		if (content_top++ >= &content[MAX_BOUNDARIES]) {
+	if (slurp_attr(line->buf, "boundary=", boundary)) {
+		strbuf_insert(boundary, 0, "--", 2);
+		if (++content_top > &content[MAX_BOUNDARIES]) {
 			fprintf(stderr, "Too many boundaries to handle\n");
 			exit(1);
 		}
-		content_top->boundary_len = strlen(boundary);
-		content_top->boundary = xmalloc(content_top->boundary_len+1);
-		strcpy(content_top->boundary, boundary);
+		*content_top = boundary;
+		boundary = NULL;
 	}
-	if (slurp_attr(line, "charset=", charset)) {
-		int i, c;
-		for (i = 0; (c = charset[i]) != 0; i++)
-			charset[i] = tolower(c);
+	if (slurp_attr(line->buf, "charset=", &charset))
+		strbuf_tolower(&charset);
+
+	if (boundary) {
+		strbuf_release(boundary);
+		free(boundary);
 	}
-	return 0;
 }
 
-static int handle_content_transfer_encoding(char *line)
+static void handle_content_transfer_encoding(const struct strbuf *line)
 {
-	if (strcasestr(line, "base64"))
+	if (strcasestr(line->buf, "base64"))
 		transfer_encoding = TE_BASE64;
-	else if (strcasestr(line, "quoted-printable"))
+	else if (strcasestr(line->buf, "quoted-printable"))
 		transfer_encoding = TE_QP;
 	else
 		transfer_encoding = TE_DONTCARE;
-	return 0;
 }
 
-static int is_multipart_boundary(const char *line)
+static int is_multipart_boundary(const struct strbuf *line)
 {
-	return (!memcmp(line, content_top->boundary, content_top->boundary_len));
+	return (((*content_top)->len <= line->len) &&
+		!memcmp(line->buf, (*content_top)->buf, (*content_top)->len));
 }
 
-static int eatspace(char *line)
+static void cleanup_subject(struct strbuf *subject)
 {
-	int len = strlen(line);
-	while (len > 0 && isspace(line[len-1]))
-		line[--len] = 0;
-	return len;
-}
-
-static char *cleanup_subject(char *subject)
-{
-	for (;;) {
-		char *p;
-		int len, remove;
-		switch (*subject) {
+	char *pos;
+	size_t remove;
+	while (subject->len) {
+		switch (*subject->buf) {
 		case 'r': case 'R':
-			if (!memcmp("e:", subject+1, 2)) {
-				subject += 3;
+			if (subject->len <= 3)
+				break;
+			if (!memcmp(subject->buf + 1, "e:", 2)) {
+				strbuf_remove(subject, 0, 3);
 				continue;
 			}
 			break;
 		case ' ': case '\t': case ':':
-			subject++;
+			strbuf_remove(subject, 0, 1);
 			continue;
-
 		case '[':
-			p = strchr(subject, ']');
-			if (!p) {
-				subject++;
-				continue;
-			}
-			len = strlen(p);
-			remove = p - subject;
-			if (remove <= len *2) {
-				subject = p+1;
-				continue;
-			}
+			if ((pos = strchr(subject->buf, ']'))) {
+				remove = pos - subject->buf;
+				if (remove <= (subject->len - remove) * 2) {
+					strbuf_remove(subject, 0, remove + 1);
+					continue;
+				}
+			} else
+				strbuf_remove(subject, 0, 1);
 			break;
 		}
-		eatspace(subject);
-		return subject;
+		strbuf_trim(subject);
+		return;
 	}
 }
 
-static void cleanup_space(char *buf)
+static void cleanup_space(struct strbuf *sb)
 {
-	unsigned char c;
-	while ((c = *buf) != 0) {
-		buf++;
-		if (isspace(c)) {
-			buf[-1] = ' ';
-			c = *buf;
-			while (isspace(c)) {
-				int len = strlen(buf);
-				memmove(buf, buf+1, len);
-				c = *buf;
-			}
+	size_t pos, cnt;
+	for (pos = 0; pos < sb->len; pos++) {
+		if (isspace(sb->buf[pos])) {
+			sb->buf[pos] = ' ';
+			for (cnt = 0; isspace(sb->buf[pos + cnt + 1]); cnt++);
+			strbuf_remove(sb, pos + 1, cnt);
 		}
 	}
 }
 
-static void decode_header(char *it, unsigned itsize);
+static void decode_header(struct strbuf *line);
 static const char *header[MAX_HDR_PARSED] = {
 	"From","Subject","Date",
 };
 
-static int check_header(char *line, unsigned linesize, char **hdr_data, int overwrite)
+static inline int cmp_header(const struct strbuf *line, const char *hdr)
 {
-	int i;
+	int len = strlen(hdr);
+	return !strncasecmp(line->buf, hdr, len) && line->len > len &&
+			line->buf[len] == ':' && isspace(line->buf[len + 1]);
+}
 
+static int check_header(const struct strbuf *line,
+				struct strbuf *hdr_data[], int overwrite)
+{
+	int i, ret = 0, len;
+	struct strbuf sb = STRBUF_INIT;
 	/* search for the interesting parts */
 	for (i = 0; header[i]; i++) {
 		int len = strlen(header[i]);
-		if ((!hdr_data[i] || overwrite) &&
-		    !strncasecmp(line, header[i], len) &&
-		    line[len] == ':' && isspace(line[len + 1])) {
+		if ((!hdr_data[i] || overwrite) && cmp_header(line, header[i])) {
 			/* Unwrap inline B and Q encoding, and optionally
 			 * normalize the meta information to utf8.
 			 */
-			decode_header(line + len + 2, linesize - len - 2);
-			hdr_data[i] = xmalloc(1000 * sizeof(char));
-			if (! handle_header(line, hdr_data[i], len + 2)) {
-				return 1;
-			}
+			strbuf_add(&sb, line->buf + len + 2, line->len - len - 2);
+			decode_header(&sb);
+			handle_header(&hdr_data[i], &sb);
+			ret = 1;
+			goto check_header_out;
 		}
 	}
 
 	/* Content stuff */
-	if (!strncasecmp(line, "Content-Type", 12) &&
-		line[12] == ':' && isspace(line[12 + 1])) {
-		decode_header(line + 12 + 2, linesize - 12 - 2);
-		if (! handle_content_type(line)) {
-			return 1;
-		}
+	if (cmp_header(line, "Content-Type")) {
+		len = strlen("Content-Type: ");
+		strbuf_add(&sb, line->buf + len, line->len - len);
+		decode_header(&sb);
+		strbuf_insert(&sb, 0, "Content-Type: ", len);
+		handle_content_type(&sb);
+		ret = 1;
+		goto check_header_out;
 	}
-	if (!strncasecmp(line, "Content-Transfer-Encoding", 25) &&
-		line[25] == ':' && isspace(line[25 + 1])) {
-		decode_header(line + 25 + 2, linesize - 25 - 2);
-		if (! handle_content_transfer_encoding(line)) {
-			return 1;
-		}
+	if (cmp_header(line, "Content-Transfer-Encoding")) {
+		len = strlen("Content-Transfer-Encoding: ");
+		strbuf_add(&sb, line->buf + len, line->len - len);
+		decode_header(&sb);
+		handle_content_transfer_encoding(&sb);
+		ret = 1;
+		goto check_header_out;
 	}
 
 	/* for inbody stuff */
-	if (!memcmp(">From", line, 5) && isspace(line[5]))
-		return 1;
-	if (!memcmp("[PATCH]", line, 7) && isspace(line[7])) {
+	if (!prefixcmp(line->buf, ">From") && isspace(line->buf[5])) {
+		ret = 1; /* Should this return 0? */
+		goto check_header_out;
+	}
+	if (!prefixcmp(line->buf, "[PATCH]") && isspace(line->buf[7])) {
 		for (i = 0; header[i]; i++) {
 			if (!memcmp("Subject", header[i], 7)) {
-				if (!hdr_data[i])
-					hdr_data[i] = xmalloc(linesize + 20);
-				if (! handle_header(line, hdr_data[i], 0)) {
-					return 1;
-				}
+				handle_header(&hdr_data[i], line);
+				ret = 1;
+				goto check_header_out;
 			}
 		}
 	}
 
-	/* no match */
-	return 0;
+check_header_out:
+	strbuf_release(&sb);
+	return ret;
 }
 
-static int is_rfc2822_header(char *line)
+static int is_rfc2822_header(const struct strbuf *line)
 {
 	/*
 	 * The section that defines the loosest possible
@@ -359,15 +334,15 @@
 	 * ftext = %d33-57 / %59-126
 	 */
 	int ch;
-	char *cp = line;
+	char *cp = line->buf;
 
 	/* Count mbox From headers as headers */
-	if (!memcmp(line, "From ", 5) || !memcmp(line, ">From ", 6))
+	if (!prefixcmp(cp, "From ") || !prefixcmp(cp, ">From "))
 		return 1;
 
 	while ((ch = *cp++)) {
 		if (ch == ':')
-			return cp != line;
+			return 1;
 		if ((33 <= ch && ch <= 57) ||
 		    (59 <= ch && ch <= 126))
 			continue;
@@ -376,34 +351,20 @@
 	return 0;
 }
 
-/*
- * sz is size of 'line' buffer in bytes.  Must be reasonably
- * long enough to hold one physical real-world e-mail line.
- */
-static int read_one_header_line(char *line, int sz, FILE *in)
+static int read_one_header_line(struct strbuf *line, FILE *in)
 {
-	int len;
-
-	/*
-	 * We will read at most (sz-1) bytes and then potentially
-	 * re-add NUL after it.  Accessing line[sz] after this is safe
-	 * and we can allow len to grow up to and including sz.
-	 */
-	sz--;
-
 	/* Get the first part of the line. */
-	if (!fgets(line, sz, in))
+	if (strbuf_getline(line, in, '\n'))
 		return 0;
 
 	/*
 	 * Is it an empty line or not a valid rfc2822 header?
 	 * If so, stop here, and return false ("not a header")
 	 */
-	len = eatspace(line);
-	if (!len || !is_rfc2822_header(line)) {
+	strbuf_rtrim(line);
+	if (!line->len || !is_rfc2822_header(line)) {
 		/* Re-add the newline */
-		line[len] = '\n';
-		line[len + 1] = '\0';
+		strbuf_addch(line, '\n');
 		return 0;
 	}
 
@@ -412,65 +373,53 @@
 	 * Yuck, 2822 header "folding"
 	 */
 	for (;;) {
-		int peek, addlen;
-		static char continuation[1000];
+		int peek;
+		struct strbuf continuation = STRBUF_INIT;
 
 		peek = fgetc(in); ungetc(peek, in);
 		if (peek != ' ' && peek != '\t')
 			break;
-		if (!fgets(continuation, sizeof(continuation), in))
+		if (strbuf_getline(&continuation, in, '\n'))
 			break;
-		addlen = eatspace(continuation);
-		if (len < sz - 1) {
-			if (addlen >= sz - len)
-				addlen = sz - len - 1;
-			memcpy(line + len, continuation, addlen);
-			line[len] = '\n';
-			len += addlen;
-		}
+		continuation.buf[0] = '\n';
+		strbuf_rtrim(&continuation);
+		strbuf_addbuf(line, &continuation);
 	}
-	line[len] = 0;
 
 	return 1;
 }
 
-static int decode_q_segment(char *in, char *ot, unsigned otsize, char *ep, int rfc2047)
+static struct strbuf *decode_q_segment(const struct strbuf *q_seg, int rfc2047)
 {
-	char *otbegin = ot;
-	char *otend = ot + otsize;
+	const char *in = q_seg->buf;
 	int c;
-	while ((c = *in++) != 0 && (in <= ep)) {
-		if (ot == otend) {
-			*--ot = '\0';
-			return -1;
-		}
+	struct strbuf *out = xmalloc(sizeof(struct strbuf));
+	strbuf_init(out, q_seg->len);
+
+	while ((c = *in++) != 0) {
 		if (c == '=') {
 			int d = *in++;
 			if (d == '\n' || !d)
 				break; /* drop trailing newline */
-			*ot++ = ((hexval(d) << 4) | hexval(*in++));
+			strbuf_addch(out, (hexval(d) << 4) | hexval(*in++));
 			continue;
 		}
 		if (rfc2047 && c == '_') /* rfc2047 4.2 (2) */
 			c = 0x20;
-		*ot++ = c;
+		strbuf_addch(out, c);
 	}
-	*ot = 0;
-	return (ot - otbegin);
+	return out;
 }
 
-static int decode_b_segment(char *in, char *ot, unsigned otsize, char *ep)
+static struct strbuf *decode_b_segment(const struct strbuf *b_seg)
 {
 	/* Decode in..ep, possibly in-place to ot */
 	int c, pos = 0, acc = 0;
-	char *otbegin = ot;
-	char *otend = ot + otsize;
+	const char *in = b_seg->buf;
+	struct strbuf *out = xmalloc(sizeof(struct strbuf));
+	strbuf_init(out, b_seg->len);
 
-	while ((c = *in++) != 0 && (in <= ep)) {
-		if (ot == otend) {
-			*--ot = '\0';
-			return -1;
-		}
+	while ((c = *in++) != 0) {
 		if (c == '+')
 			c = 62;
 		else if (c == '/')
@@ -495,21 +444,20 @@
 			acc = (c << 2);
 			break;
 		case 1:
-			*ot++ = (acc | (c >> 4));
+			strbuf_addch(out, (acc | (c >> 4)));
 			acc = (c & 15) << 4;
 			break;
 		case 2:
-			*ot++ = (acc | (c >> 2));
+			strbuf_addch(out, (acc | (c >> 2)));
 			acc = (c & 3) << 6;
 			break;
 		case 3:
-			*ot++ = (acc | c);
+			strbuf_addch(out, (acc | c));
 			acc = pos = 0;
 			break;
 		}
 	}
-	*ot = 0;
-	return (ot - otbegin);
+	return out;
 }
 
 /*
@@ -523,16 +471,16 @@
  * Otherwise, we default to assuming it is Latin1 for historical
  * reasons.
  */
-static const char *guess_charset(const char *line, const char *target_charset)
+static const char *guess_charset(const struct strbuf *line, const char *target_charset)
 {
 	if (is_encoding_utf8(target_charset)) {
-		if (is_utf8(line))
+		if (is_utf8(line->buf))
 			return NULL;
 	}
 	return "latin1";
 }
 
-static void convert_to_utf8(char *line, unsigned linesize, const char *charset)
+static void convert_to_utf8(struct strbuf *line, const char *charset)
 {
 	char *out;
 
@@ -544,112 +492,118 @@
 
 	if (!strcmp(metainfo_charset, charset))
 		return;
-	out = reencode_string(line, metainfo_charset, charset);
+	out = reencode_string(line->buf, metainfo_charset, charset);
 	if (!out)
 		die("cannot convert from %s to %s\n",
 		    charset, metainfo_charset);
-	strlcpy(line, out, linesize);
-	free(out);
+	strbuf_attach(line, out, strlen(out), strlen(out));
 }
 
-static int decode_header_bq(char *it, unsigned itsize)
+static int decode_header_bq(struct strbuf *it)
 {
-	char *in, *out, *ep, *cp, *sp;
-	char outbuf[1000];
+	char *in, *ep, *cp;
+	struct strbuf outbuf = STRBUF_INIT, *dec;
+	struct strbuf charset_q = STRBUF_INIT, piecebuf = STRBUF_INIT;
 	int rfc2047 = 0;
 
-	in = it;
-	out = outbuf;
-	while ((ep = strstr(in, "=?")) != NULL) {
-		int sz, encoding;
-		char charset_q[256], piecebuf[256];
+	in = it->buf;
+	while (in - it->buf <= it->len && (ep = strstr(in, "=?")) != NULL) {
+		int encoding;
+		strbuf_reset(&charset_q);
+		strbuf_reset(&piecebuf);
 		rfc2047 = 1;
 
 		if (in != ep) {
-			sz = ep - in;
-			memcpy(out, in, sz);
-			out += sz;
-			in += sz;
+			strbuf_add(&outbuf, in, ep - in);
+			in = ep;
 		}
 		/* E.g.
 		 * ep : "=?iso-2022-jp?B?GyR...?= foo"
 		 * ep : "=?ISO-8859-1?Q?Foo=FCbar?= baz"
 		 */
 		ep += 2;
-		cp = strchr(ep, '?');
-		if (!cp)
-			return rfc2047; /* no munging */
-		for (sp = ep; sp < cp; sp++)
-			charset_q[sp - ep] = tolower(*sp);
-		charset_q[cp - ep] = 0;
+
+		if (ep - it->buf >= it->len || !(cp = strchr(ep, '?')))
+			goto decode_header_bq_out;
+
+		if (cp + 3 - it->buf > it->len)
+			goto decode_header_bq_out;
+		strbuf_add(&charset_q, ep, cp - ep);
+		strbuf_tolower(&charset_q);
+
 		encoding = cp[1];
 		if (!encoding || cp[2] != '?')
-			return rfc2047; /* no munging */
+			goto decode_header_bq_out;
 		ep = strstr(cp + 3, "?=");
 		if (!ep)
-			return rfc2047; /* no munging */
+			goto decode_header_bq_out;
+		strbuf_add(&piecebuf, cp + 3, ep - cp - 3);
 		switch (tolower(encoding)) {
 		default:
-			return rfc2047; /* no munging */
+			goto decode_header_bq_out;
 		case 'b':
-			sz = decode_b_segment(cp + 3, piecebuf, sizeof(piecebuf), ep);
+			dec = decode_b_segment(&piecebuf);
 			break;
 		case 'q':
-			sz = decode_q_segment(cp + 3, piecebuf, sizeof(piecebuf), ep, 1);
+			dec = decode_q_segment(&piecebuf, 1);
 			break;
 		}
-		if (sz < 0)
-			return rfc2047;
 		if (metainfo_charset)
-			convert_to_utf8(piecebuf, sizeof(piecebuf), charset_q);
+			convert_to_utf8(dec, charset_q.buf);
 
-		sz = strlen(piecebuf);
-		if (outbuf + sizeof(outbuf) <= out + sz)
-			return rfc2047; /* no munging */
-		strcpy(out, piecebuf);
-		out += sz;
+		strbuf_addbuf(&outbuf, dec);
+		strbuf_release(dec);
+		free(dec);
 		in = ep + 2;
 	}
-	strcpy(out, in);
-	strlcpy(it, outbuf, itsize);
+	strbuf_addstr(&outbuf, in);
+	strbuf_reset(it);
+	strbuf_addbuf(it, &outbuf);
+decode_header_bq_out:
+	strbuf_release(&outbuf);
+	strbuf_release(&charset_q);
+	strbuf_release(&piecebuf);
 	return rfc2047;
 }
 
-static void decode_header(char *it, unsigned itsize)
+static void decode_header(struct strbuf *it)
 {
-
-	if (decode_header_bq(it, itsize))
+	if (decode_header_bq(it))
 		return;
 	/* otherwise "it" is a straight copy of the input.
 	 * This can be binary guck but there is no charset specified.
 	 */
 	if (metainfo_charset)
-		convert_to_utf8(it, itsize, "");
+		convert_to_utf8(it, "");
 }
 
-static int decode_transfer_encoding(char *line, unsigned linesize, int inputlen)
+static void decode_transfer_encoding(struct strbuf *line)
 {
-	char *ep;
+	struct strbuf *ret;
 
 	switch (transfer_encoding) {
 	case TE_QP:
-		ep = line + inputlen;
-		return decode_q_segment(line, line, linesize, ep, 0);
+		ret = decode_q_segment(line, 0);
+		break;
 	case TE_BASE64:
-		ep = line + inputlen;
-		return decode_b_segment(line, line, linesize, ep);
+		ret = decode_b_segment(line);
+		break;
 	case TE_DONTCARE:
 	default:
-		return inputlen;
+		return;
 	}
+	strbuf_reset(line);
+	strbuf_addbuf(line, ret);
+	strbuf_release(ret);
+	free(ret);
 }
 
-static int handle_filter(char *line, unsigned linesize, int linelen);
+static void handle_filter(struct strbuf *line);
 
 static int find_boundary(void)
 {
-	while(fgets(line, sizeof(line), fin) != NULL) {
-		if (is_multipart_boundary(line))
+	while (!strbuf_getline(&line, fin, '\n')) {
+		if (*content_top && is_multipart_boundary(&line))
 			return 1;
 	}
 	return 0;
@@ -657,22 +611,28 @@
 
 static int handle_boundary(void)
 {
-	char newline[]="\n";
+	struct strbuf newline = STRBUF_INIT;
+
+	strbuf_addch(&newline, '\n');
 again:
-	if (!memcmp(line+content_top->boundary_len, "--", 2)) {
+	if (line.len >= (*content_top)->len + 2 &&
+	    !memcmp(line.buf + (*content_top)->len, "--", 2)) {
 		/* we hit an end boundary */
 		/* pop the current boundary off the stack */
-		free(content_top->boundary);
+		strbuf_release(*content_top);
+		free(*content_top);
+		*content_top = NULL;
 
 		/* technically won't happen as is_multipart_boundary()
 		   will fail first.  But just in case..
 		 */
-		if (content_top-- < content) {
+		if (--content_top < content) {
 			fprintf(stderr, "Detected mismatched boundaries, "
 					"can't recover\n");
 			exit(1);
 		}
-		handle_filter(newline, sizeof(newline), strlen(newline));
+		handle_filter(&newline);
+		strbuf_release(&newline);
 
 		/* skip to the next boundary */
 		if (!find_boundary())
@@ -682,39 +642,47 @@
 
 	/* set some defaults */
 	transfer_encoding = TE_DONTCARE;
-	charset[0] = 0;
+	strbuf_reset(&charset);
 	message_type = TYPE_TEXT;
 
 	/* slurp in this section's info */
-	while (read_one_header_line(line, sizeof(line), fin))
-		check_header(line, sizeof(line), p_hdr_data, 0);
+	while (read_one_header_line(&line, fin))
+		check_header(&line, p_hdr_data, 0);
 
-	/* eat the blank line after section info */
-	return (fgets(line, sizeof(line), fin) != NULL);
+	strbuf_release(&newline);
+	/* replenish line */
+	if (strbuf_getline(&line, fin, '\n'))
+		return 0;
+	strbuf_addch(&line, '\n');
+	return 1;
 }
 
-static inline int patchbreak(const char *line)
+static inline int patchbreak(const struct strbuf *line)
 {
+	size_t i;
+
 	/* Beginning of a "diff -" header? */
-	if (!memcmp("diff -", line, 6))
+	if (!prefixcmp(line->buf, "diff -"))
 		return 1;
 
 	/* CVS "Index: " line? */
-	if (!memcmp("Index: ", line, 7))
+	if (!prefixcmp(line->buf, "Index: "))
 		return 1;
 
 	/*
 	 * "--- <filename>" starts patches without headers
 	 * "---<sp>*" is a manual separator
 	 */
-	if (!memcmp("---", line, 3)) {
-		line += 3;
+	if (line->len < 4)
+		return 0;
+
+	if (!prefixcmp(line->buf, "---")) {
 		/* space followed by a filename? */
-		if (line[0] == ' ' && !isspace(line[1]))
+		if (line->buf[3] == ' ' && !isspace(line->buf[4]))
 			return 1;
 		/* Just whitespace? */
-		for (;;) {
-			unsigned char c = *line++;
+		for (i = 3; i < line->len; i++) {
+			unsigned char c = line->buf[i];
 			if (c == '\n')
 				return 1;
 			if (!isspace(c))
@@ -725,32 +693,24 @@
 	return 0;
 }
 
-
-static int handle_commit_msg(char *line, unsigned linesize)
+static int handle_commit_msg(struct strbuf *line)
 {
 	static int still_looking = 1;
-	char *endline = line + linesize;
 
 	if (!cmitmsg)
 		return 0;
 
 	if (still_looking) {
-		char *cp = line;
-		if (isspace(*line)) {
-			for (cp = line + 1; *cp; cp++) {
-				if (!isspace(*cp))
-					break;
-			}
-			if (!*cp)
-				return 0;
-		}
-		if ((still_looking = check_header(cp, endline - cp, s_hdr_data, 0)) != 0)
+		strbuf_ltrim(line);
+		if (!line->len)
+			return 0;
+		if ((still_looking = check_header(line, s_hdr_data, 0)) != 0)
 			return 0;
 	}
 
 	/* normalize the log message to UTF-8. */
 	if (metainfo_charset)
-		convert_to_utf8(line, endline - line, charset);
+		convert_to_utf8(line, charset.buf);
 
 	if (patchbreak(line)) {
 		fclose(cmitmsg);
@@ -758,142 +718,133 @@
 		return 1;
 	}
 
-	fputs(line, cmitmsg);
+	fputs(line->buf, cmitmsg);
 	return 0;
 }
 
-static int handle_patch(char *line, int len)
+static void handle_patch(const struct strbuf *line)
 {
-	fwrite(line, 1, len, patchfile);
+	fwrite(line->buf, 1, line->len, patchfile);
 	patch_lines++;
-	return 0;
 }
 
-static int handle_filter(char *line, unsigned linesize, int linelen)
+static void handle_filter(struct strbuf *line)
 {
 	static int filter = 0;
 
-	/* filter tells us which part we left off on
-	 * a non-zero return indicates we hit a filter point
-	 */
+	/* filter tells us which part we left off on */
 	switch (filter) {
 	case 0:
-		if (!handle_commit_msg(line, linesize))
+		if (!handle_commit_msg(line))
 			break;
 		filter++;
 	case 1:
-		if (!handle_patch(line, linelen))
-			break;
-		filter++;
-	default:
-		return 1;
+		handle_patch(line);
+		break;
 	}
-
-	return 0;
 }
 
 static void handle_body(void)
 {
-	int rc = 0;
-	static char newline[2000];
-	static char *np = newline;
-	int len = strlen(line);
+	int len = 0;
+	struct strbuf prev = STRBUF_INIT;
 
 	/* Skip up to the first boundary */
-	if (content_top->boundary) {
+	if (*content_top) {
 		if (!find_boundary())
-			return;
+			goto handle_body_out;
 	}
 
 	do {
+		strbuf_setlen(&line, line.len + len);
+
 		/* process any boundary lines */
-		if (content_top->boundary && is_multipart_boundary(line)) {
+		if (*content_top && is_multipart_boundary(&line)) {
 			/* flush any leftover */
-			if (np != newline)
-				handle_filter(newline, sizeof(newline),
-					      np - newline);
+			if (prev.len) {
+				handle_filter(&prev);
+				strbuf_reset(&prev);
+			}
 			if (!handle_boundary())
-				return;
-			len = strlen(line);
+				goto handle_body_out;
 		}
 
 		/* Unwrap transfer encoding */
-		len = decode_transfer_encoding(line, sizeof(line), len);
-		if (len < 0) {
-			error("Malformed input line");
-			return;
-		}
+		decode_transfer_encoding(&line);
 
 		switch (transfer_encoding) {
 		case TE_BASE64:
 		case TE_QP:
 		{
-			char *op = line;
+			struct strbuf **lines, **it, *sb;
+
+			/* Prepend any previous partial lines */
+			strbuf_insert(&line, 0, prev.buf, prev.len);
+			strbuf_reset(&prev);
 
 			/* binary data most likely doesn't have newlines */
 			if (message_type != TYPE_TEXT) {
-				rc = handle_filter(line, sizeof(line), len);
+				handle_filter(&line);
 				break;
 			}
-
 			/*
 			 * This is a decoded line that may contain
 			 * multiple new lines.  Pass only one chunk
 			 * at a time to handle_filter()
 			 */
-			do {
-				while (op < line + len && *op != '\n')
-					*np++ = *op++;
-				*np = *op;
-				if (*np != 0) {
-					/* should be sitting on a new line */
-					*(++np) = 0;
-					op++;
-					rc = handle_filter(newline, sizeof(newline), np - newline);
-					np = newline;
-				}
-			} while (op < line + len);
+			lines = strbuf_split(&line, '\n');
+			for (it = lines; (sb = *it); it++) {
+				if (*(it + 1) == NULL) /* The last line */
+					if (sb->buf[sb->len - 1] != '\n') {
+						/* Partial line, save it for later. */
+						strbuf_addbuf(&prev, sb);
+						break;
+					}
+				handle_filter(sb);
+			}
 			/*
-			 * The partial chunk is saved in newline and will be
+			 * The partial chunk is saved in "prev" and will be
 			 * appended by the next iteration of read_line_with_nul().
 			 */
+			strbuf_list_free(lines);
 			break;
 		}
 		default:
-			rc = handle_filter(line, sizeof(line), len);
+			handle_filter(&line);
 		}
-		if (rc)
-			/* nothing left to filter */
-			break;
-	} while ((len = read_line_with_nul(line, sizeof(line), fin)));
 
-	return;
+		strbuf_reset(&line);
+		if (strbuf_avail(&line) < 100)
+			strbuf_grow(&line, 100);
+	} while ((len = read_line_with_nul(line.buf, strbuf_avail(&line), fin)));
+
+handle_body_out:
+	strbuf_release(&prev);
 }
 
-static void output_header_lines(FILE *fout, const char *hdr, char *data)
+static void output_header_lines(FILE *fout, const char *hdr, const struct strbuf *data)
 {
+	const char *sp = data->buf;
 	while (1) {
-		char *ep = strchr(data, '\n');
+		char *ep = strchr(sp, '\n');
 		int len;
 		if (!ep)
-			len = strlen(data);
+			len = strlen(sp);
 		else
-			len = ep - data;
-		fprintf(fout, "%s: %.*s\n", hdr, len, data);
+			len = ep - sp;
+		fprintf(fout, "%s: %.*s\n", hdr, len, sp);
 		if (!ep)
 			break;
-		data = ep + 1;
+		sp = ep + 1;
 	}
 }
 
 static void handle_info(void)
 {
-	char *sub;
-	char *hdr;
+	struct strbuf *hdr;
 	int i;
 
 	for (i = 0; header[i]; i++) {
-
 		/* only print inbody headers if we output a patch file */
 		if (patch_lines && s_hdr_data[i])
 			hdr = s_hdr_data[i];
@@ -903,20 +854,18 @@
 			continue;
 
 		if (!memcmp(header[i], "Subject", 7)) {
-			if (keep_subject)
-				sub = hdr;
-			else {
-				sub = cleanup_subject(hdr);
-				cleanup_space(sub);
+			if (!keep_subject) {
+				cleanup_subject(hdr);
+				cleanup_space(hdr);
 			}
-			output_header_lines(fout, "Subject", sub);
+			output_header_lines(fout, "Subject", hdr);
 		} else if (!memcmp(header[i], "From", 4)) {
 			handle_from(hdr);
-			fprintf(fout, "Author: %s\n", name);
-			fprintf(fout, "Email: %s\n", email);
+			fprintf(fout, "Author: %s\n", name.buf);
+			fprintf(fout, "Email: %s\n", email.buf);
 		} else {
 			cleanup_space(hdr);
-			fprintf(fout, "%s: %s\n", header[i], hdr);
+			fprintf(fout, "%s: %s\n", header[i], hdr->buf);
 		}
 	}
 	fprintf(fout, "\n");
@@ -943,8 +892,8 @@
 		return -1;
 	}
 
-	p_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(char *));
-	s_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(char *));
+	p_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(*p_hdr_data));
+	s_hdr_data = xcalloc(MAX_HDR_PARSED, sizeof(*s_hdr_data));
 
 	do {
 		peek = fgetc(in);
@@ -952,8 +901,8 @@
 	ungetc(peek, in);
 
 	/* process the email header */
-	while (read_one_header_line(line, sizeof(line), fin))
-		check_header(line, sizeof(line), p_hdr_data, 1);
+	while (read_one_header_line(&line, fin))
+		check_header(&line, p_hdr_data, 1);
 
 	handle_body();
 	handle_info();
@@ -962,7 +911,7 @@
 }
 
 static const char mailinfo_usage[] =
-	"git-mailinfo [-k] [-u | --encoding=<encoding> | -n] msg patch <mail >info";
+	"git mailinfo [-k] [-u | --encoding=<encoding> | -n] msg patch <mail >info";
 
 int cmd_mailinfo(int argc, const char **argv, const char *prefix)
 {
diff --git a/builtin-mailsplit.c b/builtin-mailsplit.c
index ae2b4cb..71f3b3b 100644
--- a/builtin-mailsplit.c
+++ b/builtin-mailsplit.c
@@ -6,10 +6,10 @@
  */
 #include "cache.h"
 #include "builtin.h"
-#include "path-list.h"
+#include "string-list.h"
 
 static const char git_mailsplit_usage[] =
-"git-mailsplit [-d<prec>] [-f<n>] [-b] -o<directory> <mbox>|<Maildir>...";
+"git mailsplit [-d<prec>] [-f<n>] [-b] -o<directory> [<mbox>|<Maildir>...]";
 
 static int is_from_line(const char *line, int len)
 {
@@ -115,7 +115,7 @@
 	exit(1);
 }
 
-static int populate_maildir_list(struct path_list *list, const char *path)
+static int populate_maildir_list(struct string_list *list, const char *path)
 {
 	DIR *dir;
 	struct dirent *dent;
@@ -136,7 +136,7 @@
 			if (dent->d_name[0] == '.')
 				continue;
 			snprintf(name, sizeof(name), "%s/%s", *sub, dent->d_name);
-			path_list_insert(name, list);
+			string_list_insert(name, list);
 		}
 
 		closedir(dir);
@@ -152,14 +152,14 @@
 	char name[PATH_MAX];
 	int ret = -1;
 	int i;
-	struct path_list list = {NULL, 0, 0, 1};
+	struct string_list list = {NULL, 0, 0, 1};
 
 	if (populate_maildir_list(&list, maildir) < 0)
 		goto out;
 
 	for (i = 0; i < list.nr; i++) {
 		FILE *f;
-		snprintf(file, sizeof(file), "%s/%s", maildir, list.items[i].path);
+		snprintf(file, sizeof(file), "%s/%s", maildir, list.items[i].string);
 		f = fopen(file, "r");
 		if (!f) {
 			error("cannot open mail %s (%s)", file, strerror(errno));
@@ -179,7 +179,7 @@
 
 	ret = skip;
 out:
-	path_list_clear(&list, 1);
+	string_list_clear(&list, 1);
 	return ret;
 }
 
diff --git a/builtin-merge-base.c b/builtin-merge-base.c
index bcf9395..3382b13 100644
--- a/builtin-merge-base.c
+++ b/builtin-merge-base.c
@@ -20,12 +20,25 @@
 }
 
 static const char merge_base_usage[] =
-"git-merge-base [--all] <commit-id> <commit-id>";
+"git merge-base [--all] <commit-id> <commit-id>";
+
+static struct commit *get_commit_reference(const char *arg)
+{
+	unsigned char revkey[20];
+	struct commit *r;
+
+	if (get_sha1(arg, revkey))
+		die("Not a valid object name %s", arg);
+	r = lookup_commit_reference(revkey);
+	if (!r)
+		die("Not a valid commit name %s", arg);
+
+	return r;
+}
 
 int cmd_merge_base(int argc, const char **argv, const char *prefix)
 {
 	struct commit *rev1, *rev2;
-	unsigned char rev1key[20], rev2key[20];
 	int show_all = 0;
 
 	git_config(git_default_config, NULL);
@@ -40,13 +53,8 @@
 	}
 	if (argc != 3)
 		usage(merge_base_usage);
-	if (get_sha1(argv[1], rev1key))
-		die("Not a valid object name %s", argv[1]);
-	if (get_sha1(argv[2], rev2key))
-		die("Not a valid object name %s", argv[2]);
-	rev1 = lookup_commit_reference(rev1key);
-	rev2 = lookup_commit_reference(rev2key);
-	if (!rev1 || !rev2)
-		return 1;
+	rev1 = get_commit_reference(argv[1]);
+	rev2 = get_commit_reference(argv[2]);
+
 	return show_merge_base(rev1, rev2, show_all);
 }
diff --git a/builtin-merge-recursive.c b/builtin-merge-recursive.c
index 43bf6aa..b973865 100644
--- a/builtin-merge-recursive.c
+++ b/builtin-merge-recursive.c
@@ -13,11 +13,12 @@
 #include "diffcore.h"
 #include "tag.h"
 #include "unpack-trees.h"
-#include "path-list.h"
+#include "string-list.h"
 #include "xdiff-interface.h"
 #include "ll-merge.h"
 #include "interpolate.h"
 #include "attr.h"
+#include "dir.h"
 #include "merge-recursive.h"
 
 static int subtree_merge;
@@ -42,14 +43,6 @@
  * - *(int *)commit->object.sha1 set to the virtual id.
  */
 
-static unsigned commit_list_count(const struct commit_list *l)
-{
-	unsigned c = 0;
-	for (; l; l = l->next )
-		c++;
-	return c;
-}
-
 static struct commit *make_virtual_commit(struct tree *tree, const char *comment)
 {
 	struct commit *commit = xcalloc(1, sizeof(struct commit));
@@ -87,8 +80,8 @@
 	unsigned processed:1;
 };
 
-static struct path_list current_file_set = {NULL, 0, 0, 1};
-static struct path_list current_directory_set = {NULL, 0, 0, 1};
+static struct string_list current_file_set = {NULL, 0, 0, 1};
+static struct string_list current_directory_set = {NULL, 0, 0, 1};
 
 static int call_depth = 0;
 static int verbosity = 2;
@@ -256,7 +249,7 @@
 
 static int save_files_dirs(const unsigned char *sha1,
 		const char *base, int baselen, const char *path,
-		unsigned int mode, int stage)
+		unsigned int mode, int stage, void *context)
 {
 	int len = strlen(path);
 	char *newpath = xmalloc(baselen + len + 1);
@@ -265,9 +258,9 @@
 	newpath[baselen + len] = '\0';
 
 	if (S_ISDIR(mode))
-		path_list_insert(newpath, &current_directory_set);
+		string_list_insert(newpath, &current_directory_set);
 	else
-		path_list_insert(newpath, &current_file_set);
+		string_list_insert(newpath, &current_file_set);
 	free(newpath);
 
 	return READ_TREE_RECURSIVE;
@@ -276,7 +269,7 @@
 static int get_files_dirs(struct tree *tree)
 {
 	int n;
-	if (read_tree_recursive(tree, "", 0, 0, NULL, save_files_dirs) != 0)
+	if (read_tree_recursive(tree, "", 0, 0, NULL, save_files_dirs, NULL))
 		return 0;
 	n = current_file_set.nr + current_directory_set.nr;
 	return n;
@@ -288,9 +281,9 @@
  */
 static struct stage_data *insert_stage_data(const char *path,
 		struct tree *o, struct tree *a, struct tree *b,
-		struct path_list *entries)
+		struct string_list *entries)
 {
-	struct path_list_item *item;
+	struct string_list_item *item;
 	struct stage_data *e = xcalloc(1, sizeof(struct stage_data));
 	get_tree_entry(o->object.sha1, path,
 			e->stages[1].sha, &e->stages[1].mode);
@@ -298,7 +291,7 @@
 			e->stages[2].sha, &e->stages[2].mode);
 	get_tree_entry(b->object.sha1, path,
 			e->stages[3].sha, &e->stages[3].mode);
-	item = path_list_insert(path, entries);
+	item = string_list_insert(path, entries);
 	item->util = e;
 	return e;
 }
@@ -307,23 +300,23 @@
  * Create a dictionary mapping file names to stage_data objects. The
  * dictionary contains one entry for every path with a non-zero stage entry.
  */
-static struct path_list *get_unmerged(void)
+static struct string_list *get_unmerged(void)
 {
-	struct path_list *unmerged = xcalloc(1, sizeof(struct path_list));
+	struct string_list *unmerged = xcalloc(1, sizeof(struct string_list));
 	int i;
 
-	unmerged->strdup_paths = 1;
+	unmerged->strdup_strings = 1;
 
 	for (i = 0; i < active_nr; i++) {
-		struct path_list_item *item;
+		struct string_list_item *item;
 		struct stage_data *e;
 		struct cache_entry *ce = active_cache[i];
 		if (!ce_stage(ce))
 			continue;
 
-		item = path_list_lookup(ce->name, unmerged);
+		item = string_list_lookup(ce->name, unmerged);
 		if (!item) {
-			item = path_list_insert(ce->name, unmerged);
+			item = string_list_insert(ce->name, unmerged);
 			item->util = xcalloc(1, sizeof(struct stage_data));
 		}
 		e = item->util;
@@ -348,17 +341,17 @@
  * 'b_tree') to be able to associate the correct cache entries with
  * the rename information. 'tree' is always equal to either a_tree or b_tree.
  */
-static struct path_list *get_renames(struct tree *tree,
+static struct string_list *get_renames(struct tree *tree,
 					struct tree *o_tree,
 					struct tree *a_tree,
 					struct tree *b_tree,
-					struct path_list *entries)
+					struct string_list *entries)
 {
 	int i;
-	struct path_list *renames;
+	struct string_list *renames;
 	struct diff_options opts;
 
-	renames = xcalloc(1, sizeof(struct path_list));
+	renames = xcalloc(1, sizeof(struct string_list));
 	diff_setup(&opts);
 	DIFF_OPT_SET(&opts, RECURSIVE);
 	opts.detect_rename = DIFF_DETECT_RENAME;
@@ -372,7 +365,7 @@
 	diff_tree_sha1(o_tree->object.sha1, tree->object.sha1, "", &opts);
 	diffcore_std(&opts);
 	for (i = 0; i < diff_queued_diff.nr; ++i) {
-		struct path_list_item *item;
+		struct string_list_item *item;
 		struct rename *re;
 		struct diff_filepair *pair = diff_queued_diff.queue[i];
 		if (pair->status != 'R') {
@@ -382,20 +375,20 @@
 		re = xmalloc(sizeof(*re));
 		re->processed = 0;
 		re->pair = pair;
-		item = path_list_lookup(re->pair->one->path, entries);
+		item = string_list_lookup(re->pair->one->path, entries);
 		if (!item)
 			re->src_entry = insert_stage_data(re->pair->one->path,
 					o_tree, a_tree, b_tree, entries);
 		else
 			re->src_entry = item->util;
 
-		item = path_list_lookup(re->pair->two->path, entries);
+		item = string_list_lookup(re->pair->two->path, entries);
 		if (!item)
 			re->dst_entry = insert_stage_data(re->pair->two->path,
 					o_tree, a_tree, b_tree, entries);
 		else
 			re->dst_entry = item->util;
-		item = path_list_insert(pair->one->path, renames);
+		item = string_list_insert(pair->one->path, renames);
 		item->util = re;
 	}
 	opts.output_format = DIFF_FORMAT_NO_OUTPUT;
@@ -424,24 +417,6 @@
 	return 0;
 }
 
-static int remove_path(const char *name)
-{
-	int ret;
-	char *slash, *dirs;
-
-	ret = unlink(name);
-	if (ret)
-		return ret;
-	dirs = xstrdup(name);
-	while ((slash = strrchr(name, '/'))) {
-		*slash = '\0';
-		if (rmdir(name) != 0)
-			break;
-	}
-	free(dirs);
-	return ret;
-}
-
 static int remove_file(int clean, const char *path, int no_wd)
 {
 	int update_cache = index_only || clean;
@@ -452,10 +427,8 @@
 			return -1;
 	}
 	if (update_working_directory) {
-		unlink(path);
-		if (errno != ENOENT || errno != EISDIR)
+		if (remove_path(path))
 			return -1;
-		remove_path(path);
 	}
 	return 0;
 }
@@ -472,12 +445,12 @@
 	for (; *p; ++p)
 		if ('/' == *p)
 			*p = '_';
-	while (path_list_has_path(&current_file_set, newpath) ||
-	       path_list_has_path(&current_directory_set, newpath) ||
+	while (string_list_has_string(&current_file_set, newpath) ||
+	       string_list_has_string(&current_directory_set, newpath) ||
 	       lstat(newpath, &st) == 0)
 		sprintf(p, "_%d", suffix++);
 
-	path_list_insert(newpath, &current_file_set);
+	string_list_insert(newpath, &current_file_set);
 	return newpath;
 }
 
@@ -735,13 +708,13 @@
 	const char *ren2_dst = ren2->pair->two->path;
 	const char *dst_name1 = ren1_dst;
 	const char *dst_name2 = ren2_dst;
-	if (path_list_has_path(&current_directory_set, ren1_dst)) {
+	if (string_list_has_string(&current_directory_set, ren1_dst)) {
 		dst_name1 = del[delp++] = unique_path(ren1_dst, branch1);
 		output(1, "%s is a directory in %s added as %s instead",
 		       ren1_dst, branch2, dst_name1);
 		remove_file(0, ren1_dst, 0);
 	}
-	if (path_list_has_path(&current_directory_set, ren2_dst)) {
+	if (string_list_has_string(&current_directory_set, ren2_dst)) {
 		dst_name2 = del[delp++] = unique_path(ren2_dst, branch2);
 		output(1, "%s is a directory in %s added as %s instead",
 		       ren2_dst, branch1, dst_name2);
@@ -791,30 +764,30 @@
 	free(new_path1);
 }
 
-static int process_renames(struct path_list *a_renames,
-			   struct path_list *b_renames,
+static int process_renames(struct string_list *a_renames,
+			   struct string_list *b_renames,
 			   const char *a_branch,
 			   const char *b_branch)
 {
 	int clean_merge = 1, i, j;
-	struct path_list a_by_dst = {NULL, 0, 0, 0}, b_by_dst = {NULL, 0, 0, 0};
+	struct string_list a_by_dst = {NULL, 0, 0, 0}, b_by_dst = {NULL, 0, 0, 0};
 	const struct rename *sre;
 
 	for (i = 0; i < a_renames->nr; i++) {
 		sre = a_renames->items[i].util;
-		path_list_insert(sre->pair->two->path, &a_by_dst)->util
+		string_list_insert(sre->pair->two->path, &a_by_dst)->util
 			= sre->dst_entry;
 	}
 	for (i = 0; i < b_renames->nr; i++) {
 		sre = b_renames->items[i].util;
-		path_list_insert(sre->pair->two->path, &b_by_dst)->util
+		string_list_insert(sre->pair->two->path, &b_by_dst)->util
 			= sre->dst_entry;
 	}
 
 	for (i = 0, j = 0; i < a_renames->nr || j < b_renames->nr;) {
 		int compare;
 		char *src;
-		struct path_list *renames1, *renames2, *renames2Dst;
+		struct string_list *renames1, *renames2, *renames2Dst;
 		struct rename *ren1 = NULL, *ren2 = NULL;
 		const char *branch1, *branch2;
 		const char *ren1_src, *ren1_dst;
@@ -826,8 +799,8 @@
 			compare = -1;
 			ren1 = a_renames->items[i++].util;
 		} else {
-			compare = strcmp(a_renames->items[i].path,
-					b_renames->items[j].path);
+			compare = strcmp(a_renames->items[i].string,
+					b_renames->items[j].string);
 			if (compare <= 0)
 				ren1 = a_renames->items[i++].util;
 			if (compare >= 0)
@@ -916,7 +889,7 @@
 			}
 		} else {
 			/* Renamed in 1, maybe changed in 2 */
-			struct path_list_item *item;
+			struct string_list_item *item;
 			/* we only use sha1 and mode of these */
 			struct diff_filespec src_other, dst_other;
 			int try_merge, stage = a_renames == renames1 ? 3: 2;
@@ -930,7 +903,7 @@
 
 			try_merge = 0;
 
-			if (path_list_has_path(&current_directory_set, ren1_dst)) {
+			if (string_list_has_string(&current_directory_set, ren1_dst)) {
 				clean_merge = 0;
 				output(1, "CONFLICT (rename/directory): Renamed %s->%s in %s "
 				       " directory %s added in %s",
@@ -955,7 +928,7 @@
 				new_path = unique_path(ren1_dst, branch2);
 				output(1, "Added as %s instead", new_path);
 				update_file(0, dst_other.sha1, dst_other.mode, new_path);
-			} else if ((item = path_list_lookup(ren1_dst, renames2Dst))) {
+			} else if ((item = string_list_lookup(ren1_dst, renames2Dst))) {
 				ren2 = item->util;
 				clean_merge = 0;
 				ren2->processed = 1;
@@ -1011,8 +984,8 @@
 			}
 		}
 	}
-	path_list_clear(&a_by_dst, 0);
-	path_list_clear(&b_by_dst, 0);
+	string_list_clear(&a_by_dst, 0);
+	string_list_clear(&b_by_dst, 0);
 
 	return clean_merge;
 }
@@ -1090,7 +1063,7 @@
 			sha = b_sha;
 			conf = "directory/file";
 		}
-		if (path_list_has_path(&current_directory_set, path)) {
+		if (string_list_has_string(&current_directory_set, path)) {
 			const char *new_path = unique_path(path, add_branch);
 			clean_merge = 0;
 			output(1, "CONFLICT (%s): There is a directory with name %s in %s. "
@@ -1181,10 +1154,10 @@
 		    sha1_to_hex(merge->object.sha1));
 
 	if (unmerged_cache()) {
-		struct path_list *entries, *re_head, *re_merge;
+		struct string_list *entries, *re_head, *re_merge;
 		int i;
-		path_list_clear(&current_file_set, 1);
-		path_list_clear(&current_directory_set, 1);
+		string_list_clear(&current_file_set, 1);
+		string_list_clear(&current_directory_set, 1);
 		get_files_dirs(head);
 		get_files_dirs(merge);
 
@@ -1194,16 +1167,16 @@
 		clean = process_renames(re_head, re_merge,
 				branch1, branch2);
 		for (i = 0; i < entries->nr; i++) {
-			const char *path = entries->items[i].path;
+			const char *path = entries->items[i].string;
 			struct stage_data *e = entries->items[i].util;
 			if (!e->processed
 				&& !process_entry(path, e, branch1, branch2))
 				clean = 0;
 		}
 
-		path_list_clear(re_merge, 0);
-		path_list_clear(re_head, 0);
-		path_list_clear(entries, 1);
+		string_list_clear(re_merge, 0);
+		string_list_clear(re_head, 0);
+		string_list_clear(entries, 1);
 
 	}
 	else
diff --git a/builtin-merge.c b/builtin-merge.c
new file mode 100644
index 0000000..d0bf1fc
--- /dev/null
+++ b/builtin-merge.c
@@ -0,0 +1,1147 @@
+/*
+ * Builtin "git merge"
+ *
+ * Copyright (c) 2008 Miklos Vajna <vmiklos@frugalware.org>
+ *
+ * Based on git-merge.sh by Junio C Hamano.
+ */
+
+#include "cache.h"
+#include "parse-options.h"
+#include "builtin.h"
+#include "run-command.h"
+#include "diff.h"
+#include "refs.h"
+#include "commit.h"
+#include "diffcore.h"
+#include "revision.h"
+#include "unpack-trees.h"
+#include "cache-tree.h"
+#include "dir.h"
+#include "utf8.h"
+#include "log-tree.h"
+#include "color.h"
+#include "rerere.h"
+
+#define DEFAULT_TWOHEAD (1<<0)
+#define DEFAULT_OCTOPUS (1<<1)
+#define NO_FAST_FORWARD (1<<2)
+#define NO_TRIVIAL      (1<<3)
+
+struct strategy {
+	const char *name;
+	unsigned attr;
+};
+
+static const char * const builtin_merge_usage[] = {
+	"git-merge [options] <remote>...",
+	"git-merge [options] <msg> HEAD <remote>",
+	NULL
+};
+
+static int show_diffstat = 1, option_log, squash;
+static int option_commit = 1, allow_fast_forward = 1;
+static int allow_trivial = 1, have_message;
+static struct strbuf merge_msg;
+static struct commit_list *remoteheads;
+static unsigned char head[20], stash[20];
+static struct strategy **use_strategies;
+static size_t use_strategies_nr, use_strategies_alloc;
+static const char *branch;
+
+static struct strategy all_strategy[] = {
+	{ "recursive",  DEFAULT_TWOHEAD | NO_TRIVIAL },
+	{ "octopus",    DEFAULT_OCTOPUS },
+	{ "resolve",    0 },
+	{ "ours",       NO_FAST_FORWARD | NO_TRIVIAL },
+	{ "subtree",    NO_FAST_FORWARD | NO_TRIVIAL },
+};
+
+static const char *pull_twohead, *pull_octopus;
+
+static int option_parse_message(const struct option *opt,
+				const char *arg, int unset)
+{
+	struct strbuf *buf = opt->value;
+
+	if (unset)
+		strbuf_setlen(buf, 0);
+	else if (arg) {
+		strbuf_addf(buf, "%s\n\n", arg);
+		have_message = 1;
+	} else
+		return error("switch `m' requires a value");
+	return 0;
+}
+
+static struct strategy *get_strategy(const char *name)
+{
+	int i;
+	struct strbuf err;
+
+	if (!name)
+		return NULL;
+
+	for (i = 0; i < ARRAY_SIZE(all_strategy); i++)
+		if (!strcmp(name, all_strategy[i].name))
+			return &all_strategy[i];
+
+	strbuf_init(&err, 0);
+	for (i = 0; i < ARRAY_SIZE(all_strategy); i++)
+		strbuf_addf(&err, " %s", all_strategy[i].name);
+	fprintf(stderr, "Could not find merge strategy '%s'.\n", name);
+	fprintf(stderr, "Available strategies are:%s.\n", err.buf);
+	exit(1);
+}
+
+static void append_strategy(struct strategy *s)
+{
+	ALLOC_GROW(use_strategies, use_strategies_nr + 1, use_strategies_alloc);
+	use_strategies[use_strategies_nr++] = s;
+}
+
+static int option_parse_strategy(const struct option *opt,
+				 const char *name, int unset)
+{
+	if (unset)
+		return 0;
+
+	append_strategy(get_strategy(name));
+	return 0;
+}
+
+static int option_parse_n(const struct option *opt,
+			  const char *arg, int unset)
+{
+	show_diffstat = unset;
+	return 0;
+}
+
+static struct option builtin_merge_options[] = {
+	{ OPTION_CALLBACK, 'n', NULL, NULL, NULL,
+		"do not show a diffstat at the end of the merge",
+		PARSE_OPT_NOARG, option_parse_n },
+	OPT_BOOLEAN(0, "stat", &show_diffstat,
+		"show a diffstat at the end of the merge"),
+	OPT_BOOLEAN(0, "summary", &show_diffstat, "(synonym to --stat)"),
+	OPT_BOOLEAN(0, "log", &option_log,
+		"add list of one-line log to merge commit message"),
+	OPT_BOOLEAN(0, "squash", &squash,
+		"create a single commit instead of doing a merge"),
+	OPT_BOOLEAN(0, "commit", &option_commit,
+		"perform a commit if the merge succeeds (default)"),
+	OPT_BOOLEAN(0, "ff", &allow_fast_forward,
+		"allow fast forward (default)"),
+	OPT_CALLBACK('s', "strategy", &use_strategies, "strategy",
+		"merge strategy to use", option_parse_strategy),
+	OPT_CALLBACK('m', "message", &merge_msg, "message",
+		"message to be used for the merge commit (if any)",
+		option_parse_message),
+	OPT_END()
+};
+
+/* Cleans up metadata that is uninteresting after a succeeded merge. */
+static void drop_save(void)
+{
+	unlink(git_path("MERGE_HEAD"));
+	unlink(git_path("MERGE_MSG"));
+}
+
+static void save_state(void)
+{
+	int len;
+	struct child_process cp;
+	struct strbuf buffer = STRBUF_INIT;
+	const char *argv[] = {"stash", "create", NULL};
+
+	memset(&cp, 0, sizeof(cp));
+	cp.argv = argv;
+	cp.out = -1;
+	cp.git_cmd = 1;
+
+	if (start_command(&cp))
+		die("could not run stash.");
+	len = strbuf_read(&buffer, cp.out, 1024);
+	close(cp.out);
+
+	if (finish_command(&cp) || len < 0)
+		die("stash failed");
+	else if (!len)
+		return;
+	strbuf_setlen(&buffer, buffer.len-1);
+	if (get_sha1(buffer.buf, stash))
+		die("not a valid object: %s", buffer.buf);
+}
+
+static void reset_hard(unsigned const char *sha1, int verbose)
+{
+	int i = 0;
+	const char *args[6];
+
+	args[i++] = "read-tree";
+	if (verbose)
+		args[i++] = "-v";
+	args[i++] = "--reset";
+	args[i++] = "-u";
+	args[i++] = sha1_to_hex(sha1);
+	args[i] = NULL;
+
+	if (run_command_v_opt(args, RUN_GIT_CMD))
+		die("read-tree failed");
+}
+
+static void restore_state(void)
+{
+	struct strbuf sb;
+	const char *args[] = { "stash", "apply", NULL, NULL };
+
+	if (is_null_sha1(stash))
+		return;
+
+	reset_hard(head, 1);
+
+	strbuf_init(&sb, 0);
+	args[2] = sha1_to_hex(stash);
+
+	/*
+	 * It is OK to ignore error here, for example when there was
+	 * nothing to restore.
+	 */
+	run_command_v_opt(args, RUN_GIT_CMD);
+
+	strbuf_release(&sb);
+	refresh_cache(REFRESH_QUIET);
+}
+
+/* This is called when no merge was necessary. */
+static void finish_up_to_date(const char *msg)
+{
+	printf("%s%s\n", squash ? " (nothing to squash)" : "", msg);
+	drop_save();
+}
+
+static void squash_message(void)
+{
+	struct rev_info rev;
+	struct commit *commit;
+	struct strbuf out;
+	struct commit_list *j;
+	int fd;
+
+	printf("Squash commit -- not updating HEAD\n");
+	fd = open(git_path("SQUASH_MSG"), O_WRONLY | O_CREAT, 0666);
+	if (fd < 0)
+		die("Could not write to %s", git_path("SQUASH_MSG"));
+
+	init_revisions(&rev, NULL);
+	rev.ignore_merges = 1;
+	rev.commit_format = CMIT_FMT_MEDIUM;
+
+	commit = lookup_commit(head);
+	commit->object.flags |= UNINTERESTING;
+	add_pending_object(&rev, &commit->object, NULL);
+
+	for (j = remoteheads; j; j = j->next)
+		add_pending_object(&rev, &j->item->object, NULL);
+
+	setup_revisions(0, NULL, &rev, NULL);
+	if (prepare_revision_walk(&rev))
+		die("revision walk setup failed");
+
+	strbuf_init(&out, 0);
+	strbuf_addstr(&out, "Squashed commit of the following:\n");
+	while ((commit = get_revision(&rev)) != NULL) {
+		strbuf_addch(&out, '\n');
+		strbuf_addf(&out, "commit %s\n",
+			sha1_to_hex(commit->object.sha1));
+		pretty_print_commit(rev.commit_format, commit, &out, rev.abbrev,
+			NULL, NULL, rev.date_mode, 0);
+	}
+	write(fd, out.buf, out.len);
+	close(fd);
+	strbuf_release(&out);
+}
+
+static int run_hook(const char *name)
+{
+	struct child_process hook;
+	const char *argv[3], *env[2];
+	char index[PATH_MAX];
+
+	argv[0] = git_path("hooks/%s", name);
+	if (access(argv[0], X_OK) < 0)
+		return 0;
+
+	snprintf(index, sizeof(index), "GIT_INDEX_FILE=%s", get_index_file());
+	env[0] = index;
+	env[1] = NULL;
+
+	if (squash)
+		argv[1] = "1";
+	else
+		argv[1] = "0";
+	argv[2] = NULL;
+
+	memset(&hook, 0, sizeof(hook));
+	hook.argv = argv;
+	hook.no_stdin = 1;
+	hook.stdout_to_stderr = 1;
+	hook.env = env;
+
+	return run_command(&hook);
+}
+
+static void finish(const unsigned char *new_head, const char *msg)
+{
+	struct strbuf reflog_message;
+
+	strbuf_init(&reflog_message, 0);
+	if (!msg)
+		strbuf_addstr(&reflog_message, getenv("GIT_REFLOG_ACTION"));
+	else {
+		printf("%s\n", msg);
+		strbuf_addf(&reflog_message, "%s: %s",
+			getenv("GIT_REFLOG_ACTION"), msg);
+	}
+	if (squash) {
+		squash_message();
+	} else {
+		if (!merge_msg.len)
+			printf("No merge message -- not updating HEAD\n");
+		else {
+			const char *argv_gc_auto[] = { "gc", "--auto", NULL };
+			update_ref(reflog_message.buf, "HEAD",
+				new_head, head, 0,
+				DIE_ON_ERR);
+			/*
+			 * We ignore errors in 'gc --auto', since the
+			 * user should see them.
+			 */
+			run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
+		}
+	}
+	if (new_head && show_diffstat) {
+		struct diff_options opts;
+		diff_setup(&opts);
+		opts.output_format |=
+			DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
+		opts.detect_rename = DIFF_DETECT_RENAME;
+		if (diff_use_color_default > 0)
+			DIFF_OPT_SET(&opts, COLOR_DIFF);
+		if (diff_setup_done(&opts) < 0)
+			die("diff_setup_done failed");
+		diff_tree_sha1(head, new_head, "", &opts);
+		diffcore_std(&opts);
+		diff_flush(&opts);
+	}
+
+	/* Run a post-merge hook */
+	run_hook("post-merge");
+
+	strbuf_release(&reflog_message);
+}
+
+/* Get the name for the merge commit's message. */
+static void merge_name(const char *remote, struct strbuf *msg)
+{
+	struct object *remote_head;
+	unsigned char branch_head[20], buf_sha[20];
+	struct strbuf buf;
+	const char *ptr;
+	int len, early;
+
+	memset(branch_head, 0, sizeof(branch_head));
+	remote_head = peel_to_type(remote, 0, NULL, OBJ_COMMIT);
+	if (!remote_head)
+		die("'%s' does not point to a commit", remote);
+
+	strbuf_init(&buf, 0);
+	strbuf_addstr(&buf, "refs/heads/");
+	strbuf_addstr(&buf, remote);
+	resolve_ref(buf.buf, branch_head, 0, 0);
+
+	if (!hashcmp(remote_head->sha1, branch_head)) {
+		strbuf_addf(msg, "%s\t\tbranch '%s' of .\n",
+			sha1_to_hex(branch_head), remote);
+		return;
+	}
+
+	/* See if remote matches <name>^^^.. or <name>~<number> */
+	for (len = 0, ptr = remote + strlen(remote);
+	     remote < ptr && ptr[-1] == '^';
+	     ptr--)
+		len++;
+	if (len)
+		early = 1;
+	else {
+		early = 0;
+		ptr = strrchr(remote, '~');
+		if (ptr) {
+			int seen_nonzero = 0;
+
+			len++; /* count ~ */
+			while (*++ptr && isdigit(*ptr)) {
+				seen_nonzero |= (*ptr != '0');
+				len++;
+			}
+			if (*ptr)
+				len = 0; /* not ...~<number> */
+			else if (seen_nonzero)
+				early = 1;
+			else if (len == 1)
+				early = 1; /* "name~" is "name~1"! */
+		}
+	}
+	if (len) {
+		struct strbuf truname = STRBUF_INIT;
+		strbuf_addstr(&truname, "refs/heads/");
+		strbuf_addstr(&truname, remote);
+		strbuf_setlen(&truname, truname.len - len);
+		if (resolve_ref(truname.buf, buf_sha, 0, 0)) {
+			strbuf_addf(msg,
+				    "%s\t\tbranch '%s'%s of .\n",
+				    sha1_to_hex(remote_head->sha1),
+				    truname.buf + 11,
+				    (early ? " (early part)" : ""));
+			return;
+		}
+	}
+
+	if (!strcmp(remote, "FETCH_HEAD") &&
+			!access(git_path("FETCH_HEAD"), R_OK)) {
+		FILE *fp;
+		struct strbuf line;
+		char *ptr;
+
+		strbuf_init(&line, 0);
+		fp = fopen(git_path("FETCH_HEAD"), "r");
+		if (!fp)
+			die("could not open %s for reading: %s",
+				git_path("FETCH_HEAD"), strerror(errno));
+		strbuf_getline(&line, fp, '\n');
+		fclose(fp);
+		ptr = strstr(line.buf, "\tnot-for-merge\t");
+		if (ptr)
+			strbuf_remove(&line, ptr-line.buf+1, 13);
+		strbuf_addbuf(msg, &line);
+		strbuf_release(&line);
+		return;
+	}
+	strbuf_addf(msg, "%s\t\tcommit '%s'\n",
+		sha1_to_hex(remote_head->sha1), remote);
+}
+
+static int git_merge_config(const char *k, const char *v, void *cb)
+{
+	if (branch && !prefixcmp(k, "branch.") &&
+		!prefixcmp(k + 7, branch) &&
+		!strcmp(k + 7 + strlen(branch), ".mergeoptions")) {
+		const char **argv;
+		int argc;
+		char *buf;
+
+		buf = xstrdup(v);
+		argc = split_cmdline(buf, &argv);
+		if (argc < 0)
+			die("Bad branch.%s.mergeoptions string", branch);
+		argv = xrealloc(argv, sizeof(*argv) * (argc + 2));
+		memmove(argv + 1, argv, sizeof(*argv) * (argc + 1));
+		argc++;
+		parse_options(argc, argv, builtin_merge_options,
+			      builtin_merge_usage, 0);
+		free(buf);
+	}
+
+	if (!strcmp(k, "merge.diffstat") || !strcmp(k, "merge.stat"))
+		show_diffstat = git_config_bool(k, v);
+	else if (!strcmp(k, "pull.twohead"))
+		return git_config_string(&pull_twohead, k, v);
+	else if (!strcmp(k, "pull.octopus"))
+		return git_config_string(&pull_octopus, k, v);
+	else if (!strcmp(k, "merge.log") || !strcmp(k, "merge.summary"))
+		option_log = git_config_bool(k, v);
+	return git_diff_ui_config(k, v, cb);
+}
+
+static int read_tree_trivial(unsigned char *common, unsigned char *head,
+			     unsigned char *one)
+{
+	int i, nr_trees = 0;
+	struct tree *trees[MAX_UNPACK_TREES];
+	struct tree_desc t[MAX_UNPACK_TREES];
+	struct unpack_trees_options opts;
+
+	memset(&opts, 0, sizeof(opts));
+	opts.head_idx = 2;
+	opts.src_index = &the_index;
+	opts.dst_index = &the_index;
+	opts.update = 1;
+	opts.verbose_update = 1;
+	opts.trivial_merges_only = 1;
+	opts.merge = 1;
+	trees[nr_trees] = parse_tree_indirect(common);
+	if (!trees[nr_trees++])
+		return -1;
+	trees[nr_trees] = parse_tree_indirect(head);
+	if (!trees[nr_trees++])
+		return -1;
+	trees[nr_trees] = parse_tree_indirect(one);
+	if (!trees[nr_trees++])
+		return -1;
+	opts.fn = threeway_merge;
+	cache_tree_free(&active_cache_tree);
+	for (i = 0; i < nr_trees; i++) {
+		parse_tree(trees[i]);
+		init_tree_desc(t+i, trees[i]->buffer, trees[i]->size);
+	}
+	if (unpack_trees(nr_trees, t, &opts))
+		return -1;
+	return 0;
+}
+
+static void write_tree_trivial(unsigned char *sha1)
+{
+	if (write_cache_as_tree(sha1, 0, NULL))
+		die("git write-tree failed to write a tree");
+}
+
+static int try_merge_strategy(const char *strategy, struct commit_list *common,
+			      const char *head_arg)
+{
+	const char **args;
+	int i = 0, ret;
+	struct commit_list *j;
+	struct strbuf buf;
+
+	args = xmalloc((4 + commit_list_count(common) +
+			commit_list_count(remoteheads)) * sizeof(char *));
+	strbuf_init(&buf, 0);
+	strbuf_addf(&buf, "merge-%s", strategy);
+	args[i++] = buf.buf;
+	for (j = common; j; j = j->next)
+		args[i++] = xstrdup(sha1_to_hex(j->item->object.sha1));
+	args[i++] = "--";
+	args[i++] = head_arg;
+	for (j = remoteheads; j; j = j->next)
+		args[i++] = xstrdup(sha1_to_hex(j->item->object.sha1));
+	args[i] = NULL;
+	ret = run_command_v_opt(args, RUN_GIT_CMD);
+	strbuf_release(&buf);
+	i = 1;
+	for (j = common; j; j = j->next)
+		free((void *)args[i++]);
+	i += 2;
+	for (j = remoteheads; j; j = j->next)
+		free((void *)args[i++]);
+	free(args);
+	return -ret;
+}
+
+static void count_diff_files(struct diff_queue_struct *q,
+			     struct diff_options *opt, void *data)
+{
+	int *count = data;
+
+	(*count) += q->nr;
+}
+
+static int count_unmerged_entries(void)
+{
+	const struct index_state *state = &the_index;
+	int i, ret = 0;
+
+	for (i = 0; i < state->cache_nr; i++)
+		if (ce_stage(state->cache[i]))
+			ret++;
+
+	return ret;
+}
+
+static int checkout_fast_forward(unsigned char *head, unsigned char *remote)
+{
+	struct tree *trees[MAX_UNPACK_TREES];
+	struct unpack_trees_options opts;
+	struct tree_desc t[MAX_UNPACK_TREES];
+	int i, fd, nr_trees = 0;
+	struct dir_struct dir;
+	struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file));
+
+	refresh_cache(REFRESH_QUIET);
+
+	fd = hold_locked_index(lock_file, 1);
+
+	memset(&trees, 0, sizeof(trees));
+	memset(&opts, 0, sizeof(opts));
+	memset(&t, 0, sizeof(t));
+	memset(&dir, 0, sizeof(dir));
+	dir.show_ignored = 1;
+	dir.exclude_per_dir = ".gitignore";
+	opts.dir = &dir;
+
+	opts.head_idx = 1;
+	opts.src_index = &the_index;
+	opts.dst_index = &the_index;
+	opts.update = 1;
+	opts.verbose_update = 1;
+	opts.merge = 1;
+	opts.fn = twoway_merge;
+
+	trees[nr_trees] = parse_tree_indirect(head);
+	if (!trees[nr_trees++])
+		return -1;
+	trees[nr_trees] = parse_tree_indirect(remote);
+	if (!trees[nr_trees++])
+		return -1;
+	for (i = 0; i < nr_trees; i++) {
+		parse_tree(trees[i]);
+		init_tree_desc(t+i, trees[i]->buffer, trees[i]->size);
+	}
+	if (unpack_trees(nr_trees, t, &opts))
+		return -1;
+	if (write_cache(fd, active_cache, active_nr) ||
+		commit_locked_index(lock_file))
+		die("unable to write new index file");
+	return 0;
+}
+
+static void split_merge_strategies(const char *string, struct strategy **list,
+				   int *nr, int *alloc)
+{
+	char *p, *q, *buf;
+
+	if (!string)
+		return;
+
+	buf = xstrdup(string);
+	q = buf;
+	for (;;) {
+		p = strchr(q, ' ');
+		if (!p) {
+			ALLOC_GROW(*list, *nr + 1, *alloc);
+			(*list)[(*nr)++].name = xstrdup(q);
+			free(buf);
+			return;
+		} else {
+			*p = '\0';
+			ALLOC_GROW(*list, *nr + 1, *alloc);
+			(*list)[(*nr)++].name = xstrdup(q);
+			q = ++p;
+		}
+	}
+}
+
+static void add_strategies(const char *string, unsigned attr)
+{
+	struct strategy *list = NULL;
+	int list_alloc = 0, list_nr = 0, i;
+
+	memset(&list, 0, sizeof(list));
+	split_merge_strategies(string, &list, &list_nr, &list_alloc);
+	if (list) {
+		for (i = 0; i < list_nr; i++)
+			append_strategy(get_strategy(list[i].name));
+		return;
+	}
+	for (i = 0; i < ARRAY_SIZE(all_strategy); i++)
+		if (all_strategy[i].attr & attr)
+			append_strategy(&all_strategy[i]);
+
+}
+
+static int merge_trivial(void)
+{
+	unsigned char result_tree[20], result_commit[20];
+	struct commit_list *parent = xmalloc(sizeof(*parent));
+
+	write_tree_trivial(result_tree);
+	printf("Wonderful.\n");
+	parent->item = lookup_commit(head);
+	parent->next = xmalloc(sizeof(*parent->next));
+	parent->next->item = remoteheads->item;
+	parent->next->next = NULL;
+	commit_tree(merge_msg.buf, result_tree, parent, result_commit);
+	finish(result_commit, "In-index merge");
+	drop_save();
+	return 0;
+}
+
+static int finish_automerge(struct commit_list *common,
+			    unsigned char *result_tree,
+			    const char *wt_strategy)
+{
+	struct commit_list *parents = NULL, *j;
+	struct strbuf buf = STRBUF_INIT;
+	unsigned char result_commit[20];
+
+	free_commit_list(common);
+	if (allow_fast_forward) {
+		parents = remoteheads;
+		commit_list_insert(lookup_commit(head), &parents);
+		parents = reduce_heads(parents);
+	} else {
+		struct commit_list **pptr = &parents;
+
+		pptr = &commit_list_insert(lookup_commit(head),
+				pptr)->next;
+		for (j = remoteheads; j; j = j->next)
+			pptr = &commit_list_insert(j->item, pptr)->next;
+	}
+	free_commit_list(remoteheads);
+	strbuf_addch(&merge_msg, '\n');
+	commit_tree(merge_msg.buf, result_tree, parents, result_commit);
+	strbuf_addf(&buf, "Merge made by %s.", wt_strategy);
+	finish(result_commit, buf.buf);
+	strbuf_release(&buf);
+	drop_save();
+	return 0;
+}
+
+static int suggest_conflicts(void)
+{
+	FILE *fp;
+	int pos;
+
+	fp = fopen(git_path("MERGE_MSG"), "a");
+	if (!fp)
+		die("Could open %s for writing", git_path("MERGE_MSG"));
+	fprintf(fp, "\nConflicts:\n");
+	for (pos = 0; pos < active_nr; pos++) {
+		struct cache_entry *ce = active_cache[pos];
+
+		if (ce_stage(ce)) {
+			fprintf(fp, "\t%s\n", ce->name);
+			while (pos + 1 < active_nr &&
+					!strcmp(ce->name,
+						active_cache[pos + 1]->name))
+				pos++;
+		}
+	}
+	fclose(fp);
+	rerere();
+	printf("Automatic merge failed; "
+			"fix conflicts and then commit the result.\n");
+	return 1;
+}
+
+static struct commit *is_old_style_invocation(int argc, const char **argv)
+{
+	struct commit *second_token = NULL;
+	if (argc > 1) {
+		unsigned char second_sha1[20];
+
+		if (get_sha1(argv[1], second_sha1))
+			return NULL;
+		second_token = lookup_commit_reference_gently(second_sha1, 0);
+		if (!second_token)
+			die("'%s' is not a commit", argv[1]);
+		if (hashcmp(second_token->object.sha1, head))
+			return NULL;
+	}
+	return second_token;
+}
+
+static int evaluate_result(void)
+{
+	int cnt = 0;
+	struct rev_info rev;
+
+	discard_cache();
+	if (read_cache() < 0)
+		die("failed to read the cache");
+
+	/* Check how many files differ. */
+	init_revisions(&rev, "");
+	setup_revisions(0, NULL, &rev, NULL);
+	rev.diffopt.output_format |=
+		DIFF_FORMAT_CALLBACK;
+	rev.diffopt.format_callback = count_diff_files;
+	rev.diffopt.format_callback_data = &cnt;
+	run_diff_files(&rev, 0);
+
+	/*
+	 * Check how many unmerged entries are
+	 * there.
+	 */
+	cnt += count_unmerged_entries();
+
+	return cnt;
+}
+
+int cmd_merge(int argc, const char **argv, const char *prefix)
+{
+	unsigned char result_tree[20];
+	struct strbuf buf;
+	const char *head_arg;
+	int flag, head_invalid = 0, i;
+	int best_cnt = -1, merge_was_ok = 0, automerge_was_ok = 0;
+	struct commit_list *common = NULL;
+	const char *best_strategy = NULL, *wt_strategy = NULL;
+	struct commit_list **remotes = &remoteheads;
+
+	setup_work_tree();
+	if (read_cache_unmerged())
+		die("You are in the middle of a conflicted merge.");
+
+	/*
+	 * Check if we are _not_ on a detached HEAD, i.e. if there is a
+	 * current branch.
+	 */
+	branch = resolve_ref("HEAD", head, 0, &flag);
+	if (branch && !prefixcmp(branch, "refs/heads/"))
+		branch += 11;
+	if (is_null_sha1(head))
+		head_invalid = 1;
+
+	git_config(git_merge_config, NULL);
+
+	/* for color.ui */
+	if (diff_use_color_default == -1)
+		diff_use_color_default = git_use_color_default;
+
+	argc = parse_options(argc, argv, builtin_merge_options,
+			builtin_merge_usage, 0);
+
+	if (squash) {
+		if (!allow_fast_forward)
+			die("You cannot combine --squash with --no-ff.");
+		option_commit = 0;
+	}
+
+	if (!argc)
+		usage_with_options(builtin_merge_usage,
+			builtin_merge_options);
+
+	/*
+	 * This could be traditional "merge <msg> HEAD <commit>..."  and
+	 * the way we can tell it is to see if the second token is HEAD,
+	 * but some people might have misused the interface and used a
+	 * committish that is the same as HEAD there instead.
+	 * Traditional format never would have "-m" so it is an
+	 * additional safety measure to check for it.
+	 */
+	strbuf_init(&buf, 0);
+
+	if (!have_message && is_old_style_invocation(argc, argv)) {
+		strbuf_addstr(&merge_msg, argv[0]);
+		head_arg = argv[1];
+		argv += 2;
+		argc -= 2;
+	} else if (head_invalid) {
+		struct object *remote_head;
+		/*
+		 * If the merged head is a valid one there is no reason
+		 * to forbid "git merge" into a branch yet to be born.
+		 * We do the same for "git pull".
+		 */
+		if (argc != 1)
+			die("Can merge only exactly one commit into "
+				"empty head");
+		remote_head = peel_to_type(argv[0], 0, NULL, OBJ_COMMIT);
+		if (!remote_head)
+			die("%s - not something we can merge", argv[0]);
+		update_ref("initial pull", "HEAD", remote_head->sha1, NULL, 0,
+				DIE_ON_ERR);
+		reset_hard(remote_head->sha1, 0);
+		return 0;
+	} else {
+		struct strbuf msg;
+
+		/* We are invoked directly as the first-class UI. */
+		head_arg = "HEAD";
+
+		/*
+		 * All the rest are the commits being merged;
+		 * prepare the standard merge summary message to
+		 * be appended to the given message.  If remote
+		 * is invalid we will die later in the common
+		 * codepath so we discard the error in this
+		 * loop.
+		 */
+		strbuf_init(&msg, 0);
+		for (i = 0; i < argc; i++)
+			merge_name(argv[i], &msg);
+		fmt_merge_msg(option_log, &msg, &merge_msg);
+		if (merge_msg.len)
+			strbuf_setlen(&merge_msg, merge_msg.len-1);
+	}
+
+	if (head_invalid || !argc)
+		usage_with_options(builtin_merge_usage,
+			builtin_merge_options);
+
+	strbuf_addstr(&buf, "merge");
+	for (i = 0; i < argc; i++)
+		strbuf_addf(&buf, " %s", argv[i]);
+	setenv("GIT_REFLOG_ACTION", buf.buf, 0);
+	strbuf_reset(&buf);
+
+	for (i = 0; i < argc; i++) {
+		struct object *o;
+
+		o = peel_to_type(argv[i], 0, NULL, OBJ_COMMIT);
+		if (!o)
+			die("%s - not something we can merge", argv[i]);
+		remotes = &commit_list_insert(lookup_commit(o->sha1),
+			remotes)->next;
+
+		strbuf_addf(&buf, "GITHEAD_%s", sha1_to_hex(o->sha1));
+		setenv(buf.buf, argv[i], 1);
+		strbuf_reset(&buf);
+	}
+
+	if (!use_strategies) {
+		if (!remoteheads->next)
+			add_strategies(pull_twohead, DEFAULT_TWOHEAD);
+		else
+			add_strategies(pull_octopus, DEFAULT_OCTOPUS);
+	}
+
+	for (i = 0; i < use_strategies_nr; i++) {
+		if (use_strategies[i]->attr & NO_FAST_FORWARD)
+			allow_fast_forward = 0;
+		if (use_strategies[i]->attr & NO_TRIVIAL)
+			allow_trivial = 0;
+	}
+
+	if (!remoteheads->next)
+		common = get_merge_bases(lookup_commit(head),
+				remoteheads->item, 1);
+	else {
+		struct commit_list *list = remoteheads;
+		commit_list_insert(lookup_commit(head), &list);
+		common = get_octopus_merge_bases(list);
+		free(list);
+	}
+
+	update_ref("updating ORIG_HEAD", "ORIG_HEAD", head, NULL, 0,
+		DIE_ON_ERR);
+
+	if (!common)
+		; /* No common ancestors found. We need a real merge. */
+	else if (!remoteheads->next && !common->next &&
+			common->item == remoteheads->item) {
+		/*
+		 * If head can reach all the merge then we are up to date.
+		 * but first the most common case of merging one remote.
+		 */
+		finish_up_to_date("Already up-to-date.");
+		return 0;
+	} else if (allow_fast_forward && !remoteheads->next &&
+			!common->next &&
+			!hashcmp(common->item->object.sha1, head)) {
+		/* Again the most common case of merging one remote. */
+		struct strbuf msg;
+		struct object *o;
+		char hex[41];
+
+		strcpy(hex, find_unique_abbrev(head, DEFAULT_ABBREV));
+
+		printf("Updating %s..%s\n",
+			hex,
+			find_unique_abbrev(remoteheads->item->object.sha1,
+			DEFAULT_ABBREV));
+		strbuf_init(&msg, 0);
+		strbuf_addstr(&msg, "Fast forward");
+		if (have_message)
+			strbuf_addstr(&msg,
+				" (no commit created; -m option ignored)");
+		o = peel_to_type(sha1_to_hex(remoteheads->item->object.sha1),
+			0, NULL, OBJ_COMMIT);
+		if (!o)
+			return 1;
+
+		if (checkout_fast_forward(head, remoteheads->item->object.sha1))
+			return 1;
+
+		finish(o->sha1, msg.buf);
+		drop_save();
+		return 0;
+	} else if (!remoteheads->next && common->next)
+		;
+		/*
+		 * We are not doing octopus and not fast forward.  Need
+		 * a real merge.
+		 */
+	else if (!remoteheads->next && !common->next && option_commit) {
+		/*
+		 * We are not doing octopus, not fast forward, and have
+		 * only one common.
+		 */
+		refresh_cache(REFRESH_QUIET);
+		if (allow_trivial) {
+			/* See if it is really trivial. */
+			git_committer_info(IDENT_ERROR_ON_NO_NAME);
+			printf("Trying really trivial in-index merge...\n");
+			if (!read_tree_trivial(common->item->object.sha1,
+					head, remoteheads->item->object.sha1))
+				return merge_trivial();
+			printf("Nope.\n");
+		}
+	} else {
+		/*
+		 * An octopus.  If we can reach all the remote we are up
+		 * to date.
+		 */
+		int up_to_date = 1;
+		struct commit_list *j;
+
+		for (j = remoteheads; j; j = j->next) {
+			struct commit_list *common_one;
+
+			/*
+			 * Here we *have* to calculate the individual
+			 * merge_bases again, otherwise "git merge HEAD^
+			 * HEAD^^" would be missed.
+			 */
+			common_one = get_merge_bases(lookup_commit(head),
+				j->item, 1);
+			if (hashcmp(common_one->item->object.sha1,
+				j->item->object.sha1)) {
+				up_to_date = 0;
+				break;
+			}
+		}
+		if (up_to_date) {
+			finish_up_to_date("Already up-to-date. Yeeah!");
+			return 0;
+		}
+	}
+
+	/* We are going to make a new commit. */
+	git_committer_info(IDENT_ERROR_ON_NO_NAME);
+
+	/*
+	 * At this point, we need a real merge.  No matter what strategy
+	 * we use, it would operate on the index, possibly affecting the
+	 * working tree, and when resolved cleanly, have the desired
+	 * tree in the index -- this means that the index must be in
+	 * sync with the head commit.  The strategies are responsible
+	 * to ensure this.
+	 */
+	if (use_strategies_nr != 1) {
+		/*
+		 * Stash away the local changes so that we can try more
+		 * than one.
+		 */
+		save_state();
+	} else {
+		memcpy(stash, null_sha1, 20);
+	}
+
+	for (i = 0; i < use_strategies_nr; i++) {
+		int ret;
+		if (i) {
+			printf("Rewinding the tree to pristine...\n");
+			restore_state();
+		}
+		if (use_strategies_nr != 1)
+			printf("Trying merge strategy %s...\n",
+				use_strategies[i]->name);
+		/*
+		 * Remember which strategy left the state in the working
+		 * tree.
+		 */
+		wt_strategy = use_strategies[i]->name;
+
+		ret = try_merge_strategy(use_strategies[i]->name,
+			common, head_arg);
+		if (!option_commit && !ret) {
+			merge_was_ok = 1;
+			/*
+			 * This is necessary here just to avoid writing
+			 * the tree, but later we will *not* exit with
+			 * status code 1 because merge_was_ok is set.
+			 */
+			ret = 1;
+		}
+
+		if (ret) {
+			/*
+			 * The backend exits with 1 when conflicts are
+			 * left to be resolved, with 2 when it does not
+			 * handle the given merge at all.
+			 */
+			if (ret == 1) {
+				int cnt = evaluate_result();
+
+				if (best_cnt <= 0 || cnt <= best_cnt) {
+					best_strategy = use_strategies[i]->name;
+					best_cnt = cnt;
+				}
+			}
+			if (merge_was_ok)
+				break;
+			else
+				continue;
+		}
+
+		/* Automerge succeeded. */
+		discard_cache();
+		write_tree_trivial(result_tree);
+		automerge_was_ok = 1;
+		break;
+	}
+
+	/*
+	 * If we have a resulting tree, that means the strategy module
+	 * auto resolved the merge cleanly.
+	 */
+	if (automerge_was_ok)
+		return finish_automerge(common, result_tree, wt_strategy);
+
+	/*
+	 * Pick the result from the best strategy and have the user fix
+	 * it up.
+	 */
+	if (!best_strategy) {
+		restore_state();
+		if (use_strategies_nr > 1)
+			fprintf(stderr,
+				"No merge strategy handled the merge.\n");
+		else
+			fprintf(stderr, "Merge with strategy %s failed.\n",
+				use_strategies[0]->name);
+		return 2;
+	} else if (best_strategy == wt_strategy)
+		; /* We already have its result in the working tree. */
+	else {
+		printf("Rewinding the tree to pristine...\n");
+		restore_state();
+		printf("Using the %s to prepare resolving by hand.\n",
+			best_strategy);
+		try_merge_strategy(best_strategy, common, head_arg);
+	}
+
+	if (squash)
+		finish(NULL, NULL);
+	else {
+		int fd;
+		struct commit_list *j;
+
+		for (j = remoteheads; j; j = j->next)
+			strbuf_addf(&buf, "%s\n",
+				sha1_to_hex(j->item->object.sha1));
+		fd = open(git_path("MERGE_HEAD"), O_WRONLY | O_CREAT, 0666);
+		if (fd < 0)
+			die("Could open %s for writing",
+				git_path("MERGE_HEAD"));
+		if (write_in_full(fd, buf.buf, buf.len) != buf.len)
+			die("Could not write to %s", git_path("MERGE_HEAD"));
+		close(fd);
+		strbuf_addch(&merge_msg, '\n');
+		fd = open(git_path("MERGE_MSG"), O_WRONLY | O_CREAT, 0666);
+		if (fd < 0)
+			die("Could open %s for writing", git_path("MERGE_MSG"));
+		if (write_in_full(fd, merge_msg.buf, merge_msg.len) !=
+			merge_msg.len)
+			die("Could not write to %s", git_path("MERGE_MSG"));
+		close(fd);
+	}
+
+	if (merge_was_ok) {
+		fprintf(stderr, "Automatic merge went well; "
+			"stopped before committing as requested\n");
+		return 0;
+	} else
+		return suggest_conflicts();
+}
diff --git a/builtin-mv.c b/builtin-mv.c
index 5530e11..4f65b5a 100644
--- a/builtin-mv.c
+++ b/builtin-mv.c
@@ -7,11 +7,11 @@
 #include "builtin.h"
 #include "dir.h"
 #include "cache-tree.h"
-#include "path-list.h"
+#include "string-list.h"
 #include "parse-options.h"
 
 static const char * const builtin_mv_usage[] = {
-	"git-mv [options] <source>... <destination>",
+	"git mv [options] <source>... <destination>",
 	NULL
 };
 
@@ -36,17 +36,6 @@
 	return get_pathspec(prefix, result);
 }
 
-static void show_list(const char *label, struct path_list *list)
-{
-	if (list->nr > 0) {
-		int i;
-		printf("%s", label);
-		for (i = 0; i < list->nr; i++)
-			printf("%s%s", i > 0 ? ", " : "", list->items[i].path);
-		putchar('\n');
-	}
-}
-
 static const char *add_slash(const char *path)
 {
 	int len = strlen(path);
@@ -75,11 +64,7 @@
 	const char **source, **destination, **dest_path;
 	enum update_mode { BOTH = 0, WORKING_DIRECTORY, INDEX } *modes;
 	struct stat st;
-	struct path_list overwritten = {NULL, 0, 0, 0};
-	struct path_list src_for_dst = {NULL, 0, 0, 0};
-	struct path_list added = {NULL, 0, 0, 0};
-	struct path_list deleted = {NULL, 0, 0, 0};
-	struct path_list changed = {NULL, 0, 0, 0};
+	struct string_list src_for_dst = {NULL, 0, 0, 0};
 
 	git_config(git_default_config, NULL);
 
@@ -184,21 +169,20 @@
 				 * only files can overwrite each other:
 				 * check both source and destination
 				 */
-				if (S_ISREG(st.st_mode)) {
+				if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
 					fprintf(stderr, "Warning: %s;"
 							" will overwrite!\n",
 							bad);
 					bad = NULL;
-					path_list_insert(dst, &overwritten);
 				} else
 					bad = "Cannot overwrite";
 			}
 		} else if (cache_name_pos(src, length) < 0)
 			bad = "not under version control";
-		else if (path_list_has_path(&src_for_dst, dst))
+		else if (string_list_has_string(&src_for_dst, dst))
 			bad = "multiple sources for the same target";
 		else
-			path_list_insert(dst, &src_for_dst);
+			string_list_insert(dst, &src_for_dst);
 
 		if (bad) {
 			if (ignore_errors) {
@@ -218,6 +202,7 @@
 	for (i = 0; i < argc; i++) {
 		const char *src = source[i], *dst = destination[i];
 		enum update_mode mode = modes[i];
+		int pos;
 		if (show_only || verbose)
 			printf("Renaming %s to %s\n", src, dst);
 		if (!show_only && mode != INDEX &&
@@ -227,47 +212,16 @@
 		if (mode == WORKING_DIRECTORY)
 			continue;
 
-		if (cache_name_pos(src, strlen(src)) >= 0) {
-			path_list_insert(src, &deleted);
-
-			/* destination can be a directory with 1 file inside */
-			if (path_list_has_path(&overwritten, dst))
-				path_list_insert(dst, &changed);
-			else
-				path_list_insert(dst, &added);
-		} else
-			path_list_insert(dst, &added);
+		pos = cache_name_pos(src, strlen(src));
+		assert(pos >= 0);
+		if (!show_only)
+			rename_cache_entry_at(pos, dst);
 	}
 
-	if (show_only) {
-		show_list("Changed  : ", &changed);
-		show_list("Adding   : ", &added);
-		show_list("Deleting : ", &deleted);
-	} else {
-		for (i = 0; i < changed.nr; i++) {
-			const char *path = changed.items[i].path;
-			int j = cache_name_pos(path, strlen(path));
-			struct cache_entry *ce = active_cache[j];
-
-			if (j < 0)
-				die ("Huh? Cache entry for %s unknown?", path);
-			refresh_cache_entry(ce, 0);
-		}
-
-		for (i = 0; i < added.nr; i++) {
-			const char *path = added.items[i].path;
-			if (add_file_to_cache(path, verbose ? ADD_CACHE_VERBOSE : 0))
-				die("updating index entries failed");
-		}
-
-		for (i = 0; i < deleted.nr; i++)
-			remove_file_from_cache(deleted.items[i].path);
-
-		if (active_cache_changed) {
-			if (write_cache(newfd, active_cache, active_nr) ||
-			    commit_locked_index(&lock_file))
-				die("Unable to write new index file");
-		}
+	if (active_cache_changed) {
+		if (write_cache(newfd, active_cache, active_nr) ||
+		    commit_locked_index(&lock_file))
+			die("Unable to write new index file");
 	}
 
 	return 0;
diff --git a/builtin-name-rev.c b/builtin-name-rev.c
index 5352bc8..08c8aab 100644
--- a/builtin-name-rev.c
+++ b/builtin-name-rev.c
@@ -172,7 +172,7 @@
 }
 
 static char const * const name_rev_usage[] = {
-	"git-name-rev [options] ( --all | --stdin | <commit>... )",
+	"git name-rev [options] ( --all | --stdin | <commit>... )",
 	NULL
 };
 
diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
index 447d492..fb5e14d 100644
--- a/builtin-pack-objects.c
+++ b/builtin-pack-objects.c
@@ -23,7 +23,7 @@
 #endif
 
 static const char pack_usage[] = "\
-git-pack-objects [{ -q | --progress | --all-progress }] \n\
+git pack-objects [{ -q | --progress | --all-progress }] \n\
 	[--max-pack-size=N] [--local] [--incremental] \n\
 	[--window=N] [--window-memory=N] [--depth=N] \n\
 	[--no-reuse-delta] [--no-reuse-object] [--delta-base-offset] \n\
@@ -71,6 +71,7 @@
 static int keep_unreachable, unpack_unreachable, include_tag;
 static int local;
 static int incremental;
+static int ignore_packed_keep;
 static int allow_ofs_delta;
 static const char *base_name;
 static int progress = 1;
@@ -209,28 +210,6 @@
 		stream.total_in == len) ? 0 : -1;
 }
 
-static int check_pack_crc(struct packed_git *p, struct pack_window **w_curs,
-			  off_t offset, off_t len, unsigned int nr)
-{
-	const uint32_t *index_crc;
-	uint32_t data_crc = crc32(0, Z_NULL, 0);
-
-	do {
-		unsigned int avail;
-		void *data = use_pack(p, w_curs, offset, &avail);
-		if (avail > len)
-			avail = len;
-		data_crc = crc32(data_crc, data, avail);
-		offset += avail;
-		len -= avail;
-	} while (len);
-
-	index_crc = p->index_data;
-	index_crc += 2 + 256 + p->num_objects * (20/4) + nr;
-
-	return data_crc != ntohl(*index_crc);
-}
-
 static void copy_pack_data(struct sha1file *f,
 		struct packed_git *p,
 		struct pack_window **w_curs,
@@ -267,8 +246,16 @@
 	type = entry->type;
 
 	/* write limit if limited packsize and not first object */
-	limit = pack_size_limit && nr_written ?
-			pack_size_limit - write_offset : 0;
+	if (!pack_size_limit || !nr_written)
+		limit = 0;
+	else if (pack_size_limit <= write_offset)
+		/*
+		 * the earlier object did not fit the limit; avoid
+		 * mistaking this with unlimited (i.e. limit = 0).
+		 */
+		limit = 1;
+	else
+		limit = pack_size_limit - write_offset;
 
 	if (!entry->delta)
 		usable_delta = 0;	/* no delta */
@@ -432,25 +419,22 @@
 	return hdrlen + datalen;
 }
 
-static off_t write_one(struct sha1file *f,
+static int write_one(struct sha1file *f,
 			       struct object_entry *e,
-			       off_t offset)
+			       off_t *offset)
 {
 	unsigned long size;
 
 	/* offset is non zero if object is written already. */
 	if (e->idx.offset || e->preferred_base)
-		return offset;
+		return 1;
 
 	/* if we are deltified, write out base object first. */
-	if (e->delta) {
-		offset = write_one(f, e->delta, offset);
-		if (!offset)
-			return 0;
-	}
+	if (e->delta && !write_one(f, e->delta, offset))
+		return 0;
 
-	e->idx.offset = offset;
-	size = write_object(f, e, offset);
+	e->idx.offset = *offset;
+	size = write_object(f, e, *offset);
 	if (!size) {
 		e->idx.offset = 0;
 		return 0;
@@ -458,9 +442,10 @@
 	written_list[nr_written++] = &e->idx;
 
 	/* make sure off_t is sufficiently large not to wrap */
-	if (offset > offset + size)
+	if (*offset > *offset + size)
 		die("pack too large for current definition of off_t");
-	return offset + size;
+	*offset += size;
+	return 1;
 }
 
 /* forward declaration for write_pack_file */
@@ -470,7 +455,7 @@
 {
 	uint32_t i = 0, j;
 	struct sha1file *f;
-	off_t offset, offset_one, last_obj_offset = 0;
+	off_t offset;
 	struct pack_header hdr;
 	uint32_t nr_remaining = nr_result;
 	time_t last_mtime = 0;
@@ -489,7 +474,7 @@
 			char tmpname[PATH_MAX];
 			int fd;
 			snprintf(tmpname, sizeof(tmpname),
-				 "%s/tmp_pack_XXXXXX", get_object_directory());
+				 "%s/pack/tmp_pack_XXXXXX", get_object_directory());
 			fd = xmkstemp(tmpname);
 			pack_tmp_name = xstrdup(tmpname);
 			f = sha1fd(fd, pack_tmp_name);
@@ -502,11 +487,8 @@
 		offset = sizeof(hdr);
 		nr_written = 0;
 		for (; i < nr_objects; i++) {
-			last_obj_offset = offset;
-			offset_one = write_one(f, objects + i, offset);
-			if (!offset_one)
+			if (!write_one(f, objects + i, &offset))
 				break;
-			offset = offset_one;
 			display_progress(progress_state, written);
 		}
 
@@ -519,9 +501,9 @@
 		} else if (nr_written == nr_remaining) {
 			sha1close(f, sha1, CSUM_FSYNC);
 		} else {
-			int fd = sha1close(f, NULL, 0);
-			fixup_pack_header_footer(fd, sha1, pack_tmp_name, nr_written);
-			fsync_or_die(fd, pack_tmp_name);
+			int fd = sha1close(f, sha1, 0);
+			fixup_pack_header_footer(fd, sha1, pack_tmp_name,
+						 nr_written, sha1, offset);
 			close(fd);
 		}
 
@@ -538,6 +520,7 @@
 
 			snprintf(tmpname, sizeof(tmpname), "%s-%s.pack",
 				 base_name, sha1_to_hex(sha1));
+			free_pack_by_name(tmpname);
 			if (adjust_perm(pack_tmp_name, mode))
 				die("unable to make temporary pack file readable: %s",
 				    strerror(errno));
@@ -590,7 +573,8 @@
 	free(written_list);
 	stop_progress(&progress_state);
 	if (written != nr_result)
-		die("wrote %u objects while expecting %u", written, nr_result);
+		die("wrote %"PRIu32" objects while expecting %"PRIu32,
+			written, nr_result);
 	/*
 	 * We have scanned through [0 ... i).  Since we have written
 	 * the correct number of objects,  the remaining [i ... nr_objects)
@@ -602,7 +586,8 @@
 		j += !e->idx.offset && !e->preferred_base;
 	}
 	if (j)
-		die("wrote %u objects as expected but %u unwritten", written, j);
+		die("wrote %"PRIu32" objects as expected but %"PRIu32
+			" unwritten", written, j);
 }
 
 static int locate_object_entry_hash(const unsigned char *sha1)
@@ -715,6 +700,9 @@
 		return 0;
 	}
 
+	if (!exclude && local && has_loose_object_nonlocal(sha1))
+		return 0;
+
 	for (p = packed_git; p; p = p->next) {
 		off_t offset = find_pack_entry_one(sha1, p);
 		if (offset) {
@@ -728,6 +716,8 @@
 				return 0;
 			if (local && !p->pack_local)
 				return 0;
+			if (ignore_packed_keep && p->pack_local && p->pack_keep)
+				return 0;
 		}
 	}
 
@@ -1116,9 +1106,12 @@
 	}
 
 	entry->type = sha1_object_info(entry->idx.sha1, &entry->size);
-	if (entry->type < 0)
-		die("unable to get type of object %s",
-		    sha1_to_hex(entry->idx.sha1));
+	/*
+	 * The error condition is checked in prepare_pack().  This is
+	 * to permit a missing preferred base object to be ignored
+	 * as a preferred base.  Doing so can result in a larger
+	 * pack file, but the transfer will still take place.
+	 */
 }
 
 static int pack_offset_sort(const void *_a, const void *_b)
@@ -1148,8 +1141,6 @@
 		sorted_by_offset[i] = objects + i;
 	qsort(sorted_by_offset, nr_objects, sizeof(*sorted_by_offset), pack_offset_sort);
 
-	init_pack_revindex();
-
 	for (i = 0; i < nr_objects; i++)
 		check_object(sorted_by_offset[i]);
 
@@ -1401,7 +1392,7 @@
 	memset(array, 0, array_size);
 
 	for (;;) {
-		struct object_entry *entry = *list++;
+		struct object_entry *entry;
 		struct unpacked *n = array + idx;
 		int j, max_depth, best_base = -1;
 
@@ -1410,6 +1401,7 @@
 			progress_unlock();
 			break;
 		}
+		entry = *list++;
 		(*list_size)--;
 		if (!entry->preferred_base) {
 			(*processed)++;
@@ -1718,7 +1710,8 @@
 static void prepare_pack(int window, int depth)
 {
 	struct object_entry **delta_list;
-	uint32_t i, n, nr_deltas;
+	uint32_t i, nr_deltas;
+	unsigned n;
 
 	get_object_details();
 
@@ -1743,8 +1736,12 @@
 		if (entry->no_try_delta)
 			continue;
 
-		if (!entry->preferred_base)
+		if (!entry->preferred_base) {
 			nr_deltas++;
+			if (entry->type < 0)
+				die("unable to get type of object %s",
+				    sha1_to_hex(entry->idx.sha1));
+		}
 
 		delta_list[n++] = entry;
 	}
@@ -1809,7 +1806,8 @@
 	if (!strcmp(k, "pack.indexversion")) {
 		pack_idx_default_version = git_config_int(k, v);
 		if (pack_idx_default_version > 2)
-			die("bad pack.indexversion=%d", pack_idx_default_version);
+			die("bad pack.indexversion=%"PRIu32,
+				pack_idx_default_version);
 		return 0;
 	}
 	if (!strcmp(k, "pack.packsizelimit")) {
@@ -1890,7 +1888,7 @@
 
 /*
  * Compare the objects in the offset order, in order to emulate the
- * "git-rev-list --objects" output that produced the pack originally.
+ * "git rev-list --objects" output that produced the pack originally.
  */
 static int ofscmp(const void *a_, const void *b_)
 {
@@ -2059,6 +2057,10 @@
 			incremental = 1;
 			continue;
 		}
+		if (!strcmp("--honor-pack-keep", arg)) {
+			ignore_packed_keep = 1;
+			continue;
+		}
 		if (!prefixcmp(arg, "--compression=")) {
 			char *end;
 			int level = strtoul(arg+14, &end, 0);
@@ -2243,7 +2245,8 @@
 		prepare_pack(window, depth);
 	write_pack_file();
 	if (progress)
-		fprintf(stderr, "Total %u (delta %u), reused %u (delta %u)\n",
+		fprintf(stderr, "Total %"PRIu32" (delta %"PRIu32"),"
+			" reused %"PRIu32" (delta %"PRIu32")\n",
 			written, written_delta, reused, reused_delta);
 	return 0;
 }
diff --git a/builtin-pack-refs.c b/builtin-pack-refs.c
index 1aaa76d..34246df 100644
--- a/builtin-pack-refs.c
+++ b/builtin-pack-refs.c
@@ -1,128 +1,9 @@
-#include "builtin.h"
 #include "cache.h"
-#include "refs.h"
-#include "object.h"
-#include "tag.h"
 #include "parse-options.h"
-
-struct ref_to_prune {
-	struct ref_to_prune *next;
-	unsigned char sha1[20];
-	char name[FLEX_ARRAY];
-};
-
-#define PACK_REFS_PRUNE	0x0001
-#define PACK_REFS_ALL	0x0002
-
-struct pack_refs_cb_data {
-	unsigned int flags;
-	struct ref_to_prune *ref_to_prune;
-	FILE *refs_file;
-};
-
-static int do_not_prune(int flags)
-{
-	/* If it is already packed or if it is a symref,
-	 * do not prune it.
-	 */
-	return (flags & (REF_ISSYMREF|REF_ISPACKED));
-}
-
-static int handle_one_ref(const char *path, const unsigned char *sha1,
-			  int flags, void *cb_data)
-{
-	struct pack_refs_cb_data *cb = cb_data;
-	int is_tag_ref;
-
-	/* Do not pack the symbolic refs */
-	if ((flags & REF_ISSYMREF))
-		return 0;
-	is_tag_ref = !prefixcmp(path, "refs/tags/");
-
-	/* ALWAYS pack refs that were already packed or are tags */
-	if (!(cb->flags & PACK_REFS_ALL) && !is_tag_ref && !(flags & REF_ISPACKED))
-		return 0;
-
-	fprintf(cb->refs_file, "%s %s\n", sha1_to_hex(sha1), path);
-	if (is_tag_ref) {
-		struct object *o = parse_object(sha1);
-		if (o->type == OBJ_TAG) {
-			o = deref_tag(o, path, 0);
-			if (o)
-				fprintf(cb->refs_file, "^%s\n",
-					sha1_to_hex(o->sha1));
-		}
-	}
-
-	if ((cb->flags & PACK_REFS_PRUNE) && !do_not_prune(flags)) {
-		int namelen = strlen(path) + 1;
-		struct ref_to_prune *n = xcalloc(1, sizeof(*n) + namelen);
-		hashcpy(n->sha1, sha1);
-		strcpy(n->name, path);
-		n->next = cb->ref_to_prune;
-		cb->ref_to_prune = n;
-	}
-	return 0;
-}
-
-/* make sure nobody touched the ref, and unlink */
-static void prune_ref(struct ref_to_prune *r)
-{
-	struct ref_lock *lock = lock_ref_sha1(r->name + 5, r->sha1);
-
-	if (lock) {
-		unlink(git_path("%s", r->name));
-		unlock_ref(lock);
-	}
-}
-
-static void prune_refs(struct ref_to_prune *r)
-{
-	while (r) {
-		prune_ref(r);
-		r = r->next;
-	}
-}
-
-static struct lock_file packed;
-
-static int pack_refs(unsigned int flags)
-{
-	int fd;
-	struct pack_refs_cb_data cbdata;
-
-	memset(&cbdata, 0, sizeof(cbdata));
-	cbdata.flags = flags;
-
-	fd = hold_lock_file_for_update(&packed, git_path("packed-refs"), 1);
-	cbdata.refs_file = fdopen(fd, "w");
-	if (!cbdata.refs_file)
-		die("unable to create ref-pack file structure (%s)",
-		    strerror(errno));
-
-	/* perhaps other traits later as well */
-	fprintf(cbdata.refs_file, "# pack-refs with: peeled \n");
-
-	for_each_ref(handle_one_ref, &cbdata);
-	if (ferror(cbdata.refs_file))
-		die("failed to write ref-pack file");
-	if (fflush(cbdata.refs_file) || fsync(fd) || fclose(cbdata.refs_file))
-		die("failed to write ref-pack file (%s)", strerror(errno));
-	/*
-	 * Since the lock file was fdopen()'ed and then fclose()'ed above,
-	 * assign -1 to the lock file descriptor so that commit_lock_file()
-	 * won't try to close() it.
-	 */
-	packed.fd = -1;
-	if (commit_lock_file(&packed) < 0)
-		die("unable to overwrite old ref-pack file (%s)", strerror(errno));
-	if (cbdata.flags & PACK_REFS_PRUNE)
-		prune_refs(cbdata.ref_to_prune);
-	return 0;
-}
+#include "pack-refs.h"
 
 static char const * const pack_refs_usage[] = {
-	"git-pack-refs [options]",
+	"git pack-refs [options]",
 	NULL
 };
 
diff --git a/builtin-prune-packed.c b/builtin-prune-packed.c
index 241afbb..10cb8df 100644
--- a/builtin-prune-packed.c
+++ b/builtin-prune-packed.c
@@ -3,7 +3,7 @@
 #include "progress.h"
 
 static const char prune_packed_usage[] =
-"git-prune-packed [-n] [-q]";
+"git prune-packed [-n] [-q]";
 
 #define DRY_RUN 01
 #define VERBOSE 02
diff --git a/builtin-prune.c b/builtin-prune.c
index bd3d2f6..1663f8b 100644
--- a/builtin-prune.c
+++ b/builtin-prune.c
@@ -7,12 +7,28 @@
 #include "parse-options.h"
 
 static const char * const prune_usage[] = {
-	"git-prune [-n] [--expire <time>] [--] [<head>...]",
+	"git prune [-n] [--expire <time>] [--] [<head>...]",
 	NULL
 };
 static int show_only;
 static unsigned long expire;
 
+static int prune_tmp_object(const char *path, const char *filename)
+{
+	const char *fullpath = mkpath("%s/%s", path, filename);
+	if (expire) {
+		struct stat st;
+		if (lstat(fullpath, &st))
+			return error("Could not stat '%s'", fullpath);
+		if (st.st_mtime > expire)
+			return 0;
+	}
+	printf("Removing stale temporary file %s\n", fullpath);
+	if (!show_only)
+		unlink(fullpath);
+	return 0;
+}
+
 static int prune_object(char *path, const char *filename, const unsigned char *sha1)
 {
 	const char *fullpath = mkpath("%s/%s", path, filename);
@@ -69,6 +85,10 @@
 			prune_object(path, de->d_name, sha1);
 			continue;
 		}
+		if (!prefixcmp(de->d_name, "tmp_obj_")) {
+			prune_tmp_object(path, de->d_name);
+			continue;
+		}
 		fprintf(stderr, "bad sha1 file: %s/%s\n", path, de->d_name);
 	}
 	if (!show_only)
@@ -90,38 +110,22 @@
 /*
  * Write errors (particularly out of space) can result in
  * failed temporary packs (and more rarely indexes and other
- * files begining with "tmp_") accumulating in the
- * object directory.
+ * files begining with "tmp_") accumulating in the object
+ * and the pack directories.
  */
-static void remove_temporary_files(void)
+static void remove_temporary_files(const char *path)
 {
 	DIR *dir;
 	struct dirent *de;
-	char* dirname=get_object_directory();
 
-	dir = opendir(dirname);
+	dir = opendir(path);
 	if (!dir) {
-		fprintf(stderr, "Unable to open object directory %s\n",
-			dirname);
+		fprintf(stderr, "Unable to open directory %s\n", path);
 		return;
 	}
-	while ((de = readdir(dir)) != NULL) {
-		if (!prefixcmp(de->d_name, "tmp_")) {
-			char name[PATH_MAX];
-			int c = snprintf(name, PATH_MAX, "%s/%s",
-					 dirname, de->d_name);
-			if (c < 0 || c >= PATH_MAX)
-				continue;
-			if (expire) {
-				struct stat st;
-				if (stat(name, &st) != 0 || st.st_mtime >= expire)
-					continue;
-			}
-			printf("Removing stale temporary file %s\n", name);
-			if (!show_only)
-				unlink(name);
-		}
-	}
+	while ((de = readdir(dir)) != NULL)
+		if (!prefixcmp(de->d_name, "tmp_"))
+			prune_tmp_object(path, de->d_name);
 	closedir(dir);
 }
 
@@ -135,6 +139,7 @@
 			 "expire objects older than <time>"),
 		OPT_END()
 	};
+	char *s;
 
 	save_commit_buffer = 0;
 	init_revisions(&revs, prefix);
@@ -157,6 +162,9 @@
 	prune_object_dir(get_object_directory());
 
 	prune_packed_objects(show_only);
-	remove_temporary_files();
+	remove_temporary_files(get_object_directory());
+	s = xstrdup(mkpath("%s/pack", get_object_directory()));
+	remove_temporary_files(s);
+	free(s);
 	return 0;
 }
diff --git a/builtin-push.c b/builtin-push.c
index b35aad6..f5cc762 100644
--- a/builtin-push.c
+++ b/builtin-push.c
@@ -10,11 +10,11 @@
 #include "parse-options.h"
 
 static const char * const push_usage[] = {
-	"git-push [--all | --mirror] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]",
+	"git push [--all | --mirror] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>] [--repo=<repository>] [-f | --force] [-v] [<repository> <refspec>...]",
 	NULL,
 };
 
-static int thin, verbose;
+static int thin;
 static const char *receivepack;
 
 static const char **refspec;
@@ -84,7 +84,7 @@
 		if (thin)
 			transport_set_option(transport, TRANS_OPT_THIN, "yes");
 
-		if (verbose)
+		if (flags & TRANSPORT_PUSH_VERBOSE)
 			fprintf(stderr, "Pushing to %s\n", remote->url[i]);
 		err = transport_push(transport, refspec_nr, refspec, flags);
 		err |= transport_disconnect(transport);
@@ -101,22 +101,19 @@
 int cmd_push(int argc, const char **argv, const char *prefix)
 {
 	int flags = 0;
-	int all = 0;
-	int mirror = 0;
-	int dry_run = 0;
-	int force = 0;
 	int tags = 0;
 	int rc;
 	const char *repo = NULL;	/* default repository */
 
 	struct option options[] = {
-		OPT__VERBOSE(&verbose),
+		OPT_BIT('v', "verbose", &flags, "be verbose", TRANSPORT_PUSH_VERBOSE),
 		OPT_STRING( 0 , "repo", &repo, "repository", "repository"),
-		OPT_BOOLEAN( 0 , "all", &all, "push all refs"),
-		OPT_BOOLEAN( 0 , "mirror", &mirror, "mirror all refs"),
+		OPT_BIT( 0 , "all", &flags, "push all refs", TRANSPORT_PUSH_ALL),
+		OPT_BIT( 0 , "mirror", &flags, "mirror all refs",
+			    (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
 		OPT_BOOLEAN( 0 , "tags", &tags, "push tags"),
-		OPT_BOOLEAN( 0 , "dry-run", &dry_run, "dry run"),
-		OPT_BOOLEAN('f', "force", &force, "force updates"),
+		OPT_BIT( 0 , "dry-run", &flags, "dry run", TRANSPORT_PUSH_DRY_RUN),
+		OPT_BIT('f', "force", &flags, "force updates", TRANSPORT_PUSH_FORCE),
 		OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"),
 		OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"),
 		OPT_STRING( 0 , "exec", &receivepack, "receive-pack", "receive pack program"),
@@ -125,18 +122,8 @@
 
 	argc = parse_options(argc, argv, options, push_usage, 0);
 
-	if (force)
-		flags |= TRANSPORT_PUSH_FORCE;
-	if (dry_run)
-		flags |= TRANSPORT_PUSH_DRY_RUN;
-	if (verbose)
-		flags |= TRANSPORT_PUSH_VERBOSE;
 	if (tags)
 		add_refspec("refs/tags/*");
-	if (all)
-		flags |= TRANSPORT_PUSH_ALL;
-	if (mirror)
-		flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
 
 	if (argc > 0) {
 		repo = argv[0];
diff --git a/builtin-read-tree.c b/builtin-read-tree.c
index 5a09e17..38fef34 100644
--- a/builtin-read-tree.c
+++ b/builtin-read-tree.c
@@ -29,30 +29,6 @@
 	return 0;
 }
 
-static int read_cache_unmerged(void)
-{
-	int i;
-	struct cache_entry **dst;
-	struct cache_entry *last = NULL;
-
-	read_cache();
-	dst = active_cache;
-	for (i = 0; i < active_nr; i++) {
-		struct cache_entry *ce = active_cache[i];
-		if (ce_stage(ce)) {
-			remove_name_hash(ce);
-			if (last && !strcmp(ce->name, last->name))
-				continue;
-			cache_tree_invalidate_path(active_cache_tree, ce->name);
-			last = ce;
-			continue;
-		}
-		*dst++ = ce;
-	}
-	active_nr = dst - active_cache;
-	return !!last;
-}
-
 static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree)
 {
 	struct tree_desc desc;
@@ -88,7 +64,7 @@
 
 }
 
-static const char read_tree_usage[] = "git-read-tree (<sha> | [[-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>] [-u | -i]] [--exclude-per-directory=<gitignore>] [--index-output=<file>] <sha1> [<sha2> [<sha3>]])";
+static const char read_tree_usage[] = "git read-tree (<sha> | [[-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>] [-u | -i]] [--exclude-per-directory=<gitignore>] [--index-output=<file>] <sha1> [<sha2> [<sha3>]])";
 
 static struct lock_file lock_file;
 
@@ -218,6 +194,8 @@
 		usage(read_tree_usage);
 	if ((opts.dir && !opts.update))
 		die("--exclude-per-directory is meaningless unless -u");
+	if (opts.merge && !opts.index_only)
+		setup_work_tree();
 
 	if (opts.merge) {
 		if (stage < 2)
@@ -228,6 +206,7 @@
 			break;
 		case 2:
 			opts.fn = twoway_merge;
+			opts.initial_checkout = is_cache_unborn();
 			break;
 		case 3:
 		default:
diff --git a/builtin-reflog.c b/builtin-reflog.c
index 7d7047d..da96da3 100644
--- a/builtin-reflog.c
+++ b/builtin-reflog.c
@@ -13,9 +13,9 @@
  */
 
 static const char reflog_expire_usage[] =
-"git-reflog (show|expire) [--verbose] [--dry-run] [--stale-fix] [--expire=<time>] [--expire-unreachable=<time>] [--all] <refs>...";
+"git reflog (show|expire) [--verbose] [--dry-run] [--stale-fix] [--expire=<time>] [--expire-unreachable=<time>] [--all] <refs>...";
 static const char reflog_delete_usage[] =
-"git-reflog delete [--verbose] [--dry-run] [--rewrite] [--updateref] <refs>...";
+"git reflog delete [--verbose] [--dry-run] [--rewrite] [--updateref] <refs>...";
 
 static unsigned long default_reflog_expire;
 static unsigned long default_reflog_expire_unreachable;
@@ -277,11 +277,11 @@
 	lock = lock_any_ref_for_update(ref, sha1, 0);
 	if (!lock)
 		return error("cannot lock ref '%s'", ref);
-	log_file = xstrdup(git_path("logs/%s", ref));
+	log_file = git_pathdup("logs/%s", ref);
 	if (!file_exists(log_file))
 		goto finish;
 	if (!cmd->dry_run) {
-		newlog_path = xstrdup(git_path("logs/%s.lock", ref));
+		newlog_path = git_pathdup("logs/%s.lock", ref);
 		cb.newlog = fopen(newlog_path, "w");
 	}
 
@@ -630,7 +630,7 @@
  */
 
 static const char reflog_usage[] =
-"git-reflog (expire | ...)";
+"git reflog (expire | ...)";
 
 int cmd_reflog(int argc, const char **argv, const char *prefix)
 {
diff --git a/builtin-remote.c b/builtin-remote.c
index 145dd85..5af4e64 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -2,7 +2,7 @@
 #include "parse-options.h"
 #include "transport.h"
 #include "remote.h"
-#include "path-list.h"
+#include "string-list.h"
 #include "strbuf.h"
 #include "run-command.h"
 #include "refs.h"
@@ -29,19 +29,13 @@
 	return strcmp(string + len1 - len2, postfix);
 }
 
-static inline const char *skip_prefix(const char *name, const char *prefix)
-{
-	return !name ? "" :
-		prefixcmp(name, prefix) ?  name : name + strlen(prefix);
-}
-
 static int opt_parse_track(const struct option *opt, const char *arg, int not)
 {
-	struct path_list *list = opt->value;
+	struct string_list *list = opt->value;
 	if (not)
-		path_list_clear(list, 0);
+		string_list_clear(list, 0);
 	else
-		path_list_append(arg, list);
+		string_list_append(arg, list);
 	return 0;
 }
 
@@ -57,7 +51,7 @@
 static int add(int argc, const char **argv)
 {
 	int fetch = 0, mirror = 0;
-	struct path_list track = { NULL, 0, 0 };
+	struct string_list track = { NULL, 0, 0 };
 	const char *master = NULL;
 	struct remote *remote;
 	struct strbuf buf, buf2;
@@ -102,18 +96,18 @@
 	strbuf_addf(&buf, "remote.%s.fetch", name);
 
 	if (track.nr == 0)
-		path_list_append("*", &track);
+		string_list_append("*", &track);
 	for (i = 0; i < track.nr; i++) {
-		struct path_list_item *item = track.items + i;
+		struct string_list_item *item = track.items + i;
 
 		strbuf_reset(&buf2);
 		strbuf_addch(&buf2, '+');
 		if (mirror)
 			strbuf_addf(&buf2, "refs/%s:refs/%s",
-					item->path, item->path);
+					item->string, item->string);
 		else
 			strbuf_addf(&buf2, "refs/heads/%s:refs/remotes/%s/%s",
-					item->path, name, item->path);
+					item->string, name, item->string);
 		if (git_config_set_multivar(buf.buf, buf2.buf, "^$", 0))
 			return 1;
 	}
@@ -121,7 +115,7 @@
 	if (mirror) {
 		strbuf_reset(&buf);
 		strbuf_addf(&buf, "remote.%s.mirror", name);
-		if (git_config_set(buf.buf, "yes"))
+		if (git_config_set(buf.buf, "true"))
 			return 1;
 	}
 
@@ -141,23 +135,32 @@
 
 	strbuf_release(&buf);
 	strbuf_release(&buf2);
-	path_list_clear(&track, 0);
+	string_list_clear(&track, 0);
 
 	return 0;
 }
 
 struct branch_info {
 	char *remote;
-	struct path_list merge;
+	struct string_list merge;
 };
 
-static struct path_list branch_list;
+static struct string_list branch_list;
+
+static const char *abbrev_ref(const char *name, const char *prefix)
+{
+	const char *abbrev = skip_prefix(name, prefix);
+	if (abbrev)
+		return abbrev;
+	return name;
+}
+#define abbrev_branch(name) abbrev_ref((name), "refs/heads/")
 
 static int config_read_branches(const char *key, const char *value, void *cb)
 {
 	if (!prefixcmp(key, "branch.")) {
 		char *name;
-		struct path_list_item *item;
+		struct string_list_item *item;
 		struct branch_info *info;
 		enum { REMOTE, MERGE } type;
 
@@ -171,7 +174,7 @@
 		} else
 			return 0;
 
-		item = path_list_insert(name, &branch_list);
+		item = string_list_insert(name, &branch_list);
 
 		if (!item->util)
 			item->util = xcalloc(sizeof(struct branch_info), 1);
@@ -182,15 +185,15 @@
 			info->remote = xstrdup(value);
 		} else {
 			char *space = strchr(value, ' ');
-			value = skip_prefix(value, "refs/heads/");
+			value = abbrev_branch(value);
 			while (space) {
 				char *merge;
 				merge = xstrndup(value, space - value);
-				path_list_append(merge, &info->merge);
-				value = skip_prefix(space + 1, "refs/heads/");
+				string_list_append(merge, &info->merge);
+				value = abbrev_branch(space + 1);
 				space = strchr(value, ' ');
 			}
-			path_list_append(xstrdup(value), &info->merge);
+			string_list_append(xstrdup(value), &info->merge);
 		}
 	}
 	return 0;
@@ -201,12 +204,12 @@
 	if (branch_list.nr)
 		return;
 	git_config(config_read_branches, NULL);
-	sort_path_list(&branch_list);
+	sort_string_list(&branch_list);
 }
 
 struct ref_states {
 	struct remote *remote;
-	struct path_list new, stale, tracked;
+	struct string_list new, stale, tracked;
 };
 
 static int handle_one_branch(const char *refname,
@@ -218,16 +221,16 @@
 	memset(&refspec, 0, sizeof(refspec));
 	refspec.dst = (char *)refname;
 	if (!remote_find_tracking(states->remote, &refspec)) {
-		struct path_list_item *item;
-		const char *name = skip_prefix(refspec.src, "refs/heads/");
+		struct string_list_item *item;
+		const char *name = abbrev_branch(refspec.src);
 		/* symbolic refs pointing nowhere were handled already */
 		if ((flags & REF_ISSYMREF) ||
-				unsorted_path_list_has_path(&states->tracked,
+				unsorted_string_list_has_string(&states->tracked,
 					name) ||
-				unsorted_path_list_has_path(&states->new,
+				unsorted_string_list_has_string(&states->new,
 					name))
 			return 0;
-		item = path_list_append(name, &states->stale);
+		item = string_list_append(name, &states->stale);
 		item->util = xstrdup(refname);
 	}
 	return 0;
@@ -243,9 +246,9 @@
 			die("Could not get fetch map for refspec %s",
 				states->remote->fetch_refspec[i]);
 
-	states->new.strdup_paths = states->tracked.strdup_paths = 1;
+	states->new.strdup_strings = states->tracked.strdup_strings = 1;
 	for (ref = fetch_map; ref; ref = ref->next) {
-		struct path_list *target = &states->tracked;
+		struct string_list *target = &states->tracked;
 		unsigned char sha1[20];
 		void *util = NULL;
 
@@ -256,13 +259,12 @@
 			if (hashcmp(sha1, ref->new_sha1))
 				util = &states;
 		}
-		path_list_append(skip_prefix(ref->name, "refs/heads/"),
-				target)->util = util;
+		string_list_append(abbrev_branch(ref->name), target)->util = util;
 	}
 	free_refs(fetch_map);
 
 	for_each_ref(handle_one_branch, states);
-	sort_path_list(&states->stale);
+	sort_string_list(&states->stale);
 
 	return 0;
 }
@@ -294,7 +296,7 @@
 
 struct branches_for_remote {
 	struct remote *remote;
-	struct path_list *branches;
+	struct string_list *branches;
 	struct known_remotes *keep;
 };
 
@@ -303,7 +305,7 @@
 {
 	struct branches_for_remote *branches = cb_data;
 	struct refspec refspec;
-	struct path_list_item *item;
+	struct string_list_item *item;
 	struct known_remote *kr;
 
 	memset(&refspec, 0, sizeof(refspec));
@@ -321,24 +323,24 @@
 
 	/* make sure that symrefs are deleted */
 	if (flags & REF_ISSYMREF)
-		return unlink(git_path(refname));
+		return unlink(git_path("%s", refname));
 
-	item = path_list_append(refname, branches->branches);
+	item = string_list_append(refname, branches->branches);
 	item->util = xmalloc(20);
 	hashcpy(item->util, sha1);
 
 	return 0;
 }
 
-static int remove_branches(struct path_list *branches)
+static int remove_branches(struct string_list *branches)
 {
 	int i, result = 0;
 	for (i = 0; i < branches->nr; i++) {
-		struct path_list_item *item = branches->items + i;
-		const char *refname = item->path;
+		struct string_list_item *item = branches->items + i;
+		const char *refname = item->string;
 		unsigned char *sha1 = item->util;
 
-		if (delete_ref(refname, sha1))
+		if (delete_ref(refname, sha1, 0))
 			result |= error("Could not remove branch %s", refname);
 	}
 	return result;
@@ -352,7 +354,7 @@
 	struct remote *remote;
 	struct strbuf buf;
 	struct known_remotes known_remotes = { NULL, NULL };
-	struct path_list branches = { NULL, 0, 0, 1 };
+	struct string_list branches = { NULL, 0, 0, 1 };
 	struct branches_for_remote cb_data = { NULL, &branches, &known_remotes };
 	int i;
 
@@ -373,14 +375,14 @@
 
 	read_branches();
 	for (i = 0; i < branch_list.nr; i++) {
-		struct path_list_item *item = branch_list.items + i;
+		struct string_list_item *item = branch_list.items + i;
 		struct branch_info *info = item->util;
 		if (info->remote && !strcmp(info->remote, remote->name)) {
 			const char *keys[] = { "remote", "merge", NULL }, **k;
 			for (k = keys; *k; k++) {
 				strbuf_reset(&buf);
 				strbuf_addf(&buf, "branch.%s.%s",
-						item->path, *k);
+						item->string, *k);
 				if (git_config_set(buf.buf, NULL)) {
 					strbuf_release(&buf);
 					return -1;
@@ -400,22 +402,23 @@
 
 	if (!i)
 		i = remove_branches(&branches);
-	path_list_clear(&branches, 1);
+	string_list_clear(&branches, 1);
 
 	return i;
 }
 
-static void show_list(const char *title, struct path_list *list)
+static void show_list(const char *title, struct string_list *list,
+		      const char *extra_arg)
 {
 	int i;
 
 	if (!list->nr)
 		return;
 
-	printf(title, list->nr > 1 ? "es" : "");
+	printf(title, list->nr > 1 ? "es" : "", extra_arg);
 	printf("\n    ");
 	for (i = 0; i < list->nr; i++)
-		printf("%s%s", i ? " " : "", list->items[i].path);
+		printf("%s%s", i ? " " : "", list->items[i].string);
 	printf("\n");
 }
 
@@ -452,10 +455,8 @@
 
 	memset(&refspec, 0, sizeof(refspec));
 	refspec.dst = (char *)refname;
-	if (!remote_find_tracking(states->remote, &refspec)) {
-		path_list_append(skip_prefix(refspec.src, "refs/heads/"),
-			&states->tracked);
-	}
+	if (!remote_find_tracking(states->remote, &refspec))
+		string_list_append(abbrev_branch(refspec.src), &states->tracked);
 
 	return 0;
 }
@@ -477,7 +478,6 @@
 
 	memset(&states, 0, sizeof(states));
 	for (; argc; argc--, argv++) {
-		struct strbuf buf;
 		int i;
 
 		get_remote_ref_states(*argv, &states, !no_query);
@@ -487,7 +487,7 @@
 				states.remote->url[0] : "(no URL)");
 
 		for (i = 0; i < branch_list.nr; i++) {
-			struct path_list_item *branch = branch_list.items + i;
+			struct string_list_item *branch = branch_list.items + i;
 			struct branch_info *info = branch->util;
 			int j;
 
@@ -496,25 +496,23 @@
 			printf("  Remote branch%s merged with 'git pull' "
 				"while on branch %s\n   ",
 				info->merge.nr > 1 ? "es" : "",
-				branch->path);
+				branch->string);
 			for (j = 0; j < info->merge.nr; j++)
-				printf(" %s", info->merge.items[j].path);
+				printf(" %s", info->merge.items[j].string);
 			printf("\n");
 		}
 
 		if (!no_query) {
-			strbuf_init(&buf, 0);
-			strbuf_addf(&buf, "  New remote branch%%s (next fetch "
-				"will store in remotes/%s)", states.remote->name);
-			show_list(buf.buf, &states.new);
-			strbuf_release(&buf);
+			show_list("  New remote branch%s (next fetch "
+				"will store in remotes/%s)",
+				&states.new, states.remote->name);
 			show_list("  Stale tracking branch%s (use 'git remote "
-				"prune')", &states.stale);
+				"prune')", &states.stale, "");
 		}
 
 		if (no_query)
 			for_each_ref(append_ref_to_tracked_list, &states);
-		show_list("  Tracked remote branch%s", &states.tracked);
+		show_list("  Tracked remote branch%s", &states.tracked, "");
 
 		if (states.remote->push_refspec_nr) {
 			printf("  Local branch%s pushed with 'git push'\n   ",
@@ -523,17 +521,17 @@
 			for (i = 0; i < states.remote->push_refspec_nr; i++) {
 				struct refspec *spec = states.remote->push + i;
 				printf(" %s%s%s%s", spec->force ? "+" : "",
-					skip_prefix(spec->src, "refs/heads/"),
-					spec->dst ? ":" : "",
-					skip_prefix(spec->dst, "refs/heads/"));
+				       abbrev_branch(spec->src),
+				       spec->dst ? ":" : "",
+				       spec->dst ? abbrev_branch(spec->dst) : "");
 			}
 			printf("\n");
 		}
 
 		/* NEEDSWORK: free remote */
-		path_list_clear(&states.new, 0);
-		path_list_clear(&states.stale, 0);
-		path_list_clear(&states.tracked, 0);
+		string_list_clear(&states.new, 0);
+		string_list_clear(&states.stale, 0);
+		string_list_clear(&states.tracked, 0);
 	}
 
 	return result;
@@ -572,16 +570,16 @@
 			const char *refname = states.stale.items[i].util;
 
 			if (!dry_run)
-				result |= delete_ref(refname, NULL);
+				result |= delete_ref(refname, NULL, 0);
 
 			printf(" * [%s] %s\n", dry_run ? "would prune" : "pruned",
-			       skip_prefix(refname, "refs/remotes/"));
+			       abbrev_ref(refname, "refs/remotes/"));
 		}
 
 		/* NEEDSWORK: free remote */
-		path_list_clear(&states.new, 0);
-		path_list_clear(&states.stale, 0);
-		path_list_clear(&states.tracked, 0);
+		string_list_clear(&states.new, 0);
+		string_list_clear(&states.stale, 0);
+		string_list_clear(&states.tracked, 0);
 	}
 
 	return result;
@@ -589,15 +587,15 @@
 
 static int get_one_remote_for_update(struct remote *remote, void *priv)
 {
-	struct path_list *list = priv;
+	struct string_list *list = priv;
 	if (!remote->skip_default_update)
-		path_list_append(xstrdup(remote->name), list);
+		string_list_append(xstrdup(remote->name), list);
 	return 0;
 }
 
 struct remote_group {
 	const char *name;
-	struct path_list *list;
+	struct string_list *list;
 } remote_group;
 
 static int get_remote_group(const char *key, const char *value, void *cb)
@@ -608,7 +606,7 @@
 		int space = strcspn(value, " \t\n");
 		while (*value) {
 			if (space > 1)
-				path_list_append(xstrndup(value, space),
+				string_list_append(xstrndup(value, space),
 						remote_group.list);
 			value += space + (value[space] != '\0');
 			space = strcspn(value, " \t\n");
@@ -621,7 +619,7 @@
 static int update(int argc, const char **argv)
 {
 	int i, result = 0;
-	struct path_list list = { NULL, 0, 0, 0 };
+	struct string_list list = { NULL, 0, 0, 0 };
 	static const char *default_argv[] = { NULL, "default", NULL };
 
 	if (argc < 2) {
@@ -639,42 +637,49 @@
 		result = for_each_remote(get_one_remote_for_update, &list);
 
 	for (i = 0; i < list.nr; i++)
-		result |= fetch_remote(list.items[i].path);
+		result |= fetch_remote(list.items[i].string);
 
 	/* all names were strdup()ed or strndup()ed */
-	list.strdup_paths = 1;
-	path_list_clear(&list, 0);
+	list.strdup_strings = 1;
+	string_list_clear(&list, 0);
 
 	return result;
 }
 
 static int get_one_entry(struct remote *remote, void *priv)
 {
-	struct path_list *list = priv;
+	struct string_list *list = priv;
 
-	path_list_append(remote->name, list)->util = remote->url_nr ?
-		(void *)remote->url[0] : NULL;
-	if (remote->url_nr > 1)
-		warning("Remote %s has more than one URL", remote->name);
+	if (remote->url_nr > 0) {
+		int i;
+
+		for (i = 0; i < remote->url_nr; i++)
+			string_list_append(remote->name, list)->util = (void *)remote->url[i];
+	} else
+		string_list_append(remote->name, list)->util = NULL;
 
 	return 0;
 }
 
 static int show_all(void)
 {
-	struct path_list list = { NULL, 0, 0 };
+	struct string_list list = { NULL, 0, 0 };
 	int result = for_each_remote(get_one_entry, &list);
 
 	if (!result) {
 		int i;
 
-		sort_path_list(&list);
+		sort_string_list(&list);
 		for (i = 0; i < list.nr; i++) {
-			struct path_list_item *item = list.items + i;
-			printf("%s%s%s\n", item->path,
-				verbose ? "\t" : "",
-				verbose && item->util ?
-					(const char *)item->util : "");
+			struct string_list_item *item = list.items + i;
+			if (verbose)
+				printf("%s\t%s\n", item->string,
+					item->util ? (const char *)item->util : "");
+			else {
+				if (i && !strcmp((item - 1)->string, item->string))
+					continue;
+				printf("%s\n", item->string);
+			}
 		}
 	}
 	return result;
diff --git a/builtin-rerere.c b/builtin-rerere.c
index 85222d9..dd4573f 100644
--- a/builtin-rerere.c
+++ b/builtin-rerere.c
@@ -1,193 +1,32 @@
 #include "builtin.h"
 #include "cache.h"
-#include "path-list.h"
+#include "string-list.h"
+#include "rerere.h"
 #include "xdiff/xdiff.h"
 #include "xdiff-interface.h"
 
-#include <time.h>
-
 static const char git_rerere_usage[] =
-"git-rerere [clear | status | diff | gc]";
+"git rerere [clear | status | diff | gc]";
 
 /* these values are days */
 static int cutoff_noresolve = 15;
 static int cutoff_resolve = 60;
 
-/* if rerere_enabled == -1, fall back to detection of .git/rr-cache */
-static int rerere_enabled = -1;
-
-static char *merge_rr_path;
-
 static const char *rr_path(const char *name, const char *file)
 {
 	return git_path("rr-cache/%s/%s", name, file);
 }
 
-static void read_rr(struct path_list *rr)
+static time_t rerere_created_at(const char *name)
 {
-	unsigned char sha1[20];
-	char buf[PATH_MAX];
-	FILE *in = fopen(merge_rr_path, "r");
-	if (!in)
-		return;
-	while (fread(buf, 40, 1, in) == 1) {
-		int i;
-		char *name;
-		if (get_sha1_hex(buf, sha1))
-			die("corrupt MERGE_RR");
-		buf[40] = '\0';
-		name = xstrdup(buf);
-		if (fgetc(in) != '\t')
-			die("corrupt MERGE_RR");
-		for (i = 0; i < sizeof(buf) && (buf[i] = fgetc(in)); i++)
-			; /* do nothing */
-		if (i == sizeof(buf))
-			die("filename too long");
-		path_list_insert(buf, rr)->util = name;
-	}
-	fclose(in);
+	struct stat st;
+	return stat(rr_path(name, "preimage"), &st) ? (time_t) 0 : st.st_mtime;
 }
 
-static struct lock_file write_lock;
-
-static int write_rr(struct path_list *rr, int out_fd)
+static int has_resolution(const char *name)
 {
-	int i;
-	for (i = 0; i < rr->nr; i++) {
-		const char *path = rr->items[i].path;
-		int length = strlen(path) + 1;
-		if (write_in_full(out_fd, rr->items[i].util, 40) != 40 ||
-		    write_in_full(out_fd, "\t", 1) != 1 ||
-		    write_in_full(out_fd, path, length) != length)
-			die("unable to write rerere record");
-	}
-	if (commit_lock_file(&write_lock) != 0)
-		die("unable to write rerere record");
-	return 0;
-}
-
-static int handle_file(const char *path,
-	 unsigned char *sha1, const char *output)
-{
-	SHA_CTX ctx;
-	char buf[1024];
-	int hunk = 0, hunk_no = 0;
-	struct strbuf one, two;
-	FILE *f = fopen(path, "r");
-	FILE *out = NULL;
-
-	if (!f)
-		return error("Could not open %s", path);
-
-	if (output) {
-		out = fopen(output, "w");
-		if (!out) {
-			fclose(f);
-			return error("Could not write %s", output);
-		}
-	}
-
-	if (sha1)
-		SHA1_Init(&ctx);
-
-	strbuf_init(&one, 0);
-	strbuf_init(&two,  0);
-	while (fgets(buf, sizeof(buf), f)) {
-		if (!prefixcmp(buf, "<<<<<<< "))
-			hunk = 1;
-		else if (!prefixcmp(buf, "======="))
-			hunk = 2;
-		else if (!prefixcmp(buf, ">>>>>>> ")) {
-			int cmp = strbuf_cmp(&one, &two);
-
-			hunk_no++;
-			hunk = 0;
-			if (cmp > 0) {
-				strbuf_swap(&one, &two);
-			}
-			if (out) {
-				fputs("<<<<<<<\n", out);
-				fwrite(one.buf, one.len, 1, out);
-				fputs("=======\n", out);
-				fwrite(two.buf, two.len, 1, out);
-				fputs(">>>>>>>\n", out);
-			}
-			if (sha1) {
-				SHA1_Update(&ctx, one.buf ? one.buf : "",
-					    one.len + 1);
-				SHA1_Update(&ctx, two.buf ? two.buf : "",
-					    two.len + 1);
-			}
-			strbuf_reset(&one);
-			strbuf_reset(&two);
-		} else if (hunk == 1)
-			strbuf_addstr(&one, buf);
-		else if (hunk == 2)
-			strbuf_addstr(&two, buf);
-		else if (out)
-			fputs(buf, out);
-	}
-	strbuf_release(&one);
-	strbuf_release(&two);
-
-	fclose(f);
-	if (out)
-		fclose(out);
-	if (sha1)
-		SHA1_Final(sha1, &ctx);
-	return hunk_no;
-}
-
-static int find_conflict(struct path_list *conflict)
-{
-	int i;
-	if (read_cache() < 0)
-		return error("Could not read index");
-	for (i = 0; i+1 < active_nr; i++) {
-		struct cache_entry *e2 = active_cache[i];
-		struct cache_entry *e3 = active_cache[i+1];
-		if (ce_stage(e2) == 2 &&
-		    ce_stage(e3) == 3 &&
-		    ce_same_name(e2, e3) &&
-		    S_ISREG(e2->ce_mode) &&
-		    S_ISREG(e3->ce_mode)) {
-			path_list_insert((const char *)e2->name, conflict);
-			i++; /* skip over both #2 and #3 */
-		}
-	}
-	return 0;
-}
-
-static int merge(const char *name, const char *path)
-{
-	int ret;
-	mmfile_t cur, base, other;
-	mmbuffer_t result = {NULL, 0};
-	xpparam_t xpp = {XDF_NEED_MINIMAL};
-
-	if (handle_file(path, NULL, rr_path(name, "thisimage")) < 0)
-		return 1;
-
-	if (read_mmfile(&cur, rr_path(name, "thisimage")) ||
-			read_mmfile(&base, rr_path(name, "preimage")) ||
-			read_mmfile(&other, rr_path(name, "postimage")))
-		return 1;
-	ret = xdl_merge(&base, &cur, "", &other, "",
-			&xpp, XDL_MERGE_ZEALOUS, &result);
-	if (!ret) {
-		FILE *f = fopen(path, "w");
-		if (!f)
-			return error("Could not write to %s", path);
-		fwrite(result.ptr, result.size, 1, f);
-		fclose(f);
-	}
-
-	free(cur.ptr);
-	free(base.ptr);
-	free(other.ptr);
-	free(result.ptr);
-
-	return ret;
+	struct stat st;
+	return !stat(rr_path(name, "postimage"), &st);
 }
 
 static void unlink_rr_item(const char *name)
@@ -198,40 +37,43 @@
 	rmdir(git_path("rr-cache/%s", name));
 }
 
-static void garbage_collect(struct path_list *rr)
+static int git_rerere_gc_config(const char *var, const char *value, void *cb)
 {
-	struct path_list to_remove = { NULL, 0, 0, 1 };
-	char buf[1024];
+	if (!strcmp(var, "gc.rerereresolved"))
+		cutoff_resolve = git_config_int(var, value);
+	else if (!strcmp(var, "gc.rerereunresolved"))
+		cutoff_noresolve = git_config_int(var, value);
+	else
+		return git_default_config(var, value, cb);
+	return 0;
+}
+
+static void garbage_collect(struct string_list *rr)
+{
+	struct string_list to_remove = { NULL, 0, 0, 1 };
 	DIR *dir;
 	struct dirent *e;
-	int len, i, cutoff;
+	int i, cutoff;
 	time_t now = time(NULL), then;
 
-	strlcpy(buf, git_path("rr-cache"), sizeof(buf));
-	len = strlen(buf);
-	dir = opendir(buf);
-	strcpy(buf + len++, "/");
+	git_config(git_rerere_gc_config, NULL);
+	dir = opendir(git_path("rr-cache"));
 	while ((e = readdir(dir))) {
 		const char *name = e->d_name;
-		struct stat st;
-		if (name[0] == '.' && (name[1] == '\0' ||
-					(name[1] == '.' && name[2] == '\0')))
+		if (name[0] == '.' &&
+		    (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
 			continue;
-		i = snprintf(buf + len, sizeof(buf) - len, "%s", name);
-		strlcpy(buf + len + i, "/preimage", sizeof(buf) - len - i);
-		if (stat(buf, &st))
+		then = rerere_created_at(name);
+		if (!then)
 			continue;
-		then = st.st_mtime;
-		strlcpy(buf + len + i, "/postimage", sizeof(buf) - len - i);
-		cutoff = stat(buf, &st) ? cutoff_noresolve : cutoff_resolve;
-		if (then < now - cutoff * 86400) {
-			buf[len + i] = '\0';
-			path_list_insert(xstrdup(name), &to_remove);
-		}
+		cutoff = (has_resolution(name)
+			  ? cutoff_resolve : cutoff_noresolve);
+		if (then < now - cutoff * 86400)
+			string_list_append(name, &to_remove);
 	}
 	for (i = 0; i < to_remove.nr; i++)
-		unlink_rr_item(to_remove.items[i].path);
-	path_list_clear(&to_remove, 0);
+		unlink_rr_item(to_remove.items[i].string);
+	string_list_clear(&to_remove, 0);
 }
 
 static int outf(void *dummy, mmbuffer_t *ptr, int nbuf)
@@ -267,171 +109,39 @@
 	return 0;
 }
 
-static int do_plain_rerere(struct path_list *rr, int fd)
-{
-	struct path_list conflict = { NULL, 0, 0, 1 };
-	int i;
-
-	find_conflict(&conflict);
-
-	/*
-	 * MERGE_RR records paths with conflicts immediately after merge
-	 * failed.  Some of the conflicted paths might have been hand resolved
-	 * in the working tree since then, but the initial run would catch all
-	 * and register their preimages.
-	 */
-
-	for (i = 0; i < conflict.nr; i++) {
-		const char *path = conflict.items[i].path;
-		if (!path_list_has_path(rr, path)) {
-			unsigned char sha1[20];
-			char *hex;
-			int ret;
-			ret = handle_file(path, sha1, NULL);
-			if (ret < 1)
-				continue;
-			hex = xstrdup(sha1_to_hex(sha1));
-			path_list_insert(path, rr)->util = hex;
-			if (mkdir(git_path("rr-cache/%s", hex), 0755))
-				continue;;
-			handle_file(path, NULL, rr_path(hex, "preimage"));
-			fprintf(stderr, "Recorded preimage for '%s'\n", path);
-		}
-	}
-
-	/*
-	 * Now some of the paths that had conflicts earlier might have been
-	 * hand resolved.  Others may be similar to a conflict already that
-	 * was resolved before.
-	 */
-
-	for (i = 0; i < rr->nr; i++) {
-		struct stat st;
-		int ret;
-		const char *path = rr->items[i].path;
-		const char *name = (const char *)rr->items[i].util;
-
-		if (!stat(rr_path(name, "preimage"), &st) &&
-				!stat(rr_path(name, "postimage"), &st)) {
-			if (!merge(name, path)) {
-				fprintf(stderr, "Resolved '%s' using "
-						"previous resolution.\n", path);
-				goto tail_optimization;
-			}
-		}
-
-		/* Let's see if we have resolved it. */
-		ret = handle_file(path, NULL, NULL);
-		if (ret)
-			continue;
-
-		fprintf(stderr, "Recorded resolution for '%s'.\n", path);
-		copy_file(rr_path(name, "postimage"), path, 0666);
-tail_optimization:
-		if (i < rr->nr - 1)
-			memmove(rr->items + i,
-				rr->items + i + 1,
-				sizeof(rr->items[0]) * (rr->nr - i - 1));
-		rr->nr--;
-		i--;
-	}
-
-	return write_rr(rr, fd);
-}
-
-static int git_rerere_config(const char *var, const char *value, void *cb)
-{
-	if (!strcmp(var, "gc.rerereresolved"))
-		cutoff_resolve = git_config_int(var, value);
-	else if (!strcmp(var, "gc.rerereunresolved"))
-		cutoff_noresolve = git_config_int(var, value);
-	else if (!strcmp(var, "rerere.enabled"))
-		rerere_enabled = git_config_bool(var, value);
-	else
-		return git_default_config(var, value, cb);
-	return 0;
-}
-
-static int is_rerere_enabled(void)
-{
-	struct stat st;
-	const char *rr_cache;
-	int rr_cache_exists;
-
-	if (!rerere_enabled)
-		return 0;
-
-	rr_cache = git_path("rr-cache");
-	rr_cache_exists = !stat(rr_cache, &st) && S_ISDIR(st.st_mode);
-	if (rerere_enabled < 0)
-		return rr_cache_exists;
-
-	if (!rr_cache_exists &&
-	    (mkdir(rr_cache, 0777) || adjust_shared_perm(rr_cache)))
-		die("Could not create directory %s", rr_cache);
-	return 1;
-}
-
-static int setup_rerere(struct path_list *merge_rr)
-{
-	int fd;
-
-	git_config(git_rerere_config, NULL);
-	if (!is_rerere_enabled())
-		return -1;
-
-	merge_rr_path = xstrdup(git_path("rr-cache/MERGE_RR"));
-	fd = hold_lock_file_for_update(&write_lock, merge_rr_path, 1);
-	read_rr(merge_rr);
-	return fd;
-}
-
-int rerere(void)
-{
-	struct path_list merge_rr = { NULL, 0, 0, 1 };
-	int fd;
-
-	fd = setup_rerere(&merge_rr);
-	if (fd < 0)
-		return 0;
-	return do_plain_rerere(&merge_rr, fd);
-}
-
 int cmd_rerere(int argc, const char **argv, const char *prefix)
 {
-	struct path_list merge_rr = { NULL, 0, 0, 1 };
+	struct string_list merge_rr = { NULL, 0, 0, 1 };
 	int i, fd;
 
+	if (argc < 2)
+		return rerere();
+
 	fd = setup_rerere(&merge_rr);
 	if (fd < 0)
 		return 0;
 
-	if (argc < 2)
-		return do_plain_rerere(&merge_rr, fd);
-	else if (!strcmp(argv[1], "clear")) {
+	if (!strcmp(argv[1], "clear")) {
 		for (i = 0; i < merge_rr.nr; i++) {
-			struct stat st;
 			const char *name = (const char *)merge_rr.items[i].util;
-			if (!stat(git_path("rr-cache/%s", name), &st) &&
-					S_ISDIR(st.st_mode) &&
-					stat(rr_path(name, "postimage"), &st))
+			if (!has_resolution(name))
 				unlink_rr_item(name);
 		}
-		unlink(merge_rr_path);
+		unlink(git_path("rr-cache/MERGE_RR"));
 	} else if (!strcmp(argv[1], "gc"))
 		garbage_collect(&merge_rr);
 	else if (!strcmp(argv[1], "status"))
 		for (i = 0; i < merge_rr.nr; i++)
-			printf("%s\n", merge_rr.items[i].path);
+			printf("%s\n", merge_rr.items[i].string);
 	else if (!strcmp(argv[1], "diff"))
 		for (i = 0; i < merge_rr.nr; i++) {
-			const char *path = merge_rr.items[i].path;
+			const char *path = merge_rr.items[i].string;
 			const char *name = (const char *)merge_rr.items[i].util;
 			diff_two(rr_path(name, "preimage"), path, path, path);
 		}
 	else
 		usage(git_rerere_usage);
 
-	path_list_clear(&merge_rr, 1);
+	string_list_clear(&merge_rr, 1);
 	return 0;
 }
diff --git a/builtin-reset.c b/builtin-reset.c
index a0321694..9514b77 100644
--- a/builtin-reset.c
+++ b/builtin-reset.c
@@ -20,8 +20,8 @@
 #include "parse-options.h"
 
 static const char * const git_reset_usage[] = {
-	"git-reset [--mixed | --soft | --hard] [-q] [<commit>]",
-	"git-reset [--mixed] <commit> [--] <paths>...",
+	"git reset [--mixed | --soft | --hard] [-q] [<commit>]",
+	"git reset [--mixed] <commit> [--] <paths>...",
 	NULL
 };
 
@@ -85,7 +85,7 @@
 		printf("\n");
 }
 
-static int update_index_refresh(int fd, struct lock_file *index_lock)
+static int update_index_refresh(int fd, struct lock_file *index_lock, int flags)
 {
 	int result;
 
@@ -96,7 +96,8 @@
 
 	if (read_cache() < 0)
 		return error("Could not read index");
-	result = refresh_cache(0) ? 1 : 0;
+
+	result = refresh_cache(flags) ? 1 : 0;
 	if (write_cache(fd, active_cache, active_nr) ||
 			commit_locked_index(index_lock))
 		return error ("Could not refresh index");
@@ -120,6 +121,9 @@
 			struct cache_entry *ce;
 			ce = make_cache_entry(one->mode, one->sha1, one->path,
 				0, 0);
+			if (!ce)
+				die("make_cache_entry failed for path '%s'",
+				    one->path);
 			add_cache_entry(ce, ADD_CACHE_OK_TO_ADD |
 				ADD_CACHE_OK_TO_REPLACE);
 		} else
@@ -128,7 +132,7 @@
 }
 
 static int read_from_tree(const char *prefix, const char **argv,
-		unsigned char *tree_sha1)
+		unsigned char *tree_sha1, int refresh_flags)
 {
 	struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));
 	int index_fd, index_was_discarded = 0;
@@ -152,7 +156,7 @@
 	if (!index_was_discarded)
 		/* The index is still clobbered from do_diff_cache() */
 		discard_cache();
-	return update_index_refresh(index_fd, lock);
+	return update_index_refresh(index_fd, lock, refresh_flags);
 }
 
 static void prepend_reflog_action(const char *action, char *buf, size_t size)
@@ -246,7 +250,8 @@
 		else if (reset_type != NONE)
 			die("Cannot do %s reset with paths.",
 					reset_type_names[reset_type]);
-		return read_from_tree(prefix, argv + i, sha1);
+		return read_from_tree(prefix, argv + i, sha1,
+				quiet ? REFRESH_QUIET : REFRESH_SAY_CHANGED);
 	}
 	if (reset_type == NONE)
 		reset_type = MIXED; /* by default */
@@ -274,7 +279,7 @@
 		update_ref(msg, "ORIG_HEAD", orig, old_orig, 0, MSG_ON_ERR);
 	}
 	else if (old_orig)
-		delete_ref("ORIG_HEAD", old_orig);
+		delete_ref("ORIG_HEAD", old_orig, 0);
 	prepend_reflog_action("updating HEAD", msg, sizeof(msg));
 	update_ref_status = update_ref(msg, "HEAD", sha1, orig, 0, MSG_ON_ERR);
 
@@ -286,7 +291,8 @@
 	case SOFT: /* Nothing else to do. */
 		break;
 	case MIXED: /* Report what has not been updated. */
-		update_index_refresh(0, NULL);
+		update_index_refresh(0, NULL,
+				quiet ? REFRESH_QUIET : REFRESH_SAY_CHANGED);
 		break;
 	}
 
diff --git a/builtin-rev-list.c b/builtin-rev-list.c
index 39ec61c..facaff2 100644
--- a/builtin-rev-list.c
+++ b/builtin-rev-list.c
@@ -17,7 +17,7 @@
 #define COUNTED		(1u<<16)
 
 static const char rev_list_usage[] =
-"git-rev-list [OPTION] <commit-id>... [ -- paths... ]\n"
+"git rev-list [OPTION] <commit-id>... [ -- paths... ]\n"
 "  limiting output:\n"
 "    --max-count=nr\n"
 "    --max-age=epoch\n"
@@ -37,6 +37,7 @@
 "    --reverse\n"
 "  formatting output:\n"
 "    --parents\n"
+"    --children\n"
 "    --objects | --objects-edge\n"
 "    --unpacked\n"
 "    --header | --pretty\n"
@@ -90,6 +91,15 @@
 			parents = parents->next;
 		}
 	}
+	if (revs.children.name) {
+		struct commit_list *children;
+
+		children = lookup_decoration(&revs.children, &commit->object);
+		while (children) {
+			printf(" %s", sha1_to_hex(children->item->object.sha1));
+			children = children->next;
+		}
+	}
 	show_decorations(commit);
 	if (revs.commit_format == CMIT_FMT_ONELINE)
 		putchar(' ');
@@ -168,7 +178,7 @@
 static void show_object(struct object_array_entry *p)
 {
 	/* An object with name "foo\n0000000..." can be used to
-	 * confuse downstream git-pack-objects very badly.
+	 * confuse downstream "git pack-objects" very badly.
 	 */
 	const char *ep = strchr(p->name, '\n');
 
@@ -565,23 +575,6 @@
 	return best;
 }
 
-static void read_revisions_from_stdin(struct rev_info *revs)
-{
-	char line[1000];
-
-	while (fgets(line, sizeof(line), stdin) != NULL) {
-		int len = strlen(line);
-		if (len && line[len - 1] == '\n')
-			line[--len] = 0;
-		if (!len)
-			break;
-		if (line[0] == '-')
-			die("options not supported in --stdin mode");
-		if (handle_revision_arg(line, revs, 0, 1))
-			die("bad revision '%s'", line);
-	}
-}
-
 int cmd_rev_list(int argc, const char **argv, const char *prefix)
 {
 	struct commit_list *list;
@@ -652,7 +645,8 @@
 	    revs.diff)
 		usage(rev_list_usage);
 
-	save_commit_buffer = revs.verbose_header || revs.grep_filter;
+	save_commit_buffer = revs.verbose_header ||
+		revs.grep_filter.pattern_list;
 	if (bisect_list)
 		revs.limited = 1;
 
diff --git a/builtin-rev-parse.c b/builtin-rev-parse.c
index a7860ed..9aa049e 100644
--- a/builtin-rev-parse.c
+++ b/builtin-rev-parse.c
@@ -241,6 +241,36 @@
 	return 0;
 }
 
+static int try_parent_shorthands(const char *arg)
+{
+	char *dotdot;
+	unsigned char sha1[20];
+	struct commit *commit;
+	struct commit_list *parents;
+	int parents_only;
+
+	if ((dotdot = strstr(arg, "^!")))
+		parents_only = 0;
+	else if ((dotdot = strstr(arg, "^@")))
+		parents_only = 1;
+
+	if (!dotdot || dotdot[2])
+		return 0;
+
+	*dotdot = 0;
+	if (get_sha1(arg, sha1))
+		return 0;
+
+	if (!parents_only)
+		show_rev(NORMAL, sha1, arg);
+	commit = lookup_commit_reference(sha1);
+	for (parents = commit->parents; parents; parents = parents->next)
+		show_rev(parents_only ? NORMAL : REVERSED,
+				parents->item->object.sha1, arg);
+
+	return 1;
+}
+
 static int parseopt_dump(const struct option *o, const char *arg, int unset)
 {
 	struct strbuf *parsed = o->value;
@@ -268,7 +298,7 @@
 {
 	static int keep_dashdash = 0;
 	static char const * const parseopt_usage[] = {
-		"git-rev-parse --parseopt [options] -- [<args>...]",
+		"git rev-parse --parseopt [options] -- [<args>...]",
 		NULL
 	};
 	static struct option parseopt_opts[] = {
@@ -573,6 +603,8 @@
 		/* Not a flag argument */
 		if (try_difference(arg))
 			continue;
+		if (try_parent_shorthands(arg))
+			continue;
 		name = arg;
 		type = NORMAL;
 		if (*arg == '^') {
diff --git a/builtin-revert.c b/builtin-revert.c
index bde28b2..74845ef 100644
--- a/builtin-revert.c
+++ b/builtin-revert.c
@@ -24,12 +24,12 @@
  */
 
 static const char * const revert_usage[] = {
-	"git-revert [options] <commit-ish>",
+	"git revert [options] <commit-ish>",
 	NULL
 };
 
 static const char * const cherry_pick_usage[] = {
-	"git-cherry-pick [options] <commit-ish>",
+	"git cherry-pick [options] <commit-ish>",
 	NULL
 };
 
@@ -206,6 +206,7 @@
 {
 	char buffer[256];
 	const char *argv[6];
+	int i = 0;
 
 	sprintf(buffer, "GITHEAD_%s", head_sha1);
 	setenv(buffer, head_name, 1);
@@ -218,12 +219,13 @@
 	 * and $prev on top of us (when reverting), or the change between
 	 * $prev and $commit on top of us (when cherry-picking or replaying).
 	 */
-	argv[0] = "merge-recursive";
-	argv[1] = base_sha1;
-	argv[2] = "--";
-	argv[3] = head_sha1;
-	argv[4] = next_sha1;
-	argv[5] = NULL;
+	argv[i++] = "merge-recursive";
+	if (base_sha1)
+		argv[i++] = base_sha1;
+	argv[i++] = "--";
+	argv[i++] = head_sha1;
+	argv[i++] = next_sha1;
+	argv[i++] = NULL;
 
 	return run_command_v_opt(argv, RUN_COMMAND_NO_STDIN | RUN_GIT_CMD);
 }
@@ -267,7 +269,7 @@
 	int i;
 	char *oneline, *reencoded_message = NULL;
 	const char *message, *encoding;
-	const char *defmsg = xstrdup(git_path("MERGE_MSG"));
+	char *defmsg = git_pathdup("MERGE_MSG");
 
 	git_config(git_default_config, NULL);
 	me = action == REVERT ? "revert" : "cherry-pick";
@@ -297,9 +299,12 @@
 		discard_cache();
 	}
 
-	if (!commit->parents)
-		die ("Cannot %s a root commit", me);
-	if (commit->parents->next) {
+	if (!commit->parents) {
+		if (action == REVERT)
+			die ("Cannot revert a root commit");
+		parent = NULL;
+	}
+	else if (commit->parents->next) {
 		/* Reverting or cherry-picking a merge commit */
 		int cnt;
 		struct commit_list *p;
@@ -333,7 +338,8 @@
 	 * reverse of it if we are revert.
 	 */
 
-	msg_fd = hold_lock_file_for_update(&msg_file, defmsg, 1);
+	msg_fd = hold_lock_file_for_update(&msg_file, defmsg,
+					   LOCK_DIE_ON_ERROR);
 
 	encoding = get_encoding(message);
 	if (!encoding)
@@ -368,7 +374,8 @@
 		}
 	}
 
-	if (merge_recursive(sha1_to_hex(base->object.sha1),
+	if (merge_recursive(base == NULL ?
+				NULL : sha1_to_hex(base->object.sha1),
 				sha1_to_hex(head), "HEAD",
 				sha1_to_hex(next->object.sha1), oneline) ||
 			write_cache_as_tree(head, 0, NULL)) {
@@ -420,6 +427,7 @@
 		return execv_git_cmd(args);
 	}
 	free(reencoded_message);
+	free(defmsg);
 
 	return 0;
 }
diff --git a/builtin-rm.c b/builtin-rm.c
index abdab7f..e06640c 100644
--- a/builtin-rm.c
+++ b/builtin-rm.c
@@ -11,7 +11,7 @@
 #include "parse-options.h"
 
 static const char * const builtin_rm_usage[] = {
-	"git-rm [options] [--] <file>...",
+	"git rm [options] [--] <file>...",
 	NULL
 };
 
@@ -29,26 +29,6 @@
 	list.name[list.nr++] = name;
 }
 
-static int remove_file(const char *name)
-{
-	int ret;
-	char *slash;
-
-	ret = unlink(name);
-	if (ret && errno == ENOENT)
-		/* The user has removed it from the filesystem by hand */
-		ret = errno = 0;
-
-	if (!ret && (slash = strrchr(name, '/'))) {
-		char *n = xstrdup(name);
-		do {
-			n[slash - name] = 0;
-			name = n;
-		} while (!rmdir(name) && (slash = strrchr(name, '/')));
-	}
-	return ret;
-}
-
 static int check_local_mod(unsigned char *head, int index_only)
 {
 	/* items in list are already sorted in the cache order,
@@ -104,7 +84,7 @@
 				     "from both the file and the HEAD\n"
 				     "(use -f to force removal)", name);
 		else if (!index_only) {
-			/* It's not dangerous to git-rm --cached a
+			/* It's not dangerous to "git rm --cached" a
 			 * file if the index matches the file or the
 			 * HEAD, since it means the deleted content is
 			 * still available somewhere.
@@ -131,7 +111,7 @@
 	OPT__DRY_RUN(&show_only),
 	OPT__QUIET(&quiet),
 	OPT_BOOLEAN( 0 , "cached",         &index_only, "only remove from the index"),
-	OPT_BOOLEAN('f', NULL,             &force,      "override the up-to-date check"),
+	OPT_BOOLEAN('f', "force",          &force,      "override the up-to-date check"),
 	OPT_BOOLEAN('r', NULL,             &recursive,  "allow recursive removal"),
 	OPT_BOOLEAN( 0 , "ignore-unmatch", &ignore_unmatch,
 				"exit with a zero status even if nothing matched"),
@@ -157,6 +137,7 @@
 
 	if (read_cache() < 0)
 		die("index file corrupt");
+	refresh_cache(REFRESH_QUIET);
 
 	pathspec = get_pathspec(prefix, argv);
 	seen = NULL;
@@ -221,7 +202,7 @@
 			printf("rm '%s'\n", path);
 
 		if (remove_file_from_cache(path))
-			die("git-rm: unable to remove %s", path);
+			die("git rm: unable to remove %s", path);
 	}
 
 	if (show_only)
@@ -239,12 +220,12 @@
 		int removed = 0;
 		for (i = 0; i < list.nr; i++) {
 			const char *path = list.name[i];
-			if (!remove_file(path)) {
+			if (!remove_path(path)) {
 				removed = 1;
 				continue;
 			}
 			if (!removed)
-				die("git-rm: %s: %s", path, strerror(errno));
+				die("git rm: %s: %s", path, strerror(errno));
 		}
 	}
 
diff --git a/builtin-send-pack.c b/builtin-send-pack.c
index a708d0a..e428eac 100644
--- a/builtin-send-pack.c
+++ b/builtin-send-pack.c
@@ -8,7 +8,7 @@
 #include "send-pack.h"
 
 static const char send_pack_usage[] =
-"git-send-pack [--all | --mirror] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\n"
+"git send-pack [--all | --mirror] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [<host>:]<directory> [<ref>...]\n"
 "  --all and explicit <ref> specification are mutually exclusive.";
 
 static struct send_pack_args args = {
@@ -43,7 +43,7 @@
 	po.out = fd;
 	po.git_cmd = 1;
 	if (start_command(&po))
-		die("git-pack-objects failed (%s)", strerror(errno));
+		die("git pack-objects failed (%s)", strerror(errno));
 
 	/*
 	 * We feed the pack-objects we just spawned with revision
@@ -132,7 +132,13 @@
 static int one_local_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
 {
 	struct ref *ref;
-	int len = strlen(refname) + 1;
+	int len;
+
+	/* we already know it starts with refs/ to get here */
+	if (check_ref_format(refname + 5))
+		return 0;
+
+	len = strlen(refname) + 1;
 	ref = xcalloc(1, sizeof(*ref) + len);
 	hashcpy(ref->new_sha1, sha1);
 	memcpy(ref->name, refname, len);
@@ -216,7 +222,7 @@
 {
 	struct refspec rs;
 
-	if (ref->status != REF_STATUS_OK)
+	if (ref->status != REF_STATUS_OK && ref->status != REF_STATUS_UPTODATE)
 		return;
 
 	rs.src = ref->name;
@@ -226,7 +232,7 @@
 		if (args.verbose)
 			fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst);
 		if (ref->deletion) {
-			delete_ref(rs.dst, NULL);
+			delete_ref(rs.dst, NULL, 0);
 		} else
 			update_ref("update by push", rs.dst,
 					ref->new_sha1, NULL, 0, 0);
@@ -418,24 +424,19 @@
 	 */
 	new_refs = 0;
 	for (ref = remote_refs; ref; ref = ref->next) {
-		const unsigned char *new_sha1;
 
-		if (!ref->peer_ref) {
-			if (!args.send_mirror)
-				continue;
-			new_sha1 = null_sha1;
-		}
-		else
-			new_sha1 = ref->peer_ref->new_sha1;
+		if (ref->peer_ref)
+			hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
+		else if (!args.send_mirror)
+			continue;
 
-
-		ref->deletion = is_null_sha1(new_sha1);
+		ref->deletion = is_null_sha1(ref->new_sha1);
 		if (ref->deletion && !allow_deleting_refs) {
 			ref->status = REF_STATUS_REJECT_NODELETE;
 			continue;
 		}
 		if (!ref->deletion &&
-		    !hashcmp(ref->old_sha1, new_sha1)) {
+		    !hashcmp(ref->old_sha1, ref->new_sha1)) {
 			ref->status = REF_STATUS_UPTODATE;
 			continue;
 		}
@@ -463,14 +464,13 @@
 		    !ref->deletion &&
 		    !is_null_sha1(ref->old_sha1) &&
 		    (!has_sha1_file(ref->old_sha1)
-		      || !ref_newer(new_sha1, ref->old_sha1));
+		      || !ref_newer(ref->new_sha1, ref->old_sha1));
 
 		if (ref->nonfastforward && !ref->force && !args.force_update) {
 			ref->status = REF_STATUS_REJECT_NONFASTFORWARD;
 			continue;
 		}
 
-		hashcpy(ref->new_sha1, new_sha1);
 		if (!ref->deletion)
 			new_refs++;
 
diff --git a/builtin-shortlog.c b/builtin-shortlog.c
index e6a2865..d03f14f 100644
--- a/builtin-shortlog.c
+++ b/builtin-shortlog.c
@@ -2,19 +2,24 @@
 #include "cache.h"
 #include "commit.h"
 #include "diff.h"
-#include "path-list.h"
+#include "string-list.h"
 #include "revision.h"
 #include "utf8.h"
 #include "mailmap.h"
 #include "shortlog.h"
+#include "parse-options.h"
 
-static const char shortlog_usage[] =
-"git-shortlog [-n] [-s] [-e] [-w] [<commit-id>... ]";
+static char const * const shortlog_usage[] = {
+	"git shortlog [-n] [-s] [-e] [-w] [rev-opts] [--] [<commit-id>... ]",
+	"",
+	"[rev-opts] are documented in git-rev-list(1)",
+	NULL
+};
 
 static int compare_by_number(const void *a1, const void *a2)
 {
-	const struct path_list_item *i1 = a1, *i2 = a2;
-	const struct path_list *l1 = i1->util, *l2 = i2->util;
+	const struct string_list_item *i1 = a1, *i2 = a2;
+	const struct string_list *l1 = i1->util, *l2 = i2->util;
 
 	if (l1->nr < l2->nr)
 		return 1;
@@ -30,8 +35,8 @@
 {
 	const char *dot3 = log->common_repo_prefix;
 	char *buffer, *p;
-	struct path_list_item *item;
-	struct path_list *onelines;
+	struct string_list_item *item;
+	struct string_list *onelines;
 	char namebuf[1024];
 	size_t len;
 	const char *eol;
@@ -64,9 +69,9 @@
 	}
 
 	buffer = xstrdup(namebuf);
-	item = path_list_insert(buffer, &log->list);
+	item = string_list_insert(buffer, &log->list);
 	if (item->util == NULL)
-		item->util = xcalloc(1, sizeof(struct path_list));
+		item->util = xcalloc(1, sizeof(struct string_list));
 	else
 		free(buffer);
 
@@ -104,11 +109,11 @@
 		onelines->alloc = alloc_nr(onelines->nr);
 		onelines->items = xrealloc(onelines->items,
 				onelines->alloc
-				* sizeof(struct path_list_item));
+				* sizeof(struct string_list_item));
 	}
 
 	onelines->items[onelines->nr].util = NULL;
-	onelines->items[onelines->nr++].path = buffer;
+	onelines->items[onelines->nr++].string = buffer;
 }
 
 static void read_from_stdin(struct shortlog *log)
@@ -149,6 +154,15 @@
 	if (!author)
 		die("Missing author: %s",
 		    sha1_to_hex(commit->object.sha1));
+	if (log->user_format) {
+		struct strbuf buf = STRBUF_INIT;
+
+		pretty_print_commit(CMIT_FMT_USERFORMAT, commit, &buf,
+			DEFAULT_ABBREV, "", "", DATE_NORMAL, 0);
+		insert_one_record(log, author, buf.buf);
+		strbuf_release(&buf);
+		return;
+	}
 	if (*buffer)
 		buffer++;
 	insert_one_record(log, author, !*buffer ? "<none>" : buffer);
@@ -164,21 +178,19 @@
 		shortlog_add_commit(log, commit);
 }
 
-static int parse_uint(char const **arg, int comma)
+static int parse_uint(char const **arg, int comma, int defval)
 {
 	unsigned long ul;
 	int ret;
 	char *endp;
 
 	ul = strtoul(*arg, &endp, 10);
-	if (endp != *arg && *endp && *endp != comma)
+	if (*endp && *endp != comma)
 		return -1;
-	ret = (int) ul;
-	if (ret != ul)
+	if (ul > INT_MAX)
 		return -1;
-	*arg = endp;
-	if (**arg)
-		(*arg)++;
+	ret = *arg == endp ? defval : (int)ul;
+	*arg = *endp ? endp + 1 : endp;
 	return ret;
 }
 
@@ -187,30 +199,30 @@
 #define DEFAULT_INDENT1 6
 #define DEFAULT_INDENT2 9
 
-static void parse_wrap_args(const char *arg, int *in1, int *in2, int *wrap)
+static int parse_wrap_args(const struct option *opt, const char *arg, int unset)
 {
-	arg += 2; /* skip -w */
+	struct shortlog *log = opt->value;
 
-	*wrap = parse_uint(&arg, ',');
-	if (*wrap < 0)
-		die(wrap_arg_usage);
-	*in1 = parse_uint(&arg, ',');
-	if (*in1 < 0)
-		die(wrap_arg_usage);
-	*in2 = parse_uint(&arg, '\0');
-	if (*in2 < 0)
-		die(wrap_arg_usage);
+	log->wrap_lines = !unset;
+	if (unset)
+		return 0;
+	if (!arg) {
+		log->wrap = DEFAULT_WRAPLEN;
+		log->in1 = DEFAULT_INDENT1;
+		log->in2 = DEFAULT_INDENT2;
+		return 0;
+	}
 
-	if (!*wrap)
-		*wrap = DEFAULT_WRAPLEN;
-	if (!*in1)
-		*in1 = DEFAULT_INDENT1;
-	if (!*in2)
-		*in2 = DEFAULT_INDENT2;
-	if (*wrap &&
-	    ((*in1 && *wrap <= *in1) ||
-	     (*in2 && *wrap <= *in2)))
-		die(wrap_arg_usage);
+	log->wrap = parse_uint(&arg, ',', DEFAULT_WRAPLEN);
+	log->in1 = parse_uint(&arg, ',', DEFAULT_INDENT1);
+	log->in2 = parse_uint(&arg, '\0', DEFAULT_INDENT2);
+	if (log->wrap < 0 || log->in1 < 0 || log->in2 < 0)
+		return error(wrap_arg_usage);
+	if (log->wrap &&
+	    ((log->in1 && log->wrap <= log->in1) ||
+	     (log->in2 && log->wrap <= log->in2)))
+		return error(wrap_arg_usage);
+	return 0;
 }
 
 void shortlog_init(struct shortlog *log)
@@ -219,7 +231,7 @@
 
 	read_mailmap(&log->mailmap, ".mailmap", &log->common_repo_prefix);
 
-	log->list.strdup_paths = 1;
+	log->list.strdup_strings = 1;
 	log->wrap = DEFAULT_WRAPLEN;
 	log->in1 = DEFAULT_INDENT1;
 	log->in2 = DEFAULT_INDENT2;
@@ -227,38 +239,48 @@
 
 int cmd_shortlog(int argc, const char **argv, const char *prefix)
 {
-	struct shortlog log;
-	struct rev_info rev;
+	static struct shortlog log;
+	static struct rev_info rev;
 	int nongit;
 
+	static const struct option options[] = {
+		OPT_BOOLEAN('n', "numbered", &log.sort_by_number,
+			    "sort output according to the number of commits per author"),
+		OPT_BOOLEAN('s', "summary", &log.summary,
+			    "Suppress commit descriptions, only provides commit count"),
+		OPT_BOOLEAN('e', "email", &log.email,
+			    "Show the email address of each author"),
+		{ OPTION_CALLBACK, 'w', NULL, &log, "w[,i1[,i2]]",
+			"Linewrap output", PARSE_OPT_OPTARG, &parse_wrap_args },
+		OPT_END(),
+	};
+
+	struct parse_opt_ctx_t ctx;
+
 	prefix = setup_git_directory_gently(&nongit);
 	shortlog_init(&log);
-
-	/* since -n is a shadowed rev argument, parse our args first */
-	while (argc > 1) {
-		if (!strcmp(argv[1], "-n") || !strcmp(argv[1], "--numbered"))
-			log.sort_by_number = 1;
-		else if (!strcmp(argv[1], "-s") ||
-				!strcmp(argv[1], "--summary"))
-			log.summary = 1;
-		else if (!strcmp(argv[1], "-e") ||
-			 !strcmp(argv[1], "--email"))
-			log.email = 1;
-		else if (!prefixcmp(argv[1], "-w")) {
-			log.wrap_lines = 1;
-			parse_wrap_args(argv[1], &log.in1, &log.in2, &log.wrap);
-		}
-		else if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
-			usage(shortlog_usage);
-		else
-			break;
-		argv++;
-		argc--;
-	}
 	init_revisions(&rev, prefix);
-	argc = setup_revisions(argc, argv, &rev, NULL);
-	if (argc > 1)
-		die ("unrecognized argument: %s", argv[1]);
+	parse_options_start(&ctx, argc, argv, PARSE_OPT_KEEP_DASHDASH |
+			    PARSE_OPT_KEEP_ARGV0);
+
+	for (;;) {
+		switch (parse_options_step(&ctx, options, shortlog_usage)) {
+		case PARSE_OPT_HELP:
+			exit(129);
+		case PARSE_OPT_DONE:
+			goto parse_done;
+		}
+		parse_revision_opt(&rev, &ctx, options, shortlog_usage);
+	}
+parse_done:
+	argc = parse_options_end(&ctx);
+
+	if (setup_revisions(argc, argv, &rev, NULL) != 1) {
+		error("unrecognized argument: %s", argv[1]);
+		usage_with_options(shortlog_usage, options);
+	}
+
+	log.user_format = rev.commit_format == CMIT_FMT_USERFORMAT;
 
 	/* assume HEAD if from a tty */
 	if (!nongit && !rev.pending.nr && isatty(0))
@@ -277,17 +299,17 @@
 {
 	int i, j;
 	if (log->sort_by_number)
-		qsort(log->list.items, log->list.nr, sizeof(struct path_list_item),
+		qsort(log->list.items, log->list.nr, sizeof(struct string_list_item),
 			compare_by_number);
 	for (i = 0; i < log->list.nr; i++) {
-		struct path_list *onelines = log->list.items[i].util;
+		struct string_list *onelines = log->list.items[i].util;
 
 		if (log->summary) {
-			printf("%6d\t%s\n", onelines->nr, log->list.items[i].path);
+			printf("%6d\t%s\n", onelines->nr, log->list.items[i].string);
 		} else {
-			printf("%s (%d):\n", log->list.items[i].path, onelines->nr);
+			printf("%s (%d):\n", log->list.items[i].string, onelines->nr);
 			for (j = onelines->nr - 1; j >= 0; j--) {
-				const char *msg = onelines->items[j].path;
+				const char *msg = onelines->items[j].string;
 
 				if (log->wrap_lines) {
 					int col = print_wrapped_text(msg, log->in1, log->in2, log->wrap);
@@ -300,14 +322,14 @@
 			putchar('\n');
 		}
 
-		onelines->strdup_paths = 1;
-		path_list_clear(onelines, 1);
+		onelines->strdup_strings = 1;
+		string_list_clear(onelines, 1);
 		free(onelines);
 		log->list.items[i].util = NULL;
 	}
 
-	log->list.strdup_paths = 1;
-	path_list_clear(&log->list, 1);
-	log->mailmap.strdup_paths = 1;
-	path_list_clear(&log->mailmap, 1);
+	log->list.strdup_strings = 1;
+	string_list_clear(&log->list, 1);
+	log->mailmap.strdup_strings = 1;
+	string_list_clear(&log->mailmap, 1);
 }
diff --git a/builtin-show-branch.c b/builtin-show-branch.c
index 93047f5..233eed4 100644
--- a/builtin-show-branch.c
+++ b/builtin-show-branch.c
@@ -4,7 +4,7 @@
 #include "builtin.h"
 
 static const char show_branch_usage[] =
-"git-show-branch [--sparse] [--current] [--all] [--remotes] [--topo-order] [--more=count | --list | --independent | --merge-base ] [--topics] [<refs>...] | --reflog[=n[,b]] <branch>";
+"git show-branch [--sparse] [--current] [--all] [--remotes] [--topo-order] [--more=count | --list | --independent | --merge-base ] [--topics] [<refs>...] | --reflog[=n[,b]] <branch>";
 static const char show_branch_usage_reflog[] =
 "--reflog is incompatible with --all, --remotes, --independent or --merge-base";
 
diff --git a/builtin-show-ref.c b/builtin-show-ref.c
index a323633..572b114 100644
--- a/builtin-show-ref.c
+++ b/builtin-show-ref.c
@@ -3,7 +3,7 @@
 #include "refs.h"
 #include "object.h"
 #include "tag.h"
-#include "path-list.h"
+#include "string-list.h"
 
 static const char show_ref_usage[] = "git show-ref [-q|--quiet] [--verify] [-h|--head] [-d|--dereference] [-s|--hash[=<length>]] [--abbrev[=<length>]] [--tags] [--heads] [--] [pattern*] < ref-list";
 
@@ -62,7 +62,7 @@
 	 * ref points at a nonexistent object.
 	 */
 	if (!has_sha1_file(sha1))
-		die("git-show-ref: bad ref %s (%s)", refname,
+		die("git show-ref: bad ref %s (%s)", refname,
 		    sha1_to_hex(sha1));
 
 	if (quiet)
@@ -82,12 +82,12 @@
 	else {
 		obj = parse_object(sha1);
 		if (!obj)
-			die("git-show-ref: bad ref %s (%s)", refname,
+			die("git show-ref: bad ref %s (%s)", refname,
 			    sha1_to_hex(sha1));
 		if (obj->type == OBJ_TAG) {
 			obj = deref_tag(obj, refname, 0);
 			if (!obj)
-				die("git-show-ref: bad tag at ref %s (%s)", refname,
+				die("git show-ref: bad tag at ref %s (%s)", refname,
 				    sha1_to_hex(sha1));
 			hex = find_unique_abbrev(obj->sha1, abbrev);
 			printf("%s %s^{}\n", hex, refname);
@@ -98,8 +98,8 @@
 
 static int add_existing(const char *refname, const unsigned char *sha1, int flag, void *cbdata)
 {
-	struct path_list *list = (struct path_list *)cbdata;
-	path_list_insert(refname, list);
+	struct string_list *list = (struct string_list *)cbdata;
+	string_list_insert(refname, list);
 	return 0;
 }
 
@@ -114,7 +114,7 @@
  */
 static int exclude_existing(const char *match)
 {
-	static struct path_list existing_refs = { NULL, 0, 0, 0 };
+	static struct string_list existing_refs = { NULL, 0, 0, 0 };
 	char buf[1024];
 	int matchlen = match ? strlen(match) : 0;
 
@@ -143,7 +143,7 @@
 			fprintf(stderr, "warning: ref '%s' ignored\n", ref);
 			continue;
 		}
-		if (!path_list_has_path(&existing_refs, ref)) {
+		if (!string_list_has_string(&existing_refs, ref)) {
 			printf("%s\n", buf);
 		}
 	}
diff --git a/builtin-symbolic-ref.c b/builtin-symbolic-ref.c
index b49bdb6..bfc78bb 100644
--- a/builtin-symbolic-ref.c
+++ b/builtin-symbolic-ref.c
@@ -4,7 +4,7 @@
 #include "parse-options.h"
 
 static const char * const git_symbolic_ref_usage[] = {
-	"git-symbolic-ref [options] name [ref]",
+	"git symbolic-ref [options] name [ref]",
 	NULL
 };
 
diff --git a/builtin-tag.c b/builtin-tag.c
index 3bd019c..2cdefb1 100644
--- a/builtin-tag.c
+++ b/builtin-tag.c
@@ -14,68 +14,15 @@
 #include "parse-options.h"
 
 static const char * const git_tag_usage[] = {
-	"git-tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]",
-	"git-tag -d <tagname>...",
-	"git-tag -l [-n[<num>]] [<pattern>]",
-	"git-tag -v <tagname>...",
+	"git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]",
+	"git tag -d <tagname>...",
+	"git tag -l [-n[<num>]] [<pattern>]",
+	"git tag -v <tagname>...",
 	NULL
 };
 
 static char signingkey[1000];
 
-void launch_editor(const char *path, struct strbuf *buffer, const char *const *env)
-{
-	const char *editor, *terminal;
-
-	editor = getenv("GIT_EDITOR");
-	if (!editor && editor_program)
-		editor = editor_program;
-	if (!editor)
-		editor = getenv("VISUAL");
-	if (!editor)
-		editor = getenv("EDITOR");
-
-	terminal = getenv("TERM");
-	if (!editor && (!terminal || !strcmp(terminal, "dumb"))) {
-		fprintf(stderr,
-		"Terminal is dumb but no VISUAL nor EDITOR defined.\n"
-		"Please supply the message using either -m or -F option.\n");
-		exit(1);
-	}
-
-	if (!editor)
-		editor = "vi";
-
-	if (strcmp(editor, ":")) {
-		size_t len = strlen(editor);
-		int i = 0;
-		const char *args[6];
-		struct strbuf arg0;
-
-		strbuf_init(&arg0, 0);
-		if (strcspn(editor, "$ \t'") != len) {
-			/* there are specials */
-			strbuf_addf(&arg0, "%s \"$@\"", editor);
-			args[i++] = "sh";
-			args[i++] = "-c";
-			args[i++] = arg0.buf;
-		}
-		args[i++] = editor;
-		args[i++] = path;
-		args[i] = NULL;
-
-		if (run_command_v_opt_cd_env(args, 0, NULL, env))
-			die("There was a problem with the editor %s.", editor);
-		strbuf_release(&arg0);
-	}
-
-	if (!buffer)
-		return;
-	if (strbuf_read_file(buffer, path, 0) < 0)
-		die("could not read message file '%s': %s",
-		    path, strerror(errno));
-}
-
 struct tag_filter {
 	const char *pattern;
 	int lines;
@@ -178,7 +125,7 @@
 static int delete_tag(const char *name, const char *ref,
 				const unsigned char *sha1)
 {
-	if (delete_ref(ref, sha1))
+	if (delete_ref(ref, sha1, 0))
 		return 1;
 	printf("Deleted tag '%s'\n", name);
 	return 0;
@@ -202,6 +149,7 @@
 	const char *args[4];
 	char *bracket;
 	int len;
+	int i, j;
 
 	if (!*signingkey) {
 		if (strlcpy(signingkey, git_committer_info(IDENT_ERROR_ON_NO_NAME),
@@ -241,6 +189,15 @@
 	if (finish_command(&gpg) || !len || len < 0)
 		return error("gpg failed to sign the tag");
 
+	/* Strip CR from the line endings, in case we are on Windows. */
+	for (i = j = 0; i < buffer->len; i++)
+		if (buffer->buf[i] != '\r') {
+			if (i != j)
+				buffer->buf[j] = buffer->buf[i];
+			j++;
+		}
+	strbuf_setlen(buffer, j);
+
 	return 0;
 }
 
@@ -296,6 +253,15 @@
 	free(buf);
 }
 
+static int build_tag_object(struct strbuf *buf, int sign, unsigned char *result)
+{
+	if (sign && do_sign(buf) < 0)
+		return error("unable to sign the tag");
+	if (write_sha1_file(buf->buf, buf->len, tag_type, result) < 0)
+		return error("unable to write tag file");
+	return 0;
+}
+
 static void create_tag(const unsigned char *object, const char *tag,
 		       struct strbuf *buf, int message, int sign,
 		       unsigned char *prev, unsigned char *result)
@@ -303,6 +269,7 @@
 	enum object_type type;
 	char header_buf[1024];
 	int header_len;
+	char *path = NULL;
 
 	type = sha1_object_info(object, NULL);
 	if (type <= OBJ_NONE)
@@ -322,11 +289,10 @@
 		die("tag header too big.");
 
 	if (!message) {
-		char *path;
 		int fd;
 
 		/* write the template message before editing: */
-		path = xstrdup(git_path("TAG_EDITMSG"));
+		path = git_pathdup("TAG_EDITMSG");
 		fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
 		if (fd < 0)
 			die("could not create file '%s': %s",
@@ -338,10 +304,11 @@
 			write_or_die(fd, tag_template, strlen(tag_template));
 		close(fd);
 
-		launch_editor(path, buf, NULL);
-
-		unlink(path);
-		free(path);
+		if (launch_editor(path, buf, NULL)) {
+			fprintf(stderr,
+			"Please supply the message using either -m or -F option.\n");
+			exit(1);
+		}
 	}
 
 	stripspace(buf, 1);
@@ -351,10 +318,16 @@
 
 	strbuf_insert(buf, 0, header_buf, header_len);
 
-	if (sign && do_sign(buf) < 0)
-		die("unable to sign the tag");
-	if (write_sha1_file(buf->buf, buf->len, tag_type, result) < 0)
-		die("unable to write tag file");
+	if (build_tag_object(buf, sign, result) < 0) {
+		if (path)
+			fprintf(stderr, "The tag message has been left in %s\n",
+				path);
+		exit(128);
+	}
+	if (path) {
+		unlink(path);
+		free(path);
+	}
 }
 
 struct msg_arg {
@@ -383,7 +356,7 @@
 	const char *object_ref, *tag;
 	struct ref_lock *lock;
 
-	int annotate = 0, sign = 0, force = 0, lines = 0,
+	int annotate = 0, sign = 0, force = 0, lines = -1,
 		list = 0, delete = 0, verify = 0;
 	const char *msgfile = NULL, *keyid = NULL;
 	struct msg_arg msg = { 0, STRBUF_INIT };
@@ -419,9 +392,19 @@
 	}
 	if (sign)
 		annotate = 1;
+	if (argc == 0 && !(delete || verify))
+		list = 1;
 
+	if ((annotate || msg.given || msgfile || force) &&
+	    (list || delete || verify))
+		usage_with_options(git_tag_usage, options);
+
+	if (list + delete + verify > 1)
+		usage_with_options(git_tag_usage, options);
 	if (list)
-		return list_tags(argv[0], lines);
+		return list_tags(argv[0], lines == -1 ? 0 : lines);
+	if (lines != -1)
+		die("-n option is only allowed with -l.");
 	if (delete)
 		return for_each_tag_name(argv, delete_tag);
 	if (verify)
@@ -446,11 +429,6 @@
 		}
 	}
 
-	if (argc == 0) {
-		if (annotate)
-			usage_with_options(git_tag_usage, options);
-		return list_tags(NULL, lines);
-	}
 	tag = argv[0];
 
 	object_ref = argc == 2 ? argv[1] : "HEAD";
diff --git a/builtin-tar-tree.c b/builtin-tar-tree.c
index b04719e..0713bca 100644
--- a/builtin-tar-tree.c
+++ b/builtin-tar-tree.c
@@ -8,27 +8,27 @@
 #include "quote.h"
 
 static const char tar_tree_usage[] =
-"git-tar-tree [--remote=<repo>] <tree-ish> [basedir]\n"
-"*** Note that this command is now deprecated; use git-archive instead.";
+"git tar-tree [--remote=<repo>] <tree-ish> [basedir]\n"
+"*** Note that this command is now deprecated; use \"git archive\" instead.";
 
 int cmd_tar_tree(int argc, const char **argv, const char *prefix)
 {
 	/*
-	 * git-tar-tree is now a wrapper around git-archive --format=tar
+	 * "git tar-tree" is now a wrapper around "git archive --format=tar"
 	 *
 	 * $0 --remote=<repo> arg... ==>
-	 *	git-archive --format=tar --remote=<repo> arg...
+	 *	git archive --format=tar --remote=<repo> arg...
 	 * $0 tree-ish ==>
-	 *	git-archive --format=tar tree-ish
+	 *	git archive --format=tar tree-ish
 	 * $0 tree-ish basedir ==>
-	 * 	git-archive --format-tar --prefix=basedir tree-ish
+	 * 	git archive --format-tar --prefix=basedir tree-ish
 	 */
 	int i;
 	const char **nargv = xcalloc(sizeof(*nargv), argc + 2);
 	char *basedir_arg;
 	int nargc = 0;
 
-	nargv[nargc++] = "git-archive";
+	nargv[nargc++] = "archive";
 	nargv[nargc++] = "--format=tar";
 
 	if (2 <= argc && !prefixcmp(argv[1], "--remote=")) {
@@ -53,8 +53,8 @@
 	nargv[nargc] = NULL;
 
 	fprintf(stderr,
-		"*** git-tar-tree is now deprecated.\n"
-		"*** Running git-archive instead.\n***");
+		"*** \"git tar-tree\" is now deprecated.\n"
+		"*** Running \"git archive\" instead.\n***");
 	for (i = 0; i < nargc; i++) {
 		fputc(' ', stderr);
 		sq_quote_print(stderr, nargv[i]);
@@ -76,7 +76,7 @@
 
 	n = read_in_full(0, buffer, HEADERSIZE);
 	if (n < HEADERSIZE)
-		die("git-get-tar-commit-id: read error");
+		die("git get-tar-commit-id: read error");
 	if (header->typeflag[0] != 'g')
 		return 1;
 	if (memcmp(content, "52 comment=", 11))
@@ -84,7 +84,7 @@
 
 	n = write_in_full(1, content + 11, 41);
 	if (n < 41)
-		die("git-get-tar-commit-id: write error");
+		die("git get-tar-commit-id: write error");
 
 	return 0;
 }
diff --git a/builtin-unpack-objects.c b/builtin-unpack-objects.c
index 85043d1..40b20f2 100644
--- a/builtin-unpack-objects.c
+++ b/builtin-unpack-objects.c
@@ -13,7 +13,7 @@
 #include "fsck.h"
 
 static int dry_run, quiet, recover, has_errors, strict;
-static const char unpack_usage[] = "git-unpack-objects [-n] [-q] [-r] [--strict] < pack-file";
+static const char unpack_usage[] = "git unpack-objects [-n] [-q] [-r] [--strict] < pack-file";
 
 /* We always read in 4kB chunks. */
 static unsigned char buffer[4096];
@@ -471,7 +471,8 @@
 	if (ntohl(hdr->hdr_signature) != PACK_SIGNATURE)
 		die("bad pack file");
 	if (!pack_version_ok(hdr->hdr_version))
-		die("unknown pack file version %d", ntohl(hdr->hdr_version));
+		die("unknown pack file version %"PRIu32,
+			ntohl(hdr->hdr_version));
 	use(sizeof(struct pack_header));
 
 	if (!quiet)
diff --git a/builtin-update-index.c b/builtin-update-index.c
index 9e0d7ab..9d19c51 100644
--- a/builtin-update-index.c
+++ b/builtin-update-index.c
@@ -14,7 +14,7 @@
  * Default to not allowing changes to the list of files. The
  * tool doesn't actually care, but this makes it harder to add
  * files to the revision control by mistake by doing something
- * like "git-update-index *" and suddenly having all the object
+ * like "git update-index *" and suddenly having all the object
  * files be revision controlled.
  */
 static int allow_add;
@@ -262,7 +262,7 @@
 	report("chmod %cx '%s'", flip, path);
 	return;
  fail:
-	die("git-update-index: cannot chmod %cx '%s'", flip, path);
+	die("git update-index: cannot chmod %cx '%s'", flip, path);
 }
 
 static void update_one(const char *path, const char *prefix, int prefix_length)
@@ -280,7 +280,7 @@
 
 	if (force_remove) {
 		if (remove_file_from_cache(p))
-			die("git-update-index: unable to remove %s", path);
+			die("git update-index: unable to remove %s", path);
 		report("remove '%s'", path);
 		goto free_return;
 	}
@@ -310,18 +310,18 @@
 		/* This reads lines formatted in one of three formats:
 		 *
 		 * (1) mode         SP sha1          TAB path
-		 * The first format is what "git-apply --index-info"
+		 * The first format is what "git apply --index-info"
 		 * reports, and used to reconstruct a partial tree
 		 * that is used for phony merge base tree when falling
 		 * back on 3-way merge.
 		 *
 		 * (2) mode SP type SP sha1          TAB path
-		 * The second format is to stuff git-ls-tree output
+		 * The second format is to stuff "git ls-tree" output
 		 * into the index file.
 		 *
 		 * (3) mode         SP sha1 SP stage TAB path
 		 * This format is to put higher order stages into the
-		 * index file and matches git-ls-files --stage output.
+		 * index file and matches "git ls-files --stage" output.
 		 */
 		errno = 0;
 		ul = strtoul(buf.buf, &ptr, 8);
@@ -351,7 +351,7 @@
 		if (line_termination && path_name[0] == '"') {
 			strbuf_reset(&uq);
 			if (unquote_c_style(&uq, path_name, NULL)) {
-				die("git-update-index: bad quoting of path name");
+				die("git update-index: bad quoting of path name");
 			}
 			path_name = uq.buf;
 		}
@@ -364,7 +364,7 @@
 		if (!mode) {
 			/* mode == 0 means there is no such path -- remove */
 			if (remove_file_from_cache(path_name))
-				die("git-update-index: unable to remove %s",
+				die("git update-index: unable to remove %s",
 				    ptr);
 		}
 		else {
@@ -374,7 +374,7 @@
 			 */
 			ptr[-42] = ptr[-1] = 0;
 			if (add_cacheinfo(mode, sha1, path_name, stage))
-				die("git-update-index: unable to update %s",
+				die("git update-index: unable to update %s",
 				    path_name);
 		}
 		continue;
@@ -387,7 +387,7 @@
 }
 
 static const char update_index_usage[] =
-"git-update-index [-q] [--add] [--replace] [--remove] [--unmerged] [--refresh] [--really-refresh] [--cacheinfo] [--chmod=(+|-)x] [--assume-unchanged] [--info-only] [--force-remove] [--stdin] [--index-info] [--unresolve] [--again | -g] [--ignore-missing] [-z] [--verbose] [--] <file>...";
+"git update-index [-q] [--add] [--replace] [--remove] [--unmerged] [--refresh] [--really-refresh] [--cacheinfo] [--chmod=(+|-)x] [--assume-unchanged] [--info-only] [--force-remove] [--stdin] [--index-info] [--unresolve] [--again | -g] [--ignore-missing] [-z] [--verbose] [--] <file>...";
 
 static unsigned char head_sha1[20];
 static unsigned char merge_head_sha1[20];
@@ -614,10 +614,12 @@
 				continue;
 			}
 			if (!strcmp(path, "--refresh")) {
+				setup_work_tree();
 				has_errors |= refresh_cache(refresh_flags);
 				continue;
 			}
 			if (!strcmp(path, "--really-refresh")) {
+				setup_work_tree();
 				has_errors |= refresh_cache(REFRESH_REALLY | refresh_flags);
 				continue;
 			}
@@ -626,12 +628,12 @@
 				unsigned int mode;
 
 				if (i+3 >= argc)
-					die("git-update-index: --cacheinfo <mode> <sha1> <path>");
+					die("git update-index: --cacheinfo <mode> <sha1> <path>");
 
 				if (strtoul_ui(argv[i+1], 8, &mode) ||
 				    get_sha1_hex(argv[i+2], sha1) ||
 				    add_cacheinfo(mode, sha1, argv[i+3], 0))
-					die("git-update-index: --cacheinfo"
+					die("git update-index: --cacheinfo"
 					    " cannot add %s", argv[i+3]);
 				i += 3;
 				continue;
@@ -639,7 +641,7 @@
 			if (!strcmp(path, "--chmod=-x") ||
 			    !strcmp(path, "--chmod=+x")) {
 				if (argc <= i+1)
-					die("git-update-index: %s <path>", path);
+					die("git update-index: %s <path>", path);
 				set_executable_bit = path[8];
 				continue;
 			}
@@ -684,6 +686,7 @@
 				goto finish;
 			}
 			if (!strcmp(path, "--again") || !strcmp(path, "-g")) {
+				setup_work_tree();
 				has_errors = do_reupdate(argc - i, argv + i,
 							 prefix, prefix_length);
 				if (has_errors)
@@ -702,6 +705,7 @@
 				usage(update_index_usage);
 			die("unknown option %s", path);
 		}
+		setup_work_tree();
 		p = prefix_path(prefix, prefix_length, path);
 		update_one(p, NULL, 0);
 		if (set_executable_bit)
@@ -714,6 +718,7 @@
 
 		strbuf_init(&buf, 0);
 		strbuf_init(&nbuf, 0);
+		setup_work_tree();
 		while (strbuf_getline(&buf, stdin, line_termination) != EOF) {
 			const char *p;
 			if (line_termination && buf.buf[0] == '"') {
diff --git a/builtin-update-ref.c b/builtin-update-ref.c
index 93c1271..378dc1b 100644
--- a/builtin-update-ref.c
+++ b/builtin-update-ref.c
@@ -4,16 +4,16 @@
 #include "parse-options.h"
 
 static const char * const git_update_ref_usage[] = {
-	"git-update-ref [options] -d <refname> <oldval>",
-	"git-update-ref [options]    <refname> <newval> [<oldval>]",
+	"git update-ref [options] -d <refname> [<oldval>]",
+	"git update-ref [options]    <refname> <newval> [<oldval>]",
 	NULL
 };
 
 int cmd_update_ref(int argc, const char **argv, const char *prefix)
 {
-	const char *refname, *value, *oldval, *msg=NULL;
+	const char *refname, *oldval, *msg=NULL;
 	unsigned char sha1[20], oldsha1[20];
-	int delete = 0, no_deref = 0;
+	int delete = 0, no_deref = 0, flags = 0;
 	struct option options[] = {
 		OPT_STRING( 'm', NULL, &msg, "reason", "reason of the update"),
 		OPT_BOOLEAN('d', NULL, &delete, "deletes the reference"),
@@ -27,25 +27,31 @@
 	if (msg && !*msg)
 		die("Refusing to perform update with empty message.");
 
-	if (argc < 2 || argc > 3)
-		usage_with_options(git_update_ref_usage, options);
-	refname = argv[0];
-	value   = argv[1];
-	oldval  = argv[2];
-
-	if (get_sha1(value, sha1))
-		die("%s: not a valid SHA1", value);
-
 	if (delete) {
-		if (oldval)
+		if (argc < 1 || argc > 2)
 			usage_with_options(git_update_ref_usage, options);
-		return delete_ref(refname, sha1);
+		refname = argv[0];
+		oldval = argv[1];
+	} else {
+		const char *value;
+		if (argc < 2 || argc > 3)
+			usage_with_options(git_update_ref_usage, options);
+		refname = argv[0];
+		value = argv[1];
+		oldval = argv[2];
+		if (get_sha1(value, sha1))
+			die("%s: not a valid SHA1", value);
 	}
 
-	hashclr(oldsha1);
+	hashclr(oldsha1); /* all-zero hash in case oldval is the empty string */
 	if (oldval && *oldval && get_sha1(oldval, oldsha1))
 		die("%s: not a valid old SHA1", oldval);
 
-	return update_ref(msg, refname, sha1, oldval ? oldsha1 : NULL,
-			  no_deref ? REF_NODEREF : 0, DIE_ON_ERR);
+	if (no_deref)
+		flags = REF_NODEREF;
+	if (delete)
+		return delete_ref(refname, oldval ? oldsha1 : NULL, flags);
+	else
+		return update_ref(msg, refname, sha1, oldval ? oldsha1 : NULL,
+				  flags, DIE_ON_ERR);
 }
diff --git a/builtin-upload-archive.c b/builtin-upload-archive.c
index 371400d..a9b02fa 100644
--- a/builtin-upload-archive.c
+++ b/builtin-upload-archive.c
@@ -8,22 +8,21 @@
 #include "sideband.h"
 
 static const char upload_archive_usage[] =
-	"git-upload-archive <repo>";
+	"git upload-archive <repo>";
 
 static const char deadchild[] =
-"git-upload-archive: archiver died with error";
+"git upload-archive: archiver died with error";
 
 static const char lostchild[] =
-"git-upload-archive: archiver process was lost";
+"git upload-archive: archiver process was lost";
 
+#define MAX_ARGS (64)
 
 static int run_upload_archive(int argc, const char **argv, const char *prefix)
 {
-	struct archiver ar;
 	const char *sent_argv[MAX_ARGS];
 	const char *arg_cmd = "argument ";
 	char *p, buf[4096];
-	int treeish_idx;
 	int sent_argc;
 	int len;
 
@@ -47,7 +46,7 @@
 		if (len == 0)
 			break;	/* got a flush */
 		if (sent_argc > MAX_ARGS - 2)
-			die("Too many options (>29)");
+			die("Too many options (>%d)", MAX_ARGS - 2);
 
 		if (p[len-1] == '\n') {
 			p[--len] = 0;
@@ -65,12 +64,7 @@
 	sent_argv[sent_argc] = NULL;
 
 	/* parse all options sent by the client */
-	treeish_idx = parse_archive_args(sent_argc, sent_argv, &ar);
-
-	parse_treeish_arg(sent_argv + treeish_idx, &ar.args, prefix);
-	parse_pathspec_arg(sent_argv + treeish_idx + 1, &ar.args);
-
-	return ar.write_archive(&ar.args);
+	return write_archive(sent_argc, sent_argv, prefix, 0);
 }
 
 static void error_clnt(const char *fmt, ...)
diff --git a/builtin-verify-pack.c b/builtin-verify-pack.c
index 4c515a0..25a29f1 100644
--- a/builtin-verify-pack.c
+++ b/builtin-verify-pack.c
@@ -1,6 +1,58 @@
 #include "builtin.h"
 #include "cache.h"
 #include "pack.h"
+#include "pack-revindex.h"
+
+#define MAX_CHAIN 50
+
+static void show_pack_info(struct packed_git *p)
+{
+	uint32_t nr_objects, i, chain_histogram[MAX_CHAIN+1];
+
+	nr_objects = p->num_objects;
+	memset(chain_histogram, 0, sizeof(chain_histogram));
+
+	for (i = 0; i < nr_objects; i++) {
+		const unsigned char *sha1;
+		unsigned char base_sha1[20];
+		const char *type;
+		unsigned long size;
+		unsigned long store_size;
+		off_t offset;
+		unsigned int delta_chain_length;
+
+		sha1 = nth_packed_object_sha1(p, i);
+		if (!sha1)
+			die("internal error pack-check nth-packed-object");
+		offset = nth_packed_object_offset(p, i);
+		type = packed_object_info_detail(p, offset, &size, &store_size,
+						 &delta_chain_length,
+						 base_sha1);
+		printf("%s ", sha1_to_hex(sha1));
+		if (!delta_chain_length)
+			printf("%-6s %lu %lu %"PRIuMAX"\n",
+			       type, size, store_size, (uintmax_t)offset);
+		else {
+			printf("%-6s %lu %lu %"PRIuMAX" %u %s\n",
+			       type, size, store_size, (uintmax_t)offset,
+			       delta_chain_length, sha1_to_hex(base_sha1));
+			if (delta_chain_length <= MAX_CHAIN)
+				chain_histogram[delta_chain_length]++;
+			else
+				chain_histogram[0]++;
+		}
+	}
+
+	for (i = 0; i <= MAX_CHAIN; i++) {
+		if (!chain_histogram[i])
+			continue;
+		printf("chain length = %"PRIu32": %"PRIu32" object%s\n", i,
+		       chain_histogram[i], chain_histogram[i] > 1 ? "s" : "");
+	}
+	if (chain_histogram[0])
+		printf("chain length > %d: %"PRIu32" object%s\n", MAX_CHAIN,
+		       chain_histogram[0], chain_histogram[0] > 1 ? "s" : "");
+}
 
 static int verify_one_pack(const char *path, int verbose)
 {
@@ -41,7 +93,16 @@
 		return error("packfile %s not found.", arg);
 
 	install_packed_git(pack);
-	err = verify_pack(pack, verbose);
+	err = verify_pack(pack);
+
+	if (verbose) {
+		if (err)
+			printf("%s: bad\n", pack->pack_name);
+		else {
+			show_pack_info(pack);
+			printf("%s: ok\n", pack->pack_name);
+		}
+	}
 
 	return err;
 }
@@ -68,6 +129,7 @@
 		else {
 			if (verify_one_pack(argv[1], verbose))
 				err = 1;
+			discard_revindex();
 			nothing_done = 0;
 		}
 		argc--; argv++;
diff --git a/builtin-verify-tag.c b/builtin-verify-tag.c
index 92eaa89..729a159 100644
--- a/builtin-verify-tag.c
+++ b/builtin-verify-tag.c
@@ -12,7 +12,7 @@
 #include <signal.h>
 
 static const char builtin_verify_tag_usage[] =
-		"git-verify-tag [-v|--verbose] <tag>...";
+		"git verify-tag [-v|--verbose] <tag>...";
 
 #define PGP_SIGNATURE "-----BEGIN PGP SIGNATURE-----"
 
@@ -92,14 +92,15 @@
 
 	git_config(git_default_config, NULL);
 
-	if (argc == 1)
-		usage(builtin_verify_tag_usage);
-
-	if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--verbose")) {
+	if (argc > 1 &&
+	    (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--verbose"))) {
 		verbose = 1;
 		i++;
 	}
 
+	if (argc <= i)
+		usage(builtin_verify_tag_usage);
+
 	/* sometimes the program was terminated because this signal
 	 * was received in the process of writing the gpg input: */
 	signal(SIGPIPE, SIG_IGN);
diff --git a/builtin-write-tree.c b/builtin-write-tree.c
index c218799..52a3c01 100644
--- a/builtin-write-tree.c
+++ b/builtin-write-tree.c
@@ -9,7 +9,7 @@
 #include "cache-tree.h"
 
 static const char write_tree_usage[] =
-"git-write-tree [--missing-ok] [--prefix=<prefix>/]";
+"git write-tree [--missing-ok] [--prefix=<prefix>/]";
 
 int cmd_write_tree(int argc, const char **argv, const char *unused_prefix)
 {
diff --git a/builtin.h b/builtin.h
index b460b2d..f3502d3 100644
--- a/builtin.h
+++ b/builtin.h
@@ -2,6 +2,9 @@
 #define BUILTIN_H
 
 #include "git-compat-util.h"
+#include "strbuf.h"
+#include "cache.h"
+#include "commit.h"
 
 extern const char git_version_string[];
 extern const char git_usage_string[];
@@ -11,6 +14,11 @@
 extern void help_unknown_cmd(const char *cmd);
 extern void prune_packed_objects(int);
 extern int read_line_with_nul(char *buf, int size, FILE *file);
+extern int fmt_merge_msg(int merge_summary, struct strbuf *in,
+	struct strbuf *out);
+extern int commit_tree(const char *msg, unsigned char *tree,
+		struct commit_list *parents, unsigned char *ret);
+extern int check_pager_config(const char *cmd);
 
 extern int cmd_add(int argc, const char **argv, const char *prefix);
 extern int cmd_annotate(int argc, const char **argv, const char *prefix);
@@ -57,6 +65,7 @@
 extern int cmd_ls_remote(int argc, const char **argv, const char *prefix);
 extern int cmd_mailinfo(int argc, const char **argv, const char *prefix);
 extern int cmd_mailsplit(int argc, const char **argv, const char *prefix);
+extern int cmd_merge(int argc, const char **argv, const char *prefix);
 extern int cmd_merge_base(int argc, const char **argv, const char *prefix);
 extern int cmd_merge_ours(int argc, const char **argv, const char *prefix);
 extern int cmd_merge_file(int argc, const char **argv, const char *prefix);
diff --git a/bundle.c b/bundle.c
index 0ba5df1..daecd8e 100644
--- a/bundle.c
+++ b/bundle.c
@@ -114,7 +114,7 @@
 			continue;
 		}
 		if (++ret == 1)
-			error(message);
+			error("%s", message);
 		error("%s %s", sha1_to_hex(e->sha1), e->name);
 	}
 	if (revs.pending.nr != p->nr)
@@ -139,7 +139,7 @@
 	for (i = 0; i < req_nr; i++)
 		if (!(refs.objects[i].item->flags & SHOWN)) {
 			if (++ret == 1)
-				error(message);
+				error("%s", message);
 			error("%s %s", sha1_to_hex(refs.objects[i].item->sha1),
 				refs.objects[i].name);
 		}
@@ -178,6 +178,7 @@
 	int i, ref_count = 0;
 	char buffer[1024];
 	struct rev_info revs;
+	int read_from_stdin = 0;
 	struct child_process rls;
 	FILE *rls_fout;
 
@@ -185,7 +186,8 @@
 	if (bundle_to_stdout)
 		bundle_fd = 1;
 	else
-		bundle_fd = hold_lock_file_for_update(&lock, path, 1);
+		bundle_fd = hold_lock_file_for_update(&lock, path,
+						      LOCK_DIE_ON_ERROR);
 
 	/* write signature */
 	write_or_die(bundle_fd, bundle_signature, strlen(bundle_signature));
@@ -227,8 +229,16 @@
 
 	/* write references */
 	argc = setup_revisions(argc, argv, &revs, NULL);
-	if (argc > 1)
-		return error("unrecognized argument: %s'", argv[1]);
+
+	for (i = 1; i < argc; i++) {
+		if (!strcmp(argv[i], "--stdin")) {
+			if (read_from_stdin++)
+				die("--stdin given twice?");
+			read_revisions_from_stdin(&revs);
+			continue;
+		}
+		return error("unrecognized argument: %s'", argv[i]);
+	}
 
 	for (i = 0; i < revs.pending.nr; i++) {
 		struct object_array_entry *e = revs.pending.objects + i;
diff --git a/cache-tree.c b/cache-tree.c
index 73cb340..5f8ee87 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -507,7 +507,7 @@
 	return read_one(&buffer, &size);
 }
 
-struct cache_tree *cache_tree_find(struct cache_tree *it, const char *path)
+static struct cache_tree *cache_tree_find(struct cache_tree *it, const char *path)
 {
 	while (*path) {
 		const char *slash;
diff --git a/cache-tree.h b/cache-tree.h
index 44aad42..cf8b790 100644
--- a/cache-tree.h
+++ b/cache-tree.h
@@ -28,8 +28,6 @@
 int cache_tree_fully_valid(struct cache_tree *);
 int cache_tree_update(struct cache_tree *, struct cache_entry **, int, int, int);
 
-struct cache_tree *cache_tree_find(struct cache_tree *, const char *);
-
 #define WRITE_TREE_UNREADABLE_INDEX (-1)
 #define WRITE_TREE_UNMERGED_INDEX (-2)
 #define WRITE_TREE_PREFIX_ERROR (-3)
diff --git a/cache.h b/cache.h
index 8822651..42f2f27 100644
--- a/cache.h
+++ b/cache.h
@@ -222,7 +222,8 @@
 	struct cache_tree *cache_tree;
 	time_t timestamp;
 	void *alloc;
-	unsigned name_hash_initialized : 1;
+	unsigned name_hash_initialized : 1,
+		 initialized : 1;
 	struct hash_table name_hash;
 };
 
@@ -254,11 +255,14 @@
 
 #define read_cache() read_index(&the_index)
 #define read_cache_from(path) read_index_from(&the_index, (path))
+#define is_cache_unborn() is_index_unborn(&the_index)
+#define read_cache_unmerged() read_index_unmerged(&the_index)
 #define write_cache(newfd, cache, entries) write_index(&the_index, (newfd))
 #define discard_cache() discard_index(&the_index)
 #define unmerged_cache() unmerged_index(&the_index)
 #define cache_name_pos(name, namelen) index_name_pos(&the_index,(name),(namelen))
 #define add_cache_entry(ce, option) add_index_entry(&the_index, (ce), (option))
+#define rename_cache_entry_at(pos, new_name) rename_index_entry_at(&the_index, (pos), (new_name))
 #define remove_cache_entry_at(pos) remove_index_entry_at(&the_index, (pos))
 #define remove_file_from_cache(path) remove_file_from_index(&the_index, (path))
 #define add_to_cache(path, st, flags) add_to_index(&the_index, (path), (st), (flags))
@@ -267,6 +271,7 @@
 #define ce_match_stat(ce, st, options) ie_match_stat(&the_index, (ce), (st), (options))
 #define ce_modified(ce, st, options) ie_modified(&the_index, (ce), (st), (options))
 #define cache_name_exists(name, namelen, igncase) index_name_exists(&the_index, (name), (namelen), (igncase))
+#define cache_name_is_other(name, namelen) index_name_is_other(&the_index, (name), (namelen))
 #endif
 
 enum object_type {
@@ -298,8 +303,8 @@
 #define GRAFT_ENVIRONMENT "GIT_GRAFT_FILE"
 #define TEMPLATE_DIR_ENVIRONMENT "GIT_TEMPLATE_DIR"
 #define CONFIG_ENVIRONMENT "GIT_CONFIG"
-#define CONFIG_LOCAL_ENVIRONMENT "GIT_CONFIG_LOCAL"
 #define EXEC_PATH_ENVIRONMENT "GIT_EXEC_PATH"
+#define CEILING_DIRECTORIES_ENVIRONMENT "GIT_CEILING_DIRECTORIES"
 #define GITATTRIBUTES_FILE ".gitattributes"
 #define INFOATTRIBUTES_FILE "info/attributes"
 #define ATTRIBUTE_MACRO_PREFIX "[attr]"
@@ -311,7 +316,6 @@
 extern int is_inside_work_tree(void);
 extern const char *get_git_dir(void);
 extern char *get_object_directory(void);
-extern char *get_refs_directory(void);
 extern char *get_index_file(void);
 extern char *get_graft_file(void);
 extern int set_git_dir(const char *path);
@@ -357,6 +361,8 @@
 /* Initialize and use the cache information */
 extern int read_index(struct index_state *);
 extern int read_index_from(struct index_state *, const char *path);
+extern int is_index_unborn(struct index_state *);
+extern int read_index_unmerged(struct index_state *);
 extern int write_index(const struct index_state *, int newfd);
 extern int discard_index(struct index_state *);
 extern int unmerged_index(const struct index_state *);
@@ -369,6 +375,7 @@
 #define ADD_CACHE_JUST_APPEND 8		/* Append only; tree.c::read_tree() */
 extern int add_index_entry(struct index_state *, struct cache_entry *ce, int option);
 extern struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really);
+extern void rename_index_entry_at(struct index_state *, int pos, const char *new_name);
 extern int remove_index_entry_at(struct index_state *, int pos);
 extern int remove_file_from_index(struct index_state *, const char *path);
 #define ADD_CACHE_VERBOSE 1
@@ -378,6 +385,7 @@
 extern int add_file_to_index(struct index_state *, const char *path, int flags);
 extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, int refresh);
 extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);
+extern int index_name_is_other(const struct index_state *, const char *, int);
 
 /* do stat comparison even if CE_VALID is true */
 #define CE_MATCH_IGNORE_VALID		01
@@ -397,6 +405,7 @@
 #define REFRESH_QUIET		0x0004	/* be quiet about it */
 #define REFRESH_IGNORE_MISSING	0x0008	/* ignore non-existent */
 #define REFRESH_IGNORE_SUBMODULES	0x0010	/* ignore submodules */
+#define REFRESH_SAY_CHANGED	0x0020	/* say "changed" not "needs update" */
 extern int refresh_index(struct index_state *, unsigned int flags, const char **pathspec, char *seen);
 
 struct lock_file {
@@ -406,6 +415,8 @@
 	char on_list;
 	char filename[PATH_MAX];
 };
+#define LOCK_DIE_ON_ERROR 1
+#define LOCK_NODEREF 2
 extern int hold_lock_file_for_update(struct lock_file *, const char *path, int);
 extern int hold_lock_file_for_append(struct lock_file *, const char *path, int);
 extern int commit_lock_file(struct lock_file *);
@@ -415,10 +426,11 @@
 extern void set_alternate_index_output(const char *);
 extern int close_lock_file(struct lock_file *);
 extern void rollback_lock_file(struct lock_file *);
-extern int delete_ref(const char *, const unsigned char *sha1);
+extern int delete_ref(const char *, const unsigned char *sha1, int delopt);
 
 /* Environment bits from configuration mechanism */
 extern int trust_executable_bit;
+extern int trust_ctime;
 extern int quote_path_fully;
 extern int has_symlinks;
 extern int ignore_case;
@@ -474,6 +486,13 @@
 #define DATA_CHANGED    0x0020
 #define TYPE_CHANGED    0x0040
 
+extern char *mksnpath(char *buf, size_t n, const char *fmt, ...)
+	__attribute__((format (printf, 3, 4)));
+extern char *git_snpath(char *buf, size_t n, const char *fmt, ...)
+	__attribute__((format (printf, 3, 4)));
+extern char *git_pathdup(const char *fmt, ...)
+	__attribute__((format (printf, 1, 2)));
+
 /* Return a statically allocated filename matching the sha1 signature */
 extern char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
 extern char *git_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
@@ -523,11 +542,13 @@
 char *enter_repo(char *path, int strict);
 static inline int is_absolute_path(const char *path)
 {
-	return path[0] == '/';
+	return path[0] == '/' || has_dos_drive_prefix(path);
 }
 const char *make_absolute_path(const char *path);
 const char *make_nonrelative_path(const char *path);
 const char *make_relative_path(const char *abs, const char *base);
+int normalize_absolute_path(char *buf, const char *path);
+int longest_ancestor_length(const char *path, const char *prefix_list);
 
 /* Read and unpack a sha1 file into memory, write memory to a sha1 file */
 extern int sha1_object_info(const unsigned char *, unsigned long *);
@@ -537,12 +558,16 @@
 extern int pretend_sha1_file(void *, unsigned long, enum object_type, unsigned char *);
 extern int force_object_loose(const unsigned char *sha1, time_t mtime);
 
+/* just like read_sha1_file(), but non fatal in presence of bad objects */
+extern void *read_object(const unsigned char *sha1, enum object_type *type, unsigned long *size);
+
 extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned long size, const char *type);
 
 extern int move_temp_to_file(const char *tmpfile, const char *filename);
 
 extern int has_sha1_pack(const unsigned char *sha1, const char **ignore);
 extern int has_sha1_file(const unsigned char *sha1);
+extern int has_loose_object_nonlocal(const unsigned char *sha1);
 
 extern int has_pack_file(const unsigned char *sha1);
 extern int has_pack_index(const unsigned char *sha1);
@@ -644,10 +669,13 @@
 	const void *index_data;
 	size_t index_size;
 	uint32_t num_objects;
+	uint32_t num_bad_objects;
+	unsigned char *bad_object_sha1;
 	int index_version;
 	time_t mtime;
 	int pack_fd;
-	int pack_local;
+	unsigned pack_local:1,
+		 pack_keep:1;
 	unsigned char sha1[20];
 	/* something like ".git/objects/pack/xxxxx.pack" */
 	char pack_name[FLEX_ARRAY]; /* more */
@@ -710,8 +738,10 @@
 extern unsigned char* use_pack(struct packed_git *, struct pack_window **, off_t, unsigned int *);
 extern void close_pack_windows(struct packed_git *);
 extern void unuse_pack(struct pack_window **);
+extern void free_pack_by_name(const char *);
 extern struct packed_git *add_packed_git(const char *, int, int);
 extern const unsigned char *nth_packed_object_sha1(struct packed_git *, uint32_t);
+extern off_t nth_packed_object_offset(const struct packed_git *, uint32_t);
 extern off_t find_pack_entry_one(const unsigned char *, struct packed_git *);
 extern void *unpack_entry(struct packed_git *, off_t, enum object_type *, unsigned long *);
 extern unsigned long unpack_object_header_gently(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep);
@@ -738,10 +768,10 @@
 extern int git_config_rename_section(const char *, const char *);
 extern const char *git_etc_gitconfig(void);
 extern int check_repository_format_version(const char *var, const char *value, void *cb);
-extern int git_env_bool(const char *, int);
 extern int git_config_system(void);
 extern int git_config_global(void);
 extern int config_error_nonbool(const char *);
+extern const char *config_exclusive_filename;
 
 #define MAX_GITNAME (1000)
 extern char git_default_email[MAX_GITNAME];
@@ -818,11 +848,11 @@
 extern unsigned whitespace_rule_cfg;
 extern unsigned whitespace_rule(const char *);
 extern unsigned parse_whitespace_rule(const char *);
-extern unsigned check_and_emit_line(const char *line, int len, unsigned ws_rule,
-    FILE *stream, const char *set,
-    const char *reset, const char *ws);
+extern unsigned ws_check(const char *line, int len, unsigned ws_rule);
+extern void ws_check_emit(const char *line, int len, unsigned ws_rule, FILE *stream, const char *set, const char *reset, const char *ws);
 extern char *whitespace_error_string(unsigned ws);
 extern int ws_fix_copy(char *, const char *, int, unsigned, int *);
+extern int ws_blank_line(const char *line, int len, unsigned ws_rule);
 
 /* ls-files */
 int pathspec_match(const char **spec, char *matched, const char *filename, int skiplen);
@@ -830,5 +860,6 @@
 void overlay_tree_on_cache(const char *tree_name, const char *prefix);
 
 char *alias_lookup(const char *alias);
+int split_cmdline(char *cmdline, const char ***argv);
 
 #endif /* CACHE_H */
diff --git a/check_bindir b/check_bindir
new file mode 100755
index 0000000..a1c4c3e
--- /dev/null
+++ b/check_bindir
@@ -0,0 +1,13 @@
+#!/bin/sh
+bindir="$1"
+gitexecdir="$2"
+gitcmd="$3"
+if test "$bindir" != "$gitexecdir" -a -x "$gitcmd"
+then
+	echo
+	echo "!! You have installed git-* commands to new gitexecdir."
+	echo "!! Old version git-* commands still remain in bindir."
+	echo "!! Mixing two versions of Git will lead to problems."
+	echo "!! Please remove old version commands in bindir now."
+	echo
+fi
diff --git a/combine-diff.c b/combine-diff.c
index 9f80a1c..aa9d79e 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -500,6 +500,18 @@
 	return (isalpha(ch) || ch == '_' || ch == '$');
 }
 
+static void show_line_to_eol(const char *line, int len, const char *reset)
+{
+	int saw_cr_at_eol = 0;
+	if (len < 0)
+		len = strlen(line);
+	saw_cr_at_eol = (len && line[len-1] == '\r');
+
+	printf("%.*s%s%s\n", len - saw_cr_at_eol, line,
+	       reset,
+	       saw_cr_at_eol ? "\r" : "");
+}
+
 static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent,
 		       int use_color)
 {
@@ -593,7 +605,7 @@
 					else
 						putchar(' ');
 				}
-				printf("%s%s\n", ll->line, c_reset);
+				show_line_to_eol(ll->line, -1, c_reset);
 				ll = ll->next;
 			}
 			if (cnt < lno)
@@ -617,7 +629,7 @@
 					putchar(' ');
 				p_mask <<= 1;
 			}
-			printf("%.*s%s\n", sl->len, sl->bol, c_reset);
+			show_line_to_eol(sl->bol, sl->len, c_reset);
 		}
 	}
 }
@@ -727,6 +739,18 @@
 				die("early EOF '%s'", elem->path);
 
 			result[len] = 0;
+
+			/* If not a fake symlink, apply filters, e.g. autocrlf */
+			if (is_file) {
+				struct strbuf buf;
+
+				strbuf_init(&buf, 0);
+				if (convert_to_git(elem->path, result, len, &buf, safe_crlf)) {
+					free(result);
+					result = strbuf_detach(&buf, &len);
+					result_size = len;
+				}
+			}
 		}
 		else {
 		deleted_file:
diff --git a/commit.c b/commit.c
index 09cf167..dc0c5bf 100644
--- a/commit.c
+++ b/commit.c
@@ -325,6 +325,14 @@
 	return new_list;
 }
 
+unsigned commit_list_count(const struct commit_list *l)
+{
+	unsigned c = 0;
+	for (; l; l = l->next )
+		c++;
+	return c;
+}
+
 void free_commit_list(struct commit_list *list)
 {
 	while (list) {
@@ -524,26 +532,34 @@
 	return NULL;
 }
 
-static struct commit_list *merge_bases(struct commit *one, struct commit *two)
+static struct commit_list *merge_bases_many(struct commit *one, int n, struct commit **twos)
 {
 	struct commit_list *list = NULL;
 	struct commit_list *result = NULL;
+	int i;
 
-	if (one == two)
-		/* We do not mark this even with RESULT so we do not
-		 * have to clean it up.
-		 */
-		return commit_list_insert(one, &result);
+	for (i = 0; i < n; i++) {
+		if (one == twos[i])
+			/*
+			 * We do not mark this even with RESULT so we do not
+			 * have to clean it up.
+			 */
+			return commit_list_insert(one, &result);
+	}
 
 	if (parse_commit(one))
 		return NULL;
-	if (parse_commit(two))
-		return NULL;
+	for (i = 0; i < n; i++) {
+		if (parse_commit(twos[i]))
+			return NULL;
+	}
 
 	one->object.flags |= PARENT1;
-	two->object.flags |= PARENT2;
 	insert_by_date(one, &list);
-	insert_by_date(two, &list);
+	for (i = 0; i < n; i++) {
+		twos[i]->object.flags |= PARENT2;
+		insert_by_date(twos[i], &list);
+	}
 
 	while (interesting(list)) {
 		struct commit *commit;
@@ -591,21 +607,53 @@
 	return result;
 }
 
-struct commit_list *get_merge_bases(struct commit *one,
-					struct commit *two, int cleanup)
+struct commit_list *get_octopus_merge_bases(struct commit_list *in)
+{
+	struct commit_list *i, *j, *k, *ret = NULL;
+	struct commit_list **pptr = &ret;
+
+	for (i = in; i; i = i->next) {
+		if (!ret)
+			pptr = &commit_list_insert(i->item, pptr)->next;
+		else {
+			struct commit_list *new = NULL, *end = NULL;
+
+			for (j = ret; j; j = j->next) {
+				struct commit_list *bases;
+				bases = get_merge_bases(i->item, j->item, 1);
+				if (!new)
+					new = bases;
+				else
+					end->next = bases;
+				for (k = bases; k; k = k->next)
+					end = k;
+			}
+			ret = new;
+		}
+	}
+	return ret;
+}
+
+struct commit_list *get_merge_bases_many(struct commit *one,
+					 int n,
+					 struct commit **twos,
+					 int cleanup)
 {
 	struct commit_list *list;
 	struct commit **rslt;
 	struct commit_list *result;
 	int cnt, i, j;
 
-	result = merge_bases(one, two);
-	if (one == two)
-		return result;
+	result = merge_bases_many(one, n, twos);
+	for (i = 0; i < n; i++) {
+		if (one == twos[i])
+			return result;
+	}
 	if (!result || !result->next) {
 		if (cleanup) {
 			clear_commit_marks(one, all_flags);
-			clear_commit_marks(two, all_flags);
+			for (i = 0; i < n; i++)
+				clear_commit_marks(twos[i], all_flags);
 		}
 		return result;
 	}
@@ -623,12 +671,13 @@
 	free_commit_list(result);
 
 	clear_commit_marks(one, all_flags);
-	clear_commit_marks(two, all_flags);
+	for (i = 0; i < n; i++)
+		clear_commit_marks(twos[i], all_flags);
 	for (i = 0; i < cnt - 1; i++) {
 		for (j = i+1; j < cnt; j++) {
 			if (!rslt[i] || !rslt[j])
 				continue;
-			result = merge_bases(rslt[i], rslt[j]);
+			result = merge_bases_many(rslt[i], 1, &rslt[j]);
 			clear_commit_marks(rslt[i], all_flags);
 			clear_commit_marks(rslt[j], all_flags);
 			for (list = result; list; list = list->next) {
@@ -650,6 +699,12 @@
 	return result;
 }
 
+struct commit_list *get_merge_bases(struct commit *one, struct commit *two,
+				    int cleanup)
+{
+	return get_merge_bases_many(one, 1, &two, cleanup);
+}
+
 int in_merge_bases(struct commit *commit, struct commit **reference, int num)
 {
 	struct commit_list *bases, *b;
@@ -669,3 +724,55 @@
 	free_commit_list(bases);
 	return ret;
 }
+
+struct commit_list *reduce_heads(struct commit_list *heads)
+{
+	struct commit_list *p;
+	struct commit_list *result = NULL, **tail = &result;
+	struct commit **other;
+	size_t num_head, num_other;
+
+	if (!heads)
+		return NULL;
+
+	/* Avoid unnecessary reallocations */
+	for (p = heads, num_head = 0; p; p = p->next)
+		num_head++;
+	other = xcalloc(sizeof(*other), num_head);
+
+	/* For each commit, see if it can be reached by others */
+	for (p = heads; p; p = p->next) {
+		struct commit_list *q, *base;
+
+		/* Do we already have this in the result? */
+		for (q = result; q; q = q->next)
+			if (p->item == q->item)
+				break;
+		if (q)
+			continue;
+
+		num_other = 0;
+		for (q = heads; q; q = q->next) {
+			if (p->item == q->item)
+				continue;
+			other[num_other++] = q->item;
+		}
+		if (num_other)
+			base = get_merge_bases_many(p->item, num_other, other, 1);
+		else
+			base = NULL;
+		/*
+		 * If p->item does not have anything common with other
+		 * commits, there won't be any merge base.  If it is
+		 * reachable from some of the others, p->item will be
+		 * the merge base.  If its history is connected with
+		 * others, but p->item is not reachable by others, we
+		 * will get something other than p->item back.
+		 */
+		if (!base || (base->item != p->item))
+			tail = &(commit_list_insert(p->item, tail)->next);
+		free_commit_list(base);
+	}
+	free(other);
+	return result;
+}
diff --git a/commit.h b/commit.h
index 2d94d41..ecdd573 100644
--- a/commit.h
+++ b/commit.h
@@ -41,6 +41,7 @@
 int parse_commit(struct commit *item);
 
 struct commit_list * commit_list_insert(struct commit *item, struct commit_list **list_p);
+unsigned commit_list_count(const struct commit_list *l);
 struct commit_list * insert_by_date(struct commit *item, struct commit_list **list);
 
 void free_commit_list(struct commit_list *list);
@@ -66,7 +67,8 @@
 struct rev_info; /* in revision.h, it circularly uses enum cmit_fmt */
 extern void get_commit_format(const char *arg, struct rev_info *);
 extern void format_commit_message(const struct commit *commit,
-                                  const void *format, struct strbuf *sb);
+				  const void *format, struct strbuf *sb,
+				  enum date_mode dmode);
 extern void pretty_print_commit(enum cmit_fmt fmt, const struct commit*,
                                 struct strbuf *,
                                 int abbrev, const char *subject,
@@ -120,6 +122,7 @@
 struct commit_graft *lookup_commit_graft(const unsigned char *sha1);
 
 extern struct commit_list *get_merge_bases(struct commit *rev1, struct commit *rev2, int cleanup);
+extern struct commit_list *get_octopus_merge_bases(struct commit_list *in);
 
 extern int register_shallow(const unsigned char *sha1);
 extern int unregister_shallow(const unsigned char *sha1);
@@ -131,11 +134,12 @@
 int in_merge_bases(struct commit *, struct commit **, int);
 
 extern int interactive_add(int argc, const char **argv, const char *prefix);
-extern int rerere(void);
 
 static inline int single_parent(struct commit *commit)
 {
 	return commit->parents && !commit->parents->next;
 }
 
+struct commit_list *reduce_heads(struct commit_list *heads);
+
 #endif /* COMMIT_H */
diff --git a/compat/fnmatch/fnmatch.c b/compat/fnmatch/fnmatch.c
new file mode 100644
index 0000000..1f4ead5
--- /dev/null
+++ b/compat/fnmatch/fnmatch.c
@@ -0,0 +1,488 @@
+/* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Enable GNU extensions in fnmatch.h.  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE	1
+#endif
+
+#include <errno.h>
+#include <fnmatch.h>
+#include <ctype.h>
+
+#if HAVE_STRING_H || defined _LIBC
+# include <string.h>
+#else
+# include <strings.h>
+#endif
+
+#if defined STDC_HEADERS || defined _LIBC
+# include <stdlib.h>
+#endif
+
+/* For platform which support the ISO C amendement 1 functionality we
+   support user defined character classes.  */
+#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>.  */
+# include <wchar.h>
+# include <wctype.h>
+#endif
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+   actually compiling the library itself.  This code is part of the GNU C
+   Library, but also included in many other GNU distributions.  Compiling
+   and linking in this code is a waste when using the GNU C library
+   (especially if it is a shared library).  Rather than having every GNU
+   program understand `configure --with-gnu-libc' and omit the object files,
+   it is simpler to just do this in the source for each such file.  */
+
+#if defined _LIBC || !defined __GNU_LIBRARY__
+
+
+# if defined STDC_HEADERS || !defined isascii
+#  define ISASCII(c) 1
+# else
+#  define ISASCII(c) isascii(c)
+# endif
+
+# ifdef isblank
+#  define ISBLANK(c) (ISASCII (c) && isblank (c))
+# else
+#  define ISBLANK(c) ((c) == ' ' || (c) == '\t')
+# endif
+# ifdef isgraph
+#  define ISGRAPH(c) (ISASCII (c) && isgraph (c))
+# else
+#  define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
+# endif
+
+# define ISPRINT(c) (ISASCII (c) && isprint (c))
+# define ISDIGIT(c) (ISASCII (c) && isdigit (c))
+# define ISALNUM(c) (ISASCII (c) && isalnum (c))
+# define ISALPHA(c) (ISASCII (c) && isalpha (c))
+# define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
+# define ISLOWER(c) (ISASCII (c) && islower (c))
+# define ISPUNCT(c) (ISASCII (c) && ispunct (c))
+# define ISSPACE(c) (ISASCII (c) && isspace (c))
+# define ISUPPER(c) (ISASCII (c) && isupper (c))
+# define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
+
+# define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
+
+# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+/* The GNU C library provides support for user-defined character classes
+   and the functions from ISO C amendement 1.  */
+#  ifdef CHARCLASS_NAME_MAX
+#   define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
+#  else
+/* This shouldn't happen but some implementation might still have this
+   problem.  Use a reasonable default value.  */
+#   define CHAR_CLASS_MAX_LENGTH 256
+#  endif
+
+#  ifdef _LIBC
+#   define IS_CHAR_CLASS(string) __wctype (string)
+#  else
+#   define IS_CHAR_CLASS(string) wctype (string)
+#  endif
+# else
+#  define CHAR_CLASS_MAX_LENGTH  6 /* Namely, `xdigit'.  */
+
+#  define IS_CHAR_CLASS(string)						      \
+   (STREQ (string, "alpha") || STREQ (string, "upper")			      \
+    || STREQ (string, "lower") || STREQ (string, "digit")		      \
+    || STREQ (string, "alnum") || STREQ (string, "xdigit")		      \
+    || STREQ (string, "space") || STREQ (string, "print")		      \
+    || STREQ (string, "punct") || STREQ (string, "graph")		      \
+    || STREQ (string, "cntrl") || STREQ (string, "blank"))
+# endif
+
+/* Avoid depending on library functions or files
+   whose names are inconsistent.  */
+
+# if !defined _LIBC && !defined getenv
+extern char *getenv ();
+# endif
+
+# ifndef errno
+extern int errno;
+# endif
+
+/* This function doesn't exist on most systems.  */
+
+# if !defined HAVE___STRCHRNUL && !defined _LIBC
+static char *
+__strchrnul (s, c)
+     const char *s;
+     int c;
+{
+  char *result = strchr (s, c);
+  if (result == NULL)
+    result = strchr (s, '\0');
+  return result;
+}
+# endif
+
+# ifndef internal_function
+/* Inside GNU libc we mark some function in a special way.  In other
+   environments simply ignore the marking.  */
+#  define internal_function
+# endif
+
+/* Match STRING against the filename pattern PATTERN, returning zero if
+   it matches, nonzero if not.  */
+static int internal_fnmatch __P ((const char *pattern, const char *string,
+				  int no_leading_period, int flags))
+     internal_function;
+static int
+internal_function
+internal_fnmatch (pattern, string, no_leading_period, flags)
+     const char *pattern;
+     const char *string;
+     int no_leading_period;
+     int flags;
+{
+  register const char *p = pattern, *n = string;
+  register unsigned char c;
+
+/* Note that this evaluates C many times.  */
+# ifdef _LIBC
+#  define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
+# else
+#  define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
+# endif
+
+  while ((c = *p++) != '\0')
+    {
+      c = FOLD (c);
+
+      switch (c)
+	{
+	case '?':
+	  if (*n == '\0')
+	    return FNM_NOMATCH;
+	  else if (*n == '/' && (flags & FNM_FILE_NAME))
+	    return FNM_NOMATCH;
+	  else if (*n == '.' && no_leading_period
+		   && (n == string
+		       || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
+	    return FNM_NOMATCH;
+	  break;
+
+	case '\\':
+	  if (!(flags & FNM_NOESCAPE))
+	    {
+	      c = *p++;
+	      if (c == '\0')
+		/* Trailing \ loses.  */
+		return FNM_NOMATCH;
+	      c = FOLD (c);
+	    }
+	  if (FOLD ((unsigned char) *n) != c)
+	    return FNM_NOMATCH;
+	  break;
+
+	case '*':
+	  if (*n == '.' && no_leading_period
+	      && (n == string
+		  || (n[-1] == '/' && (flags & FNM_FILE_NAME))))
+	    return FNM_NOMATCH;
+
+	  for (c = *p++; c == '?' || c == '*'; c = *p++)
+	    {
+	      if (*n == '/' && (flags & FNM_FILE_NAME))
+		/* A slash does not match a wildcard under FNM_FILE_NAME.  */
+		return FNM_NOMATCH;
+	      else if (c == '?')
+		{
+		  /* A ? needs to match one character.  */
+		  if (*n == '\0')
+		    /* There isn't another character; no match.  */
+		    return FNM_NOMATCH;
+		  else
+		    /* One character of the string is consumed in matching
+		       this ? wildcard, so *??? won't match if there are
+		       less than three characters.  */
+		    ++n;
+		}
+	    }
+
+	  if (c == '\0')
+	    /* The wildcard(s) is/are the last element of the pattern.
+	       If the name is a file name and contains another slash
+	       this does mean it cannot match.  */
+	    return ((flags & FNM_FILE_NAME) && strchr (n, '/') != NULL
+		    ? FNM_NOMATCH : 0);
+	  else
+	    {
+	      const char *endp;
+
+	      endp = __strchrnul (n, (flags & FNM_FILE_NAME) ? '/' : '\0');
+
+	      if (c == '[')
+		{
+		  int flags2 = ((flags & FNM_FILE_NAME)
+				? flags : (flags & ~FNM_PERIOD));
+
+		  for (--p; n < endp; ++n)
+		    if (internal_fnmatch (p, n,
+					  (no_leading_period
+					   && (n == string
+					       || (n[-1] == '/'
+						   && (flags
+						       & FNM_FILE_NAME)))),
+					  flags2)
+			== 0)
+		      return 0;
+		}
+	      else if (c == '/' && (flags & FNM_FILE_NAME))
+		{
+		  while (*n != '\0' && *n != '/')
+		    ++n;
+		  if (*n == '/'
+		      && (internal_fnmatch (p, n + 1, flags & FNM_PERIOD,
+					    flags) == 0))
+		    return 0;
+		}
+	      else
+		{
+		  int flags2 = ((flags & FNM_FILE_NAME)
+				? flags : (flags & ~FNM_PERIOD));
+
+		  if (c == '\\' && !(flags & FNM_NOESCAPE))
+		    c = *p;
+		  c = FOLD (c);
+		  for (--p; n < endp; ++n)
+		    if (FOLD ((unsigned char) *n) == c
+			&& (internal_fnmatch (p, n,
+					      (no_leading_period
+					       && (n == string
+						   || (n[-1] == '/'
+						       && (flags
+							   & FNM_FILE_NAME)))),
+					      flags2) == 0))
+		      return 0;
+		}
+	    }
+
+	  /* If we come here no match is possible with the wildcard.  */
+	  return FNM_NOMATCH;
+
+	case '[':
+	  {
+	    /* Nonzero if the sense of the character class is inverted.  */
+	    static int posixly_correct;
+	    register int not;
+	    char cold;
+
+	    if (posixly_correct == 0)
+	      posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1;
+
+	    if (*n == '\0')
+	      return FNM_NOMATCH;
+
+	    if (*n == '.' && no_leading_period && (n == string
+						   || (n[-1] == '/'
+						       && (flags
+							   & FNM_FILE_NAME))))
+	      return FNM_NOMATCH;
+
+	    if (*n == '/' && (flags & FNM_FILE_NAME))
+	      /* `/' cannot be matched.  */
+	      return FNM_NOMATCH;
+
+	    not = (*p == '!' || (posixly_correct < 0 && *p == '^'));
+	    if (not)
+	      ++p;
+
+	    c = *p++;
+	    for (;;)
+	      {
+		unsigned char fn = FOLD ((unsigned char) *n);
+
+		if (!(flags & FNM_NOESCAPE) && c == '\\')
+		  {
+		    if (*p == '\0')
+		      return FNM_NOMATCH;
+		    c = FOLD ((unsigned char) *p);
+		    ++p;
+
+		    if (c == fn)
+		      goto matched;
+		  }
+		else if (c == '[' && *p == ':')
+		  {
+		    /* Leave room for the null.  */
+		    char str[CHAR_CLASS_MAX_LENGTH + 1];
+		    size_t c1 = 0;
+# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+		    wctype_t wt;
+# endif
+		    const char *startp = p;
+
+		    for (;;)
+		      {
+			if (c1 == CHAR_CLASS_MAX_LENGTH)
+			  /* The name is too long and therefore the pattern
+			     is ill-formed.  */
+			  return FNM_NOMATCH;
+
+			c = *++p;
+			if (c == ':' && p[1] == ']')
+			  {
+			    p += 2;
+			    break;
+			  }
+			if (c < 'a' || c >= 'z')
+			  {
+			    /* This cannot possibly be a character class name.
+			       Match it as a normal range.  */
+			    p = startp;
+			    c = '[';
+			    goto normal_bracket;
+			  }
+			str[c1++] = c;
+		      }
+		    str[c1] = '\0';
+
+# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H)
+		    wt = IS_CHAR_CLASS (str);
+		    if (wt == 0)
+		      /* Invalid character class name.  */
+		      return FNM_NOMATCH;
+
+		    if (__iswctype (__btowc ((unsigned char) *n), wt))
+		      goto matched;
+# else
+		    if ((STREQ (str, "alnum") && ISALNUM ((unsigned char) *n))
+			|| (STREQ (str, "alpha") && ISALPHA ((unsigned char) *n))
+			|| (STREQ (str, "blank") && ISBLANK ((unsigned char) *n))
+			|| (STREQ (str, "cntrl") && ISCNTRL ((unsigned char) *n))
+			|| (STREQ (str, "digit") && ISDIGIT ((unsigned char) *n))
+			|| (STREQ (str, "graph") && ISGRAPH ((unsigned char) *n))
+			|| (STREQ (str, "lower") && ISLOWER ((unsigned char) *n))
+			|| (STREQ (str, "print") && ISPRINT ((unsigned char) *n))
+			|| (STREQ (str, "punct") && ISPUNCT ((unsigned char) *n))
+			|| (STREQ (str, "space") && ISSPACE ((unsigned char) *n))
+			|| (STREQ (str, "upper") && ISUPPER ((unsigned char) *n))
+			|| (STREQ (str, "xdigit") && ISXDIGIT ((unsigned char) *n)))
+		      goto matched;
+# endif
+		  }
+		else if (c == '\0')
+		  /* [ (unterminated) loses.  */
+		  return FNM_NOMATCH;
+		else
+		  {
+		  normal_bracket:
+		    if (FOLD (c) == fn)
+		      goto matched;
+
+		    cold = c;
+		    c = *p++;
+
+		    if (c == '-' && *p != ']')
+		      {
+			/* It is a range.  */
+			unsigned char cend = *p++;
+			if (!(flags & FNM_NOESCAPE) && cend == '\\')
+			  cend = *p++;
+			if (cend == '\0')
+			  return FNM_NOMATCH;
+
+			if (cold <= fn && fn <= FOLD (cend))
+			  goto matched;
+
+			c = *p++;
+		      }
+		  }
+
+		if (c == ']')
+		  break;
+	      }
+
+	    if (!not)
+	      return FNM_NOMATCH;
+	    break;
+
+	  matched:
+	    /* Skip the rest of the [...] that already matched.  */
+	    while (c != ']')
+	      {
+		if (c == '\0')
+		  /* [... (unterminated) loses.  */
+		  return FNM_NOMATCH;
+
+		c = *p++;
+		if (!(flags & FNM_NOESCAPE) && c == '\\')
+		  {
+		    if (*p == '\0')
+		      return FNM_NOMATCH;
+		    /* XXX 1003.2d11 is unclear if this is right.  */
+		    ++p;
+		  }
+		else if (c == '[' && *p == ':')
+		  {
+		    do
+		      if (*++p == '\0')
+			return FNM_NOMATCH;
+		    while (*p != ':' || p[1] == ']');
+		    p += 2;
+		    c = *p;
+		  }
+	      }
+	    if (not)
+	      return FNM_NOMATCH;
+	  }
+	  break;
+
+	default:
+	  if (c != FOLD ((unsigned char) *n))
+	    return FNM_NOMATCH;
+	}
+
+      ++n;
+    }
+
+  if (*n == '\0')
+    return 0;
+
+  if ((flags & FNM_LEADING_DIR) && *n == '/')
+    /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz".  */
+    return 0;
+
+  return FNM_NOMATCH;
+
+# undef FOLD
+}
+
+
+int
+fnmatch (pattern, string, flags)
+     const char *pattern;
+     const char *string;
+     int flags;
+{
+  return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags);
+}
+
+#endif	/* _LIBC or not __GNU_LIBRARY__.  */
diff --git a/compat/fnmatch/fnmatch.h b/compat/fnmatch/fnmatch.h
new file mode 100644
index 0000000..cc3ec37
--- /dev/null
+++ b/compat/fnmatch/fnmatch.h
@@ -0,0 +1,84 @@
+/* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef	_FNMATCH_H
+#define	_FNMATCH_H	1
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+#if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32
+# if !defined __GLIBC__ || !defined __P
+#  undef	__P
+#  define __P(protos)	protos
+# endif
+#else /* Not C++ or ANSI C.  */
+# undef	__P
+# define __P(protos)	()
+/* We can get away without defining `const' here only because in this file
+   it is used only inside the prototype for `fnmatch', which is elided in
+   non-ANSI C where `const' is problematical.  */
+#endif /* C++ or ANSI C.  */
+
+#ifndef const
+# if (defined __STDC__ && __STDC__) || defined __cplusplus
+#  define __const	const
+# else
+#  define __const
+# endif
+#endif
+
+/* We #undef these before defining them because some losing systems
+   (HP-UX A.08.07 for example) define these in <unistd.h>.  */
+#undef	FNM_PATHNAME
+#undef	FNM_NOESCAPE
+#undef	FNM_PERIOD
+
+/* Bits set in the FLAGS argument to `fnmatch'.  */
+#define	FNM_PATHNAME	(1 << 0) /* No wildcard can ever match `/'.  */
+#define	FNM_NOESCAPE	(1 << 1) /* Backslashes don't quote special chars.  */
+#define	FNM_PERIOD	(1 << 2) /* Leading `.' is matched only explicitly.  */
+
+#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _GNU_SOURCE
+# define FNM_FILE_NAME	 FNM_PATHNAME	/* Preferred GNU name.  */
+# define FNM_LEADING_DIR (1 << 3)	/* Ignore `/...' after a match.  */
+# define FNM_CASEFOLD	 (1 << 4)	/* Compare without regard to case.  */
+#endif
+
+/* Value returned by `fnmatch' if STRING does not match PATTERN.  */
+#define	FNM_NOMATCH	1
+
+/* This value is returned if the implementation does not support
+   `fnmatch'.  Since this is not the case here it will never be
+   returned but the conformance test suites still require the symbol
+   to be defined.  */
+#ifdef _XOPEN_SOURCE
+# define FNM_NOSYS	(-1)
+#endif
+
+/* Match NAME against the filename pattern PATTERN,
+   returning zero if it matches, FNM_NOMATCH if not.  */
+extern int fnmatch __P ((__const char *__pattern, __const char *__name,
+			 int __flags));
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* fnmatch.h */
diff --git a/compat/mingw.c b/compat/mingw.c
new file mode 100644
index 0000000..45733f9
--- /dev/null
+++ b/compat/mingw.c
@@ -0,0 +1,1051 @@
+#include "../git-compat-util.h"
+#include "../strbuf.h"
+
+unsigned int _CRT_fmode = _O_BINARY;
+
+#undef open
+int mingw_open (const char *filename, int oflags, ...)
+{
+	va_list args;
+	unsigned mode;
+	va_start(args, oflags);
+	mode = va_arg(args, int);
+	va_end(args);
+
+	if (!strcmp(filename, "/dev/null"))
+		filename = "nul";
+	int fd = open(filename, oflags, mode);
+	if (fd < 0 && (oflags & O_CREAT) && errno == EACCES) {
+		DWORD attrs = GetFileAttributes(filename);
+		if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY))
+			errno = EISDIR;
+	}
+	return fd;
+}
+
+static inline time_t filetime_to_time_t(const FILETIME *ft)
+{
+	long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
+	winTime -= 116444736000000000LL; /* Windows to Unix Epoch conversion */
+	winTime /= 10000000;		 /* Nano to seconds resolution */
+	return (time_t)winTime;
+}
+
+static inline size_t size_to_blocks(size_t s)
+{
+	return (s+511)/512;
+}
+
+extern int _getdrive( void );
+/* We keep the do_lstat code in a separate function to avoid recursion.
+ * When a path ends with a slash, the stat will fail with ENOENT. In
+ * this case, we strip the trailing slashes and stat again.
+ */
+static int do_lstat(const char *file_name, struct stat *buf)
+{
+	WIN32_FILE_ATTRIBUTE_DATA fdata;
+
+	if (GetFileAttributesExA(file_name, GetFileExInfoStandard, &fdata)) {
+		int fMode = S_IREAD;
+		if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+			fMode |= S_IFDIR;
+		else
+			fMode |= S_IFREG;
+		if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
+			fMode |= S_IWRITE;
+
+		buf->st_ino = 0;
+		buf->st_gid = 0;
+		buf->st_uid = 0;
+		buf->st_mode = fMode;
+		buf->st_size = fdata.nFileSizeLow; /* Can't use nFileSizeHigh, since it's not a stat64 */
+		buf->st_blocks = size_to_blocks(buf->st_size);
+		buf->st_dev = _getdrive() - 1;
+		buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
+		buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
+		buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
+		errno = 0;
+		return 0;
+	}
+
+	switch (GetLastError()) {
+	case ERROR_ACCESS_DENIED:
+	case ERROR_SHARING_VIOLATION:
+	case ERROR_LOCK_VIOLATION:
+	case ERROR_SHARING_BUFFER_EXCEEDED:
+		errno = EACCES;
+		break;
+	case ERROR_BUFFER_OVERFLOW:
+		errno = ENAMETOOLONG;
+		break;
+	case ERROR_NOT_ENOUGH_MEMORY:
+		errno = ENOMEM;
+		break;
+	default:
+		errno = ENOENT;
+		break;
+	}
+	return -1;
+}
+
+/* We provide our own lstat/fstat functions, since the provided
+ * lstat/fstat functions are so slow. These stat functions are
+ * tailored for Git's usage (read: fast), and are not meant to be
+ * complete. Note that Git stat()s are redirected to mingw_lstat()
+ * too, since Windows doesn't really handle symlinks that well.
+ */
+int mingw_lstat(const char *file_name, struct mingw_stat *buf)
+{
+	int namelen;
+	static char alt_name[PATH_MAX];
+
+	if (!do_lstat(file_name, buf))
+		return 0;
+
+	/* if file_name ended in a '/', Windows returned ENOENT;
+	 * try again without trailing slashes
+	 */
+	if (errno != ENOENT)
+		return -1;
+
+	namelen = strlen(file_name);
+	if (namelen && file_name[namelen-1] != '/')
+		return -1;
+	while (namelen && file_name[namelen-1] == '/')
+		--namelen;
+	if (!namelen || namelen >= PATH_MAX)
+		return -1;
+
+	memcpy(alt_name, file_name, namelen);
+	alt_name[namelen] = 0;
+	return do_lstat(alt_name, buf);
+}
+
+#undef fstat
+#undef stat
+int mingw_fstat(int fd, struct mingw_stat *buf)
+{
+	HANDLE fh = (HANDLE)_get_osfhandle(fd);
+	BY_HANDLE_FILE_INFORMATION fdata;
+
+	if (fh == INVALID_HANDLE_VALUE) {
+		errno = EBADF;
+		return -1;
+	}
+	/* direct non-file handles to MS's fstat() */
+	if (GetFileType(fh) != FILE_TYPE_DISK) {
+		struct stat st;
+		if (fstat(fd, &st))
+			return -1;
+		buf->st_ino = st.st_ino;
+		buf->st_gid = st.st_gid;
+		buf->st_uid = st.st_uid;
+		buf->st_mode = st.st_mode;
+		buf->st_size = st.st_size;
+		buf->st_blocks = size_to_blocks(buf->st_size);
+		buf->st_dev = st.st_dev;
+		buf->st_atime = st.st_atime;
+		buf->st_mtime = st.st_mtime;
+		buf->st_ctime = st.st_ctime;
+		return 0;
+	}
+
+	if (GetFileInformationByHandle(fh, &fdata)) {
+		int fMode = S_IREAD;
+		if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+			fMode |= S_IFDIR;
+		else
+			fMode |= S_IFREG;
+		if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
+			fMode |= S_IWRITE;
+
+		buf->st_ino = 0;
+		buf->st_gid = 0;
+		buf->st_uid = 0;
+		buf->st_mode = fMode;
+		buf->st_size = fdata.nFileSizeLow; /* Can't use nFileSizeHigh, since it's not a stat64 */
+		buf->st_blocks = size_to_blocks(buf->st_size);
+		buf->st_dev = _getdrive() - 1;
+		buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
+		buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
+		buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
+		return 0;
+	}
+	errno = EBADF;
+	return -1;
+}
+
+static inline void time_t_to_filetime(time_t t, FILETIME *ft)
+{
+	long long winTime = t * 10000000LL + 116444736000000000LL;
+	ft->dwLowDateTime = winTime;
+	ft->dwHighDateTime = winTime >> 32;
+}
+
+int mingw_utime (const char *file_name, const struct utimbuf *times)
+{
+	FILETIME mft, aft;
+	int fh, rc;
+
+	/* must have write permission */
+	if ((fh = open(file_name, O_RDWR | O_BINARY)) < 0)
+		return -1;
+
+	time_t_to_filetime(times->modtime, &mft);
+	time_t_to_filetime(times->actime, &aft);
+	if (!SetFileTime((HANDLE)_get_osfhandle(fh), NULL, &aft, &mft)) {
+		errno = EINVAL;
+		rc = -1;
+	} else
+		rc = 0;
+	close(fh);
+	return rc;
+}
+
+unsigned int sleep (unsigned int seconds)
+{
+	Sleep(seconds*1000);
+	return 0;
+}
+
+int mkstemp(char *template)
+{
+	char *filename = mktemp(template);
+	if (filename == NULL)
+		return -1;
+	return open(filename, O_RDWR | O_CREAT, 0600);
+}
+
+int gettimeofday(struct timeval *tv, void *tz)
+{
+	SYSTEMTIME st;
+	struct tm tm;
+	GetSystemTime(&st);
+	tm.tm_year = st.wYear-1900;
+	tm.tm_mon = st.wMonth-1;
+	tm.tm_mday = st.wDay;
+	tm.tm_hour = st.wHour;
+	tm.tm_min = st.wMinute;
+	tm.tm_sec = st.wSecond;
+	tv->tv_sec = tm_to_time_t(&tm);
+	if (tv->tv_sec < 0)
+		return -1;
+	tv->tv_usec = st.wMilliseconds*1000;
+	return 0;
+}
+
+int pipe(int filedes[2])
+{
+	int fd;
+	HANDLE h[2], parent;
+
+	if (_pipe(filedes, 8192, 0) < 0)
+		return -1;
+
+	parent = GetCurrentProcess();
+
+	if (!DuplicateHandle (parent, (HANDLE)_get_osfhandle(filedes[0]),
+			parent, &h[0], 0, FALSE, DUPLICATE_SAME_ACCESS)) {
+		close(filedes[0]);
+		close(filedes[1]);
+		return -1;
+	}
+	if (!DuplicateHandle (parent, (HANDLE)_get_osfhandle(filedes[1]),
+			parent, &h[1], 0, FALSE, DUPLICATE_SAME_ACCESS)) {
+		close(filedes[0]);
+		close(filedes[1]);
+		CloseHandle(h[0]);
+		return -1;
+	}
+	fd = _open_osfhandle((int)h[0], O_NOINHERIT);
+	if (fd < 0) {
+		close(filedes[0]);
+		close(filedes[1]);
+		CloseHandle(h[0]);
+		CloseHandle(h[1]);
+		return -1;
+	}
+	close(filedes[0]);
+	filedes[0] = fd;
+	fd = _open_osfhandle((int)h[1], O_NOINHERIT);
+	if (fd < 0) {
+		close(filedes[0]);
+		close(filedes[1]);
+		CloseHandle(h[1]);
+		return -1;
+	}
+	close(filedes[1]);
+	filedes[1] = fd;
+	return 0;
+}
+
+int poll(struct pollfd *ufds, unsigned int nfds, int timeout)
+{
+	int i, pending;
+
+	if (timeout != -1)
+		return errno = EINVAL, error("poll timeout not supported");
+
+	/* When there is only one fd to wait for, then we pretend that
+	 * input is available and let the actual wait happen when the
+	 * caller invokes read().
+	 */
+	if (nfds == 1) {
+		if (!(ufds[0].events & POLLIN))
+			return errno = EINVAL, error("POLLIN not set");
+		ufds[0].revents = POLLIN;
+		return 0;
+	}
+
+repeat:
+	pending = 0;
+	for (i = 0; i < nfds; i++) {
+		DWORD avail = 0;
+		HANDLE h = (HANDLE) _get_osfhandle(ufds[i].fd);
+		if (h == INVALID_HANDLE_VALUE)
+			return -1;	/* errno was set */
+
+		if (!(ufds[i].events & POLLIN))
+			return errno = EINVAL, error("POLLIN not set");
+
+		/* this emulation works only for pipes */
+		if (!PeekNamedPipe(h, NULL, 0, NULL, &avail, NULL)) {
+			int err = GetLastError();
+			if (err == ERROR_BROKEN_PIPE) {
+				ufds[i].revents = POLLHUP;
+				pending++;
+			} else {
+				errno = EINVAL;
+				return error("PeekNamedPipe failed,"
+					" GetLastError: %u", err);
+			}
+		} else if (avail) {
+			ufds[i].revents = POLLIN;
+			pending++;
+		} else
+			ufds[i].revents = 0;
+	}
+	if (!pending) {
+		/* The only times that we spin here is when the process
+		 * that is connected through the pipes is waiting for
+		 * its own input data to become available. But since
+		 * the process (pack-objects) is itself CPU intensive,
+		 * it will happily pick up the time slice that we are
+		 * relinguishing here.
+		 */
+		Sleep(0);
+		goto repeat;
+	}
+	return 0;
+}
+
+struct tm *gmtime_r(const time_t *timep, struct tm *result)
+{
+	/* gmtime() in MSVCRT.DLL is thread-safe, but not reentrant */
+	memcpy(result, gmtime(timep), sizeof(struct tm));
+	return result;
+}
+
+struct tm *localtime_r(const time_t *timep, struct tm *result)
+{
+	/* localtime() in MSVCRT.DLL is thread-safe, but not reentrant */
+	memcpy(result, localtime(timep), sizeof(struct tm));
+	return result;
+}
+
+#undef getcwd
+char *mingw_getcwd(char *pointer, int len)
+{
+	int i;
+	char *ret = getcwd(pointer, len);
+	if (!ret)
+		return ret;
+	for (i = 0; pointer[i]; i++)
+		if (pointer[i] == '\\')
+			pointer[i] = '/';
+	return ret;
+}
+
+#undef getenv
+char *mingw_getenv(const char *name)
+{
+	char *result = getenv(name);
+	if (!result && !strcmp(name, "TMPDIR")) {
+		/* on Windows it is TMP and TEMP */
+		result = getenv("TMP");
+		if (!result)
+			result = getenv("TEMP");
+	}
+	return result;
+}
+
+/*
+ * See http://msdn2.microsoft.com/en-us/library/17w5ykft(vs.71).aspx
+ * (Parsing C++ Command-Line Arguments)
+ */
+static const char *quote_arg(const char *arg)
+{
+	/* count chars to quote */
+	int len = 0, n = 0;
+	int force_quotes = 0;
+	char *q, *d;
+	const char *p = arg;
+	if (!*p) force_quotes = 1;
+	while (*p) {
+		if (isspace(*p) || *p == '*' || *p == '?' || *p == '{')
+			force_quotes = 1;
+		else if (*p == '"')
+			n++;
+		else if (*p == '\\') {
+			int count = 0;
+			while (*p == '\\') {
+				count++;
+				p++;
+				len++;
+			}
+			if (*p == '"')
+				n += count*2 + 1;
+			continue;
+		}
+		len++;
+		p++;
+	}
+	if (!force_quotes && n == 0)
+		return arg;
+
+	/* insert \ where necessary */
+	d = q = xmalloc(len+n+3);
+	*d++ = '"';
+	while (*arg) {
+		if (*arg == '"')
+			*d++ = '\\';
+		else if (*arg == '\\') {
+			int count = 0;
+			while (*arg == '\\') {
+				count++;
+				*d++ = *arg++;
+			}
+			if (*arg == '"') {
+				while (count-- > 0)
+					*d++ = '\\';
+				*d++ = '\\';
+			}
+		}
+		*d++ = *arg++;
+	}
+	*d++ = '"';
+	*d++ = 0;
+	return q;
+}
+
+static const char *parse_interpreter(const char *cmd)
+{
+	static char buf[100];
+	char *p, *opt;
+	int n, fd;
+
+	/* don't even try a .exe */
+	n = strlen(cmd);
+	if (n >= 4 && !strcasecmp(cmd+n-4, ".exe"))
+		return NULL;
+
+	fd = open(cmd, O_RDONLY);
+	if (fd < 0)
+		return NULL;
+	n = read(fd, buf, sizeof(buf)-1);
+	close(fd);
+	if (n < 4)	/* at least '#!/x' and not error */
+		return NULL;
+
+	if (buf[0] != '#' || buf[1] != '!')
+		return NULL;
+	buf[n] = '\0';
+	p = strchr(buf, '\n');
+	if (!p)
+		return NULL;
+
+	*p = '\0';
+	if (!(p = strrchr(buf+2, '/')) && !(p = strrchr(buf+2, '\\')))
+		return NULL;
+	/* strip options */
+	if ((opt = strchr(p+1, ' ')))
+		*opt = '\0';
+	return p+1;
+}
+
+/*
+ * Splits the PATH into parts.
+ */
+static char **get_path_split(void)
+{
+	char *p, **path, *envpath = getenv("PATH");
+	int i, n = 0;
+
+	if (!envpath || !*envpath)
+		return NULL;
+
+	envpath = xstrdup(envpath);
+	p = envpath;
+	while (p) {
+		char *dir = p;
+		p = strchr(p, ';');
+		if (p) *p++ = '\0';
+		if (*dir) {	/* not earlier, catches series of ; */
+			++n;
+		}
+	}
+	if (!n)
+		return NULL;
+
+	path = xmalloc((n+1)*sizeof(char*));
+	p = envpath;
+	i = 0;
+	do {
+		if (*p)
+			path[i++] = xstrdup(p);
+		p = p+strlen(p)+1;
+	} while (i < n);
+	path[i] = NULL;
+
+	free(envpath);
+
+	return path;
+}
+
+static void free_path_split(char **path)
+{
+	if (!path)
+		return;
+
+	char **p = path;
+	while (*p)
+		free(*p++);
+	free(path);
+}
+
+/*
+ * exe_only means that we only want to detect .exe files, but not scripts
+ * (which do not have an extension)
+ */
+static char *lookup_prog(const char *dir, const char *cmd, int isexe, int exe_only)
+{
+	char path[MAX_PATH];
+	snprintf(path, sizeof(path), "%s/%s.exe", dir, cmd);
+
+	if (!isexe && access(path, F_OK) == 0)
+		return xstrdup(path);
+	path[strlen(path)-4] = '\0';
+	if ((!exe_only || isexe) && access(path, F_OK) == 0)
+		if (!(GetFileAttributes(path) & FILE_ATTRIBUTE_DIRECTORY))
+			return xstrdup(path);
+	return NULL;
+}
+
+/*
+ * Determines the absolute path of cmd using the the split path in path.
+ * If cmd contains a slash or backslash, no lookup is performed.
+ */
+static char *path_lookup(const char *cmd, char **path, int exe_only)
+{
+	char *prog = NULL;
+	int len = strlen(cmd);
+	int isexe = len >= 4 && !strcasecmp(cmd+len-4, ".exe");
+
+	if (strchr(cmd, '/') || strchr(cmd, '\\'))
+		prog = xstrdup(cmd);
+
+	while (!prog && *path)
+		prog = lookup_prog(*path++, cmd, isexe, exe_only);
+
+	return prog;
+}
+
+static int env_compare(const void *a, const void *b)
+{
+	char *const *ea = a;
+	char *const *eb = b;
+	return strcasecmp(*ea, *eb);
+}
+
+static pid_t mingw_spawnve(const char *cmd, const char **argv, char **env,
+			   int prepend_cmd)
+{
+	STARTUPINFO si;
+	PROCESS_INFORMATION pi;
+	struct strbuf envblk, args;
+	unsigned flags;
+	BOOL ret;
+
+	/* Determine whether or not we are associated to a console */
+	HANDLE cons = CreateFile("CONOUT$", GENERIC_WRITE,
+			FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
+			FILE_ATTRIBUTE_NORMAL, NULL);
+	if (cons == INVALID_HANDLE_VALUE) {
+		/* There is no console associated with this process.
+		 * Since the child is a console process, Windows
+		 * would normally create a console window. But
+		 * since we'll be redirecting std streams, we do
+		 * not need the console.
+		 */
+		flags = CREATE_NO_WINDOW;
+	} else {
+		/* There is already a console. If we specified
+		 * CREATE_NO_WINDOW here, too, Windows would
+		 * disassociate the child from the console.
+		 * Go figure!
+		 */
+		flags = 0;
+		CloseHandle(cons);
+	}
+	memset(&si, 0, sizeof(si));
+	si.cb = sizeof(si);
+	si.dwFlags = STARTF_USESTDHANDLES;
+	si.hStdInput = (HANDLE) _get_osfhandle(0);
+	si.hStdOutput = (HANDLE) _get_osfhandle(1);
+	si.hStdError = (HANDLE) _get_osfhandle(2);
+
+	/* concatenate argv, quoting args as we go */
+	strbuf_init(&args, 0);
+	if (prepend_cmd) {
+		char *quoted = (char *)quote_arg(cmd);
+		strbuf_addstr(&args, quoted);
+		if (quoted != cmd)
+			free(quoted);
+	}
+	for (; *argv; argv++) {
+		char *quoted = (char *)quote_arg(*argv);
+		if (*args.buf)
+			strbuf_addch(&args, ' ');
+		strbuf_addstr(&args, quoted);
+		if (quoted != *argv)
+			free(quoted);
+	}
+
+	if (env) {
+		int count = 0;
+		char **e, **sorted_env;
+
+		for (e = env; *e; e++)
+			count++;
+
+		/* environment must be sorted */
+		sorted_env = xmalloc(sizeof(*sorted_env) * (count + 1));
+		memcpy(sorted_env, env, sizeof(*sorted_env) * (count + 1));
+		qsort(sorted_env, count, sizeof(*sorted_env), env_compare);
+
+		strbuf_init(&envblk, 0);
+		for (e = sorted_env; *e; e++) {
+			strbuf_addstr(&envblk, *e);
+			strbuf_addch(&envblk, '\0');
+		}
+		free(sorted_env);
+	}
+
+	memset(&pi, 0, sizeof(pi));
+	ret = CreateProcess(cmd, args.buf, NULL, NULL, TRUE, flags,
+		env ? envblk.buf : NULL, NULL, &si, &pi);
+
+	if (env)
+		strbuf_release(&envblk);
+	strbuf_release(&args);
+
+	if (!ret) {
+		errno = ENOENT;
+		return -1;
+	}
+	CloseHandle(pi.hThread);
+	return (pid_t)pi.hProcess;
+}
+
+pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env)
+{
+	pid_t pid;
+	char **path = get_path_split();
+	char *prog = path_lookup(cmd, path, 0);
+
+	if (!prog) {
+		errno = ENOENT;
+		pid = -1;
+	}
+	else {
+		const char *interpr = parse_interpreter(prog);
+
+		if (interpr) {
+			const char *argv0 = argv[0];
+			char *iprog = path_lookup(interpr, path, 1);
+			argv[0] = prog;
+			if (!iprog) {
+				errno = ENOENT;
+				pid = -1;
+			}
+			else {
+				pid = mingw_spawnve(iprog, argv, env, 1);
+				free(iprog);
+			}
+			argv[0] = argv0;
+		}
+		else
+			pid = mingw_spawnve(prog, argv, env, 0);
+		free(prog);
+	}
+	free_path_split(path);
+	return pid;
+}
+
+static int try_shell_exec(const char *cmd, char *const *argv, char **env)
+{
+	const char *interpr = parse_interpreter(cmd);
+	char **path;
+	char *prog;
+	int pid = 0;
+
+	if (!interpr)
+		return 0;
+	path = get_path_split();
+	prog = path_lookup(interpr, path, 1);
+	if (prog) {
+		int argc = 0;
+		const char **argv2;
+		while (argv[argc]) argc++;
+		argv2 = xmalloc(sizeof(*argv) * (argc+1));
+		argv2[0] = (char *)cmd;	/* full path to the script file */
+		memcpy(&argv2[1], &argv[1], sizeof(*argv) * argc);
+		pid = mingw_spawnve(prog, argv2, env, 1);
+		if (pid >= 0) {
+			int status;
+			if (waitpid(pid, &status, 0) < 0)
+				status = 255;
+			exit(status);
+		}
+		pid = 1;	/* indicate that we tried but failed */
+		free(prog);
+		free(argv2);
+	}
+	free_path_split(path);
+	return pid;
+}
+
+static void mingw_execve(const char *cmd, char *const *argv, char *const *env)
+{
+	/* check if git_command is a shell script */
+	if (!try_shell_exec(cmd, argv, (char **)env)) {
+		int pid, status;
+
+		pid = mingw_spawnve(cmd, (const char **)argv, (char **)env, 0);
+		if (pid < 0)
+			return;
+		if (waitpid(pid, &status, 0) < 0)
+			status = 255;
+		exit(status);
+	}
+}
+
+void mingw_execvp(const char *cmd, char *const *argv)
+{
+	char **path = get_path_split();
+	char *prog = path_lookup(cmd, path, 0);
+
+	if (prog) {
+		mingw_execve(prog, argv, environ);
+		free(prog);
+	} else
+		errno = ENOENT;
+
+	free_path_split(path);
+}
+
+char **copy_environ()
+{
+	char **env;
+	int i = 0;
+	while (environ[i])
+		i++;
+	env = xmalloc((i+1)*sizeof(*env));
+	for (i = 0; environ[i]; i++)
+		env[i] = xstrdup(environ[i]);
+	env[i] = NULL;
+	return env;
+}
+
+void free_environ(char **env)
+{
+	int i;
+	for (i = 0; env[i]; i++)
+		free(env[i]);
+	free(env);
+}
+
+static int lookup_env(char **env, const char *name, size_t nmln)
+{
+	int i;
+
+	for (i = 0; env[i]; i++) {
+		if (0 == strncmp(env[i], name, nmln)
+		    && '=' == env[i][nmln])
+			/* matches */
+			return i;
+	}
+	return -1;
+}
+
+/*
+ * If name contains '=', then sets the variable, otherwise it unsets it
+ */
+char **env_setenv(char **env, const char *name)
+{
+	char *eq = strchrnul(name, '=');
+	int i = lookup_env(env, name, eq-name);
+
+	if (i < 0) {
+		if (*eq) {
+			for (i = 0; env[i]; i++)
+				;
+			env = xrealloc(env, (i+2)*sizeof(*env));
+			env[i] = xstrdup(name);
+			env[i+1] = NULL;
+		}
+	}
+	else {
+		free(env[i]);
+		if (*eq)
+			env[i] = xstrdup(name);
+		else
+			for (; env[i]; i++)
+				env[i] = env[i+1];
+	}
+	return env;
+}
+
+/* this is the first function to call into WS_32; initialize it */
+#undef gethostbyname
+struct hostent *mingw_gethostbyname(const char *host)
+{
+	WSADATA wsa;
+
+	if (WSAStartup(MAKEWORD(2,2), &wsa))
+		die("unable to initialize winsock subsystem, error %d",
+			WSAGetLastError());
+	atexit((void(*)(void)) WSACleanup);
+	return gethostbyname(host);
+}
+
+int mingw_socket(int domain, int type, int protocol)
+{
+	int sockfd;
+	SOCKET s = WSASocket(domain, type, protocol, NULL, 0, 0);
+	if (s == INVALID_SOCKET) {
+		/*
+		 * WSAGetLastError() values are regular BSD error codes
+		 * biased by WSABASEERR.
+		 * However, strerror() does not know about networking
+		 * specific errors, which are values beginning at 38 or so.
+		 * Therefore, we choose to leave the biased error code
+		 * in errno so that _if_ someone looks up the code somewhere,
+		 * then it is at least the number that are usually listed.
+		 */
+		errno = WSAGetLastError();
+		return -1;
+	}
+	/* convert into a file descriptor */
+	if ((sockfd = _open_osfhandle(s, O_RDWR|O_BINARY)) < 0) {
+		closesocket(s);
+		return error("unable to make a socket file descriptor: %s",
+			strerror(errno));
+	}
+	return sockfd;
+}
+
+#undef connect
+int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz)
+{
+	SOCKET s = (SOCKET)_get_osfhandle(sockfd);
+	return connect(s, sa, sz);
+}
+
+#undef rename
+int mingw_rename(const char *pold, const char *pnew)
+{
+	DWORD attrs;
+
+	/*
+	 * Try native rename() first to get errno right.
+	 * It is based on MoveFile(), which cannot overwrite existing files.
+	 */
+	if (!rename(pold, pnew))
+		return 0;
+	if (errno != EEXIST)
+		return -1;
+	if (MoveFileEx(pold, pnew, MOVEFILE_REPLACE_EXISTING))
+		return 0;
+	/* TODO: translate more errors */
+	if (GetLastError() == ERROR_ACCESS_DENIED &&
+	    (attrs = GetFileAttributes(pnew)) != INVALID_FILE_ATTRIBUTES) {
+		if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
+			errno = EISDIR;
+			return -1;
+		}
+		if ((attrs & FILE_ATTRIBUTE_READONLY) &&
+		    SetFileAttributes(pnew, attrs & ~FILE_ATTRIBUTE_READONLY)) {
+			if (MoveFileEx(pold, pnew, MOVEFILE_REPLACE_EXISTING))
+				return 0;
+			/* revert file attributes on failure */
+			SetFileAttributes(pnew, attrs);
+		}
+	}
+	errno = EACCES;
+	return -1;
+}
+
+struct passwd *getpwuid(int uid)
+{
+	static char user_name[100];
+	static struct passwd p;
+
+	DWORD len = sizeof(user_name);
+	if (!GetUserName(user_name, &len))
+		return NULL;
+	p.pw_name = user_name;
+	p.pw_gecos = "unknown";
+	p.pw_dir = NULL;
+	return &p;
+}
+
+static HANDLE timer_event;
+static HANDLE timer_thread;
+static int timer_interval;
+static int one_shot;
+static sig_handler_t timer_fn = SIG_DFL;
+
+/* The timer works like this:
+ * The thread, ticktack(), is a trivial routine that most of the time
+ * only waits to receive the signal to terminate. The main thread tells
+ * the thread to terminate by setting the timer_event to the signalled
+ * state.
+ * But ticktack() interrupts the wait state after the timer's interval
+ * length to call the signal handler.
+ */
+
+static __stdcall unsigned ticktack(void *dummy)
+{
+	while (WaitForSingleObject(timer_event, timer_interval) == WAIT_TIMEOUT) {
+		if (timer_fn == SIG_DFL)
+			die("Alarm");
+		if (timer_fn != SIG_IGN)
+			timer_fn(SIGALRM);
+		if (one_shot)
+			break;
+	}
+	return 0;
+}
+
+static int start_timer_thread(void)
+{
+	timer_event = CreateEvent(NULL, FALSE, FALSE, NULL);
+	if (timer_event) {
+		timer_thread = (HANDLE) _beginthreadex(NULL, 0, ticktack, NULL, 0, NULL);
+		if (!timer_thread )
+			return errno = ENOMEM,
+				error("cannot start timer thread");
+	} else
+		return errno = ENOMEM,
+			error("cannot allocate resources for timer");
+	return 0;
+}
+
+static void stop_timer_thread(void)
+{
+	if (timer_event)
+		SetEvent(timer_event);	/* tell thread to terminate */
+	if (timer_thread) {
+		int rc = WaitForSingleObject(timer_thread, 1000);
+		if (rc == WAIT_TIMEOUT)
+			error("timer thread did not terminate timely");
+		else if (rc != WAIT_OBJECT_0)
+			error("waiting for timer thread failed: %lu",
+			      GetLastError());
+		CloseHandle(timer_thread);
+	}
+	if (timer_event)
+		CloseHandle(timer_event);
+	timer_event = NULL;
+	timer_thread = NULL;
+}
+
+static inline int is_timeval_eq(const struct timeval *i1, const struct timeval *i2)
+{
+	return i1->tv_sec == i2->tv_sec && i1->tv_usec == i2->tv_usec;
+}
+
+int setitimer(int type, struct itimerval *in, struct itimerval *out)
+{
+	static const struct timeval zero;
+	static int atexit_done;
+
+	if (out != NULL)
+		return errno = EINVAL,
+			error("setitimer param 3 != NULL not implemented");
+	if (!is_timeval_eq(&in->it_interval, &zero) &&
+	    !is_timeval_eq(&in->it_interval, &in->it_value))
+		return errno = EINVAL,
+			error("setitimer: it_interval must be zero or eq it_value");
+
+	if (timer_thread)
+		stop_timer_thread();
+
+	if (is_timeval_eq(&in->it_value, &zero) &&
+	    is_timeval_eq(&in->it_interval, &zero))
+		return 0;
+
+	timer_interval = in->it_value.tv_sec * 1000 + in->it_value.tv_usec / 1000;
+	one_shot = is_timeval_eq(&in->it_interval, &zero);
+	if (!atexit_done) {
+		atexit(stop_timer_thread);
+		atexit_done = 1;
+	}
+	return start_timer_thread();
+}
+
+int sigaction(int sig, struct sigaction *in, struct sigaction *out)
+{
+	if (sig != SIGALRM)
+		return errno = EINVAL,
+			error("sigaction only implemented for SIGALRM");
+	if (out != NULL)
+		return errno = EINVAL,
+			error("sigaction: param 3 != NULL not implemented");
+
+	timer_fn = in->sa_handler;
+	return 0;
+}
+
+#undef signal
+sig_handler_t mingw_signal(int sig, sig_handler_t handler)
+{
+	if (sig != SIGALRM)
+		return signal(sig, handler);
+	sig_handler_t old = timer_fn;
+	timer_fn = handler;
+	return old;
+}
+
+static const char *make_backslash_path(const char *path)
+{
+	static char buf[PATH_MAX + 1];
+	char *c;
+
+	if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
+		die("Too long path: %.*s", 60, path);
+
+	for (c = buf; *c; c++) {
+		if (*c == '/')
+			*c = '\\';
+	}
+	return buf;
+}
+
+void mingw_open_html(const char *unixpath)
+{
+	const char *htmlpath = make_backslash_path(unixpath);
+	printf("Launching default browser to display HTML ...\n");
+	ShellExecute(NULL, "open", htmlpath, NULL, "\\", 0);
+}
diff --git a/compat/mingw.h b/compat/mingw.h
new file mode 100644
index 0000000..a52e657
--- /dev/null
+++ b/compat/mingw.h
@@ -0,0 +1,238 @@
+#include <winsock2.h>
+
+/*
+ * things that are not available in header files
+ */
+
+typedef int pid_t;
+#define hstrerror strerror
+
+#define S_IFLNK    0120000 /* Symbolic link */
+#define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK)
+#define S_ISSOCK(x) 0
+#define S_IRGRP 0
+#define S_IWGRP 0
+#define S_IXGRP 0
+#define S_ISGID 0
+#define S_IROTH 0
+#define S_IXOTH 0
+
+#define WIFEXITED(x) ((unsigned)(x) < 259)	/* STILL_ACTIVE */
+#define WEXITSTATUS(x) ((x) & 0xff)
+#define WIFSIGNALED(x) ((unsigned)(x) > 259)
+
+#define SIGKILL 0
+#define SIGCHLD 0
+#define SIGPIPE 0
+#define SIGHUP 0
+#define SIGQUIT 0
+#define SIGALRM 100
+
+#define F_GETFD 1
+#define F_SETFD 2
+#define FD_CLOEXEC 0x1
+
+struct passwd {
+	char *pw_name;
+	char *pw_gecos;
+	char *pw_dir;
+};
+
+struct pollfd {
+	int fd;           /* file descriptor */
+	short events;     /* requested events */
+	short revents;    /* returned events */
+};
+#define POLLIN 1
+#define POLLHUP 2
+
+typedef void (__cdecl *sig_handler_t)(int);
+struct sigaction {
+	sig_handler_t sa_handler;
+	unsigned sa_flags;
+};
+#define sigemptyset(x) (void)0
+#define SA_RESTART 0
+
+struct itimerval {
+	struct timeval it_value, it_interval;
+};
+#define ITIMER_REAL 0
+
+/*
+ * trivial stubs
+ */
+
+static inline int readlink(const char *path, char *buf, size_t bufsiz)
+{ errno = ENOSYS; return -1; }
+static inline int symlink(const char *oldpath, const char *newpath)
+{ errno = ENOSYS; return -1; }
+static inline int link(const char *oldpath, const char *newpath)
+{ errno = ENOSYS; return -1; }
+static inline int fchmod(int fildes, mode_t mode)
+{ errno = ENOSYS; return -1; }
+static inline int fork(void)
+{ errno = ENOSYS; return -1; }
+static inline unsigned int alarm(unsigned int seconds)
+{ return 0; }
+static inline int fsync(int fd)
+{ return 0; }
+static inline int getppid(void)
+{ return 1; }
+static inline void sync(void)
+{}
+static inline int getuid()
+{ return 1; }
+static inline struct passwd *getpwnam(const char *name)
+{ return NULL; }
+static inline int fcntl(int fd, int cmd, long arg)
+{
+	if (cmd == F_GETFD || cmd == F_SETFD)
+		return 0;
+	errno = EINVAL;
+	return -1;
+}
+
+/*
+ * simple adaptors
+ */
+
+static inline int mingw_mkdir(const char *path, int mode)
+{
+	return mkdir(path);
+}
+#define mkdir mingw_mkdir
+
+static inline int mingw_unlink(const char *pathname)
+{
+	/* read-only files cannot be removed */
+	chmod(pathname, 0666);
+	return unlink(pathname);
+}
+#define unlink mingw_unlink
+
+static inline int waitpid(pid_t pid, unsigned *status, unsigned options)
+{
+	if (options == 0)
+		return _cwait(status, pid, 0);
+	errno = EINVAL;
+	return -1;
+}
+
+/*
+ * implementations of missing functions
+ */
+
+int pipe(int filedes[2]);
+unsigned int sleep (unsigned int seconds);
+int mkstemp(char *template);
+int gettimeofday(struct timeval *tv, void *tz);
+int poll(struct pollfd *ufds, unsigned int nfds, int timeout);
+struct tm *gmtime_r(const time_t *timep, struct tm *result);
+struct tm *localtime_r(const time_t *timep, struct tm *result);
+int getpagesize(void);	/* defined in MinGW's libgcc.a */
+struct passwd *getpwuid(int uid);
+int setitimer(int type, struct itimerval *in, struct itimerval *out);
+int sigaction(int sig, struct sigaction *in, struct sigaction *out);
+
+/*
+ * replacements of existing functions
+ */
+
+int mingw_open (const char *filename, int oflags, ...);
+#define open mingw_open
+
+char *mingw_getcwd(char *pointer, int len);
+#define getcwd mingw_getcwd
+
+char *mingw_getenv(const char *name);
+#define getenv mingw_getenv
+
+struct hostent *mingw_gethostbyname(const char *host);
+#define gethostbyname mingw_gethostbyname
+
+int mingw_socket(int domain, int type, int protocol);
+#define socket mingw_socket
+
+int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz);
+#define connect mingw_connect
+
+int mingw_rename(const char*, const char*);
+#define rename mingw_rename
+
+/* Use mingw_lstat() instead of lstat()/stat() and
+ * mingw_fstat() instead of fstat() on Windows.
+ * struct stat is redefined because it lacks the st_blocks member.
+ */
+struct mingw_stat {
+	unsigned st_mode;
+	time_t st_mtime, st_atime, st_ctime;
+	unsigned st_dev, st_ino, st_uid, st_gid;
+	size_t st_size;
+	size_t st_blocks;
+};
+int mingw_lstat(const char *file_name, struct mingw_stat *buf);
+int mingw_fstat(int fd, struct mingw_stat *buf);
+#define fstat mingw_fstat
+#define lstat mingw_lstat
+#define stat mingw_stat
+static inline int mingw_stat(const char *file_name, struct mingw_stat *buf)
+{ return mingw_lstat(file_name, buf); }
+
+int mingw_utime(const char *file_name, const struct utimbuf *times);
+#define utime mingw_utime
+
+pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env);
+void mingw_execvp(const char *cmd, char *const *argv);
+#define execvp mingw_execvp
+
+static inline unsigned int git_ntohl(unsigned int x)
+{ return (unsigned int)ntohl(x); }
+#define ntohl git_ntohl
+
+sig_handler_t mingw_signal(int sig, sig_handler_t handler);
+#define signal mingw_signal
+
+/*
+ * ANSI emulation wrappers
+ */
+
+int winansi_fputs(const char *str, FILE *stream);
+int winansi_printf(const char *format, ...) __attribute__((format (printf, 1, 2)));
+int winansi_fprintf(FILE *stream, const char *format, ...) __attribute__((format (printf, 2, 3)));
+#define fputs winansi_fputs
+#define printf(...) winansi_printf(__VA_ARGS__)
+#define fprintf(...) winansi_fprintf(__VA_ARGS__)
+
+/*
+ * git specific compatibility
+ */
+
+#define has_dos_drive_prefix(path) (isalpha(*(path)) && (path)[1] == ':')
+#define is_dir_sep(c) ((c) == '/' || (c) == '\\')
+#define PATH_SEP ';'
+#define PRIuMAX "I64u"
+
+void mingw_open_html(const char *path);
+#define open_html mingw_open_html
+
+/*
+ * helpers
+ */
+
+char **copy_environ(void);
+void free_environ(char **env);
+char **env_setenv(char **env, const char *name);
+
+/*
+ * A replacement of main() that ensures that argv[0] has a path
+ */
+
+#define main(c,v) dummy_decl_mingw_main(); \
+static int mingw_main(); \
+int main(int argc, const char **argv) \
+{ \
+	argv[0] = xstrdup(_pgmptr); \
+	return mingw_main(argc, argv); \
+} \
+static int mingw_main(c,v)
diff --git a/compat/regex/regex.c b/compat/regex/regex.c
new file mode 100644
index 0000000..87b33e4
--- /dev/null
+++ b/compat/regex/regex.c
@@ -0,0 +1,4927 @@
+/* Extended regular expression matching and search library,
+   version 0.12.
+   (Implements POSIX draft P10003.2/D11.2, except for
+   internationalization features.)
+
+   Copyright (C) 1993 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* AIX requires this to be the first thing in the file. */
+#if defined (_AIX) && !defined (REGEX_MALLOC)
+  #pragma alloca
+#endif
+
+#define _GNU_SOURCE
+
+/* We need this for `regex.h', and perhaps for the Emacs include files.  */
+#include <sys/types.h>
+
+/* We used to test for `BSTRING' here, but only GCC and Emacs define
+   `BSTRING', as far as I know, and neither of them use this code.  */
+#include <string.h>
+#ifndef bcmp
+#define bcmp(s1, s2, n)	memcmp ((s1), (s2), (n))
+#endif
+#ifndef bcopy
+#define bcopy(s, d, n)	memcpy ((d), (s), (n))
+#endif
+#ifndef bzero
+#define bzero(s, n)	memset ((s), 0, (n))
+#endif
+
+#include <stdlib.h>
+
+
+/* Define the syntax stuff for \<, \>, etc.  */
+
+/* This must be nonzero for the wordchar and notwordchar pattern
+   commands in re_match_2.  */
+#ifndef Sword
+#define Sword 1
+#endif
+
+#ifdef SYNTAX_TABLE
+
+extern char *re_syntax_table;
+
+#else /* not SYNTAX_TABLE */
+
+/* How many characters in the character set.  */
+#define CHAR_SET_SIZE 256
+
+static char re_syntax_table[CHAR_SET_SIZE];
+
+static void
+init_syntax_once ()
+{
+   register int c;
+   static int done = 0;
+
+   if (done)
+     return;
+
+   bzero (re_syntax_table, sizeof re_syntax_table);
+
+   for (c = 'a'; c <= 'z'; c++)
+     re_syntax_table[c] = Sword;
+
+   for (c = 'A'; c <= 'Z'; c++)
+     re_syntax_table[c] = Sword;
+
+   for (c = '0'; c <= '9'; c++)
+     re_syntax_table[c] = Sword;
+
+   re_syntax_table['_'] = Sword;
+
+   done = 1;
+}
+
+#endif /* not SYNTAX_TABLE */
+
+#define SYNTAX(c) re_syntax_table[c]
+
+
+/* Get the interface, including the syntax bits.  */
+#include "regex.h"
+
+/* isalpha etc. are used for the character classes.  */
+#include <ctype.h>
+
+#ifndef isascii
+#define isascii(c) 1
+#endif
+
+#ifdef isblank
+#define ISBLANK(c) (isascii (c) && isblank (c))
+#else
+#define ISBLANK(c) ((c) == ' ' || (c) == '\t')
+#endif
+#ifdef isgraph
+#define ISGRAPH(c) (isascii (c) && isgraph (c))
+#else
+#define ISGRAPH(c) (isascii (c) && isprint (c) && !isspace (c))
+#endif
+
+#define ISPRINT(c) (isascii (c) && isprint (c))
+#define ISDIGIT(c) (isascii (c) && isdigit (c))
+#define ISALNUM(c) (isascii (c) && isalnum (c))
+#define ISALPHA(c) (isascii (c) && isalpha (c))
+#define ISCNTRL(c) (isascii (c) && iscntrl (c))
+#define ISLOWER(c) (isascii (c) && islower (c))
+#define ISPUNCT(c) (isascii (c) && ispunct (c))
+#define ISSPACE(c) (isascii (c) && isspace (c))
+#define ISUPPER(c) (isascii (c) && isupper (c))
+#define ISXDIGIT(c) (isascii (c) && isxdigit (c))
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/* We remove any previous definition of `SIGN_EXTEND_CHAR',
+   since ours (we hope) works properly with all combinations of
+   machines, compilers, `char' and `unsigned char' argument types.
+   (Per Bothner suggested the basic approach.)  */
+#undef SIGN_EXTEND_CHAR
+#if __STDC__
+#define SIGN_EXTEND_CHAR(c) ((signed char) (c))
+#else  /* not __STDC__ */
+/* As in Harbison and Steele.  */
+#define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128)
+#endif
+
+/* Should we use malloc or alloca?  If REGEX_MALLOC is not defined, we
+   use `alloca' instead of `malloc'.  This is because using malloc in
+   re_search* or re_match* could cause memory leaks when C-g is used in
+   Emacs; also, malloc is slower and causes storage fragmentation.  On
+   the other hand, malloc is more portable, and easier to debug.
+
+   Because we sometimes use alloca, some routines have to be macros,
+   not functions -- `alloca'-allocated space disappears at the end of the
+   function it is called in.  */
+
+#ifdef REGEX_MALLOC
+
+#define REGEX_ALLOCATE malloc
+#define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize)
+
+#else /* not REGEX_MALLOC  */
+
+/* Emacs already defines alloca, sometimes.  */
+#ifndef alloca
+
+/* Make alloca work the best possible way.  */
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* not __GNUC__ */
+#if HAVE_ALLOCA_H
+#include <alloca.h>
+#else /* not __GNUC__ or HAVE_ALLOCA_H */
+#ifndef _AIX /* Already did AIX, up at the top.  */
+char *alloca ();
+#endif /* not _AIX */
+#endif /* not HAVE_ALLOCA_H */
+#endif /* not __GNUC__ */
+
+#endif /* not alloca */
+
+#define REGEX_ALLOCATE alloca
+
+/* Assumes a `char *destination' variable.  */
+#define REGEX_REALLOCATE(source, osize, nsize)				\
+  (destination = (char *) alloca (nsize),				\
+   bcopy (source, destination, osize),					\
+   destination)
+
+#endif /* not REGEX_MALLOC */
+
+
+/* True if `size1' is non-NULL and PTR is pointing anywhere inside
+   `string1' or just past its end.  This works if PTR is NULL, which is
+   a good thing.  */
+#define FIRST_STRING_P(ptr) 					\
+  (size1 && string1 <= (ptr) && (ptr) <= string1 + size1)
+
+/* (Re)Allocate N items of type T using malloc, or fail.  */
+#define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t)))
+#define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t)))
+#define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t)))
+
+#define BYTEWIDTH 8 /* In bits.  */
+
+#define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
+
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+typedef char boolean;
+#define false 0
+#define true 1
+
+/* These are the command codes that appear in compiled regular
+   expressions.  Some opcodes are followed by argument bytes.  A
+   command code can specify any interpretation whatsoever for its
+   arguments.  Zero bytes may appear in the compiled regular expression.
+
+   The value of `exactn' is needed in search.c (search_buffer) in Emacs.
+   So regex.h defines a symbol `RE_EXACTN_VALUE' to be 1; the value of
+   `exactn' we use here must also be 1.  */
+
+typedef enum
+{
+  no_op = 0,
+
+	/* Followed by one byte giving n, then by n literal bytes.  */
+  exactn = 1,
+
+	/* Matches any (more or less) character.  */
+  anychar,
+
+	/* Matches any one char belonging to specified set.  First
+	   following byte is number of bitmap bytes.  Then come bytes
+	   for a bitmap saying which chars are in.  Bits in each byte
+	   are ordered low-bit-first.  A character is in the set if its
+	   bit is 1.  A character too large to have a bit in the map is
+	   automatically not in the set.  */
+  charset,
+
+	/* Same parameters as charset, but match any character that is
+	   not one of those specified.  */
+  charset_not,
+
+	/* Start remembering the text that is matched, for storing in a
+	   register.  Followed by one byte with the register number, in
+	   the range 0 to one less than the pattern buffer's re_nsub
+	   field.  Then followed by one byte with the number of groups
+	   inner to this one.  (This last has to be part of the
+	   start_memory only because we need it in the on_failure_jump
+	   of re_match_2.)  */
+  start_memory,
+
+	/* Stop remembering the text that is matched and store it in a
+	   memory register.  Followed by one byte with the register
+	   number, in the range 0 to one less than `re_nsub' in the
+	   pattern buffer, and one byte with the number of inner groups,
+	   just like `start_memory'.  (We need the number of inner
+	   groups here because we don't have any easy way of finding the
+	   corresponding start_memory when we're at a stop_memory.)  */
+  stop_memory,
+
+	/* Match a duplicate of something remembered. Followed by one
+	   byte containing the register number.  */
+  duplicate,
+
+	/* Fail unless at beginning of line.  */
+  begline,
+
+	/* Fail unless at end of line.  */
+  endline,
+
+	/* Succeeds if at beginning of buffer (if emacs) or at beginning
+	   of string to be matched (if not).  */
+  begbuf,
+
+	/* Analogously, for end of buffer/string.  */
+  endbuf,
+
+	/* Followed by two byte relative address to which to jump.  */
+  jump,
+
+	/* Same as jump, but marks the end of an alternative.  */
+  jump_past_alt,
+
+	/* Followed by two-byte relative address of place to resume at
+	   in case of failure.  */
+  on_failure_jump,
+
+	/* Like on_failure_jump, but pushes a placeholder instead of the
+	   current string position when executed.  */
+  on_failure_keep_string_jump,
+
+	/* Throw away latest failure point and then jump to following
+	   two-byte relative address.  */
+  pop_failure_jump,
+
+	/* Change to pop_failure_jump if know won't have to backtrack to
+	   match; otherwise change to jump.  This is used to jump
+	   back to the beginning of a repeat.  If what follows this jump
+	   clearly won't match what the repeat does, such that we can be
+	   sure that there is no use backtracking out of repetitions
+	   already matched, then we change it to a pop_failure_jump.
+	   Followed by two-byte address.  */
+  maybe_pop_jump,
+
+	/* Jump to following two-byte address, and push a dummy failure
+	   point. This failure point will be thrown away if an attempt
+	   is made to use it for a failure.  A `+' construct makes this
+	   before the first repeat.  Also used as an intermediary kind
+	   of jump when compiling an alternative.  */
+  dummy_failure_jump,
+
+	/* Push a dummy failure point and continue.  Used at the end of
+	   alternatives.  */
+  push_dummy_failure,
+
+	/* Followed by two-byte relative address and two-byte number n.
+	   After matching N times, jump to the address upon failure.  */
+  succeed_n,
+
+	/* Followed by two-byte relative address, and two-byte number n.
+	   Jump to the address N times, then fail.  */
+  jump_n,
+
+	/* Set the following two-byte relative address to the
+	   subsequent two-byte number.  The address *includes* the two
+	   bytes of number.  */
+  set_number_at,
+
+  wordchar,	/* Matches any word-constituent character.  */
+  notwordchar,	/* Matches any char that is not a word-constituent.  */
+
+  wordbeg,	/* Succeeds if at word beginning.  */
+  wordend,	/* Succeeds if at word end.  */
+
+  wordbound,	/* Succeeds if at a word boundary.  */
+  notwordbound	/* Succeeds if not at a word boundary.  */
+
+#ifdef emacs
+  ,before_dot,	/* Succeeds if before point.  */
+  at_dot,	/* Succeeds if at point.  */
+  after_dot,	/* Succeeds if after point.  */
+
+	/* Matches any character whose syntax is specified.  Followed by
+	   a byte which contains a syntax code, e.g., Sword.  */
+  syntaxspec,
+
+	/* Matches any character whose syntax is not that specified.  */
+  notsyntaxspec
+#endif /* emacs */
+} re_opcode_t;
+
+/* Common operations on the compiled pattern.  */
+
+/* Store NUMBER in two contiguous bytes starting at DESTINATION.  */
+
+#define STORE_NUMBER(destination, number)				\
+  do {									\
+    (destination)[0] = (number) & 0377;					\
+    (destination)[1] = (number) >> 8;					\
+  } while (0)
+
+/* Same as STORE_NUMBER, except increment DESTINATION to
+   the byte after where the number is stored.  Therefore, DESTINATION
+   must be an lvalue.  */
+
+#define STORE_NUMBER_AND_INCR(destination, number)			\
+  do {									\
+    STORE_NUMBER (destination, number);					\
+    (destination) += 2;							\
+  } while (0)
+
+/* Put into DESTINATION a number stored in two contiguous bytes starting
+   at SOURCE.  */
+
+#define EXTRACT_NUMBER(destination, source)				\
+  do {									\
+    (destination) = *(source) & 0377;					\
+    (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8;		\
+  } while (0)
+
+#ifdef DEBUG
+static void
+extract_number (dest, source)
+    int *dest;
+    unsigned char *source;
+{
+  int temp = SIGN_EXTEND_CHAR (*(source + 1));
+  *dest = *source & 0377;
+  *dest += temp << 8;
+}
+
+#ifndef EXTRACT_MACROS /* To debug the macros.  */
+#undef EXTRACT_NUMBER
+#define EXTRACT_NUMBER(dest, src) extract_number (&dest, src)
+#endif /* not EXTRACT_MACROS */
+
+#endif /* DEBUG */
+
+/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number.
+   SOURCE must be an lvalue.  */
+
+#define EXTRACT_NUMBER_AND_INCR(destination, source)			\
+  do {									\
+    EXTRACT_NUMBER (destination, source);				\
+    (source) += 2; 							\
+  } while (0)
+
+#ifdef DEBUG
+static void
+extract_number_and_incr (destination, source)
+    int *destination;
+    unsigned char **source;
+{
+  extract_number (destination, *source);
+  *source += 2;
+}
+
+#ifndef EXTRACT_MACROS
+#undef EXTRACT_NUMBER_AND_INCR
+#define EXTRACT_NUMBER_AND_INCR(dest, src) \
+  extract_number_and_incr (&dest, &src)
+#endif /* not EXTRACT_MACROS */
+
+#endif /* DEBUG */
+
+/* If DEBUG is defined, Regex prints many voluminous messages about what
+   it is doing (if the variable `debug' is nonzero).  If linked with the
+   main program in `iregex.c', you can enter patterns and strings
+   interactively.  And if linked with the main program in `main.c' and
+   the other test files, you can run the already-written tests.  */
+
+#ifdef DEBUG
+
+/* We use standard I/O for debugging.  */
+#include <stdio.h>
+
+/* It is useful to test things that ``must'' be true when debugging.  */
+#include <assert.h>
+
+static int debug = 0;
+
+#define DEBUG_STATEMENT(e) e
+#define DEBUG_PRINT1(x) if (debug) printf (x)
+#define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2)
+#define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3)
+#define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4)
+#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) 				\
+  if (debug) print_partial_compiled_pattern (s, e)
+#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)			\
+  if (debug) print_double_string (w, s1, sz1, s2, sz2)
+
+
+extern void printchar ();
+
+/* Print the fastmap in human-readable form.  */
+
+void
+print_fastmap (fastmap)
+    char *fastmap;
+{
+  unsigned was_a_range = 0;
+  unsigned i = 0;
+
+  while (i < (1 << BYTEWIDTH))
+    {
+      if (fastmap[i++])
+	{
+	  was_a_range = 0;
+	  printchar (i - 1);
+	  while (i < (1 << BYTEWIDTH)  &&  fastmap[i])
+	    {
+	      was_a_range = 1;
+	      i++;
+	    }
+	  if (was_a_range)
+	    {
+	      printf ("-");
+	      printchar (i - 1);
+	    }
+	}
+    }
+  putchar ('\n');
+}
+
+
+/* Print a compiled pattern string in human-readable form, starting at
+   the START pointer into it and ending just before the pointer END.  */
+
+void
+print_partial_compiled_pattern (start, end)
+    unsigned char *start;
+    unsigned char *end;
+{
+  int mcnt, mcnt2;
+  unsigned char *p = start;
+  unsigned char *pend = end;
+
+  if (start == NULL)
+    {
+      printf ("(null)\n");
+      return;
+    }
+
+  /* Loop over pattern commands.  */
+  while (p < pend)
+    {
+      switch ((re_opcode_t) *p++)
+	{
+	case no_op:
+	  printf ("/no_op");
+	  break;
+
+	case exactn:
+	  mcnt = *p++;
+	  printf ("/exactn/%d", mcnt);
+	  do
+	    {
+	      putchar ('/');
+	      printchar (*p++);
+	    }
+	  while (--mcnt);
+	  break;
+
+	case start_memory:
+	  mcnt = *p++;
+	  printf ("/start_memory/%d/%d", mcnt, *p++);
+	  break;
+
+	case stop_memory:
+	  mcnt = *p++;
+	  printf ("/stop_memory/%d/%d", mcnt, *p++);
+	  break;
+
+	case duplicate:
+	  printf ("/duplicate/%d", *p++);
+	  break;
+
+	case anychar:
+	  printf ("/anychar");
+	  break;
+
+	case charset:
+	case charset_not:
+	  {
+	    register int c;
+
+	    printf ("/charset%s",
+		    (re_opcode_t) *(p - 1) == charset_not ? "_not" : "");
+
+	    assert (p + *p < pend);
+
+	    for (c = 0; c < *p; c++)
+	      {
+		unsigned bit;
+		unsigned char map_byte = p[1 + c];
+
+		putchar ('/');
+
+		for (bit = 0; bit < BYTEWIDTH; bit++)
+		  if (map_byte & (1 << bit))
+		    printchar (c * BYTEWIDTH + bit);
+	      }
+	    p += 1 + *p;
+	    break;
+	  }
+
+	case begline:
+	  printf ("/begline");
+	  break;
+
+	case endline:
+	  printf ("/endline");
+	  break;
+
+	case on_failure_jump:
+	  extract_number_and_incr (&mcnt, &p);
+	  printf ("/on_failure_jump/0/%d", mcnt);
+	  break;
+
+	case on_failure_keep_string_jump:
+	  extract_number_and_incr (&mcnt, &p);
+	  printf ("/on_failure_keep_string_jump/0/%d", mcnt);
+	  break;
+
+	case dummy_failure_jump:
+	  extract_number_and_incr (&mcnt, &p);
+	  printf ("/dummy_failure_jump/0/%d", mcnt);
+	  break;
+
+	case push_dummy_failure:
+	  printf ("/push_dummy_failure");
+	  break;
+
+	case maybe_pop_jump:
+	  extract_number_and_incr (&mcnt, &p);
+	  printf ("/maybe_pop_jump/0/%d", mcnt);
+	  break;
+
+	case pop_failure_jump:
+	  extract_number_and_incr (&mcnt, &p);
+	  printf ("/pop_failure_jump/0/%d", mcnt);
+	  break;
+
+	case jump_past_alt:
+	  extract_number_and_incr (&mcnt, &p);
+	  printf ("/jump_past_alt/0/%d", mcnt);
+	  break;
+
+	case jump:
+	  extract_number_and_incr (&mcnt, &p);
+	  printf ("/jump/0/%d", mcnt);
+	  break;
+
+	case succeed_n:
+	  extract_number_and_incr (&mcnt, &p);
+	  extract_number_and_incr (&mcnt2, &p);
+	  printf ("/succeed_n/0/%d/0/%d", mcnt, mcnt2);
+	  break;
+
+	case jump_n:
+	  extract_number_and_incr (&mcnt, &p);
+	  extract_number_and_incr (&mcnt2, &p);
+	  printf ("/jump_n/0/%d/0/%d", mcnt, mcnt2);
+	  break;
+
+	case set_number_at:
+	  extract_number_and_incr (&mcnt, &p);
+	  extract_number_and_incr (&mcnt2, &p);
+	  printf ("/set_number_at/0/%d/0/%d", mcnt, mcnt2);
+	  break;
+
+	case wordbound:
+	  printf ("/wordbound");
+	  break;
+
+	case notwordbound:
+	  printf ("/notwordbound");
+	  break;
+
+	case wordbeg:
+	  printf ("/wordbeg");
+	  break;
+
+	case wordend:
+	  printf ("/wordend");
+
+#ifdef emacs
+	case before_dot:
+	  printf ("/before_dot");
+	  break;
+
+	case at_dot:
+	  printf ("/at_dot");
+	  break;
+
+	case after_dot:
+	  printf ("/after_dot");
+	  break;
+
+	case syntaxspec:
+	  printf ("/syntaxspec");
+	  mcnt = *p++;
+	  printf ("/%d", mcnt);
+	  break;
+
+	case notsyntaxspec:
+	  printf ("/notsyntaxspec");
+	  mcnt = *p++;
+	  printf ("/%d", mcnt);
+	  break;
+#endif /* emacs */
+
+	case wordchar:
+	  printf ("/wordchar");
+	  break;
+
+	case notwordchar:
+	  printf ("/notwordchar");
+	  break;
+
+	case begbuf:
+	  printf ("/begbuf");
+	  break;
+
+	case endbuf:
+	  printf ("/endbuf");
+	  break;
+
+	default:
+	  printf ("?%d", *(p-1));
+	}
+    }
+  printf ("/\n");
+}
+
+
+void
+print_compiled_pattern (bufp)
+    struct re_pattern_buffer *bufp;
+{
+  unsigned char *buffer = bufp->buffer;
+
+  print_partial_compiled_pattern (buffer, buffer + bufp->used);
+  printf ("%d bytes used/%d bytes allocated.\n", bufp->used, bufp->allocated);
+
+  if (bufp->fastmap_accurate && bufp->fastmap)
+    {
+      printf ("fastmap: ");
+      print_fastmap (bufp->fastmap);
+    }
+
+  printf ("re_nsub: %d\t", bufp->re_nsub);
+  printf ("regs_alloc: %d\t", bufp->regs_allocated);
+  printf ("can_be_null: %d\t", bufp->can_be_null);
+  printf ("newline_anchor: %d\n", bufp->newline_anchor);
+  printf ("no_sub: %d\t", bufp->no_sub);
+  printf ("not_bol: %d\t", bufp->not_bol);
+  printf ("not_eol: %d\t", bufp->not_eol);
+  printf ("syntax: %d\n", bufp->syntax);
+  /* Perhaps we should print the translate table?  */
+}
+
+
+void
+print_double_string (where, string1, size1, string2, size2)
+    const char *where;
+    const char *string1;
+    const char *string2;
+    int size1;
+    int size2;
+{
+  unsigned this_char;
+
+  if (where == NULL)
+    printf ("(null)");
+  else
+    {
+      if (FIRST_STRING_P (where))
+	{
+	  for (this_char = where - string1; this_char < size1; this_char++)
+	    printchar (string1[this_char]);
+
+	  where = string2;
+	}
+
+      for (this_char = where - string2; this_char < size2; this_char++)
+	printchar (string2[this_char]);
+    }
+}
+
+#else /* not DEBUG */
+
+#undef assert
+#define assert(e)
+
+#define DEBUG_STATEMENT(e)
+#define DEBUG_PRINT1(x)
+#define DEBUG_PRINT2(x1, x2)
+#define DEBUG_PRINT3(x1, x2, x3)
+#define DEBUG_PRINT4(x1, x2, x3, x4)
+#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e)
+#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)
+
+#endif /* not DEBUG */
+
+/* Set by `re_set_syntax' to the current regexp syntax to recognize.  Can
+   also be assigned to arbitrarily: each pattern buffer stores its own
+   syntax, so it can be changed between regex compilations.  */
+reg_syntax_t re_syntax_options = RE_SYNTAX_EMACS;
+
+
+/* Specify the precise syntax of regexps for compilation.  This provides
+   for compatibility for various utilities which historically have
+   different, incompatible syntaxes.
+
+   The argument SYNTAX is a bit mask comprised of the various bits
+   defined in regex.h.  We return the old syntax.  */
+
+reg_syntax_t
+re_set_syntax (syntax)
+    reg_syntax_t syntax;
+{
+  reg_syntax_t ret = re_syntax_options;
+
+  re_syntax_options = syntax;
+  return ret;
+}
+
+/* This table gives an error message for each of the error codes listed
+   in regex.h.  Obviously the order here has to be same as there.  */
+
+static const char *re_error_msg[] =
+  { NULL,					/* REG_NOERROR */
+    "No match",					/* REG_NOMATCH */
+    "Invalid regular expression",		/* REG_BADPAT */
+    "Invalid collation character",		/* REG_ECOLLATE */
+    "Invalid character class name",		/* REG_ECTYPE */
+    "Trailing backslash",			/* REG_EESCAPE */
+    "Invalid back reference",			/* REG_ESUBREG */
+    "Unmatched [ or [^",			/* REG_EBRACK */
+    "Unmatched ( or \\(",			/* REG_EPAREN */
+    "Unmatched \\{",				/* REG_EBRACE */
+    "Invalid content of \\{\\}",		/* REG_BADBR */
+    "Invalid range end",			/* REG_ERANGE */
+    "Memory exhausted",				/* REG_ESPACE */
+    "Invalid preceding regular expression",	/* REG_BADRPT */
+    "Premature end of regular expression",	/* REG_EEND */
+    "Regular expression too big",		/* REG_ESIZE */
+    "Unmatched ) or \\)",			/* REG_ERPAREN */
+  };
+
+/* Subroutine declarations and macros for regex_compile.  */
+
+static void store_op1 (), store_op2 ();
+static void insert_op1 (), insert_op2 ();
+static boolean at_begline_loc_p (), at_endline_loc_p ();
+static boolean group_in_compile_stack ();
+static reg_errcode_t compile_range ();
+
+/* Fetch the next character in the uncompiled pattern---translating it
+   if necessary.  Also cast from a signed character in the constant
+   string passed to us by the user to an unsigned char that we can use
+   as an array index (in, e.g., `translate').  */
+#define PATFETCH(c)							\
+  do {if (p == pend) return REG_EEND;					\
+    c = (unsigned char) *p++;						\
+    if (translate) c = translate[c]; 					\
+  } while (0)
+
+/* Fetch the next character in the uncompiled pattern, with no
+   translation.  */
+#define PATFETCH_RAW(c)							\
+  do {if (p == pend) return REG_EEND;					\
+    c = (unsigned char) *p++; 						\
+  } while (0)
+
+/* Go backwards one character in the pattern.  */
+#define PATUNFETCH p--
+
+
+/* If `translate' is non-null, return translate[D], else just D.  We
+   cast the subscript to translate because some data is declared as
+   `char *', to avoid warnings when a string constant is passed.  But
+   when we use a character as a subscript we must make it unsigned.  */
+#define TRANSLATE(d) (translate ? translate[(unsigned char) (d)] : (d))
+
+
+/* Macros for outputting the compiled pattern into `buffer'.  */
+
+/* If the buffer isn't allocated when it comes in, use this.  */
+#define INIT_BUF_SIZE  32
+
+/* Make sure we have at least N more bytes of space in buffer.  */
+#define GET_BUFFER_SPACE(n)						\
+    while (b - bufp->buffer + (n) > bufp->allocated)			\
+      EXTEND_BUFFER ()
+
+/* Make sure we have one more byte of buffer space and then add C to it.  */
+#define BUF_PUSH(c)							\
+  do {									\
+    GET_BUFFER_SPACE (1);						\
+    *b++ = (unsigned char) (c);						\
+  } while (0)
+
+
+/* Ensure we have two more bytes of buffer space and then append C1 and C2.  */
+#define BUF_PUSH_2(c1, c2)						\
+  do {									\
+    GET_BUFFER_SPACE (2);						\
+    *b++ = (unsigned char) (c1);					\
+    *b++ = (unsigned char) (c2);					\
+  } while (0)
+
+
+/* As with BUF_PUSH_2, except for three bytes.  */
+#define BUF_PUSH_3(c1, c2, c3)						\
+  do {									\
+    GET_BUFFER_SPACE (3);						\
+    *b++ = (unsigned char) (c1);					\
+    *b++ = (unsigned char) (c2);					\
+    *b++ = (unsigned char) (c3);					\
+  } while (0)
+
+
+/* Store a jump with opcode OP at LOC to location TO.  We store a
+   relative address offset by the three bytes the jump itself occupies.  */
+#define STORE_JUMP(op, loc, to) \
+  store_op1 (op, loc, (to) - (loc) - 3)
+
+/* Likewise, for a two-argument jump.  */
+#define STORE_JUMP2(op, loc, to, arg) \
+  store_op2 (op, loc, (to) - (loc) - 3, arg)
+
+/* Like `STORE_JUMP', but for inserting.  Assume `b' is the buffer end.  */
+#define INSERT_JUMP(op, loc, to) \
+  insert_op1 (op, loc, (to) - (loc) - 3, b)
+
+/* Like `STORE_JUMP2', but for inserting.  Assume `b' is the buffer end.  */
+#define INSERT_JUMP2(op, loc, to, arg) \
+  insert_op2 (op, loc, (to) - (loc) - 3, arg, b)
+
+
+/* This is not an arbitrary limit: the arguments which represent offsets
+   into the pattern are two bytes long.  So if 2^16 bytes turns out to
+   be too small, many things would have to change.  */
+#define MAX_BUF_SIZE (1L << 16)
+
+
+/* Extend the buffer by twice its current size via realloc and
+   reset the pointers that pointed into the old block to point to the
+   correct places in the new one.  If extending the buffer results in it
+   being larger than MAX_BUF_SIZE, then flag memory exhausted.  */
+#define EXTEND_BUFFER()							\
+  do { 									\
+    unsigned char *old_buffer = bufp->buffer;				\
+    if (bufp->allocated == MAX_BUF_SIZE) 				\
+      return REG_ESIZE;							\
+    bufp->allocated <<= 1;						\
+    if (bufp->allocated > MAX_BUF_SIZE)					\
+      bufp->allocated = MAX_BUF_SIZE; 					\
+    bufp->buffer = (unsigned char *) realloc (bufp->buffer, bufp->allocated);\
+    if (bufp->buffer == NULL)						\
+      return REG_ESPACE;						\
+    /* If the buffer moved, move all the pointers into it.  */		\
+    if (old_buffer != bufp->buffer)					\
+      {									\
+	b = (b - old_buffer) + bufp->buffer;				\
+	begalt = (begalt - old_buffer) + bufp->buffer;			\
+	if (fixup_alt_jump)						\
+	  fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\
+	if (laststart)							\
+	  laststart = (laststart - old_buffer) + bufp->buffer;		\
+	if (pending_exact)						\
+	  pending_exact = (pending_exact - old_buffer) + bufp->buffer;	\
+      }									\
+  } while (0)
+
+
+/* Since we have one byte reserved for the register number argument to
+   {start,stop}_memory, the maximum number of groups we can report
+   things about is what fits in that byte.  */
+#define MAX_REGNUM 255
+
+/* But patterns can have more than `MAX_REGNUM' registers.  We just
+   ignore the excess.  */
+typedef unsigned regnum_t;
+
+
+/* Macros for the compile stack.  */
+
+/* Since offsets can go either forwards or backwards, this type needs to
+   be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1.  */
+typedef int pattern_offset_t;
+
+typedef struct
+{
+  pattern_offset_t begalt_offset;
+  pattern_offset_t fixup_alt_jump;
+  pattern_offset_t inner_group_offset;
+  pattern_offset_t laststart_offset;
+  regnum_t regnum;
+} compile_stack_elt_t;
+
+
+typedef struct
+{
+  compile_stack_elt_t *stack;
+  unsigned size;
+  unsigned avail;			/* Offset of next open position.  */
+} compile_stack_type;
+
+
+#define INIT_COMPILE_STACK_SIZE 32
+
+#define COMPILE_STACK_EMPTY  (compile_stack.avail == 0)
+#define COMPILE_STACK_FULL  (compile_stack.avail == compile_stack.size)
+
+/* The next available element.  */
+#define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail])
+
+
+/* Set the bit for character C in a list.  */
+#define SET_LIST_BIT(c)                               \
+  (b[((unsigned char) (c)) / BYTEWIDTH]               \
+   |= 1 << (((unsigned char) c) % BYTEWIDTH))
+
+
+/* Get the next unsigned number in the uncompiled pattern.  */
+#define GET_UNSIGNED_NUMBER(num) 					\
+  { if (p != pend)							\
+     {									\
+       PATFETCH (c); 							\
+       while (ISDIGIT (c)) 						\
+	 { 								\
+	   if (num < 0)							\
+	      num = 0;							\
+	   num = num * 10 + c - '0'; 					\
+	   if (p == pend) 						\
+	      break; 							\
+	   PATFETCH (c);						\
+	 } 								\
+       } 								\
+    }
+
+#define CHAR_CLASS_MAX_LENGTH  6 /* Namely, `xdigit'.  */
+
+#define IS_CHAR_CLASS(string)						\
+   (STREQ (string, "alpha") || STREQ (string, "upper")			\
+    || STREQ (string, "lower") || STREQ (string, "digit")		\
+    || STREQ (string, "alnum") || STREQ (string, "xdigit")		\
+    || STREQ (string, "space") || STREQ (string, "print")		\
+    || STREQ (string, "punct") || STREQ (string, "graph")		\
+    || STREQ (string, "cntrl") || STREQ (string, "blank"))
+
+/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX.
+   Returns one of error codes defined in `regex.h', or zero for success.
+
+   Assumes the `allocated' (and perhaps `buffer') and `translate'
+   fields are set in BUFP on entry.
+
+   If it succeeds, results are put in BUFP (if it returns an error, the
+   contents of BUFP are undefined):
+     `buffer' is the compiled pattern;
+     `syntax' is set to SYNTAX;
+     `used' is set to the length of the compiled pattern;
+     `fastmap_accurate' is zero;
+     `re_nsub' is the number of subexpressions in PATTERN;
+     `not_bol' and `not_eol' are zero;
+
+   The `fastmap' and `newline_anchor' fields are neither
+   examined nor set.  */
+
+static reg_errcode_t
+regex_compile (pattern, size, syntax, bufp)
+     const char *pattern;
+     int size;
+     reg_syntax_t syntax;
+     struct re_pattern_buffer *bufp;
+{
+  /* We fetch characters from PATTERN here.  Even though PATTERN is
+     `char *' (i.e., signed), we declare these variables as unsigned, so
+     they can be reliably used as array indices.  */
+  register unsigned char c, c1;
+
+  /* A random tempory spot in PATTERN.  */
+  const char *p1;
+
+  /* Points to the end of the buffer, where we should append.  */
+  register unsigned char *b;
+
+  /* Keeps track of unclosed groups.  */
+  compile_stack_type compile_stack;
+
+  /* Points to the current (ending) position in the pattern.  */
+  const char *p = pattern;
+  const char *pend = pattern + size;
+
+  /* How to translate the characters in the pattern.  */
+  char *translate = bufp->translate;
+
+  /* Address of the count-byte of the most recently inserted `exactn'
+     command.  This makes it possible to tell if a new exact-match
+     character can be added to that command or if the character requires
+     a new `exactn' command.  */
+  unsigned char *pending_exact = 0;
+
+  /* Address of start of the most recently finished expression.
+     This tells, e.g., postfix * where to find the start of its
+     operand.  Reset at the beginning of groups and alternatives.  */
+  unsigned char *laststart = 0;
+
+  /* Address of beginning of regexp, or inside of last group.  */
+  unsigned char *begalt;
+
+  /* Place in the uncompiled pattern (i.e., the {) to
+     which to go back if the interval is invalid.  */
+  const char *beg_interval;
+
+  /* Address of the place where a forward jump should go to the end of
+     the containing expression.  Each alternative of an `or' -- except the
+     last -- ends with a forward jump of this sort.  */
+  unsigned char *fixup_alt_jump = 0;
+
+  /* Counts open-groups as they are encountered.  Remembered for the
+     matching close-group on the compile stack, so the same register
+     number is put in the stop_memory as the start_memory.  */
+  regnum_t regnum = 0;
+
+#ifdef DEBUG
+  DEBUG_PRINT1 ("\nCompiling pattern: ");
+  if (debug)
+    {
+      unsigned debug_count;
+
+      for (debug_count = 0; debug_count < size; debug_count++)
+	printchar (pattern[debug_count]);
+      putchar ('\n');
+    }
+#endif /* DEBUG */
+
+  /* Initialize the compile stack.  */
+  compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t);
+  if (compile_stack.stack == NULL)
+    return REG_ESPACE;
+
+  compile_stack.size = INIT_COMPILE_STACK_SIZE;
+  compile_stack.avail = 0;
+
+  /* Initialize the pattern buffer.  */
+  bufp->syntax = syntax;
+  bufp->fastmap_accurate = 0;
+  bufp->not_bol = bufp->not_eol = 0;
+
+  /* Set `used' to zero, so that if we return an error, the pattern
+     printer (for debugging) will think there's no pattern.  We reset it
+     at the end.  */
+  bufp->used = 0;
+
+  /* Always count groups, whether or not bufp->no_sub is set.  */
+  bufp->re_nsub = 0;
+
+#if !defined (emacs) && !defined (SYNTAX_TABLE)
+  /* Initialize the syntax table.  */
+   init_syntax_once ();
+#endif
+
+  if (bufp->allocated == 0)
+    {
+      if (bufp->buffer)
+	{ /* If zero allocated, but buffer is non-null, try to realloc
+	     enough space.  This loses if buffer's address is bogus, but
+	     that is the user's responsibility.  */
+	  RETALLOC (bufp->buffer, INIT_BUF_SIZE, unsigned char);
+	}
+      else
+	{ /* Caller did not allocate a buffer.  Do it for them.  */
+	  bufp->buffer = TALLOC (INIT_BUF_SIZE, unsigned char);
+	}
+      if (!bufp->buffer) return REG_ESPACE;
+
+      bufp->allocated = INIT_BUF_SIZE;
+    }
+
+  begalt = b = bufp->buffer;
+
+  /* Loop through the uncompiled pattern until we're at the end.  */
+  while (p != pend)
+    {
+      PATFETCH (c);
+
+      switch (c)
+	{
+	case '^':
+	  {
+	    if (   /* If at start of pattern, it's an operator.  */
+		   p == pattern + 1
+		   /* If context independent, it's an operator.  */
+		|| syntax & RE_CONTEXT_INDEP_ANCHORS
+		   /* Otherwise, depends on what's come before.  */
+		|| at_begline_loc_p (pattern, p, syntax))
+	      BUF_PUSH (begline);
+	    else
+	      goto normal_char;
+	  }
+	  break;
+
+
+	case '$':
+	  {
+	    if (   /* If at end of pattern, it's an operator.  */
+		   p == pend
+		   /* If context independent, it's an operator.  */
+		|| syntax & RE_CONTEXT_INDEP_ANCHORS
+		   /* Otherwise, depends on what's next.  */
+		|| at_endline_loc_p (p, pend, syntax))
+	       BUF_PUSH (endline);
+	     else
+	       goto normal_char;
+	   }
+	   break;
+
+
+	case '+':
+	case '?':
+	  if ((syntax & RE_BK_PLUS_QM)
+	      || (syntax & RE_LIMITED_OPS))
+	    goto normal_char;
+	handle_plus:
+	case '*':
+	  /* If there is no previous pattern... */
+	  if (!laststart)
+	    {
+	      if (syntax & RE_CONTEXT_INVALID_OPS)
+		return REG_BADRPT;
+	      else if (!(syntax & RE_CONTEXT_INDEP_OPS))
+		goto normal_char;
+	    }
+
+	  {
+	    /* Are we optimizing this jump?  */
+	    boolean keep_string_p = false;
+
+	    /* 1 means zero (many) matches is allowed.  */
+	    char zero_times_ok = 0, many_times_ok = 0;
+
+	    /* If there is a sequence of repetition chars, collapse it
+	       down to just one (the right one).  We can't combine
+	       interval operators with these because of, e.g., `a{2}*',
+	       which should only match an even number of `a's.  */
+
+	    for (;;)
+	      {
+		zero_times_ok |= c != '+';
+		many_times_ok |= c != '?';
+
+		if (p == pend)
+		  break;
+
+		PATFETCH (c);
+
+		if (c == '*'
+		    || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?')))
+		  ;
+
+		else if (syntax & RE_BK_PLUS_QM  &&  c == '\\')
+		  {
+		    if (p == pend) return REG_EESCAPE;
+
+		    PATFETCH (c1);
+		    if (!(c1 == '+' || c1 == '?'))
+		      {
+			PATUNFETCH;
+			PATUNFETCH;
+			break;
+		      }
+
+		    c = c1;
+		  }
+		else
+		  {
+		    PATUNFETCH;
+		    break;
+		  }
+
+		/* If we get here, we found another repeat character.  */
+	       }
+
+	    /* Star, etc. applied to an empty pattern is equivalent
+	       to an empty pattern.  */
+	    if (!laststart)
+	      break;
+
+	    /* Now we know whether or not zero matches is allowed
+	       and also whether or not two or more matches is allowed.  */
+	    if (many_times_ok)
+	      { /* More than one repetition is allowed, so put in at the
+		   end a backward relative jump from `b' to before the next
+		   jump we're going to put in below (which jumps from
+		   laststart to after this jump).
+
+		   But if we are at the `*' in the exact sequence `.*\n',
+		   insert an unconditional jump backwards to the .,
+		   instead of the beginning of the loop.  This way we only
+		   push a failure point once, instead of every time
+		   through the loop.  */
+		assert (p - 1 > pattern);
+
+		/* Allocate the space for the jump.  */
+		GET_BUFFER_SPACE (3);
+
+		/* We know we are not at the first character of the pattern,
+		   because laststart was nonzero.  And we've already
+		   incremented `p', by the way, to be the character after
+		   the `*'.  Do we have to do something analogous here
+		   for null bytes, because of RE_DOT_NOT_NULL?  */
+		if (TRANSLATE (*(p - 2)) == TRANSLATE ('.')
+		    && zero_times_ok
+		    && p < pend && TRANSLATE (*p) == TRANSLATE ('\n')
+		    && !(syntax & RE_DOT_NEWLINE))
+		  { /* We have .*\n.  */
+		    STORE_JUMP (jump, b, laststart);
+		    keep_string_p = true;
+		  }
+		else
+		  /* Anything else.  */
+		  STORE_JUMP (maybe_pop_jump, b, laststart - 3);
+
+		/* We've added more stuff to the buffer.  */
+		b += 3;
+	      }
+
+	    /* On failure, jump from laststart to b + 3, which will be the
+	       end of the buffer after this jump is inserted.  */
+	    GET_BUFFER_SPACE (3);
+	    INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump
+				       : on_failure_jump,
+			 laststart, b + 3);
+	    pending_exact = 0;
+	    b += 3;
+
+	    if (!zero_times_ok)
+	      {
+		/* At least one repetition is required, so insert a
+		   `dummy_failure_jump' before the initial
+		   `on_failure_jump' instruction of the loop. This
+		   effects a skip over that instruction the first time
+		   we hit that loop.  */
+		GET_BUFFER_SPACE (3);
+		INSERT_JUMP (dummy_failure_jump, laststart, laststart + 6);
+		b += 3;
+	      }
+	    }
+	  break;
+
+
+	case '.':
+	  laststart = b;
+	  BUF_PUSH (anychar);
+	  break;
+
+
+	case '[':
+	  {
+	    boolean had_char_class = false;
+
+	    if (p == pend) return REG_EBRACK;
+
+	    /* Ensure that we have enough space to push a charset: the
+	       opcode, the length count, and the bitset; 34 bytes in all.  */
+	    GET_BUFFER_SPACE (34);
+
+	    laststart = b;
+
+	    /* We test `*p == '^' twice, instead of using an if
+	       statement, so we only need one BUF_PUSH.  */
+	    BUF_PUSH (*p == '^' ? charset_not : charset);
+	    if (*p == '^')
+	      p++;
+
+	    /* Remember the first position in the bracket expression.  */
+	    p1 = p;
+
+	    /* Push the number of bytes in the bitmap.  */
+	    BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH);
+
+	    /* Clear the whole map.  */
+	    bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH);
+
+	    /* charset_not matches newline according to a syntax bit.  */
+	    if ((re_opcode_t) b[-2] == charset_not
+		&& (syntax & RE_HAT_LISTS_NOT_NEWLINE))
+	      SET_LIST_BIT ('\n');
+
+	    /* Read in characters and ranges, setting map bits.  */
+	    for (;;)
+	      {
+		if (p == pend) return REG_EBRACK;
+
+		PATFETCH (c);
+
+		/* \ might escape characters inside [...] and [^...].  */
+		if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\')
+		  {
+		    if (p == pend) return REG_EESCAPE;
+
+		    PATFETCH (c1);
+		    SET_LIST_BIT (c1);
+		    continue;
+		  }
+
+		/* Could be the end of the bracket expression.  If it's
+		   not (i.e., when the bracket expression is `[]' so
+		   far), the ']' character bit gets set way below.  */
+		if (c == ']' && p != p1 + 1)
+		  break;
+
+		/* Look ahead to see if it's a range when the last thing
+		   was a character class.  */
+		if (had_char_class && c == '-' && *p != ']')
+		  return REG_ERANGE;
+
+		/* Look ahead to see if it's a range when the last thing
+		   was a character: if this is a hyphen not at the
+		   beginning or the end of a list, then it's the range
+		   operator.  */
+		if (c == '-'
+		    && !(p - 2 >= pattern && p[-2] == '[')
+		    && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^')
+		    && *p != ']')
+		  {
+		    reg_errcode_t ret
+		      = compile_range (&p, pend, translate, syntax, b);
+		    if (ret != REG_NOERROR) return ret;
+		  }
+
+		else if (p[0] == '-' && p[1] != ']')
+		  { /* This handles ranges made up of characters only.  */
+		    reg_errcode_t ret;
+
+		    /* Move past the `-'.  */
+		    PATFETCH (c1);
+
+		    ret = compile_range (&p, pend, translate, syntax, b);
+		    if (ret != REG_NOERROR) return ret;
+		  }
+
+		/* See if we're at the beginning of a possible character
+		   class.  */
+
+		else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':')
+		  { /* Leave room for the null.  */
+		    char str[CHAR_CLASS_MAX_LENGTH + 1];
+
+		    PATFETCH (c);
+		    c1 = 0;
+
+		    /* If pattern is `[[:'.  */
+		    if (p == pend) return REG_EBRACK;
+
+		    for (;;)
+		      {
+			PATFETCH (c);
+			if (c == ':' || c == ']' || p == pend
+			    || c1 == CHAR_CLASS_MAX_LENGTH)
+			  break;
+			str[c1++] = c;
+		      }
+		    str[c1] = '\0';
+
+		    /* If isn't a word bracketed by `[:' and:`]':
+		       undo the ending character, the letters, and leave
+		       the leading `:' and `[' (but set bits for them).  */
+		    if (c == ':' && *p == ']')
+		      {
+			int ch;
+			boolean is_alnum = STREQ (str, "alnum");
+			boolean is_alpha = STREQ (str, "alpha");
+			boolean is_blank = STREQ (str, "blank");
+			boolean is_cntrl = STREQ (str, "cntrl");
+			boolean is_digit = STREQ (str, "digit");
+			boolean is_graph = STREQ (str, "graph");
+			boolean is_lower = STREQ (str, "lower");
+			boolean is_print = STREQ (str, "print");
+			boolean is_punct = STREQ (str, "punct");
+			boolean is_space = STREQ (str, "space");
+			boolean is_upper = STREQ (str, "upper");
+			boolean is_xdigit = STREQ (str, "xdigit");
+
+			if (!IS_CHAR_CLASS (str)) return REG_ECTYPE;
+
+			/* Throw away the ] at the end of the character
+			   class.  */
+			PATFETCH (c);
+
+			if (p == pend) return REG_EBRACK;
+
+			for (ch = 0; ch < 1 << BYTEWIDTH; ch++)
+			  {
+			    if (   (is_alnum  && ISALNUM (ch))
+				|| (is_alpha  && ISALPHA (ch))
+				|| (is_blank  && ISBLANK (ch))
+				|| (is_cntrl  && ISCNTRL (ch))
+				|| (is_digit  && ISDIGIT (ch))
+				|| (is_graph  && ISGRAPH (ch))
+				|| (is_lower  && ISLOWER (ch))
+				|| (is_print  && ISPRINT (ch))
+				|| (is_punct  && ISPUNCT (ch))
+				|| (is_space  && ISSPACE (ch))
+				|| (is_upper  && ISUPPER (ch))
+				|| (is_xdigit && ISXDIGIT (ch)))
+			    SET_LIST_BIT (ch);
+			  }
+			had_char_class = true;
+		      }
+		    else
+		      {
+			c1++;
+			while (c1--)
+			  PATUNFETCH;
+			SET_LIST_BIT ('[');
+			SET_LIST_BIT (':');
+			had_char_class = false;
+		      }
+		  }
+		else
+		  {
+		    had_char_class = false;
+		    SET_LIST_BIT (c);
+		  }
+	      }
+
+	    /* Discard any (non)matching list bytes that are all 0 at the
+	       end of the map.  Decrease the map-length byte too.  */
+	    while ((int) b[-1] > 0 && b[b[-1] - 1] == 0)
+	      b[-1]--;
+	    b += b[-1];
+	  }
+	  break;
+
+
+	case '(':
+	  if (syntax & RE_NO_BK_PARENS)
+	    goto handle_open;
+	  else
+	    goto normal_char;
+
+
+	case ')':
+	  if (syntax & RE_NO_BK_PARENS)
+	    goto handle_close;
+	  else
+	    goto normal_char;
+
+
+	case '\n':
+	  if (syntax & RE_NEWLINE_ALT)
+	    goto handle_alt;
+	  else
+	    goto normal_char;
+
+
+	case '|':
+	  if (syntax & RE_NO_BK_VBAR)
+	    goto handle_alt;
+	  else
+	    goto normal_char;
+
+
+	case '{':
+	   if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES)
+	     goto handle_interval;
+	   else
+	     goto normal_char;
+
+
+	case '\\':
+	  if (p == pend) return REG_EESCAPE;
+
+	  /* Do not translate the character after the \, so that we can
+	     distinguish, e.g., \B from \b, even if we normally would
+	     translate, e.g., B to b.  */
+	  PATFETCH_RAW (c);
+
+	  switch (c)
+	    {
+	    case '(':
+	      if (syntax & RE_NO_BK_PARENS)
+		goto normal_backslash;
+
+	    handle_open:
+	      bufp->re_nsub++;
+	      regnum++;
+
+	      if (COMPILE_STACK_FULL)
+		{
+		  RETALLOC (compile_stack.stack, compile_stack.size << 1,
+			    compile_stack_elt_t);
+		  if (compile_stack.stack == NULL) return REG_ESPACE;
+
+		  compile_stack.size <<= 1;
+		}
+
+	      /* These are the values to restore when we hit end of this
+		 group.  They are all relative offsets, so that if the
+		 whole pattern moves because of realloc, they will still
+		 be valid.  */
+	      COMPILE_STACK_TOP.begalt_offset = begalt - bufp->buffer;
+	      COMPILE_STACK_TOP.fixup_alt_jump
+		= fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0;
+	      COMPILE_STACK_TOP.laststart_offset = b - bufp->buffer;
+	      COMPILE_STACK_TOP.regnum = regnum;
+
+	      /* We will eventually replace the 0 with the number of
+		 groups inner to this one.  But do not push a
+		 start_memory for groups beyond the last one we can
+		 represent in the compiled pattern.  */
+	      if (regnum <= MAX_REGNUM)
+		{
+		  COMPILE_STACK_TOP.inner_group_offset = b - bufp->buffer + 2;
+		  BUF_PUSH_3 (start_memory, regnum, 0);
+		}
+
+	      compile_stack.avail++;
+
+	      fixup_alt_jump = 0;
+	      laststart = 0;
+	      begalt = b;
+	      /* If we've reached MAX_REGNUM groups, then this open
+		 won't actually generate any code, so we'll have to
+		 clear pending_exact explicitly.  */
+	      pending_exact = 0;
+	      break;
+
+
+	    case ')':
+	      if (syntax & RE_NO_BK_PARENS) goto normal_backslash;
+
+	      if (COMPILE_STACK_EMPTY)
+	      {
+		if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
+		  goto normal_backslash;
+		else
+		  return REG_ERPAREN;
+	      }
+
+	    handle_close:
+	      if (fixup_alt_jump)
+		{ /* Push a dummy failure point at the end of the
+		     alternative for a possible future
+		     `pop_failure_jump' to pop.  See comments at
+		     `push_dummy_failure' in `re_match_2'.  */
+		  BUF_PUSH (push_dummy_failure);
+
+		  /* We allocated space for this jump when we assigned
+		     to `fixup_alt_jump', in the `handle_alt' case below.  */
+		  STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1);
+		}
+
+	      /* See similar code for backslashed left paren above.  */
+	      if (COMPILE_STACK_EMPTY)
+	      {
+		if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
+		  goto normal_char;
+		else
+		  return REG_ERPAREN;
+	      }
+
+	      /* Since we just checked for an empty stack above, this
+		 ``can't happen''.  */
+	      assert (compile_stack.avail != 0);
+	      {
+		/* We don't just want to restore into `regnum', because
+		   later groups should continue to be numbered higher,
+		   as in `(ab)c(de)' -- the second group is #2.  */
+		regnum_t this_group_regnum;
+
+		compile_stack.avail--;
+		begalt = bufp->buffer + COMPILE_STACK_TOP.begalt_offset;
+		fixup_alt_jump
+		  = COMPILE_STACK_TOP.fixup_alt_jump
+		    ? bufp->buffer + COMPILE_STACK_TOP.fixup_alt_jump - 1
+		    : 0;
+		laststart = bufp->buffer + COMPILE_STACK_TOP.laststart_offset;
+		this_group_regnum = COMPILE_STACK_TOP.regnum;
+		/* If we've reached MAX_REGNUM groups, then this open
+		   won't actually generate any code, so we'll have to
+		   clear pending_exact explicitly.  */
+		pending_exact = 0;
+
+		/* We're at the end of the group, so now we know how many
+		   groups were inside this one.  */
+		if (this_group_regnum <= MAX_REGNUM)
+		  {
+		    unsigned char *inner_group_loc
+		      = bufp->buffer + COMPILE_STACK_TOP.inner_group_offset;
+
+		    *inner_group_loc = regnum - this_group_regnum;
+		    BUF_PUSH_3 (stop_memory, this_group_regnum,
+				regnum - this_group_regnum);
+		  }
+	      }
+	      break;
+
+
+	    case '|':					/* `\|'.  */
+	      if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR)
+		goto normal_backslash;
+	    handle_alt:
+	      if (syntax & RE_LIMITED_OPS)
+		goto normal_char;
+
+	      /* Insert before the previous alternative a jump which
+		 jumps to this alternative if the former fails.  */
+	      GET_BUFFER_SPACE (3);
+	      INSERT_JUMP (on_failure_jump, begalt, b + 6);
+	      pending_exact = 0;
+	      b += 3;
+
+	      /* The alternative before this one has a jump after it
+		 which gets executed if it gets matched.  Adjust that
+		 jump so it will jump to this alternative's analogous
+		 jump (put in below, which in turn will jump to the next
+		 (if any) alternative's such jump, etc.).  The last such
+		 jump jumps to the correct final destination.  A picture:
+			  _____ _____
+			  |   | |   |
+			  |   v |   v
+			 a | b   | c
+
+		 If we are at `b', then fixup_alt_jump right now points to a
+		 three-byte space after `a'.  We'll put in the jump, set
+		 fixup_alt_jump to right after `b', and leave behind three
+		 bytes which we'll fill in when we get to after `c'.  */
+
+	      if (fixup_alt_jump)
+		STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
+
+	      /* Mark and leave space for a jump after this alternative,
+		 to be filled in later either by next alternative or
+		 when know we're at the end of a series of alternatives.  */
+	      fixup_alt_jump = b;
+	      GET_BUFFER_SPACE (3);
+	      b += 3;
+
+	      laststart = 0;
+	      begalt = b;
+	      break;
+
+
+	    case '{':
+	      /* If \{ is a literal.  */
+	      if (!(syntax & RE_INTERVALS)
+		     /* If we're at `\{' and it's not the open-interval
+			operator.  */
+		  || ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
+		  || (p - 2 == pattern  &&  p == pend))
+		goto normal_backslash;
+
+	    handle_interval:
+	      {
+		/* If got here, then the syntax allows intervals.  */
+
+		/* At least (most) this many matches must be made.  */
+		int lower_bound = -1, upper_bound = -1;
+
+		beg_interval = p - 1;
+
+		if (p == pend)
+		  {
+		    if (syntax & RE_NO_BK_BRACES)
+		      goto unfetch_interval;
+		    else
+		      return REG_EBRACE;
+		  }
+
+		GET_UNSIGNED_NUMBER (lower_bound);
+
+		if (c == ',')
+		  {
+		    GET_UNSIGNED_NUMBER (upper_bound);
+		    if (upper_bound < 0) upper_bound = RE_DUP_MAX;
+		  }
+		else
+		  /* Interval such as `{1}' => match exactly once. */
+		  upper_bound = lower_bound;
+
+		if (lower_bound < 0 || upper_bound > RE_DUP_MAX
+		    || lower_bound > upper_bound)
+		  {
+		    if (syntax & RE_NO_BK_BRACES)
+		      goto unfetch_interval;
+		    else
+		      return REG_BADBR;
+		  }
+
+		if (!(syntax & RE_NO_BK_BRACES))
+		  {
+		    if (c != '\\') return REG_EBRACE;
+
+		    PATFETCH (c);
+		  }
+
+		if (c != '}')
+		  {
+		    if (syntax & RE_NO_BK_BRACES)
+		      goto unfetch_interval;
+		    else
+		      return REG_BADBR;
+		  }
+
+		/* We just parsed a valid interval.  */
+
+		/* If it's invalid to have no preceding re.  */
+		if (!laststart)
+		  {
+		    if (syntax & RE_CONTEXT_INVALID_OPS)
+		      return REG_BADRPT;
+		    else if (syntax & RE_CONTEXT_INDEP_OPS)
+		      laststart = b;
+		    else
+		      goto unfetch_interval;
+		  }
+
+		/* If the upper bound is zero, don't want to succeed at
+		   all; jump from `laststart' to `b + 3', which will be
+		   the end of the buffer after we insert the jump.  */
+		 if (upper_bound == 0)
+		   {
+		     GET_BUFFER_SPACE (3);
+		     INSERT_JUMP (jump, laststart, b + 3);
+		     b += 3;
+		   }
+
+		 /* Otherwise, we have a nontrivial interval.  When
+		    we're all done, the pattern will look like:
+		      set_number_at <jump count> <upper bound>
+		      set_number_at <succeed_n count> <lower bound>
+		      succeed_n <after jump addr> <succed_n count>
+		      <body of loop>
+		      jump_n <succeed_n addr> <jump count>
+		    (The upper bound and `jump_n' are omitted if
+		    `upper_bound' is 1, though.)  */
+		 else
+		   { /* If the upper bound is > 1, we need to insert
+			more at the end of the loop.  */
+		     unsigned nbytes = 10 + (upper_bound > 1) * 10;
+
+		     GET_BUFFER_SPACE (nbytes);
+
+		     /* Initialize lower bound of the `succeed_n', even
+			though it will be set during matching by its
+			attendant `set_number_at' (inserted next),
+			because `re_compile_fastmap' needs to know.
+			Jump to the `jump_n' we might insert below.  */
+		     INSERT_JUMP2 (succeed_n, laststart,
+				   b + 5 + (upper_bound > 1) * 5,
+				   lower_bound);
+		     b += 5;
+
+		     /* Code to initialize the lower bound.  Insert
+			before the `succeed_n'.  The `5' is the last two
+			bytes of this `set_number_at', plus 3 bytes of
+			the following `succeed_n'.  */
+		     insert_op2 (set_number_at, laststart, 5, lower_bound, b);
+		     b += 5;
+
+		     if (upper_bound > 1)
+		       { /* More than one repetition is allowed, so
+			    append a backward jump to the `succeed_n'
+			    that starts this interval.
+
+			    When we've reached this during matching,
+			    we'll have matched the interval once, so
+			    jump back only `upper_bound - 1' times.  */
+			 STORE_JUMP2 (jump_n, b, laststart + 5,
+				      upper_bound - 1);
+			 b += 5;
+
+			 /* The location we want to set is the second
+			    parameter of the `jump_n'; that is `b-2' as
+			    an absolute address.  `laststart' will be
+			    the `set_number_at' we're about to insert;
+			    `laststart+3' the number to set, the source
+			    for the relative address.  But we are
+			    inserting into the middle of the pattern --
+			    so everything is getting moved up by 5.
+			    Conclusion: (b - 2) - (laststart + 3) + 5,
+			    i.e., b - laststart.
+
+			    We insert this at the beginning of the loop
+			    so that if we fail during matching, we'll
+			    reinitialize the bounds.  */
+			 insert_op2 (set_number_at, laststart, b - laststart,
+				     upper_bound - 1, b);
+			 b += 5;
+		       }
+		   }
+		pending_exact = 0;
+		beg_interval = NULL;
+	      }
+	      break;
+
+	    unfetch_interval:
+	      /* If an invalid interval, match the characters as literals.  */
+	       assert (beg_interval);
+	       p = beg_interval;
+	       beg_interval = NULL;
+
+	       /* normal_char and normal_backslash need `c'.  */
+	       PATFETCH (c);
+
+	       if (!(syntax & RE_NO_BK_BRACES))
+		 {
+		   if (p > pattern  &&  p[-1] == '\\')
+		     goto normal_backslash;
+		 }
+	       goto normal_char;
+
+#ifdef emacs
+	    /* There is no way to specify the before_dot and after_dot
+	       operators.  rms says this is ok.  --karl  */
+	    case '=':
+	      BUF_PUSH (at_dot);
+	      break;
+
+	    case 's':
+	      laststart = b;
+	      PATFETCH (c);
+	      BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]);
+	      break;
+
+	    case 'S':
+	      laststart = b;
+	      PATFETCH (c);
+	      BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]);
+	      break;
+#endif /* emacs */
+
+
+	    case 'w':
+	      laststart = b;
+	      BUF_PUSH (wordchar);
+	      break;
+
+
+	    case 'W':
+	      laststart = b;
+	      BUF_PUSH (notwordchar);
+	      break;
+
+
+	    case '<':
+	      BUF_PUSH (wordbeg);
+	      break;
+
+	    case '>':
+	      BUF_PUSH (wordend);
+	      break;
+
+	    case 'b':
+	      BUF_PUSH (wordbound);
+	      break;
+
+	    case 'B':
+	      BUF_PUSH (notwordbound);
+	      break;
+
+	    case '`':
+	      BUF_PUSH (begbuf);
+	      break;
+
+	    case '\'':
+	      BUF_PUSH (endbuf);
+	      break;
+
+	    case '1': case '2': case '3': case '4': case '5':
+	    case '6': case '7': case '8': case '9':
+	      if (syntax & RE_NO_BK_REFS)
+		goto normal_char;
+
+	      c1 = c - '0';
+
+	      if (c1 > regnum)
+		return REG_ESUBREG;
+
+	      /* Can't back reference to a subexpression if inside of it.  */
+	      if (group_in_compile_stack (compile_stack, c1))
+		goto normal_char;
+
+	      laststart = b;
+	      BUF_PUSH_2 (duplicate, c1);
+	      break;
+
+
+	    case '+':
+	    case '?':
+	      if (syntax & RE_BK_PLUS_QM)
+		goto handle_plus;
+	      else
+		goto normal_backslash;
+
+	    default:
+	    normal_backslash:
+	      /* You might think it would be useful for \ to mean
+		 not to translate; but if we don't translate it
+		 it will never match anything.  */
+	      c = TRANSLATE (c);
+	      goto normal_char;
+	    }
+	  break;
+
+
+	default:
+	/* Expects the character in `c'.  */
+	normal_char:
+	      /* If no exactn currently being built.  */
+	  if (!pending_exact
+
+	      /* If last exactn not at current position.  */
+	      || pending_exact + *pending_exact + 1 != b
+
+	      /* We have only one byte following the exactn for the count.  */
+	      || *pending_exact == (1 << BYTEWIDTH) - 1
+
+	      /* If followed by a repetition operator.  */
+	      || *p == '*' || *p == '^'
+	      || ((syntax & RE_BK_PLUS_QM)
+		  ? *p == '\\' && (p[1] == '+' || p[1] == '?')
+		  : (*p == '+' || *p == '?'))
+	      || ((syntax & RE_INTERVALS)
+		  && ((syntax & RE_NO_BK_BRACES)
+		      ? *p == '{'
+		      : (p[0] == '\\' && p[1] == '{'))))
+	    {
+	      /* Start building a new exactn.  */
+
+	      laststart = b;
+
+	      BUF_PUSH_2 (exactn, 0);
+	      pending_exact = b - 1;
+	    }
+
+	  BUF_PUSH (c);
+	  (*pending_exact)++;
+	  break;
+	} /* switch (c) */
+    } /* while p != pend */
+
+
+  /* Through the pattern now.  */
+
+  if (fixup_alt_jump)
+    STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
+
+  if (!COMPILE_STACK_EMPTY)
+    return REG_EPAREN;
+
+  free (compile_stack.stack);
+
+  /* We have succeeded; set the length of the buffer.  */
+  bufp->used = b - bufp->buffer;
+
+#ifdef DEBUG
+  if (debug)
+    {
+      DEBUG_PRINT1 ("\nCompiled pattern: ");
+      print_compiled_pattern (bufp);
+    }
+#endif /* DEBUG */
+
+  return REG_NOERROR;
+} /* regex_compile */
+
+/* Subroutines for `regex_compile'.  */
+
+/* Store OP at LOC followed by two-byte integer parameter ARG.  */
+
+static void
+store_op1 (op, loc, arg)
+    re_opcode_t op;
+    unsigned char *loc;
+    int arg;
+{
+  *loc = (unsigned char) op;
+  STORE_NUMBER (loc + 1, arg);
+}
+
+
+/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2.  */
+
+static void
+store_op2 (op, loc, arg1, arg2)
+    re_opcode_t op;
+    unsigned char *loc;
+    int arg1, arg2;
+{
+  *loc = (unsigned char) op;
+  STORE_NUMBER (loc + 1, arg1);
+  STORE_NUMBER (loc + 3, arg2);
+}
+
+
+/* Copy the bytes from LOC to END to open up three bytes of space at LOC
+   for OP followed by two-byte integer parameter ARG.  */
+
+static void
+insert_op1 (op, loc, arg, end)
+    re_opcode_t op;
+    unsigned char *loc;
+    int arg;
+    unsigned char *end;
+{
+  register unsigned char *pfrom = end;
+  register unsigned char *pto = end + 3;
+
+  while (pfrom != loc)
+    *--pto = *--pfrom;
+
+  store_op1 (op, loc, arg);
+}
+
+
+/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2.  */
+
+static void
+insert_op2 (op, loc, arg1, arg2, end)
+    re_opcode_t op;
+    unsigned char *loc;
+    int arg1, arg2;
+    unsigned char *end;
+{
+  register unsigned char *pfrom = end;
+  register unsigned char *pto = end + 5;
+
+  while (pfrom != loc)
+    *--pto = *--pfrom;
+
+  store_op2 (op, loc, arg1, arg2);
+}
+
+
+/* P points to just after a ^ in PATTERN.  Return true if that ^ comes
+   after an alternative or a begin-subexpression.  We assume there is at
+   least one character before the ^.  */
+
+static boolean
+at_begline_loc_p (pattern, p, syntax)
+    const char *pattern, *p;
+    reg_syntax_t syntax;
+{
+  const char *prev = p - 2;
+  boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\';
+
+  return
+       /* After a subexpression?  */
+       (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash))
+       /* After an alternative?  */
+    || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash));
+}
+
+
+/* The dual of at_begline_loc_p.  This one is for $.  We assume there is
+   at least one character after the $, i.e., `P < PEND'.  */
+
+static boolean
+at_endline_loc_p (p, pend, syntax)
+    const char *p, *pend;
+    int syntax;
+{
+  const char *next = p;
+  boolean next_backslash = *next == '\\';
+  const char *next_next = p + 1 < pend ? p + 1 : NULL;
+
+  return
+       /* Before a subexpression?  */
+       (syntax & RE_NO_BK_PARENS ? *next == ')'
+	: next_backslash && next_next && *next_next == ')')
+       /* Before an alternative?  */
+    || (syntax & RE_NO_BK_VBAR ? *next == '|'
+	: next_backslash && next_next && *next_next == '|');
+}
+
+
+/* Returns true if REGNUM is in one of COMPILE_STACK's elements and
+   false if it's not.  */
+
+static boolean
+group_in_compile_stack (compile_stack, regnum)
+    compile_stack_type compile_stack;
+    regnum_t regnum;
+{
+  int this_element;
+
+  for (this_element = compile_stack.avail - 1;
+       this_element >= 0;
+       this_element--)
+    if (compile_stack.stack[this_element].regnum == regnum)
+      return true;
+
+  return false;
+}
+
+
+/* Read the ending character of a range (in a bracket expression) from the
+   uncompiled pattern *P_PTR (which ends at PEND).  We assume the
+   starting character is in `P[-2]'.  (`P[-1]' is the character `-'.)
+   Then we set the translation of all bits between the starting and
+   ending characters (inclusive) in the compiled pattern B.
+
+   Return an error code.
+
+   We use these short variable names so we can use the same macros as
+   `regex_compile' itself.  */
+
+static reg_errcode_t
+compile_range (p_ptr, pend, translate, syntax, b)
+    const char **p_ptr, *pend;
+    char *translate;
+    reg_syntax_t syntax;
+    unsigned char *b;
+{
+  unsigned this_char;
+
+  const char *p = *p_ptr;
+  int range_start, range_end;
+
+  if (p == pend)
+    return REG_ERANGE;
+
+  /* Even though the pattern is a signed `char *', we need to fetch
+     with unsigned char *'s; if the high bit of the pattern character
+     is set, the range endpoints will be negative if we fetch using a
+     signed char *.
+
+     We also want to fetch the endpoints without translating them; the
+     appropriate translation is done in the bit-setting loop below.  */
+  range_start = ((unsigned char *) p)[-2];
+  range_end   = ((unsigned char *) p)[0];
+
+  /* Have to increment the pointer into the pattern string, so the
+     caller isn't still at the ending character.  */
+  (*p_ptr)++;
+
+  /* If the start is after the end, the range is empty.  */
+  if (range_start > range_end)
+    return syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR;
+
+  /* Here we see why `this_char' has to be larger than an `unsigned
+     char' -- the range is inclusive, so if `range_end' == 0xff
+     (assuming 8-bit characters), we would otherwise go into an infinite
+     loop, since all characters <= 0xff.  */
+  for (this_char = range_start; this_char <= range_end; this_char++)
+    {
+      SET_LIST_BIT (TRANSLATE (this_char));
+    }
+
+  return REG_NOERROR;
+}
+
+/* Failure stack declarations and macros; both re_compile_fastmap and
+   re_match_2 use a failure stack.  These have to be macros because of
+   REGEX_ALLOCATE.  */
+
+
+/* Number of failure points for which to initially allocate space
+   when matching.  If this number is exceeded, we allocate more
+   space, so it is not a hard limit.  */
+#ifndef INIT_FAILURE_ALLOC
+#define INIT_FAILURE_ALLOC 5
+#endif
+
+/* Roughly the maximum number of failure points on the stack.  Would be
+   exactly that if always used MAX_FAILURE_SPACE each time we failed.
+   This is a variable only so users of regex can assign to it; we never
+   change it ourselves.  */
+int re_max_failures = 2000;
+
+typedef const unsigned char *fail_stack_elt_t;
+
+typedef struct
+{
+  fail_stack_elt_t *stack;
+  unsigned size;
+  unsigned avail;			/* Offset of next open position.  */
+} fail_stack_type;
+
+#define FAIL_STACK_EMPTY()     (fail_stack.avail == 0)
+#define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0)
+#define FAIL_STACK_FULL()      (fail_stack.avail == fail_stack.size)
+#define FAIL_STACK_TOP()       (fail_stack.stack[fail_stack.avail])
+
+
+/* Initialize `fail_stack'.  Do `return -2' if the alloc fails.  */
+
+#define INIT_FAIL_STACK()						\
+  do {									\
+    fail_stack.stack = (fail_stack_elt_t *)				\
+      REGEX_ALLOCATE (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t));	\
+									\
+    if (fail_stack.stack == NULL)					\
+      return -2;							\
+									\
+    fail_stack.size = INIT_FAILURE_ALLOC;				\
+    fail_stack.avail = 0;						\
+  } while (0)
+
+
+/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items.
+
+   Return 1 if succeeds, and 0 if either ran out of memory
+   allocating space for it or it was already too large.
+
+   REGEX_REALLOCATE requires `destination' be declared.   */
+
+#define DOUBLE_FAIL_STACK(fail_stack)					\
+  ((fail_stack).size > re_max_failures * MAX_FAILURE_ITEMS		\
+   ? 0									\
+   : ((fail_stack).stack = (fail_stack_elt_t *)				\
+	REGEX_REALLOCATE ((fail_stack).stack, 				\
+	  (fail_stack).size * sizeof (fail_stack_elt_t),		\
+	  ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)),	\
+									\
+      (fail_stack).stack == NULL					\
+      ? 0								\
+      : ((fail_stack).size <<= 1, 					\
+	 1)))
+
+
+/* Push PATTERN_OP on FAIL_STACK.
+
+   Return 1 if was able to do so and 0 if ran out of memory allocating
+   space to do so.  */
+#define PUSH_PATTERN_OP(pattern_op, fail_stack)				\
+  ((FAIL_STACK_FULL ()							\
+    && !DOUBLE_FAIL_STACK (fail_stack))					\
+    ? 0									\
+    : ((fail_stack).stack[(fail_stack).avail++] = pattern_op,		\
+       1))
+
+/* This pushes an item onto the failure stack.  Must be a four-byte
+   value.  Assumes the variable `fail_stack'.  Probably should only
+   be called from within `PUSH_FAILURE_POINT'.  */
+#define PUSH_FAILURE_ITEM(item)						\
+  fail_stack.stack[fail_stack.avail++] = (fail_stack_elt_t) item
+
+/* The complement operation.  Assumes `fail_stack' is nonempty.  */
+#define POP_FAILURE_ITEM() fail_stack.stack[--fail_stack.avail]
+
+/* Used to omit pushing failure point id's when we're not debugging.  */
+#ifdef DEBUG
+#define DEBUG_PUSH PUSH_FAILURE_ITEM
+#define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_ITEM ()
+#else
+#define DEBUG_PUSH(item)
+#define DEBUG_POP(item_addr)
+#endif
+
+
+/* Push the information about the state we will need
+   if we ever fail back to it.
+
+   Requires variables fail_stack, regstart, regend, reg_info, and
+   num_regs be declared.  DOUBLE_FAIL_STACK requires `destination' be
+   declared.
+
+   Does `return FAILURE_CODE' if runs out of memory.  */
+
+#define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code)	\
+  do {									\
+    char *destination;							\
+    /* Must be int, so when we don't save any registers, the arithmetic	\
+       of 0 + -1 isn't done as unsigned.  */				\
+    int this_reg;							\
+									\
+    DEBUG_STATEMENT (failure_id++);					\
+    DEBUG_STATEMENT (nfailure_points_pushed++);				\
+    DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id);		\
+    DEBUG_PRINT2 ("  Before push, next avail: %d\n", (fail_stack).avail);\
+    DEBUG_PRINT2 ("                     size: %d\n", (fail_stack).size);\
+									\
+    DEBUG_PRINT2 ("  slots needed: %d\n", NUM_FAILURE_ITEMS);		\
+    DEBUG_PRINT2 ("     available: %d\n", REMAINING_AVAIL_SLOTS);	\
+									\
+    /* Ensure we have enough space allocated for what we will push.  */	\
+    while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS)			\
+      {									\
+	if (!DOUBLE_FAIL_STACK (fail_stack))			\
+	  return failure_code;						\
+									\
+	DEBUG_PRINT2 ("\n  Doubled stack; size now: %d\n",		\
+		       (fail_stack).size);				\
+	DEBUG_PRINT2 ("  slots available: %d\n", REMAINING_AVAIL_SLOTS);\
+      }									\
+									\
+    /* Push the info, starting with the registers.  */			\
+    DEBUG_PRINT1 ("\n");						\
+									\
+    for (this_reg = lowest_active_reg; this_reg <= highest_active_reg;	\
+	 this_reg++)							\
+      {									\
+	DEBUG_PRINT2 ("  Pushing reg: %d\n", this_reg);			\
+	DEBUG_STATEMENT (num_regs_pushed++);				\
+									\
+	DEBUG_PRINT2 ("    start: 0x%x\n", regstart[this_reg]);		\
+	PUSH_FAILURE_ITEM (regstart[this_reg]);				\
+									\
+	DEBUG_PRINT2 ("    end: 0x%x\n", regend[this_reg]);		\
+	PUSH_FAILURE_ITEM (regend[this_reg]);				\
+									\
+	DEBUG_PRINT2 ("    info: 0x%x\n      ", reg_info[this_reg]);	\
+	DEBUG_PRINT2 (" match_null=%d",					\
+		      REG_MATCH_NULL_STRING_P (reg_info[this_reg]));	\
+	DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg]));	\
+	DEBUG_PRINT2 (" matched_something=%d",				\
+		      MATCHED_SOMETHING (reg_info[this_reg]));		\
+	DEBUG_PRINT2 (" ever_matched=%d",				\
+		      EVER_MATCHED_SOMETHING (reg_info[this_reg]));	\
+	DEBUG_PRINT1 ("\n");						\
+	PUSH_FAILURE_ITEM (reg_info[this_reg].word);			\
+      }									\
+									\
+    DEBUG_PRINT2 ("  Pushing  low active reg: %d\n", lowest_active_reg);\
+    PUSH_FAILURE_ITEM (lowest_active_reg);				\
+									\
+    DEBUG_PRINT2 ("  Pushing high active reg: %d\n", highest_active_reg);\
+    PUSH_FAILURE_ITEM (highest_active_reg);				\
+									\
+    DEBUG_PRINT2 ("  Pushing pattern 0x%x: ", pattern_place);		\
+    DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend);		\
+    PUSH_FAILURE_ITEM (pattern_place);					\
+									\
+    DEBUG_PRINT2 ("  Pushing string 0x%x: `", string_place);		\
+    DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2,   \
+				 size2);				\
+    DEBUG_PRINT1 ("'\n");						\
+    PUSH_FAILURE_ITEM (string_place);					\
+									\
+    DEBUG_PRINT2 ("  Pushing failure id: %u\n", failure_id);		\
+    DEBUG_PUSH (failure_id);						\
+  } while (0)
+
+/* This is the number of items that are pushed and popped on the stack
+   for each register.  */
+#define NUM_REG_ITEMS  3
+
+/* Individual items aside from the registers.  */
+#ifdef DEBUG
+#define NUM_NONREG_ITEMS 5 /* Includes failure point id.  */
+#else
+#define NUM_NONREG_ITEMS 4
+#endif
+
+/* We push at most this many items on the stack.  */
+#define MAX_FAILURE_ITEMS ((num_regs - 1) * NUM_REG_ITEMS + NUM_NONREG_ITEMS)
+
+/* We actually push this many items.  */
+#define NUM_FAILURE_ITEMS						\
+  ((highest_active_reg - lowest_active_reg + 1) * NUM_REG_ITEMS 	\
+    + NUM_NONREG_ITEMS)
+
+/* How many items can still be added to the stack without overflowing it.  */
+#define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail)
+
+
+/* Pops what PUSH_FAIL_STACK pushes.
+
+   We restore into the parameters, all of which should be lvalues:
+     STR -- the saved data position.
+     PAT -- the saved pattern position.
+     LOW_REG, HIGH_REG -- the highest and lowest active registers.
+     REGSTART, REGEND -- arrays of string positions.
+     REG_INFO -- array of information about each subexpression.
+
+   Also assumes the variables `fail_stack' and (if debugging), `bufp',
+   `pend', `string1', `size1', `string2', and `size2'.  */
+
+#define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\
+{									\
+  DEBUG_STATEMENT (fail_stack_elt_t failure_id;)			\
+  int this_reg;								\
+  const unsigned char *string_temp;					\
+									\
+  assert (!FAIL_STACK_EMPTY ());					\
+									\
+  /* Remove failure points and point to how many regs pushed.  */	\
+  DEBUG_PRINT1 ("POP_FAILURE_POINT:\n");				\
+  DEBUG_PRINT2 ("  Before pop, next avail: %d\n", fail_stack.avail);	\
+  DEBUG_PRINT2 ("                    size: %d\n", fail_stack.size);	\
+									\
+  assert (fail_stack.avail >= NUM_NONREG_ITEMS);			\
+									\
+  DEBUG_POP (&failure_id);						\
+  DEBUG_PRINT2 ("  Popping failure id: %u\n", failure_id);		\
+									\
+  /* If the saved string location is NULL, it came from an		\
+     on_failure_keep_string_jump opcode, and we want to throw away the	\
+     saved NULL, thus retaining our current position in the string.  */	\
+  string_temp = POP_FAILURE_ITEM ();					\
+  if (string_temp != NULL)						\
+    str = (const char *) string_temp;					\
+									\
+  DEBUG_PRINT2 ("  Popping string 0x%x: `", str);			\
+  DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2);	\
+  DEBUG_PRINT1 ("'\n");							\
+									\
+  pat = (unsigned char *) POP_FAILURE_ITEM ();				\
+  DEBUG_PRINT2 ("  Popping pattern 0x%x: ", pat);			\
+  DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend);			\
+									\
+  /* Restore register info.  */						\
+  high_reg = (unsigned) POP_FAILURE_ITEM ();				\
+  DEBUG_PRINT2 ("  Popping high active reg: %d\n", high_reg);		\
+									\
+  low_reg = (unsigned) POP_FAILURE_ITEM ();				\
+  DEBUG_PRINT2 ("  Popping  low active reg: %d\n", low_reg);		\
+									\
+  for (this_reg = high_reg; this_reg >= low_reg; this_reg--)		\
+    {									\
+      DEBUG_PRINT2 ("    Popping reg: %d\n", this_reg);			\
+									\
+      reg_info[this_reg].word = POP_FAILURE_ITEM ();			\
+      DEBUG_PRINT2 ("      info: 0x%x\n", reg_info[this_reg]);		\
+									\
+      regend[this_reg] = (const char *) POP_FAILURE_ITEM ();		\
+      DEBUG_PRINT2 ("      end: 0x%x\n", regend[this_reg]);		\
+									\
+      regstart[this_reg] = (const char *) POP_FAILURE_ITEM ();		\
+      DEBUG_PRINT2 ("      start: 0x%x\n", regstart[this_reg]);		\
+    }									\
+									\
+  DEBUG_STATEMENT (nfailure_points_popped++);				\
+} /* POP_FAILURE_POINT */
+
+/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in
+   BUFP.  A fastmap records which of the (1 << BYTEWIDTH) possible
+   characters can start a string that matches the pattern.  This fastmap
+   is used by re_search to skip quickly over impossible starting points.
+
+   The caller must supply the address of a (1 << BYTEWIDTH)-byte data
+   area as BUFP->fastmap.
+
+   We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in
+   the pattern buffer.
+
+   Returns 0 if we succeed, -2 if an internal error.   */
+
+int
+re_compile_fastmap (bufp)
+     struct re_pattern_buffer *bufp;
+{
+  int j, k;
+  fail_stack_type fail_stack;
+#ifndef REGEX_MALLOC
+  char *destination;
+#endif
+  /* We don't push any register information onto the failure stack.  */
+  unsigned num_regs = 0;
+
+  register char *fastmap = bufp->fastmap;
+  unsigned char *pattern = bufp->buffer;
+  unsigned long size = bufp->used;
+  const unsigned char *p = pattern;
+  register unsigned char *pend = pattern + size;
+
+  /* Assume that each path through the pattern can be null until
+     proven otherwise.  We set this false at the bottom of switch
+     statement, to which we get only if a particular path doesn't
+     match the empty string.  */
+  boolean path_can_be_null = true;
+
+  /* We aren't doing a `succeed_n' to begin with.  */
+  boolean succeed_n_p = false;
+
+  assert (fastmap != NULL && p != NULL);
+
+  INIT_FAIL_STACK ();
+  bzero (fastmap, 1 << BYTEWIDTH);  /* Assume nothing's valid.  */
+  bufp->fastmap_accurate = 1;	    /* It will be when we're done.  */
+  bufp->can_be_null = 0;
+
+  while (p != pend || !FAIL_STACK_EMPTY ())
+    {
+      if (p == pend)
+	{
+	  bufp->can_be_null |= path_can_be_null;
+
+	  /* Reset for next path.  */
+	  path_can_be_null = true;
+
+	  p = fail_stack.stack[--fail_stack.avail];
+	}
+
+      /* We should never be about to go beyond the end of the pattern.  */
+      assert (p < pend);
+
+#ifdef SWITCH_ENUM_BUG
+      switch ((int) ((re_opcode_t) *p++))
+#else
+      switch ((re_opcode_t) *p++)
+#endif
+	{
+
+	/* I guess the idea here is to simply not bother with a fastmap
+	   if a backreference is used, since it's too hard to figure out
+	   the fastmap for the corresponding group.  Setting
+	   `can_be_null' stops `re_search_2' from using the fastmap, so
+	   that is all we do.  */
+	case duplicate:
+	  bufp->can_be_null = 1;
+	  return 0;
+
+
+      /* Following are the cases which match a character.  These end
+	 with `break'.  */
+
+	case exactn:
+	  fastmap[p[1]] = 1;
+	  break;
+
+
+	case charset:
+	  for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
+	    if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))
+	      fastmap[j] = 1;
+	  break;
+
+
+	case charset_not:
+	  /* Chars beyond end of map must be allowed.  */
+	  for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++)
+	    fastmap[j] = 1;
+
+	  for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
+	    if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))))
+	      fastmap[j] = 1;
+	  break;
+
+
+	case wordchar:
+	  for (j = 0; j < (1 << BYTEWIDTH); j++)
+	    if (SYNTAX (j) == Sword)
+	      fastmap[j] = 1;
+	  break;
+
+
+	case notwordchar:
+	  for (j = 0; j < (1 << BYTEWIDTH); j++)
+	    if (SYNTAX (j) != Sword)
+	      fastmap[j] = 1;
+	  break;
+
+
+	case anychar:
+	  /* `.' matches anything ...  */
+	  for (j = 0; j < (1 << BYTEWIDTH); j++)
+	    fastmap[j] = 1;
+
+	  /* ... except perhaps newline.  */
+	  if (!(bufp->syntax & RE_DOT_NEWLINE))
+	    fastmap['\n'] = 0;
+
+	  /* Return if we have already set `can_be_null'; if we have,
+	     then the fastmap is irrelevant.  Something's wrong here.  */
+	  else if (bufp->can_be_null)
+	    return 0;
+
+	  /* Otherwise, have to check alternative paths.  */
+	  break;
+
+
+#ifdef emacs
+	case syntaxspec:
+	  k = *p++;
+	  for (j = 0; j < (1 << BYTEWIDTH); j++)
+	    if (SYNTAX (j) == (enum syntaxcode) k)
+	      fastmap[j] = 1;
+	  break;
+
+
+	case notsyntaxspec:
+	  k = *p++;
+	  for (j = 0; j < (1 << BYTEWIDTH); j++)
+	    if (SYNTAX (j) != (enum syntaxcode) k)
+	      fastmap[j] = 1;
+	  break;
+
+
+      /* All cases after this match the empty string.  These end with
+	 `continue'.  */
+
+
+	case before_dot:
+	case at_dot:
+	case after_dot:
+	  continue;
+#endif /* not emacs */
+
+
+	case no_op:
+	case begline:
+	case endline:
+	case begbuf:
+	case endbuf:
+	case wordbound:
+	case notwordbound:
+	case wordbeg:
+	case wordend:
+	case push_dummy_failure:
+	  continue;
+
+
+	case jump_n:
+	case pop_failure_jump:
+	case maybe_pop_jump:
+	case jump:
+	case jump_past_alt:
+	case dummy_failure_jump:
+	  EXTRACT_NUMBER_AND_INCR (j, p);
+	  p += j;
+	  if (j > 0)
+	    continue;
+
+	  /* Jump backward implies we just went through the body of a
+	     loop and matched nothing.  Opcode jumped to should be
+	     `on_failure_jump' or `succeed_n'.  Just treat it like an
+	     ordinary jump.  For a * loop, it has pushed its failure
+	     point already; if so, discard that as redundant.  */
+	  if ((re_opcode_t) *p != on_failure_jump
+	      && (re_opcode_t) *p != succeed_n)
+	    continue;
+
+	  p++;
+	  EXTRACT_NUMBER_AND_INCR (j, p);
+	  p += j;
+
+	  /* If what's on the stack is where we are now, pop it.  */
+	  if (!FAIL_STACK_EMPTY ()
+	      && fail_stack.stack[fail_stack.avail - 1] == p)
+	    fail_stack.avail--;
+
+	  continue;
+
+
+	case on_failure_jump:
+	case on_failure_keep_string_jump:
+	handle_on_failure_jump:
+	  EXTRACT_NUMBER_AND_INCR (j, p);
+
+	  /* For some patterns, e.g., `(a?)?', `p+j' here points to the
+	     end of the pattern.  We don't want to push such a point,
+	     since when we restore it above, entering the switch will
+	     increment `p' past the end of the pattern.  We don't need
+	     to push such a point since we obviously won't find any more
+	     fastmap entries beyond `pend'.  Such a pattern can match
+	     the null string, though.  */
+	  if (p + j < pend)
+	    {
+	      if (!PUSH_PATTERN_OP (p + j, fail_stack))
+		return -2;
+	    }
+	  else
+	    bufp->can_be_null = 1;
+
+	  if (succeed_n_p)
+	    {
+	      EXTRACT_NUMBER_AND_INCR (k, p);	/* Skip the n.  */
+	      succeed_n_p = false;
+	    }
+
+	  continue;
+
+
+	case succeed_n:
+	  /* Get to the number of times to succeed.  */
+	  p += 2;
+
+	  /* Increment p past the n for when k != 0.  */
+	  EXTRACT_NUMBER_AND_INCR (k, p);
+	  if (k == 0)
+	    {
+	      p -= 4;
+	      succeed_n_p = true;  /* Spaghetti code alert.  */
+	      goto handle_on_failure_jump;
+	    }
+	  continue;
+
+
+	case set_number_at:
+	  p += 4;
+	  continue;
+
+
+	case start_memory:
+	case stop_memory:
+	  p += 2;
+	  continue;
+
+
+	default:
+	  abort (); /* We have listed all the cases.  */
+	} /* switch *p++ */
+
+      /* Getting here means we have found the possible starting
+	 characters for one path of the pattern -- and that the empty
+	 string does not match.  We need not follow this path further.
+	 Instead, look at the next alternative (remembered on the
+	 stack), or quit if no more.  The test at the top of the loop
+	 does these things.  */
+      path_can_be_null = false;
+      p = pend;
+    } /* while p */
+
+  /* Set `can_be_null' for the last path (also the first path, if the
+     pattern is empty).  */
+  bufp->can_be_null |= path_can_be_null;
+  return 0;
+} /* re_compile_fastmap */
+
+/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
+   ENDS.  Subsequent matches using PATTERN_BUFFER and REGS will use
+   this memory for recording register information.  STARTS and ENDS
+   must be allocated using the malloc library routine, and must each
+   be at least NUM_REGS * sizeof (regoff_t) bytes long.
+
+   If NUM_REGS == 0, then subsequent matches should allocate their own
+   register data.
+
+   Unless this function is called, the first search or match using
+   PATTERN_BUFFER will allocate its own register data, without
+   freeing the old data.  */
+
+void
+re_set_registers (bufp, regs, num_regs, starts, ends)
+    struct re_pattern_buffer *bufp;
+    struct re_registers *regs;
+    unsigned num_regs;
+    regoff_t *starts, *ends;
+{
+  if (num_regs)
+    {
+      bufp->regs_allocated = REGS_REALLOCATE;
+      regs->num_regs = num_regs;
+      regs->start = starts;
+      regs->end = ends;
+    }
+  else
+    {
+      bufp->regs_allocated = REGS_UNALLOCATED;
+      regs->num_regs = 0;
+      regs->start = regs->end = (regoff_t) 0;
+    }
+}
+
+/* Searching routines.  */
+
+/* Like re_search_2, below, but only one string is specified, and
+   doesn't let you say where to stop matching. */
+
+int
+re_search (bufp, string, size, startpos, range, regs)
+     struct re_pattern_buffer *bufp;
+     const char *string;
+     int size, startpos, range;
+     struct re_registers *regs;
+{
+  return re_search_2 (bufp, NULL, 0, string, size, startpos, range,
+		      regs, size);
+}
+
+
+/* Using the compiled pattern in BUFP->buffer, first tries to match the
+   virtual concatenation of STRING1 and STRING2, starting first at index
+   STARTPOS, then at STARTPOS + 1, and so on.
+
+   STRING1 and STRING2 have length SIZE1 and SIZE2, respectively.
+
+   RANGE is how far to scan while trying to match.  RANGE = 0 means try
+   only at STARTPOS; in general, the last start tried is STARTPOS +
+   RANGE.
+
+   In REGS, return the indices of the virtual concatenation of STRING1
+   and STRING2 that matched the entire BUFP->buffer and its contained
+   subexpressions.
+
+   Do not consider matching one past the index STOP in the virtual
+   concatenation of STRING1 and STRING2.
+
+   We return either the position in the strings at which the match was
+   found, -1 if no match, or -2 if error (such as failure
+   stack overflow).  */
+
+int
+re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop)
+     struct re_pattern_buffer *bufp;
+     const char *string1, *string2;
+     int size1, size2;
+     int startpos;
+     int range;
+     struct re_registers *regs;
+     int stop;
+{
+  int val;
+  register char *fastmap = bufp->fastmap;
+  register char *translate = bufp->translate;
+  int total_size = size1 + size2;
+  int endpos = startpos + range;
+
+  /* Check for out-of-range STARTPOS.  */
+  if (startpos < 0 || startpos > total_size)
+    return -1;
+
+  /* Fix up RANGE if it might eventually take us outside
+     the virtual concatenation of STRING1 and STRING2.  */
+  if (endpos < -1)
+    range = -1 - startpos;
+  else if (endpos > total_size)
+    range = total_size - startpos;
+
+  /* If the search isn't to be a backwards one, don't waste time in a
+     search for a pattern that must be anchored.  */
+  if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == begbuf && range > 0)
+    {
+      if (startpos > 0)
+	return -1;
+      else
+	range = 1;
+    }
+
+  /* Update the fastmap now if not correct already.  */
+  if (fastmap && !bufp->fastmap_accurate)
+    if (re_compile_fastmap (bufp) == -2)
+      return -2;
+
+  /* Loop through the string, looking for a place to start matching.  */
+  for (;;)
+    {
+      /* If a fastmap is supplied, skip quickly over characters that
+	 cannot be the start of a match.  If the pattern can match the
+	 null string, however, we don't need to skip characters; we want
+	 the first null string.  */
+      if (fastmap && startpos < total_size && !bufp->can_be_null)
+	{
+	  if (range > 0)	/* Searching forwards.  */
+	    {
+	      register const char *d;
+	      register int lim = 0;
+	      int irange = range;
+
+	      if (startpos < size1 && startpos + range >= size1)
+		lim = range - (size1 - startpos);
+
+	      d = (startpos >= size1 ? string2 - size1 : string1) + startpos;
+
+	      /* Written out as an if-else to avoid testing `translate'
+		 inside the loop.  */
+	      if (translate)
+		while (range > lim
+		       && !fastmap[(unsigned char)
+				   translate[(unsigned char) *d++]])
+		  range--;
+	      else
+		while (range > lim && !fastmap[(unsigned char) *d++])
+		  range--;
+
+	      startpos += irange - range;
+	    }
+	  else				/* Searching backwards.  */
+	    {
+	      register char c = (size1 == 0 || startpos >= size1
+				 ? string2[startpos - size1]
+				 : string1[startpos]);
+
+	      if (!fastmap[(unsigned char) TRANSLATE (c)])
+		goto advance;
+	    }
+	}
+
+      /* If can't match the null string, and that's all we have left, fail.  */
+      if (range >= 0 && startpos == total_size && fastmap
+	  && !bufp->can_be_null)
+	return -1;
+
+      val = re_match_2 (bufp, string1, size1, string2, size2,
+			startpos, regs, stop);
+      if (val >= 0)
+	return startpos;
+
+      if (val == -2)
+	return -2;
+
+    advance:
+      if (!range)
+	break;
+      else if (range > 0)
+	{
+	  range--;
+	  startpos++;
+	}
+      else
+	{
+	  range++;
+	  startpos--;
+	}
+    }
+  return -1;
+} /* re_search_2 */
+
+/* Declarations and macros for re_match_2.  */
+
+static int bcmp_translate ();
+static boolean alt_match_null_string_p (),
+	       common_op_match_null_string_p (),
+	       group_match_null_string_p ();
+
+/* Structure for per-register (a.k.a. per-group) information.
+   This must not be longer than one word, because we push this value
+   onto the failure stack.  Other register information, such as the
+   starting and ending positions (which are addresses), and the list of
+   inner groups (which is a bits list) are maintained in separate
+   variables.
+
+   We are making a (strictly speaking) nonportable assumption here: that
+   the compiler will pack our bit fields into something that fits into
+   the type of `word', i.e., is something that fits into one item on the
+   failure stack.  */
+typedef union
+{
+  fail_stack_elt_t word;
+  struct
+  {
+      /* This field is one if this group can match the empty string,
+	 zero if not.  If not yet determined,  `MATCH_NULL_UNSET_VALUE'.  */
+#define MATCH_NULL_UNSET_VALUE 3
+    unsigned match_null_string_p : 2;
+    unsigned is_active : 1;
+    unsigned matched_something : 1;
+    unsigned ever_matched_something : 1;
+  } bits;
+} register_info_type;
+
+#define REG_MATCH_NULL_STRING_P(R)  ((R).bits.match_null_string_p)
+#define IS_ACTIVE(R)  ((R).bits.is_active)
+#define MATCHED_SOMETHING(R)  ((R).bits.matched_something)
+#define EVER_MATCHED_SOMETHING(R)  ((R).bits.ever_matched_something)
+
+
+/* Call this when have matched a real character; it sets `matched' flags
+   for the subexpressions which we are currently inside.  Also records
+   that those subexprs have matched.  */
+#define SET_REGS_MATCHED()						\
+  do									\
+    {									\
+      unsigned r;							\
+      for (r = lowest_active_reg; r <= highest_active_reg; r++)		\
+	{								\
+	  MATCHED_SOMETHING (reg_info[r])				\
+	    = EVER_MATCHED_SOMETHING (reg_info[r])			\
+	    = 1;							\
+	}								\
+    }									\
+  while (0)
+
+
+/* This converts PTR, a pointer into one of the search strings `string1'
+   and `string2' into an offset from the beginning of that string.  */
+#define POINTER_TO_OFFSET(ptr)						\
+  (FIRST_STRING_P (ptr) ? (ptr) - string1 : (ptr) - string2 + size1)
+
+/* Registers are set to a sentinel when they haven't yet matched.  */
+#define REG_UNSET_VALUE ((char *) -1)
+#define REG_UNSET(e) ((e) == REG_UNSET_VALUE)
+
+
+/* Macros for dealing with the split strings in re_match_2.  */
+
+#define MATCHING_IN_FIRST_STRING  (dend == end_match_1)
+
+/* Call before fetching a character with *d.  This switches over to
+   string2 if necessary.  */
+#define PREFETCH()							\
+  while (d == dend)						    	\
+    {									\
+      /* End of string2 => fail.  */					\
+      if (dend == end_match_2) 						\
+	goto fail;							\
+      /* End of string1 => advance to string2.  */ 			\
+      d = string2;						        \
+      dend = end_match_2;						\
+    }
+
+
+/* Test if at very beginning or at very end of the virtual concatenation
+   of `string1' and `string2'.  If only one string, it's `string2'.  */
+#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2)
+#define AT_STRINGS_END(d) ((d) == end2)
+
+
+/* Test if D points to a character which is word-constituent.  We have
+   two special cases to check for: if past the end of string1, look at
+   the first character in string2; and if before the beginning of
+   string2, look at the last character in string1.  */
+#define WORDCHAR_P(d)							\
+  (SYNTAX ((d) == end1 ? *string2					\
+	   : (d) == string2 - 1 ? *(end1 - 1) : *(d))			\
+   == Sword)
+
+/* Test if the character before D and the one at D differ with respect
+   to being word-constituent.  */
+#define AT_WORD_BOUNDARY(d)						\
+  (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)				\
+   || WORDCHAR_P (d - 1) != WORDCHAR_P (d))
+
+
+/* Free everything we malloc.  */
+#ifdef REGEX_MALLOC
+#define FREE_VAR(var) if (var) free (var); var = NULL
+#define FREE_VARIABLES()						\
+  do {									\
+    FREE_VAR (fail_stack.stack);					\
+    FREE_VAR (regstart);						\
+    FREE_VAR (regend);							\
+    FREE_VAR (old_regstart);						\
+    FREE_VAR (old_regend);						\
+    FREE_VAR (best_regstart);						\
+    FREE_VAR (best_regend);						\
+    FREE_VAR (reg_info);						\
+    FREE_VAR (reg_dummy);						\
+    FREE_VAR (reg_info_dummy);						\
+  } while (0)
+#else /* not REGEX_MALLOC */
+/* Some MIPS systems (at least) want this to free alloca'd storage.  */
+#define FREE_VARIABLES() alloca (0)
+#endif /* not REGEX_MALLOC */
+
+
+/* These values must meet several constraints.  They must not be valid
+   register values; since we have a limit of 255 registers (because
+   we use only one byte in the pattern for the register number), we can
+   use numbers larger than 255.  They must differ by 1, because of
+   NUM_FAILURE_ITEMS above.  And the value for the lowest register must
+   be larger than the value for the highest register, so we do not try
+   to actually save any registers when none are active.  */
+#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH)
+#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1)
+
+/* Matching routines.  */
+
+#ifndef emacs   /* Emacs never uses this.  */
+/* re_match is like re_match_2 except it takes only a single string.  */
+
+int
+re_match (bufp, string, size, pos, regs)
+     struct re_pattern_buffer *bufp;
+     const char *string;
+     int size, pos;
+     struct re_registers *regs;
+ {
+  return re_match_2 (bufp, NULL, 0, string, size, pos, regs, size);
+}
+#endif /* not emacs */
+
+
+/* re_match_2 matches the compiled pattern in BUFP against the
+   the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1
+   and SIZE2, respectively).  We start matching at POS, and stop
+   matching at STOP.
+
+   If REGS is non-null and the `no_sub' field of BUFP is nonzero, we
+   store offsets for the substring each group matched in REGS.  See the
+   documentation for exactly how many groups we fill.
+
+   We return -1 if no match, -2 if an internal error (such as the
+   failure stack overflowing).  Otherwise, we return the length of the
+   matched substring.  */
+
+int
+re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
+     struct re_pattern_buffer *bufp;
+     const char *string1, *string2;
+     int size1, size2;
+     int pos;
+     struct re_registers *regs;
+     int stop;
+{
+  /* General temporaries.  */
+  int mcnt;
+  unsigned char *p1;
+
+  /* Just past the end of the corresponding string.  */
+  const char *end1, *end2;
+
+  /* Pointers into string1 and string2, just past the last characters in
+     each to consider matching.  */
+  const char *end_match_1, *end_match_2;
+
+  /* Where we are in the data, and the end of the current string.  */
+  const char *d, *dend;
+
+  /* Where we are in the pattern, and the end of the pattern.  */
+  unsigned char *p = bufp->buffer;
+  register unsigned char *pend = p + bufp->used;
+
+  /* We use this to map every character in the string.  */
+  char *translate = bufp->translate;
+
+  /* Failure point stack.  Each place that can handle a failure further
+     down the line pushes a failure point on this stack.  It consists of
+     restart, regend, and reg_info for all registers corresponding to
+     the subexpressions we're currently inside, plus the number of such
+     registers, and, finally, two char *'s.  The first char * is where
+     to resume scanning the pattern; the second one is where to resume
+     scanning the strings.  If the latter is zero, the failure point is
+     a ``dummy''; if a failure happens and the failure point is a dummy,
+     it gets discarded and the next next one is tried.  */
+  fail_stack_type fail_stack;
+#ifdef DEBUG
+  static unsigned failure_id = 0;
+  unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0;
+#endif
+
+  /* We fill all the registers internally, independent of what we
+     return, for use in backreferences.  The number here includes
+     an element for register zero.  */
+  unsigned num_regs = bufp->re_nsub + 1;
+
+  /* The currently active registers.  */
+  unsigned lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+  unsigned highest_active_reg = NO_HIGHEST_ACTIVE_REG;
+
+  /* Information on the contents of registers. These are pointers into
+     the input strings; they record just what was matched (on this
+     attempt) by a subexpression part of the pattern, that is, the
+     regnum-th regstart pointer points to where in the pattern we began
+     matching and the regnum-th regend points to right after where we
+     stopped matching the regnum-th subexpression.  (The zeroth register
+     keeps track of what the whole pattern matches.)  */
+  const char **regstart = NULL, **regend = NULL;
+
+  /* If a group that's operated upon by a repetition operator fails to
+     match anything, then the register for its start will need to be
+     restored because it will have been set to wherever in the string we
+     are when we last see its open-group operator.  Similarly for a
+     register's end.  */
+  const char **old_regstart = NULL, **old_regend = NULL;
+
+  /* The is_active field of reg_info helps us keep track of which (possibly
+     nested) subexpressions we are currently in. The matched_something
+     field of reg_info[reg_num] helps us tell whether or not we have
+     matched any of the pattern so far this time through the reg_num-th
+     subexpression.  These two fields get reset each time through any
+     loop their register is in.  */
+  register_info_type *reg_info = NULL;
+
+  /* The following record the register info as found in the above
+     variables when we find a match better than any we've seen before.
+     This happens as we backtrack through the failure points, which in
+     turn happens only if we have not yet matched the entire string. */
+  unsigned best_regs_set = false;
+  const char **best_regstart = NULL, **best_regend = NULL;
+
+  /* Logically, this is `best_regend[0]'.  But we don't want to have to
+     allocate space for that if we're not allocating space for anything
+     else (see below).  Also, we never need info about register 0 for
+     any of the other register vectors, and it seems rather a kludge to
+     treat `best_regend' differently than the rest.  So we keep track of
+     the end of the best match so far in a separate variable.  We
+     initialize this to NULL so that when we backtrack the first time
+     and need to test it, it's not garbage.  */
+  const char *match_end = NULL;
+
+  /* Used when we pop values we don't care about.  */
+  const char **reg_dummy = NULL;
+  register_info_type *reg_info_dummy = NULL;
+
+#ifdef DEBUG
+  /* Counts the total number of registers pushed.  */
+  unsigned num_regs_pushed = 0;
+#endif
+
+  DEBUG_PRINT1 ("\n\nEntering re_match_2.\n");
+
+  INIT_FAIL_STACK ();
+
+  /* Do not bother to initialize all the register variables if there are
+     no groups in the pattern, as it takes a fair amount of time.  If
+     there are groups, we include space for register 0 (the whole
+     pattern), even though we never use it, since it simplifies the
+     array indexing.  We should fix this.  */
+  if (bufp->re_nsub)
+    {
+      regstart = REGEX_TALLOC (num_regs, const char *);
+      regend = REGEX_TALLOC (num_regs, const char *);
+      old_regstart = REGEX_TALLOC (num_regs, const char *);
+      old_regend = REGEX_TALLOC (num_regs, const char *);
+      best_regstart = REGEX_TALLOC (num_regs, const char *);
+      best_regend = REGEX_TALLOC (num_regs, const char *);
+      reg_info = REGEX_TALLOC (num_regs, register_info_type);
+      reg_dummy = REGEX_TALLOC (num_regs, const char *);
+      reg_info_dummy = REGEX_TALLOC (num_regs, register_info_type);
+
+      if (!(regstart && regend && old_regstart && old_regend && reg_info
+	    && best_regstart && best_regend && reg_dummy && reg_info_dummy))
+	{
+	  FREE_VARIABLES ();
+	  return -2;
+	}
+    }
+#ifdef REGEX_MALLOC
+  else
+    {
+      /* We must initialize all our variables to NULL, so that
+	 `FREE_VARIABLES' doesn't try to free them.  */
+      regstart = regend = old_regstart = old_regend = best_regstart
+	= best_regend = reg_dummy = NULL;
+      reg_info = reg_info_dummy = (register_info_type *) NULL;
+    }
+#endif /* REGEX_MALLOC */
+
+  /* The starting position is bogus.  */
+  if (pos < 0 || pos > size1 + size2)
+    {
+      FREE_VARIABLES ();
+      return -1;
+    }
+
+  /* Initialize subexpression text positions to -1 to mark ones that no
+     start_memory/stop_memory has been seen for. Also initialize the
+     register information struct.  */
+  for (mcnt = 1; mcnt < num_regs; mcnt++)
+    {
+      regstart[mcnt] = regend[mcnt]
+	= old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE;
+
+      REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE;
+      IS_ACTIVE (reg_info[mcnt]) = 0;
+      MATCHED_SOMETHING (reg_info[mcnt]) = 0;
+      EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0;
+    }
+
+  /* We move `string1' into `string2' if the latter's empty -- but not if
+     `string1' is null.  */
+  if (size2 == 0 && string1 != NULL)
+    {
+      string2 = string1;
+      size2 = size1;
+      string1 = 0;
+      size1 = 0;
+    }
+  end1 = string1 + size1;
+  end2 = string2 + size2;
+
+  /* Compute where to stop matching, within the two strings.  */
+  if (stop <= size1)
+    {
+      end_match_1 = string1 + stop;
+      end_match_2 = string2;
+    }
+  else
+    {
+      end_match_1 = end1;
+      end_match_2 = string2 + stop - size1;
+    }
+
+  /* `p' scans through the pattern as `d' scans through the data.
+     `dend' is the end of the input string that `d' points within.  `d'
+     is advanced into the following input string whenever necessary, but
+     this happens before fetching; therefore, at the beginning of the
+     loop, `d' can be pointing at the end of a string, but it cannot
+     equal `string2'.  */
+  if (size1 > 0 && pos <= size1)
+    {
+      d = string1 + pos;
+      dend = end_match_1;
+    }
+  else
+    {
+      d = string2 + pos - size1;
+      dend = end_match_2;
+    }
+
+  DEBUG_PRINT1 ("The compiled pattern is: ");
+  DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend);
+  DEBUG_PRINT1 ("The string to match is: `");
+  DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2);
+  DEBUG_PRINT1 ("'\n");
+
+  /* This loops over pattern commands.  It exits by returning from the
+     function if the match is complete, or it drops through if the match
+     fails at this starting point in the input data.  */
+  for (;;)
+    {
+      DEBUG_PRINT2 ("\n0x%x: ", p);
+
+      if (p == pend)
+	{ /* End of pattern means we might have succeeded.  */
+	  DEBUG_PRINT1 ("end of pattern ... ");
+
+	  /* If we haven't matched the entire string, and we want the
+	     longest match, try backtracking.  */
+	  if (d != end_match_2)
+	    {
+	      DEBUG_PRINT1 ("backtracking.\n");
+
+	      if (!FAIL_STACK_EMPTY ())
+		{ /* More failure points to try.  */
+		  boolean same_str_p = (FIRST_STRING_P (match_end)
+					== MATCHING_IN_FIRST_STRING);
+
+		  /* If exceeds best match so far, save it.  */
+		  if (!best_regs_set
+		      || (same_str_p && d > match_end)
+		      || (!same_str_p && !MATCHING_IN_FIRST_STRING))
+		    {
+		      best_regs_set = true;
+		      match_end = d;
+
+		      DEBUG_PRINT1 ("\nSAVING match as best so far.\n");
+
+		      for (mcnt = 1; mcnt < num_regs; mcnt++)
+			{
+			  best_regstart[mcnt] = regstart[mcnt];
+			  best_regend[mcnt] = regend[mcnt];
+			}
+		    }
+		  goto fail;
+		}
+
+	      /* If no failure points, don't restore garbage.  */
+	      else if (best_regs_set)
+		{
+		restore_best_regs:
+		  /* Restore best match.  It may happen that `dend ==
+		     end_match_1' while the restored d is in string2.
+		     For example, the pattern `x.*y.*z' against the
+		     strings `x-' and `y-z-', if the two strings are
+		     not consecutive in memory.  */
+		  DEBUG_PRINT1 ("Restoring best registers.\n");
+
+		  d = match_end;
+		  dend = ((d >= string1 && d <= end1)
+			   ? end_match_1 : end_match_2);
+
+		  for (mcnt = 1; mcnt < num_regs; mcnt++)
+		    {
+		      regstart[mcnt] = best_regstart[mcnt];
+		      regend[mcnt] = best_regend[mcnt];
+		    }
+		}
+	    } /* d != end_match_2 */
+
+	  DEBUG_PRINT1 ("Accepting match.\n");
+
+	  /* If caller wants register contents data back, do it.  */
+	  if (regs && !bufp->no_sub)
+	    {
+	      /* Have the register data arrays been allocated?  */
+	      if (bufp->regs_allocated == REGS_UNALLOCATED)
+		{ /* No.  So allocate them with malloc.  We need one
+		     extra element beyond `num_regs' for the `-1' marker
+		     GNU code uses.  */
+		  regs->num_regs = MAX (RE_NREGS, num_regs + 1);
+		  regs->start = TALLOC (regs->num_regs, regoff_t);
+		  regs->end = TALLOC (regs->num_regs, regoff_t);
+		  if (regs->start == NULL || regs->end == NULL)
+		    return -2;
+		  bufp->regs_allocated = REGS_REALLOCATE;
+		}
+	      else if (bufp->regs_allocated == REGS_REALLOCATE)
+		{ /* Yes.  If we need more elements than were already
+		     allocated, reallocate them.  If we need fewer, just
+		     leave it alone.  */
+		  if (regs->num_regs < num_regs + 1)
+		    {
+		      regs->num_regs = num_regs + 1;
+		      RETALLOC (regs->start, regs->num_regs, regoff_t);
+		      RETALLOC (regs->end, regs->num_regs, regoff_t);
+		      if (regs->start == NULL || regs->end == NULL)
+			return -2;
+		    }
+		}
+	      else
+		assert (bufp->regs_allocated == REGS_FIXED);
+
+	      /* Convert the pointer data in `regstart' and `regend' to
+		 indices.  Register zero has to be set differently,
+		 since we haven't kept track of any info for it.  */
+	      if (regs->num_regs > 0)
+		{
+		  regs->start[0] = pos;
+		  regs->end[0] = (MATCHING_IN_FIRST_STRING ? d - string1
+				  : d - string2 + size1);
+		}
+
+	      /* Go through the first `min (num_regs, regs->num_regs)'
+		 registers, since that is all we initialized.  */
+	      for (mcnt = 1; mcnt < MIN (num_regs, regs->num_regs); mcnt++)
+		{
+		  if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt]))
+		    regs->start[mcnt] = regs->end[mcnt] = -1;
+		  else
+		    {
+		      regs->start[mcnt] = POINTER_TO_OFFSET (regstart[mcnt]);
+		      regs->end[mcnt] = POINTER_TO_OFFSET (regend[mcnt]);
+		    }
+		}
+
+	      /* If the regs structure we return has more elements than
+		 were in the pattern, set the extra elements to -1.  If
+		 we (re)allocated the registers, this is the case,
+		 because we always allocate enough to have at least one
+		 -1 at the end.  */
+	      for (mcnt = num_regs; mcnt < regs->num_regs; mcnt++)
+		regs->start[mcnt] = regs->end[mcnt] = -1;
+	    } /* regs && !bufp->no_sub */
+
+	  FREE_VARIABLES ();
+	  DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n",
+			nfailure_points_pushed, nfailure_points_popped,
+			nfailure_points_pushed - nfailure_points_popped);
+	  DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed);
+
+	  mcnt = d - pos - (MATCHING_IN_FIRST_STRING
+			    ? string1
+			    : string2 - size1);
+
+	  DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt);
+
+	  return mcnt;
+	}
+
+      /* Otherwise match next pattern command.  */
+#ifdef SWITCH_ENUM_BUG
+      switch ((int) ((re_opcode_t) *p++))
+#else
+      switch ((re_opcode_t) *p++)
+#endif
+	{
+	/* Ignore these.  Used to ignore the n of succeed_n's which
+	   currently have n == 0.  */
+	case no_op:
+	  DEBUG_PRINT1 ("EXECUTING no_op.\n");
+	  break;
+
+
+	/* Match the next n pattern characters exactly.  The following
+	   byte in the pattern defines n, and the n bytes after that
+	   are the characters to match.  */
+	case exactn:
+	  mcnt = *p++;
+	  DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt);
+
+	  /* This is written out as an if-else so we don't waste time
+	     testing `translate' inside the loop.  */
+	  if (translate)
+	    {
+	      do
+		{
+		  PREFETCH ();
+		  if (translate[(unsigned char) *d++] != (char) *p++)
+		    goto fail;
+		}
+	      while (--mcnt);
+	    }
+	  else
+	    {
+	      do
+		{
+		  PREFETCH ();
+		  if (*d++ != (char) *p++) goto fail;
+		}
+	      while (--mcnt);
+	    }
+	  SET_REGS_MATCHED ();
+	  break;
+
+
+	/* Match any character except possibly a newline or a null.  */
+	case anychar:
+	  DEBUG_PRINT1 ("EXECUTING anychar.\n");
+
+	  PREFETCH ();
+
+	  if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n')
+	      || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000'))
+	    goto fail;
+
+	  SET_REGS_MATCHED ();
+	  DEBUG_PRINT2 ("  Matched `%d'.\n", *d);
+	  d++;
+	  break;
+
+
+	case charset:
+	case charset_not:
+	  {
+	    register unsigned char c;
+	    boolean not = (re_opcode_t) *(p - 1) == charset_not;
+
+	    DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : "");
+
+	    PREFETCH ();
+	    c = TRANSLATE (*d); /* The character to match.  */
+
+	    /* Cast to `unsigned' instead of `unsigned char' in case the
+	       bit list is a full 32 bytes long.  */
+	    if (c < (unsigned) (*p * BYTEWIDTH)
+		&& p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
+	      not = !not;
+
+	    p += 1 + *p;
+
+	    if (!not) goto fail;
+
+	    SET_REGS_MATCHED ();
+	    d++;
+	    break;
+	  }
+
+
+	/* The beginning of a group is represented by start_memory.
+	   The arguments are the register number in the next byte, and the
+	   number of groups inner to this one in the next.  The text
+	   matched within the group is recorded (in the internal
+	   registers data structure) under the register number.  */
+	case start_memory:
+	  DEBUG_PRINT3 ("EXECUTING start_memory %d (%d):\n", *p, p[1]);
+
+	  /* Find out if this group can match the empty string.  */
+	  p1 = p;		/* To send to group_match_null_string_p.  */
+
+	  if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE)
+	    REG_MATCH_NULL_STRING_P (reg_info[*p])
+	      = group_match_null_string_p (&p1, pend, reg_info);
+
+	  /* Save the position in the string where we were the last time
+	     we were at this open-group operator in case the group is
+	     operated upon by a repetition operator, e.g., with `(a*)*b'
+	     against `ab'; then we want to ignore where we are now in
+	     the string in case this attempt to match fails.  */
+	  old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
+			     ? REG_UNSET (regstart[*p]) ? d : regstart[*p]
+			     : regstart[*p];
+	  DEBUG_PRINT2 ("  old_regstart: %d\n",
+			 POINTER_TO_OFFSET (old_regstart[*p]));
+
+	  regstart[*p] = d;
+	  DEBUG_PRINT2 ("  regstart: %d\n", POINTER_TO_OFFSET (regstart[*p]));
+
+	  IS_ACTIVE (reg_info[*p]) = 1;
+	  MATCHED_SOMETHING (reg_info[*p]) = 0;
+
+	  /* This is the new highest active register.  */
+	  highest_active_reg = *p;
+
+	  /* If nothing was active before, this is the new lowest active
+	     register.  */
+	  if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
+	    lowest_active_reg = *p;
+
+	  /* Move past the register number and inner group count.  */
+	  p += 2;
+	  break;
+
+
+	/* The stop_memory opcode represents the end of a group.  Its
+	   arguments are the same as start_memory's: the register
+	   number, and the number of inner groups.  */
+	case stop_memory:
+	  DEBUG_PRINT3 ("EXECUTING stop_memory %d (%d):\n", *p, p[1]);
+
+	  /* We need to save the string position the last time we were at
+	     this close-group operator in case the group is operated
+	     upon by a repetition operator, e.g., with `((a*)*(b*)*)*'
+	     against `aba'; then we want to ignore where we are now in
+	     the string in case this attempt to match fails.  */
+	  old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
+			   ? REG_UNSET (regend[*p]) ? d : regend[*p]
+			   : regend[*p];
+	  DEBUG_PRINT2 ("      old_regend: %d\n",
+			 POINTER_TO_OFFSET (old_regend[*p]));
+
+	  regend[*p] = d;
+	  DEBUG_PRINT2 ("      regend: %d\n", POINTER_TO_OFFSET (regend[*p]));
+
+	  /* This register isn't active anymore.  */
+	  IS_ACTIVE (reg_info[*p]) = 0;
+
+	  /* If this was the only register active, nothing is active
+	     anymore.  */
+	  if (lowest_active_reg == highest_active_reg)
+	    {
+	      lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+	      highest_active_reg = NO_HIGHEST_ACTIVE_REG;
+	    }
+	  else
+	    { /* We must scan for the new highest active register, since
+		 it isn't necessarily one less than now: consider
+		 (a(b)c(d(e)f)g).  When group 3 ends, after the f), the
+		 new highest active register is 1.  */
+	      unsigned char r = *p - 1;
+	      while (r > 0 && !IS_ACTIVE (reg_info[r]))
+		r--;
+
+	      /* If we end up at register zero, that means that we saved
+		 the registers as the result of an `on_failure_jump', not
+		 a `start_memory', and we jumped to past the innermost
+		 `stop_memory'.  For example, in ((.)*) we save
+		 registers 1 and 2 as a result of the *, but when we pop
+		 back to the second ), we are at the stop_memory 1.
+		 Thus, nothing is active.  */
+	      if (r == 0)
+		{
+		  lowest_active_reg = NO_LOWEST_ACTIVE_REG;
+		  highest_active_reg = NO_HIGHEST_ACTIVE_REG;
+		}
+	      else
+		highest_active_reg = r;
+	    }
+
+	  /* If just failed to match something this time around with a
+	     group that's operated on by a repetition operator, try to
+	     force exit from the ``loop'', and restore the register
+	     information for this group that we had before trying this
+	     last match.  */
+	  if ((!MATCHED_SOMETHING (reg_info[*p])
+	       || (re_opcode_t) p[-3] == start_memory)
+	      && (p + 2) < pend)
+	    {
+	      boolean is_a_jump_n = false;
+
+	      p1 = p + 2;
+	      mcnt = 0;
+	      switch ((re_opcode_t) *p1++)
+		{
+		  case jump_n:
+		    is_a_jump_n = true;
+		  case pop_failure_jump:
+		  case maybe_pop_jump:
+		  case jump:
+		  case dummy_failure_jump:
+		    EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+		    if (is_a_jump_n)
+		      p1 += 2;
+		    break;
+
+		  default:
+		    /* do nothing */ ;
+		}
+	      p1 += mcnt;
+
+	      /* If the next operation is a jump backwards in the pattern
+		 to an on_failure_jump right before the start_memory
+		 corresponding to this stop_memory, exit from the loop
+		 by forcing a failure after pushing on the stack the
+		 on_failure_jump's jump in the pattern, and d.  */
+	      if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump
+		  && (re_opcode_t) p1[3] == start_memory && p1[4] == *p)
+		{
+		  /* If this group ever matched anything, then restore
+		     what its registers were before trying this last
+		     failed match, e.g., with `(a*)*b' against `ab' for
+		     regstart[1], and, e.g., with `((a*)*(b*)*)*'
+		     against `aba' for regend[3].
+
+		     Also restore the registers for inner groups for,
+		     e.g., `((a*)(b*))*' against `aba' (register 3 would
+		     otherwise get trashed).  */
+
+		  if (EVER_MATCHED_SOMETHING (reg_info[*p]))
+		    {
+		      unsigned r;
+
+		      EVER_MATCHED_SOMETHING (reg_info[*p]) = 0;
+
+		      /* Restore this and inner groups' (if any) registers.  */
+		      for (r = *p; r < *p + *(p + 1); r++)
+			{
+			  regstart[r] = old_regstart[r];
+
+			  /* xx why this test?  */
+			  if ((int) old_regend[r] >= (int) regstart[r])
+			    regend[r] = old_regend[r];
+			}
+		    }
+		  p1++;
+		  EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+		  PUSH_FAILURE_POINT (p1 + mcnt, d, -2);
+
+		  goto fail;
+		}
+	    }
+
+	  /* Move past the register number and the inner group count.  */
+	  p += 2;
+	  break;
+
+
+	/* \<digit> has been turned into a `duplicate' command which is
+	   followed by the numeric value of <digit> as the register number.  */
+	case duplicate:
+	  {
+	    register const char *d2, *dend2;
+	    int regno = *p++;   /* Get which register to match against.  */
+	    DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno);
+
+	    /* Can't back reference a group which we've never matched.  */
+	    if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno]))
+	      goto fail;
+
+	    /* Where in input to try to start matching.  */
+	    d2 = regstart[regno];
+
+	    /* Where to stop matching; if both the place to start and
+	       the place to stop matching are in the same string, then
+	       set to the place to stop, otherwise, for now have to use
+	       the end of the first string.  */
+
+	    dend2 = ((FIRST_STRING_P (regstart[regno])
+		      == FIRST_STRING_P (regend[regno]))
+		     ? regend[regno] : end_match_1);
+	    for (;;)
+	      {
+		/* If necessary, advance to next segment in register
+		   contents.  */
+		while (d2 == dend2)
+		  {
+		    if (dend2 == end_match_2) break;
+		    if (dend2 == regend[regno]) break;
+
+		    /* End of string1 => advance to string2. */
+		    d2 = string2;
+		    dend2 = regend[regno];
+		  }
+		/* At end of register contents => success */
+		if (d2 == dend2) break;
+
+		/* If necessary, advance to next segment in data.  */
+		PREFETCH ();
+
+		/* How many characters left in this segment to match.  */
+		mcnt = dend - d;
+
+		/* Want how many consecutive characters we can match in
+		   one shot, so, if necessary, adjust the count.  */
+		if (mcnt > dend2 - d2)
+		  mcnt = dend2 - d2;
+
+		/* Compare that many; failure if mismatch, else move
+		   past them.  */
+		if (translate
+		    ? bcmp_translate (d, d2, mcnt, translate)
+		    : bcmp (d, d2, mcnt))
+		  goto fail;
+		d += mcnt, d2 += mcnt;
+	      }
+	  }
+	  break;
+
+
+	/* begline matches the empty string at the beginning of the string
+	   (unless `not_bol' is set in `bufp'), and, if
+	   `newline_anchor' is set, after newlines.  */
+	case begline:
+	  DEBUG_PRINT1 ("EXECUTING begline.\n");
+
+	  if (AT_STRINGS_BEG (d))
+	    {
+	      if (!bufp->not_bol) break;
+	    }
+	  else if (d[-1] == '\n' && bufp->newline_anchor)
+	    {
+	      break;
+	    }
+	  /* In all other cases, we fail.  */
+	  goto fail;
+
+
+	/* endline is the dual of begline.  */
+	case endline:
+	  DEBUG_PRINT1 ("EXECUTING endline.\n");
+
+	  if (AT_STRINGS_END (d))
+	    {
+	      if (!bufp->not_eol) break;
+	    }
+
+	  /* We have to ``prefetch'' the next character.  */
+	  else if ((d == end1 ? *string2 : *d) == '\n'
+		   && bufp->newline_anchor)
+	    {
+	      break;
+	    }
+	  goto fail;
+
+
+	/* Match at the very beginning of the data.  */
+	case begbuf:
+	  DEBUG_PRINT1 ("EXECUTING begbuf.\n");
+	  if (AT_STRINGS_BEG (d))
+	    break;
+	  goto fail;
+
+
+	/* Match at the very end of the data.  */
+	case endbuf:
+	  DEBUG_PRINT1 ("EXECUTING endbuf.\n");
+	  if (AT_STRINGS_END (d))
+	    break;
+	  goto fail;
+
+
+	/* on_failure_keep_string_jump is used to optimize `.*\n'.  It
+	   pushes NULL as the value for the string on the stack.  Then
+	   `pop_failure_point' will keep the current value for the
+	   string, instead of restoring it.  To see why, consider
+	   matching `foo\nbar' against `.*\n'.  The .* matches the foo;
+	   then the . fails against the \n.  But the next thing we want
+	   to do is match the \n against the \n; if we restored the
+	   string value, we would be back at the foo.
+
+	   Because this is used only in specific cases, we don't need to
+	   check all the things that `on_failure_jump' does, to make
+	   sure the right things get saved on the stack.  Hence we don't
+	   share its code.  The only reason to push anything on the
+	   stack at all is that otherwise we would have to change
+	   `anychar's code to do something besides goto fail in this
+	   case; that seems worse than this.  */
+	case on_failure_keep_string_jump:
+	  DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump");
+
+	  EXTRACT_NUMBER_AND_INCR (mcnt, p);
+	  DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt);
+
+	  PUSH_FAILURE_POINT (p + mcnt, NULL, -2);
+	  break;
+
+
+	/* Uses of on_failure_jump:
+
+	   Each alternative starts with an on_failure_jump that points
+	   to the beginning of the next alternative.  Each alternative
+	   except the last ends with a jump that in effect jumps past
+	   the rest of the alternatives.  (They really jump to the
+	   ending jump of the following alternative, because tensioning
+	   these jumps is a hassle.)
+
+	   Repeats start with an on_failure_jump that points past both
+	   the repetition text and either the following jump or
+	   pop_failure_jump back to this on_failure_jump.  */
+	case on_failure_jump:
+	on_failure:
+	  DEBUG_PRINT1 ("EXECUTING on_failure_jump");
+
+	  EXTRACT_NUMBER_AND_INCR (mcnt, p);
+	  DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt);
+
+	  /* If this on_failure_jump comes right before a group (i.e.,
+	     the original * applied to a group), save the information
+	     for that group and all inner ones, so that if we fail back
+	     to this point, the group's information will be correct.
+	     For example, in \(a*\)*\1, we need the preceding group,
+	     and in \(\(a*\)b*\)\2, we need the inner group.  */
+
+	  /* We can't use `p' to check ahead because we push
+	     a failure point to `p + mcnt' after we do this.  */
+	  p1 = p;
+
+	  /* We need to skip no_op's before we look for the
+	     start_memory in case this on_failure_jump is happening as
+	     the result of a completed succeed_n, as in \(a\)\{1,3\}b\1
+	     against aba.  */
+	  while (p1 < pend && (re_opcode_t) *p1 == no_op)
+	    p1++;
+
+	  if (p1 < pend && (re_opcode_t) *p1 == start_memory)
+	    {
+	      /* We have a new highest active register now.  This will
+		 get reset at the start_memory we are about to get to,
+		 but we will have saved all the registers relevant to
+		 this repetition op, as described above.  */
+	      highest_active_reg = *(p1 + 1) + *(p1 + 2);
+	      if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
+		lowest_active_reg = *(p1 + 1);
+	    }
+
+	  DEBUG_PRINT1 (":\n");
+	  PUSH_FAILURE_POINT (p + mcnt, d, -2);
+	  break;
+
+
+	/* A smart repeat ends with `maybe_pop_jump'.
+	   We change it to either `pop_failure_jump' or `jump'.  */
+	case maybe_pop_jump:
+	  EXTRACT_NUMBER_AND_INCR (mcnt, p);
+	  DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt);
+	  {
+	    register unsigned char *p2 = p;
+
+	    /* Compare the beginning of the repeat with what in the
+	       pattern follows its end. If we can establish that there
+	       is nothing that they would both match, i.e., that we
+	       would have to backtrack because of (as in, e.g., `a*a')
+	       then we can change to pop_failure_jump, because we'll
+	       never have to backtrack.
+
+	       This is not true in the case of alternatives: in
+	       `(a|ab)*' we do need to backtrack to the `ab' alternative
+	       (e.g., if the string was `ab').  But instead of trying to
+	       detect that here, the alternative has put on a dummy
+	       failure point which is what we will end up popping.  */
+
+	    /* Skip over open/close-group commands.  */
+	    while (p2 + 2 < pend
+		   && ((re_opcode_t) *p2 == stop_memory
+		       || (re_opcode_t) *p2 == start_memory))
+	      p2 += 3;			/* Skip over args, too.  */
+
+	    /* If we're at the end of the pattern, we can change.  */
+	    if (p2 == pend)
+	      {
+		/* Consider what happens when matching ":\(.*\)"
+		   against ":/".  I don't really understand this code
+		   yet.  */
+		p[-3] = (unsigned char) pop_failure_jump;
+		DEBUG_PRINT1
+		  ("  End of pattern: change to `pop_failure_jump'.\n");
+	      }
+
+	    else if ((re_opcode_t) *p2 == exactn
+		     || (bufp->newline_anchor && (re_opcode_t) *p2 == endline))
+	      {
+		register unsigned char c
+		  = *p2 == (unsigned char) endline ? '\n' : p2[2];
+		p1 = p + mcnt;
+
+		/* p1[0] ... p1[2] are the `on_failure_jump' corresponding
+		   to the `maybe_finalize_jump' of this case.  Examine what
+		   follows.  */
+		if ((re_opcode_t) p1[3] == exactn && p1[5] != c)
+		  {
+		    p[-3] = (unsigned char) pop_failure_jump;
+		    DEBUG_PRINT3 ("  %c != %c => pop_failure_jump.\n",
+				  c, p1[5]);
+		  }
+
+		else if ((re_opcode_t) p1[3] == charset
+			 || (re_opcode_t) p1[3] == charset_not)
+		  {
+		    int not = (re_opcode_t) p1[3] == charset_not;
+
+		    if (c < (unsigned char) (p1[4] * BYTEWIDTH)
+			&& p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
+		      not = !not;
+
+		    /* `not' is equal to 1 if c would match, which means
+			that we can't change to pop_failure_jump.  */
+		    if (!not)
+		      {
+			p[-3] = (unsigned char) pop_failure_jump;
+			DEBUG_PRINT1 ("  No match => pop_failure_jump.\n");
+		      }
+		  }
+	      }
+	  }
+	  p -= 2;		/* Point at relative address again.  */
+	  if ((re_opcode_t) p[-1] != pop_failure_jump)
+	    {
+	      p[-1] = (unsigned char) jump;
+	      DEBUG_PRINT1 ("  Match => jump.\n");
+	      goto unconditional_jump;
+	    }
+	/* Note fall through.  */
+
+
+	/* The end of a simple repeat has a pop_failure_jump back to
+	   its matching on_failure_jump, where the latter will push a
+	   failure point.  The pop_failure_jump takes off failure
+	   points put on by this pop_failure_jump's matching
+	   on_failure_jump; we got through the pattern to here from the
+	   matching on_failure_jump, so didn't fail.  */
+	case pop_failure_jump:
+	  {
+	    /* We need to pass separate storage for the lowest and
+	       highest registers, even though we don't care about the
+	       actual values.  Otherwise, we will restore only one
+	       register from the stack, since lowest will == highest in
+	       `pop_failure_point'.  */
+	    unsigned dummy_low_reg, dummy_high_reg;
+	    unsigned char *pdummy;
+	    const char *sdummy;
+
+	    DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n");
+	    POP_FAILURE_POINT (sdummy, pdummy,
+			       dummy_low_reg, dummy_high_reg,
+			       reg_dummy, reg_dummy, reg_info_dummy);
+	  }
+	  /* Note fall through.  */
+
+
+	/* Unconditionally jump (without popping any failure points).  */
+	case jump:
+	unconditional_jump:
+	  EXTRACT_NUMBER_AND_INCR (mcnt, p);	/* Get the amount to jump.  */
+	  DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt);
+	  p += mcnt;				/* Do the jump.  */
+	  DEBUG_PRINT2 ("(to 0x%x).\n", p);
+	  break;
+
+
+	/* We need this opcode so we can detect where alternatives end
+	   in `group_match_null_string_p' et al.  */
+	case jump_past_alt:
+	  DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n");
+	  goto unconditional_jump;
+
+
+	/* Normally, the on_failure_jump pushes a failure point, which
+	   then gets popped at pop_failure_jump.  We will end up at
+	   pop_failure_jump, also, and with a pattern of, say, `a+', we
+	   are skipping over the on_failure_jump, so we have to push
+	   something meaningless for pop_failure_jump to pop.  */
+	case dummy_failure_jump:
+	  DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n");
+	  /* It doesn't matter what we push for the string here.  What
+	     the code at `fail' tests is the value for the pattern.  */
+	  PUSH_FAILURE_POINT (0, 0, -2);
+	  goto unconditional_jump;
+
+
+	/* At the end of an alternative, we need to push a dummy failure
+	   point in case we are followed by a `pop_failure_jump', because
+	   we don't want the failure point for the alternative to be
+	   popped.  For example, matching `(a|ab)*' against `aab'
+	   requires that we match the `ab' alternative.  */
+	case push_dummy_failure:
+	  DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n");
+	  /* See comments just above at `dummy_failure_jump' about the
+	     two zeroes.  */
+	  PUSH_FAILURE_POINT (0, 0, -2);
+	  break;
+
+	/* Have to succeed matching what follows at least n times.
+	   After that, handle like `on_failure_jump'.  */
+	case succeed_n:
+	  EXTRACT_NUMBER (mcnt, p + 2);
+	  DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt);
+
+	  assert (mcnt >= 0);
+	  /* Originally, this is how many times we HAVE to succeed.  */
+	  if (mcnt > 0)
+	    {
+	       mcnt--;
+	       p += 2;
+	       STORE_NUMBER_AND_INCR (p, mcnt);
+	       DEBUG_PRINT3 ("  Setting 0x%x to %d.\n", p, mcnt);
+	    }
+	  else if (mcnt == 0)
+	    {
+	      DEBUG_PRINT2 ("  Setting two bytes from 0x%x to no_op.\n", p+2);
+	      p[2] = (unsigned char) no_op;
+	      p[3] = (unsigned char) no_op;
+	      goto on_failure;
+	    }
+	  break;
+
+	case jump_n:
+	  EXTRACT_NUMBER (mcnt, p + 2);
+	  DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt);
+
+	  /* Originally, this is how many times we CAN jump.  */
+	  if (mcnt)
+	    {
+	       mcnt--;
+	       STORE_NUMBER (p + 2, mcnt);
+	       goto unconditional_jump;
+	    }
+	  /* If don't have to jump any more, skip over the rest of command.  */
+	  else
+	    p += 4;
+	  break;
+
+	case set_number_at:
+	  {
+	    DEBUG_PRINT1 ("EXECUTING set_number_at.\n");
+
+	    EXTRACT_NUMBER_AND_INCR (mcnt, p);
+	    p1 = p + mcnt;
+	    EXTRACT_NUMBER_AND_INCR (mcnt, p);
+	    DEBUG_PRINT3 ("  Setting 0x%x to %d.\n", p1, mcnt);
+	    STORE_NUMBER (p1, mcnt);
+	    break;
+	  }
+
+	case wordbound:
+	  DEBUG_PRINT1 ("EXECUTING wordbound.\n");
+	  if (AT_WORD_BOUNDARY (d))
+	    break;
+	  goto fail;
+
+	case notwordbound:
+	  DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
+	  if (AT_WORD_BOUNDARY (d))
+	    goto fail;
+	  break;
+
+	case wordbeg:
+	  DEBUG_PRINT1 ("EXECUTING wordbeg.\n");
+	  if (WORDCHAR_P (d) && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1)))
+	    break;
+	  goto fail;
+
+	case wordend:
+	  DEBUG_PRINT1 ("EXECUTING wordend.\n");
+	  if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1)
+	      && (!WORDCHAR_P (d) || AT_STRINGS_END (d)))
+	    break;
+	  goto fail;
+
+#ifdef emacs
+#ifdef emacs19
+	case before_dot:
+	  DEBUG_PRINT1 ("EXECUTING before_dot.\n");
+	  if (PTR_CHAR_POS ((unsigned char *) d) >= point)
+	    goto fail;
+	  break;
+
+	case at_dot:
+	  DEBUG_PRINT1 ("EXECUTING at_dot.\n");
+	  if (PTR_CHAR_POS ((unsigned char *) d) != point)
+	    goto fail;
+	  break;
+
+	case after_dot:
+	  DEBUG_PRINT1 ("EXECUTING after_dot.\n");
+	  if (PTR_CHAR_POS ((unsigned char *) d) <= point)
+	    goto fail;
+	  break;
+#else /* not emacs19 */
+	case at_dot:
+	  DEBUG_PRINT1 ("EXECUTING at_dot.\n");
+	  if (PTR_CHAR_POS ((unsigned char *) d) + 1 != point)
+	    goto fail;
+	  break;
+#endif /* not emacs19 */
+
+	case syntaxspec:
+	  DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt);
+	  mcnt = *p++;
+	  goto matchsyntax;
+
+	case wordchar:
+	  DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n");
+	  mcnt = (int) Sword;
+	matchsyntax:
+	  PREFETCH ();
+	  if (SYNTAX (*d++) != (enum syntaxcode) mcnt)
+	    goto fail;
+	  SET_REGS_MATCHED ();
+	  break;
+
+	case notsyntaxspec:
+	  DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt);
+	  mcnt = *p++;
+	  goto matchnotsyntax;
+
+	case notwordchar:
+	  DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n");
+	  mcnt = (int) Sword;
+	matchnotsyntax:
+	  PREFETCH ();
+	  if (SYNTAX (*d++) == (enum syntaxcode) mcnt)
+	    goto fail;
+	  SET_REGS_MATCHED ();
+	  break;
+
+#else /* not emacs */
+	case wordchar:
+	  DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n");
+	  PREFETCH ();
+	  if (!WORDCHAR_P (d))
+	    goto fail;
+	  SET_REGS_MATCHED ();
+	  d++;
+	  break;
+
+	case notwordchar:
+	  DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n");
+	  PREFETCH ();
+	  if (WORDCHAR_P (d))
+	    goto fail;
+	  SET_REGS_MATCHED ();
+	  d++;
+	  break;
+#endif /* not emacs */
+
+	default:
+	  abort ();
+	}
+      continue;  /* Successfully executed one pattern command; keep going.  */
+
+
+    /* We goto here if a matching operation fails. */
+    fail:
+      if (!FAIL_STACK_EMPTY ())
+	{ /* A restart point is known.  Restore to that state.  */
+	  DEBUG_PRINT1 ("\nFAIL:\n");
+	  POP_FAILURE_POINT (d, p,
+			     lowest_active_reg, highest_active_reg,
+			     regstart, regend, reg_info);
+
+	  /* If this failure point is a dummy, try the next one.  */
+	  if (!p)
+	    goto fail;
+
+	  /* If we failed to the end of the pattern, don't examine *p.  */
+	  assert (p <= pend);
+	  if (p < pend)
+	    {
+	      boolean is_a_jump_n = false;
+
+	      /* If failed to a backwards jump that's part of a repetition
+		 loop, need to pop this failure point and use the next one.  */
+	      switch ((re_opcode_t) *p)
+		{
+		case jump_n:
+		  is_a_jump_n = true;
+		case maybe_pop_jump:
+		case pop_failure_jump:
+		case jump:
+		  p1 = p + 1;
+		  EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+		  p1 += mcnt;
+
+		  if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n)
+		      || (!is_a_jump_n
+			  && (re_opcode_t) *p1 == on_failure_jump))
+		    goto fail;
+		  break;
+		default:
+		  /* do nothing */ ;
+		}
+	    }
+
+	  if (d >= string1 && d <= end1)
+	    dend = end_match_1;
+	}
+      else
+	break;   /* Matching at this starting point really fails.  */
+    } /* for (;;) */
+
+  if (best_regs_set)
+    goto restore_best_regs;
+
+  FREE_VARIABLES ();
+
+  return -1;         			/* Failure to match.  */
+} /* re_match_2 */
+
+/* Subroutine definitions for re_match_2.  */
+
+
+/* We are passed P pointing to a register number after a start_memory.
+
+   Return true if the pattern up to the corresponding stop_memory can
+   match the empty string, and false otherwise.
+
+   If we find the matching stop_memory, sets P to point to one past its number.
+   Otherwise, sets P to an undefined byte less than or equal to END.
+
+   We don't handle duplicates properly (yet).  */
+
+static boolean
+group_match_null_string_p (p, end, reg_info)
+    unsigned char **p, *end;
+    register_info_type *reg_info;
+{
+  int mcnt;
+  /* Point to after the args to the start_memory.  */
+  unsigned char *p1 = *p + 2;
+
+  while (p1 < end)
+    {
+      /* Skip over opcodes that can match nothing, and return true or
+	 false, as appropriate, when we get to one that can't, or to the
+	 matching stop_memory.  */
+
+      switch ((re_opcode_t) *p1)
+	{
+	/* Could be either a loop or a series of alternatives.  */
+	case on_failure_jump:
+	  p1++;
+	  EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+
+	  /* If the next operation is not a jump backwards in the
+	     pattern.  */
+
+	  if (mcnt >= 0)
+	    {
+	      /* Go through the on_failure_jumps of the alternatives,
+		 seeing if any of the alternatives cannot match nothing.
+		 The last alternative starts with only a jump,
+		 whereas the rest start with on_failure_jump and end
+		 with a jump, e.g., here is the pattern for `a|b|c':
+
+		 /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6
+		 /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3
+		 /exactn/1/c
+
+		 So, we have to first go through the first (n-1)
+		 alternatives and then deal with the last one separately.  */
+
+
+	      /* Deal with the first (n-1) alternatives, which start
+		 with an on_failure_jump (see above) that jumps to right
+		 past a jump_past_alt.  */
+
+	      while ((re_opcode_t) p1[mcnt-3] == jump_past_alt)
+		{
+		  /* `mcnt' holds how many bytes long the alternative
+		     is, including the ending `jump_past_alt' and
+		     its number.  */
+
+		  if (!alt_match_null_string_p (p1, p1 + mcnt - 3,
+						      reg_info))
+		    return false;
+
+		  /* Move to right after this alternative, including the
+		     jump_past_alt.  */
+		  p1 += mcnt;
+
+		  /* Break if it's the beginning of an n-th alternative
+		     that doesn't begin with an on_failure_jump.  */
+		  if ((re_opcode_t) *p1 != on_failure_jump)
+		    break;
+
+		  /* Still have to check that it's not an n-th
+		     alternative that starts with an on_failure_jump.  */
+		  p1++;
+		  EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+		  if ((re_opcode_t) p1[mcnt-3] != jump_past_alt)
+		    {
+		      /* Get to the beginning of the n-th alternative.  */
+		      p1 -= 3;
+		      break;
+		    }
+		}
+
+	      /* Deal with the last alternative: go back and get number
+		 of the `jump_past_alt' just before it.  `mcnt' contains
+		 the length of the alternative.  */
+	      EXTRACT_NUMBER (mcnt, p1 - 2);
+
+	      if (!alt_match_null_string_p (p1, p1 + mcnt, reg_info))
+		return false;
+
+	      p1 += mcnt;	/* Get past the n-th alternative.  */
+	    } /* if mcnt > 0 */
+	  break;
+
+
+	case stop_memory:
+	  assert (p1[1] == **p);
+	  *p = p1 + 2;
+	  return true;
+
+
+	default:
+	  if (!common_op_match_null_string_p (&p1, end, reg_info))
+	    return false;
+	}
+    } /* while p1 < end */
+
+  return false;
+} /* group_match_null_string_p */
+
+
+/* Similar to group_match_null_string_p, but doesn't deal with alternatives:
+   It expects P to be the first byte of a single alternative and END one
+   byte past the last. The alternative can contain groups.  */
+
+static boolean
+alt_match_null_string_p (p, end, reg_info)
+    unsigned char *p, *end;
+    register_info_type *reg_info;
+{
+  int mcnt;
+  unsigned char *p1 = p;
+
+  while (p1 < end)
+    {
+      /* Skip over opcodes that can match nothing, and break when we get
+	 to one that can't.  */
+
+      switch ((re_opcode_t) *p1)
+	{
+	/* It's a loop.  */
+	case on_failure_jump:
+	  p1++;
+	  EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+	  p1 += mcnt;
+	  break;
+
+	default:
+	  if (!common_op_match_null_string_p (&p1, end, reg_info))
+	    return false;
+	}
+    }  /* while p1 < end */
+
+  return true;
+} /* alt_match_null_string_p */
+
+
+/* Deals with the ops common to group_match_null_string_p and
+   alt_match_null_string_p.
+
+   Sets P to one after the op and its arguments, if any.  */
+
+static boolean
+common_op_match_null_string_p (p, end, reg_info)
+    unsigned char **p, *end;
+    register_info_type *reg_info;
+{
+  int mcnt;
+  boolean ret;
+  int reg_no;
+  unsigned char *p1 = *p;
+
+  switch ((re_opcode_t) *p1++)
+    {
+    case no_op:
+    case begline:
+    case endline:
+    case begbuf:
+    case endbuf:
+    case wordbeg:
+    case wordend:
+    case wordbound:
+    case notwordbound:
+#ifdef emacs
+    case before_dot:
+    case at_dot:
+    case after_dot:
+#endif
+      break;
+
+    case start_memory:
+      reg_no = *p1;
+      assert (reg_no > 0 && reg_no <= MAX_REGNUM);
+      ret = group_match_null_string_p (&p1, end, reg_info);
+
+      /* Have to set this here in case we're checking a group which
+	 contains a group and a back reference to it.  */
+
+      if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE)
+	REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret;
+
+      if (!ret)
+	return false;
+      break;
+
+    /* If this is an optimized succeed_n for zero times, make the jump.  */
+    case jump:
+      EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+      if (mcnt >= 0)
+	p1 += mcnt;
+      else
+	return false;
+      break;
+
+    case succeed_n:
+      /* Get to the number of times to succeed.  */
+      p1 += 2;
+      EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+
+      if (mcnt == 0)
+	{
+	  p1 -= 4;
+	  EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+	  p1 += mcnt;
+	}
+      else
+	return false;
+      break;
+
+    case duplicate:
+      if (!REG_MATCH_NULL_STRING_P (reg_info[*p1]))
+	return false;
+      break;
+
+    case set_number_at:
+      p1 += 4;
+
+    default:
+      /* All other opcodes mean we cannot match the empty string.  */
+      return false;
+  }
+
+  *p = p1;
+  return true;
+} /* common_op_match_null_string_p */
+
+
+/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN
+   bytes; nonzero otherwise.  */
+
+static int
+bcmp_translate(
+     unsigned char *s1,
+     unsigned char *s2,
+     int len,
+     char *translate
+)
+{
+  register unsigned char *p1 = s1, *p2 = s2;
+  while (len)
+    {
+      if (translate[*p1++] != translate[*p2++]) return 1;
+      len--;
+    }
+  return 0;
+}
+
+/* Entry points for GNU code.  */
+
+/* re_compile_pattern is the GNU regular expression compiler: it
+   compiles PATTERN (of length SIZE) and puts the result in BUFP.
+   Returns 0 if the pattern was valid, otherwise an error string.
+
+   Assumes the `allocated' (and perhaps `buffer') and `translate' fields
+   are set in BUFP on entry.
+
+   We call regex_compile to do the actual compilation.  */
+
+const char *
+re_compile_pattern (pattern, length, bufp)
+     const char *pattern;
+     int length;
+     struct re_pattern_buffer *bufp;
+{
+  reg_errcode_t ret;
+
+  /* GNU code is written to assume at least RE_NREGS registers will be set
+     (and at least one extra will be -1).  */
+  bufp->regs_allocated = REGS_UNALLOCATED;
+
+  /* And GNU code determines whether or not to get register information
+     by passing null for the REGS argument to re_match, etc., not by
+     setting no_sub.  */
+  bufp->no_sub = 0;
+
+  /* Match anchors at newline.  */
+  bufp->newline_anchor = 1;
+
+  ret = regex_compile (pattern, length, re_syntax_options, bufp);
+
+  return re_error_msg[(int) ret];
+}
+
+/* Entry points compatible with 4.2 BSD regex library.  We don't define
+   them if this is an Emacs or POSIX compilation.  */
+
+#if !defined (emacs) && !defined (_POSIX_SOURCE)
+
+/* BSD has one and only one pattern buffer.  */
+static struct re_pattern_buffer re_comp_buf;
+
+char *
+re_comp (s)
+    const char *s;
+{
+  reg_errcode_t ret;
+
+  if (!s)
+    {
+      if (!re_comp_buf.buffer)
+	return "No previous regular expression";
+      return 0;
+    }
+
+  if (!re_comp_buf.buffer)
+    {
+      re_comp_buf.buffer = (unsigned char *) malloc (200);
+      if (re_comp_buf.buffer == NULL)
+	return "Memory exhausted";
+      re_comp_buf.allocated = 200;
+
+      re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH);
+      if (re_comp_buf.fastmap == NULL)
+	return "Memory exhausted";
+    }
+
+  /* Since `re_exec' always passes NULL for the `regs' argument, we
+     don't need to initialize the pattern buffer fields which affect it.  */
+
+  /* Match anchors at newlines.  */
+  re_comp_buf.newline_anchor = 1;
+
+  ret = regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf);
+
+  /* Yes, we're discarding `const' here.  */
+  return (char *) re_error_msg[(int) ret];
+}
+
+
+int
+re_exec (s)
+    const char *s;
+{
+  const int len = strlen (s);
+  return
+    0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0);
+}
+#endif /* not emacs and not _POSIX_SOURCE */
+
+/* POSIX.2 functions.  Don't define these for Emacs.  */
+
+#ifndef emacs
+
+/* regcomp takes a regular expression as a string and compiles it.
+
+   PREG is a regex_t *.  We do not expect any fields to be initialized,
+   since POSIX says we shouldn't.  Thus, we set
+
+     `buffer' to the compiled pattern;
+     `used' to the length of the compiled pattern;
+     `syntax' to RE_SYNTAX_POSIX_EXTENDED if the
+       REG_EXTENDED bit in CFLAGS is set; otherwise, to
+       RE_SYNTAX_POSIX_BASIC;
+     `newline_anchor' to REG_NEWLINE being set in CFLAGS;
+     `fastmap' and `fastmap_accurate' to zero;
+     `re_nsub' to the number of subexpressions in PATTERN.
+
+   PATTERN is the address of the pattern string.
+
+   CFLAGS is a series of bits which affect compilation.
+
+     If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we
+     use POSIX basic syntax.
+
+     If REG_NEWLINE is set, then . and [^...] don't match newline.
+     Also, regexec will try a match beginning after every newline.
+
+     If REG_ICASE is set, then we considers upper- and lowercase
+     versions of letters to be equivalent when matching.
+
+     If REG_NOSUB is set, then when PREG is passed to regexec, that
+     routine will report only success or failure, and nothing about the
+     registers.
+
+   It returns 0 if it succeeds, nonzero if it doesn't.  (See regex.h for
+   the return codes and their meanings.)  */
+
+int
+regcomp (preg, pattern, cflags)
+    regex_t *preg;
+    const char *pattern;
+    int cflags;
+{
+  reg_errcode_t ret;
+  unsigned syntax
+    = (cflags & REG_EXTENDED) ?
+      RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC;
+
+  /* regex_compile will allocate the space for the compiled pattern.  */
+  preg->buffer = 0;
+  preg->allocated = 0;
+
+  /* Don't bother to use a fastmap when searching.  This simplifies the
+     REG_NEWLINE case: if we used a fastmap, we'd have to put all the
+     characters after newlines into the fastmap.  This way, we just try
+     every character.  */
+  preg->fastmap = 0;
+
+  if (cflags & REG_ICASE)
+    {
+      unsigned i;
+
+      preg->translate = (char *) malloc (CHAR_SET_SIZE);
+      if (preg->translate == NULL)
+	return (int) REG_ESPACE;
+
+      /* Map uppercase characters to corresponding lowercase ones.  */
+      for (i = 0; i < CHAR_SET_SIZE; i++)
+	preg->translate[i] = ISUPPER (i) ? tolower (i) : i;
+    }
+  else
+    preg->translate = NULL;
+
+  /* If REG_NEWLINE is set, newlines are treated differently.  */
+  if (cflags & REG_NEWLINE)
+    { /* REG_NEWLINE implies neither . nor [^...] match newline.  */
+      syntax &= ~RE_DOT_NEWLINE;
+      syntax |= RE_HAT_LISTS_NOT_NEWLINE;
+      /* It also changes the matching behavior.  */
+      preg->newline_anchor = 1;
+    }
+  else
+    preg->newline_anchor = 0;
+
+  preg->no_sub = !!(cflags & REG_NOSUB);
+
+  /* POSIX says a null character in the pattern terminates it, so we
+     can use strlen here in compiling the pattern.  */
+  ret = regex_compile (pattern, strlen (pattern), syntax, preg);
+
+  /* POSIX doesn't distinguish between an unmatched open-group and an
+     unmatched close-group: both are REG_EPAREN.  */
+  if (ret == REG_ERPAREN) ret = REG_EPAREN;
+
+  return (int) ret;
+}
+
+
+/* regexec searches for a given pattern, specified by PREG, in the
+   string STRING.
+
+   If NMATCH is zero or REG_NOSUB was set in the cflags argument to
+   `regcomp', we ignore PMATCH.  Otherwise, we assume PMATCH has at
+   least NMATCH elements, and we set them to the offsets of the
+   corresponding matched substrings.
+
+   EFLAGS specifies `execution flags' which affect matching: if
+   REG_NOTBOL is set, then ^ does not match at the beginning of the
+   string; if REG_NOTEOL is set, then $ does not match at the end.
+
+   We return 0 if we find a match and REG_NOMATCH if not.  */
+
+int
+regexec (preg, string, nmatch, pmatch, eflags)
+    const regex_t *preg;
+    const char *string;
+    size_t nmatch;
+    regmatch_t pmatch[];
+    int eflags;
+{
+  int ret;
+  struct re_registers regs;
+  regex_t private_preg;
+  int len = strlen (string);
+  boolean want_reg_info = !preg->no_sub && nmatch > 0;
+
+  private_preg = *preg;
+
+  private_preg.not_bol = !!(eflags & REG_NOTBOL);
+  private_preg.not_eol = !!(eflags & REG_NOTEOL);
+
+  /* The user has told us exactly how many registers to return
+     information about, via `nmatch'.  We have to pass that on to the
+     matching routines.  */
+  private_preg.regs_allocated = REGS_FIXED;
+
+  if (want_reg_info)
+    {
+      regs.num_regs = nmatch;
+      regs.start = TALLOC (nmatch, regoff_t);
+      regs.end = TALLOC (nmatch, regoff_t);
+      if (regs.start == NULL || regs.end == NULL)
+	return (int) REG_NOMATCH;
+    }
+
+  /* Perform the searching operation.  */
+  ret = re_search (&private_preg, string, len,
+		   /* start: */ 0, /* range: */ len,
+		   want_reg_info ? &regs : (struct re_registers *) 0);
+
+  /* Copy the register information to the POSIX structure.  */
+  if (want_reg_info)
+    {
+      if (ret >= 0)
+	{
+	  unsigned r;
+
+	  for (r = 0; r < nmatch; r++)
+	    {
+	      pmatch[r].rm_so = regs.start[r];
+	      pmatch[r].rm_eo = regs.end[r];
+	    }
+	}
+
+      /* If we needed the temporary register info, free the space now.  */
+      free (regs.start);
+      free (regs.end);
+    }
+
+  /* We want zero return to mean success, unlike `re_search'.  */
+  return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH;
+}
+
+
+/* Returns a message corresponding to an error code, ERRCODE, returned
+   from either regcomp or regexec.   We don't use PREG here.  */
+
+size_t
+regerror (errcode, preg, errbuf, errbuf_size)
+    int errcode;
+    const regex_t *preg;
+    char *errbuf;
+    size_t errbuf_size;
+{
+  const char *msg;
+  size_t msg_size;
+
+  if (errcode < 0
+      || errcode >= (sizeof (re_error_msg) / sizeof (re_error_msg[0])))
+    /* Only error codes returned by the rest of the code should be passed
+       to this routine.  If we are given anything else, or if other regex
+       code generates an invalid error code, then the program has a bug.
+       Dump core so we can fix it.  */
+    abort ();
+
+  msg = re_error_msg[errcode];
+
+  /* POSIX doesn't require that we do anything in this case, but why
+     not be nice.  */
+  if (! msg)
+    msg = "Success";
+
+  msg_size = strlen (msg) + 1; /* Includes the null.  */
+
+  if (errbuf_size != 0)
+    {
+      if (msg_size > errbuf_size)
+	{
+	  strncpy (errbuf, msg, errbuf_size - 1);
+	  errbuf[errbuf_size - 1] = 0;
+	}
+      else
+	strcpy (errbuf, msg);
+    }
+
+  return msg_size;
+}
+
+
+/* Free dynamically allocated space used by PREG.  */
+
+void
+regfree (preg)
+    regex_t *preg;
+{
+  if (preg->buffer != NULL)
+    free (preg->buffer);
+  preg->buffer = NULL;
+
+  preg->allocated = 0;
+  preg->used = 0;
+
+  if (preg->fastmap != NULL)
+    free (preg->fastmap);
+  preg->fastmap = NULL;
+  preg->fastmap_accurate = 0;
+
+  if (preg->translate != NULL)
+    free (preg->translate);
+  preg->translate = NULL;
+}
+
+#endif /* not emacs  */
+
+/*
+Local variables:
+make-backup-files: t
+version-control: t
+trim-versions-without-asking: nil
+End:
+*/
diff --git a/compat/regex/regex.h b/compat/regex/regex.h
new file mode 100644
index 0000000..6eb64f1
--- /dev/null
+++ b/compat/regex/regex.h
@@ -0,0 +1,490 @@
+/* Definitions for data structures and routines for the regular
+   expression library, version 0.12.
+
+   Copyright (C) 1985, 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifndef __REGEXP_LIBRARY_H__
+#define __REGEXP_LIBRARY_H__
+
+/* POSIX says that <sys/types.h> must be included (by the caller) before
+   <regex.h>.  */
+
+#ifdef VMS
+/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it
+   should be there.  */
+#include <stddef.h>
+#endif
+
+
+/* The following bits are used to determine the regexp syntax we
+   recognize.  The set/not-set meanings are chosen so that Emacs syntax
+   remains the value 0.  The bits are given in alphabetical order, and
+   the definitions shifted by one from the previous bit; thus, when we
+   add or remove a bit, only one other definition need change.  */
+typedef unsigned reg_syntax_t;
+
+/* If this bit is not set, then \ inside a bracket expression is literal.
+   If set, then such a \ quotes the following character.  */
+#define RE_BACKSLASH_ESCAPE_IN_LISTS (1)
+
+/* If this bit is not set, then + and ? are operators, and \+ and \? are
+     literals.
+   If set, then \+ and \? are operators and + and ? are literals.  */
+#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)
+
+/* If this bit is set, then character classes are supported.  They are:
+     [:alpha:], [:upper:], [:lower:],  [:digit:], [:alnum:], [:xdigit:],
+     [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
+   If not set, then character classes are not supported.  */
+#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
+
+/* If this bit is set, then ^ and $ are always anchors (outside bracket
+     expressions, of course).
+   If this bit is not set, then it depends:
+	^  is an anchor if it is at the beginning of a regular
+	   expression or after an open-group or an alternation operator;
+	$  is an anchor if it is at the end of a regular expression, or
+	   before a close-group or an alternation operator.
+
+   This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because
+   POSIX draft 11.2 says that * etc. in leading positions is undefined.
+   We already implemented a previous draft which made those constructs
+   invalid, though, so we haven't changed the code back.  */
+#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
+
+/* If this bit is set, then special characters are always special
+     regardless of where they are in the pattern.
+   If this bit is not set, then special characters are special only in
+     some contexts; otherwise they are ordinary.  Specifically,
+     * + ? and intervals are only special when not after the beginning,
+     open-group, or alternation operator.  */
+#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
+
+/* If this bit is set, then *, +, ?, and { cannot be first in an re or
+     immediately after an alternation or begin-group operator.  */
+#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
+
+/* If this bit is set, then . matches newline.
+   If not set, then it doesn't.  */
+#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
+
+/* If this bit is set, then . doesn't match NUL.
+   If not set, then it does.  */
+#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
+
+/* If this bit is set, nonmatching lists [^...] do not match newline.
+   If not set, they do.  */
+#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)
+
+/* If this bit is set, either \{...\} or {...} defines an
+     interval, depending on RE_NO_BK_BRACES.
+   If not set, \{, \}, {, and } are literals.  */
+#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
+
+/* If this bit is set, +, ? and | aren't recognized as operators.
+   If not set, they are.  */
+#define RE_LIMITED_OPS (RE_INTERVALS << 1)
+
+/* If this bit is set, newline is an alternation operator.
+   If not set, newline is literal.  */
+#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
+
+/* If this bit is set, then `{...}' defines an interval, and \{ and \}
+     are literals.
+  If not set, then `\{...\}' defines an interval.  */
+#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
+
+/* If this bit is set, (...) defines a group, and \( and \) are literals.
+   If not set, \(...\) defines a group, and ( and ) are literals.  */
+#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
+
+/* If this bit is set, then \<digit> matches <digit>.
+   If not set, then \<digit> is a back-reference.  */
+#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
+
+/* If this bit is set, then | is an alternation operator, and \| is literal.
+   If not set, then \| is an alternation operator, and | is literal.  */
+#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
+
+/* If this bit is set, then an ending range point collating higher
+     than the starting range point, as in [z-a], is invalid.
+   If not set, then when ending range point collates higher than the
+     starting range point, the range is ignored.  */
+#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
+
+/* If this bit is set, then an unmatched ) is ordinary.
+   If not set, then an unmatched ) is invalid.  */
+#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
+
+/* This global variable defines the particular regexp syntax to use (for
+   some interfaces).  When a regexp is compiled, the syntax used is
+   stored in the pattern buffer, so changing this does not affect
+   already-compiled regexps.  */
+extern reg_syntax_t re_syntax_options;
+
+/* Define combinations of the above bits for the standard possibilities.
+   (The [[[ comments delimit what gets put into the Texinfo file, so
+   don't delete them!)  */
+/* [[[begin syntaxes]]] */
+#define RE_SYNTAX_EMACS 0
+
+#define RE_SYNTAX_AWK							\
+  (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL			\
+   | RE_NO_BK_PARENS            | RE_NO_BK_REFS				\
+   | RE_NO_BK_VBAR               | RE_NO_EMPTY_RANGES			\
+   | RE_UNMATCHED_RIGHT_PAREN_ORD)
+
+#define RE_SYNTAX_POSIX_AWK 						\
+  (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS)
+
+#define RE_SYNTAX_GREP							\
+  (RE_BK_PLUS_QM              | RE_CHAR_CLASSES				\
+   | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS				\
+   | RE_NEWLINE_ALT)
+
+#define RE_SYNTAX_EGREP							\
+  (RE_CHAR_CLASSES        | RE_CONTEXT_INDEP_ANCHORS			\
+   | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE			\
+   | RE_NEWLINE_ALT       | RE_NO_BK_PARENS				\
+   | RE_NO_BK_VBAR)
+
+#define RE_SYNTAX_POSIX_EGREP						\
+  (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES)
+
+/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff.  */
+#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
+
+#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
+
+/* Syntax bits common to both basic and extended POSIX regex syntax.  */
+#define _RE_SYNTAX_POSIX_COMMON						\
+  (RE_CHAR_CLASSES | RE_DOT_NEWLINE      | RE_DOT_NOT_NULL		\
+   | RE_INTERVALS  | RE_NO_EMPTY_RANGES)
+
+#define RE_SYNTAX_POSIX_BASIC						\
+  (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM)
+
+/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
+   RE_LIMITED_OPS, i.e., \? \+ \| are not recognized.  Actually, this
+   isn't minimal, since other operators, such as \`, aren't disabled.  */
+#define RE_SYNTAX_POSIX_MINIMAL_BASIC					\
+  (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)
+
+#define RE_SYNTAX_POSIX_EXTENDED					\
+  (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS			\
+   | RE_CONTEXT_INDEP_OPS  | RE_NO_BK_BRACES				\
+   | RE_NO_BK_PARENS       | RE_NO_BK_VBAR				\
+   | RE_UNMATCHED_RIGHT_PAREN_ORD)
+
+/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INVALID_OPS
+   replaces RE_CONTEXT_INDEP_OPS and RE_NO_BK_REFS is added.  */
+#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED				\
+  (_RE_SYNTAX_POSIX_COMMON  | RE_CONTEXT_INDEP_ANCHORS			\
+   | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES				\
+   | RE_NO_BK_PARENS        | RE_NO_BK_REFS				\
+   | RE_NO_BK_VBAR	    | RE_UNMATCHED_RIGHT_PAREN_ORD)
+/* [[[end syntaxes]]] */
+
+/* Maximum number of duplicates an interval can allow.  Some systems
+   (erroneously) define this in other header files, but we want our
+   value, so remove any previous define.  */
+#ifdef RE_DUP_MAX
+#undef RE_DUP_MAX
+#endif
+#define RE_DUP_MAX ((1 << 15) - 1)
+
+
+/* POSIX `cflags' bits (i.e., information for `regcomp').  */
+
+/* If this bit is set, then use extended regular expression syntax.
+   If not set, then use basic regular expression syntax.  */
+#define REG_EXTENDED 1
+
+/* If this bit is set, then ignore case when matching.
+   If not set, then case is significant.  */
+#define REG_ICASE (REG_EXTENDED << 1)
+
+/* If this bit is set, then anchors do not match at newline
+     characters in the string.
+   If not set, then anchors do match at newlines.  */
+#define REG_NEWLINE (REG_ICASE << 1)
+
+/* If this bit is set, then report only success or fail in regexec.
+   If not set, then returns differ between not matching and errors.  */
+#define REG_NOSUB (REG_NEWLINE << 1)
+
+
+/* POSIX `eflags' bits (i.e., information for regexec).  */
+
+/* If this bit is set, then the beginning-of-line operator doesn't match
+     the beginning of the string (presumably because it's not the
+     beginning of a line).
+   If not set, then the beginning-of-line operator does match the
+     beginning of the string.  */
+#define REG_NOTBOL 1
+
+/* Like REG_NOTBOL, except for the end-of-line.  */
+#define REG_NOTEOL (1 << 1)
+
+
+/* If any error codes are removed, changed, or added, update the
+   `re_error_msg' table in regex.c.  */
+typedef enum
+{
+  REG_NOERROR = 0,	/* Success.  */
+  REG_NOMATCH,		/* Didn't find a match (for regexec).  */
+
+  /* POSIX regcomp return error codes.  (In the order listed in the
+     standard.)  */
+  REG_BADPAT,		/* Invalid pattern.  */
+  REG_ECOLLATE,		/* Not implemented.  */
+  REG_ECTYPE,		/* Invalid character class name.  */
+  REG_EESCAPE,		/* Trailing backslash.  */
+  REG_ESUBREG,		/* Invalid back reference.  */
+  REG_EBRACK,		/* Unmatched left bracket.  */
+  REG_EPAREN,		/* Parenthesis imbalance.  */
+  REG_EBRACE,		/* Unmatched \{.  */
+  REG_BADBR,		/* Invalid contents of \{\}.  */
+  REG_ERANGE,		/* Invalid range end.  */
+  REG_ESPACE,		/* Ran out of memory.  */
+  REG_BADRPT,		/* No preceding re for repetition op.  */
+
+  /* Error codes we've added.  */
+  REG_EEND,		/* Premature end.  */
+  REG_ESIZE,		/* Compiled pattern bigger than 2^16 bytes.  */
+  REG_ERPAREN		/* Unmatched ) or \); not returned from regcomp.  */
+} reg_errcode_t;
+
+/* This data structure represents a compiled pattern.  Before calling
+   the pattern compiler, the fields `buffer', `allocated', `fastmap',
+   `translate', and `no_sub' can be set.  After the pattern has been
+   compiled, the `re_nsub' field is available.  All other fields are
+   private to the regex routines.  */
+
+struct re_pattern_buffer
+{
+/* [[[begin pattern_buffer]]] */
+	/* Space that holds the compiled pattern.  It is declared as
+	  `unsigned char *' because its elements are
+	   sometimes used as array indexes.  */
+  unsigned char *buffer;
+
+	/* Number of bytes to which `buffer' points.  */
+  unsigned long allocated;
+
+	/* Number of bytes actually used in `buffer'.  */
+  unsigned long used;
+
+	/* Syntax setting with which the pattern was compiled.  */
+  reg_syntax_t syntax;
+
+	/* Pointer to a fastmap, if any, otherwise zero.  re_search uses
+	   the fastmap, if there is one, to skip over impossible
+	   starting points for matches.  */
+  char *fastmap;
+
+	/* Either a translate table to apply to all characters before
+	   comparing them, or zero for no translation.  The translation
+	   is applied to a pattern when it is compiled and to a string
+	   when it is matched.  */
+  char *translate;
+
+	/* Number of subexpressions found by the compiler.  */
+  size_t re_nsub;
+
+	/* Zero if this pattern cannot match the empty string, one else.
+	   Well, in truth it's used only in `re_search_2', to see
+	   whether or not we should use the fastmap, so we don't set
+	   this absolutely perfectly; see `re_compile_fastmap' (the
+	   `duplicate' case).  */
+  unsigned can_be_null : 1;
+
+	/* If REGS_UNALLOCATED, allocate space in the `regs' structure
+	     for `max (RE_NREGS, re_nsub + 1)' groups.
+	   If REGS_REALLOCATE, reallocate space if necessary.
+	   If REGS_FIXED, use what's there.  */
+#define REGS_UNALLOCATED 0
+#define REGS_REALLOCATE 1
+#define REGS_FIXED 2
+  unsigned regs_allocated : 2;
+
+	/* Set to zero when `regex_compile' compiles a pattern; set to one
+	   by `re_compile_fastmap' if it updates the fastmap.  */
+  unsigned fastmap_accurate : 1;
+
+	/* If set, `re_match_2' does not return information about
+	   subexpressions.  */
+  unsigned no_sub : 1;
+
+	/* If set, a beginning-of-line anchor doesn't match at the
+	   beginning of the string.  */
+  unsigned not_bol : 1;
+
+	/* Similarly for an end-of-line anchor.  */
+  unsigned not_eol : 1;
+
+	/* If true, an anchor at a newline matches.  */
+  unsigned newline_anchor : 1;
+
+/* [[[end pattern_buffer]]] */
+};
+
+typedef struct re_pattern_buffer regex_t;
+
+
+/* search.c (search_buffer) in Emacs needs this one opcode value.  It is
+   defined both in `regex.c' and here.  */
+#define RE_EXACTN_VALUE 1
+
+/* Type for byte offsets within the string.  POSIX mandates this.  */
+typedef int regoff_t;
+
+
+/* This is the structure we store register match data in.  See
+   regex.texinfo for a full description of what registers match.  */
+struct re_registers
+{
+  unsigned num_regs;
+  regoff_t *start;
+  regoff_t *end;
+};
+
+
+/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
+   `re_match_2' returns information about at least this many registers
+   the first time a `regs' structure is passed.  */
+#ifndef RE_NREGS
+#define RE_NREGS 30
+#endif
+
+
+/* POSIX specification for registers.  Aside from the different names than
+   `re_registers', POSIX uses an array of structures, instead of a
+   structure of arrays.  */
+typedef struct
+{
+  regoff_t rm_so;  /* Byte offset from string's start to substring's start.  */
+  regoff_t rm_eo;  /* Byte offset from string's start to substring's end.  */
+} regmatch_t;
+
+/* Declarations for routines.  */
+
+/* To avoid duplicating every routine declaration -- once with a
+   prototype (if we are ANSI), and once without (if we aren't) -- we
+   use the following macro to declare argument types.  This
+   unfortunately clutters up the declarations a bit, but I think it's
+   worth it.  */
+
+#if __STDC__
+
+#define _RE_ARGS(args) args
+
+#else /* not __STDC__ */
+
+#define _RE_ARGS(args) ()
+
+#endif /* not __STDC__ */
+
+/* Sets the current default syntax to SYNTAX, and return the old syntax.
+   You can also simply assign to the `re_syntax_options' variable.  */
+extern reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax));
+
+/* Compile the regular expression PATTERN, with length LENGTH
+   and syntax given by the global `re_syntax_options', into the buffer
+   BUFFER.  Return NULL if successful, and an error string if not.  */
+extern const char *re_compile_pattern
+  _RE_ARGS ((const char *pattern, int length,
+	     struct re_pattern_buffer *buffer));
+
+
+/* Compile a fastmap for the compiled pattern in BUFFER; used to
+   accelerate searches.  Return 0 if successful and -2 if was an
+   internal error.  */
+extern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer));
+
+
+/* Search in the string STRING (with length LENGTH) for the pattern
+   compiled into BUFFER.  Start searching at position START, for RANGE
+   characters.  Return the starting position of the match, -1 for no
+   match, or -2 for an internal error.  Also return register
+   information in REGS (if REGS and BUFFER->no_sub are nonzero).  */
+extern int re_search
+  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
+	    int length, int start, int range, struct re_registers *regs));
+
+
+/* Like `re_search', but search in the concatenation of STRING1 and
+   STRING2.  Also, stop searching at index START + STOP.  */
+extern int re_search_2
+  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
+	     int length1, const char *string2, int length2,
+	     int start, int range, struct re_registers *regs, int stop));
+
+
+/* Like `re_search', but return how many characters in STRING the regexp
+   in BUFFER matched, starting at position START.  */
+extern int re_match
+  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
+	     int length, int start, struct re_registers *regs));
+
+
+/* Relates to `re_match' as `re_search_2' relates to `re_search'.  */
+extern int re_match_2
+  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
+	     int length1, const char *string2, int length2,
+	     int start, struct re_registers *regs, int stop));
+
+
+/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
+   ENDS.  Subsequent matches using BUFFER and REGS will use this memory
+   for recording register information.  STARTS and ENDS must be
+   allocated with malloc, and must each be at least `NUM_REGS * sizeof
+   (regoff_t)' bytes long.
+
+   If NUM_REGS == 0, then subsequent matches should allocate their own
+   register data.
+
+   Unless this function is called, the first search or match using
+   PATTERN_BUFFER will allocate its own register data, without
+   freeing the old data.  */
+extern void re_set_registers
+  _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs,
+	     unsigned num_regs, regoff_t *starts, regoff_t *ends));
+
+/* 4.2 bsd compatibility.  */
+extern char *re_comp _RE_ARGS ((const char *));
+extern int re_exec _RE_ARGS ((const char *));
+
+/* POSIX compatibility.  */
+extern int regcomp _RE_ARGS ((regex_t *preg, const char *pattern, int cflags));
+extern int regexec
+  _RE_ARGS ((const regex_t *preg, const char *string, size_t nmatch,
+	     regmatch_t pmatch[], int eflags));
+extern size_t regerror
+  _RE_ARGS ((int errcode, const regex_t *preg, char *errbuf,
+	     size_t errbuf_size));
+extern void regfree _RE_ARGS ((regex_t *preg));
+
+#endif /* not __REGEXP_LIBRARY_H__ */
+
+/*
+Local variables:
+make-backup-files: t
+version-control: t
+trim-versions-without-asking: nil
+End:
+*/
diff --git a/compat/snprintf.c b/compat/snprintf.c
index dbfc2d6..357e733 100644
--- a/compat/snprintf.c
+++ b/compat/snprintf.c
@@ -1,12 +1,27 @@
 #include "../git-compat-util.h"
 
+/*
+ * The size parameter specifies the available space, i.e. includes
+ * the trailing NUL byte; but Windows's vsnprintf expects the
+ * number of characters to write without the trailing NUL.
+ */
+#ifndef SNPRINTF_SIZE_CORR
+#define SNPRINTF_SIZE_CORR 0
+#endif
+
 #undef vsnprintf
 int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap)
 {
 	char *s;
-	int ret;
+	int ret = -1;
 
-	ret = vsnprintf(str, maxsize, format, ap);
+	if (maxsize > 0) {
+		ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap);
+		if (ret == maxsize-1)
+			ret = -1;
+		/* Windows does not NUL-terminate if result fills buffer */
+		str[maxsize-1] = 0;
+	}
 	if (ret != -1)
 		return ret;
 
@@ -20,7 +35,9 @@
 		if (! str)
 			break;
 		s = str;
-		ret = vsnprintf(str, maxsize, format, ap);
+		ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap);
+		if (ret == maxsize-1)
+			ret = -1;
 	}
 	free(s);
 	return ret;
diff --git a/compat/winansi.c b/compat/winansi.c
new file mode 100644
index 0000000..e2d96df
--- /dev/null
+++ b/compat/winansi.c
@@ -0,0 +1,345 @@
+/*
+ * Copyright 2008 Peter Harris <git@peter.is-a-geek.org>
+ */
+
+#include <windows.h>
+#include "../git-compat-util.h"
+
+/*
+ Functions to be wrapped:
+*/
+#undef printf
+#undef fprintf
+#undef fputs
+/* TODO: write */
+
+/*
+ ANSI codes used by git: m, K
+
+ This file is git-specific. Therefore, this file does not attempt
+ to implement any codes that are not used by git.
+
+ TODO: K
+*/
+
+static HANDLE console;
+static WORD plain_attr;
+static WORD attr;
+static int negative;
+
+static void init(void)
+{
+	CONSOLE_SCREEN_BUFFER_INFO sbi;
+
+	static int initialized = 0;
+	if (initialized)
+		return;
+
+	console = GetStdHandle(STD_OUTPUT_HANDLE);
+	if (console == INVALID_HANDLE_VALUE)
+		console = NULL;
+
+	if (!console)
+		return;
+
+	GetConsoleScreenBufferInfo(console, &sbi);
+	attr = plain_attr = sbi.wAttributes;
+	negative = 0;
+
+	initialized = 1;
+}
+
+
+#define FOREGROUND_ALL (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
+#define BACKGROUND_ALL (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)
+
+static void set_console_attr(void)
+{
+	WORD attributes = attr;
+	if (negative) {
+		attributes &= ~FOREGROUND_ALL;
+		attributes &= ~BACKGROUND_ALL;
+
+		/* This could probably use a bitmask
+		   instead of a series of ifs */
+		if (attr & FOREGROUND_RED)
+			attributes |= BACKGROUND_RED;
+		if (attr & FOREGROUND_GREEN)
+			attributes |= BACKGROUND_GREEN;
+		if (attr & FOREGROUND_BLUE)
+			attributes |= BACKGROUND_BLUE;
+
+		if (attr & BACKGROUND_RED)
+			attributes |= FOREGROUND_RED;
+		if (attr & BACKGROUND_GREEN)
+			attributes |= FOREGROUND_GREEN;
+		if (attr & BACKGROUND_BLUE)
+			attributes |= FOREGROUND_BLUE;
+	}
+	SetConsoleTextAttribute(console, attributes);
+}
+
+static const char *set_attr(const char *str)
+{
+	const char *func;
+	size_t len = strspn(str, "0123456789;");
+	func = str + len;
+
+	switch (*func) {
+	case 'm':
+		do {
+			long val = strtol(str, (char **)&str, 10);
+			switch (val) {
+			case 0: /* reset */
+				attr = plain_attr;
+				negative = 0;
+				break;
+			case 1: /* bold */
+				attr |= FOREGROUND_INTENSITY;
+				break;
+			case 2:  /* faint */
+			case 22: /* normal */
+				attr &= ~FOREGROUND_INTENSITY;
+				break;
+			case 3:  /* italic */
+				/* Unsupported */
+				break;
+			case 4:  /* underline */
+			case 21: /* double underline */
+				/* Wikipedia says this flag does nothing */
+				/* Furthermore, mingw doesn't define this flag
+				attr |= COMMON_LVB_UNDERSCORE; */
+				break;
+			case 24: /* no underline */
+				/* attr &= ~COMMON_LVB_UNDERSCORE; */
+				break;
+			case 5:  /* slow blink */
+			case 6:  /* fast blink */
+				/* We don't have blink, but we do have
+				   background intensity */
+				attr |= BACKGROUND_INTENSITY;
+				break;
+			case 25: /* no blink */
+				attr &= ~BACKGROUND_INTENSITY;
+				break;
+			case 7:  /* negative */
+				negative = 1;
+				break;
+			case 27: /* positive */
+				negative = 0;
+				break;
+			case 8:  /* conceal */
+			case 28: /* reveal */
+				/* Unsupported */
+				break;
+			case 30: /* Black */
+				attr &= ~FOREGROUND_ALL;
+				break;
+			case 31: /* Red */
+				attr &= ~FOREGROUND_ALL;
+				attr |= FOREGROUND_RED;
+				break;
+			case 32: /* Green */
+				attr &= ~FOREGROUND_ALL;
+				attr |= FOREGROUND_GREEN;
+				break;
+			case 33: /* Yellow */
+				attr &= ~FOREGROUND_ALL;
+				attr |= FOREGROUND_RED | FOREGROUND_GREEN;
+				break;
+			case 34: /* Blue */
+				attr &= ~FOREGROUND_ALL;
+				attr |= FOREGROUND_BLUE;
+				break;
+			case 35: /* Magenta */
+				attr &= ~FOREGROUND_ALL;
+				attr |= FOREGROUND_RED | FOREGROUND_BLUE;
+				break;
+			case 36: /* Cyan */
+				attr &= ~FOREGROUND_ALL;
+				attr |= FOREGROUND_GREEN | FOREGROUND_BLUE;
+				break;
+			case 37: /* White */
+				attr |= FOREGROUND_RED |
+					FOREGROUND_GREEN |
+					FOREGROUND_BLUE;
+				break;
+			case 38: /* Unknown */
+				break;
+			case 39: /* reset */
+				attr &= ~FOREGROUND_ALL;
+				attr |= (plain_attr & FOREGROUND_ALL);
+				break;
+			case 40: /* Black */
+				attr &= ~BACKGROUND_ALL;
+				break;
+			case 41: /* Red */
+				attr &= ~BACKGROUND_ALL;
+				attr |= BACKGROUND_RED;
+				break;
+			case 42: /* Green */
+				attr &= ~BACKGROUND_ALL;
+				attr |= BACKGROUND_GREEN;
+				break;
+			case 43: /* Yellow */
+				attr &= ~BACKGROUND_ALL;
+				attr |= BACKGROUND_RED | BACKGROUND_GREEN;
+				break;
+			case 44: /* Blue */
+				attr &= ~BACKGROUND_ALL;
+				attr |= BACKGROUND_BLUE;
+				break;
+			case 45: /* Magenta */
+				attr &= ~BACKGROUND_ALL;
+				attr |= BACKGROUND_RED | BACKGROUND_BLUE;
+				break;
+			case 46: /* Cyan */
+				attr &= ~BACKGROUND_ALL;
+				attr |= BACKGROUND_GREEN | BACKGROUND_BLUE;
+				break;
+			case 47: /* White */
+				attr |= BACKGROUND_RED |
+					BACKGROUND_GREEN |
+					BACKGROUND_BLUE;
+				break;
+			case 48: /* Unknown */
+				break;
+			case 49: /* reset */
+				attr &= ~BACKGROUND_ALL;
+				attr |= (plain_attr & BACKGROUND_ALL);
+				break;
+			default:
+				/* Unsupported code */
+				break;
+			}
+			str++;
+		} while (*(str-1) == ';');
+
+		set_console_attr();
+		break;
+	case 'K':
+		/* TODO */
+		break;
+	default:
+		/* Unsupported code */
+		break;
+	}
+
+	return func + 1;
+}
+
+static int ansi_emulate(const char *str, FILE *stream)
+{
+	int rv = 0;
+	const char *pos = str;
+
+	while (*pos) {
+		pos = strstr(str, "\033[");
+		if (pos) {
+			size_t len = pos - str;
+
+			if (len) {
+				size_t out_len = fwrite(str, 1, len, stream);
+				rv += out_len;
+				if (out_len < len)
+					return rv;
+			}
+
+			str = pos + 2;
+			rv += 2;
+
+			fflush(stream);
+
+			pos = set_attr(str);
+			rv += pos - str;
+			str = pos;
+		} else {
+			rv += strlen(str);
+			fputs(str, stream);
+			return rv;
+		}
+	}
+	return rv;
+}
+
+int winansi_fputs(const char *str, FILE *stream)
+{
+	int rv;
+
+	if (!isatty(fileno(stream)))
+		return fputs(str, stream);
+
+	init();
+
+	if (!console)
+		return fputs(str, stream);
+
+	rv = ansi_emulate(str, stream);
+
+	if (rv >= 0)
+		return 0;
+	else
+		return EOF;
+}
+
+static int winansi_vfprintf(FILE *stream, const char *format, va_list list)
+{
+	int len, rv;
+	char small_buf[256];
+	char *buf = small_buf;
+	va_list cp;
+
+	if (!isatty(fileno(stream)))
+		goto abort;
+
+	init();
+
+	if (!console)
+		goto abort;
+
+	va_copy(cp, list);
+	len = vsnprintf(small_buf, sizeof(small_buf), format, cp);
+	va_end(cp);
+
+	if (len > sizeof(small_buf) - 1) {
+		buf = malloc(len + 1);
+		if (!buf)
+			goto abort;
+
+		len = vsnprintf(buf, len + 1, format, list);
+	}
+
+	rv = ansi_emulate(buf, stream);
+
+	if (buf != small_buf)
+		free(buf);
+	return rv;
+
+abort:
+	rv = vfprintf(stream, format, list);
+	return rv;
+}
+
+int winansi_fprintf(FILE *stream, const char *format, ...)
+{
+	va_list list;
+	int rv;
+
+	va_start(list, format);
+	rv = winansi_vfprintf(stream, format, list);
+	va_end(list);
+
+	return rv;
+}
+
+int winansi_printf(const char *format, ...)
+{
+	va_list list;
+	int rv;
+
+	va_start(list, format);
+	rv = winansi_vfprintf(stdout, format, list);
+	va_end(list);
+
+	return rv;
+}
diff --git a/config.c b/config.c
index b2d5b4e..82807c8 100644
--- a/config.c
+++ b/config.c
@@ -16,6 +16,8 @@
 static int config_file_eof;
 static int zlib_compression_seen;
 
+const char *config_exclusive_filename = NULL;
+
 static int get_next_char(void)
 {
 	int c;
@@ -339,6 +341,10 @@
 		trust_executable_bit = git_config_bool(var, value);
 		return 0;
 	}
+	if (!strcmp(var, "core.trustctime")) {
+		trust_ctime = git_config_bool(var, value);
+		return 0;
+	}
 
 	if (!strcmp(var, "core.quotepath")) {
 		quote_path_fully = git_config_bool(var, value);
@@ -579,19 +585,12 @@
 const char *git_etc_gitconfig(void)
 {
 	static const char *system_wide;
-	if (!system_wide) {
-		system_wide = ETC_GITCONFIG;
-		if (!is_absolute_path(system_wide)) {
-			/* interpret path relative to exec-dir */
-			struct strbuf d = STRBUF_INIT;
-			strbuf_addf(&d, "%s/%s", git_exec_path(), system_wide);
-			system_wide = strbuf_detach(&d, NULL);
-		}
-	}
+	if (!system_wide)
+		system_wide = system_path(ETC_GITCONFIG);
 	return system_wide;
 }
 
-int git_env_bool(const char *k, int def)
+static int git_env_bool(const char *k, int def)
 {
 	const char *v = getenv(k);
 	return v ? git_config_bool(k, v) : def;
@@ -611,31 +610,28 @@
 {
 	int ret = 0;
 	char *repo_config = NULL;
-	const char *home = NULL, *filename;
+	const char *home = NULL;
 
 	/* $GIT_CONFIG makes git read _only_ the given config file,
 	 * $GIT_CONFIG_LOCAL will make it process it in addition to the
 	 * global config file, the same way it would the per-repository
 	 * config file otherwise. */
-	filename = getenv(CONFIG_ENVIRONMENT);
-	if (!filename) {
-		if (git_config_system() && !access(git_etc_gitconfig(), R_OK))
-			ret += git_config_from_file(fn, git_etc_gitconfig(),
-				data);
-		home = getenv("HOME");
-		filename = getenv(CONFIG_LOCAL_ENVIRONMENT);
-		if (!filename)
-			filename = repo_config = xstrdup(git_path("config"));
-	}
+	if (config_exclusive_filename)
+		return git_config_from_file(fn, config_exclusive_filename, data);
+	if (git_config_system() && !access(git_etc_gitconfig(), R_OK))
+		ret += git_config_from_file(fn, git_etc_gitconfig(),
+					    data);
 
+	home = getenv("HOME");
 	if (git_config_global() && home) {
 		char *user_config = xstrdup(mkpath("%s/.gitconfig", home));
 		if (!access(user_config, R_OK))
-			ret = git_config_from_file(fn, user_config, data);
+			ret += git_config_from_file(fn, user_config, data);
 		free(user_config);
 	}
 
-	ret += git_config_from_file(fn, filename, data);
+	repo_config = git_pathdup("config");
+	ret += git_config_from_file(fn, repo_config, data);
 	free(repo_config);
 	return ret;
 }
@@ -873,13 +869,10 @@
 	struct lock_file *lock = NULL;
 	const char* last_dot = strrchr(key, '.');
 
-	config_filename = getenv(CONFIG_ENVIRONMENT);
-	if (!config_filename) {
-		config_filename = getenv(CONFIG_LOCAL_ENVIRONMENT);
-		if (!config_filename)
-			config_filename  = git_path("config");
-	}
-	config_filename = xstrdup(config_filename);
+	if (config_exclusive_filename)
+		config_filename = xstrdup(config_exclusive_filename);
+	else
+		config_filename = git_pathdup("config");
 
 	/*
 	 * Since "key" actually contains the section name and the real
@@ -1136,13 +1129,10 @@
 	int out_fd;
 	char buf[1024];
 
-	config_filename = getenv(CONFIG_ENVIRONMENT);
-	if (!config_filename) {
-		config_filename = getenv(CONFIG_LOCAL_ENVIRONMENT);
-		if (!config_filename)
-			config_filename  = git_path("config");
-	}
-	config_filename = xstrdup(config_filename);
+	if (config_exclusive_filename)
+		config_filename = xstrdup(config_exclusive_filename);
+	else
+		config_filename = git_pathdup("config");
 	out_fd = hold_lock_file_for_update(lock, config_filename, 0);
 	if (out_fd < 0) {
 		ret = error("could not lock config file %s", config_filename);
diff --git a/config.mak.in b/config.mak.in
index 7868dfd..b776149 100644
--- a/config.mak.in
+++ b/config.mak.in
@@ -11,7 +11,7 @@
 prefix = @prefix@
 exec_prefix = @exec_prefix@
 bindir = @bindir@
-#gitexecdir = @libexecdir@/git-core/
+gitexecdir = @libexecdir@/git-core/
 datarootdir = @datarootdir@
 template_dir = @datadir@/git-core/templates/
 
diff --git a/connect.c b/connect.c
index e92af29..dd96f8e 100644
--- a/connect.c
+++ b/connect.c
@@ -97,7 +97,7 @@
 	int len = packet_read_line(fd, line, sizeof(line));
 
 	if (!len)
-		die("git-fetch-pack: expected ACK/NAK, got EOF");
+		die("git fetch-pack: expected ACK/NAK, got EOF");
 	if (line[len-1] == '\n')
 		line[--len] = 0;
 	if (!strcmp(line, "NAK"))
@@ -109,7 +109,7 @@
 			return 1;
 		}
 	}
-	die("git-fetch_pack: expected ACK/NAK, got '%s'", line);
+	die("git fetch_pack: expected ACK/NAK, got '%s'", line);
 }
 
 int path_match(const char *path, int nr, char **match)
@@ -529,7 +529,7 @@
 		end = host;
 
 	path = strchr(end, c);
-	if (path) {
+	if (path && !has_dos_drive_prefix(end)) {
 		if (c == ':') {
 			protocol = PROTO_SSH;
 			*path++ = '\0';
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 72f02f2..554a03f 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -73,26 +73,26 @@
 	if [ -n "$g" ]; then
 		local r
 		local b
-		if [ -d "$g/../.dotest" ]
+		if [ -d "$g/rebase-apply" ]
 		then
-			if test -f "$g/../.dotest/rebasing"
+			if test -f "$g/rebase-apply/rebasing"
 			then
 				r="|REBASE"
-			elif test -f "$g/../.dotest/applying"
+			elif test -f "$g/rebase-apply/applying"
 			then
 				r="|AM"
 			else
 				r="|AM/REBASE"
 			fi
 			b="$(git symbolic-ref HEAD 2>/dev/null)"
-		elif [ -f "$g/.dotest-merge/interactive" ]
+		elif [ -f "$g/rebase-merge/interactive" ]
 		then
 			r="|REBASE-i"
-			b="$(cat "$g/.dotest-merge/head-name")"
-		elif [ -d "$g/.dotest-merge" ]
+			b="$(cat "$g/rebase-merge/head-name")"
+		elif [ -d "$g/rebase-merge" ]
 		then
 			r="|REBASE-m"
-			b="$(cat "$g/.dotest-merge/head-name")"
+			b="$(cat "$g/rebase-merge/head-name")"
 		elif [ -f "$g/MERGE_HEAD" ]
 		then
 			r="|MERGING"
@@ -271,15 +271,17 @@
 		echo "$__git_merge_strategylist"
 		return
 	fi
-	sed -n "/^all_strategies='/{
-		s/^all_strategies='//
-		s/'//
+	git merge -s help 2>&1 |
+	sed -n -e '/[Aa]vailable strategies are: /,/^$/{
+		s/\.$//
+		s/.*://
+		s/^[ 	]*//
+		s/[ 	]*$//
 		p
-		q
-		}" "$(git --exec-path)/git-merge"
+	}'
 }
 __git_merge_strategylist=
-__git_merge_strategylist="$(__git_merge_strategies 2>/dev/null)"
+__git_merge_strategylist=$(__git_merge_strategies 2>/dev/null)
 
 __git_complete_file ()
 {
@@ -349,10 +351,10 @@
 	esac
 }
 
-__git_commands ()
+__git_all_commands ()
 {
-	if [ -n "$__git_commandlist" ]; then
-		echo "$__git_commandlist"
+	if [ -n "$__git_all_commandlist" ]; then
+		echo "$__git_all_commandlist"
 		return
 	fi
 	local i IFS=" "$'\n'
@@ -360,13 +362,33 @@
 	do
 		case $i in
 		*--*)             : helper pattern;;
+		*) echo $i;;
+		esac
+	done
+}
+__git_all_commandlist=
+__git_all_commandlist="$(__git_all_commands 2>/dev/null)"
+
+__git_porcelain_commands ()
+{
+	if [ -n "$__git_porcelain_commandlist" ]; then
+		echo "$__git_porcelain_commandlist"
+		return
+	fi
+	local i IFS=" "$'\n'
+	for i in "help" $(__git_all_commands)
+	do
+		case $i in
+		*--*)             : helper pattern;;
 		applymbox)        : ask gittus;;
 		applypatch)       : ask gittus;;
 		archimport)       : import;;
 		cat-file)         : plumbing;;
 		check-attr)       : plumbing;;
 		check-ref-format) : plumbing;;
+		checkout-index)   : plumbing;;
 		commit-tree)      : plumbing;;
+		count-objects)    : infrequent;;
 		cvsexportcommit)  : export;;
 		cvsimport)        : import;;
 		cvsserver)        : daemon;;
@@ -375,6 +397,7 @@
 		diff-index)       : plumbing;;
 		diff-tree)        : plumbing;;
 		fast-import)      : import;;
+		fast-export)      : export;;
 		fsck-objects)     : plumbing;;
 		fetch-pack)       : plumbing;;
 		fmt-merge-msg)    : plumbing;;
@@ -384,6 +407,10 @@
 		index-pack)       : plumbing;;
 		init-db)          : deprecated;;
 		local-fetch)      : plumbing;;
+		lost-found)       : infrequent;;
+		ls-files)         : plumbing;;
+		ls-remote)        : plumbing;;
+		ls-tree)          : plumbing;;
 		mailinfo)         : plumbing;;
 		mailsplit)        : plumbing;;
 		merge-*)          : plumbing;;
@@ -408,6 +435,7 @@
 		runstatus)        : plumbing;;
 		sh-setup)         : internal;;
 		shell)            : daemon;;
+		show-ref)         : plumbing;;
 		send-pack)        : plumbing;;
 		show-index)       : plumbing;;
 		ssh-*)            : transport;;
@@ -422,13 +450,15 @@
 		upload-archive)   : plumbing;;
 		upload-pack)      : plumbing;;
 		write-tree)       : plumbing;;
+		var)              : infrequent;;
+		verify-pack)      : infrequent;;
 		verify-tag)       : plumbing;;
 		*) echo $i;;
 		esac
 	done
 }
-__git_commandlist=
-__git_commandlist="$(__git_commands 2>/dev/null)"
+__git_porcelain_commandlist=
+__git_porcelain_commandlist="$(__git_porcelain_commands 2>/dev/null)"
 
 __git_aliases ()
 {
@@ -483,13 +513,13 @@
 	return 1
 }
 
-__git_whitespacelist="nowarn warn error error-all strip"
+__git_whitespacelist="nowarn warn error error-all fix"
 
 _git_am ()
 {
-	local cur="${COMP_WORDS[COMP_CWORD]}"
-	if [ -d .dotest ]; then
-		__gitcomp "--skip --resolved"
+	local cur="${COMP_WORDS[COMP_CWORD]}" dir="$(__gitdir)"
+	if [ -d "$dir"/rebase-apply ]; then
+		__gitcomp "--skip --resolved --abort"
 		return
 	fi
 	case "$cur" in
@@ -543,11 +573,34 @@
 	COMPREPLY=()
 }
 
+_git_archive ()
+{
+	local cur="${COMP_WORDS[COMP_CWORD]}"
+	case "$cur" in
+	--format=*)
+		__gitcomp "$(git archive --list)" "" "${cur##--format=}"
+		return
+		;;
+	--remote=*)
+		__gitcomp "$(__git_remotes)" "" "${cur##--remote=}"
+		return
+		;;
+	--*)
+		__gitcomp "
+			--format= --list --verbose
+			--prefix= --remote= --exec=
+			"
+		return
+		;;
+	esac
+	__git_complete_file
+}
+
 _git_bisect ()
 {
 	__git_has_doubledash && return
 
-	local subcommands="start bad good reset visualize replay log"
+	local subcommands="start bad good skip reset visualize replay log run"
 	local subcommand="$(__git_find_subcommand "$subcommands")"
 	if [ -z "$subcommand" ]; then
 		__gitcomp "$subcommands"
@@ -555,7 +608,7 @@
 	fi
 
 	case "$subcommand" in
-	bad|good|reset)
+	bad|good|reset|skip)
 		__gitcomp "$(__git_refs)"
 		;;
 	*)
@@ -582,7 +635,7 @@
 	--*)
 		__gitcomp "
 			--color --no-color --verbose --abbrev= --no-abbrev
-			--track --no-track
+			--track --no-track --contains --merged --no-merged
 			"
 		;;
 	*)
@@ -597,21 +650,12 @@
 
 _git_bundle ()
 {
-	local mycword="$COMP_CWORD"
-	case "${COMP_WORDS[0]}" in
-	git)
-		local cmd="${COMP_WORDS[2]}"
-		mycword="$((mycword-1))"
-		;;
-	git-bundle*)
-		local cmd="${COMP_WORDS[1]}"
-		;;
-	esac
-	case "$mycword" in
-	1)
+	local cmd="${COMP_WORDS[2]}"
+	case "$COMP_CWORD" in
+	2)
 		__gitcomp "create list-heads verify unbundle"
 		;;
-	2)
+	3)
 		# looking for a file
 		;;
 	*)
@@ -626,6 +670,8 @@
 
 _git_checkout ()
 {
+	__git_has_doubledash && return
+
 	__gitcomp "$(__git_refs)"
 }
 
@@ -647,6 +693,45 @@
 	esac
 }
 
+_git_clean ()
+{
+	__git_has_doubledash && return
+
+	local cur="${COMP_WORDS[COMP_CWORD]}"
+	case "$cur" in
+	--*)
+		__gitcomp "--dry-run --quiet"
+		return
+		;;
+	esac
+	COMPREPLY=()
+}
+
+_git_clone ()
+{
+	local cur="${COMP_WORDS[COMP_CWORD]}"
+	case "$cur" in
+	--*)
+		__gitcomp "
+			--local
+			--no-hardlinks
+			--shared
+			--reference
+			--quiet
+			--no-checkout
+			--bare
+			--mirror
+			--origin
+			--upload-pack
+			--template=
+			--depth
+			"
+		return
+		;;
+	esac
+	COMPREPLY=()
+}
+
 _git_commit ()
 {
 	__git_has_doubledash && return
@@ -656,7 +741,7 @@
 	--*)
 		__gitcomp "
 			--all --author= --signoff --verify --no-verify
-			--edit --amend --include --only
+			--edit --amend --include --only --interactive
 			"
 		return
 	esac
@@ -665,6 +750,15 @@
 
 _git_describe ()
 {
+	local cur="${COMP_WORDS[COMP_CWORD]}"
+	case "$cur" in
+	--*)
+		__gitcomp "
+			--all --tags --contains --abbrev= --candidates=
+			--exact-match --debug --long --match --always
+			"
+		return
+	esac
 	__gitcomp "$(__git_refs)"
 }
 
@@ -678,7 +772,7 @@
 		__gitcomp "--cached --stat --numstat --shortstat --summary
 			--patch-with-stat --name-only --name-status --color
 			--no-color --color-words --no-renames --check
-			--full-index --binary --abbrev --diff-filter
+			--full-index --binary --abbrev --diff-filter=
 			--find-copies-harder --pickaxe-all --pickaxe-regex
 			--text --ignore-space-at-eol --ignore-space-change
 			--ignore-all-space --exit-code --quiet --ext-diff
@@ -692,23 +786,13 @@
 	__git_complete_file
 }
 
-_git_diff_tree ()
-{
-	__gitcomp "$(__git_refs)"
-}
-
 _git_fetch ()
 {
 	local cur="${COMP_WORDS[COMP_CWORD]}"
 
-	case "${COMP_WORDS[0]},$COMP_CWORD" in
-	git-fetch*,1)
+	if [ "$COMP_CWORD" = 2 ]; then
 		__gitcomp "$(__git_remotes)"
-		;;
-	git,2)
-		__gitcomp "$(__git_remotes)"
-		;;
-	*)
+	else
 		case "$cur" in
 		*:*)
 			local pfx=""
@@ -719,16 +803,10 @@
 			__gitcomp "$(__git_refs)" "$pfx" "${cur#*:}"
 			;;
 		*)
-			local remote
-			case "${COMP_WORDS[0]}" in
-			git-fetch) remote="${COMP_WORDS[1]}" ;;
-			git)       remote="${COMP_WORDS[2]}" ;;
-			esac
-			__gitcomp "$(__git_refs2 "$remote")"
+			__gitcomp "$(__git_refs2 "${COMP_WORDS[2]}")"
 			;;
 		esac
-		;;
-	esac
+	fi
 }
 
 _git_format_patch ()
@@ -767,6 +845,83 @@
 	COMPREPLY=()
 }
 
+_git_grep ()
+{
+	__git_has_doubledash && return
+
+	local cur="${COMP_WORDS[COMP_CWORD]}"
+	case "$cur" in
+	--*)
+		__gitcomp "
+			--cached
+			--text --ignore-case --word-regexp --invert-match
+			--full-name
+			--extended-regexp --basic-regexp --fixed-strings
+			--files-with-matches --name-only
+			--files-without-match
+			--count
+			--and --or --not --all-match
+			"
+		return
+		;;
+	esac
+	COMPREPLY=()
+}
+
+_git_help ()
+{
+	local cur="${COMP_WORDS[COMP_CWORD]}"
+	case "$cur" in
+	--*)
+		__gitcomp "--all --info --man --web"
+		return
+		;;
+	esac
+	__gitcomp "$(__git_all_commands)
+		attributes cli core-tutorial cvs-migration
+		diffcore gitk glossary hooks ignore modules
+		repository-layout tutorial tutorial-2
+		"
+}
+
+_git_init ()
+{
+	local cur="${COMP_WORDS[COMP_CWORD]}"
+	case "$cur" in
+	--shared=*)
+		__gitcomp "
+			false true umask group all world everybody
+			" "" "${cur##--shared=}"
+		return
+		;;
+	--*)
+		__gitcomp "--quiet --bare --template= --shared --shared="
+		return
+		;;
+	esac
+	COMPREPLY=()
+}
+
+_git_ls_files ()
+{
+	__git_has_doubledash && return
+
+	local cur="${COMP_WORDS[COMP_CWORD]}"
+	case "$cur" in
+	--*)
+		__gitcomp "--cached --deleted --modified --others --ignored
+			--stage --directory --no-empty-directory --unmerged
+			--killed --exclude= --exclude-from=
+			--exclude-per-directory= --exclude-standard
+			--error-unmatch --with-tree= --full-name
+			--abbrev --ignored --exclude-per-directory
+			"
+		return
+		;;
+	esac
+	COMPREPLY=()
+}
+
 _git_ls_remote ()
 {
 	__gitcomp "$(__git_remotes)"
@@ -809,6 +964,11 @@
 			--not --all
 			--left-right --cherry-pick
 			--graph
+			--stat --numstat --shortstat
+			--decorate --diff-filter=
+			--color-words --walk-reflogs
+			--parents --children --full-history
+			--merge
 			"
 		return
 		;;
@@ -838,11 +998,42 @@
 	__gitcomp "$(__git_refs)"
 }
 
+_git_mergetool ()
+{
+	local cur="${COMP_WORDS[COMP_CWORD]}"
+	case "$cur" in
+	--tool=*)
+		__gitcomp "
+			kdiff3 tkdiff meld xxdiff emerge
+			vimdiff gvimdiff ecmerge opendiff
+			" "" "${cur##--tool=}"
+		return
+		;;
+	--*)
+		__gitcomp "--tool="
+		return
+		;;
+	esac
+	COMPREPLY=()
+}
+
 _git_merge_base ()
 {
 	__gitcomp "$(__git_refs)"
 }
 
+_git_mv ()
+{
+	local cur="${COMP_WORDS[COMP_CWORD]}"
+	case "$cur" in
+	--*)
+		__gitcomp "--dry-run"
+		return
+		;;
+	esac
+	COMPREPLY=()
+}
+
 _git_name_rev ()
 {
 	__gitcomp "--tags --all --stdin"
@@ -852,51 +1043,29 @@
 {
 	local cur="${COMP_WORDS[COMP_CWORD]}"
 
-	case "${COMP_WORDS[0]},$COMP_CWORD" in
-	git-pull*,1)
+	if [ "$COMP_CWORD" = 2 ]; then
 		__gitcomp "$(__git_remotes)"
-		;;
-	git,2)
-		__gitcomp "$(__git_remotes)"
-		;;
-	*)
-		local remote
-		case "${COMP_WORDS[0]}" in
-		git-pull)  remote="${COMP_WORDS[1]}" ;;
-		git)       remote="${COMP_WORDS[2]}" ;;
-		esac
-		__gitcomp "$(__git_refs "$remote")"
-		;;
-	esac
+	else
+		__gitcomp "$(__git_refs "${COMP_WORDS[2]}")"
+	fi
 }
 
 _git_push ()
 {
 	local cur="${COMP_WORDS[COMP_CWORD]}"
 
-	case "${COMP_WORDS[0]},$COMP_CWORD" in
-	git-push*,1)
+	if [ "$COMP_CWORD" = 2 ]; then
 		__gitcomp "$(__git_remotes)"
-		;;
-	git,2)
-		__gitcomp "$(__git_remotes)"
-		;;
-	*)
+	else
 		case "$cur" in
 		*:*)
-			local remote
-			case "${COMP_WORDS[0]}" in
-			git-push)  remote="${COMP_WORDS[1]}" ;;
-			git)       remote="${COMP_WORDS[2]}" ;;
-			esac
-
 			local pfx=""
 			case "$COMP_WORDBREAKS" in
 			*:*) : great ;;
 			*)   pfx="${cur%%:*}:" ;;
 			esac
 
-			__gitcomp "$(__git_refs "$remote")" "$pfx" "${cur#*:}"
+			__gitcomp "$(__git_refs "${COMP_WORDS[2]}")" "$pfx" "${cur#*:}"
 			;;
 		+*)
 			__gitcomp "$(__git_refs)" + "${cur#+}"
@@ -905,14 +1074,13 @@
 			__gitcomp "$(__git_refs)"
 			;;
 		esac
-		;;
-	esac
+	fi
 }
 
 _git_rebase ()
 {
 	local cur="${COMP_WORDS[COMP_CWORD]}" dir="$(__gitdir)"
-	if [ -d .dotest ] || [ -d "$dir"/.dotest-merge ]; then
+	if [ -d "$dir"/rebase-apply ] || [ -d "$dir"/rebase-merge ]; then
 		__gitcomp "--continue --skip --abort"
 		return
 	fi
@@ -933,6 +1101,24 @@
 	__gitcomp "$(__git_refs)"
 }
 
+_git_send_email ()
+{
+	local cur="${COMP_WORDS[COMP_CWORD]}"
+	case "$cur" in
+	--*)
+		__gitcomp "--bcc --cc --cc-cmd --chain-reply-to --compose
+			--dry-run --envelope-sender --from --identity
+			--in-reply-to --no-chain-reply-to --no-signed-off-by-cc
+			--no-suppress-from --no-thread --quiet
+			--signed-off-by-cc --smtp-pass --smtp-server
+			--smtp-server-port --smtp-ssl --smtp-user --subject
+			--suppress-cc --suppress-from --thread --to"
+		return
+		;;
+	esac
+	COMPREPLY=()
+}
+
 _git_config ()
 {
 	local cur="${COMP_WORDS[COMP_CWORD]}"
@@ -1092,7 +1278,6 @@
 		pull.octopus
 		pull.twohead
 		repack.useDeltaBaseOffset
-		show.difftree
 		showbranch.default
 		tar.umask
 		transfer.unpackLimit
@@ -1101,7 +1286,6 @@
 		user.name
 		user.email
 		user.signingkey
-		whatchanged.difftree
 		branch. remote.
 	"
 }
@@ -1151,6 +1335,32 @@
 	__gitcomp "$(__git_refs)"
 }
 
+_git_revert ()
+{
+	local cur="${COMP_WORDS[COMP_CWORD]}"
+	case "$cur" in
+	--*)
+		__gitcomp "--edit --mainline --no-edit --no-commit --signoff"
+		return
+		;;
+	esac
+	__gitcomp "$(__git_refs)"
+}
+
+_git_rm ()
+{
+	__git_has_doubledash && return
+
+	local cur="${COMP_WORDS[COMP_CWORD]}"
+	case "$cur" in
+	--*)
+		__gitcomp "--cached --dry-run --ignore-unmatch --quiet"
+		return
+		;;
+	esac
+	COMPREPLY=()
+}
+
 _git_shortlog ()
 {
 	__git_has_doubledash && return
@@ -1175,6 +1385,8 @@
 
 _git_show ()
 {
+	__git_has_doubledash && return
+
 	local cur="${COMP_WORDS[COMP_CWORD]}"
 	case "$cur" in
 	--pretty=*)
@@ -1191,11 +1403,48 @@
 	__git_complete_file
 }
 
+_git_show_branch ()
+{
+	local cur="${COMP_WORDS[COMP_CWORD]}"
+	case "$cur" in
+	--*)
+		__gitcomp "
+			--all --remotes --topo-order --current --more=
+			--list --independent --merge-base --no-name
+			--sha1-name --topics --reflog
+			"
+		return
+		;;
+	esac
+	__git_complete_revlist
+}
+
 _git_stash ()
 {
-	local subcommands='save list show apply clear drop pop create'
-	if [ -z "$(__git_find_subcommand "$subcommands")" ]; then
+	local subcommands='save list show apply clear drop pop create branch'
+	local subcommand="$(__git_find_subcommand "$subcommands")"
+	if [ -z "$subcommand" ]; then
 		__gitcomp "$subcommands"
+	else
+		local cur="${COMP_WORDS[COMP_CWORD]}"
+		case "$subcommand,$cur" in
+		save,--*)
+			__gitcomp "--keep-index"
+			;;
+		apply,--*)
+			__gitcomp "--index"
+			;;
+		show,--*|drop,--*|pop,--*|branch,--*)
+			COMPREPLY=()
+			;;
+		show,*|apply,*|drop,*|pop,*|branch,*)
+			__gitcomp "$(git --git-dir="$(__gitdir)" stash list \
+					| sed -n -e 's/:.*//p')"
+			;;
+		*)
+			COMPREPLY=()
+			;;
+		esac
 	fi
 }
 
@@ -1317,7 +1566,7 @@
 	-m|-F)
 		COMPREPLY=()
 		;;
-	-*|tag|git-tag)
+	-*|tag)
 		if [ $f = 1 ]; then
 			__gitcomp "$(__git_tags)"
 		else
@@ -1339,7 +1588,8 @@
 		case "$i" in
 		--git-dir=*) __git_dir="${i#--git-dir=}" ;;
 		--bare)      __git_dir="." ;;
-		--version|--help|-p|--paginate) ;;
+		--version|-p|--paginate) ;;
+		--help) command="help"; break ;;
 		*) command="$i"; break ;;
 		esac
 		c=$((++c))
@@ -1359,7 +1609,7 @@
 			--help
 			"
 			;;
-		*)     __gitcomp "$(__git_commands) $(__git_aliases)" ;;
+		*)     __gitcomp "$(__git_porcelain_commands) $(__git_aliases)" ;;
 		esac
 		return
 	fi
@@ -1371,12 +1621,15 @@
 	am)          _git_am ;;
 	add)         _git_add ;;
 	apply)       _git_apply ;;
+	archive)     _git_archive ;;
 	bisect)      _git_bisect ;;
 	bundle)      _git_bundle ;;
 	branch)      _git_branch ;;
 	checkout)    _git_checkout ;;
 	cherry)      _git_cherry ;;
 	cherry-pick) _git_cherry_pick ;;
+	clean)       _git_clean ;;
+	clone)       _git_clone ;;
 	commit)      _git_commit ;;
 	config)      _git_config ;;
 	describe)    _git_describe ;;
@@ -1384,20 +1637,29 @@
 	fetch)       _git_fetch ;;
 	format-patch) _git_format_patch ;;
 	gc)          _git_gc ;;
+	grep)        _git_grep ;;
+	help)        _git_help ;;
+	init)        _git_init ;;
 	log)         _git_log ;;
+	ls-files)    _git_ls_files ;;
 	ls-remote)   _git_ls_remote ;;
 	ls-tree)     _git_ls_tree ;;
 	merge)       _git_merge;;
+	mergetool)   _git_mergetool;;
 	merge-base)  _git_merge_base ;;
+	mv)          _git_mv ;;
 	name-rev)    _git_name_rev ;;
 	pull)        _git_pull ;;
 	push)        _git_push ;;
 	rebase)      _git_rebase ;;
 	remote)      _git_remote ;;
 	reset)       _git_reset ;;
+	revert)      _git_revert ;;
+	rm)          _git_rm ;;
+	send-email)  _git_send_email ;;
 	shortlog)    _git_shortlog ;;
 	show)        _git_show ;;
-	show-branch) _git_log ;;
+	show-branch) _git_show_branch ;;
 	stash)       _git_stash ;;
 	submodule)   _git_submodule ;;
 	svn)         _git_svn ;;
@@ -1428,64 +1690,11 @@
 
 complete -o default -o nospace -F _git git
 complete -o default -o nospace -F _gitk gitk
-complete -o default -o nospace -F _git_am git-am
-complete -o default -o nospace -F _git_apply git-apply
-complete -o default -o nospace -F _git_bisect git-bisect
-complete -o default -o nospace -F _git_branch git-branch
-complete -o default -o nospace -F _git_bundle git-bundle
-complete -o default -o nospace -F _git_checkout git-checkout
-complete -o default -o nospace -F _git_cherry git-cherry
-complete -o default -o nospace -F _git_cherry_pick git-cherry-pick
-complete -o default -o nospace -F _git_commit git-commit
-complete -o default -o nospace -F _git_describe git-describe
-complete -o default -o nospace -F _git_diff git-diff
-complete -o default -o nospace -F _git_fetch git-fetch
-complete -o default -o nospace -F _git_format_patch git-format-patch
-complete -o default -o nospace -F _git_gc git-gc
-complete -o default -o nospace -F _git_log git-log
-complete -o default -o nospace -F _git_ls_remote git-ls-remote
-complete -o default -o nospace -F _git_ls_tree git-ls-tree
-complete -o default -o nospace -F _git_merge git-merge
-complete -o default -o nospace -F _git_merge_base git-merge-base
-complete -o default -o nospace -F _git_name_rev git-name-rev
-complete -o default -o nospace -F _git_pull git-pull
-complete -o default -o nospace -F _git_push git-push
-complete -o default -o nospace -F _git_rebase git-rebase
-complete -o default -o nospace -F _git_config git-config
-complete -o default -o nospace -F _git_remote git-remote
-complete -o default -o nospace -F _git_reset git-reset
-complete -o default -o nospace -F _git_shortlog git-shortlog
-complete -o default -o nospace -F _git_show git-show
-complete -o default -o nospace -F _git_stash git-stash
-complete -o default -o nospace -F _git_submodule git-submodule
-complete -o default -o nospace -F _git_svn git-svn
-complete -o default -o nospace -F _git_log git-show-branch
-complete -o default -o nospace -F _git_tag git-tag
-complete -o default -o nospace -F _git_log git-whatchanged
 
 # The following are necessary only for Cygwin, and only are needed
 # when the user has tab-completed the executable name and consequently
 # included the '.exe' suffix.
 #
 if [ Cygwin = "$(uname -o 2>/dev/null)" ]; then
-complete -o default -o nospace -F _git_add git-add.exe
-complete -o default -o nospace -F _git_apply git-apply.exe
 complete -o default -o nospace -F _git git.exe
-complete -o default -o nospace -F _git_branch git-branch.exe
-complete -o default -o nospace -F _git_bundle git-bundle.exe
-complete -o default -o nospace -F _git_cherry git-cherry.exe
-complete -o default -o nospace -F _git_describe git-describe.exe
-complete -o default -o nospace -F _git_diff git-diff.exe
-complete -o default -o nospace -F _git_format_patch git-format-patch.exe
-complete -o default -o nospace -F _git_log git-log.exe
-complete -o default -o nospace -F _git_ls_tree git-ls-tree.exe
-complete -o default -o nospace -F _git_merge_base git-merge-base.exe
-complete -o default -o nospace -F _git_name_rev git-name-rev.exe
-complete -o default -o nospace -F _git_push git-push.exe
-complete -o default -o nospace -F _git_config git-config
-complete -o default -o nospace -F _git_shortlog git-shortlog.exe
-complete -o default -o nospace -F _git_show git-show.exe
-complete -o default -o nospace -F _git_log git-show-branch.exe
-complete -o default -o nospace -F _git_tag git-tag.exe
-complete -o default -o nospace -F _git_log git-whatchanged.exe
 fi
diff --git a/contrib/emacs/git-blame.el b/contrib/emacs/git-blame.el
index 9f92cd2..4fa70c5 100644
--- a/contrib/emacs/git-blame.el
+++ b/contrib/emacs/git-blame.el
@@ -381,7 +381,7 @@
                   "log" "-1"
 		  (concat "--pretty=" git-blame-log-oneline-format)
                   hash)
-    (buffer-substring (point-min) (1- (point-max)))))
+    (buffer-substring (point-min) (point-max))))
 
 (defvar git-blame-last-identification nil)
 (make-variable-buffer-local 'git-blame-last-identification)
diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el
index 4fa853f..c1cf1cb 100644
--- a/contrib/emacs/git.el
+++ b/contrib/emacs/git.el
@@ -1252,8 +1252,8 @@
        "\n")
       (when subject (insert subject "\n\n"))
       (cond (msg (insert msg "\n"))
-            ((file-readable-p ".dotest/msg")
-             (insert-file-contents ".dotest/msg"))
+            ((file-readable-p ".git/rebase-apply/msg")
+             (insert-file-contents ".git/rebase-apply/msg"))
             ((file-readable-p ".git/MERGE_MSG")
              (insert-file-contents ".git/MERGE_MSG")))
       ; delete empty lines at end
@@ -1272,9 +1272,9 @@
           (coding-system (git-get-commits-coding-system))
           author-name author-email subject date)
       (when (eq 0 (buffer-size buffer))
-        (when (file-readable-p ".dotest/info")
+        (when (file-readable-p ".git/rebase-apply/info")
           (with-temp-buffer
-            (insert-file-contents ".dotest/info")
+            (insert-file-contents ".git/rebase-apply/info")
             (goto-char (point-min))
             (when (re-search-forward "^Author: \\(.*\\)\nEmail: \\(.*\\)$" nil t)
               (setq author-name (match-string 1))
diff --git a/contrib/examples/git-commit.sh b/contrib/examples/git-commit.sh
index 2c4a406..5c72f65 100755
--- a/contrib/examples/git-commit.sh
+++ b/contrib/examples/git-commit.sh
@@ -443,7 +443,7 @@
 
 case "$signoff" in
 t)
-	sign=$(git-var GIT_COMMITTER_IDENT | sed -e '
+	sign=$(git var GIT_COMMITTER_IDENT | sed -e '
 		s/>.*/>/
 		s/^/Signed-off-by: /
 		')
@@ -535,8 +535,8 @@
 
 case "$no_edit" in
 '')
-	git-var GIT_AUTHOR_IDENT > /dev/null  || die
-	git-var GIT_COMMITTER_IDENT > /dev/null  || die
+	git var GIT_AUTHOR_IDENT > /dev/null  || die
+	git var GIT_COMMITTER_IDENT > /dev/null  || die
 	git_editor "$GIT_DIR/COMMIT_EDITMSG"
 	;;
 esac
diff --git a/git-merge.sh b/contrib/examples/git-merge.sh
similarity index 98%
rename from git-merge.sh
rename to contrib/examples/git-merge.sh
index 8026ccf..e9588ee 100755
--- a/git-merge.sh
+++ b/contrib/examples/git-merge.sh
@@ -5,8 +5,8 @@
 
 OPTIONS_KEEPDASHDASH=
 OPTIONS_SPEC="\
-git-merge [options] <remote>...
-git-merge [options] <msg> HEAD <remote>
+git merge [options] <remote>...
+git merge [options] <msg> HEAD <remote>
 --
 stat                 show a diffstat at the end of the merge
 n                    don't show a diffstat at the end of the merge
diff --git a/contrib/examples/git-remote.perl b/contrib/examples/git-remote.perl
index b30ed73..b17952a 100755
--- a/contrib/examples/git-remote.perl
+++ b/contrib/examples/git-remote.perl
@@ -129,10 +129,7 @@
 	return if (($harder == 0) ||
 		   (($harder == 1) && exists $info->{'LS_REMOTE'}));
 
-	my @ref = map {
-		s|^[0-9a-f]{40}\s+refs/heads/||;
-		$_;
-	} $git->command(qw(ls-remote --heads), $info->{'URL'});
+	my @ref = map { s|refs/heads/||; $_; } keys %{$git->remote_refs($info->{'URL'}, [ 'heads' ])};
 	$info->{'LS_REMOTE'} = \@ref;
 }
 
@@ -312,7 +309,7 @@
 			}
 		}
 	} else {
-		print STDERR "Remote group $name does not exists.\n";
+		print STDERR "Remote group $name does not exist.\n";
 		exit(1);
 	}
 	for (@remotes) {
diff --git a/contrib/examples/git-svnimport.perl b/contrib/examples/git-svnimport.perl
index ea8c1b2..a13bb6a 100755
--- a/contrib/examples/git-svnimport.perl
+++ b/contrib/examples/git-svnimport.perl
@@ -933,7 +933,7 @@
 	$to_rev = $from_rev + $repack_after;
 	$to_rev = $opt_l if $opt_l < $to_rev;
 	print "Fetching from $from_rev to $to_rev ...\n" if $opt_v;
-	$svn->{'svn'}->get_log("/",$from_rev,$to_rev,0,1,1,\&commit_all);
+	$svn->{'svn'}->get_log("",$from_rev,$to_rev,0,1,1,\&commit_all);
 	my $pid = fork();
 	die "Fork: $!\n" unless defined $pid;
 	unless($pid) {
diff --git a/contrib/examples/git-tag.sh b/contrib/examples/git-tag.sh
index e9f3a22..2c15bc9 100755
--- a/contrib/examples/git-tag.sh
+++ b/contrib/examples/git-tag.sh
@@ -164,7 +164,7 @@
 
 object=$(git rev-parse --verify --default HEAD "$@") || exit 1
 type=$(git cat-file -t $object) || exit 1
-tagger=$(git-var GIT_COMMITTER_IDENT) || exit 1
+tagger=$(git var GIT_COMMITTER_IDENT) || exit 1
 
 test -n "$username" ||
 	username=$(git config user.signingkey) ||
diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4
index d8de9f6..2b122d3 100755
--- a/contrib/fast-import/git-p4
+++ b/contrib/fast-import/git-p4
@@ -16,6 +16,46 @@
 
 verbose = False
 
+
+def p4_build_cmd(cmd):
+    """Build a suitable p4 command line.
+
+    This consolidates building and returning a p4 command line into one
+    location. It means that hooking into the environment, or other configuration
+    can be done more easily.
+    """
+    real_cmd = "%s " % "p4"
+
+    user = gitConfig("git-p4.user")
+    if len(user) > 0:
+        real_cmd += "-u %s " % user
+
+    password = gitConfig("git-p4.password")
+    if len(password) > 0:
+        real_cmd += "-P %s " % password
+
+    port = gitConfig("git-p4.port")
+    if len(port) > 0:
+        real_cmd += "-p %s " % port
+
+    host = gitConfig("git-p4.host")
+    if len(host) > 0:
+        real_cmd += "-h %s " % host
+
+    client = gitConfig("git-p4.client")
+    if len(client) > 0:
+        real_cmd += "-c %s " % client
+
+    real_cmd += "%s" % (cmd)
+    if verbose:
+        print real_cmd
+    return real_cmd
+
+def chdir(dir):
+    if os.name == 'nt':
+        os.environ['PWD']=dir
+    os.chdir(dir)
+
 def die(msg):
     if verbose:
         raise Exception(msg)
@@ -34,6 +74,10 @@
 
     return val
 
+def p4_write_pipe(c, str):
+    real_cmd = p4_build_cmd(c)
+    return write_pipe(real_cmd, str)
+
 def read_pipe(c, ignore_error=False):
     if verbose:
         sys.stderr.write('Reading pipe: %s\n' % c)
@@ -45,6 +89,9 @@
 
     return val
 
+def p4_read_pipe(c, ignore_error=False):
+    real_cmd = p4_build_cmd(c)
+    return read_pipe(real_cmd, ignore_error)
 
 def read_pipe_lines(c):
     if verbose:
@@ -57,12 +104,22 @@
 
     return val
 
+def p4_read_pipe_lines(c):
+    """Specifically invoke p4 on the command supplied. """
+    real_cmd = p4_build_cmd(c)
+    return read_pipe_lines(real_cmd)
+
 def system(cmd):
     if verbose:
         sys.stderr.write("executing %s\n" % cmd)
     if os.system(cmd) != 0:
         die("command failed: %s" % cmd)
 
+def p4_system(cmd):
+    """Specifically invoke p4 as the system command. """
+    real_cmd = p4_build_cmd(cmd)
+    return system(real_cmd)
+
 def isP4Exec(kind):
     """Determine if a Perforce 'kind' should have execute permission
 
@@ -84,12 +141,12 @@
         if p4Type[-1] == "+":
             p4Type = p4Type[0:-1]
 
-    system("p4 reopen -t %s %s" % (p4Type, file))
+    p4_system("reopen -t %s %s" % (p4Type, file))
 
 def getP4OpenedType(file):
     # Returns the perforce file type for the given file.
 
-    result = read_pipe("p4 opened %s" % file)
+    result = p4_read_pipe("opened %s" % file)
     match = re.match(".*\((.+)\)\r?$", result)
     if match:
         return match.group(1)
@@ -145,7 +202,7 @@
     return isModeExec(src_mode) != isModeExec(dst_mode)
 
 def p4CmdList(cmd, stdin=None, stdin_mode='w+b'):
-    cmd = "p4 -G %s" % cmd
+    cmd = p4_build_cmd("-G %s" % (cmd))
     if verbose:
         sys.stderr.write("Opening pipe: %s\n" % cmd)
 
@@ -364,7 +421,7 @@
 
 def p4ChangesForPaths(depotPaths, changeRange):
     assert depotPaths
-    output = read_pipe_lines("p4 changes " + ' '.join (["%s...%s" % (p, changeRange)
+    output = p4_read_pipe_lines("changes " + ' '.join (["%s...%s" % (p, changeRange)
                                                         for p in depotPaths]))
 
     changes = []
@@ -512,7 +569,7 @@
         # remove lines in the Files section that show changes to files outside the depot path we're committing into
         template = ""
         inFilesSection = False
-        for line in read_pipe_lines("p4 change -o"):
+        for line in p4_read_pipe_lines("change -o"):
             if line.endswith("\r\n"):
                 line = line[:-2] + "\n"
             if inFilesSection:
@@ -547,7 +604,7 @@
             modifier = diff['status']
             path = diff['src']
             if modifier == "M":
-                system("p4 edit \"%s\"" % path)
+                p4_system("edit \"%s\"" % path)
                 if isModeExecChanged(diff['src_mode'], diff['dst_mode']):
                     filesToChangeExecBit[path] = diff['dst_mode']
                 editedFiles.add(path)
@@ -562,8 +619,8 @@
                     filesToAdd.remove(path)
             elif modifier == "R":
                 src, dest = diff['src'], diff['dst']
-                system("p4 integrate -Dt \"%s\" \"%s\"" % (src, dest))
-                system("p4 edit \"%s\"" % (dest))
+                p4_system("integrate -Dt \"%s\" \"%s\"" % (src, dest))
+                p4_system("edit \"%s\"" % (dest))
                 if isModeExecChanged(diff['src_mode'], diff['dst_mode']):
                     filesToChangeExecBit[dest] = diff['dst_mode']
                 os.unlink(dest)
@@ -587,7 +644,7 @@
             if response == "s":
                 print "Skipping! Good luck with the next patches..."
                 for f in editedFiles:
-                    system("p4 revert \"%s\"" % f);
+                    p4_system("revert \"%s\"" % f);
                 for f in filesToAdd:
                     system("rm %s" %f)
                 return
@@ -610,10 +667,10 @@
         system(applyPatchCmd)
 
         for f in filesToAdd:
-            system("p4 add \"%s\"" % f)
+            p4_system("add \"%s\"" % f)
         for f in filesToDelete:
-            system("p4 revert \"%s\"" % f)
-            system("p4 delete \"%s\"" % f)
+            p4_system("revert \"%s\"" % f)
+            p4_system("delete \"%s\"" % f)
 
         # Set/clear executable bits
         for f in filesToChangeExecBit.keys():
@@ -629,7 +686,7 @@
             submitTemplate = self.prepareLogMessage(template, logMessage)
             if os.environ.has_key("P4DIFF"):
                 del(os.environ["P4DIFF"])
-            diff = read_pipe("p4 diff -du ...")
+            diff = p4_read_pipe("diff -du ...")
 
             newdiff = ""
             for newFile in filesToAdd:
@@ -667,7 +724,7 @@
             if self.isWindows:
                 submitTemplate = submitTemplate.replace("\r\n", "\n")
 
-            write_pipe("p4 submit -i", submitTemplate)
+            p4_write_pipe("submit -i", submitTemplate)
         else:
             fileName = "submit.txt"
             file = open(fileName, "w+")
@@ -687,6 +744,10 @@
         else:
             return False
 
+        allowSubmit = gitConfig("git-p4.allowSubmit")
+        if len(allowSubmit) > 0 and not self.master in allowSubmit.split(","):
+            die("%s is not in git-p4.allowSubmit" % self.master)
+
         [upstream, settings] = findUpstreamBranchPoint()
         self.depotPath = settings['depot-paths'][0]
         if len(self.origin) == 0:
@@ -708,9 +769,9 @@
         print "Perforce checkout for depot path %s located at %s" % (self.depotPath, self.clientPath)
         self.oldWorkingDirectory = os.getcwd()
 
-        os.chdir(self.clientPath)
+        chdir(self.clientPath)
         print "Syncronizing p4 checkout..."
-        system("p4 sync ...")
+        p4_system("sync ...")
 
         self.check()
 
@@ -728,7 +789,7 @@
 
         if len(commits) == 0:
             print "All changes applied!"
-            os.chdir(self.oldWorkingDirectory)
+            chdir(self.oldWorkingDirectory)
 
             sync = P4Sync()
             sync.run([])
@@ -902,7 +963,7 @@
             if stat['type'] in ('text+ko', 'unicode+ko', 'binary+ko'):
                 text = re.sub(r'(?i)\$(Id|Header):[^$]*\$',r'$\1$', text)
             elif stat['type'] in ('text+k', 'ktext', 'kxtext', 'unicode+k', 'binary+k'):
-                text = re.sub(r'(?i)\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$]*\$',r'$\1$', text)
+                text = re.sub(r'\$(Id|Header|Author|Date|DateTime|Change|File|Revision):[^$\n]*\$',r'$\1$', text)
 
             contents[stat['depotFile']] = text
 
@@ -1395,7 +1456,7 @@
             if not gitBranchExists(self.refPrefix + "HEAD") and self.importIntoRemotes and gitBranchExists(self.branch):
                 system("git symbolic-ref %sHEAD %s" % (self.refPrefix, self.branch))
 
-        if self.useClientSpec or gitConfig("p4.useclientspec") == "true":
+        if self.useClientSpec or gitConfig("git-p4.useclientspec") == "true":
             self.getClientSpec()
 
         # TODO: should always look at previous commits,
@@ -1666,7 +1727,7 @@
         print "Importing from %s into %s" % (', '.join(depotPaths), self.cloneDestination)
         if not os.path.exists(self.cloneDestination):
             os.makedirs(self.cloneDestination)
-        os.chdir(self.cloneDestination)
+        chdir(self.cloneDestination)
         system("git init")
         self.gitdir = os.getcwd() + "/.git"
         if not P4Sync.run(self, depotPaths):
@@ -1778,7 +1839,7 @@
                 if os.path.exists(cmd.gitdir):
                     cdup = read_pipe("git rev-parse --show-cdup").strip()
                     if len(cdup) > 0:
-                        os.chdir(cdup);
+                        chdir(cdup);
 
         if not isValidGitDir(cmd.gitdir):
             if isValidGitDir(cmd.gitdir + "/.git"):
diff --git a/contrib/fast-import/git-p4.txt b/contrib/fast-import/git-p4.txt
index b16a838..49b3359 100644
--- a/contrib/fast-import/git-p4.txt
+++ b/contrib/fast-import/git-p4.txt
@@ -3,14 +3,16 @@
 Usage
 =====
 
-git-p4 supports two main modes: Importing from Perforce to a Git repository is
-done using "git-p4 sync" or "git-p4 rebase". Submitting changes from Git back
-to Perforce is done using "git-p4 submit".
+git-p4 can be used in two different ways:
+
+1) To import changes from Perforce to a Git repository, using "git-p4 sync".
+
+2) To submit changes from Git back to Perforce, using "git-p4 submit".
 
 Importing
 =========
 
-You can simply start with
+Simply start with
 
   git-p4 clone //depot/path/project
 
@@ -18,11 +20,18 @@
 
   git-p4 clone //depot/path/project myproject
 
-This will create an empty git repository in a subdirectory called "project" (or
-"myproject" with the second command), import the head revision from the
-specified perforce path into a git "p4" branch (remotes/p4 actually), create a
-master branch off it and check it out. If you want the entire history (not just
-the head revision) then you can simply append a "@all" to the depot path:
+This will:
+
+1) Create an empty git repository in a subdirectory called "project" (or
+"myproject" with the second command)
+
+2) Import the head revision from the given Perforce path into a git branch
+called "p4" (remotes/p4 actually)
+
+3) Create a master branch based on it and check it out.
+
+If you want the entire history (not just the head revision) then you can simply
+append a "@all" to the depot path:
 
   git-p4 clone //depot/project/main@all myproject
 
@@ -37,43 +46,40 @@
 
 This will import the current head revision of the specified depot path into a
 "remotes/p4/master" branch of your git repository. You can use the
---branch=mybranch option to use a different branch.
+--branch=mybranch option to import into a different branch.
 
-If you want to import the entire history of a given depot path just use
+If you want to import the entire history of a given depot path simply use:
 
   git-p4 sync //path/in/depot@all
 
+
+Note:
+
 To achieve optimal compression you may want to run 'git repack -a -d -f' after
 a big import. This may take a while.
 
-Support for Perforce integrations is still work in progress. Don't bother
-trying it unless you want to hack on it :)
-
 Incremental Imports
 ===================
 
-After an initial import you can easily synchronize your git repository with
-newer changes from the Perforce depot by just calling
+After an initial import you can continue to synchronize your git repository
+with newer changes from the Perforce depot by just calling
 
   git-p4 sync
 
 in your git repository. By default the "remotes/p4/master" branch is updated.
 
-It is recommended to run 'git repack -a -d -f' from time to time when using
-incremental imports to optimally combine the individual git packs that each
-incremental import creates through the use of git-fast-import.
+Advanced Setup
+==============
 
+Suppose you have a periodically updated git repository somewhere, containing a
+complete import of a Perforce project. This repository can be cloned and used
+with git-p4. When updating the cloned repository with the "sync" command,
+git-p4 will try to fetch changes from the original repository first. The git
+protocol used with this is usually faster than importing from Perforce
+directly.
 
-A useful setup may be that you have a periodically updated git repository
-somewhere that contains a complete import of a Perforce project. That git
-repository can be used to clone the working repository from and one would
-import from Perforce directly after cloning using git-p4. If the connection to
-the Perforce server is slow and the working repository hasn't been synced for a
-while it may be desirable to fetch changes from the origin git repository using
-the efficient git protocol. git-p4 supports this setup by calling "git fetch origin"
-by default if there is an origin branch. You can disable this using
-
-  git config git-p4.syncFromOrigin false
+This behaviour can be disabled by setting the "git-p4.syncFromOrigin" git
+configuration variable to "false".
 
 Updating
 ========
@@ -91,7 +97,7 @@
 ==========
 
 git-p4 has support for submitting changes from a git repository back to the
-Perforce depot. This requires a Perforce checkout separate to your git
+Perforce depot. This requires a Perforce checkout separate from your git
 repository. To submit all changes that are in the current git branch but not in
 the "p4" branch (or "origin" if "p4" doesn't exist) simply call
 
@@ -109,17 +115,6 @@
 
   git-p4 submit --continue
 
-After submitting you should sync your perforce import branch ("p4" or "origin")
-from Perforce using git-p4's sync command.
-
-If you have changes in your working directory that you haven't committed into
-git yet but that you want to commit to Perforce directly ("quick fixes") then
-you do not have to go through the intermediate step of creating a git commit
-first but you can just call
-
-  git-p4 submit --direct
-
-
 Example
 =======
 
@@ -140,6 +135,62 @@
   git-p4 rebase
 
 
+Configuration parameters
+========================
+
+git-p4.user ($P4USER)
+
+Allows you to specify the username to use to connect to the Perforce repository.
+
+  git config [--global] git-p4.user public
+
+git-p4.password ($P4PASS)
+
+Allows you to specify the password to use to connect to the Perforce repository.
+Warning this password will be visible on the command-line invocation of the p4 binary.
+
+  git config [--global] git-p4.password public1234
+
+git-p4.port ($P4PORT)
+
+Specify the port to be used to contact the Perforce server. As this will be passed
+directly to the p4 binary, it may be in the format host:port as well.
+
+  git config [--global] git-p4.port codes.zimbra.com:2666
+
+git-p4.host ($P4HOST)
+
+Specify the host to contact for a Perforce repository.
+
+  git config [--global] git-p4.host perforce.example.com
+
+git-p4.client ($P4CLIENT)
+
+Specify the client name to use
+
+  git config [--global] git-p4.client public-view
+
+git-p4.allowSubmit
+
+  git config [--global] git-p4.allowSubmit false
+
+git-p4.syncFromOrigin
+
+A useful setup may be that you have a periodically updated git repository
+somewhere that contains a complete import of a Perforce project. That git
+repository can be used to clone the working repository from and one would
+import from Perforce directly after cloning using git-p4. If the connection to
+the Perforce server is slow and the working repository hasn't been synced for a
+while it may be desirable to fetch changes from the origin git repository using
+the efficient git protocol. git-p4 supports this setup by calling "git fetch origin"
+by default if there is an origin branch. You can disable this using:
+
+  git config [--global] git-p4.syncFromOrigin false
+
+git-p4.useclientspec
+
+  git config [--global] git-p4.useclientspec false
+
 Implementation Details...
 =========================
 
diff --git a/contrib/fast-import/import-zips.py b/contrib/fast-import/import-zips.py
new file mode 100755
index 0000000..c674fa2
--- /dev/null
+++ b/contrib/fast-import/import-zips.py
@@ -0,0 +1,72 @@
+#!/usr/bin/python
+
+## zip archive frontend for git-fast-import
+##
+## For example:
+##
+##  mkdir project; cd project; git init
+##  python import-zips.py *.zip
+##  git log --stat import-zips
+
+from os import popen, path
+from sys import argv, exit
+from time import mktime
+from zipfile import ZipFile
+
+if len(argv) < 2:
+	print 'Usage:', argv[0], '<zipfile>...'
+	exit(1)
+
+branch_ref = 'refs/heads/import-zips'
+committer_name = 'Z Ip Creator'
+committer_email = 'zip@example.com'
+
+fast_import = popen('git fast-import --quiet', 'w')
+def printlines(list):
+	for str in list:
+		fast_import.write(str + "\n")
+
+for zipfile in argv[1:]:
+	commit_time = 0
+	next_mark = 1
+	common_prefix = None
+	mark = dict()
+
+	zip = ZipFile(zipfile, 'r')
+	for name in zip.namelist():
+		if name.endswith('/'):
+			continue
+		info = zip.getinfo(name)
+
+		if commit_time < info.date_time:
+			commit_time = info.date_time
+		if common_prefix == None:
+			common_prefix = name[:name.rfind('/') + 1]
+		else:
+			while not name.startswith(common_prefix):
+				common_prefix = name[:name.rfind('/') + 1]
+
+		mark[name] = ':' + str(next_mark)
+		next_mark += 1
+
+		printlines(('blob', 'mark ' + mark[name], \
+					'data ' + str(info.file_size)))
+		fast_import.write(zip.read(name) + "\n")
+
+	committer = committer_name + ' <' + committer_email + '> %d +0000' % \
+		mktime(commit_time + (0, 0, 0))
+
+	printlines(('commit ' + branch_ref, 'committer ' + committer, \
+		'data <<EOM', 'Imported from ' + zipfile + '.', 'EOM', \
+		'', 'deleteall'))
+
+	for name in mark.keys():
+		fast_import.write('M 100644 ' + mark[name] + ' ' +
+			name[len(common_prefix):] + "\n")
+
+	printlines(('',  'tag ' + path.basename(zipfile), \
+		'from ' + branch_ref, 'tagger ' + committer, \
+		'data <<EOM', 'Package ' + zipfile, 'EOM', ''))
+
+if fast_import.close():
+	exit(1)
diff --git a/contrib/hg-to-git/hg-to-git.py b/contrib/hg-to-git/hg-to-git.py
index f68ef72..7b03204 100755
--- a/contrib/hg-to-git/hg-to-git.py
+++ b/contrib/hg-to-git/hg-to-git.py
@@ -89,7 +89,7 @@
         if o in ('-v', '--verbose'):
             verbose = True
     if len(args) != 1:
-        raise('params')
+        raise Exception('params')
 except:
     usage()
     sys.exit(1)
@@ -106,7 +106,10 @@
     else:
         print 'State does not exist, first run'
 
-tip = os.popen('hg tip --template "{rev}"').read()
+sock = os.popen('hg tip --template "{rev}"')
+tip = sock.read()
+if sock.close():
+    sys.exit(1)
 if verbose:
     print 'tip is', tip
 
@@ -149,7 +152,7 @@
 
 if not hgvers.has_key("0"):
     print 'creating repository'
-    os.system('git-init-db')
+    os.system('git init')
 
 # loop through every hg changeset
 for cset in range(int(tip) + 1):
@@ -191,10 +194,10 @@
     if cset != 0:
         if hgbranch[str(cset)] == "branch-" + str(cset):
             print 'creating new branch', hgbranch[str(cset)]
-            os.system('git-checkout -b %s %s' % (hgbranch[str(cset)], hgvers[parent]))
+            os.system('git checkout -b %s %s' % (hgbranch[str(cset)], hgvers[parent]))
         else:
             print 'checking out branch', hgbranch[str(cset)]
-            os.system('git-checkout %s' % hgbranch[str(cset)])
+            os.system('git checkout %s' % hgbranch[str(cset)])
 
     # merge
     if mparent:
@@ -203,7 +206,7 @@
         else:
             otherbranch = hgbranch[parent]
         print 'merging', otherbranch, 'into', hgbranch[str(cset)]
-        os.system(getgitenv(user, date) + 'git-merge --no-commit -s ours "" %s %s' % (hgbranch[str(cset)], otherbranch))
+        os.system(getgitenv(user, date) + 'git merge --no-commit -s ours "" %s %s' % (hgbranch[str(cset)], otherbranch))
 
     # remove everything except .git and .hg directories
     os.system('find . \( -path "./.hg" -o -path "./.git" \) -prune -o ! -name "." -print | xargs rm -rf')
@@ -212,9 +215,9 @@
     os.system('hg update -C %d' % cset)
 
     # add new files
-    os.system('git-ls-files -x .hg --others | git-update-index --add --stdin')
+    os.system('git ls-files -x .hg --others | git update-index --add --stdin')
     # delete removed files
-    os.system('git-ls-files -x .hg --deleted | git-update-index --remove --stdin')
+    os.system('git ls-files -x .hg --deleted | git update-index --remove --stdin')
 
     # commit
     os.system(getgitenv(user, date) + 'git commit --allow-empty -a -F %s' % filecomment)
@@ -222,20 +225,20 @@
 
     # tag
     if tag and tag != 'tip':
-        os.system(getgitenv(user, date) + 'git-tag %s' % tag)
+        os.system(getgitenv(user, date) + 'git tag %s' % tag)
 
     # delete branch if not used anymore...
     if mparent and len(hgchildren[str(cset)]):
         print "Deleting unused branch:", otherbranch
-        os.system('git-branch -d %s' % otherbranch)
+        os.system('git branch -d %s' % otherbranch)
 
     # retrieve and record the version
-    vvv = os.popen('git-show --quiet --pretty=format:%H').read()
+    vvv = os.popen('git show --quiet --pretty=format:%H').read()
     print 'record', cset, '->', vvv
     hgvers[str(cset)] = vvv
 
 if hgnewcsets >= opt_nrepack and opt_nrepack != -1:
-    os.system('git-repack -a -d')
+    os.system('git repack -a -d')
 
 # write the state for incrementals
 if state:
diff --git a/contrib/hooks/setgitperms.perl b/contrib/hooks/setgitperms.perl
index dab7c8e..a577ad0 100644
--- a/contrib/hooks/setgitperms.perl
+++ b/contrib/hooks/setgitperms.perl
@@ -50,7 +50,7 @@
 			      )) { die $usage; }
 die $usage unless ($read_mode xor $write_mode);
 
-my $topdir = `git-rev-parse --show-cdup` or die "\n"; chomp $topdir;
+my $topdir = `git rev-parse --show-cdup` or die "\n"; chomp $topdir;
 my $gitdir = $topdir . '.git';
 my $gitmeta = $topdir . '.gitmeta';
 
@@ -155,7 +155,7 @@
 	open (OUT, ">$gitmeta.tmp") or die "Could not open $gitmeta.tmp for writing: $!\n";
     }
 
-    my @files = `git-ls-files`;
+    my @files = `git ls-files`;
     my %dirs;
 
     foreach my $path (@files) {
diff --git a/contrib/stats/packinfo.pl b/contrib/stats/packinfo.pl
index f4a7b62..be188c0 100755
--- a/contrib/stats/packinfo.pl
+++ b/contrib/stats/packinfo.pl
@@ -1,9 +1,9 @@
 #!/usr/bin/perl
 #
 # This tool will print vaguely pretty information about a pack.  It
-# expects the output of "git-verify-pack -v" as input on stdin.
+# expects the output of "git verify-pack -v" as input on stdin.
 #
-# $ git-verify-pack -v | packinfo.pl
+# $ git verify-pack -v | packinfo.pl
 #
 # This prints some full-pack statistics; currently "all sizes", "all
 # path sizes", "tree sizes", "tree path sizes", and "depths".
@@ -20,7 +20,7 @@
 #
 # When run as:
 #
-# $ git-verify-pack -v | packinfo.pl -tree
+# $ git verify-pack -v | packinfo.pl -tree
 #
 # the trees of objects are output along with the stats.  This looks
 # like:
@@ -43,7 +43,7 @@
 #
 # When run as:
 #
-# $ git-verify-pack -v | packinfo.pl -tree -filenames
+# $ git verify-pack -v | packinfo.pl -tree -filenames
 #
 # it adds filenames to the tree.  Getting this information is slow:
 #
@@ -58,7 +58,7 @@
 #
 # When run as:
 #
-# $ git-verify-pack -v | packinfo.pl -dump
+# $ git verify-pack -v | packinfo.pl -dump
 #
 # it prints out "sha1 size pathsize depth" for each sha1 in lexical
 # order.
@@ -106,7 +106,7 @@
 }
 
 if ($filenames && ($tree || $dump)) {
-    open(NAMES, "git-name-rev --all|");
+    open(NAMES, "git name-rev --all|");
     while (<NAMES>) {
         if (/^(\S+)\s+(.*)$/) {
             my ($sha1, $name) = ($1, $2);
@@ -117,7 +117,7 @@
 
     for my $commit (@commits) {
         my $name = $names{$commit};
-        open(TREE, "git-ls-tree -t -r $commit|");
+        open(TREE, "git ls-tree -t -r $commit|");
         print STDERR "Plumbing tree $name\n";
         while (<TREE>) {
             if (/^(\S+)\s+(\S+)\s+(\S+)\s+(.*)$/) {
diff --git a/contrib/thunderbird-patch-inline/README b/contrib/thunderbird-patch-inline/README
new file mode 100644
index 0000000..39f96aa
--- /dev/null
+++ b/contrib/thunderbird-patch-inline/README
@@ -0,0 +1,20 @@
+appp.sh is a script that is supposed to be used together with ExternalEditor
+for Mozilla Thundebird. It will let you include patches inline in e-mails
+in an easy way.
+
+Usage:
+- Generate the patch with git format-patch.
+- Start writing a new e-mail in Thunderbird.
+- Press the external editor button (or Ctrl-E) to run appp.sh
+- Select the previosly generated patch file.
+- Finish editing the e-mail.
+
+Any text that is entered into the message editor before appp.sh is called
+will be moved to the section between the --- and the diffstat.
+
+All S-O-B:s and Cc:s in the patch will be added to the CC list.
+
+To set it up, just install External Editor and tell it to use appp.sh as the
+editor.
+
+Zenity is a required dependency.
diff --git a/contrib/thunderbird-patch-inline/appp.sh b/contrib/thunderbird-patch-inline/appp.sh
new file mode 100755
index 0000000..cc518f3
--- /dev/null
+++ b/contrib/thunderbird-patch-inline/appp.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+# Copyright 2008 Lukas Sandström <luksan@gmail.com>
+#
+# AppendPatch - A script to be used together with ExternalEditor
+# for Mozilla Thunderbird to properly include pathes inline i e-mails.
+
+# ExternalEditor can be downloaded at http://globs.org/articles.php?lng=en&pg=2
+
+CONFFILE=~/.appprc
+
+SEP="-=-=-=-=-=-=-=-=-=# Don't remove this line #=-=-=-=-=-=-=-=-=-"
+if [ -e "$CONFFILE" ] ; then
+	LAST_DIR=`grep -m 1 "^LAST_DIR=" "${CONFFILE}"|sed -e 's/^LAST_DIR=//'`
+	cd "${LAST_DIR}"
+else
+	cd > /dev/null
+fi
+
+PATCH=$(zenity --file-selection)
+
+if [ "$?" != "0" ] ; then
+	#zenity --error --text "No patchfile given."
+	exit 1
+fi
+
+cd - > /dev/null
+
+SUBJECT=`sed -n -e '/^Subject: /p' "${PATCH}"`
+HEADERS=`sed -e '/^'"${SEP}"'$/,$d' $1`
+BODY=`sed -e "1,/${SEP}/d" $1`
+CMT_MSG=`sed -e '1,/^$/d' -e '/^---$/,$d' "${PATCH}"`
+DIFF=`sed -e '1,/^---$/d' "${PATCH}"`
+
+CCS=`echo -e "$CMT_MSG\n$HEADERS" | sed -n -e 's/^Cc: \(.*\)$/\1,/gp' \
+	-e 's/^Signed-off-by: \(.*\)/\1,/gp'`
+
+echo "$SUBJECT" > $1
+echo "Cc: $CCS" >> $1
+echo "$HEADERS" | sed -e '/^Subject: /d' -e '/^Cc: /d' >> $1
+echo "$SEP" >> $1
+
+echo "$CMT_MSG" >> $1
+echo "---" >> $1
+if [ "x${BODY}x" != "xx" ] ; then
+	echo >> $1
+	echo "$BODY" >> $1
+	echo >> $1
+fi
+echo "$DIFF" >> $1
+
+LAST_DIR=`dirname "${PATCH}"`
+
+grep -v "^LAST_DIR=" "${CONFFILE}" > "${CONFFILE}_"
+echo "LAST_DIR=${LAST_DIR}" >> "${CONFFILE}_"
+mv "${CONFFILE}_" "${CONFFILE}"
diff --git a/convert.c b/convert.c
index 352b69d..78efed8 100644
--- a/convert.c
+++ b/convert.c
@@ -61,6 +61,10 @@
 		else
 			stats->printable++;
 	}
+
+	/* If file ends with EOF then don't count this EOF as non-printable. */
+	if (size >= 1 && buf[size-1] == '\032')
+		stats->nonprintable--;
 }
 
 /*
diff --git a/csum-file.c b/csum-file.c
index ace64f1..cfc1ac4 100644
--- a/csum-file.c
+++ b/csum-file.c
@@ -11,7 +11,7 @@
 #include "progress.h"
 #include "csum-file.h"
 
-static void sha1flush(struct sha1file *f, unsigned int count)
+static void flush(struct sha1file *f, unsigned int count)
 {
 	void *buf = f->buffer;
 
@@ -32,22 +32,28 @@
 	}
 }
 
-int sha1close(struct sha1file *f, unsigned char *result, unsigned int flags)
+void sha1flush(struct sha1file *f)
 {
-	int fd;
 	unsigned offset = f->offset;
 
 	if (offset) {
 		SHA1_Update(&f->ctx, f->buffer, offset);
-		sha1flush(f, offset);
+		flush(f, offset);
 		f->offset = 0;
 	}
+}
+
+int sha1close(struct sha1file *f, unsigned char *result, unsigned int flags)
+{
+	int fd;
+
+	sha1flush(f);
+	SHA1_Final(f->buffer, &f->ctx);
+	if (result)
+		hashcpy(result, f->buffer);
 	if (flags & (CSUM_CLOSE | CSUM_FSYNC)) {
 		/* write checksum and close fd */
-		SHA1_Final(f->buffer, &f->ctx);
-		if (result)
-			hashcpy(result, f->buffer);
-		sha1flush(f, 20);
+		flush(f, 20);
 		if (flags & CSUM_FSYNC)
 			fsync_or_die(f->fd, f->name);
 		if (close(f->fd))
@@ -76,7 +82,7 @@
 		left -= nr;
 		if (!left) {
 			SHA1_Update(&f->ctx, f->buffer, offset);
-			sha1flush(f, offset);
+			flush(f, offset);
 			offset = 0;
 		}
 		f->offset = offset;
diff --git a/csum-file.h b/csum-file.h
index 72c9487..01f13b5 100644
--- a/csum-file.h
+++ b/csum-file.h
@@ -24,6 +24,7 @@
 extern struct sha1file *sha1fd_throughput(int fd, const char *name, struct progress *tp);
 extern int sha1close(struct sha1file *, unsigned char *, unsigned int);
 extern int sha1write(struct sha1file *, void *, unsigned int);
+extern void sha1flush(struct sha1file *f);
 extern void crc32_begin(struct sha1file *);
 extern uint32_t crc32_end(struct sha1file *);
 
diff --git a/ctype.c b/ctype.c
index ee06eb7..d2bd38e 100644
--- a/ctype.c
+++ b/ctype.c
@@ -5,6 +5,11 @@
  */
 #include "cache.h"
 
+/* Just so that no insane platform contaminate namespace with these symbols */
+#undef SS
+#undef AA
+#undef DD
+
 #define SS GIT_SPACE
 #define AA GIT_ALPHA
 #define DD GIT_DIGIT
diff --git a/daemon.c b/daemon.c
index ce3a6f5..8dcde73 100644
--- a/daemon.c
+++ b/daemon.c
@@ -16,9 +16,10 @@
 static int log_syslog;
 static int verbose;
 static int reuseaddr;
+static int child_handler_pipe[2];
 
 static const char daemon_usage[] =
-"git-daemon [--verbose] [--syslog] [--export-all]\n"
+"git daemon [--verbose] [--syslog] [--export-all]\n"
 "           [--timeout=n] [--init-timeout=n] [--strict-paths]\n"
 "           [--base-path=path] [--base-path-relaxed]\n"
 "           [--user-path | --user-path=path]\n"
@@ -788,10 +789,12 @@
 				pid = -pid;
 			dead_child[reaped % MAX_CHILDREN] = pid;
 			children_reaped = reaped + 1;
+			write(child_handler_pipe[1], &status, 1);
 			continue;
 		}
 		break;
 	}
+	signal(SIGCHLD, child_handler);
 }
 
 static int set_reuse_addr(int sockfd)
@@ -933,29 +936,24 @@
 	struct pollfd *pfd;
 	int i;
 
-	pfd = xcalloc(socknum, sizeof(struct pollfd));
+	if (pipe(child_handler_pipe) < 0)
+		die ("Could not set up pipe for child handler");
+
+	pfd = xcalloc(socknum + 1, sizeof(struct pollfd));
 
 	for (i = 0; i < socknum; i++) {
 		pfd[i].fd = socklist[i];
 		pfd[i].events = POLLIN;
 	}
+	pfd[socknum].fd = child_handler_pipe[0];
+	pfd[socknum].events = POLLIN;
 
 	signal(SIGCHLD, child_handler);
 
 	for (;;) {
 		int i;
-		int timeout;
 
-		/*
-		 * This 1-sec timeout could lead to idly looping but it is
-		 * here so that children culled in child_handler() are reported
-		 * without too much delay.  We could probably set up a pipe
-		 * to ourselves that we poll, and write to the fd from child_handler()
-		 * to wake us up (and consume it when the poll() returns...
-		 */
-		timeout = (children_spawned != children_deleted) ? 1000 : -1;
-		i = poll(pfd, socknum, timeout);
-		if (i < 0) {
+		if (poll(pfd, socknum + 1, -1) < 0) {
 			if (errno != EINTR) {
 				error("poll failed, resuming: %s",
 				      strerror(errno));
@@ -963,9 +961,9 @@
 			}
 			continue;
 		}
-		if (i == 0) {
+		if (pfd[socknum].revents & POLLIN) {
+			read(child_handler_pipe[0], &i, 1);
 			check_dead_children();
-			continue;
 		}
 
 		for (i = 0; i < socknum; i++) {
diff --git a/date.c b/date.c
index 1a4eb87..950b88f 100644
--- a/date.c
+++ b/date.c
@@ -6,7 +6,10 @@
 
 #include "cache.h"
 
-static time_t my_mktime(struct tm *tm)
+/*
+ * This is like mktime, but without normalization of tm_wday and tm_yday.
+ */
+time_t tm_to_time_t(const struct tm *tm)
 {
 	static const int mdays[] = {
 	    0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
@@ -67,7 +70,7 @@
 
 	t = time;
 	localtime_r(&t, &tm);
-	t_local = my_mktime(&tm);
+	t_local = tm_to_time_t(&tm);
 
 	if (t_local < t) {
 		eastwest = -1;
@@ -322,7 +325,7 @@
 		if (!now_tm)
 			return 1;
 
-		specified = my_mktime(r);
+		specified = tm_to_time_t(r);
 
 		/* Be it commit time or author time, it does not make
 		 * sense to specify timestamp way into the future.  Make
@@ -399,6 +402,15 @@
 	return end - date;
 }
 
+/* Have we filled in any part of the time/date yet? */
+static inline int nodate(struct tm *tm)
+{
+	return tm->tm_year < 0 &&
+		tm->tm_mon < 0 &&
+		tm->tm_mday < 0 &&
+		!(tm->tm_hour | tm->tm_min | tm->tm_sec);
+}
+
 /*
  * We've seen a digit. Time? Year? Date?
  */
@@ -415,7 +427,7 @@
 	 * more than 8 digits. This is because we don't want to rule out
 	 * numbers like 20070606 as a YYYYMMDD date.
 	 */
-	if (num >= 100000000) {
+	if (num >= 100000000 && nodate(tm)) {
 		time_t time = num;
 		if (gmtime_r(&time, tm)) {
 			*tm_gmt = 1;
@@ -460,6 +472,13 @@
 	}
 
 	/*
+	 * Ignore lots of numerals. We took care of 4-digit years above.
+	 * Days or months must be one or two digits.
+	 */
+	if (n > 2)
+		return n;
+
+	/*
 	 * NOTE! We will give precedence to day-of-month over month or
 	 * year numbers in the 1-12 range. So 05 is always "mday 5",
 	 * unless we already have a mday..
@@ -485,10 +504,6 @@
 
 	if (num > 0 && num < 32) {
 		tm->tm_mday = num;
-	} else if (num > 1900) {
-		tm->tm_year = num - 1900;
-	} else if (num > 70) {
-		tm->tm_year = num;
 	} else if (num > 0 && num < 13) {
 		tm->tm_mon = num-1;
 	}
@@ -572,7 +587,7 @@
 	}
 
 	/* mktime uses local timezone */
-	then = my_mktime(&tm);
+	then = tm_to_time_t(&tm);
 	if (offset == -1)
 		offset = (then - mktime(&tm)) / 60;
 
@@ -611,7 +626,7 @@
 
 	time(&now);
 
-	offset = my_mktime(localtime(&now)) - now;
+	offset = tm_to_time_t(localtime(&now)) - now;
 	offset /= 60;
 
 	date_string(now, offset, buf, bufsize);
@@ -820,7 +835,9 @@
 		}
 	}
 
-	*num = number;
+	/* Accept zero-padding only for small numbers ("Dec 02", never "Dec 0002") */
+	if (date[0] != '0' || end - date <= 2)
+		*num = number;
 	return end;
 }
 
diff --git a/decorate.c b/decorate.c
index 23f6b00..82d9e22 100644
--- a/decorate.c
+++ b/decorate.c
@@ -6,13 +6,13 @@
 #include "object.h"
 #include "decorate.h"
 
-static unsigned int hash_obj(struct object *obj, unsigned int n)
+static unsigned int hash_obj(const struct object *obj, unsigned int n)
 {
 	unsigned int hash = *(unsigned int *)obj->sha1;
 	return hash % n;
 }
 
-static void *insert_decoration(struct decoration *n, struct object *base, void *decoration)
+static void *insert_decoration(struct decoration *n, const struct object *base, void *decoration)
 {
 	int size = n->size;
 	struct object_decoration *hash = n->hash;
@@ -37,17 +37,14 @@
 {
 	int i;
 	int old_size = n->size;
-	struct object_decoration *old_hash;
-
-	old_size = n->size;
-	old_hash = n->hash;
+	struct object_decoration *old_hash = n->hash;
 
 	n->size = (old_size + 1000) * 3 / 2;
 	n->hash = xcalloc(n->size, sizeof(struct object_decoration));
 	n->nr = 0;
 
 	for (i = 0; i < old_size; i++) {
-		struct object *base = old_hash[i].base;
+		const struct object *base = old_hash[i].base;
 		void *decoration = old_hash[i].decoration;
 
 		if (!base)
@@ -58,7 +55,8 @@
 }
 
 /* Add a decoration pointer, return any old one */
-void *add_decoration(struct decoration *n, struct object *obj, void *decoration)
+void *add_decoration(struct decoration *n, const struct object *obj,
+		void *decoration)
 {
 	int nr = n->nr + 1;
 
@@ -68,7 +66,7 @@
 }
 
 /* Lookup a decoration pointer */
-void *lookup_decoration(struct decoration *n, struct object *obj)
+void *lookup_decoration(struct decoration *n, const struct object *obj)
 {
 	int j;
 
diff --git a/decorate.h b/decorate.h
index 1fa4ad9..e732804 100644
--- a/decorate.h
+++ b/decorate.h
@@ -2,7 +2,7 @@
 #define DECORATE_H
 
 struct object_decoration {
-	struct object *base;
+	const struct object *base;
 	void *decoration;
 };
 
@@ -12,7 +12,7 @@
 	struct object_decoration *hash;
 };
 
-extern void *add_decoration(struct decoration *n, struct object *obj, void *decoration);
-extern void *lookup_decoration(struct decoration *n, struct object *obj);
+extern void *add_decoration(struct decoration *n, const struct object *obj, void *decoration);
+extern void *lookup_decoration(struct decoration *n, const struct object *obj);
 
 #endif
diff --git a/diff-no-index.c b/diff-no-index.c
index f6994cf..7d68b7f 100644
--- a/diff-no-index.c
+++ b/diff-no-index.c
@@ -14,9 +14,9 @@
 #include "revision.h"
 #include "log-tree.h"
 #include "builtin.h"
-#include "path-list.h"
+#include "string-list.h"
 
-static int read_directory(const char *path, struct path_list *list)
+static int read_directory(const char *path, struct string_list *list)
 {
 	DIR *dir;
 	struct dirent *e;
@@ -26,7 +26,7 @@
 
 	while ((e = readdir(dir)))
 		if (strcmp(".", e->d_name) && strcmp("..", e->d_name))
-			path_list_insert(e->d_name, list);
+			string_list_insert(e->d_name, list);
 
 	closedir(dir);
 	return 0;
@@ -60,13 +60,13 @@
 
 	if (S_ISDIR(mode1) || S_ISDIR(mode2)) {
 		char buffer1[PATH_MAX], buffer2[PATH_MAX];
-		struct path_list p1 = {NULL, 0, 0, 1}, p2 = {NULL, 0, 0, 1};
+		struct string_list p1 = {NULL, 0, 0, 1}, p2 = {NULL, 0, 0, 1};
 		int len1 = 0, len2 = 0, i1, i2, ret = 0;
 
 		if (name1 && read_directory(name1, &p1))
 			return -1;
 		if (name2 && read_directory(name2, &p2)) {
-			path_list_clear(&p1, 0);
+			string_list_clear(&p1, 0);
 			return -1;
 		}
 
@@ -95,14 +95,14 @@
 			else if (i2 == p2.nr)
 				comp = -1;
 			else
-				comp = strcmp(p1.items[i1].path,
-					p2.items[i2].path);
+				comp = strcmp(p1.items[i1].string,
+					p2.items[i2].string);
 
 			if (comp > 0)
 				n1 = NULL;
 			else {
 				n1 = buffer1;
-				strncpy(buffer1 + len1, p1.items[i1++].path,
+				strncpy(buffer1 + len1, p1.items[i1++].string,
 						PATH_MAX - len1);
 			}
 
@@ -110,14 +110,14 @@
 				n2 = NULL;
 			else {
 				n2 = buffer2;
-				strncpy(buffer2 + len2, p2.items[i2++].path,
+				strncpy(buffer2 + len2, p2.items[i2++].string,
 						PATH_MAX - len2);
 			}
 
 			ret = queue_diff(o, n1, n2);
 		}
-		path_list_clear(&p1, 0);
-		path_list_clear(&p2, 0);
+		string_list_clear(&p1, 0);
+		string_list_clear(&p2, 0);
 
 		return ret;
 	} else {
diff --git a/diff.c b/diff.c
index 342733b..f91f256 100644
--- a/diff.c
+++ b/diff.c
@@ -94,32 +94,37 @@
  * to define a customized regexp to find the beginning of a function to
  * be used for hunk header lines of "diff -p" style output.
  */
-static struct funcname_pattern {
+struct funcname_pattern_entry {
 	char *name;
 	char *pattern;
-	struct funcname_pattern *next;
+	int cflags;
+};
+static struct funcname_pattern_list {
+	struct funcname_pattern_list *next;
+	struct funcname_pattern_entry e;
 } *funcname_pattern_list;
 
-static int parse_funcname_pattern(const char *var, const char *ep, const char *value)
+static int parse_funcname_pattern(const char *var, const char *ep, const char *value, int cflags)
 {
 	const char *name;
 	int namelen;
-	struct funcname_pattern *pp;
+	struct funcname_pattern_list *pp;
 
 	name = var + 5; /* "diff." */
 	namelen = ep - name;
 
 	for (pp = funcname_pattern_list; pp; pp = pp->next)
-		if (!strncmp(pp->name, name, namelen) && !pp->name[namelen])
+		if (!strncmp(pp->e.name, name, namelen) && !pp->e.name[namelen])
 			break;
 	if (!pp) {
 		pp = xcalloc(1, sizeof(*pp));
-		pp->name = xmemdupz(name, namelen);
+		pp->e.name = xmemdupz(name, namelen);
 		pp->next = funcname_pattern_list;
 		funcname_pattern_list = pp;
 	}
-	free(pp->pattern);
-	pp->pattern = xstrdup(value);
+	free(pp->e.pattern);
+	pp->e.pattern = xstrdup(value);
+	pp->e.cflags = cflags;
 	return 0;
 }
 
@@ -182,7 +187,13 @@
 			if (!strcmp(ep, ".funcname")) {
 				if (!value)
 					return config_error_nonbool(var);
-				return parse_funcname_pattern(var, ep, value);
+				return parse_funcname_pattern(var, ep, value,
+					0);
+			} else if (!strcmp(ep, ".xfuncname")) {
+				if (!value)
+					return config_error_nonbool(var);
+				return parse_funcname_pattern(var, ep, value,
+					REG_EXTENDED);
 			}
 		}
 	}
@@ -511,13 +522,20 @@
 
 static void emit_line(FILE *file, const char *set, const char *reset, const char *line, int len)
 {
-	int has_trailing_newline = (len > 0 && line[len-1] == '\n');
+	int has_trailing_newline, has_trailing_carriage_return;
+
+	has_trailing_newline = (len > 0 && line[len-1] == '\n');
 	if (has_trailing_newline)
 		len--;
+	has_trailing_carriage_return = (len > 0 && line[len-1] == '\r');
+	if (has_trailing_carriage_return)
+		len--;
 
 	fputs(set, file);
 	fwrite(line, len, 1, file);
 	fputs(reset, file);
+	if (has_trailing_carriage_return)
+		fputc('\r', file);
 	if (has_trailing_newline)
 		fputc('\n', file);
 }
@@ -532,9 +550,9 @@
 	else {
 		/* Emit just the prefix, then the rest. */
 		emit_line(ecbdata->file, set, reset, line, ecbdata->nparents);
-		(void)check_and_emit_line(line + ecbdata->nparents,
-		    len - ecbdata->nparents, ecbdata->ws_rule,
-		    ecbdata->file, set, reset, ws);
+		ws_check_emit(line + ecbdata->nparents,
+			      len - ecbdata->nparents, ecbdata->ws_rule,
+			      ecbdata->file, set, reset, ws);
 	}
 }
 
@@ -827,12 +845,12 @@
 	/* Sanity: give at least 5 columns to the graph,
 	 * but leave at least 10 columns for the name.
 	 */
-	if (width < name_width + 15) {
-		if (name_width <= 25)
-			width = name_width + 15;
-		else
-			name_width = width - 15;
-	}
+	if (width < 25)
+		width = 25;
+	if (name_width < 10)
+		name_width = 10;
+	else if (width < name_width + 15)
+		name_width = width - 15;
 
 	/* Find the longest filename and max number of changes */
 	reset = diff_get_color_opt(options, DIFF_RESET);
@@ -925,7 +943,8 @@
 			total = add + del;
 		}
 		show_name(options->file, prefix, name, len, reset, set);
-		fprintf(options->file, "%5d ", added + deleted);
+		fprintf(options->file, "%5d%s", added + deleted,
+				added + deleted ? " " : "");
 		show_graph(options->file, '+', add, add_c, reset);
 		show_graph(options->file, '-', del, del_c, reset);
 		fprintf(options->file, "\n");
@@ -1053,6 +1072,13 @@
 	return this_dir;
 }
 
+static int dirstat_compare(const void *_a, const void *_b)
+{
+	const struct dirstat_file *a = _a;
+	const struct dirstat_file *b = _b;
+	return strcmp(a->name, b->name);
+}
+
 static void show_dirstat(struct diff_options *options)
 {
 	int i;
@@ -1064,7 +1090,7 @@
 	dir.alloc = 0;
 	dir.nr = 0;
 	dir.percent = options->dirstat_percent;
-	dir.cumulative = options->output_format & DIFF_FORMAT_CUMULATIVE;
+	dir.cumulative = DIFF_OPT_TST(options, DIRSTAT_CUMULATIVE);
 
 	changed = 0;
 	for (i = 0; i < q->nr; i++) {
@@ -1112,6 +1138,7 @@
 		return;
 
 	/* Show all directories with more than x% of the changes */
+	qsort(dir.files, dir.nr, sizeof(dir.files[0]), dirstat_compare);
 	gather_dirstat(options->file, &dir, changed, "", 0);
 }
 
@@ -1132,42 +1159,85 @@
 struct checkdiff_t {
 	struct xdiff_emit_state xm;
 	const char *filename;
-	int lineno, color_diff;
+	int lineno;
+	struct diff_options *o;
 	unsigned ws_rule;
 	unsigned status;
-	FILE *file;
+	int trailing_blanks_start;
 };
 
+static int is_conflict_marker(const char *line, unsigned long len)
+{
+	char firstchar;
+	int cnt;
+
+	if (len < 8)
+		return 0;
+	firstchar = line[0];
+	switch (firstchar) {
+	case '=': case '>': case '<':
+		break;
+	default:
+		return 0;
+	}
+	for (cnt = 1; cnt < 7; cnt++)
+		if (line[cnt] != firstchar)
+			return 0;
+	/* line[0] thru line[6] are same as firstchar */
+	if (firstchar == '=') {
+		/* divider between ours and theirs? */
+		if (len != 8 || line[7] != '\n')
+			return 0;
+	} else if (len < 8 || !isspace(line[7])) {
+		/* not divider before ours nor after theirs */
+		return 0;
+	}
+	return 1;
+}
+
 static void checkdiff_consume(void *priv, char *line, unsigned long len)
 {
 	struct checkdiff_t *data = priv;
-	const char *ws = diff_get_color(data->color_diff, DIFF_WHITESPACE);
-	const char *reset = diff_get_color(data->color_diff, DIFF_RESET);
-	const char *set = diff_get_color(data->color_diff, DIFF_FILE_NEW);
+	int color_diff = DIFF_OPT_TST(data->o, COLOR_DIFF);
+	const char *ws = diff_get_color(color_diff, DIFF_WHITESPACE);
+	const char *reset = diff_get_color(color_diff, DIFF_RESET);
+	const char *set = diff_get_color(color_diff, DIFF_FILE_NEW);
 	char *err;
 
 	if (line[0] == '+') {
 		unsigned bad;
 		data->lineno++;
-		bad = check_and_emit_line(line + 1, len - 1,
-		    data->ws_rule, NULL, NULL, NULL, NULL);
+		if (!ws_blank_line(line + 1, len - 1, data->ws_rule))
+			data->trailing_blanks_start = 0;
+		else if (!data->trailing_blanks_start)
+			data->trailing_blanks_start = data->lineno;
+		if (is_conflict_marker(line + 1, len - 1)) {
+			data->status |= 1;
+			fprintf(data->o->file,
+				"%s:%d: leftover conflict marker\n",
+				data->filename, data->lineno);
+		}
+		bad = ws_check(line + 1, len - 1, data->ws_rule);
 		if (!bad)
 			return;
 		data->status |= bad;
 		err = whitespace_error_string(bad);
-		fprintf(data->file, "%s:%d: %s.\n", data->filename, data->lineno, err);
+		fprintf(data->o->file, "%s:%d: %s.\n",
+			data->filename, data->lineno, err);
 		free(err);
-		emit_line(data->file, set, reset, line, 1);
-		(void)check_and_emit_line(line + 1, len - 1, data->ws_rule,
-		    data->file, set, reset, ws);
-	} else if (line[0] == ' ')
+		emit_line(data->o->file, set, reset, line, 1);
+		ws_check_emit(line + 1, len - 1, data->ws_rule,
+			      data->o->file, set, reset, ws);
+	} else if (line[0] == ' ') {
 		data->lineno++;
-	else if (line[0] == '@') {
+		data->trailing_blanks_start = 0;
+	} else if (line[0] == '@') {
 		char *plus = strchr(line, '+');
 		if (plus)
 			data->lineno = strtol(plus, NULL, 10) - 1;
 		else
 			die("invalid diff");
+		data->trailing_blanks_start = 0;
 	}
 }
 
@@ -1318,31 +1388,40 @@
 	return one->is_binary;
 }
 
-static const char *funcname_pattern(const char *ident)
+static const struct funcname_pattern_entry *funcname_pattern(const char *ident)
 {
-	struct funcname_pattern *pp;
+	struct funcname_pattern_list *pp;
 
 	for (pp = funcname_pattern_list; pp; pp = pp->next)
-		if (!strcmp(ident, pp->name))
-			return pp->pattern;
+		if (!strcmp(ident, pp->e.name))
+			return &pp->e;
 	return NULL;
 }
 
-static struct builtin_funcname_pattern {
-	const char *name;
-	const char *pattern;
-} builtin_funcname_pattern[] = {
-	{ "java", "!^[ 	]*\\(catch\\|do\\|for\\|if\\|instanceof\\|"
-			"new\\|return\\|switch\\|throw\\|while\\)\n"
-			"^[ 	]*\\(\\([ 	]*"
-			"[A-Za-z_][A-Za-z_0-9]*\\)\\{2,\\}"
-			"[ 	]*([^;]*\\)$" },
-	{ "tex", "^\\(\\\\\\(sub\\)*section{.*\\)$" },
+static const struct funcname_pattern_entry builtin_funcname_pattern[] = {
+	{ "java",
+	  "!^[ \t]*(catch|do|for|if|instanceof|new|return|switch|throw|while)\n"
+	  "^[ \t]*(([ \t]*[A-Za-z_][A-Za-z_0-9]*){2,}[ \t]*\\([^;]*)$",
+	  REG_EXTENDED },
+	{ "pascal",
+	  "^((procedure|function|constructor|destructor|interface|"
+		"implementation|initialization|finalization)[ \t]*.*)$"
+	  "|"
+	  "^(.*=[ \t]*(class|record).*)$",
+	  REG_EXTENDED },
+	{ "bibtex", "(@[a-zA-Z]{1,}[ \t]*\\{{0,1}[ \t]*[^ \t\"@',\\#}{~%]*).*$",
+	  REG_EXTENDED },
+	{ "tex",
+	  "^(\\\\((sub)*section|chapter|part)\\*{0,1}\\{.*)$",
+	  REG_EXTENDED },
+	{ "ruby", "^[ \t]*((class|module|def)[ \t].*)$",
+	  REG_EXTENDED },
 };
 
-static const char *diff_funcname_pattern(struct diff_filespec *one)
+static const struct funcname_pattern_entry *diff_funcname_pattern(struct diff_filespec *one)
 {
-	const char *ident, *pattern;
+	const char *ident;
+	const struct funcname_pattern_entry *pe;
 	int i;
 
 	diff_filespec_check_attr(one);
@@ -1357,9 +1436,9 @@
 		return funcname_pattern("default");
 
 	/* Look up custom "funcname.$ident" regexp from config. */
-	pattern = funcname_pattern(ident);
-	if (pattern)
-		return pattern;
+	pe = funcname_pattern(ident);
+	if (pe)
+		return pe;
 
 	/*
 	 * And define built-in fallback patterns here.  Note that
@@ -1367,7 +1446,7 @@
 	 */
 	for (i = 0; i < ARRAY_SIZE(builtin_funcname_pattern); i++)
 		if (!strcmp(ident, builtin_funcname_pattern[i].name))
-			return builtin_funcname_pattern[i].pattern;
+			return &builtin_funcname_pattern[i];
 
 	return NULL;
 }
@@ -1386,6 +1465,10 @@
 	const char *set = diff_get_color_opt(o, DIFF_METAINFO);
 	const char *reset = diff_get_color_opt(o, DIFF_RESET);
 
+	/* Never use a non-valid filename anywhere if at all possible */
+	name_a = DIFF_FILE_VALID(one) ? name_a : name_b;
+	name_b = DIFF_FILE_VALID(two) ? name_b : name_a;
+
 	a_one = quote_two(o->a_prefix, name_a + (*name_a == '/'));
 	b_two = quote_two(o->b_prefix, name_b + (*name_b == '/'));
 	lbl[0] = DIFF_FILE_VALID(one) ? a_one : "/dev/null";
@@ -1445,11 +1528,11 @@
 		xdemitconf_t xecfg;
 		xdemitcb_t ecb;
 		struct emit_callback ecbdata;
-		const char *funcname_pattern;
+		const struct funcname_pattern_entry *pe;
 
-		funcname_pattern = diff_funcname_pattern(one);
-		if (!funcname_pattern)
-			funcname_pattern = diff_funcname_pattern(two);
+		pe = diff_funcname_pattern(one);
+		if (!pe)
+			pe = diff_funcname_pattern(two);
 
 		memset(&xecfg, 0, sizeof(xecfg));
 		memset(&ecbdata, 0, sizeof(ecbdata));
@@ -1461,8 +1544,8 @@
 		xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
 		xecfg.ctxlen = o->context;
 		xecfg.flags = XDL_EMIT_FUNCNAMES;
-		if (funcname_pattern)
-			xdiff_set_find_func(&xecfg, funcname_pattern);
+		if (pe)
+			xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags);
 		if (!diffopts)
 			;
 		else if (!prefixcmp(diffopts, "--unified="))
@@ -1540,8 +1623,9 @@
 
 static void builtin_checkdiff(const char *name_a, const char *name_b,
 			      const char *attr_path,
-			     struct diff_filespec *one,
-			     struct diff_filespec *two, struct diff_options *o)
+			      struct diff_filespec *one,
+			      struct diff_filespec *two,
+			      struct diff_options *o)
 {
 	mmfile_t mf1, mf2;
 	struct checkdiff_t data;
@@ -1553,13 +1637,18 @@
 	data.xm.consume = checkdiff_consume;
 	data.filename = name_b ? name_b : name_a;
 	data.lineno = 0;
-	data.color_diff = DIFF_OPT_TST(o, COLOR_DIFF);
+	data.o = o;
 	data.ws_rule = whitespace_rule(attr_path);
-	data.file = o->file;
 
 	if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
 		die("unable to read files to diff");
 
+	/*
+	 * All the other codepaths check both sides, but not checking
+	 * the "old" side here is deliberate.  We are checking the newly
+	 * introduced changes, and as long as the "new" side is text, we
+	 * can and should check what it introduces.
+	 */
 	if (diff_filespec_is_binary(two))
 		goto free_and_return;
 	else {
@@ -1569,10 +1658,18 @@
 		xdemitcb_t ecb;
 
 		memset(&xecfg, 0, sizeof(xecfg));
+		xecfg.ctxlen = 1; /* at least one context line */
 		xpp.flags = XDF_NEED_MINIMAL;
 		ecb.outf = xdiff_outf;
 		ecb.priv = &data;
 		xdi_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
+
+		if ((data.ws_rule & WS_TRAILING_SPACE) &&
+		    data.trailing_blanks_start) {
+			fprintf(o->file, "%s:%d: ends with blank lines.\n",
+				data.filename, data.trailing_blanks_start);
+			data.status = 1; /* report errors */
+		}
 	}
  free_and_return:
 	diff_free_filespec_data(one);
@@ -2224,6 +2321,7 @@
 	options->break_opt = -1;
 	options->rename_limit = -1;
 	options->dirstat_percent = 3;
+	DIFF_OPT_CLR(options, DIRSTAT_CUMULATIVE);
 	options->context = 3;
 
 	options->change = diff_change;
@@ -2318,13 +2416,6 @@
 		DIFF_OPT_SET(options, EXIT_WITH_STATUS);
 	}
 
-	/*
-	 * If we postprocess in diffcore, we cannot simply return
-	 * upon the first hit.  We need to run diff as usual.
-	 */
-	if (options->pickaxe || options->filter)
-		DIFF_OPT_CLR(options, QUIET);
-
 	return 0;
 }
 
@@ -2396,8 +2487,10 @@
 		options->output_format |= DIFF_FORMAT_SHORTSTAT;
 	else if (opt_arg(arg, 'X', "dirstat", &options->dirstat_percent))
 		options->output_format |= DIFF_FORMAT_DIRSTAT;
-	else if (!strcmp(arg, "--cumulative"))
-		options->output_format |= DIFF_FORMAT_CUMULATIVE;
+	else if (!strcmp(arg, "--cumulative")) {
+		options->output_format |= DIFF_FORMAT_DIRSTAT;
+		DIFF_OPT_SET(options, DIRSTAT_CUMULATIVE);
+	}
 	else if (!strcmp(arg, "--check"))
 		options->output_format |= DIFF_FORMAT_CHECKDIFF;
 	else if (!strcmp(arg, "--summary"))
@@ -3168,11 +3261,10 @@
 
 	if (output_format & DIFF_FORMAT_PATCH) {
 		if (separator) {
+			putc(options->line_termination, options->file);
 			if (options->stat_sep) {
 				/* attach patch instead of inline */
 				fputs(options->stat_sep, options->file);
-			} else {
-				putc(options->line_termination, options->file);
 			}
 		}
 
@@ -3315,10 +3407,7 @@
 
 void diffcore_std(struct diff_options *options)
 {
-	if (DIFF_OPT_TST(options, QUIET))
-		return;
-
-	if (options->skip_stat_unmatch && !DIFF_OPT_TST(options, FIND_COPIES_HARDER))
+	if (options->skip_stat_unmatch)
 		diffcore_skip_stat_unmatch(options);
 	if (options->break_opt != -1)
 		diffcore_break(options->break_opt);
diff --git a/diff.h b/diff.h
index 50fb5dd..7f53beb 100644
--- a/diff.h
+++ b/diff.h
@@ -31,7 +31,6 @@
 #define DIFF_FORMAT_PATCH	0x0010
 #define DIFF_FORMAT_SHORTSTAT	0x0020
 #define DIFF_FORMAT_DIRSTAT	0x0040
-#define DIFF_FORMAT_CUMULATIVE	0x0080
 
 /* These override all above */
 #define DIFF_FORMAT_NAME	0x0100
@@ -64,6 +63,7 @@
 #define DIFF_OPT_CHECK_FAILED        (1 << 16)
 #define DIFF_OPT_RELATIVE_NAME       (1 << 17)
 #define DIFF_OPT_IGNORE_SUBMODULES   (1 << 18)
+#define DIFF_OPT_DIRSTAT_CUMULATIVE  (1 << 19)
 #define DIFF_OPT_TST(opts, flag)    ((opts)->flags & DIFF_OPT_##flag)
 #define DIFF_OPT_SET(opts, flag)    ((opts)->flags |= DIFF_OPT_##flag)
 #define DIFF_OPT_CLR(opts, flag)    ((opts)->flags &= ~DIFF_OPT_##flag)
diff --git a/diffcore-rename.c b/diffcore-rename.c
index 1b2ebb4..168a95b 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -493,7 +493,7 @@
 	if ((num_create > rename_limit && num_src > rename_limit) ||
 	    (num_create * num_src > rename_limit * rename_limit)) {
 		if (options->warn_on_too_large_rename)
-			warning("too many files, skipping inexact rename detection");
+			warning("too many files (created: %d deleted: %d), skipping inexact rename detection", num_create, num_src);
 		goto cleanup;
 	}
 
diff --git a/diffcore.h b/diffcore.h
index cc96c20..1ebfdae 100644
--- a/diffcore.h
+++ b/diffcore.h
@@ -58,7 +58,7 @@
 	struct diff_filespec *one;
 	struct diff_filespec *two;
 	unsigned short int score;
-	char status; /* M C R N D U (see Documentation/diff-format.txt) */
+	char status; /* M C R A D U etc. (see Documentation/diff-format.txt or DIFF_STATUS_* in diff.h) */
 	unsigned broken_pair : 1;
 	unsigned renamed_pair : 1;
 	unsigned is_unmerged : 1;
@@ -92,7 +92,6 @@
 					struct diff_filespec *);
 extern void diff_q(struct diff_queue_struct *, struct diff_filepair *);
 
-extern void diffcore_pathspec(const char **pathspec);
 extern void diffcore_break(int);
 extern void diffcore_rename(struct diff_options *);
 extern void diffcore_merge_broken(void);
diff --git a/dir.c b/dir.c
index 109e05b..cfaa28f 100644
--- a/dir.c
+++ b/dir.c
@@ -837,3 +837,23 @@
 	if (excludes_file && !access(excludes_file, R_OK))
 		add_excludes_from_file(dir, excludes_file);
 }
+
+int remove_path(const char *name)
+{
+	char *slash;
+
+	if (unlink(name) && errno != ENOENT)
+		return -1;
+
+	slash = strrchr(name, '/');
+	if (slash) {
+		char *dirs = xstrdup(name);
+		slash = dirs + (slash - name);
+		do {
+			*slash = '\0';
+		} while (rmdir(dirs) && (slash = strrchr(dirs, '/')));
+		free(dirs);
+	}
+	return 0;
+}
+
diff --git a/dir.h b/dir.h
index 2df15de..278ee42 100644
--- a/dir.h
+++ b/dir.h
@@ -81,4 +81,7 @@
 extern void setup_standard_excludes(struct dir_struct *dir);
 extern int remove_dir_recursively(struct strbuf *path, int only_empty);
 
+/* tries to remove the path with empty directories along it, ignores ENOENT */
+extern int remove_path(const char *path);
+
 #endif
diff --git a/editor.c b/editor.c
new file mode 100644
index 0000000..eebc3e9
--- /dev/null
+++ b/editor.c
@@ -0,0 +1,56 @@
+#include "cache.h"
+#include "strbuf.h"
+#include "run-command.h"
+
+int launch_editor(const char *path, struct strbuf *buffer, const char *const *env)
+{
+	const char *editor, *terminal;
+
+	editor = getenv("GIT_EDITOR");
+	if (!editor && editor_program)
+		editor = editor_program;
+	if (!editor)
+		editor = getenv("VISUAL");
+	if (!editor)
+		editor = getenv("EDITOR");
+
+	terminal = getenv("TERM");
+	if (!editor && (!terminal || !strcmp(terminal, "dumb")))
+		return error("Terminal is dumb but no VISUAL nor EDITOR defined.");
+
+	if (!editor)
+		editor = "vi";
+
+	if (strcmp(editor, ":")) {
+		size_t len = strlen(editor);
+		int i = 0;
+		int failed;
+		const char *args[6];
+		struct strbuf arg0;
+
+		strbuf_init(&arg0, 0);
+		if (strcspn(editor, "$ \t'") != len) {
+			/* there are specials */
+			strbuf_addf(&arg0, "%s \"$@\"", editor);
+			args[i++] = "sh";
+			args[i++] = "-c";
+			args[i++] = arg0.buf;
+		}
+		args[i++] = editor;
+		args[i++] = path;
+		args[i] = NULL;
+
+		failed = run_command_v_opt_cd_env(args, 0, NULL, env);
+		strbuf_release(&arg0);
+		if (failed)
+			return error("There was a problem with the editor '%s'.",
+					editor);
+	}
+
+	if (!buffer)
+		return 0;
+	if (strbuf_read_file(buffer, path, 0) < 0)
+		return error("could not read file '%s': %s",
+				path, strerror(errno));
+	return 0;
+}
diff --git a/entry.c b/entry.c
index 222aaa3..aa2ee46 100644
--- a/entry.c
+++ b/entry.c
@@ -111,7 +111,7 @@
 	case S_IFREG:
 		new = read_blob_entry(ce, path, &size);
 		if (!new)
-			return error("git-checkout-index: unable to read sha1 file of %s (%s)",
+			return error("git checkout-index: unable to read sha1 file of %s (%s)",
 				path, sha1_to_hex(ce->sha1));
 
 		/*
@@ -132,7 +132,7 @@
 			fd = create_file(path, ce->ce_mode);
 		if (fd < 0) {
 			free(new);
-			return error("git-checkout-index: unable to create file %s (%s)",
+			return error("git checkout-index: unable to create file %s (%s)",
 				path, strerror(errno));
 		}
 
@@ -140,12 +140,12 @@
 		close(fd);
 		free(new);
 		if (wrote != size)
-			return error("git-checkout-index: unable to write file %s", path);
+			return error("git checkout-index: unable to write file %s", path);
 		break;
 	case S_IFLNK:
 		new = read_blob_entry(ce, path, &size);
 		if (!new)
-			return error("git-checkout-index: unable to read sha1 file of %s (%s)",
+			return error("git checkout-index: unable to read sha1 file of %s (%s)",
 				path, sha1_to_hex(ce->sha1));
 		if (to_tempfile || !has_symlinks) {
 			if (to_tempfile) {
@@ -155,31 +155,31 @@
 				fd = create_file(path, 0666);
 			if (fd < 0) {
 				free(new);
-				return error("git-checkout-index: unable to create "
+				return error("git checkout-index: unable to create "
 						 "file %s (%s)", path, strerror(errno));
 			}
 			wrote = write_in_full(fd, new, size);
 			close(fd);
 			free(new);
 			if (wrote != size)
-				return error("git-checkout-index: unable to write file %s",
+				return error("git checkout-index: unable to write file %s",
 					path);
 		} else {
 			wrote = symlink(new, path);
 			free(new);
 			if (wrote)
-				return error("git-checkout-index: unable to create "
+				return error("git checkout-index: unable to create "
 						 "symlink %s (%s)", path, strerror(errno));
 		}
 		break;
 	case S_IFGITLINK:
 		if (to_tempfile)
-			return error("git-checkout-index: cannot create temporary subproject %s", path);
+			return error("git checkout-index: cannot create temporary subproject %s", path);
 		if (mkdir(path, 0777) < 0)
-			return error("git-checkout-index: cannot create subproject directory %s", path);
+			return error("git checkout-index: cannot create subproject directory %s", path);
 		break;
 	default:
-		return error("git-checkout-index: unknown file mode for %s", path);
+		return error("git checkout-index: unknown file mode for %s", path);
 	}
 
 	if (state->refresh_cache) {
diff --git a/environment.c b/environment.c
index d5c3e29..9ebf485 100644
--- a/environment.c
+++ b/environment.c
@@ -13,7 +13,7 @@
 char git_default_name[MAX_GITNAME];
 int user_ident_explicitly_given;
 int trust_executable_bit = 1;
-int quote_path_fully = 1;
+int trust_ctime = 1;
 int has_symlinks = 1;
 int ignore_case;
 int assume_unchanged;
@@ -71,7 +71,7 @@
 	}
 	git_graft_file = getenv(GRAFT_ENVIRONMENT);
 	if (!git_graft_file)
-		git_graft_file = xstrdup(git_path("info/grafts"));
+		git_graft_file = git_pathdup("info/grafts");
 }
 
 int is_bare_repository(void)
@@ -113,7 +113,7 @@
 			work_tree = git_work_tree_cfg;
 			/* make_absolute_path also normalizes the path */
 			if (work_tree && !is_absolute_path(work_tree))
-				work_tree = xstrdup(make_absolute_path(git_path(work_tree)));
+				work_tree = xstrdup(make_absolute_path(git_path("%s", work_tree)));
 		} else if (work_tree)
 			work_tree = xstrdup(make_absolute_path(work_tree));
 		git_work_tree_initialized = 1;
@@ -130,13 +130,6 @@
 	return git_object_dir;
 }
 
-char *get_refs_directory(void)
-{
-	if (!git_refs_dir)
-		setup_git_env();
-	return git_refs_dir;
-}
-
 char *get_index_file(void)
 {
 	if (!git_index_file)
diff --git a/exec_cmd.c b/exec_cmd.c
index e189cac..ce6741e 100644
--- a/exec_cmd.c
+++ b/exec_cmd.c
@@ -4,8 +4,23 @@
 #define MAX_ARGS	32
 
 extern char **environ;
-static const char *builtin_exec_path = GIT_EXEC_PATH;
 static const char *argv_exec_path;
+static const char *argv0_path;
+
+const char *system_path(const char *path)
+{
+	if (!is_absolute_path(path) && argv0_path) {
+		struct strbuf d = STRBUF_INIT;
+		strbuf_addf(&d, "%s/%s", argv0_path, path);
+		path = strbuf_detach(&d, NULL);
+	}
+	return path;
+}
+
+void git_set_argv0_path(const char *path)
+{
+	argv0_path = path;
+}
 
 void git_set_argv_exec_path(const char *exec_path)
 {
@@ -26,7 +41,7 @@
 		return env;
 	}
 
-	return builtin_exec_path;
+	return system_path(GIT_EXEC_PATH);
 }
 
 static void add_path(struct strbuf *out, const char *path)
@@ -35,13 +50,13 @@
 		if (is_absolute_path(path))
 			strbuf_addstr(out, path);
 		else
-			strbuf_addstr(out, make_absolute_path(path));
+			strbuf_addstr(out, make_nonrelative_path(path));
 
-		strbuf_addch(out, ':');
+		strbuf_addch(out, PATH_SEP);
 	}
 }
 
-void setup_path(const char *cmd_path)
+void setup_path(void)
 {
 	const char *old_path = getenv("PATH");
 	struct strbuf new_path;
@@ -50,8 +65,8 @@
 
 	add_path(&new_path, argv_exec_path);
 	add_path(&new_path, getenv(EXEC_PATH_ENVIRONMENT));
-	add_path(&new_path, builtin_exec_path);
-	add_path(&new_path, cmd_path);
+	add_path(&new_path, system_path(GIT_EXEC_PATH));
+	add_path(&new_path, argv0_path);
 
 	if (old_path)
 		strbuf_addstr(&new_path, old_path);
@@ -63,34 +78,32 @@
 	strbuf_release(&new_path);
 }
 
-int execv_git_cmd(const char **argv)
+const char **prepare_git_cmd(const char **argv)
 {
-	struct strbuf cmd;
-	const char *tmp;
+	int argc;
+	const char **nargv;
 
-	strbuf_init(&cmd, 0);
-	strbuf_addf(&cmd, "git-%s", argv[0]);
+	for (argc = 0; argv[argc]; argc++)
+		; /* just counting */
+	nargv = xmalloc(sizeof(*nargv) * (argc + 2));
 
-	/*
-	 * argv[0] must be the git command, but the argv array
-	 * belongs to the caller, and may be reused in
-	 * subsequent loop iterations. Save argv[0] and
-	 * restore it on error.
-	 */
-	tmp = argv[0];
-	argv[0] = cmd.buf;
+	nargv[0] = "git";
+	for (argc = 0; argv[argc]; argc++)
+		nargv[argc + 1] = argv[argc];
+	nargv[argc + 1] = NULL;
+	return nargv;
+}
 
-	trace_argv_printf(argv, "trace: exec:");
+int execv_git_cmd(const char **argv) {
+	const char **nargv = prepare_git_cmd(argv);
+	trace_argv_printf(nargv, "trace: exec:");
 
 	/* execvp() can only ever return if it fails */
-	execvp(cmd.buf, (char **)argv);
+	execvp("git", (char **)nargv);
 
 	trace_printf("trace: exec failed: %s\n", strerror(errno));
 
-	argv[0] = tmp;
-
-	strbuf_release(&cmd);
-
+	free(nargv);
 	return -1;
 }
 
diff --git a/exec_cmd.h b/exec_cmd.h
index a892355..594f961 100644
--- a/exec_cmd.h
+++ b/exec_cmd.h
@@ -2,10 +2,12 @@
 #define GIT_EXEC_CMD_H
 
 extern void git_set_argv_exec_path(const char *exec_path);
+extern void git_set_argv0_path(const char *path);
 extern const char* git_exec_path(void);
-extern void setup_path(const char *);
+extern void setup_path(void);
+extern const char **prepare_git_cmd(const char **argv);
 extern int execv_git_cmd(const char **argv); /* NULL terminated */
 extern int execl_git_cmd(const char *cmd, ...);
-
+extern const char *system_path(const char *path);
 
 #endif /* GIT_EXEC_CMD_H */
diff --git a/fast-import.c b/fast-import.c
index e72b286..d58cca5 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -43,7 +43,7 @@
 
   new_tag ::= 'tag' sp tag_str lf
     'from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf
-    'tagger' sp name '<' email '>' when lf
+    ('tagger' sp name '<' email '>' when lf)?
     tag_msg;
   tag_msg ::= data;
 
@@ -816,7 +816,7 @@
 	int pack_fd;
 
 	snprintf(tmpfile, sizeof(tmpfile),
-		"%s/tmp_pack_XXXXXX", get_object_directory());
+		"%s/pack/tmp_pack_XXXXXX", get_object_directory());
 	pack_fd = xmkstemp(tmpfile);
 	p = xcalloc(1, sizeof(*p) + strlen(tmpfile) + 2);
 	strcpy(p->pack_name, tmpfile);
@@ -878,7 +878,7 @@
 	}
 
 	snprintf(tmpfile, sizeof(tmpfile),
-		"%s/tmp_idx_XXXXXX", get_object_directory());
+		"%s/pack/tmp_idx_XXXXXX", get_object_directory());
 	idx_fd = xmkstemp(tmpfile);
 	f = sha1fd(idx_fd, tmpfile);
 	sha1write(f, array, 256 * sizeof(int));
@@ -951,7 +951,8 @@
 
 		close_pack_windows(pack_data);
 		fixup_pack_header_footer(pack_data->pack_fd, pack_data->sha1,
-				    pack_data->pack_name, object_count);
+				    pack_data->pack_name, object_count,
+				    NULL, 0);
 		close(pack_data->pack_fd);
 		idx_name = keep_pack(create_index());
 
@@ -981,8 +982,10 @@
 
 		pack_id++;
 	}
-	else
+	else {
+		close(old_p->pack_fd);
 		unlink(old_p->pack_name);
+	}
 	free(old_p);
 
 	/* We can't carry a delta across packfiles. */
@@ -1868,6 +1871,7 @@
 	case S_IFREG | 0644:
 	case S_IFREG | 0755:
 	case S_IFLNK:
+	case S_IFGITLINK:
 	case 0644:
 	case 0755:
 		/* ok */
@@ -1900,7 +1904,20 @@
 		p = uq.buf;
 	}
 
-	if (inline_data) {
+	if (S_ISGITLINK(mode)) {
+		if (inline_data)
+			die("Git links cannot be specified 'inline': %s",
+				command_buf.buf);
+		else if (oe) {
+			if (oe->type != OBJ_COMMIT)
+				die("Not a commit (actually a %s): %s",
+					typename(oe->type), command_buf.buf);
+		}
+		/*
+		 * Accept the sha1 without checking; it expected to be in
+		 * another repository.
+		 */
+	} else if (inline_data) {
 		static struct strbuf buf = STRBUF_INIT;
 
 		if (p != uq.buf) {
@@ -2247,23 +2264,27 @@
 	read_next_command();
 
 	/* tagger ... */
-	if (prefixcmp(command_buf.buf, "tagger "))
-		die("Expected tagger command, got %s", command_buf.buf);
-	tagger = parse_ident(command_buf.buf + 7);
+	if (!prefixcmp(command_buf.buf, "tagger ")) {
+		tagger = parse_ident(command_buf.buf + 7);
+		read_next_command();
+	} else
+		tagger = NULL;
 
 	/* tag payload/message */
-	read_next_command();
 	parse_data(&msg);
 
 	/* build the tag object */
 	strbuf_reset(&new_data);
+
 	strbuf_addf(&new_data,
-		"object %s\n"
-		"type %s\n"
-		"tag %s\n"
-		"tagger %s\n"
-		"\n",
-		sha1_to_hex(sha1), commit_type, t->name, tagger);
+		    "object %s\n"
+		    "type %s\n"
+		    "tag %s\n",
+		    sha1_to_hex(sha1), commit_type, t->name);
+	if (tagger)
+		strbuf_addf(&new_data,
+			    "tagger %s\n", tagger);
+	strbuf_addch(&new_data, '\n');
 	strbuf_addbuf(&new_data, &msg);
 	free(tagger);
 
@@ -2374,7 +2395,7 @@
 }
 
 static const char fast_import_usage[] =
-"git-fast-import [--date-format=f] [--max-pack-size=n] [--depth=n] [--active-branches=n] [--export-marks=marks.file]";
+"git fast-import [--date-format=f] [--max-pack-size=n] [--depth=n] [--active-branches=n] [--export-marks=marks.file]";
 
 int main(int argc, const char **argv)
 {
diff --git a/fixup-builtins b/fixup-builtins
index 49e861d..63dfa4c 100755
--- a/fixup-builtins
+++ b/fixup-builtins
@@ -1,16 +1,16 @@
 #!/bin/sh
 while [ "$1" ]
 do
-	old="$1"
-	new=$(echo "$1" | sed 's/git-/git /')
-	echo "Converting '$old' to '$new'"
-	git ls-files '*.sh' | while read file
-	do
-		sed "s/\\<$old\\>/$new/g" < $file > $file.new
-		chmod --reference=$file $file.new
-		mv $file.new $file
-	done
+	if [ "$1" != "git-sh-setup" -a "$1" != "git-parse-remote" -a "$1" != "git-svn" ]; then
+		old="$1"
+		new=$(echo "$1" | sed 's/git-/git /')
+		echo "Converting '$old' to '$new'"
+		sed -i "s/\\<$old\\>/$new/g" $(git ls-files '*.sh')
+	fi
 	shift
 done
+
+sed -i 's/git merge-one-file/git-merge-one-file/g
+s/git rebase-todo/git-rebase-todo/g' $(git ls-files '*.sh')
 git update-index --refresh >& /dev/null
 exit 0
diff --git a/fsck.c b/fsck.c
index 797e317..ab64c18 100644
--- a/fsck.c
+++ b/fsck.c
@@ -327,7 +327,7 @@
 			die("this should not happen, your snprintf is broken");
 	}
 
-	error(sb.buf);
+	error("%s", sb.buf);
 	strbuf_release(&sb);
 	return 1;
 }
diff --git a/generate-cmdlist.sh b/generate-cmdlist.sh
index a2913c2..75c68d9 100755
--- a/generate-cmdlist.sh
+++ b/generate-cmdlist.sh
@@ -14,7 +14,7 @@
 while read cmd
 do
      sed -n '
-     /NAME/,/git-'"$cmd"'/H
+     /^NAME/,/git-'"$cmd"'/H
      ${
             x
             s/.*git-'"$cmd"' - \(.*\)/  {"'"$cmd"'", "\1"},/
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index 709caa9..b0223c3 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -18,6 +18,18 @@
 	$diff_use_color ? (
 		$repo->get_color('color.diff.frag', 'cyan'),
 	) : ();
+my ($diff_plain_color) =
+	$diff_use_color ? (
+		$repo->get_color('color.diff.plain', ''),
+	) : ();
+my ($diff_old_color) =
+	$diff_use_color ? (
+		$repo->get_color('color.diff.old', 'red'),
+	) : ();
+my ($diff_new_color) =
+	$diff_use_color ? (
+		$repo->get_color('color.diff.new', 'green'),
+	) : ();
 
 my $normal_color = $repo->get_color("", "reset");
 
@@ -42,7 +54,7 @@
 my $patch_mode;
 
 sub run_cmd_pipe {
-	if ($^O eq 'MSWin32') {
+	if ($^O eq 'MSWin32' || $^O eq 'msys') {
 		my @invalid = grep {m/[":*]/} @_;
 		die "$^O does not support: @invalid\n" if @invalid;
 		my @args = map { m/ /o ? "\"$_\"": $_ } @_;
@@ -682,92 +694,104 @@
 	return @split;
 }
 
-sub find_last_o_ctx {
-	my ($it) = @_;
-	my $text = $it->{TEXT};
-	my ($o_ofs, $o_cnt) = parse_hunk_header($text->[0]);
-	my $i = @{$text};
-	my $last_o_ctx = $o_ofs + $o_cnt;
-	while (0 < --$i) {
-		my $line = $text->[$i];
-		if ($line =~ /^ /) {
-			$last_o_ctx--;
-			next;
-		}
-		last;
-	}
-	return $last_o_ctx;
+
+sub color_diff {
+	return map {
+		colored((/^@/  ? $fraginfo_color :
+			 /^\+/ ? $diff_new_color :
+			 /^-/  ? $diff_old_color :
+			 $diff_plain_color),
+			$_);
+	} @_;
 }
 
-sub merge_hunk {
-	my ($prev, $this) = @_;
-	my ($o0_ofs, $o0_cnt, $n0_ofs, $n0_cnt) =
-	    parse_hunk_header($prev->{TEXT}[0]);
-	my ($o1_ofs, $o1_cnt, $n1_ofs, $n1_cnt) =
-	    parse_hunk_header($this->{TEXT}[0]);
+sub edit_hunk_manually {
+	my ($oldtext) = @_;
 
-	my (@line, $i, $ofs, $o_cnt, $n_cnt);
-	$ofs = $o0_ofs;
-	$o_cnt = $n_cnt = 0;
-	for ($i = 1; $i < @{$prev->{TEXT}}; $i++) {
-		my $line = $prev->{TEXT}[$i];
-		if ($line =~ /^\+/) {
-			$n_cnt++;
-			push @line, $line;
-			next;
-		}
+	my $hunkfile = $repo->repo_path . "/addp-hunk-edit.diff";
+	my $fh;
+	open $fh, '>', $hunkfile
+		or die "failed to open hunk edit file for writing: " . $!;
+	print $fh "# Manual hunk edit mode -- see bottom for a quick guide\n";
+	print $fh @$oldtext;
+	print $fh <<EOF;
+# ---
+# To remove '-' lines, make them ' ' lines (context).
+# To remove '+' lines, delete them.
+# Lines starting with # will be removed.
+#
+# If the patch applies cleanly, the edited hunk will immediately be
+# marked for staging. If it does not apply cleanly, you will be given
+# an opportunity to edit again. If all lines of the hunk are removed,
+# then the edit is aborted and the hunk is left unchanged.
+EOF
+	close $fh;
 
-		last if ($o1_ofs <= $ofs);
+	my $editor = $ENV{GIT_EDITOR} || $repo->config("core.editor")
+		|| $ENV{VISUAL} || $ENV{EDITOR} || "vi";
+	system('sh', '-c', $editor.' "$@"', $editor, $hunkfile);
 
-		$o_cnt++;
-		$ofs++;
-		if ($line =~ /^ /) {
-			$n_cnt++;
-		}
-		push @line, $line;
+	open $fh, '<', $hunkfile
+		or die "failed to open hunk edit file for reading: " . $!;
+	my @newtext = grep { !/^#/ } <$fh>;
+	close $fh;
+	unlink $hunkfile;
+
+	# Abort if nothing remains
+	if (!grep { /\S/ } @newtext) {
+		return undef;
 	}
 
-	for ($i = 1; $i < @{$this->{TEXT}}; $i++) {
-		my $line = $this->{TEXT}[$i];
-		if ($line =~ /^\+/) {
-			$n_cnt++;
-			push @line, $line;
-			next;
-		}
-		$ofs++;
-		$o_cnt++;
-		if ($line =~ /^ /) {
-			$n_cnt++;
-		}
-		push @line, $line;
+	# Reinsert the first hunk header if the user accidentally deleted it
+	if ($newtext[0] !~ /^@/) {
+		unshift @newtext, $oldtext->[0];
 	}
-	my $head = ("@@ -$o0_ofs" .
-		    (($o_cnt != 1) ? ",$o_cnt" : '') .
-		    " +$n0_ofs" .
-		    (($n_cnt != 1) ? ",$n_cnt" : '') .
-		    " @@\n");
-	@{$prev->{TEXT}} = ($head, @line);
+	return \@newtext;
 }
 
-sub coalesce_overlapping_hunks {
-	my (@in) = @_;
-	my @out = ();
+sub diff_applies {
+	my $fh;
+	open $fh, '| git apply --recount --cached --check';
+	for my $h (@_) {
+		print $fh @{$h->{TEXT}};
+	}
+	return close $fh;
+}
 
-	my ($last_o_ctx);
+sub prompt_yesno {
+	my ($prompt) = @_;
+	while (1) {
+		print colored $prompt_color, $prompt;
+		my $line = <STDIN>;
+		return 0 if $line =~ /^n/i;
+		return 1 if $line =~ /^y/i;
+	}
+}
 
-	for (grep { $_->{USE} } @in) {
-		my $text = $_->{TEXT};
-		my ($o_ofs) = parse_hunk_header($text->[0]);
-		if (defined $last_o_ctx &&
-		    $o_ofs <= $last_o_ctx) {
-			merge_hunk($out[-1], $_);
+sub edit_hunk_loop {
+	my ($head, $hunk, $ix) = @_;
+	my $text = $hunk->[$ix]->{TEXT};
+
+	while (1) {
+		$text = edit_hunk_manually($text);
+		if (!defined $text) {
+			return undef;
+		}
+		my $newhunk = { TEXT => $text, USE => 1 };
+		if (diff_applies($head,
+				 @{$hunk}[0..$ix-1],
+				 $newhunk,
+				 @{$hunk}[$ix+1..$#{$hunk}])) {
+			$newhunk->{DISPLAY} = [color_diff(@{$text})];
+			return $newhunk;
 		}
 		else {
-			push @out, $_;
+			prompt_yesno(
+				'Your edited hunk does not apply. Edit again '
+				. '(saying "no" discards!) [y/n]? '
+				) or return undef;
 		}
-		$last_o_ctx = find_last_o_ctx($out[-1]);
 	}
-	return @out;
 }
 
 sub help_patch_cmd {
@@ -781,16 +805,22 @@
 k - leave this hunk undecided, see previous undecided hunk
 K - leave this hunk undecided, see previous hunk
 s - split the current hunk into smaller hunks
+e - manually edit the current hunk
 ? - print help
 EOF
 }
 
 sub patch_update_cmd {
-	my @mods = grep { !($_->{BINARY}) } list_modified('file-only');
+	my @all_mods = list_modified('file-only');
+	my @mods = grep { !($_->{BINARY}) } @all_mods;
 	my @them;
 
 	if (!@mods) {
-		print STDERR "No changes.\n";
+		if (@all_mods) {
+			print STDERR "Only binary files changed.\n";
+		} else {
+			print STDERR "No changes.\n";
+		}
 		return 0;
 	}
 	if ($patch_mode) {
@@ -885,6 +915,7 @@
 		if (hunk_splittable($hunk[$ix]{TEXT})) {
 			$other .= '/s';
 		}
+		$other .= '/e';
 		for (@{$hunk[$ix]{DISPLAY}}) {
 			print;
 		}
@@ -949,6 +980,12 @@
 				$num = scalar @hunk;
 				next;
 			}
+			elsif ($line =~ /^e/) {
+				my $newhunk = edit_hunk_loop($head, \@hunk, $ix);
+				if (defined $newhunk) {
+					splice @hunk, $ix, 1, $newhunk;
+				}
+			}
 			else {
 				help_patch_cmd($other);
 				next;
@@ -962,47 +999,21 @@
 		}
 	}
 
-	@hunk = coalesce_overlapping_hunks(@hunk);
-
 	my $n_lofs = 0;
 	my @result = ();
 	if ($mode->{USE}) {
 		push @result, @{$mode->{TEXT}};
 	}
 	for (@hunk) {
-		my $text = $_->{TEXT};
-		my ($o_ofs, $o_cnt, $n_ofs, $n_cnt) =
-		    parse_hunk_header($text->[0]);
-
-		if (!$_->{USE}) {
-			# We would have added ($n_cnt - $o_cnt) lines
-			# to the postimage if we were to use this hunk,
-			# but we didn't.  So the line number that the next
-			# hunk starts at would be shifted by that much.
-			$n_lofs -= ($n_cnt - $o_cnt);
-			next;
-		}
-		else {
-			if ($n_lofs) {
-				$n_ofs += $n_lofs;
-				$text->[0] = ("@@ -$o_ofs" .
-					      (($o_cnt != 1)
-					       ? ",$o_cnt" : '') .
-					      " +$n_ofs" .
-					      (($n_cnt != 1)
-					       ? ",$n_cnt" : '') .
-					      " @@\n");
-			}
-			for (@$text) {
-				push @result, $_;
-			}
+		if ($_->{USE}) {
+			push @result, @{$_->{TEXT}};
 		}
 	}
 
 	if (@result) {
 		my $fh;
 
-		open $fh, '| git apply --cached';
+		open $fh, '| git apply --cached --recount';
 		for (@{$head->{TEXT}}, @result) {
 			print $fh $_;
 		}
diff --git a/git-am.sh b/git-am.sh
index 83b277a..aa60261 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -5,13 +5,12 @@
 SUBDIRECTORY_OK=Yes
 OPTIONS_KEEPDASHDASH=
 OPTIONS_SPEC="\
-git-am [options] <mbox>|<Maildir>...
-git-am [options] --resolved
-git-am [options] --skip
+git am [options] [<mbox>|<Maildir>...]
+git am [options] (--resolved | --skip | --abort)
 --
 d,dotest=       (removed -- do not use)
 i,interactive   run interactively
-b,binary        pass --allow-binary-replacement to git-apply
+b,binary        (historical option -- no-op)
 3,3way          allow fall back on 3way merging if needed
 s,signoff       add a Signed-off-by line to the commit message
 u,utf8          recode into utf8 (default)
@@ -22,6 +21,7 @@
 resolvemsg=     override error message when patch failure occurs
 r,resolved      to be used after a patch failure
 skip            skip the current patch
+abort           restore the original branch and abort the patching operation.
 rebasing        (internal use for git-rebase)"
 
 . git-sh-setup
@@ -43,7 +43,7 @@
 	    printf '%s\n' "$resolvemsg"
 	    stop_here $1
     fi
-    cmdline=$(basename $0)
+    cmdline="git am"
     if test '' != "$interactive"
     then
         cmdline="$cmdline -i"
@@ -54,6 +54,7 @@
     fi
     echo "When you have resolved this problem run \"$cmdline --resolved\"."
     echo "If you would prefer to skip this patch, instead run \"$cmdline --skip\"."
+    echo "To restore the original branch and stop patching run \"$cmdline --abort\"."
 
     stop_here $1
 }
@@ -86,7 +87,7 @@
 
     echo Using index info to reconstruct a base tree...
     if GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \
-	git apply $binary --cached <"$dotest/patch"
+	git apply --cached <"$dotest/patch"
     then
 	mv "$dotest/patch-merge-base+" "$dotest/patch-merge-base"
 	mv "$dotest/patch-merge-tmp-index" "$dotest/patch-merge-index"
@@ -119,8 +120,8 @@
 }
 
 prec=4
-dotest=".dotest"
-sign= utf8=t keep= skip= interactive= resolved= binary= rebasing=
+dotest="$GIT_DIR/rebase-apply"
+sign= utf8=t keep= skip= interactive= resolved= rebasing= abort=
 resolvemsg= resume=
 git_apply_opt=
 
@@ -130,7 +131,7 @@
 	-i|--interactive)
 		interactive=t ;;
 	-b|--binary)
-		binary=t ;;
+		: ;;
 	-3|--3way)
 		threeway=t ;;
 	-s|--signoff)
@@ -145,8 +146,10 @@
 		resolved=t ;;
 	--skip)
 		skip=t ;;
+	--abort)
+		abort=t ;;
 	--rebasing)
-		rebasing=t threeway=t keep=t binary=t ;;
+		rebasing=t threeway=t keep=t ;;
 	-d|--dotest)
 		die "-d option is no longer supported.  Do not use."
 		;;
@@ -177,7 +180,7 @@
 
 if test -d "$dotest"
 then
-	case "$#,$skip$resolved" in
+	case "$#,$skip$resolved$abort" in
 	0,*t*)
 		# Explicit resume command and we do not have file, so
 		# we are happy.
@@ -195,11 +198,27 @@
 		false
 		;;
 	esac ||
-	die "previous dotest directory $dotest still exists but mbox given."
+	die "previous rebase directory $dotest still exists but mbox given."
 	resume=yes
+
+	case "$skip,$abort" in
+	t,)
+		git rerere clear
+		git read-tree --reset -u HEAD HEAD
+		orig_head=$(cat "$GIT_DIR/ORIG_HEAD")
+		git reset HEAD
+		git update-ref ORIG_HEAD $orig_head
+		;;
+	,t)
+		git rerere clear
+		git read-tree --reset -u HEAD ORIG_HEAD
+		git reset ORIG_HEAD
+		rm -fr "$dotest"
+		exit ;;
+	esac
 else
-	# Make sure we are not given --skip nor --resolved
-	test ",$skip,$resolved," = ,,, ||
+	# Make sure we are not given --skip, --resolved, nor --abort
+	test "$skip$resolved$abort" = "" ||
 		die "Resolve operation not in progress, we are not resuming."
 
 	# Start afresh.
@@ -228,10 +247,9 @@
 		exit 1
 	}
 
-	# -b, -s, -u, -k and --whitespace flags are kept for the
+	# -s, -u, -k and --whitespace flags are kept for the
 	# resuming session after a patch failure.
 	# -3 and -i can and must be given when resuming.
-	echo "$binary" >"$dotest/binary"
 	echo " $ws" >"$dotest/whitespace"
 	echo "$sign" >"$dotest/sign"
 	echo "$utf8" >"$dotest/utf8"
@@ -242,6 +260,7 @@
 		: >"$dotest/rebasing"
 	else
 		: >"$dotest/applying"
+		git update-ref ORIG_HEAD HEAD
 	fi
 fi
 
@@ -254,10 +273,6 @@
 	fi
 esac
 
-if test "$(cat "$dotest/binary")" = t
-then
-	binary=--allow-binary-replacement
-fi
 if test "$(cat "$dotest/utf8")" = t
 then
 	utf8=-u
@@ -271,7 +286,7 @@
 ws=`cat "$dotest/whitespace"`
 if test "$(cat "$dotest/sign")" = t
 then
-	SIGNOFF=`git-var GIT_COMMITTER_IDENT | sed -e '
+	SIGNOFF=`git var GIT_COMMITTER_IDENT | sed -e '
 			s/>.*/>/
 			s/^/Signed-off-by: /'
 		`
@@ -283,7 +298,6 @@
 this=`cat "$dotest/next"`
 if test "$skip" = t
 then
-	git rerere clear
 	this=`expr "$this" + 1`
 	resume=
 fi
@@ -324,7 +338,7 @@
 			<"$dotest"/info >/dev/null &&
 			go_next && continue
 
-		test -s $dotest/patch || {
+		test -s "$dotest/patch" || {
 			echo "Patch is empty.  Was it split wrong?"
 			stop_here $this
 		}
@@ -436,11 +450,11 @@
 		stop_here $this
 	fi
 
-	printf 'Applying %s\n' "$FIRSTLINE"
+	printf 'Applying: %s\n' "$FIRSTLINE"
 
 	case "$resolved" in
 	'')
-		git apply $git_apply_opt $binary --index "$dotest/patch"
+		git apply $git_apply_opt --index "$dotest/patch"
 		apply_status=$?
 		;;
 	t)
diff --git a/git-archimport.perl b/git-archimport.perl
index 9a7a906..98f3ede 100755
--- a/git-archimport.perl
+++ b/git-archimport.perl
@@ -9,7 +9,7 @@
 
 =head1 Invocation
 
-    git-archimport [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ]
+    git archimport [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ]
 	[ -D depth] [ -t tempdir ] <archive>/<branch> [ <archive>/<branch> ]
 
 Imports a project from one or more Arch repositories. It will follow branches
@@ -74,7 +74,7 @@
 
 sub usage() {
     print STDERR <<END;
-Usage: ${\basename $0}     # fetch/update GIT from Arch
+Usage: git archimport     # fetch/update GIT from Arch
        [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ] [ -D depth ] [ -t tempdir ]
        repository/arch-branch [ repository/arch-branch] ...
 END
diff --git a/git-bisect.sh b/git-bisect.sh
index 6c6c3de..97ac600 100755
--- a/git-bisect.sh
+++ b/git-bisect.sh
@@ -149,7 +149,7 @@
 	echo "$start_head" >"$GIT_DIR/BISECT_START" &&
 	sq "$@" >"$GIT_DIR/BISECT_NAMES" &&
 	eval "$eval" &&
-	echo "git-bisect start$orig_args" >>"$GIT_DIR/BISECT_LOG" || exit
+	echo "git bisect start$orig_args" >>"$GIT_DIR/BISECT_LOG" || exit
 	#
 	# Check if we can proceed to the next bisect state.
 	#
@@ -169,7 +169,7 @@
 	esac
 	git update-ref "refs/bisect/$tag" "$rev" || exit
 	echo "# $state: $(git show-branch $rev)" >>"$GIT_DIR/BISECT_LOG"
-	test -n "$nolog" || echo "git-bisect $state $rev" >>"$GIT_DIR/BISECT_LOG"
+	test -n "$nolog" || echo "git bisect $state $rev" >>"$GIT_DIR/BISECT_LOG"
 }
 
 bisect_state() {
@@ -427,9 +427,13 @@
 bisect_replay () {
 	test -r "$1" || die "cannot read $1 for replaying"
 	bisect_reset
-	while read bisect command rev
+	while read git bisect command rev
 	do
-		test "$bisect" = "git-bisect" || continue
+		test "$git $bisect" = "git bisect" -o "$git" = "git-bisect" || continue
+		if test "$git" = "git-bisect"; then
+			rev="$command"
+			command="$bisect"
+		fi
 		case "$command" in
 		start)
 			cmd="bisect_start $rev"
diff --git a/git-compat-util.h b/git-compat-util.h
index c04e8ba..cf89cdf 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -63,17 +63,18 @@
 #include <sys/time.h>
 #include <time.h>
 #include <signal.h>
-#include <sys/wait.h>
 #include <fnmatch.h>
+#include <assert.h>
+#include <regex.h>
+#include <utime.h>
+#ifndef __MINGW32__
+#include <sys/wait.h>
 #include <sys/poll.h>
 #include <sys/socket.h>
 #include <sys/ioctl.h>
-#include <utime.h>
 #ifndef NO_SYS_SELECT_H
 #include <sys/select.h>
 #endif
-#include <assert.h>
-#include <regex.h>
 #include <netinet/in.h>
 #include <netinet/tcp.h>
 #include <arpa/inet.h>
@@ -89,6 +90,10 @@
 #include <grp.h>
 #define _ALL_SOURCE 1
 #endif
+#else 	/* __MINGW32__ */
+/* pull in Windows compatibility stuff */
+#include "compat/mingw.h"
+#endif	/* __MINGW32__ */
 
 #ifndef NO_ICONV
 #include <iconv.h>
@@ -105,6 +110,30 @@
 #define PRIuMAX "llu"
 #endif
 
+#ifndef PRIu32
+#define PRIu32 "u"
+#endif
+
+#ifndef PRIx32
+#define PRIx32 "x"
+#endif
+
+#ifndef PATH_SEP
+#define PATH_SEP ':'
+#endif
+
+#ifndef STRIP_EXTENSION
+#define STRIP_EXTENSION ""
+#endif
+
+#ifndef has_dos_drive_prefix
+#define has_dos_drive_prefix(path) 0
+#endif
+
+#ifndef is_dir_sep
+#define is_dir_sep(c) ((c) == '/')
+#endif
+
 #ifdef __GNUC__
 #define NORETURN __attribute__((__noreturn__))
 #else
@@ -126,6 +155,13 @@
 extern void set_warn_routine(void (*routine)(const char *warn, va_list params));
 
 extern int prefixcmp(const char *str, const char *prefix);
+extern time_t tm_to_time_t(const struct tm *tm);
+
+static inline const char *skip_prefix(const char *str, const char *prefix)
+{
+	size_t len = strlen(prefix);
+	return strncmp(str, prefix, len) ? NULL : str + len;
+}
 
 #ifdef NO_MMAP
 
@@ -163,6 +199,12 @@
 #define pread git_pread
 extern ssize_t git_pread(int fd, void *buf, size_t count, off_t offset);
 #endif
+/*
+ * Forward decl that will remind us if its twin in cache.h changes.
+ * This function is used in compat/pread.c.  But we can't include
+ * cache.h there.
+ */
+extern ssize_t read_in_full(int fd, void *buf, size_t count);
 
 #ifdef NO_SETENV
 #define setenv gitsetenv
@@ -240,161 +282,18 @@
 
 extern void release_pack_memory(size_t, int);
 
-static inline char* xstrdup(const char *str)
-{
-	char *ret = strdup(str);
-	if (!ret) {
-		release_pack_memory(strlen(str) + 1, -1);
-		ret = strdup(str);
-		if (!ret)
-			die("Out of memory, strdup failed");
-	}
-	return ret;
-}
-
-static inline void *xmalloc(size_t size)
-{
-	void *ret = malloc(size);
-	if (!ret && !size)
-		ret = malloc(1);
-	if (!ret) {
-		release_pack_memory(size, -1);
-		ret = malloc(size);
-		if (!ret && !size)
-			ret = malloc(1);
-		if (!ret)
-			die("Out of memory, malloc failed");
-	}
-#ifdef XMALLOC_POISON
-	memset(ret, 0xA5, size);
-#endif
-	return ret;
-}
-
-/*
- * xmemdupz() allocates (len + 1) bytes of memory, duplicates "len" bytes of
- * "data" to the allocated memory, zero terminates the allocated memory,
- * and returns a pointer to the allocated memory. If the allocation fails,
- * the program dies.
- */
-static inline void *xmemdupz(const void *data, size_t len)
-{
-	char *p = xmalloc(len + 1);
-	memcpy(p, data, len);
-	p[len] = '\0';
-	return p;
-}
-
-static inline char *xstrndup(const char *str, size_t len)
-{
-	char *p = memchr(str, '\0', len);
-	return xmemdupz(str, p ? p - str : len);
-}
-
-static inline void *xrealloc(void *ptr, size_t size)
-{
-	void *ret = realloc(ptr, size);
-	if (!ret && !size)
-		ret = realloc(ptr, 1);
-	if (!ret) {
-		release_pack_memory(size, -1);
-		ret = realloc(ptr, size);
-		if (!ret && !size)
-			ret = realloc(ptr, 1);
-		if (!ret)
-			die("Out of memory, realloc failed");
-	}
-	return ret;
-}
-
-static inline void *xcalloc(size_t nmemb, size_t size)
-{
-	void *ret = calloc(nmemb, size);
-	if (!ret && (!nmemb || !size))
-		ret = calloc(1, 1);
-	if (!ret) {
-		release_pack_memory(nmemb * size, -1);
-		ret = calloc(nmemb, size);
-		if (!ret && (!nmemb || !size))
-			ret = calloc(1, 1);
-		if (!ret)
-			die("Out of memory, calloc failed");
-	}
-	return ret;
-}
-
-static inline void *xmmap(void *start, size_t length,
-	int prot, int flags, int fd, off_t offset)
-{
-	void *ret = mmap(start, length, prot, flags, fd, offset);
-	if (ret == MAP_FAILED) {
-		if (!length)
-			return NULL;
-		release_pack_memory(length, fd);
-		ret = mmap(start, length, prot, flags, fd, offset);
-		if (ret == MAP_FAILED)
-			die("Out of memory? mmap failed: %s", strerror(errno));
-	}
-	return ret;
-}
-
-/*
- * xread() is the same a read(), but it automatically restarts read()
- * operations with a recoverable error (EAGAIN and EINTR). xread()
- * DOES NOT GUARANTEE that "len" bytes is read even if the data is available.
- */
-static inline ssize_t xread(int fd, void *buf, size_t len)
-{
-	ssize_t nr;
-	while (1) {
-		nr = read(fd, buf, len);
-		if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
-			continue;
-		return nr;
-	}
-}
-
-/*
- * xwrite() is the same a write(), but it automatically restarts write()
- * operations with a recoverable error (EAGAIN and EINTR). xwrite() DOES NOT
- * GUARANTEE that "len" bytes is written even if the operation is successful.
- */
-static inline ssize_t xwrite(int fd, const void *buf, size_t len)
-{
-	ssize_t nr;
-	while (1) {
-		nr = write(fd, buf, len);
-		if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
-			continue;
-		return nr;
-	}
-}
-
-static inline int xdup(int fd)
-{
-	int ret = dup(fd);
-	if (ret < 0)
-		die("dup failed: %s", strerror(errno));
-	return ret;
-}
-
-static inline FILE *xfdopen(int fd, const char *mode)
-{
-	FILE *stream = fdopen(fd, mode);
-	if (stream == NULL)
-		die("Out of memory? fdopen failed: %s", strerror(errno));
-	return stream;
-}
-
-static inline int xmkstemp(char *template)
-{
-	int fd;
-
-	fd = mkstemp(template);
-	if (fd < 0)
-		die("Unable to create temporary file: %s", strerror(errno));
-	return fd;
-}
+extern char *xstrdup(const char *str);
+extern void *xmalloc(size_t size);
+extern void *xmemdupz(const void *data, size_t len);
+extern char *xstrndup(const char *str, size_t len);
+extern void *xrealloc(void *ptr, size_t size);
+extern void *xcalloc(size_t nmemb, size_t size);
+extern void *xmmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
+extern ssize_t xread(int fd, void *buf, size_t len);
+extern ssize_t xwrite(int fd, const void *buf, size_t len);
+extern int xdup(int fd);
+extern FILE *xfdopen(int fd, const char *mode);
+extern int xmkstemp(char *template);
 
 static inline size_t xsize_t(off_t len)
 {
diff --git a/git-cvsexportcommit.perl b/git-cvsexportcommit.perl
index c6c70e9..6d9f0ef 100755
--- a/git-cvsexportcommit.perl
+++ b/git-cvsexportcommit.perl
@@ -370,7 +370,7 @@
 
 sub usage {
 	print STDERR <<END;
-Usage: GIT_DIR=/path/to/.git ${\basename $0} [-h] [-p] [-v] [-c] [-f] [-u] [-w cvsworkdir] [-m msgprefix] [ parent ] commit
+Usage: GIT_DIR=/path/to/.git git cvsexportcommit [-h] [-p] [-v] [-c] [-f] [-u] [-w cvsworkdir] [-m msgprefix] [ parent ] commit
 END
 	exit(1);
 }
diff --git a/git-cvsimport.perl b/git-cvsimport.perl
index 7e95fb3..e439202 100755
--- a/git-cvsimport.perl
+++ b/git-cvsimport.perl
@@ -36,7 +36,7 @@
 	my $msg = shift;
 	print(STDERR "Error: $msg\n") if $msg;
 	print STDERR <<END;
-Usage: ${\basename $0}     # fetch/update GIT from CVS
+Usage: git cvsimport     # fetch/update GIT from CVS
        [-o branch-for-HEAD] [-h] [-v] [-d CVSROOT] [-A author-conv-file]
        [-p opts-for-cvsps] [-P file] [-C GIT_repository] [-z fuzz] [-i] [-k]
        [-u] [-s subst] [-a] [-m] [-M regex] [-S regex] [-L commitlimit]
diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index b00d1c2..b0a805c 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -101,7 +101,7 @@
 $log->info("--------------- STARTING -----------------");
 
 my $usage =
-    "Usage: git-cvsserver [options] [pserver|server] [<directory> ...]\n".
+    "Usage: git cvsserver [options] [pserver|server] [<directory> ...]\n".
     "    --base-path <path>  : Prepend to requested CVSROOT\n".
     "    --strict-paths      : Don't allow recursing into subdirectories\n".
     "    --export-all        : Don't check for gitcvs.enabled in config\n".
@@ -801,6 +801,18 @@
 
     argsplit("co");
 
+    # Provide list of modules, if -c was used.
+    if (exists $state->{opt}{c}) {
+        my $showref = `git show-ref --heads`;
+        for my $line (split '\n', $showref) {
+            if ( $line =~ m% refs/heads/(.*)$% ) {
+                print "M $1\t$1\n";
+            }
+        }
+        print "ok\n";
+        return 1;
+    }
+
     my $module = $state->{args}[0];
     $state->{module} = $module;
     my $checkout_path = $module;
@@ -947,21 +959,15 @@
     # projects (heads in this case) to checkout.
     #
     if ($state->{module} eq '') {
-	my $heads_dir = $state->{CVSROOT} . '/refs/heads';
-	if (!opendir HEADS, $heads_dir) {
-	    print "E [server aborted]: Failed to open directory, "
-	      . "$heads_dir: $!\nerror\n";
-	    return 0;
-	}
+        my $showref = `git show-ref --heads`;
         print "E cvs update: Updating .\n";
-	while (my $head = readdir(HEADS)) {
-	    if (-f $state->{CVSROOT} . '/refs/heads/' . $head) {
-	        print "E cvs update: New directory `$head'\n";
-	    }
-	}
-	closedir HEADS;
-	print "ok\n";
-	return 1;
+        for my $line (split '\n', $showref) {
+            if ( $line =~ m% refs/heads/(.*)$% ) {
+                print "E cvs update: New directory `$1'\n";
+            }
+        }
+        print "ok\n";
+        return 1;
     }
 
 
diff --git a/git-filter-branch.sh b/git-filter-branch.sh
index d04c346..a324cf0 100755
--- a/git-filter-branch.sh
+++ b/git-filter-branch.sh
@@ -97,9 +97,11 @@
 OPTIONS_SPEC=
 . git-sh-setup
 
-git diff-files --quiet &&
+if [ "$(is_bare_repository)" = false ]; then
+	git diff-files --quiet &&
 	git diff-index --cached --quiet HEAD -- ||
 	die "Cannot rewrite branch(es) with a dirty working directory."
+fi
 
 tempdir=.git-rewrite
 filter_env=
@@ -359,9 +361,17 @@
 	;;
 	$_x40)
 		echo "Ref '$ref' was rewritten"
-		git update-ref -m "filter-branch: rewrite" \
-				"$ref" $rewritten $sha1 ||
-			die "Could not rewrite $ref"
+		if ! git update-ref -m "filter-branch: rewrite" \
+					"$ref" $rewritten $sha1 2>/dev/null; then
+			if test $(git cat-file -t "$ref") = tag; then
+				if test -z "$filter_tag_name"; then
+					warn "WARNING: You said to rewrite tagged commits, but not the corresponding tag."
+					warn "WARNING: Perhaps use '--tag-name-filter cat' to rewrite the tag."
+				fi
+			else
+				die "Could not rewrite $ref"
+			fi
+		fi
 	;;
 	*)
 		# NEEDSWORK: possibly add -Werror, making this an error
@@ -434,18 +444,20 @@
 
 trap - 0
 
-unset GIT_DIR GIT_WORK_TREE GIT_INDEX_FILE
-test -z "$ORIG_GIT_DIR" || {
-	GIT_DIR="$ORIG_GIT_DIR" && export GIT_DIR
-}
-test -z "$ORIG_GIT_WORK_TREE" || {
-	GIT_WORK_TREE="$ORIG_GIT_WORK_TREE" &&
-	export GIT_WORK_TREE
-}
-test -z "$ORIG_GIT_INDEX_FILE" || {
-	GIT_INDEX_FILE="$ORIG_GIT_INDEX_FILE" &&
-	export GIT_INDEX_FILE
-}
-git read-tree -u -m HEAD
+if [ "$(is_bare_repository)" = false ]; then
+	unset GIT_DIR GIT_WORK_TREE GIT_INDEX_FILE
+	test -z "$ORIG_GIT_DIR" || {
+		GIT_DIR="$ORIG_GIT_DIR" && export GIT_DIR
+	}
+	test -z "$ORIG_GIT_WORK_TREE" || {
+		GIT_WORK_TREE="$ORIG_GIT_WORK_TREE" &&
+		export GIT_WORK_TREE
+	}
+	test -z "$ORIG_GIT_INDEX_FILE" || {
+		GIT_INDEX_FILE="$ORIG_GIT_INDEX_FILE" &&
+		export GIT_INDEX_FILE
+	}
+	git read-tree -u -m HEAD
+fi
 
 exit $ret
diff --git a/git-gui/GIT-VERSION-GEN b/git-gui/GIT-VERSION-GEN
index 0ab478e..4e709eb 100755
--- a/git-gui/GIT-VERSION-GEN
+++ b/git-gui/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=0.10.GITGUI
+DEF_VER=0.11.GITGUI
 
 LF='
 '
diff --git a/git-gui/Makefile b/git-gui/Makefile
index b19fb2d..55765c8 100644
--- a/git-gui/Makefile
+++ b/git-gui/Makefile
@@ -34,8 +34,12 @@
 endif
 
 ifndef sharedir
+ifeq (git-core,$(notdir $(gitexecdir)))
+	sharedir := $(dir $(patsubst %/,%,$(dir $(gitexecdir))))share
+else
 	sharedir := $(dir $(gitexecdir))share
 endif
+endif
 
 ifndef INSTALL
 	INSTALL = install
@@ -156,6 +160,7 @@
 ifneq (,$(findstring MINGW,$(uname_S)))
 	NO_MSGFMT=1
 	GITGUI_WINDOWS_WRAPPER := YesPlease
+	GITGUI_RELATIVE := 1
 endif
 
 ifdef GITGUI_MACOSXAPP
diff --git a/git-gui/git-gui.sh b/git-gui/git-gui.sh
index e6e8890..86402d4 100755
--- a/git-gui/git-gui.sh
+++ b/git-gui/git-gui.sh
@@ -52,7 +52,11 @@
 set oguilib {@@GITGUI_LIBDIR@@}
 set oguirel {@@GITGUI_RELATIVE@@}
 if {$oguirel eq {1}} {
-	set oguilib [file dirname [file dirname [file normalize $argv0]]]
+	set oguilib [file dirname [file normalize $argv0]]
+	if {[file tail $oguilib] eq {git-core}} {
+		set oguilib [file dirname $oguilib]
+	}
+	set oguilib [file dirname $oguilib]
 	set oguilib [file join $oguilib share git-gui lib]
 	set oguimsg [file join $oguilib msgs]
 } elseif {[string match @@* $oguirel]} {
@@ -317,7 +321,7 @@
 	return $v
 }
 
-proc _which {what} {
+proc _which {what args} {
 	global env _search_exe _search_path
 
 	if {$_search_path eq {}} {
@@ -340,8 +344,14 @@
 		}
 	}
 
+	if {[is_Windows] && [lsearch -exact $args -script] >= 0} {
+		set suffix {}
+	} else {
+		set suffix $_search_exe
+	}
+
 	foreach p $_search_path {
-		set p [file join $p $what$_search_exe]
+		set p [file join $p $what$suffix]
 		if {[file exists $p]} {
 			return [file normalize $p]
 		}
@@ -473,10 +483,10 @@
 	set pchook [gitdir hooks $hook_name]
 	lappend args 2>@1
 
-	# On Cygwin [file executable] might lie so we need to ask
+	# On Windows [file executable] might lie so we need to ask
 	# the shell if the hook is executable.  Yes that's annoying.
 	#
-	if {[is_Cygwin]} {
+	if {[is_Windows]} {
 		upvar #0 _sh interp
 		if {![info exists interp]} {
 			set interp [_which sh]
@@ -497,6 +507,20 @@
 	return {}
 }
 
+proc kill_file_process {fd} {
+	set process [pid $fd]
+
+	catch {
+		if {[is_Windows]} {
+			# Use a Cygwin-specific flag to allow killing
+			# native Windows processes
+			exec kill -f $process
+		} else {
+			exec kill $process
+		}
+	}
+}
+
 proc sq {value} {
 	regsub -all ' $value "'\\''" value
 	return "'$value'"
@@ -642,6 +666,8 @@
 set default_config(gui.matchtrackingbranch) false
 set default_config(gui.pruneduringfetch) false
 set default_config(gui.trustmtime) false
+set default_config(gui.fastcopyblame) false
+set default_config(gui.copyblamethreshold) 40
 set default_config(gui.diffcontext) 5
 set default_config(gui.commitmsgwidth) 75
 set default_config(gui.newbranchtemplate) {}
@@ -1670,10 +1696,10 @@
 	# -- Always start gitk through whatever we were loaded with.  This
 	#    lets us bypass using shell process on Windows systems.
 	#
-	set exe [file join [file dirname $::_git] gitk]
+	set exe [_which gitk -script]
 	set cmd [list [info nameofexecutable] $exe]
-	if {! [file exists $exe]} {
-		error_popup [mc "Unable to start gitk:\n\n%s does not exist" $exe]
+	if {$exe eq {}} {
+		error_popup [mc "Couldn't find gitk in PATH"]
 	} else {
 		global env
 
@@ -1774,6 +1800,11 @@
 	commit_tree
 }
 
+proc next_diff {} {
+	global next_diff_p next_diff_w next_diff_i
+	show_diff $next_diff_p $next_diff_w $next_diff_i
+}
+
 proc toggle_or_diff {w x y} {
 	global file_states file_lists current_diff_path ui_index ui_workdir
 	global last_clicked selected_paths
@@ -1792,12 +1823,34 @@
 	$ui_index tag remove in_sel 0.0 end
 	$ui_workdir tag remove in_sel 0.0 end
 
-	if {$col == 0} {
-		if {$current_diff_path eq $path} {
+	if {$col == 0 && $y > 1} {
+		set i [expr {$lno-1}]
+		set ll [expr {[llength $file_lists($w)]-1}]
+
+		if {$i == $ll && $i == 0} {
 			set after {reshow_diff;}
 		} else {
-			set after {}
+			global next_diff_p next_diff_w next_diff_i
+
+			set next_diff_w $w
+
+			if {$i < $ll} {
+				set i [expr {$i + 1}]
+				set next_diff_i $i
+			} else {
+				set next_diff_i $i
+				set i [expr {$i - 1}]
+			}
+
+			set next_diff_p [lindex $file_lists($w) $i]
+
+			if {$next_diff_p ne {} && $current_diff_path ne {}} {
+				set after {next_diff;}
+			} else {
+				set after {}
+			}
 		}
+
 		if {$w eq $ui_index} {
 			update_indexinfo \
 				"Unstaging [short_path $path] from commit" \
@@ -1879,7 +1932,7 @@
 
 proc show_less_context {} {
 	global repo_config
-	if {$repo_config(gui.diffcontext) >= 1} {
+	if {$repo_config(gui.diffcontext) > 1} {
 		incr repo_config(gui.diffcontext) -1
 		reshow_diff
 	}
@@ -1968,9 +2021,13 @@
 	}
 }
 
-.mbar.repository add command -label [mc Quit] \
-	-command do_quit \
-	-accelerator $M1T-Q
+if {[is_MacOSX]} {
+	proc ::tk::mac::Quit {args} { do_quit }
+} else {
+	.mbar.repository add command -label [mc Quit] \
+		-command do_quit \
+		-accelerator $M1T-Q
+}
 
 # -- Edit Menu
 #
@@ -2639,6 +2696,11 @@
 	-command {apply_hunk $cursorX $cursorY}
 set ui_diff_applyhunk [$ctxm index last]
 lappend diff_actions [list $ctxm entryconf $ui_diff_applyhunk -state]
+$ctxm add command \
+	-label [mc "Apply/Reverse Line"] \
+	-command {apply_line $cursorX $cursorY; do_rescan}
+set ui_diff_applyline [$ctxm index last]
+lappend diff_actions [list $ctxm entryconf $ui_diff_applyline -state]
 $ctxm add separator
 $ctxm add command \
 	-label [mc "Show Less Context"] \
@@ -2687,8 +2749,10 @@
 	set ::cursorY $y
 	if {$::ui_index eq $::current_diff_side} {
 		set l [mc "Unstage Hunk From Commit"]
+		set t [mc "Unstage Line From Commit"]
 	} else {
 		set l [mc "Stage Hunk For Commit"]
+		set t [mc "Stage Line For Commit"]
 	}
 	if {$::is_3way_diff
 		|| $current_diff_path eq {}
@@ -2699,6 +2763,7 @@
 		set s normal
 	}
 	$ctxm entryconf $::ui_diff_applyhunk -state $s -label $l
+	$ctxm entryconf $::ui_diff_applyline -state $s -label $t
 	tk_popup $ctxm $X $Y
 }
 bind_button3 $ui_diff [list popup_diff_menu $ctxm %x %y %X %Y]
@@ -2870,6 +2935,7 @@
 	populate_fetch_menu
 	set n [expr {[.mbar.remote index end] - $n}]
 	if {$n > 0} {
+		if {[.mbar.remote type 0] eq "tearoff"} { incr n }
 		.mbar.remote insert $n separator
 	}
 	unset n
diff --git a/git-gui/lib/blame.tcl b/git-gui/lib/blame.tcl
index 92fac1b..b6e42cb 100644
--- a/git-gui/lib/blame.tcl
+++ b/git-gui/lib/blame.tcl
@@ -33,13 +33,6 @@
 	#ececec
 }
 
-# Switches for original location detection
-#
-variable original_options [list -C -C]
-if {[git-version >= 1.5.3]} {
-	lappend original_options -w ; # ignore indentation changes
-}
-
 # Current blame data; cleared/reset on each load
 #
 field commit               ; # input commit to blame
@@ -263,6 +256,9 @@
 	$w.ctxm add command \
 		-label [mc "Copy Commit"] \
 		-command [cb _copycommit]
+	$w.ctxm add command \
+		-label [mc "Do Full Copy Detection"] \
+		-command [cb _fullcopyblame]
 
 	foreach i $w_columns {
 		for {set g 0} {$g < [llength $group_colors]} {incr g} {
@@ -333,19 +329,27 @@
 	bind $w.file_pane <Configure> \
 	"if {{$w.file_pane} eq {%W}} {[cb _resize %h]}"
 
+	wm protocol $top WM_DELETE_WINDOW "destroy $top"
+	bind $top <Destroy> [cb _kill]
+
 	_load $this {}
 }
 
+method _kill {} {
+	if {$current_fd ne {}} {
+		kill_file_process $current_fd
+		catch {close $current_fd}
+		set current_fd {}
+	}
+}
+
 method _load {jump} {
 	variable group_colors
 
 	_hide_tooltip $this
 
 	if {$total_lines != 0 || $current_fd ne {}} {
-		if {$current_fd ne {}} {
-			catch {close $current_fd}
-			set current_fd {}
-		}
+		_kill $this
 
 		foreach i $w_columns {
 			$i conf -state normal
@@ -511,7 +515,6 @@
 method _read_blame {fd cur_w cur_d} {
 	upvar #0 $cur_d line_data
 	variable group_colors
-	variable original_options
 
 	if {$fd ne $current_fd} {
 		catch {close $fd}
@@ -684,6 +687,18 @@
 	if {[eof $fd]} {
 		close $fd
 		if {$cur_w eq $w_asim} {
+			# Switches for original location detection
+			set threshold [get_config gui.copyblamethreshold]
+			set original_options [list "-C$threshold"]
+
+			if {![is_config_true gui.fastcopyblame]} {
+				# thorough copy search; insert before the threshold
+				set original_options [linsert $original_options 0 -C]
+			}
+			if {[git-version >= 1.5.3]} {
+				lappend original_options -w ; # ignore indentation changes
+			}
+
 			_exec_blame $this $w_amov @amov_data \
 				$original_options \
 				[mc "Loading original location annotations..."]
@@ -696,6 +711,72 @@
 	}
 } ifdeleted { catch {close $fd} }
 
+method _find_commit_bound {data_list start_idx delta} {
+	upvar #0 $data_list line_data
+	set pos $start_idx
+	set limit       [expr {[llength $line_data] - 1}]
+	set base_commit [lindex $line_data $pos 0]
+
+	while {$pos > 0 && $pos < $limit} {
+		set new_pos [expr {$pos + $delta}]
+		if {[lindex $line_data $new_pos 0] ne $base_commit} {
+			return $pos
+		}
+
+		set pos $new_pos
+	}
+
+	return $pos
+}
+
+method _fullcopyblame {} {
+	if {$current_fd ne {}} {
+		tk_messageBox \
+			-icon error \
+			-type ok \
+			-title [mc "Busy"] \
+			-message [mc "Annotation process is already running."]
+
+		return
+	}
+
+	# Switches for original location detection
+	set threshold [get_config gui.copyblamethreshold]
+	set original_options [list -C -C "-C$threshold"]
+
+	if {[git-version >= 1.5.3]} {
+		lappend original_options -w ; # ignore indentation changes
+	}
+
+	# Find the line range
+	set pos @$::cursorX,$::cursorY
+	set lno [lindex [split [$::cursorW index $pos] .] 0]
+	set min_amov_lno [_find_commit_bound $this @amov_data $lno -1]
+	set max_amov_lno [_find_commit_bound $this @amov_data $lno 1]
+	set min_asim_lno [_find_commit_bound $this @asim_data $lno -1]
+	set max_asim_lno [_find_commit_bound $this @asim_data $lno 1]
+
+	if {$min_asim_lno < $min_amov_lno} {
+		set min_amov_lno $min_asim_lno
+	}
+
+	if {$max_asim_lno > $max_amov_lno} {
+		set max_amov_lno $max_asim_lno
+	}
+
+	lappend original_options -L "$min_amov_lno,$max_amov_lno"
+
+	# Clear lines
+	for {set i $min_amov_lno} {$i <= $max_amov_lno} {incr i} {
+		lset amov_data $i [list ]
+	}
+
+	# Start the back-end process
+	_exec_blame $this $w_amov @amov_data \
+		$original_options \
+		[mc "Running thorough copy detection..."]
+}
+
 method _click {cur_w pos} {
 	set lno [lindex [split [$cur_w index $pos] .] 0]
 	_showcommit $this $cur_w $lno
diff --git a/git-gui/lib/diff.tcl b/git-gui/lib/diff.tcl
index d04f6db..1970b60 100644
--- a/git-gui/lib/diff.tcl
+++ b/git-gui/lib/diff.tcl
@@ -19,6 +19,7 @@
 proc reshow_diff {} {
 	global file_states file_lists
 	global current_diff_path current_diff_side
+	global ui_diff
 
 	set p $current_diff_path
 	if {$p eq {}} {
@@ -28,7 +29,8 @@
 		|| [lsearch -sorted -exact $file_lists($current_diff_side) $p] == -1} {
 		clear_diff
 	} else {
-		show_diff $p $current_diff_side
+		set save_pos [lindex [$ui_diff yview] 0]
+		show_diff $p $current_diff_side {} $save_pos
 	}
 }
 
@@ -52,7 +54,7 @@
 	rescan ui_ready 0
 }
 
-proc show_diff {path w {lno {}}} {
+proc show_diff {path w {lno {}} {scroll_pos {}}} {
 	global file_states file_lists
 	global is_3way_diff diff_active repo_config
 	global ui_diff ui_index ui_workdir
@@ -151,6 +153,10 @@
 		$ui_diff conf -state disabled
 		set diff_active 0
 		unlock_index
+		if {$scroll_pos ne {}} {
+			update
+			$ui_diff yview moveto $scroll_pos
+		}
 		ui_ready
 		return
 	}
@@ -169,7 +175,7 @@
 
 	lappend cmd -p
 	lappend cmd --no-color
-	if {$repo_config(gui.diffcontext) >= 0} {
+	if {$repo_config(gui.diffcontext) >= 1} {
 		lappend cmd "-U$repo_config(gui.diffcontext)"
 	}
 	if {$w eq $ui_index} {
@@ -186,14 +192,15 @@
 		return
 	}
 
+	set ::current_diff_inheader 1
 	fconfigure $fd \
 		-blocking 0 \
 		-encoding binary \
 		-translation binary
-	fileevent $fd readable [list read_diff $fd]
+	fileevent $fd readable [list read_diff $fd $scroll_pos]
 }
 
-proc read_diff {fd} {
+proc read_diff {fd scroll_pos} {
 	global ui_diff diff_active
 	global is_3way_diff current_diff_header
 
@@ -201,18 +208,21 @@
 	while {[gets $fd line] >= 0} {
 		# -- Cleanup uninteresting diff header lines.
 		#
-		if {   [string match {diff --git *}      $line]
-			|| [string match {diff --cc *}       $line]
-			|| [string match {diff --combined *} $line]
-			|| [string match {--- *}             $line]
-			|| [string match {+++ *}             $line]} {
-			append current_diff_header $line "\n"
-			continue
+		if {$::current_diff_inheader} {
+			if {   [string match {diff --git *}      $line]
+			    || [string match {diff --cc *}       $line]
+			    || [string match {diff --combined *} $line]
+			    || [string match {--- *}             $line]
+			    || [string match {+++ *}             $line]} {
+				append current_diff_header $line "\n"
+				continue
+			}
 		}
 		if {[string match {index *} $line]} continue
 		if {$line eq {deleted file mode 120000}} {
 			set line "deleted symlink"
 		}
+		set ::current_diff_inheader 0
 
 		# -- Automatically detect if this is a 3 way diff.
 		#
@@ -282,6 +292,10 @@
 		close $fd
 		set diff_active 0
 		unlock_index
+		if {$scroll_pos ne {}} {
+			update
+			$ui_diff yview moveto $scroll_pos
+		}
 		ui_ready
 
 		if {[$ui_diff index end] eq {2.0}} {
@@ -362,3 +376,148 @@
 		set current_diff_path $current_diff_path
 	}
 }
+
+proc apply_line {x y} {
+	global current_diff_path current_diff_header current_diff_side
+	global ui_diff ui_index file_states
+
+	if {$current_diff_path eq {} || $current_diff_header eq {}} return
+	if {![lock_index apply_hunk]} return
+
+	set apply_cmd {apply --cached --whitespace=nowarn}
+	set mi [lindex $file_states($current_diff_path) 0]
+	if {$current_diff_side eq $ui_index} {
+		set failed_msg [mc "Failed to unstage selected line."]
+		set to_context {+}
+		lappend apply_cmd --reverse
+		if {[string index $mi 0] ne {M}} {
+			unlock_index
+			return
+		}
+	} else {
+		set failed_msg [mc "Failed to stage selected line."]
+		set to_context {-}
+		if {[string index $mi 1] ne {M}} {
+			unlock_index
+			return
+		}
+	}
+
+	set the_l [$ui_diff index @$x,$y]
+
+	# operate only on change lines
+	set c1 [$ui_diff get "$the_l linestart"]
+	if {$c1 ne {+} && $c1 ne {-}} {
+		unlock_index
+		return
+	}
+	set sign $c1
+
+	set i_l [$ui_diff search -backwards -regexp ^@@ $the_l 0.0]
+	if {$i_l eq {}} {
+		unlock_index
+		return
+	}
+	# $i_l is now at the beginning of a line
+
+	# pick start line number from hunk header
+	set hh [$ui_diff get $i_l "$i_l + 1 lines"]
+	set hh [lindex [split $hh ,] 0]
+	set hln [lindex [split $hh -] 1]
+
+	# There is a special situation to take care of. Consider this hunk:
+	#
+	#    @@ -10,4 +10,4 @@
+	#     context before
+	#    -old 1
+	#    -old 2
+	#    +new 1
+	#    +new 2
+	#     context after
+	#
+	# We used to keep the context lines in the order they appear in the
+	# hunk. But then it is not possible to correctly stage only
+	# "-old 1" and "+new 1" - it would result in this staged text:
+	#
+	#    context before
+	#    old 2
+	#    new 1
+	#    context after
+	#
+	# (By symmetry it is not possible to *un*stage "old 2" and "new 2".)
+	#
+	# We resolve the problem by introducing an asymmetry, namely, when
+	# a "+" line is *staged*, it is moved in front of the context lines
+	# that are generated from the "-" lines that are immediately before
+	# the "+" block. That is, we construct this patch:
+	#
+	#    @@ -10,4 +10,5 @@
+	#     context before
+	#    +new 1
+	#     old 1
+	#     old 2
+	#     context after
+	#
+	# But we do *not* treat "-" lines that are *un*staged in a special
+	# way.
+	#
+	# With this asymmetry it is possible to stage the change
+	# "old 1" -> "new 1" directly, and to stage the change
+	# "old 2" -> "new 2" by first staging the entire hunk and
+	# then unstaging the change "old 1" -> "new 1".
+
+	# This is non-empty if and only if we are _staging_ changes;
+	# then it accumulates the consecutive "-" lines (after converting
+	# them to context lines) in order to be moved after the "+" change
+	# line.
+	set pre_context {}
+
+	set n 0
+	set i_l [$ui_diff index "$i_l + 1 lines"]
+	set patch {}
+	while {[$ui_diff compare $i_l < "end - 1 chars"] &&
+	       [$ui_diff get $i_l "$i_l + 2 chars"] ne {@@}} {
+		set next_l [$ui_diff index "$i_l + 1 lines"]
+		set c1 [$ui_diff get $i_l]
+		if {[$ui_diff compare $i_l <= $the_l] &&
+		    [$ui_diff compare $the_l < $next_l]} {
+			# the line to stage/unstage
+			set ln [$ui_diff get $i_l $next_l]
+			if {$c1 eq {-}} {
+				set n [expr $n+1]
+				set patch "$patch$pre_context$ln"
+			} else {
+				set patch "$patch$ln$pre_context"
+			}
+			set pre_context {}
+		} elseif {$c1 ne {-} && $c1 ne {+}} {
+			# context line
+			set ln [$ui_diff get $i_l $next_l]
+			set patch "$patch$pre_context$ln"
+			set n [expr $n+1]
+			set pre_context {}
+		} elseif {$c1 eq $to_context} {
+			# turn change line into context line
+			set ln [$ui_diff get "$i_l + 1 chars" $next_l]
+			if {$c1 eq {-}} {
+				set pre_context "$pre_context $ln"
+			} else {
+				set patch "$patch $ln"
+			}
+			set n [expr $n+1]
+		}
+		set i_l $next_l
+	}
+	set patch "@@ -$hln,$n +$hln,[eval expr $n $sign 1] @@\n$patch"
+
+	if {[catch {
+		set p [eval git_write $apply_cmd]
+		fconfigure $p -translation binary -encoding binary
+		puts -nonewline $p $current_diff_header
+		puts -nonewline $p $patch
+		close $p} err]} {
+		error_popup [append $failed_msg "\n\n$err"]
+	}
+
+	unlock_index
+}
diff --git a/git-gui/lib/merge.tcl b/git-gui/lib/merge.tcl
index cc26b07..5c01875 100644
--- a/git-gui/lib/merge.tcl
+++ b/git-gui/lib/merge.tcl
@@ -257,6 +257,7 @@
 
 		catch {file delete [gitdir MERGE_HEAD]}
 		catch {file delete [gitdir rr-cache MERGE_RR]}
+		catch {file delete [gitdir MERGE_RR]}
 		catch {file delete [gitdir SQUASH_MSG]}
 		catch {file delete [gitdir MERGE_MSG]}
 		catch {file delete [gitdir GITGUI_MSG]}
diff --git a/git-gui/lib/option.tcl b/git-gui/lib/option.tcl
index 9270512..5e1346e 100644
--- a/git-gui/lib/option.tcl
+++ b/git-gui/lib/option.tcl
@@ -123,7 +123,9 @@
 		{b gui.trustmtime  {mc "Trust File Modification Timestamps"}}
 		{b gui.pruneduringfetch {mc "Prune Tracking Branches During Fetch"}}
 		{b gui.matchtrackingbranch {mc "Match Tracking Branches"}}
-		{i-0..99 gui.diffcontext {mc "Number of Diff Context Lines"}}
+		{b gui.fastcopyblame {mc "Blame Copy Only On Changed Files"}}
+		{i-20..200 gui.copyblamethreshold {mc "Minimum Letters To Blame Copy On"}}
+		{i-1..99 gui.diffcontext {mc "Number of Diff Context Lines"}}
 		{i-0..99 gui.commitmsgwidth {mc "Commit Message Text Width"}}
 		{t gui.newbranchtemplate {mc "New Branch Name Template"}}
 		} {
diff --git a/git-gui/lib/spellcheck.tcl b/git-gui/lib/spellcheck.tcl
index 78f344f..a479b2f 100644
--- a/git-gui/lib/spellcheck.tcl
+++ b/git-gui/lib/spellcheck.tcl
@@ -80,7 +80,7 @@
 		error_popup [strcat [mc "Unrecognized spell checker"] ":\n\n$s_version"]
 		return
 	}
-	set s_version [string range $s_version 5 end]
+	set s_version [string range [string trim $s_version] 5 end]
 	regexp \
 		{International Ispell Version .* \(but really (Aspell .*?)\)$} \
 		$s_version _junk s_version
diff --git a/git-gui/macosx/AppMain.tcl b/git-gui/macosx/AppMain.tcl
index 41ca08e..ddbe633 100644
--- a/git-gui/macosx/AppMain.tcl
+++ b/git-gui/macosx/AppMain.tcl
@@ -7,7 +7,7 @@
 }
 
 if {[file tail [lindex $argv 0]] eq {gitk}} {
-	set argv0 [file join $gitexecdir gitk]
+	set argv0 [lindex $argv 0]
 	set AppMain_source $argv0
 } else {
 	set argv0 [file join $gitexecdir [file tail [lindex $argv 0]]]
diff --git a/git-gui/po/README b/git-gui/po/README
index 5e77a7d..595bbf5 100644
--- a/git-gui/po/README
+++ b/git-gui/po/README
@@ -101,7 +101,7 @@
    "printf()"-like functions.  Make sure "%s", "%d", and "%%" in your
    translated messages match the original.
 
-   When you have to change the order of words, you can add "<number>\$"
+   When you have to change the order of words, you can add "<number>$"
    between '%' and the conversion ('s', 'd', etc.) to say "<number>-th
    parameter to the format string is used at this point".  For example,
    if the original message is like this:
@@ -111,12 +111,17 @@
    and if for whatever reason your translation needs to say weight first
    and then length, you can say something like:
 
-	"WEIGHT IS %2\$d, LENGTH IS %1\$d"
+	"WEIGHT IS %2$d, LENGTH IS %1$d"
 
-   The reason you need a backslash before dollar sign is because
-   this is a double quoted string in Tcl language, and without
-   it the letter introduces a variable interpolation, which you
-   do not want here.
+   A format specification with a '*' (asterisk) refers to *two* arguments
+   instead of one, hence the succeeding argument number is two higher
+   instead of one. So, a message like this
+
+	"%s ... %*i of %*i %s (%3i%%)"
+
+   is equivalent to
+
+	"%1$s ... %2$*i of %4$*i %6$s (%7$3i%%)"
 
  - A long message can be split across multiple lines by ending the
    string with a double quote, and starting another string on the next
diff --git a/git-gui/po/de.po b/git-gui/po/de.po
index f20955c..fa43947 100644
--- a/git-gui/po/de.po
+++ b/git-gui/po/de.po
@@ -7,8 +7,8 @@
 msgstr ""
 "Project-Id-Version: git-gui\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-03-14 07:18+0100\n"
-"PO-Revision-Date: 2008-05-01 11:51+0200\n"
+"POT-Creation-Date: 2008-08-02 08:58+0200\n"
+"PO-Revision-Date: 2008-08-02 09:09+0200\n"
 "Last-Translator: Christian Stimming <stimming@tuhh.de>\n"
 "Language-Team: German\n"
 "MIME-Version: 1.0\n"
@@ -134,18 +134,11 @@
 msgid "Starting gitk... please wait..."
 msgstr "Gitk wird gestartet... bitte warten."
 
-#: git-gui.sh:1653
-#, tcl-format
-msgid ""
-"Unable to start gitk:\n"
-"\n"
-"%s does not exist"
-msgstr ""
-"Gitk kann nicht gestartet werden:\n"
-"\n"
-"%s existiert nicht"
+#: git-gui.sh:1698
+msgid "Couldn't find gitk in PATH"
+msgstr "Gitk kann im PATH nicht gefunden werden."
 
-#: git-gui.sh:1860 lib/choose_repository.tcl:36
+#: git-gui.sh:1948 lib/choose_repository.tcl:36
 msgid "Repository"
 msgstr "Projektarchiv"
 
@@ -294,7 +287,15 @@
 msgid "Revert Changes"
 msgstr "Änderungen verwerfen"
 
-#: git-gui.sh:2049 git-gui.sh:2368 git-gui.sh:2467
+#: git-gui.sh:2141 git-gui.sh:2702
+msgid "Show Less Context"
+msgstr "Weniger Zeilen anzeigen"
+
+#: git-gui.sh:2145 git-gui.sh:2706
+msgid "Show More Context"
+msgstr "Mehr Zeilen anzeigen"
+
+#: git-gui.sh:2151 git-gui.sh:2470 git-gui.sh:2569
 msgid "Sign Off"
 msgstr "Abzeichnen"
 
@@ -314,11 +315,7 @@
 msgid "Push..."
 msgstr "Versenden..."
 
-#: git-gui.sh:2092 lib/choose_repository.tcl:41
-msgid "Apple"
-msgstr "Apple"
-
-#: git-gui.sh:2095 git-gui.sh:2117 lib/about.tcl:14
+#: git-gui.sh:2197 git-gui.sh:2219 lib/about.tcl:14
 #: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50
 #, tcl-format
 msgid "About %s"
@@ -403,15 +400,11 @@
 msgid "Apply/Reverse Hunk"
 msgstr "Kontext anwenden/umkehren"
 
-#: git-gui.sh:2595
-msgid "Show Less Context"
-msgstr "Weniger Zeilen anzeigen"
+#: git-gui.sh:2696
+msgid "Apply/Reverse Line"
+msgstr "Zeile anwenden/umkehren"
 
-#: git-gui.sh:2602
-msgid "Show More Context"
-msgstr "Mehr Zeilen anzeigen"
-
-#: git-gui.sh:2610
+#: git-gui.sh:2711
 msgid "Refresh"
 msgstr "Aktualisieren"
 
@@ -427,11 +420,19 @@
 msgid "Unstage Hunk From Commit"
 msgstr "Kontext aus Bereitstellung herausnehmen"
 
-#: git-gui.sh:2648
+#: git-gui.sh:2748
+msgid "Unstage Line From Commit"
+msgstr "Zeile aus der Bereitstellung herausnehmen"
+
+#: git-gui.sh:2750
 msgid "Stage Hunk For Commit"
 msgstr "Kontext zur Bereitstellung hinzufügen"
 
-#: git-gui.sh:2667
+#: git-gui.sh:2751
+msgid "Stage Line For Commit"
+msgstr "Zeile zur Bereitstellung hinzufügen"
+
+#: git-gui.sh:2771
 msgid "Initializing..."
 msgstr "Initialisieren..."
 
@@ -493,7 +494,11 @@
 msgid "Copy Commit"
 msgstr "Version kopieren"
 
-#: lib/blame.tcl:384
+#: lib/blame.tcl:260
+msgid "Do Full Copy Detection"
+msgstr "Volle Kopie-Erkennung"
+
+#: lib/blame.tcl:388
 #, tcl-format
 msgid "Reading %s..."
 msgstr "%s lesen..."
@@ -514,7 +519,19 @@
 msgid "Annotation complete."
 msgstr "Annotierung vollständig."
 
-#: lib/blame.tcl:746
+#: lib/blame.tcl:737
+msgid "Busy"
+msgstr "Verarbeitung läuft"
+
+#: lib/blame.tcl:738
+msgid "Annotation process is already running."
+msgstr "Annotierung läuft bereits."
+
+#: lib/blame.tcl:777
+msgid "Running thorough copy detection..."
+msgstr "Intensive Kopie-Erkennung läuft..."
+
+#: lib/blame.tcl:827
 msgid "Loading annotation..."
 msgstr "Annotierung laden..."
 
@@ -759,7 +776,12 @@
 msgid "Branch '%s' does not exist."
 msgstr "Zweig »%s« existiert nicht."
 
-#: lib/checkout_op.tcl:206
+#: lib/checkout_op.tcl:193
+#, tcl-format
+msgid "Failed to configure simplified git-pull for '%s'."
+msgstr "Fehler beim Einrichten der vereinfachten git-pull für »%s«."
+
+#: lib/checkout_op.tcl:228
 #, tcl-format
 msgid ""
 "Branch '%s' already exists.\n"
@@ -1485,6 +1507,14 @@
 msgid "Failed to stage selected hunk."
 msgstr "Fehler beim Bereitstellen des gewählten Kontexts."
 
+#: lib/diff.tcl:386
+msgid "Failed to unstage selected line."
+msgstr "Fehler beim Herausnehmen der gewählten Zeile aus der Bereitstellung."
+
+#: lib/diff.tcl:394
+msgid "Failed to stage selected line."
+msgstr "Fehler beim Bereitstellen der gewählten Zeile."
+
 #: lib/error.tcl:20 lib/error.tcl:114
 msgid "error"
 msgstr "Fehler"
@@ -1750,6 +1780,14 @@
 msgstr "Passend zu Übernahmezweig"
 
 #: lib/option.tcl:126
+msgid "Blame Copy Only On Changed Files"
+msgstr "Kopie-Annotieren nur bei geänderten Dateien"
+
+#: lib/option.tcl:127
+msgid "Minimum Letters To Blame Copy On"
+msgstr "Mindestzahl Zeichen für Kopie-Annotieren"
+
+#: lib/option.tcl:128
 msgid "Number of Diff Context Lines"
 msgstr "Anzahl der Kontextzeilen beim Vergleich"
 
diff --git a/git-gui/po/fr.po b/git-gui/po/fr.po
index 89b6d51..26b866f 100644
--- a/git-gui/po/fr.po
+++ b/git-gui/po/fr.po
@@ -1,50 +1,51 @@
-# translation of fr.po to French
+# translation of fr.po to Français
 # Translation of git-gui to French.
 # Copyright (C) 2008 Shawn Pearce, et al.
 # This file is distributed under the same license as the git package.
 #
 # Christian Couder <chriscool@tuxfamily.org>, 2008.
+# Alexandre Bourget <alexandre.bourget@savoirfairelinux.com>, 2008.
 msgid ""
 msgstr ""
 "Project-Id-Version: fr\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-03-14 07:18+0100\n"
-"PO-Revision-Date: 2008-04-04 22:05+0200\n"
-"Last-Translator: Christian Couder <chriscool@tuxfamily.org>\n"
-"Language-Team: French\n"
+"POT-Creation-Date: 2008-08-02 14:45-0700\n"
+"PO-Revision-Date: 2008-08-11 17:12-0400\n"
+"Last-Translator: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com>\n"
+"Language-Team: Français <fr@li.org>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "X-Generator: KBabel 1.11.4\n"
 "Plural-Forms:  nplurals=2; plural=(n > 1);\n"
 
-#: git-gui.sh:41 git-gui.sh:634 git-gui.sh:648 git-gui.sh:661 git-gui.sh:744
-#: git-gui.sh:763
+#: git-gui.sh:41 git-gui.sh:688 git-gui.sh:702 git-gui.sh:715 git-gui.sh:798
+#: git-gui.sh:817
 msgid "git-gui: fatal error"
 msgstr "git-gui: erreur fatale"
 
-#: git-gui.sh:593
+#: git-gui.sh:644
 #, tcl-format
 msgid "Invalid font specified in %s:"
-msgstr "Invalide fonte spécifiée dans %s :"
+msgstr "Police invalide spécifiée dans %s :"
 
-#: git-gui.sh:620
+#: git-gui.sh:674
 msgid "Main Font"
-msgstr "Fonte principale"
+msgstr "Police principale"
 
-#: git-gui.sh:621
+#: git-gui.sh:675
 msgid "Diff/Console Font"
-msgstr "Fonte diff/console"
+msgstr "Police diff/console"
 
-#: git-gui.sh:635
+#: git-gui.sh:689
 msgid "Cannot find git in PATH."
 msgstr "Impossible de trouver git dans PATH."
 
-#: git-gui.sh:662
+#: git-gui.sh:716
 msgid "Cannot parse Git version string:"
 msgstr "Impossible de parser la version de Git :"
 
-#: git-gui.sh:680
+#: git-gui.sh:734
 #, tcl-format
 msgid ""
 "Git version cannot be determined.\n"
@@ -63,378 +64,381 @@
 "\n"
 "Peut'on considérer que '%s' est en version 1.5.0 ?\n"
 
-#: git-gui.sh:918
+#: git-gui.sh:972
 msgid "Git directory not found:"
-msgstr "Impossible de trouver le répertoire de Git :"
+msgstr "Impossible de trouver le répertoire git :"
 
-#: git-gui.sh:925
+#: git-gui.sh:979
 msgid "Cannot move to top of working directory:"
 msgstr "Impossible d'aller à la racine du répertoire de travail :"
 
-#: git-gui.sh:932
+#: git-gui.sh:986
 msgid "Cannot use funny .git directory:"
-msgstr "Impossible d'utiliser un drôle de répertoire git :"
+msgstr "Impossible d'utiliser le répertoire .git:"
 
-#: git-gui.sh:937
+#: git-gui.sh:991
 msgid "No working directory"
-msgstr "Pas de répertoire de travail"
+msgstr "Aucun répertoire de travail"
 
-#: git-gui.sh:1084 lib/checkout_op.tcl:283
+#: git-gui.sh:1138 lib/checkout_op.tcl:305
 msgid "Refreshing file status..."
 msgstr "Rafraichissement du status des fichiers..."
 
-#: git-gui.sh:1149
+#: git-gui.sh:1194
 msgid "Scanning for modified files ..."
 msgstr "Recherche de fichiers modifiés..."
 
-#: git-gui.sh:1324 lib/browser.tcl:246
+#: git-gui.sh:1369 lib/browser.tcl:246
 msgid "Ready."
 msgstr "Prêt."
 
-#: git-gui.sh:1590
+#: git-gui.sh:1635
 msgid "Unmodified"
 msgstr "Non modifié"
 
-#: git-gui.sh:1592
+#: git-gui.sh:1637
 msgid "Modified, not staged"
-msgstr "Modifié, non pré-commité"
+msgstr "Modifié, pas indexé"
 
-#: git-gui.sh:1593 git-gui.sh:1598
+#: git-gui.sh:1638 git-gui.sh:1643
 msgid "Staged for commit"
-msgstr "Pré-commité"
+msgstr "Indexé"
 
-#: git-gui.sh:1594 git-gui.sh:1599
+#: git-gui.sh:1639 git-gui.sh:1644
 msgid "Portions staged for commit"
-msgstr "En partie pré-commité"
+msgstr "Portions indexées"
 
-#: git-gui.sh:1595 git-gui.sh:1600
+#: git-gui.sh:1640 git-gui.sh:1645
 msgid "Staged for commit, missing"
-msgstr "Pré-commité, manquant"
+msgstr "Indexés, manquant"
 
-#: git-gui.sh:1597
+#: git-gui.sh:1642
 msgid "Untracked, not staged"
-msgstr "Non suivi, non pré-commité"
+msgstr "Non versionné, non indexé"
 
-#: git-gui.sh:1602
+#: git-gui.sh:1647
 msgid "Missing"
 msgstr "Manquant"
 
-#: git-gui.sh:1603
+#: git-gui.sh:1648
 msgid "Staged for removal"
-msgstr "Pré-commité pour suppression"
+msgstr "Indexé pour suppression"
 
-#: git-gui.sh:1604
+#: git-gui.sh:1649
 msgid "Staged for removal, still present"
-msgstr "Pré-commité pour suppression, toujours présent"
+msgstr "Indexé pour suppression, toujours présent"
 
-#: git-gui.sh:1606 git-gui.sh:1607 git-gui.sh:1608 git-gui.sh:1609
+#: git-gui.sh:1651 git-gui.sh:1652 git-gui.sh:1653 git-gui.sh:1654
 msgid "Requires merge resolution"
 msgstr "Nécessite la résolution d'une fusion"
 
-#: git-gui.sh:1644
+#: git-gui.sh:1689
 msgid "Starting gitk... please wait..."
-msgstr "Lancement de gitk... merci de patienter..."
+msgstr "Lancement de gitk... un instant..."
 
-#: git-gui.sh:1653
-#, tcl-format
-msgid ""
-"Unable to start gitk:\n"
-"\n"
-"%s does not exist"
-msgstr ""
-"Impossible de lancer gitk :\n"
-"\n"
-"%s inexistant"
+#: git-gui.sh:1698
+msgid "Couldn't find gitk in PATH"
+msgstr "Impossible de trouver gitk dans PATH."
 
-#: git-gui.sh:1860 lib/choose_repository.tcl:36
+#: git-gui.sh:1948 lib/choose_repository.tcl:36
 msgid "Repository"
-msgstr "Référentiel"
+msgstr "Dépôt"
 
-#: git-gui.sh:1861
+#: git-gui.sh:1949
 msgid "Edit"
-msgstr "Editer"
+msgstr "Edition"
 
-#: git-gui.sh:1863 lib/choose_rev.tcl:561
+#: git-gui.sh:1951 lib/choose_rev.tcl:561
 msgid "Branch"
 msgstr "Branche"
 
-#: git-gui.sh:1866 lib/choose_rev.tcl:548
+#: git-gui.sh:1954 lib/choose_rev.tcl:548
 msgid "Commit@@noun"
 msgstr "Commit"
 
-#: git-gui.sh:1869 lib/merge.tcl:120 lib/merge.tcl:149 lib/merge.tcl:167
+#: git-gui.sh:1957 lib/merge.tcl:120 lib/merge.tcl:149 lib/merge.tcl:167
 msgid "Merge"
 msgstr "Fusionner"
 
-#: git-gui.sh:1870 lib/choose_rev.tcl:557
+#: git-gui.sh:1958 lib/choose_rev.tcl:557
 msgid "Remote"
-msgstr "Référentiel distant"
+msgstr "Dépôt distant"
 
-#: git-gui.sh:1879
+#: git-gui.sh:1967
 msgid "Browse Current Branch's Files"
-msgstr "Visionner fichiers dans branche courante"
+msgstr "Naviguer dans la branche courante"
 
-#: git-gui.sh:1883
+#: git-gui.sh:1971
 msgid "Browse Branch Files..."
-msgstr "Visionner fichiers de branche"
+msgstr "Naviguer dans la branche..."
 
-#: git-gui.sh:1888
+#: git-gui.sh:1976
 msgid "Visualize Current Branch's History"
 msgstr "Visualiser historique branche courante"
 
-#: git-gui.sh:1892
+#: git-gui.sh:1980
 msgid "Visualize All Branch History"
-msgstr "Visualiser historique toutes branches"
+msgstr "Voir l'historique de toutes les branches"
 
-#: git-gui.sh:1899
+#: git-gui.sh:1987
 #, tcl-format
 msgid "Browse %s's Files"
-msgstr "Visionner fichiers de %s"
+msgstr "Naviguer l'arborescence de %s"
 
-#: git-gui.sh:1901
+#: git-gui.sh:1989
 #, tcl-format
 msgid "Visualize %s's History"
-msgstr "Visualiser historique de %s"
+msgstr "Voir l'historique de la branche: %s"
 
-#: git-gui.sh:1906 lib/database.tcl:27 lib/database.tcl:67
+#: git-gui.sh:1994 lib/database.tcl:27 lib/database.tcl:67
 msgid "Database Statistics"
-msgstr "Statistiques base de donnée"
+msgstr "Statistiques du dépôt"
 
-#: git-gui.sh:1909 lib/database.tcl:34
+#: git-gui.sh:1997 lib/database.tcl:34
 msgid "Compress Database"
-msgstr "Comprimer base de donnée"
+msgstr "Comprimer le dépôt"
 
-#: git-gui.sh:1912
+#: git-gui.sh:2000
 msgid "Verify Database"
-msgstr "Vérifier base de donnée"
+msgstr "Vérifier le dépôt"
 
-#: git-gui.sh:1919 git-gui.sh:1923 git-gui.sh:1927 lib/shortcut.tcl:7
+#: git-gui.sh:2007 git-gui.sh:2011 git-gui.sh:2015 lib/shortcut.tcl:7
 #: lib/shortcut.tcl:39 lib/shortcut.tcl:71
 msgid "Create Desktop Icon"
 msgstr "Créer icône sur bureau"
 
-#: git-gui.sh:1932 lib/choose_repository.tcl:177 lib/choose_repository.tcl:185
+#: git-gui.sh:2023 lib/choose_repository.tcl:177 lib/choose_repository.tcl:185
 msgid "Quit"
 msgstr "Quitter"
 
-#: git-gui.sh:1939
+#: git-gui.sh:2031
 msgid "Undo"
 msgstr "Défaire"
 
-#: git-gui.sh:1942
+#: git-gui.sh:2034
 msgid "Redo"
 msgstr "Refaire"
 
-#: git-gui.sh:1946 git-gui.sh:2443
+#: git-gui.sh:2038 git-gui.sh:2545
 msgid "Cut"
 msgstr "Couper"
 
-#: git-gui.sh:1949 git-gui.sh:2446 git-gui.sh:2520 git-gui.sh:2614
+#: git-gui.sh:2041 git-gui.sh:2548 git-gui.sh:2622 git-gui.sh:2715
 #: lib/console.tcl:69
 msgid "Copy"
 msgstr "Copier"
 
-#: git-gui.sh:1952 git-gui.sh:2449
+#: git-gui.sh:2044 git-gui.sh:2551
 msgid "Paste"
 msgstr "Coller"
 
-#: git-gui.sh:1955 git-gui.sh:2452 lib/branch_delete.tcl:26
+#: git-gui.sh:2047 git-gui.sh:2554 lib/branch_delete.tcl:26
 #: lib/remote_branch_delete.tcl:38
 msgid "Delete"
 msgstr "Supprimer"
 
-#: git-gui.sh:1959 git-gui.sh:2456 git-gui.sh:2618 lib/console.tcl:71
+#: git-gui.sh:2051 git-gui.sh:2558 git-gui.sh:2719 lib/console.tcl:71
 msgid "Select All"
 msgstr "Tout sélectionner"
 
-#: git-gui.sh:1968
+#: git-gui.sh:2060
 msgid "Create..."
 msgstr "Créer..."
 
-#: git-gui.sh:1974
+#: git-gui.sh:2066
 msgid "Checkout..."
-msgstr "Emprunter... "
+msgstr "Charger (checkout)..."
 
-#: git-gui.sh:1980
+#: git-gui.sh:2072
 msgid "Rename..."
 msgstr "Renommer..."
 
-#: git-gui.sh:1985 git-gui.sh:2085
+#: git-gui.sh:2077 git-gui.sh:2187
 msgid "Delete..."
 msgstr "Supprimer..."
 
-#: git-gui.sh:1990
+#: git-gui.sh:2082
 msgid "Reset..."
 msgstr "Réinitialiser..."
 
-#: git-gui.sh:2002 git-gui.sh:2389
+#: git-gui.sh:2094 git-gui.sh:2491
 msgid "New Commit"
 msgstr "Nouveau commit"
 
-#: git-gui.sh:2010 git-gui.sh:2396
+#: git-gui.sh:2102 git-gui.sh:2498
 msgid "Amend Last Commit"
 msgstr "Corriger dernier commit"
 
-#: git-gui.sh:2019 git-gui.sh:2356 lib/remote_branch_delete.tcl:99
+#: git-gui.sh:2111 git-gui.sh:2458 lib/remote_branch_delete.tcl:99
 msgid "Rescan"
-msgstr "Resynchroniser"
+msgstr "Recharger modifs."
 
-#: git-gui.sh:2025
+#: git-gui.sh:2117
 msgid "Stage To Commit"
-msgstr "Commiter un pré-commit"
+msgstr "Indexer"
 
-#: git-gui.sh:2031
+#: git-gui.sh:2123
 msgid "Stage Changed Files To Commit"
-msgstr "Commiter fichiers modifiés dans pré-commit"
+msgstr "Indexer toutes modifications"
 
-#: git-gui.sh:2037
+#: git-gui.sh:2129
 msgid "Unstage From Commit"
-msgstr "Commit vers pré-commit"
+msgstr "Désindexer"
 
-#: git-gui.sh:2042 lib/index.tcl:395
+#: git-gui.sh:2134 lib/index.tcl:395
 msgid "Revert Changes"
-msgstr "Inverser modification"
+msgstr "Annuler les modifications (revert)"
 
-#: git-gui.sh:2049 git-gui.sh:2368 git-gui.sh:2467
-msgid "Sign Off"
-msgstr "Se désinscrire"
-
-#: git-gui.sh:2053 git-gui.sh:2372
-msgid "Commit@@verb"
-msgstr "Commiter"
-
-#: git-gui.sh:2064
-msgid "Local Merge..."
-msgstr "Fusion locale..."
-
-#: git-gui.sh:2069
-msgid "Abort Merge..."
-msgstr "Abandonner fusion..."
-
-#: git-gui.sh:2081
-msgid "Push..."
-msgstr "Pousser..."
-
-#: git-gui.sh:2092 lib/choose_repository.tcl:41
-msgid "Apple"
-msgstr "Pomme"
-
-#: git-gui.sh:2095 git-gui.sh:2117 lib/about.tcl:14
-#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50
-#, tcl-format
-msgid "About %s"
-msgstr "A propos de %s"
-
-#: git-gui.sh:2099
-msgid "Preferences..."
-msgstr "Préférences..."
-
-#: git-gui.sh:2107 git-gui.sh:2639
-msgid "Options..."
-msgstr "Options..."
-
-#: git-gui.sh:2113 lib/choose_repository.tcl:47
-msgid "Help"
-msgstr "Aide"
-
-#: git-gui.sh:2154
-msgid "Online Documentation"
-msgstr "Documentation en ligne"
-
-#: git-gui.sh:2238
-#, tcl-format
-msgid "fatal: cannot stat path %s: No such file or directory"
-msgstr "erreur fatale : pas d'infos sur le chemin %s : Fichier ou répertoire inexistant"
-
-#: git-gui.sh:2271
-msgid "Current Branch:"
-msgstr "Branche courante :"
-
-#: git-gui.sh:2292
-msgid "Staged Changes (Will Commit)"
-msgstr "Modifications pré-commitées"
-
-#: git-gui.sh:2312
-msgid "Unstaged Changes"
-msgstr "Modifications non pré-commitées"
-
-#: git-gui.sh:2362
-msgid "Stage Changed"
-msgstr "Pré-commit modifié"
-
-#: git-gui.sh:2378 lib/transport.tcl:93 lib/transport.tcl:182
-msgid "Push"
-msgstr "Pousser"
-
-#: git-gui.sh:2408
-msgid "Initial Commit Message:"
-msgstr "Message de commit initial :"
-
-#: git-gui.sh:2409
-msgid "Amended Commit Message:"
-msgstr "Message de commit corrigé :"
-
-#: git-gui.sh:2410
-msgid "Amended Initial Commit Message:"
-msgstr "Message de commit initial corrigé :"
-
-#: git-gui.sh:2411
-msgid "Amended Merge Commit Message:"
-msgstr "Message de commit de fusion corrigé :"
-
-#: git-gui.sh:2412
-msgid "Merge Commit Message:"
-msgstr "Message de commit de fusion :"
-
-#: git-gui.sh:2413
-msgid "Commit Message:"
-msgstr "Message de commit :"
-
-#: git-gui.sh:2459 git-gui.sh:2622 lib/console.tcl:73
-msgid "Copy All"
-msgstr "Copier tout"
-
-#: git-gui.sh:2483 lib/blame.tcl:107
-msgid "File:"
-msgstr "Fichier :"
-
-#: git-gui.sh:2589
-msgid "Apply/Reverse Hunk"
-msgstr "Appliquer/Inverser section"
-
-#: git-gui.sh:2595
+#: git-gui.sh:2141 git-gui.sh:2702
 msgid "Show Less Context"
 msgstr "Montrer moins de contexte"
 
-#: git-gui.sh:2602
+#: git-gui.sh:2145 git-gui.sh:2706
 msgid "Show More Context"
 msgstr "Montrer plus de contexte"
 
-#: git-gui.sh:2610
+#: git-gui.sh:2151 git-gui.sh:2470 git-gui.sh:2569
+msgid "Sign Off"
+msgstr "Signer"
+
+#: git-gui.sh:2155 git-gui.sh:2474
+msgid "Commit@@verb"
+msgstr "Commiter"
+
+#: git-gui.sh:2166
+msgid "Local Merge..."
+msgstr "Fusion locale..."
+
+#: git-gui.sh:2171
+msgid "Abort Merge..."
+msgstr "Abandonner fusion..."
+
+#: git-gui.sh:2183
+msgid "Push..."
+msgstr "Pousser..."
+
+#: git-gui.sh:2197 git-gui.sh:2219 lib/about.tcl:14
+#: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50
+#, tcl-format
+msgid "About %s"
+msgstr "À propos de %s"
+
+#: git-gui.sh:2201
+msgid "Preferences..."
+msgstr "Préférences..."
+
+#: git-gui.sh:2209 git-gui.sh:2740
+msgid "Options..."
+msgstr "Options..."
+
+#: git-gui.sh:2215 lib/choose_repository.tcl:47
+msgid "Help"
+msgstr "Aide"
+
+#: git-gui.sh:2256
+msgid "Online Documentation"
+msgstr "Documentation en ligne"
+
+#: git-gui.sh:2340
+#, tcl-format
+msgid "fatal: cannot stat path %s: No such file or directory"
+msgstr ""
+"erreur fatale : pas d'infos sur le chemin %s : Fichier ou répertoire "
+"inexistant"
+
+#: git-gui.sh:2373
+msgid "Current Branch:"
+msgstr "Branche courante :"
+
+#: git-gui.sh:2394
+msgid "Staged Changes (Will Commit)"
+msgstr "Modifs. indexées (pour commit)"
+
+#: git-gui.sh:2414
+msgid "Unstaged Changes"
+msgstr "Modifs. non indexées"
+
+#: git-gui.sh:2464
+msgid "Stage Changed"
+msgstr "Indexer modifs."
+
+#: git-gui.sh:2480 lib/transport.tcl:93 lib/transport.tcl:182
+msgid "Push"
+msgstr "Pousser"
+
+#: git-gui.sh:2510
+msgid "Initial Commit Message:"
+msgstr "Message de commit initial :"
+
+#: git-gui.sh:2511
+msgid "Amended Commit Message:"
+msgstr "Message de commit corrigé :"
+
+#: git-gui.sh:2512
+msgid "Amended Initial Commit Message:"
+msgstr "Message de commit initial corrigé :"
+
+#: git-gui.sh:2513
+msgid "Amended Merge Commit Message:"
+msgstr "Message de commit de fusion corrigé :"
+
+#: git-gui.sh:2514
+msgid "Merge Commit Message:"
+msgstr "Message de commit de fusion :"
+
+#: git-gui.sh:2515
+msgid "Commit Message:"
+msgstr "Message de commit :"
+
+#: git-gui.sh:2561 git-gui.sh:2723 lib/console.tcl:73
+msgid "Copy All"
+msgstr "Copier tout"
+
+#: git-gui.sh:2585 lib/blame.tcl:100
+msgid "File:"
+msgstr "Fichier :"
+
+#: git-gui.sh:2691
+msgid "Apply/Reverse Hunk"
+msgstr "Appliquer/Inverser section"
+
+#: git-gui.sh:2696
+msgid "Apply/Reverse Line"
+msgstr "Appliquer/Inverser la ligne"
+
+#: git-gui.sh:2711
 msgid "Refresh"
 msgstr "Rafraichir"
 
-#: git-gui.sh:2631
+#: git-gui.sh:2732
 msgid "Decrease Font Size"
-msgstr "Réduire fonte"
+msgstr "Diminuer la police"
 
-#: git-gui.sh:2635
+#: git-gui.sh:2736
 msgid "Increase Font Size"
-msgstr "Agrandir fonte"
+msgstr "Agrandir la police"
 
-#: git-gui.sh:2646
+#: git-gui.sh:2747
 msgid "Unstage Hunk From Commit"
-msgstr "Enlever section pré-commitée"
+msgstr "Désindexer la section"
 
-#: git-gui.sh:2648
+#: git-gui.sh:2748
+msgid "Unstage Line From Commit"
+msgstr "Désindexer la ligne"
+
+#: git-gui.sh:2750
 msgid "Stage Hunk For Commit"
-msgstr "Pré-commiter section"
+msgstr "Indexer la section"
 
-#: git-gui.sh:2667
+#: git-gui.sh:2751
+msgid "Stage Line For Commit"
+msgstr "Indexer la ligne"
+
+#: git-gui.sh:2771
 msgid "Initializing..."
 msgstr "Initialisation..."
 
-#: git-gui.sh:2762
+#: git-gui.sh:2876
 #, tcl-format
 msgid ""
 "Possible environment issues exist.\n"
@@ -451,7 +455,7 @@
 "sous-processus de Git lancés par %s\n"
 "\n"
 
-#: git-gui.sh:2792
+#: git-gui.sh:2906
 msgid ""
 "\n"
 "This is due to a known issue with the\n"
@@ -461,7 +465,7 @@
 "Ceci est du à un problème connu avec\n"
 "le binaire Tcl distribué par Cygwin."
 
-#: git-gui.sh:2797
+#: git-gui.sh:2911
 #, tcl-format
 msgid ""
 "\n"
@@ -482,78 +486,94 @@
 msgid "git-gui - a graphical user interface for Git."
 msgstr "git-gui - une interface graphique utilisateur pour Git"
 
-#: lib/blame.tcl:77
+#: lib/blame.tcl:70
 msgid "File Viewer"
 msgstr "Visionneur de fichier"
 
-#: lib/blame.tcl:81
+#: lib/blame.tcl:74
 msgid "Commit:"
 msgstr "Commit :"
 
-#: lib/blame.tcl:264
+#: lib/blame.tcl:257
 msgid "Copy Commit"
 msgstr "Copier commit"
 
-#: lib/blame.tcl:384
+#: lib/blame.tcl:260
+msgid "Do Full Copy Detection"
+msgstr "Lancer la détection approfondie des copies"
+
+#: lib/blame.tcl:388
 #, tcl-format
 msgid "Reading %s..."
 msgstr "Lecture de %s..."
 
-#: lib/blame.tcl:488
+#: lib/blame.tcl:492
 msgid "Loading copy/move tracking annotations..."
 msgstr "Chargement des annotations de suivi des copies/déplacements..."
 
-#: lib/blame.tcl:508
+#: lib/blame.tcl:512
 msgid "lines annotated"
 msgstr "lignes annotées"
 
-#: lib/blame.tcl:689
+#: lib/blame.tcl:704
 msgid "Loading original location annotations..."
 msgstr "Chargement des annotations d'emplacement original"
 
-#: lib/blame.tcl:692
+#: lib/blame.tcl:707
 msgid "Annotation complete."
 msgstr "Annotation terminée."
 
-#: lib/blame.tcl:746
+#: lib/blame.tcl:737
+msgid "Busy"
+msgstr "Occupé"
+
+#: lib/blame.tcl:738
+msgid "Annotation process is already running."
+msgstr "Annotation en cours d'exécution."
+
+#: lib/blame.tcl:777
+msgid "Running thorough copy detection..."
+msgstr "Recherche de copie approfondie en cours..."
+
+#: lib/blame.tcl:827
 msgid "Loading annotation..."
 msgstr "Chargement des annotations..."
 
-#: lib/blame.tcl:802
+#: lib/blame.tcl:883
 msgid "Author:"
 msgstr "Auteur :"
 
-#: lib/blame.tcl:806
+#: lib/blame.tcl:887
 msgid "Committer:"
 msgstr "Commiteur :"
 
-#: lib/blame.tcl:811
+#: lib/blame.tcl:892
 msgid "Original File:"
 msgstr "Fichier original :"
 
-#: lib/blame.tcl:925
+#: lib/blame.tcl:1006
 msgid "Originally By:"
 msgstr "A l'origine par :"
 
-#: lib/blame.tcl:931
+#: lib/blame.tcl:1012
 msgid "In File:"
 msgstr "Dans le fichier :"
 
-#: lib/blame.tcl:936
+#: lib/blame.tcl:1017
 msgid "Copied Or Moved Here By:"
 msgstr "Copié ou déplacé ici par :"
 
 #: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19
 msgid "Checkout Branch"
-msgstr "Emprunter branche"
+msgstr "Charger la branche (checkout)"
 
 #: lib/branch_checkout.tcl:23
 msgid "Checkout"
-msgstr "Emprunter"
+msgstr "Charger (checkout)"
 
 #: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35
 #: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:282
-#: lib/checkout_op.tcl:522 lib/choose_font.tcl:43 lib/merge.tcl:171
+#: lib/checkout_op.tcl:544 lib/choose_font.tcl:43 lib/merge.tcl:171
 #: lib/option.tcl:103 lib/remote_branch_delete.tcl:42 lib/transport.tcl:97
 msgid "Cancel"
 msgstr "Annuler"
@@ -562,17 +582,17 @@
 msgid "Revision"
 msgstr "Révision"
 
-#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:242
+#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:244
 msgid "Options"
 msgstr "Options"
 
 #: lib/branch_checkout.tcl:39 lib/branch_create.tcl:92
 msgid "Fetch Tracking Branch"
-msgstr "Branche suivant récupération"
+msgstr "Récupérer la branche de suivi"
 
 #: lib/branch_checkout.tcl:44
 msgid "Detach From Local Branch"
-msgstr "Détacher de branche locale"
+msgstr "Détacher de la branche locale"
 
 #: lib/branch_create.tcl:22
 msgid "Create Branch"
@@ -600,7 +620,7 @@
 
 #: lib/branch_create.tcl:66
 msgid "Starting Revision"
-msgstr "Début de révision"
+msgstr "Révision initiale"
 
 #: lib/branch_create.tcl:72
 msgid "Update Existing Branch:"
@@ -612,28 +632,28 @@
 
 #: lib/branch_create.tcl:80
 msgid "Fast Forward Only"
-msgstr "Avance rapide seulement"
+msgstr "Mise-à-jour rectiligne seulement (fast-forward)"
 
-#: lib/branch_create.tcl:85 lib/checkout_op.tcl:514
+#: lib/branch_create.tcl:85 lib/checkout_op.tcl:536
 msgid "Reset"
 msgstr "Réinitialiser"
 
 #: lib/branch_create.tcl:97
 msgid "Checkout After Creation"
-msgstr "Emprunt après création"
+msgstr "Charger (checkout) après création"
 
 #: lib/branch_create.tcl:131
 msgid "Please select a tracking branch."
-msgstr "Merci de choisir une branche de suivi"
+msgstr "Choisissez une branche de suivi"
 
 #: lib/branch_create.tcl:140
 #, tcl-format
 msgid "Tracking branch %s is not a branch in the remote repository."
-msgstr "La branche de suivi %s n'est pas une branche dans le référentiel distant."
+msgstr "La branche de suivi %s n'est pas une branche dans le dépôt distant."
 
 #: lib/branch_create.tcl:153 lib/branch_rename.tcl:86
 msgid "Please supply a branch name."
-msgstr "Merci de fournir un nom de branche."
+msgstr "Fournissez un nom de branche."
 
 #: lib/branch_create.tcl:164 lib/branch_rename.tcl:106
 #, tcl-format
@@ -654,7 +674,7 @@
 
 #: lib/branch_delete.tcl:52
 msgid "Delete Only If Merged Into"
-msgstr "Supprimer ssi fusion dedans"
+msgstr "Supprimer seulement si fusionnée dans:"
 
 #: lib/branch_delete.tcl:54
 msgid "Always (Do not perform merge test.)"
@@ -704,7 +724,7 @@
 msgid "Please select a branch to rename."
 msgstr "Merci de sélectionner une branche à renommer."
 
-#: lib/branch_rename.tcl:96 lib/checkout_op.tcl:179
+#: lib/branch_rename.tcl:96 lib/checkout_op.tcl:201
 #, tcl-format
 msgid "Branch '%s' already exists."
 msgstr "La branche '%s' existe déjà."
@@ -712,7 +732,7 @@
 #: lib/branch_rename.tcl:117
 #, tcl-format
 msgid "Failed to rename '%s'."
-msgstr "Le renommage de '%s' a échoué."
+msgstr "Échec pour renommer '%s'."
 
 #: lib/browser.tcl:17
 msgid "Starting..."
@@ -733,34 +753,39 @@
 
 #: lib/browser.tcl:267 lib/browser.tcl:273
 msgid "Browse Branch Files"
-msgstr "Visionner fichiers de branches"
+msgstr "Naviguer dans les fichiers de le branche"
 
 #: lib/browser.tcl:278 lib/choose_repository.tcl:387
-#: lib/choose_repository.tcl:474 lib/choose_repository.tcl:484
-#: lib/choose_repository.tcl:987
+#: lib/choose_repository.tcl:472 lib/choose_repository.tcl:482
+#: lib/choose_repository.tcl:985
 msgid "Browse"
-msgstr "Visionner"
+msgstr "Naviguer"
 
-#: lib/checkout_op.tcl:79
+#: lib/checkout_op.tcl:84
 #, tcl-format
 msgid "Fetching %s from %s"
 msgstr "Récupération de %s à partir de %s"
 
-#: lib/checkout_op.tcl:127
+#: lib/checkout_op.tcl:132
 #, tcl-format
 msgid "fatal: Cannot resolve %s"
 msgstr "erreur fatale : Impossible de résoudre %s"
 
-#: lib/checkout_op.tcl:140 lib/console.tcl:81 lib/database.tcl:31
+#: lib/checkout_op.tcl:145 lib/console.tcl:81 lib/database.tcl:31
 msgid "Close"
 msgstr "Fermer"
 
-#: lib/checkout_op.tcl:169
+#: lib/checkout_op.tcl:174
 #, tcl-format
 msgid "Branch '%s' does not exist."
 msgstr "La branche '%s' n'existe pas."
 
-#: lib/checkout_op.tcl:206
+#: lib/checkout_op.tcl:193
+#, tcl-format
+msgid "Failed to configure simplified git-pull for '%s'."
+msgstr "Échec de la configuration simplifiée de git-pull pour '%s'."
+
+#: lib/checkout_op.tcl:228
 #, tcl-format
 msgid ""
 "Branch '%s' already exists.\n"
@@ -770,24 +795,24 @@
 msgstr ""
 "La branche '%s' existe déjà.\n"
 "\n"
-"Impossible d'avancer rapidement à %s.\n"
+"Impossible de faire une avance rapide (fast forward) vers %s.\n"
 "Une fusion est nécessaire."
 
-#: lib/checkout_op.tcl:220
+#: lib/checkout_op.tcl:242
 #, tcl-format
 msgid "Merge strategy '%s' not supported."
 msgstr "La stratégie de fusion '%s' n'est pas supportée."
 
-#: lib/checkout_op.tcl:239
+#: lib/checkout_op.tcl:261
 #, tcl-format
 msgid "Failed to update '%s'."
 msgstr "La mise à jour de '%s' a échouée."
 
-#: lib/checkout_op.tcl:251
+#: lib/checkout_op.tcl:273
 msgid "Staging area (index) is already locked."
-msgstr "L'espace de pré-commit ('index' ou 'staging') est déjà vérouillé."
+msgstr "L'index (staging area) est déjà vérouillé"
 
-#: lib/checkout_op.tcl:266
+#: lib/checkout_op.tcl:288
 msgid ""
 "Last scanned state does not match repository state.\n"
 "\n"
@@ -796,36 +821,39 @@
 "\n"
 "The rescan will be automatically started now.\n"
 msgstr ""
-"L'état lors de la dernière synchronisation ne correspond plus à l'état du référentiel.\n"
+"L'état lors de la dernière synchronisation ne correspond plus à l'état du "
+"dépôt\n"
 "\n"
-"Un autre programme Git a modifié ce référentiel depuis la dernière synchronisation. Une resynchronisation doit être effectuée avant de pouvoir modifier la branche courante.\n"
+"Un autre programme Git a modifié ce dépôt depuis la dernière "
+"synchronisation. Une resynchronisation doit être effectuée avant de pouvoir "
+"modifier la branche courante.\n"
 "\n"
 "Cela va être fait tout de suite automatiquement.\n"
 
-#: lib/checkout_op.tcl:322
+#: lib/checkout_op.tcl:344
 #, tcl-format
 msgid "Updating working directory to '%s'..."
 msgstr "Mise à jour du répertoire courant avec '%s'..."
 
-#: lib/checkout_op.tcl:323
+#: lib/checkout_op.tcl:345
 msgid "files checked out"
-msgstr "fichiers empruntés"
+msgstr "fichiers chargés"
 
-#: lib/checkout_op.tcl:353
+#: lib/checkout_op.tcl:375
 #, tcl-format
 msgid "Aborted checkout of '%s' (file level merging is required)."
-msgstr "Emprunt de '%s' abandonné. (Il est nécessaire de fusionner des fichiers.)"
+msgstr "Chargement de '%s' abandonné (il est nécessaire de fusionner des fichiers)."
 
-#: lib/checkout_op.tcl:354
+#: lib/checkout_op.tcl:376
 msgid "File level merge required."
 msgstr "Il est nécessaire de fusionner des fichiers."
 
-#: lib/checkout_op.tcl:358
+#: lib/checkout_op.tcl:380
 #, tcl-format
 msgid "Staying on branch '%s'."
 msgstr "Le répertoire de travail reste sur la branche '%s'."
 
-#: lib/checkout_op.tcl:429
+#: lib/checkout_op.tcl:451
 msgid ""
 "You are no longer on a local branch.\n"
 "\n"
@@ -837,30 +865,30 @@
 "Si vous vouliez être sur une branche, créez en une maintenant en partant de "
 "'Cet emprunt détaché'."
 
-#: lib/checkout_op.tcl:446 lib/checkout_op.tcl:450
+#: lib/checkout_op.tcl:468 lib/checkout_op.tcl:472
 #, tcl-format
 msgid "Checked out '%s'."
-msgstr "'%s' emprunté."
+msgstr "'%s' chargé."
 
-#: lib/checkout_op.tcl:478
+#: lib/checkout_op.tcl:500
 #, tcl-format
 msgid "Resetting '%s' to '%s' will lose the following commits:"
 msgstr "Réinitialiser '%s' à '%s' va faire perdre les commits suivants :"
 
-#: lib/checkout_op.tcl:500
+#: lib/checkout_op.tcl:522
 msgid "Recovering lost commits may not be easy."
 msgstr "Récupérer les commits perdus ne sera peut être pas facile."
 
-#: lib/checkout_op.tcl:505
+#: lib/checkout_op.tcl:527
 #, tcl-format
 msgid "Reset '%s'?"
 msgstr "Réinitialiser '%s' ?"
 
-#: lib/checkout_op.tcl:510 lib/merge.tcl:163
+#: lib/checkout_op.tcl:532 lib/merge.tcl:163
 msgid "Visualize"
 msgstr "Visualiser"
 
-#: lib/checkout_op.tcl:578
+#: lib/checkout_op.tcl:600
 #, tcl-format
 msgid ""
 "Failed to set current branch.\n"
@@ -884,15 +912,15 @@
 
 #: lib/choose_font.tcl:53
 msgid "Font Family"
-msgstr "Famille de fonte"
+msgstr "Familles de polices"
 
 #: lib/choose_font.tcl:74
 msgid "Font Size"
-msgstr "Taille de fonte"
+msgstr "Taille de police"
 
 #: lib/choose_font.tcl:91
 msgid "Font Example"
-msgstr "Exemple de fonte"
+msgstr "Exemple de police"
 
 #: lib/choose_font.tcl:103
 msgid ""
@@ -900,7 +928,7 @@
 "If you like this text, it can be your font."
 msgstr ""
 "C'est un texte d'exemple.\n"
-"Si vous aimez ce texte, vous pouvez choisir cette fonte."
+"Si vous aimez ce texte, vous pouvez choisir cette police"
 
 #: lib/choose_repository.tcl:28
 msgid "Git Gui"
@@ -908,23 +936,23 @@
 
 #: lib/choose_repository.tcl:81 lib/choose_repository.tcl:376
 msgid "Create New Repository"
-msgstr "Créer nouveau référentiel"
+msgstr "Créer nouveau dépôt"
 
 #: lib/choose_repository.tcl:87
 msgid "New..."
 msgstr "Nouveau..."
 
-#: lib/choose_repository.tcl:94 lib/choose_repository.tcl:460
+#: lib/choose_repository.tcl:94 lib/choose_repository.tcl:458
 msgid "Clone Existing Repository"
-msgstr "Cloner référentiel existant"
+msgstr "Cloner dépôt existant"
 
 #: lib/choose_repository.tcl:100
 msgid "Clone..."
 msgstr "Cloner..."
 
-#: lib/choose_repository.tcl:107 lib/choose_repository.tcl:976
+#: lib/choose_repository.tcl:107 lib/choose_repository.tcl:974
 msgid "Open Existing Repository"
-msgstr "Ouvrir référentiel existant"
+msgstr "Ouvrir dépôt existant"
 
 #: lib/choose_repository.tcl:113
 msgid "Open..."
@@ -932,202 +960,202 @@
 
 #: lib/choose_repository.tcl:126
 msgid "Recent Repositories"
-msgstr "Référentiels récents"
+msgstr "Dépôt récemment utilisés"
 
 #: lib/choose_repository.tcl:132
 msgid "Open Recent Repository:"
-msgstr "Ouvrir référentiel récent :"
+msgstr "Ouvrir dépôt récent :"
 
 #: lib/choose_repository.tcl:296 lib/choose_repository.tcl:303
 #: lib/choose_repository.tcl:310
 #, tcl-format
 msgid "Failed to create repository %s:"
-msgstr "La création du référentiel %s a échouée :"
+msgstr "La création du dépôt %s a échouée :"
 
-#: lib/choose_repository.tcl:381 lib/choose_repository.tcl:478
+#: lib/choose_repository.tcl:381 lib/choose_repository.tcl:476
 msgid "Directory:"
 msgstr "Répertoire :"
 
-#: lib/choose_repository.tcl:412 lib/choose_repository.tcl:537
-#: lib/choose_repository.tcl:1011
+#: lib/choose_repository.tcl:410 lib/choose_repository.tcl:535
+#: lib/choose_repository.tcl:1007
 msgid "Git Repository"
-msgstr "Référentiel Git"
+msgstr "Dépôt Git"
 
-#: lib/choose_repository.tcl:437
+#: lib/choose_repository.tcl:435
 #, tcl-format
 msgid "Directory %s already exists."
 msgstr "Le répertoire %s existe déjà."
 
-#: lib/choose_repository.tcl:441
+#: lib/choose_repository.tcl:439
 #, tcl-format
 msgid "File %s already exists."
 msgstr "Le fichier %s existe déjà."
 
-#: lib/choose_repository.tcl:455
+#: lib/choose_repository.tcl:453
 msgid "Clone"
 msgstr "Cloner"
 
-#: lib/choose_repository.tcl:468
+#: lib/choose_repository.tcl:466
 msgid "URL:"
 msgstr "URL :"
 
-#: lib/choose_repository.tcl:489
+#: lib/choose_repository.tcl:487
 msgid "Clone Type:"
 msgstr "Type de clonage :"
 
-#: lib/choose_repository.tcl:495
+#: lib/choose_repository.tcl:493
 msgid "Standard (Fast, Semi-Redundant, Hardlinks)"
 msgstr "Standard (rapide, semi-redondant, liens durs)"
 
-#: lib/choose_repository.tcl:501
+#: lib/choose_repository.tcl:499
 msgid "Full Copy (Slower, Redundant Backup)"
 msgstr "Copy complète (plus lent, sauvegarde redondante)"
 
-#: lib/choose_repository.tcl:507
+#: lib/choose_repository.tcl:505
 msgid "Shared (Fastest, Not Recommended, No Backup)"
 msgstr "Partagé (le plus rapide, non recommandé, pas de sauvegarde)"
 
-#: lib/choose_repository.tcl:543 lib/choose_repository.tcl:590
-#: lib/choose_repository.tcl:736 lib/choose_repository.tcl:806
-#: lib/choose_repository.tcl:1017 lib/choose_repository.tcl:1025
+#: lib/choose_repository.tcl:541 lib/choose_repository.tcl:588
+#: lib/choose_repository.tcl:734 lib/choose_repository.tcl:804
+#: lib/choose_repository.tcl:1013 lib/choose_repository.tcl:1021
 #, tcl-format
 msgid "Not a Git repository: %s"
-msgstr "'%s' n'est pas un référentiel Git."
+msgstr "'%s' n'est pas un dépôt Git."
 
-#: lib/choose_repository.tcl:579
+#: lib/choose_repository.tcl:577
 msgid "Standard only available for local repository."
-msgstr "Standard n'est disponible que pour un référentiel local."
+msgstr "Standard n'est disponible que pour un dépôt local."
 
-#: lib/choose_repository.tcl:583
+#: lib/choose_repository.tcl:581
 msgid "Shared only available for local repository."
-msgstr "Partagé n'est disponible que pour un référentiel local."
+msgstr "Partagé n'est disponible que pour un dépôt local."
 
-#: lib/choose_repository.tcl:604
+#: lib/choose_repository.tcl:602
 #, tcl-format
 msgid "Location %s already exists."
 msgstr "L'emplacement %s existe déjà."
 
-#: lib/choose_repository.tcl:615
+#: lib/choose_repository.tcl:613
 msgid "Failed to configure origin"
 msgstr "La configuration de l'origine a échouée."
 
-#: lib/choose_repository.tcl:627
+#: lib/choose_repository.tcl:625
 msgid "Counting objects"
-msgstr "Comptage des objets"
+msgstr "Décompte des objets"
 
-#: lib/choose_repository.tcl:628
+#: lib/choose_repository.tcl:626
 msgid "buckets"
 msgstr "paniers"
 
-#: lib/choose_repository.tcl:652
+#: lib/choose_repository.tcl:650
 #, tcl-format
 msgid "Unable to copy objects/info/alternates: %s"
 msgstr "Impossible de copier 'objects/info/alternates' : %s"
 
-#: lib/choose_repository.tcl:688
+#: lib/choose_repository.tcl:686
 #, tcl-format
 msgid "Nothing to clone from %s."
 msgstr "Il n'y a rien à cloner depuis %s."
 
-#: lib/choose_repository.tcl:690 lib/choose_repository.tcl:904
-#: lib/choose_repository.tcl:916
+#: lib/choose_repository.tcl:688 lib/choose_repository.tcl:902
+#: lib/choose_repository.tcl:914
 msgid "The 'master' branch has not been initialized."
-msgstr "Cette branche 'master' n'a pas été initialisée."
+msgstr "La branche 'master' n'a pas été initialisée."
 
-#: lib/choose_repository.tcl:703
+#: lib/choose_repository.tcl:701
 msgid "Hardlinks are unavailable.  Falling back to copying."
-msgstr "Les liens durs ne sont pas disponibles. On se résoud à copier."
+msgstr "Les liens durs ne sont pas supportés. Une copie sera effectuée à la place."
 
-#: lib/choose_repository.tcl:715
+#: lib/choose_repository.tcl:713
 #, tcl-format
 msgid "Cloning from %s"
 msgstr "Clonage depuis %s"
 
-#: lib/choose_repository.tcl:746
+#: lib/choose_repository.tcl:744
 msgid "Copying objects"
 msgstr "Copie des objets"
 
-#: lib/choose_repository.tcl:747
+#: lib/choose_repository.tcl:745
 msgid "KiB"
 msgstr "KiB"
 
-#: lib/choose_repository.tcl:771
+#: lib/choose_repository.tcl:769
 #, tcl-format
 msgid "Unable to copy object: %s"
 msgstr "Impossible de copier l'objet : %s"
 
-#: lib/choose_repository.tcl:781
+#: lib/choose_repository.tcl:779
 msgid "Linking objects"
 msgstr "Liaison des objets"
 
-#: lib/choose_repository.tcl:782
+#: lib/choose_repository.tcl:780
 msgid "objects"
 msgstr "objets"
 
-#: lib/choose_repository.tcl:790
+#: lib/choose_repository.tcl:788
 #, tcl-format
 msgid "Unable to hardlink object: %s"
 msgstr "Impossible créer un lien dur pour l'objet : %s"
 
-#: lib/choose_repository.tcl:845
+#: lib/choose_repository.tcl:843
 msgid "Cannot fetch branches and objects.  See console output for details."
 msgstr ""
 "Impossible de récupérer les branches et objets. Voir la sortie console pour "
 "plus de détails."
 
-#: lib/choose_repository.tcl:856
+#: lib/choose_repository.tcl:854
 msgid "Cannot fetch tags.  See console output for details."
 msgstr ""
-"Impossible de récupérer les marques. Voir la sortie console pour plus de "
-"détails."
+"Impossible de récupérer les marques (tags). Voir la sortie console pour plus "
+"de détails."
 
-#: lib/choose_repository.tcl:880
+#: lib/choose_repository.tcl:878
 msgid "Cannot determine HEAD.  See console output for details."
 msgstr "Impossible de déterminer HEAD. Voir la sortie console pour plus de détails."
 
-#: lib/choose_repository.tcl:889
+#: lib/choose_repository.tcl:887
 #, tcl-format
 msgid "Unable to cleanup %s"
 msgstr "Impossible de nettoyer %s"
 
-#: lib/choose_repository.tcl:895
+#: lib/choose_repository.tcl:893
 msgid "Clone failed."
 msgstr "Le clonage a échoué."
 
-#: lib/choose_repository.tcl:902
+#: lib/choose_repository.tcl:900
 msgid "No default branch obtained."
 msgstr "Aucune branche par défaut n'a été obtenue."
 
-#: lib/choose_repository.tcl:913
+#: lib/choose_repository.tcl:911
 #, tcl-format
 msgid "Cannot resolve %s as a commit."
 msgstr "Impossible de résoudre %s comme commit."
 
-#: lib/choose_repository.tcl:925
+#: lib/choose_repository.tcl:923
 msgid "Creating working directory"
 msgstr "Création du répertoire de travail"
 
-#: lib/choose_repository.tcl:926 lib/index.tcl:65 lib/index.tcl:127
+#: lib/choose_repository.tcl:924 lib/index.tcl:65 lib/index.tcl:127
 #: lib/index.tcl:193
 msgid "files"
 msgstr "fichiers"
 
-#: lib/choose_repository.tcl:955
+#: lib/choose_repository.tcl:953
 msgid "Initial file checkout failed."
-msgstr "L'emprunt initial de fichier a échoué."
+msgstr "Chargement initial du fichier échoué."
 
-#: lib/choose_repository.tcl:971
+#: lib/choose_repository.tcl:969
 msgid "Open"
 msgstr "Ouvrir"
 
-#: lib/choose_repository.tcl:981
+#: lib/choose_repository.tcl:979
 msgid "Repository:"
-msgstr "Référentiel :"
+msgstr "Dépôt :"
 
-#: lib/choose_repository.tcl:1031
+#: lib/choose_repository.tcl:1027
 #, tcl-format
 msgid "Failed to open repository %s:"
-msgstr "Impossible d'ouvrir le référentiel %s :"
+msgstr "Impossible d'ouvrir le dépôt %s :"
 
 #: lib/choose_rev.tcl:53
 msgid "This Detached Checkout"
@@ -1143,11 +1171,11 @@
 
 #: lib/choose_rev.tcl:79
 msgid "Tracking Branch"
-msgstr "Suivi de branche"
+msgstr "Branche de suivi"
 
 #: lib/choose_rev.tcl:84 lib/choose_rev.tcl:538
 msgid "Tag"
-msgstr "Marque"
+msgstr "Marque (tag)"
 
 #: lib/choose_rev.tcl:317
 #, tcl-format
@@ -1164,7 +1192,7 @@
 
 #: lib/choose_rev.tcl:531
 msgid "Updated"
-msgstr "Misa à jour"
+msgstr "Mise-à-jour:"
 
 #: lib/choose_rev.tcl:559
 msgid "URL"
@@ -1218,9 +1246,9 @@
 "The rescan will be automatically started now.\n"
 msgstr ""
 "L'état lors de la dernière synchronisation ne correspond plus à l'état du "
-"référentiel.\n"
+"dépôt.\n"
 "\n"
-"Un autre programme Git a modifié ce référentiel depuis la dernière "
+"Un autre programme Git a modifié ce dépôt depuis la dernière "
 "synchronisation. Une resynshronisation doit être effectuée avant de pouvoir "
 "créer un nouveau commit.\n"
 "\n"
@@ -1258,7 +1286,7 @@
 msgstr ""
 "Pas de modification à commiter.\n"
 "\n"
-"Vous devez pré-commiter au moins 1 fichier avant de pouvoir commiter.\n"
+"Vous devez indexer au moins 1 fichier avant de pouvoir commiter.\n"
 
 #: lib/commit.tcl:183
 msgid ""
@@ -1285,19 +1313,19 @@
 
 #: lib/commit.tcl:221
 msgid "Calling pre-commit hook..."
-msgstr "Appel du programme externe d'avant commit..."
+msgstr "Lancement de l'action d'avant-commit..."
 
 #: lib/commit.tcl:236
 msgid "Commit declined by pre-commit hook."
-msgstr "Commit refusé par le programme externe d'avant commit."
+msgstr "Commit refusé par l'action d'avant-commit."
 
 #: lib/commit.tcl:259
 msgid "Calling commit-msg hook..."
-msgstr "Appel du programme externe de message de commit..."
+msgstr "Lancement de l'action \"message de commit\"..."
 
 #: lib/commit.tcl:274
 msgid "Commit declined by commit-msg hook."
-msgstr "Commit refusé par le programme externe de message de commit."
+msgstr "Commit refusé par l'action \"message de commit\"."
 
 #: lib/commit.tcl:287
 msgid "Committing changes..."
@@ -1406,7 +1434,7 @@
 "\n"
 "Compress the database now?"
 msgstr ""
-"Ce référentiel comprend actuellement environ %i objets ayant leur fichier "
+"Ce dépôt comprend actuellement environ %i objets ayant leur fichier "
 "particulier.\n"
 "\n"
 "Pour conserver une performance optimale, il est fortement recommandé de "
@@ -1420,7 +1448,7 @@
 msgid "Invalid date from Git: %s"
 msgstr "Date invalide de Git : %s"
 
-#: lib/diff.tcl:42
+#: lib/diff.tcl:44
 #, tcl-format
 msgid ""
 "No differences detected.\n"
@@ -1443,39 +1471,47 @@
 "Une resynchronisation va être lancée automatiquement pour trouver d'autres "
 "fichiers qui pourraient se trouver dans le même état."
 
-#: lib/diff.tcl:81
+#: lib/diff.tcl:83
 #, tcl-format
 msgid "Loading diff of %s..."
 msgstr "Chargement des différences de %s..."
 
-#: lib/diff.tcl:114 lib/diff.tcl:184
+#: lib/diff.tcl:116 lib/diff.tcl:190
 #, tcl-format
 msgid "Unable to display %s"
 msgstr "Impossible d'afficher %s"
 
-#: lib/diff.tcl:115
+#: lib/diff.tcl:117
 msgid "Error loading file:"
 msgstr "Erreur lors du chargement du fichier :"
 
-#: lib/diff.tcl:122
+#: lib/diff.tcl:124
 msgid "Git Repository (subproject)"
-msgstr "Référentiel Git (sous projet)"
+msgstr "Dépôt Git (sous projet)"
 
-#: lib/diff.tcl:134
+#: lib/diff.tcl:136
 msgid "* Binary file (not showing content)."
 msgstr "* Fichier binaire (pas d'apperçu du contenu)."
 
-#: lib/diff.tcl:185
+#: lib/diff.tcl:191
 msgid "Error loading diff:"
 msgstr "Erreur lors du chargement des différences :"
 
-#: lib/diff.tcl:303
+#: lib/diff.tcl:313
 msgid "Failed to unstage selected hunk."
-msgstr "La suppression dans le pré-commit de la section sélectionnée a échouée."
+msgstr "Échec lors de la désindexation de la section sélectionnée."
 
-#: lib/diff.tcl:310
+#: lib/diff.tcl:320
 msgid "Failed to stage selected hunk."
-msgstr "Le pré-commit de la section sélectionnée a échoué."
+msgstr "Échec lors de l'indexation de la section."
+
+#: lib/diff.tcl:386
+msgid "Failed to unstage selected line."
+msgstr "Échec lors de la désindexation de la ligne sélectionnée."
+
+#: lib/diff.tcl:394
+msgid "Failed to stage selected line."
+msgstr "Échec lors de l'indexation de la ligne."
 
 #: lib/error.tcl:20 lib/error.tcl:114
 msgid "error"
@@ -1491,17 +1527,19 @@
 
 #: lib/index.tcl:6
 msgid "Unable to unlock the index."
-msgstr "Impossible de dévérouiller le pré-commit."
+msgstr "Impossible de dévérouiller l'index."
 
 #: lib/index.tcl:15
 msgid "Index Error"
-msgstr "Erreur de pré-commit"
+msgstr "Erreur de l'index"
 
 #: lib/index.tcl:21
 msgid ""
 "Updating the Git index failed.  A rescan will be automatically started to "
 "resynchronize git-gui."
-msgstr "Le pré-commit a échoué. Une resynchronisation va être lancée automatiquement."
+msgstr ""
+"Échec de la mise à jour de l'index. Une resynchronisation va être lancée "
+"automatiquement."
 
 #: lib/index.tcl:27
 msgid "Continue"
@@ -1509,12 +1547,12 @@
 
 #: lib/index.tcl:31
 msgid "Unlock Index"
-msgstr "Dévérouiller le pré-commit"
+msgstr "Déverouiller l'index"
 
 #: lib/index.tcl:282
 #, tcl-format
 msgid "Unstaging %s from commit"
-msgstr "Supprimer %s du commit"
+msgstr "Désindexation de: %s"
 
 #: lib/index.tcl:313
 msgid "Ready to commit."
@@ -1523,23 +1561,23 @@
 #: lib/index.tcl:326
 #, tcl-format
 msgid "Adding %s"
-msgstr "Ajouter %s"
+msgstr "Ajout de %s"
 
 #: lib/index.tcl:381
 #, tcl-format
 msgid "Revert changes in file %s?"
-msgstr "Inverser les modifications dans le fichier %s ? "
+msgstr "Annuler les modifications dans le fichier %s ? "
 
 #: lib/index.tcl:383
 #, tcl-format
 msgid "Revert changes in these %i files?"
-msgstr "Inverser les modifications dans ces %i fichiers ?"
+msgstr "Annuler les modifications dans ces %i fichiers ?"
 
 #: lib/index.tcl:391
 msgid "Any unstaged changes will be permanently lost by the revert."
 msgstr ""
-"Toutes les modifications non pré-commitées seront définitivement perdues "
-"lors de l'inversion."
+"Toutes les modifications non-indexées seront définitivement perdues par "
+"l'annulation."
 
 #: lib/index.tcl:394
 msgid "Do Nothing"
@@ -1551,7 +1589,7 @@
 "\n"
 "You must finish amending this commit before starting any type of merge.\n"
 msgstr ""
-"Impossible de fucionner pendant une correction.\n"
+"Impossible de fusionner pendant une correction.\n"
 "\n"
 "Vous devez finir de corriger ce commit avant de lancer une quelconque "
 "fusion.\n"
@@ -1566,9 +1604,9 @@
 "The rescan will be automatically started now.\n"
 msgstr ""
 "L'état lors de la dernière synchronisation ne correspond plus à l'état du "
-"référentiel.\n"
+"dépôt.\n"
 "\n"
-"Un autre programme Git a modifié ce référentiel depuis la dernière "
+"Un autre programme Git a modifié ce dépôt depuis la dernière "
 "synchronisation. Une resynchronisation doit être effectuée avant de pouvoir "
 "fusionner de nouveau.\n"
 "\n"
@@ -1588,8 +1626,8 @@
 "\n"
 "Le fichier %s a des conflicts de fusion.\n"
 "\n"
-"Vous devez les résoudre, puis pré-commiter le fichier, et enfin commiter "
-"pour terminer la fusion courante. Seulementà ce moment là, il sera possible "
+"Vous devez les résoudre, puis indexer le fichier, et enfin commiter pour "
+"terminer la fusion courante. Seulement à ce moment là sera-t-il possible "
 "d'effectuer une nouvelle fusion.\n"
 
 #: lib/merge.tcl:54
@@ -1685,11 +1723,11 @@
 msgid "files reset"
 msgstr "fichiers réinitialisés"
 
-#: lib/merge.tcl:265
+#: lib/merge.tcl:266
 msgid "Abort failed."
 msgstr "L'abandon a échoué."
 
-#: lib/merge.tcl:267
+#: lib/merge.tcl:268
 msgid "Abort completed.  Ready."
 msgstr "Abandon teminé. Prêt."
 
@@ -1704,11 +1742,11 @@
 #: lib/option.tcl:109
 #, tcl-format
 msgid "%s Repository"
-msgstr "Référentiel de %s"
+msgstr "Dépôt: %s"
 
 #: lib/option.tcl:110
 msgid "Global (All Repositories)"
-msgstr "Globales (tous les référentiels)"
+msgstr "Globales (tous les dépôts)"
 
 #: lib/option.tcl:116
 msgid "User Name"
@@ -1736,56 +1774,76 @@
 
 #: lib/option.tcl:124
 msgid "Prune Tracking Branches During Fetch"
-msgstr "Nettoyer les branches de suivi pendant la récupération"
+msgstr "Purger les branches de suivi pendant la récupération"
 
 #: lib/option.tcl:125
 msgid "Match Tracking Branches"
 msgstr "Faire correspondre les branches de suivi"
 
 #: lib/option.tcl:126
+msgid "Blame Copy Only On Changed Files"
+msgstr "Annoter les copies seulement sur fichiers modifiés"
+
+#: lib/option.tcl:127
+msgid "Minimum Letters To Blame Copy On"
+msgstr "Minimum de caratères pour annoter une copie"
+
+#: lib/option.tcl:128
 msgid "Number of Diff Context Lines"
 msgstr "Nombre de lignes de contexte dans les diffs"
 
-#: lib/option.tcl:127
+#: lib/option.tcl:129
 msgid "Commit Message Text Width"
 msgstr "Largeur du texte de message de commit"
 
-#: lib/option.tcl:128
+#: lib/option.tcl:130
 msgid "New Branch Name Template"
 msgstr "Nouveau modèle de nom de branche"
 
-#: lib/option.tcl:192
+#: lib/option.tcl:194
 msgid "Spelling Dictionary:"
 msgstr "Dictionnaire d'orthographe :"
 
-#: lib/option.tcl:216
+#: lib/option.tcl:218
 msgid "Change Font"
-msgstr "Modifier les fontes"
+msgstr "Modifier les polices"
 
-#: lib/option.tcl:220
+#: lib/option.tcl:222
 #, tcl-format
 msgid "Choose %s"
 msgstr "Choisir %s"
 
-#: lib/option.tcl:226
+#: lib/option.tcl:228
 msgid "pt."
 msgstr "pt."
 
-#: lib/option.tcl:240
+#: lib/option.tcl:242
 msgid "Preferences"
 msgstr "Préférences"
 
-#: lib/option.tcl:275
+#: lib/option.tcl:277
 msgid "Failed to completely save options:"
 msgstr "La sauvegarde complète des options a échouée :"
 
+#: lib/remote.tcl:165
+msgid "Prune from"
+msgstr "Purger de"
+
+#: lib/remote.tcl:170
+msgid "Fetch from"
+msgstr "Récupérer de"
+
+#: lib/remote.tcl:213
+msgid "Push to"
+msgstr "Pousser vers"
+
 #: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34
 msgid "Delete Remote Branch"
 msgstr "Supprimer branche distante"
 
 #: lib/remote_branch_delete.tcl:47
 msgid "From Repository"
-msgstr "Référentiel"
+msgstr "Dépôt source"
 
 #: lib/remote_branch_delete.tcl:50 lib/transport.tcl:123
 msgid "Remote:"
@@ -1856,25 +1914,13 @@
 
 #: lib/remote_branch_delete.tcl:286
 msgid "No repository selected."
-msgstr "Aucun référentiel n'est sélectionné."
+msgstr "Aucun dépôt n'est sélectionné."
 
 #: lib/remote_branch_delete.tcl:291
 #, tcl-format
 msgid "Scanning %s..."
 msgstr "Synchronisation de %s..."
 
-#: lib/remote.tcl:165
-msgid "Prune from"
-msgstr "Nettoyer de"
-
-#: lib/remote.tcl:170
-msgid "Fetch from"
-msgstr "Récupérer de"
-
-#: lib/remote.tcl:213
-msgid "Push to"
-msgstr "Pousser vers"
-
 #: lib/shortcut.tcl:20 lib/shortcut.tcl:61
 msgid "Cannot write shortcut:"
 msgstr "Impossible d'écrire le raccourcis :"
@@ -1908,15 +1954,15 @@
 msgid "Unrecognized spell checker"
 msgstr "Vérificateur d'orthographe non reconnu"
 
-#: lib/spellcheck.tcl:180
+#: lib/spellcheck.tcl:186
 msgid "No Suggestions"
 msgstr "Aucune suggestion"
 
-#: lib/spellcheck.tcl:381
+#: lib/spellcheck.tcl:387
 msgid "Unexpected EOF from spell checker"
-msgstr "Fin de fichier innatendue envoyée par le vérificateur d'orthographe"
+msgstr "EOF inattendue envoyée par le vérificateur d'orthographe"
 
-#: lib/spellcheck.tcl:385
+#: lib/spellcheck.tcl:391
 msgid "Spell Checker Failed"
 msgstr "Le vérificateur d'orthographe a échoué"
 
@@ -1938,7 +1984,7 @@
 #: lib/transport.tcl:18
 #, tcl-format
 msgid "remote prune %s"
-msgstr "nettoyer à distance %s"
+msgstr "purger à distance %s"
 
 #: lib/transport.tcl:19
 #, tcl-format
@@ -1970,11 +2016,11 @@
 
 #: lib/transport.tcl:120
 msgid "Destination Repository"
-msgstr "Référentiel de destination"
+msgstr "Dépôt de destination"
 
 #: lib/transport.tcl:158
 msgid "Transfer Options"
-msgstr "Transférer options"
+msgstr "Options de transfert"
 
 #: lib/transport.tcl:160
 msgid "Force overwrite existing branch (may discard changes)"
@@ -1988,5 +2034,5 @@
 
 #: lib/transport.tcl:168
 msgid "Include tags"
-msgstr "Inclure les marques"
+msgstr "Inclure les marques (tags)"
 
diff --git a/git-gui/po/git-gui.pot b/git-gui/po/git-gui.pot
index 813199f..e295000 100644
--- a/git-gui/po/git-gui.pot
+++ b/git-gui/po/git-gui.pot
@@ -8,7 +8,7 @@
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-03-14 07:18+0100\n"
+"POT-Creation-Date: 2008-08-02 14:45-0700\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -16,33 +16,33 @@
 "Content-Type: text/plain; charset=CHARSET\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: git-gui.sh:41 git-gui.sh:634 git-gui.sh:648 git-gui.sh:661 git-gui.sh:744
-#: git-gui.sh:763
+#: git-gui.sh:41 git-gui.sh:688 git-gui.sh:702 git-gui.sh:715 git-gui.sh:798
+#: git-gui.sh:817
 msgid "git-gui: fatal error"
 msgstr ""
 
-#: git-gui.sh:593
+#: git-gui.sh:644
 #, tcl-format
 msgid "Invalid font specified in %s:"
 msgstr ""
 
-#: git-gui.sh:620
+#: git-gui.sh:674
 msgid "Main Font"
 msgstr ""
 
-#: git-gui.sh:621
+#: git-gui.sh:675
 msgid "Diff/Console Font"
 msgstr ""
 
-#: git-gui.sh:635
+#: git-gui.sh:689
 msgid "Cannot find git in PATH."
 msgstr ""
 
-#: git-gui.sh:662
+#: git-gui.sh:716
 msgid "Cannot parse Git version string:"
 msgstr ""
 
-#: git-gui.sh:680
+#: git-gui.sh:734
 #, tcl-format
 msgid ""
 "Git version cannot be determined.\n"
@@ -54,375 +54,379 @@
 "Assume '%s' is version 1.5.0?\n"
 msgstr ""
 
-#: git-gui.sh:918
+#: git-gui.sh:972
 msgid "Git directory not found:"
 msgstr ""
 
-#: git-gui.sh:925
+#: git-gui.sh:979
 msgid "Cannot move to top of working directory:"
 msgstr ""
 
-#: git-gui.sh:932
+#: git-gui.sh:986
 msgid "Cannot use funny .git directory:"
 msgstr ""
 
-#: git-gui.sh:937
+#: git-gui.sh:991
 msgid "No working directory"
 msgstr ""
 
-#: git-gui.sh:1084 lib/checkout_op.tcl:283
+#: git-gui.sh:1138 lib/checkout_op.tcl:305
 msgid "Refreshing file status..."
 msgstr ""
 
-#: git-gui.sh:1149
+#: git-gui.sh:1194
 msgid "Scanning for modified files ..."
 msgstr ""
 
-#: git-gui.sh:1324 lib/browser.tcl:246
+#: git-gui.sh:1369 lib/browser.tcl:246
 msgid "Ready."
 msgstr ""
 
-#: git-gui.sh:1590
+#: git-gui.sh:1635
 msgid "Unmodified"
 msgstr ""
 
-#: git-gui.sh:1592
+#: git-gui.sh:1637
 msgid "Modified, not staged"
 msgstr ""
 
-#: git-gui.sh:1593 git-gui.sh:1598
+#: git-gui.sh:1638 git-gui.sh:1643
 msgid "Staged for commit"
 msgstr ""
 
-#: git-gui.sh:1594 git-gui.sh:1599
+#: git-gui.sh:1639 git-gui.sh:1644
 msgid "Portions staged for commit"
 msgstr ""
 
-#: git-gui.sh:1595 git-gui.sh:1600
+#: git-gui.sh:1640 git-gui.sh:1645
 msgid "Staged for commit, missing"
 msgstr ""
 
-#: git-gui.sh:1597
+#: git-gui.sh:1642
 msgid "Untracked, not staged"
 msgstr ""
 
-#: git-gui.sh:1602
+#: git-gui.sh:1647
 msgid "Missing"
 msgstr ""
 
-#: git-gui.sh:1603
+#: git-gui.sh:1648
 msgid "Staged for removal"
 msgstr ""
 
-#: git-gui.sh:1604
+#: git-gui.sh:1649
 msgid "Staged for removal, still present"
 msgstr ""
 
-#: git-gui.sh:1606 git-gui.sh:1607 git-gui.sh:1608 git-gui.sh:1609
+#: git-gui.sh:1651 git-gui.sh:1652 git-gui.sh:1653 git-gui.sh:1654
 msgid "Requires merge resolution"
 msgstr ""
 
-#: git-gui.sh:1644
+#: git-gui.sh:1689
 msgid "Starting gitk... please wait..."
 msgstr ""
 
-#: git-gui.sh:1653
-#, tcl-format
-msgid ""
-"Unable to start gitk:\n"
-"\n"
-"%s does not exist"
+#: git-gui.sh:1698
+msgid "Couldn't find gitk in PATH"
 msgstr ""
 
-#: git-gui.sh:1860 lib/choose_repository.tcl:36
+#: git-gui.sh:1948 lib/choose_repository.tcl:36
 msgid "Repository"
 msgstr ""
 
-#: git-gui.sh:1861
+#: git-gui.sh:1949
 msgid "Edit"
 msgstr ""
 
-#: git-gui.sh:1863 lib/choose_rev.tcl:561
+#: git-gui.sh:1951 lib/choose_rev.tcl:561
 msgid "Branch"
 msgstr ""
 
-#: git-gui.sh:1866 lib/choose_rev.tcl:548
+#: git-gui.sh:1954 lib/choose_rev.tcl:548
 msgid "Commit@@noun"
 msgstr ""
 
-#: git-gui.sh:1869 lib/merge.tcl:120 lib/merge.tcl:149 lib/merge.tcl:167
+#: git-gui.sh:1957 lib/merge.tcl:120 lib/merge.tcl:149 lib/merge.tcl:167
 msgid "Merge"
 msgstr ""
 
-#: git-gui.sh:1870 lib/choose_rev.tcl:557
+#: git-gui.sh:1958 lib/choose_rev.tcl:557
 msgid "Remote"
 msgstr ""
 
-#: git-gui.sh:1879
+#: git-gui.sh:1967
 msgid "Browse Current Branch's Files"
 msgstr ""
 
-#: git-gui.sh:1883
+#: git-gui.sh:1971
 msgid "Browse Branch Files..."
 msgstr ""
 
-#: git-gui.sh:1888
+#: git-gui.sh:1976
 msgid "Visualize Current Branch's History"
 msgstr ""
 
-#: git-gui.sh:1892
+#: git-gui.sh:1980
 msgid "Visualize All Branch History"
 msgstr ""
 
-#: git-gui.sh:1899
+#: git-gui.sh:1987
 #, tcl-format
 msgid "Browse %s's Files"
 msgstr ""
 
-#: git-gui.sh:1901
+#: git-gui.sh:1989
 #, tcl-format
 msgid "Visualize %s's History"
 msgstr ""
 
-#: git-gui.sh:1906 lib/database.tcl:27 lib/database.tcl:67
+#: git-gui.sh:1994 lib/database.tcl:27 lib/database.tcl:67
 msgid "Database Statistics"
 msgstr ""
 
-#: git-gui.sh:1909 lib/database.tcl:34
+#: git-gui.sh:1997 lib/database.tcl:34
 msgid "Compress Database"
 msgstr ""
 
-#: git-gui.sh:1912
+#: git-gui.sh:2000
 msgid "Verify Database"
 msgstr ""
 
-#: git-gui.sh:1919 git-gui.sh:1923 git-gui.sh:1927 lib/shortcut.tcl:7
+#: git-gui.sh:2007 git-gui.sh:2011 git-gui.sh:2015 lib/shortcut.tcl:7
 #: lib/shortcut.tcl:39 lib/shortcut.tcl:71
 msgid "Create Desktop Icon"
 msgstr ""
 
-#: git-gui.sh:1932 lib/choose_repository.tcl:177 lib/choose_repository.tcl:185
+#: git-gui.sh:2023 lib/choose_repository.tcl:177 lib/choose_repository.tcl:185
 msgid "Quit"
 msgstr ""
 
-#: git-gui.sh:1939
+#: git-gui.sh:2031
 msgid "Undo"
 msgstr ""
 
-#: git-gui.sh:1942
+#: git-gui.sh:2034
 msgid "Redo"
 msgstr ""
 
-#: git-gui.sh:1946 git-gui.sh:2443
+#: git-gui.sh:2038 git-gui.sh:2545
 msgid "Cut"
 msgstr ""
 
-#: git-gui.sh:1949 git-gui.sh:2446 git-gui.sh:2520 git-gui.sh:2614
+#: git-gui.sh:2041 git-gui.sh:2548 git-gui.sh:2622 git-gui.sh:2715
 #: lib/console.tcl:69
 msgid "Copy"
 msgstr ""
 
-#: git-gui.sh:1952 git-gui.sh:2449
+#: git-gui.sh:2044 git-gui.sh:2551
 msgid "Paste"
 msgstr ""
 
-#: git-gui.sh:1955 git-gui.sh:2452 lib/branch_delete.tcl:26
+#: git-gui.sh:2047 git-gui.sh:2554 lib/branch_delete.tcl:26
 #: lib/remote_branch_delete.tcl:38
 msgid "Delete"
 msgstr ""
 
-#: git-gui.sh:1959 git-gui.sh:2456 git-gui.sh:2618 lib/console.tcl:71
+#: git-gui.sh:2051 git-gui.sh:2558 git-gui.sh:2719 lib/console.tcl:71
 msgid "Select All"
 msgstr ""
 
-#: git-gui.sh:1968
+#: git-gui.sh:2060
 msgid "Create..."
 msgstr ""
 
-#: git-gui.sh:1974
+#: git-gui.sh:2066
 msgid "Checkout..."
 msgstr ""
 
-#: git-gui.sh:1980
+#: git-gui.sh:2072
 msgid "Rename..."
 msgstr ""
 
-#: git-gui.sh:1985 git-gui.sh:2085
+#: git-gui.sh:2077 git-gui.sh:2187
 msgid "Delete..."
 msgstr ""
 
-#: git-gui.sh:1990
+#: git-gui.sh:2082
 msgid "Reset..."
 msgstr ""
 
-#: git-gui.sh:2002 git-gui.sh:2389
+#: git-gui.sh:2094 git-gui.sh:2491
 msgid "New Commit"
 msgstr ""
 
-#: git-gui.sh:2010 git-gui.sh:2396
+#: git-gui.sh:2102 git-gui.sh:2498
 msgid "Amend Last Commit"
 msgstr ""
 
-#: git-gui.sh:2019 git-gui.sh:2356 lib/remote_branch_delete.tcl:99
+#: git-gui.sh:2111 git-gui.sh:2458 lib/remote_branch_delete.tcl:99
 msgid "Rescan"
 msgstr ""
 
-#: git-gui.sh:2025
+#: git-gui.sh:2117
 msgid "Stage To Commit"
 msgstr ""
 
-#: git-gui.sh:2031
+#: git-gui.sh:2123
 msgid "Stage Changed Files To Commit"
 msgstr ""
 
-#: git-gui.sh:2037
+#: git-gui.sh:2129
 msgid "Unstage From Commit"
 msgstr ""
 
-#: git-gui.sh:2042 lib/index.tcl:395
+#: git-gui.sh:2134 lib/index.tcl:395
 msgid "Revert Changes"
 msgstr ""
 
-#: git-gui.sh:2049 git-gui.sh:2368 git-gui.sh:2467
+#: git-gui.sh:2141 git-gui.sh:2702
+msgid "Show Less Context"
+msgstr ""
+
+#: git-gui.sh:2145 git-gui.sh:2706
+msgid "Show More Context"
+msgstr ""
+
+#: git-gui.sh:2151 git-gui.sh:2470 git-gui.sh:2569
 msgid "Sign Off"
 msgstr ""
 
-#: git-gui.sh:2053 git-gui.sh:2372
+#: git-gui.sh:2155 git-gui.sh:2474
 msgid "Commit@@verb"
 msgstr ""
 
-#: git-gui.sh:2064
+#: git-gui.sh:2166
 msgid "Local Merge..."
 msgstr ""
 
-#: git-gui.sh:2069
+#: git-gui.sh:2171
 msgid "Abort Merge..."
 msgstr ""
 
-#: git-gui.sh:2081
+#: git-gui.sh:2183
 msgid "Push..."
 msgstr ""
 
-#: git-gui.sh:2092 lib/choose_repository.tcl:41
-msgid "Apple"
-msgstr ""
-
-#: git-gui.sh:2095 git-gui.sh:2117 lib/about.tcl:14
+#: git-gui.sh:2197 git-gui.sh:2219 lib/about.tcl:14
 #: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50
 #, tcl-format
 msgid "About %s"
 msgstr ""
 
-#: git-gui.sh:2099
+#: git-gui.sh:2201
 msgid "Preferences..."
 msgstr ""
 
-#: git-gui.sh:2107 git-gui.sh:2639
+#: git-gui.sh:2209 git-gui.sh:2740
 msgid "Options..."
 msgstr ""
 
-#: git-gui.sh:2113 lib/choose_repository.tcl:47
+#: git-gui.sh:2215 lib/choose_repository.tcl:47
 msgid "Help"
 msgstr ""
 
-#: git-gui.sh:2154
+#: git-gui.sh:2256
 msgid "Online Documentation"
 msgstr ""
 
-#: git-gui.sh:2238
+#: git-gui.sh:2340
 #, tcl-format
 msgid "fatal: cannot stat path %s: No such file or directory"
 msgstr ""
 
-#: git-gui.sh:2271
+#: git-gui.sh:2373
 msgid "Current Branch:"
 msgstr ""
 
-#: git-gui.sh:2292
+#: git-gui.sh:2394
 msgid "Staged Changes (Will Commit)"
 msgstr ""
 
-#: git-gui.sh:2312
+#: git-gui.sh:2414
 msgid "Unstaged Changes"
 msgstr ""
 
-#: git-gui.sh:2362
+#: git-gui.sh:2464
 msgid "Stage Changed"
 msgstr ""
 
-#: git-gui.sh:2378 lib/transport.tcl:93 lib/transport.tcl:182
+#: git-gui.sh:2480 lib/transport.tcl:93 lib/transport.tcl:182
 msgid "Push"
 msgstr ""
 
-#: git-gui.sh:2408
+#: git-gui.sh:2510
 msgid "Initial Commit Message:"
 msgstr ""
 
-#: git-gui.sh:2409
+#: git-gui.sh:2511
 msgid "Amended Commit Message:"
 msgstr ""
 
-#: git-gui.sh:2410
+#: git-gui.sh:2512
 msgid "Amended Initial Commit Message:"
 msgstr ""
 
-#: git-gui.sh:2411
+#: git-gui.sh:2513
 msgid "Amended Merge Commit Message:"
 msgstr ""
 
-#: git-gui.sh:2412
+#: git-gui.sh:2514
 msgid "Merge Commit Message:"
 msgstr ""
 
-#: git-gui.sh:2413
+#: git-gui.sh:2515
 msgid "Commit Message:"
 msgstr ""
 
-#: git-gui.sh:2459 git-gui.sh:2622 lib/console.tcl:73
+#: git-gui.sh:2561 git-gui.sh:2723 lib/console.tcl:73
 msgid "Copy All"
 msgstr ""
 
-#: git-gui.sh:2483 lib/blame.tcl:107
+#: git-gui.sh:2585 lib/blame.tcl:100
 msgid "File:"
 msgstr ""
 
-#: git-gui.sh:2589
+#: git-gui.sh:2691
 msgid "Apply/Reverse Hunk"
 msgstr ""
 
-#: git-gui.sh:2595
-msgid "Show Less Context"
+#: git-gui.sh:2696
+msgid "Apply/Reverse Line"
 msgstr ""
 
-#: git-gui.sh:2602
-msgid "Show More Context"
-msgstr ""
-
-#: git-gui.sh:2610
+#: git-gui.sh:2711
 msgid "Refresh"
 msgstr ""
 
-#: git-gui.sh:2631
+#: git-gui.sh:2732
 msgid "Decrease Font Size"
 msgstr ""
 
-#: git-gui.sh:2635
+#: git-gui.sh:2736
 msgid "Increase Font Size"
 msgstr ""
 
-#: git-gui.sh:2646
+#: git-gui.sh:2747
 msgid "Unstage Hunk From Commit"
 msgstr ""
 
-#: git-gui.sh:2648
+#: git-gui.sh:2748
+msgid "Unstage Line From Commit"
+msgstr ""
+
+#: git-gui.sh:2750
 msgid "Stage Hunk For Commit"
 msgstr ""
 
-#: git-gui.sh:2667
+#: git-gui.sh:2751
+msgid "Stage Line For Commit"
+msgstr ""
+
+#: git-gui.sh:2771
 msgid "Initializing..."
 msgstr ""
 
-#: git-gui.sh:2762
+#: git-gui.sh:2876
 #, tcl-format
 msgid ""
 "Possible environment issues exist.\n"
@@ -433,14 +437,14 @@
 "\n"
 msgstr ""
 
-#: git-gui.sh:2792
+#: git-gui.sh:2906
 msgid ""
 "\n"
 "This is due to a known issue with the\n"
 "Tcl binary distributed by Cygwin."
 msgstr ""
 
-#: git-gui.sh:2797
+#: git-gui.sh:2911
 #, tcl-format
 msgid ""
 "\n"
@@ -455,64 +459,80 @@
 msgid "git-gui - a graphical user interface for Git."
 msgstr ""
 
-#: lib/blame.tcl:77
+#: lib/blame.tcl:70
 msgid "File Viewer"
 msgstr ""
 
-#: lib/blame.tcl:81
+#: lib/blame.tcl:74
 msgid "Commit:"
 msgstr ""
 
-#: lib/blame.tcl:264
+#: lib/blame.tcl:257
 msgid "Copy Commit"
 msgstr ""
 
-#: lib/blame.tcl:384
+#: lib/blame.tcl:260
+msgid "Do Full Copy Detection"
+msgstr ""
+
+#: lib/blame.tcl:388
 #, tcl-format
 msgid "Reading %s..."
 msgstr ""
 
-#: lib/blame.tcl:488
+#: lib/blame.tcl:492
 msgid "Loading copy/move tracking annotations..."
 msgstr ""
 
-#: lib/blame.tcl:508
+#: lib/blame.tcl:512
 msgid "lines annotated"
 msgstr ""
 
-#: lib/blame.tcl:689
+#: lib/blame.tcl:704
 msgid "Loading original location annotations..."
 msgstr ""
 
-#: lib/blame.tcl:692
+#: lib/blame.tcl:707
 msgid "Annotation complete."
 msgstr ""
 
-#: lib/blame.tcl:746
+#: lib/blame.tcl:737
+msgid "Busy"
+msgstr ""
+
+#: lib/blame.tcl:738
+msgid "Annotation process is already running."
+msgstr ""
+
+#: lib/blame.tcl:777
+msgid "Running thorough copy detection..."
+msgstr ""
+
+#: lib/blame.tcl:827
 msgid "Loading annotation..."
 msgstr ""
 
-#: lib/blame.tcl:802
+#: lib/blame.tcl:883
 msgid "Author:"
 msgstr ""
 
-#: lib/blame.tcl:806
+#: lib/blame.tcl:887
 msgid "Committer:"
 msgstr ""
 
-#: lib/blame.tcl:811
+#: lib/blame.tcl:892
 msgid "Original File:"
 msgstr ""
 
-#: lib/blame.tcl:925
+#: lib/blame.tcl:1006
 msgid "Originally By:"
 msgstr ""
 
-#: lib/blame.tcl:931
+#: lib/blame.tcl:1012
 msgid "In File:"
 msgstr ""
 
-#: lib/blame.tcl:936
+#: lib/blame.tcl:1017
 msgid "Copied Or Moved Here By:"
 msgstr ""
 
@@ -526,7 +546,7 @@
 
 #: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35
 #: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:282
-#: lib/checkout_op.tcl:522 lib/choose_font.tcl:43 lib/merge.tcl:171
+#: lib/checkout_op.tcl:544 lib/choose_font.tcl:43 lib/merge.tcl:171
 #: lib/option.tcl:103 lib/remote_branch_delete.tcl:42 lib/transport.tcl:97
 msgid "Cancel"
 msgstr ""
@@ -535,7 +555,7 @@
 msgid "Revision"
 msgstr ""
 
-#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:242
+#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:244
 msgid "Options"
 msgstr ""
 
@@ -587,7 +607,7 @@
 msgid "Fast Forward Only"
 msgstr ""
 
-#: lib/branch_create.tcl:85 lib/checkout_op.tcl:514
+#: lib/branch_create.tcl:85 lib/checkout_op.tcl:536
 msgid "Reset"
 msgstr ""
 
@@ -672,7 +692,7 @@
 msgid "Please select a branch to rename."
 msgstr ""
 
-#: lib/branch_rename.tcl:96 lib/checkout_op.tcl:179
+#: lib/branch_rename.tcl:96 lib/checkout_op.tcl:201
 #, tcl-format
 msgid "Branch '%s' already exists."
 msgstr ""
@@ -704,31 +724,36 @@
 msgstr ""
 
 #: lib/browser.tcl:278 lib/choose_repository.tcl:387
-#: lib/choose_repository.tcl:474 lib/choose_repository.tcl:484
-#: lib/choose_repository.tcl:987
+#: lib/choose_repository.tcl:472 lib/choose_repository.tcl:482
+#: lib/choose_repository.tcl:985
 msgid "Browse"
 msgstr ""
 
-#: lib/checkout_op.tcl:79
+#: lib/checkout_op.tcl:84
 #, tcl-format
 msgid "Fetching %s from %s"
 msgstr ""
 
-#: lib/checkout_op.tcl:127
+#: lib/checkout_op.tcl:132
 #, tcl-format
 msgid "fatal: Cannot resolve %s"
 msgstr ""
 
-#: lib/checkout_op.tcl:140 lib/console.tcl:81 lib/database.tcl:31
+#: lib/checkout_op.tcl:145 lib/console.tcl:81 lib/database.tcl:31
 msgid "Close"
 msgstr ""
 
-#: lib/checkout_op.tcl:169
+#: lib/checkout_op.tcl:174
 #, tcl-format
 msgid "Branch '%s' does not exist."
 msgstr ""
 
-#: lib/checkout_op.tcl:206
+#: lib/checkout_op.tcl:193
+#, tcl-format
+msgid "Failed to configure simplified git-pull for '%s'."
+msgstr ""
+
+#: lib/checkout_op.tcl:228
 #, tcl-format
 msgid ""
 "Branch '%s' already exists.\n"
@@ -737,21 +762,21 @@
 "A merge is required."
 msgstr ""
 
-#: lib/checkout_op.tcl:220
+#: lib/checkout_op.tcl:242
 #, tcl-format
 msgid "Merge strategy '%s' not supported."
 msgstr ""
 
-#: lib/checkout_op.tcl:239
+#: lib/checkout_op.tcl:261
 #, tcl-format
 msgid "Failed to update '%s'."
 msgstr ""
 
-#: lib/checkout_op.tcl:251
+#: lib/checkout_op.tcl:273
 msgid "Staging area (index) is already locked."
 msgstr ""
 
-#: lib/checkout_op.tcl:266
+#: lib/checkout_op.tcl:288
 msgid ""
 "Last scanned state does not match repository state.\n"
 "\n"
@@ -761,30 +786,30 @@
 "The rescan will be automatically started now.\n"
 msgstr ""
 
-#: lib/checkout_op.tcl:322
+#: lib/checkout_op.tcl:344
 #, tcl-format
 msgid "Updating working directory to '%s'..."
 msgstr ""
 
-#: lib/checkout_op.tcl:323
+#: lib/checkout_op.tcl:345
 msgid "files checked out"
 msgstr ""
 
-#: lib/checkout_op.tcl:353
+#: lib/checkout_op.tcl:375
 #, tcl-format
 msgid "Aborted checkout of '%s' (file level merging is required)."
 msgstr ""
 
-#: lib/checkout_op.tcl:354
+#: lib/checkout_op.tcl:376
 msgid "File level merge required."
 msgstr ""
 
-#: lib/checkout_op.tcl:358
+#: lib/checkout_op.tcl:380
 #, tcl-format
 msgid "Staying on branch '%s'."
 msgstr ""
 
-#: lib/checkout_op.tcl:429
+#: lib/checkout_op.tcl:451
 msgid ""
 "You are no longer on a local branch.\n"
 "\n"
@@ -792,30 +817,30 @@
 "Checkout'."
 msgstr ""
 
-#: lib/checkout_op.tcl:446 lib/checkout_op.tcl:450
+#: lib/checkout_op.tcl:468 lib/checkout_op.tcl:472
 #, tcl-format
 msgid "Checked out '%s'."
 msgstr ""
 
-#: lib/checkout_op.tcl:478
+#: lib/checkout_op.tcl:500
 #, tcl-format
 msgid "Resetting '%s' to '%s' will lose the following commits:"
 msgstr ""
 
-#: lib/checkout_op.tcl:500
+#: lib/checkout_op.tcl:522
 msgid "Recovering lost commits may not be easy."
 msgstr ""
 
-#: lib/checkout_op.tcl:505
+#: lib/checkout_op.tcl:527
 #, tcl-format
 msgid "Reset '%s'?"
 msgstr ""
 
-#: lib/checkout_op.tcl:510 lib/merge.tcl:163
+#: lib/checkout_op.tcl:532 lib/merge.tcl:163
 msgid "Visualize"
 msgstr ""
 
-#: lib/checkout_op.tcl:578
+#: lib/checkout_op.tcl:600
 #, tcl-format
 msgid ""
 "Failed to set current branch.\n"
@@ -860,7 +885,7 @@
 msgid "New..."
 msgstr ""
 
-#: lib/choose_repository.tcl:94 lib/choose_repository.tcl:460
+#: lib/choose_repository.tcl:94 lib/choose_repository.tcl:458
 msgid "Clone Existing Repository"
 msgstr ""
 
@@ -868,7 +893,7 @@
 msgid "Clone..."
 msgstr ""
 
-#: lib/choose_repository.tcl:107 lib/choose_repository.tcl:976
+#: lib/choose_repository.tcl:107 lib/choose_repository.tcl:974
 msgid "Open Existing Repository"
 msgstr ""
 
@@ -890,183 +915,183 @@
 msgid "Failed to create repository %s:"
 msgstr ""
 
-#: lib/choose_repository.tcl:381 lib/choose_repository.tcl:478
+#: lib/choose_repository.tcl:381 lib/choose_repository.tcl:476
 msgid "Directory:"
 msgstr ""
 
-#: lib/choose_repository.tcl:412 lib/choose_repository.tcl:537
-#: lib/choose_repository.tcl:1011
+#: lib/choose_repository.tcl:410 lib/choose_repository.tcl:535
+#: lib/choose_repository.tcl:1007
 msgid "Git Repository"
 msgstr ""
 
-#: lib/choose_repository.tcl:437
+#: lib/choose_repository.tcl:435
 #, tcl-format
 msgid "Directory %s already exists."
 msgstr ""
 
-#: lib/choose_repository.tcl:441
+#: lib/choose_repository.tcl:439
 #, tcl-format
 msgid "File %s already exists."
 msgstr ""
 
-#: lib/choose_repository.tcl:455
+#: lib/choose_repository.tcl:453
 msgid "Clone"
 msgstr ""
 
-#: lib/choose_repository.tcl:468
+#: lib/choose_repository.tcl:466
 msgid "URL:"
 msgstr ""
 
-#: lib/choose_repository.tcl:489
+#: lib/choose_repository.tcl:487
 msgid "Clone Type:"
 msgstr ""
 
-#: lib/choose_repository.tcl:495
+#: lib/choose_repository.tcl:493
 msgid "Standard (Fast, Semi-Redundant, Hardlinks)"
 msgstr ""
 
-#: lib/choose_repository.tcl:501
+#: lib/choose_repository.tcl:499
 msgid "Full Copy (Slower, Redundant Backup)"
 msgstr ""
 
-#: lib/choose_repository.tcl:507
+#: lib/choose_repository.tcl:505
 msgid "Shared (Fastest, Not Recommended, No Backup)"
 msgstr ""
 
-#: lib/choose_repository.tcl:543 lib/choose_repository.tcl:590
-#: lib/choose_repository.tcl:736 lib/choose_repository.tcl:806
-#: lib/choose_repository.tcl:1017 lib/choose_repository.tcl:1025
+#: lib/choose_repository.tcl:541 lib/choose_repository.tcl:588
+#: lib/choose_repository.tcl:734 lib/choose_repository.tcl:804
+#: lib/choose_repository.tcl:1013 lib/choose_repository.tcl:1021
 #, tcl-format
 msgid "Not a Git repository: %s"
 msgstr ""
 
-#: lib/choose_repository.tcl:579
+#: lib/choose_repository.tcl:577
 msgid "Standard only available for local repository."
 msgstr ""
 
-#: lib/choose_repository.tcl:583
+#: lib/choose_repository.tcl:581
 msgid "Shared only available for local repository."
 msgstr ""
 
-#: lib/choose_repository.tcl:604
+#: lib/choose_repository.tcl:602
 #, tcl-format
 msgid "Location %s already exists."
 msgstr ""
 
-#: lib/choose_repository.tcl:615
+#: lib/choose_repository.tcl:613
 msgid "Failed to configure origin"
 msgstr ""
 
-#: lib/choose_repository.tcl:627
+#: lib/choose_repository.tcl:625
 msgid "Counting objects"
 msgstr ""
 
-#: lib/choose_repository.tcl:628
+#: lib/choose_repository.tcl:626
 msgid "buckets"
 msgstr ""
 
-#: lib/choose_repository.tcl:652
+#: lib/choose_repository.tcl:650
 #, tcl-format
 msgid "Unable to copy objects/info/alternates: %s"
 msgstr ""
 
-#: lib/choose_repository.tcl:688
+#: lib/choose_repository.tcl:686
 #, tcl-format
 msgid "Nothing to clone from %s."
 msgstr ""
 
-#: lib/choose_repository.tcl:690 lib/choose_repository.tcl:904
-#: lib/choose_repository.tcl:916
+#: lib/choose_repository.tcl:688 lib/choose_repository.tcl:902
+#: lib/choose_repository.tcl:914
 msgid "The 'master' branch has not been initialized."
 msgstr ""
 
-#: lib/choose_repository.tcl:703
+#: lib/choose_repository.tcl:701
 msgid "Hardlinks are unavailable.  Falling back to copying."
 msgstr ""
 
-#: lib/choose_repository.tcl:715
+#: lib/choose_repository.tcl:713
 #, tcl-format
 msgid "Cloning from %s"
 msgstr ""
 
-#: lib/choose_repository.tcl:746
+#: lib/choose_repository.tcl:744
 msgid "Copying objects"
 msgstr ""
 
-#: lib/choose_repository.tcl:747
+#: lib/choose_repository.tcl:745
 msgid "KiB"
 msgstr ""
 
-#: lib/choose_repository.tcl:771
+#: lib/choose_repository.tcl:769
 #, tcl-format
 msgid "Unable to copy object: %s"
 msgstr ""
 
-#: lib/choose_repository.tcl:781
+#: lib/choose_repository.tcl:779
 msgid "Linking objects"
 msgstr ""
 
-#: lib/choose_repository.tcl:782
+#: lib/choose_repository.tcl:780
 msgid "objects"
 msgstr ""
 
-#: lib/choose_repository.tcl:790
+#: lib/choose_repository.tcl:788
 #, tcl-format
 msgid "Unable to hardlink object: %s"
 msgstr ""
 
-#: lib/choose_repository.tcl:845
+#: lib/choose_repository.tcl:843
 msgid "Cannot fetch branches and objects.  See console output for details."
 msgstr ""
 
-#: lib/choose_repository.tcl:856
+#: lib/choose_repository.tcl:854
 msgid "Cannot fetch tags.  See console output for details."
 msgstr ""
 
-#: lib/choose_repository.tcl:880
+#: lib/choose_repository.tcl:878
 msgid "Cannot determine HEAD.  See console output for details."
 msgstr ""
 
-#: lib/choose_repository.tcl:889
+#: lib/choose_repository.tcl:887
 #, tcl-format
 msgid "Unable to cleanup %s"
 msgstr ""
 
-#: lib/choose_repository.tcl:895
+#: lib/choose_repository.tcl:893
 msgid "Clone failed."
 msgstr ""
 
-#: lib/choose_repository.tcl:902
+#: lib/choose_repository.tcl:900
 msgid "No default branch obtained."
 msgstr ""
 
-#: lib/choose_repository.tcl:913
+#: lib/choose_repository.tcl:911
 #, tcl-format
 msgid "Cannot resolve %s as a commit."
 msgstr ""
 
-#: lib/choose_repository.tcl:925
+#: lib/choose_repository.tcl:923
 msgid "Creating working directory"
 msgstr ""
 
-#: lib/choose_repository.tcl:926 lib/index.tcl:65 lib/index.tcl:127
+#: lib/choose_repository.tcl:924 lib/index.tcl:65 lib/index.tcl:127
 #: lib/index.tcl:193
 msgid "files"
 msgstr ""
 
-#: lib/choose_repository.tcl:955
+#: lib/choose_repository.tcl:953
 msgid "Initial file checkout failed."
 msgstr ""
 
-#: lib/choose_repository.tcl:971
+#: lib/choose_repository.tcl:969
 msgid "Open"
 msgstr ""
 
-#: lib/choose_repository.tcl:981
+#: lib/choose_repository.tcl:979
 msgid "Repository:"
 msgstr ""
 
-#: lib/choose_repository.tcl:1031
+#: lib/choose_repository.tcl:1027
 #, tcl-format
 msgid "Failed to open repository %s:"
 msgstr ""
@@ -1314,7 +1339,7 @@
 msgid "Invalid date from Git: %s"
 msgstr ""
 
-#: lib/diff.tcl:42
+#: lib/diff.tcl:44
 #, tcl-format
 msgid ""
 "No differences detected.\n"
@@ -1328,40 +1353,48 @@
 "the same state."
 msgstr ""
 
-#: lib/diff.tcl:81
+#: lib/diff.tcl:83
 #, tcl-format
 msgid "Loading diff of %s..."
 msgstr ""
 
-#: lib/diff.tcl:114 lib/diff.tcl:184
+#: lib/diff.tcl:116 lib/diff.tcl:190
 #, tcl-format
 msgid "Unable to display %s"
 msgstr ""
 
-#: lib/diff.tcl:115
+#: lib/diff.tcl:117
 msgid "Error loading file:"
 msgstr ""
 
-#: lib/diff.tcl:122
+#: lib/diff.tcl:124
 msgid "Git Repository (subproject)"
 msgstr ""
 
-#: lib/diff.tcl:134
+#: lib/diff.tcl:136
 msgid "* Binary file (not showing content)."
 msgstr ""
 
-#: lib/diff.tcl:185
+#: lib/diff.tcl:191
 msgid "Error loading diff:"
 msgstr ""
 
-#: lib/diff.tcl:303
+#: lib/diff.tcl:313
 msgid "Failed to unstage selected hunk."
 msgstr ""
 
-#: lib/diff.tcl:310
+#: lib/diff.tcl:320
 msgid "Failed to stage selected hunk."
 msgstr ""
 
+#: lib/diff.tcl:386
+msgid "Failed to unstage selected line."
+msgstr ""
+
+#: lib/diff.tcl:394
+msgid "Failed to stage selected line."
+msgstr ""
+
 #: lib/error.tcl:20 lib/error.tcl:114
 msgid "error"
 msgstr ""
@@ -1527,11 +1560,11 @@
 msgid "files reset"
 msgstr ""
 
-#: lib/merge.tcl:265
+#: lib/merge.tcl:266
 msgid "Abort failed."
 msgstr ""
 
-#: lib/merge.tcl:267
+#: lib/merge.tcl:268
 msgid "Abort completed.  Ready."
 msgstr ""
 
@@ -1585,42 +1618,62 @@
 msgstr ""
 
 #: lib/option.tcl:126
-msgid "Number of Diff Context Lines"
+msgid "Blame Copy Only On Changed Files"
 msgstr ""
 
 #: lib/option.tcl:127
-msgid "Commit Message Text Width"
+msgid "Minimum Letters To Blame Copy On"
 msgstr ""
 
 #: lib/option.tcl:128
+msgid "Number of Diff Context Lines"
+msgstr ""
+
+#: lib/option.tcl:129
+msgid "Commit Message Text Width"
+msgstr ""
+
+#: lib/option.tcl:130
 msgid "New Branch Name Template"
 msgstr ""
 
-#: lib/option.tcl:192
+#: lib/option.tcl:194
 msgid "Spelling Dictionary:"
 msgstr ""
 
-#: lib/option.tcl:216
+#: lib/option.tcl:218
 msgid "Change Font"
 msgstr ""
 
-#: lib/option.tcl:220
+#: lib/option.tcl:222
 #, tcl-format
 msgid "Choose %s"
 msgstr ""
 
-#: lib/option.tcl:226
+#: lib/option.tcl:228
 msgid "pt."
 msgstr ""
 
-#: lib/option.tcl:240
+#: lib/option.tcl:242
 msgid "Preferences"
 msgstr ""
 
-#: lib/option.tcl:275
+#: lib/option.tcl:277
 msgid "Failed to completely save options:"
 msgstr ""
 
+#: lib/remote.tcl:165
+msgid "Prune from"
+msgstr ""
+
+#: lib/remote.tcl:170
+msgid "Fetch from"
+msgstr ""
+
+#: lib/remote.tcl:213
+msgid "Push to"
+msgstr ""
+
 #: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34
 msgid "Delete Remote Branch"
 msgstr ""
@@ -1697,18 +1750,6 @@
 msgid "Scanning %s..."
 msgstr ""
 
-#: lib/remote.tcl:165
-msgid "Prune from"
-msgstr ""
-
-#: lib/remote.tcl:170
-msgid "Fetch from"
-msgstr ""
-
-#: lib/remote.tcl:213
-msgid "Push to"
-msgstr ""
-
 #: lib/shortcut.tcl:20 lib/shortcut.tcl:61
 msgid "Cannot write shortcut:"
 msgstr ""
@@ -1742,15 +1783,15 @@
 msgid "Unrecognized spell checker"
 msgstr ""
 
-#: lib/spellcheck.tcl:180
+#: lib/spellcheck.tcl:186
 msgid "No Suggestions"
 msgstr ""
 
-#: lib/spellcheck.tcl:381
+#: lib/spellcheck.tcl:387
 msgid "Unexpected EOF from spell checker"
 msgstr ""
 
-#: lib/spellcheck.tcl:385
+#: lib/spellcheck.tcl:391
 msgid "Spell Checker Failed"
 msgstr ""
 
diff --git a/git-gui/po/it.po b/git-gui/po/it.po
index 11cc79b..3db4fb6 100644
--- a/git-gui/po/it.po
+++ b/git-gui/po/it.po
@@ -3,47 +3,47 @@
 # This file is distributed under the same license as the git-gui package.
 # Paolo Ciarrocchi <paolo.ciarrocchi@gmail.com>, 2007
 # Michele Ballabio <barra_cuda@katamail.com>, 2007.
-# 
-# 
+#
+#
 msgid ""
 msgstr ""
 "Project-Id-Version: git-gui\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-03-14 07:18+0100\n"
-"PO-Revision-Date: 2008-03-12 22:12+0100\n"
+"POT-Creation-Date: 2008-08-02 14:45-0700\n"
+"PO-Revision-Date: 2008-08-03 16:04+0200\n"
 "Last-Translator: Michele Ballabio <barra_cuda@katamail.com>\n"
 "Language-Team: Italian <tp@lists.linux.it>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: git-gui.sh:41 git-gui.sh:634 git-gui.sh:648 git-gui.sh:661 git-gui.sh:744
-#: git-gui.sh:763
+#: git-gui.sh:41 git-gui.sh:688 git-gui.sh:702 git-gui.sh:715 git-gui.sh:798
+#: git-gui.sh:817
 msgid "git-gui: fatal error"
 msgstr "git-gui: errore grave"
 
-#: git-gui.sh:593
+#: git-gui.sh:644
 #, tcl-format
 msgid "Invalid font specified in %s:"
 msgstr "Caratteri non validi specificati in %s:"
 
-#: git-gui.sh:620
+#: git-gui.sh:674
 msgid "Main Font"
 msgstr "Caratteri principali"
 
-#: git-gui.sh:621
+#: git-gui.sh:675
 msgid "Diff/Console Font"
 msgstr "Caratteri per confronti e terminale"
 
-#: git-gui.sh:635
+#: git-gui.sh:689
 msgid "Cannot find git in PATH."
 msgstr "Impossibile trovare git nel PATH"
 
-#: git-gui.sh:662
+#: git-gui.sh:716
 msgid "Cannot parse Git version string:"
 msgstr "Impossibile determinare la versione di Git:"
 
-#: git-gui.sh:680
+#: git-gui.sh:734
 #, tcl-format
 msgid ""
 "Git version cannot be determined.\n"
@@ -62,380 +62,381 @@
 "\n"
 "Assumere che '%s' sia alla versione 1.5.0?\n"
 
-#: git-gui.sh:918
+#: git-gui.sh:972
 msgid "Git directory not found:"
 msgstr "Non trovo la directory di git: "
 
-#: git-gui.sh:925
+#: git-gui.sh:979
 msgid "Cannot move to top of working directory:"
 msgstr "Impossibile spostarsi sulla directory principale del progetto:"
 
-#: git-gui.sh:932
+#: git-gui.sh:986
 msgid "Cannot use funny .git directory:"
 msgstr "Impossibile usare una .git directory strana:"
 
-#: git-gui.sh:937
+#: git-gui.sh:991
 msgid "No working directory"
 msgstr "Nessuna directory di lavoro"
 
-#: git-gui.sh:1084 lib/checkout_op.tcl:283
+#: git-gui.sh:1138 lib/checkout_op.tcl:305
 msgid "Refreshing file status..."
 msgstr "Controllo dello stato dei file in corso..."
 
-#: git-gui.sh:1149
+#: git-gui.sh:1194
 msgid "Scanning for modified files ..."
 msgstr "Ricerca di file modificati in corso..."
 
-#: git-gui.sh:1324 lib/browser.tcl:246
+#: git-gui.sh:1369 lib/browser.tcl:246
 msgid "Ready."
 msgstr "Pronto."
 
-#: git-gui.sh:1590
+#: git-gui.sh:1635
 msgid "Unmodified"
 msgstr "Non modificato"
 
-#: git-gui.sh:1592
+#: git-gui.sh:1637
 msgid "Modified, not staged"
 msgstr "Modificato, non preparato per una nuova revisione"
 
-#: git-gui.sh:1593 git-gui.sh:1598
+#: git-gui.sh:1638 git-gui.sh:1643
 msgid "Staged for commit"
 msgstr "Preparato per una nuova revisione"
 
-#: git-gui.sh:1594 git-gui.sh:1599
+#: git-gui.sh:1639 git-gui.sh:1644
 msgid "Portions staged for commit"
 msgstr "Parti preparate per una nuova revisione"
 
-#: git-gui.sh:1595 git-gui.sh:1600
+#: git-gui.sh:1640 git-gui.sh:1645
 msgid "Staged for commit, missing"
 msgstr "Preparato per una nuova revisione, mancante"
 
-#: git-gui.sh:1597
+#: git-gui.sh:1642
 msgid "Untracked, not staged"
 msgstr "Non tracciato, non preparato per una nuova revisione"
 
-#: git-gui.sh:1602
+#: git-gui.sh:1647
 msgid "Missing"
 msgstr "Mancante"
 
-#: git-gui.sh:1603
+#: git-gui.sh:1648
 msgid "Staged for removal"
 msgstr "Preparato per la rimozione"
 
-#: git-gui.sh:1604
+#: git-gui.sh:1649
 msgid "Staged for removal, still present"
 msgstr "Preparato alla rimozione, ancora presente"
 
-#: git-gui.sh:1606 git-gui.sh:1607 git-gui.sh:1608 git-gui.sh:1609
+#: git-gui.sh:1651 git-gui.sh:1652 git-gui.sh:1653 git-gui.sh:1654
 msgid "Requires merge resolution"
 msgstr "Richiede risoluzione dei conflitti"
 
-#: git-gui.sh:1644
+#: git-gui.sh:1689
 msgid "Starting gitk... please wait..."
 msgstr "Avvio di gitk... attendere..."
 
-#: git-gui.sh:1653
-#, tcl-format
-msgid ""
-"Unable to start gitk:\n"
-"\n"
-"%s does not exist"
-msgstr ""
-"Impossibile avviare gitk:\n"
-"\n"
-"%s non esiste"
+#: git-gui.sh:1698
+msgid "Couldn't find gitk in PATH"
+msgstr "Impossibile trovare gitk nel PATH"
 
-#: git-gui.sh:1860 lib/choose_repository.tcl:36
+#: git-gui.sh:1948 lib/choose_repository.tcl:36
 msgid "Repository"
 msgstr "Archivio"
 
-#: git-gui.sh:1861
+#: git-gui.sh:1949
 msgid "Edit"
 msgstr "Modifica"
 
-#: git-gui.sh:1863 lib/choose_rev.tcl:561
+#: git-gui.sh:1951 lib/choose_rev.tcl:561
 msgid "Branch"
 msgstr "Ramo"
 
-#: git-gui.sh:1866 lib/choose_rev.tcl:548
+#: git-gui.sh:1954 lib/choose_rev.tcl:548
 msgid "Commit@@noun"
 msgstr "Revisione"
 
-#: git-gui.sh:1869 lib/merge.tcl:120 lib/merge.tcl:149 lib/merge.tcl:167
+#: git-gui.sh:1957 lib/merge.tcl:120 lib/merge.tcl:149 lib/merge.tcl:167
 msgid "Merge"
 msgstr "Fusione (Merge)"
 
-#: git-gui.sh:1870 lib/choose_rev.tcl:557
+#: git-gui.sh:1958 lib/choose_rev.tcl:557
 msgid "Remote"
 msgstr "Remoto"
 
-#: git-gui.sh:1879
+#: git-gui.sh:1967
 msgid "Browse Current Branch's Files"
 msgstr "Esplora i file del ramo attuale"
 
-#: git-gui.sh:1883
+#: git-gui.sh:1971
 msgid "Browse Branch Files..."
 msgstr "Esplora i file del ramo..."
 
-#: git-gui.sh:1888
+#: git-gui.sh:1976
 msgid "Visualize Current Branch's History"
 msgstr "Visualizza la cronologia del ramo attuale"
 
-#: git-gui.sh:1892
+#: git-gui.sh:1980
 msgid "Visualize All Branch History"
 msgstr "Visualizza la cronologia di tutti i rami"
 
-#: git-gui.sh:1899
+#: git-gui.sh:1987
 #, tcl-format
 msgid "Browse %s's Files"
 msgstr "Esplora i file di %s"
 
-#: git-gui.sh:1901
+#: git-gui.sh:1989
 #, tcl-format
 msgid "Visualize %s's History"
 msgstr "Visualizza la cronologia di %s"
 
-#: git-gui.sh:1906 lib/database.tcl:27 lib/database.tcl:67
+#: git-gui.sh:1994 lib/database.tcl:27 lib/database.tcl:67
 msgid "Database Statistics"
 msgstr "Statistiche dell'archivio"
 
-#: git-gui.sh:1909 lib/database.tcl:34
+#: git-gui.sh:1997 lib/database.tcl:34
 msgid "Compress Database"
 msgstr "Comprimi l'archivio"
 
-#: git-gui.sh:1912
+#: git-gui.sh:2000
 msgid "Verify Database"
 msgstr "Verifica l'archivio"
 
-#: git-gui.sh:1919 git-gui.sh:1923 git-gui.sh:1927 lib/shortcut.tcl:7
+#: git-gui.sh:2007 git-gui.sh:2011 git-gui.sh:2015 lib/shortcut.tcl:7
 #: lib/shortcut.tcl:39 lib/shortcut.tcl:71
 msgid "Create Desktop Icon"
 msgstr "Crea icona desktop"
 
-#: git-gui.sh:1932 lib/choose_repository.tcl:177 lib/choose_repository.tcl:185
+#: git-gui.sh:2023 lib/choose_repository.tcl:177 lib/choose_repository.tcl:185
 msgid "Quit"
 msgstr "Esci"
 
-#: git-gui.sh:1939
+#: git-gui.sh:2031
 msgid "Undo"
 msgstr "Annulla"
 
-#: git-gui.sh:1942
+#: git-gui.sh:2034
 msgid "Redo"
 msgstr "Ripeti"
 
-#: git-gui.sh:1946 git-gui.sh:2443
+#: git-gui.sh:2038 git-gui.sh:2545
 msgid "Cut"
 msgstr "Taglia"
 
-#: git-gui.sh:1949 git-gui.sh:2446 git-gui.sh:2520 git-gui.sh:2614
+#: git-gui.sh:2041 git-gui.sh:2548 git-gui.sh:2622 git-gui.sh:2715
 #: lib/console.tcl:69
 msgid "Copy"
 msgstr "Copia"
 
-#: git-gui.sh:1952 git-gui.sh:2449
+#: git-gui.sh:2044 git-gui.sh:2551
 msgid "Paste"
 msgstr "Incolla"
 
-#: git-gui.sh:1955 git-gui.sh:2452 lib/branch_delete.tcl:26
+#: git-gui.sh:2047 git-gui.sh:2554 lib/branch_delete.tcl:26
 #: lib/remote_branch_delete.tcl:38
 msgid "Delete"
 msgstr "Elimina"
 
-#: git-gui.sh:1959 git-gui.sh:2456 git-gui.sh:2618 lib/console.tcl:71
+#: git-gui.sh:2051 git-gui.sh:2558 git-gui.sh:2719 lib/console.tcl:71
 msgid "Select All"
 msgstr "Seleziona tutto"
 
-#: git-gui.sh:1968
+#: git-gui.sh:2060
 msgid "Create..."
 msgstr "Crea..."
 
-#: git-gui.sh:1974
+#: git-gui.sh:2066
 msgid "Checkout..."
 msgstr "Attiva..."
 
-#: git-gui.sh:1980
+#: git-gui.sh:2072
 msgid "Rename..."
 msgstr "Rinomina"
 
-#: git-gui.sh:1985 git-gui.sh:2085
+#: git-gui.sh:2077 git-gui.sh:2187
 msgid "Delete..."
 msgstr "Elimina..."
 
-#: git-gui.sh:1990
+#: git-gui.sh:2082
 msgid "Reset..."
 msgstr "Ripristina..."
 
-#: git-gui.sh:2002 git-gui.sh:2389
+#: git-gui.sh:2094 git-gui.sh:2491
 msgid "New Commit"
 msgstr "Nuova revisione"
 
-#: git-gui.sh:2010 git-gui.sh:2396
+#: git-gui.sh:2102 git-gui.sh:2498
 msgid "Amend Last Commit"
 msgstr "Correggi l'ultima revisione"
 
-#: git-gui.sh:2019 git-gui.sh:2356 lib/remote_branch_delete.tcl:99
+#: git-gui.sh:2111 git-gui.sh:2458 lib/remote_branch_delete.tcl:99
 msgid "Rescan"
 msgstr "Analizza nuovamente"
 
-#: git-gui.sh:2025
+#: git-gui.sh:2117
 msgid "Stage To Commit"
 msgstr "Prepara per una nuova revisione"
 
-#: git-gui.sh:2031
+#: git-gui.sh:2123
 msgid "Stage Changed Files To Commit"
 msgstr "Prepara i file modificati per una nuova revisione"
 
-#: git-gui.sh:2037
+#: git-gui.sh:2129
 msgid "Unstage From Commit"
 msgstr "Annulla preparazione"
 
-#: git-gui.sh:2042 lib/index.tcl:395
+#: git-gui.sh:2134 lib/index.tcl:395
 msgid "Revert Changes"
 msgstr "Annulla modifiche"
 
-#: git-gui.sh:2049 git-gui.sh:2368 git-gui.sh:2467
+#: git-gui.sh:2141 git-gui.sh:2702
+msgid "Show Less Context"
+msgstr "Mostra meno contesto"
+
+#: git-gui.sh:2145 git-gui.sh:2706
+msgid "Show More Context"
+msgstr "Mostra più contesto"
+
+#: git-gui.sh:2151 git-gui.sh:2470 git-gui.sh:2569
 msgid "Sign Off"
 msgstr "Sign Off"
 
-#: git-gui.sh:2053 git-gui.sh:2372
+#: git-gui.sh:2155 git-gui.sh:2474
 msgid "Commit@@verb"
 msgstr "Nuova revisione"
 
-#: git-gui.sh:2064
+#: git-gui.sh:2166
 msgid "Local Merge..."
 msgstr "Fusione locale..."
 
-#: git-gui.sh:2069
+#: git-gui.sh:2171
 msgid "Abort Merge..."
 msgstr "Interrompi fusione..."
 
-#: git-gui.sh:2081
+#: git-gui.sh:2183
 msgid "Push..."
 msgstr "Propaga..."
 
-#: git-gui.sh:2092 lib/choose_repository.tcl:41
-msgid "Apple"
-msgstr "Apple"
-
-#: git-gui.sh:2095 git-gui.sh:2117 lib/about.tcl:14
+#: git-gui.sh:2197 git-gui.sh:2219 lib/about.tcl:14
 #: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50
 #, tcl-format
 msgid "About %s"
 msgstr "Informazioni su %s"
 
-#: git-gui.sh:2099
+#: git-gui.sh:2201
 msgid "Preferences..."
 msgstr "Preferenze..."
 
-#: git-gui.sh:2107 git-gui.sh:2639
+#: git-gui.sh:2209 git-gui.sh:2740
 msgid "Options..."
 msgstr "Opzioni..."
 
-#: git-gui.sh:2113 lib/choose_repository.tcl:47
+#: git-gui.sh:2215 lib/choose_repository.tcl:47
 msgid "Help"
 msgstr "Aiuto"
 
-#: git-gui.sh:2154
+#: git-gui.sh:2256
 msgid "Online Documentation"
 msgstr "Documentazione sul web"
 
-#: git-gui.sh:2238
+#: git-gui.sh:2340
 #, tcl-format
 msgid "fatal: cannot stat path %s: No such file or directory"
 msgstr ""
 "errore grave: impossibile effettuare lo stat del path %s: file o directory "
 "non trovata"
 
-#: git-gui.sh:2271
+#: git-gui.sh:2373
 msgid "Current Branch:"
 msgstr "Ramo attuale:"
 
-#: git-gui.sh:2292
+#: git-gui.sh:2394
 msgid "Staged Changes (Will Commit)"
 msgstr "Modifiche preparate (saranno nella nuova revisione)"
 
-#: git-gui.sh:2312
+#: git-gui.sh:2414
 msgid "Unstaged Changes"
 msgstr "Modifiche non preparate"
 
-#: git-gui.sh:2362
+#: git-gui.sh:2464
 msgid "Stage Changed"
 msgstr "Prepara modificati"
 
-#: git-gui.sh:2378 lib/transport.tcl:93 lib/transport.tcl:182
+#: git-gui.sh:2480 lib/transport.tcl:93 lib/transport.tcl:182
 msgid "Push"
 msgstr "Propaga (Push)"
 
-#: git-gui.sh:2408
+#: git-gui.sh:2510
 msgid "Initial Commit Message:"
 msgstr "Messaggio di revisione iniziale:"
 
-#: git-gui.sh:2409
+#: git-gui.sh:2511
 msgid "Amended Commit Message:"
 msgstr "Messaggio di revisione corretto:"
 
-#: git-gui.sh:2410
+#: git-gui.sh:2512
 msgid "Amended Initial Commit Message:"
 msgstr "Messaggio iniziale di revisione corretto:"
 
-#: git-gui.sh:2411
+#: git-gui.sh:2513
 msgid "Amended Merge Commit Message:"
 msgstr "Messaggio di fusione corretto:"
 
-#: git-gui.sh:2412
+#: git-gui.sh:2514
 msgid "Merge Commit Message:"
 msgstr "Messaggio di fusione:"
 
-#: git-gui.sh:2413
+#: git-gui.sh:2515
 msgid "Commit Message:"
 msgstr "Messaggio di revisione:"
 
-#: git-gui.sh:2459 git-gui.sh:2622 lib/console.tcl:73
+#: git-gui.sh:2561 git-gui.sh:2723 lib/console.tcl:73
 msgid "Copy All"
 msgstr "Copia tutto"
 
-#: git-gui.sh:2483 lib/blame.tcl:107
+#: git-gui.sh:2585 lib/blame.tcl:100
 msgid "File:"
 msgstr "File:"
 
-#: git-gui.sh:2589
+#: git-gui.sh:2691
 msgid "Apply/Reverse Hunk"
 msgstr "Applica/Inverti sezione"
 
-#: git-gui.sh:2595
-msgid "Show Less Context"
-msgstr "Mostra meno contesto"
+#: git-gui.sh:2696
+msgid "Apply/Reverse Line"
+msgstr "Applica/Inverti riga"
 
-#: git-gui.sh:2602
-msgid "Show More Context"
-msgstr "Mostra più contesto"
-
-#: git-gui.sh:2610
+#: git-gui.sh:2711
 msgid "Refresh"
 msgstr "Rinfresca"
 
-#: git-gui.sh:2631
+#: git-gui.sh:2732
 msgid "Decrease Font Size"
 msgstr "Diminuisci dimensione caratteri"
 
-#: git-gui.sh:2635
+#: git-gui.sh:2736
 msgid "Increase Font Size"
 msgstr "Aumenta dimensione caratteri"
 
-#: git-gui.sh:2646
+#: git-gui.sh:2747
 msgid "Unstage Hunk From Commit"
-msgstr "Sezione non preparata per una nuova revisione"
+msgstr "Annulla preparazione della sezione per una nuova revisione"
 
-#: git-gui.sh:2648
+#: git-gui.sh:2748
+msgid "Unstage Line From Commit"
+msgstr "Annulla preparazione della linea per una nuova revisione"
+
+#: git-gui.sh:2750
 msgid "Stage Hunk For Commit"
 msgstr "Prepara sezione per una nuova revisione"
 
-#: git-gui.sh:2667
+#: git-gui.sh:2751
+msgid "Stage Line For Commit"
+msgstr "Prepara linea per una nuova revisione"
+
+#: git-gui.sh:2771
 msgid "Initializing..."
 msgstr "Inizializzazione..."
 
-#: git-gui.sh:2762
+#: git-gui.sh:2876
 #, tcl-format
 msgid ""
 "Possible environment issues exist.\n"
@@ -452,7 +453,7 @@
 "da %s:\n"
 "\n"
 
-#: git-gui.sh:2792
+#: git-gui.sh:2906
 msgid ""
 "\n"
 "This is due to a known issue with the\n"
@@ -462,7 +463,7 @@
 "Ciò è dovuto a un problema conosciuto\n"
 "causato dall'eseguibile Tcl distribuito da Cygwin."
 
-#: git-gui.sh:2797
+#: git-gui.sh:2911
 #, tcl-format
 msgid ""
 "\n"
@@ -482,64 +483,80 @@
 msgid "git-gui - a graphical user interface for Git."
 msgstr "git-gui - un'interfaccia grafica per Git."
 
-#: lib/blame.tcl:77
+#: lib/blame.tcl:70
 msgid "File Viewer"
 msgstr "Mostra file"
 
-#: lib/blame.tcl:81
+#: lib/blame.tcl:74
 msgid "Commit:"
 msgstr "Revisione:"
 
-#: lib/blame.tcl:264
+#: lib/blame.tcl:257
 msgid "Copy Commit"
 msgstr "Copia revisione"
 
-#: lib/blame.tcl:384
+#: lib/blame.tcl:260
+msgid "Do Full Copy Detection"
+msgstr "Ricerca accurata delle copie"
+
+#: lib/blame.tcl:388
 #, tcl-format
 msgid "Reading %s..."
 msgstr "Lettura di %s..."
 
-#: lib/blame.tcl:488
+#: lib/blame.tcl:492
 msgid "Loading copy/move tracking annotations..."
 msgstr "Caricamento annotazioni per copie/spostamenti..."
 
-#: lib/blame.tcl:508
+#: lib/blame.tcl:512
 msgid "lines annotated"
 msgstr "linee annotate"
 
-#: lib/blame.tcl:689
+#: lib/blame.tcl:704
 msgid "Loading original location annotations..."
 msgstr "Caricamento annotazioni per posizione originaria..."
 
-#: lib/blame.tcl:692
+#: lib/blame.tcl:707
 msgid "Annotation complete."
 msgstr "Annotazione completata."
 
-#: lib/blame.tcl:746
+#: lib/blame.tcl:737
+msgid "Busy"
+msgstr "Occupato"
+
+#: lib/blame.tcl:738
+msgid "Annotation process is already running."
+msgstr "Il processo di annotazione è già in corso."
+
+#: lib/blame.tcl:777
+msgid "Running thorough copy detection..."
+msgstr "Ricerca accurata delle copie in corso..."
+
+#: lib/blame.tcl:827
 msgid "Loading annotation..."
 msgstr "Caricamento annotazioni..."
 
-#: lib/blame.tcl:802
+#: lib/blame.tcl:883
 msgid "Author:"
 msgstr "Autore:"
 
-#: lib/blame.tcl:806
+#: lib/blame.tcl:887
 msgid "Committer:"
 msgstr "Revisione creata da:"
 
-#: lib/blame.tcl:811
+#: lib/blame.tcl:892
 msgid "Original File:"
 msgstr "File originario:"
 
-#: lib/blame.tcl:925
+#: lib/blame.tcl:1006
 msgid "Originally By:"
 msgstr "In origine da:"
 
-#: lib/blame.tcl:931
+#: lib/blame.tcl:1012
 msgid "In File:"
 msgstr "Nel file:"
 
-#: lib/blame.tcl:936
+#: lib/blame.tcl:1017
 msgid "Copied Or Moved Here By:"
 msgstr "Copiato o spostato qui da:"
 
@@ -553,7 +570,7 @@
 
 #: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35
 #: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:282
-#: lib/checkout_op.tcl:522 lib/choose_font.tcl:43 lib/merge.tcl:171
+#: lib/checkout_op.tcl:544 lib/choose_font.tcl:43 lib/merge.tcl:171
 #: lib/option.tcl:103 lib/remote_branch_delete.tcl:42 lib/transport.tcl:97
 msgid "Cancel"
 msgstr "Annulla"
@@ -562,7 +579,7 @@
 msgid "Revision"
 msgstr "Revisione"
 
-#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:242
+#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:244
 msgid "Options"
 msgstr "Opzioni"
 
@@ -614,7 +631,7 @@
 msgid "Fast Forward Only"
 msgstr "Solo fast forward"
 
-#: lib/branch_create.tcl:85 lib/checkout_op.tcl:514
+#: lib/branch_create.tcl:85 lib/checkout_op.tcl:536
 msgid "Reset"
 msgstr "Ripristina"
 
@@ -705,7 +722,7 @@
 msgid "Please select a branch to rename."
 msgstr "Scegliere un ramo da rinominare."
 
-#: lib/branch_rename.tcl:96 lib/checkout_op.tcl:179
+#: lib/branch_rename.tcl:96 lib/checkout_op.tcl:201
 #, tcl-format
 msgid "Branch '%s' already exists."
 msgstr "Il ramo '%s' esiste già."
@@ -737,31 +754,36 @@
 msgstr "Esplora i file del ramo"
 
 #: lib/browser.tcl:278 lib/choose_repository.tcl:387
-#: lib/choose_repository.tcl:474 lib/choose_repository.tcl:484
-#: lib/choose_repository.tcl:987
+#: lib/choose_repository.tcl:472 lib/choose_repository.tcl:482
+#: lib/choose_repository.tcl:985
 msgid "Browse"
 msgstr "Esplora"
 
-#: lib/checkout_op.tcl:79
+#: lib/checkout_op.tcl:84
 #, tcl-format
 msgid "Fetching %s from %s"
 msgstr "Recupero %s da %s"
 
-#: lib/checkout_op.tcl:127
+#: lib/checkout_op.tcl:132
 #, tcl-format
 msgid "fatal: Cannot resolve %s"
 msgstr "errore grave: impossibile risolvere %s"
 
-#: lib/checkout_op.tcl:140 lib/console.tcl:81 lib/database.tcl:31
+#: lib/checkout_op.tcl:145 lib/console.tcl:81 lib/database.tcl:31
 msgid "Close"
 msgstr "Chiudi"
 
-#: lib/checkout_op.tcl:169
+#: lib/checkout_op.tcl:174
 #, tcl-format
 msgid "Branch '%s' does not exist."
 msgstr "Il ramo '%s' non esiste."
 
-#: lib/checkout_op.tcl:206
+#: lib/checkout_op.tcl:193
+#, tcl-format
+msgid "Failed to configure simplified git-pull for '%s'."
+msgstr "Impossibile configurare git-pull semplificato per '%s'."
+
+#: lib/checkout_op.tcl:228
 #, tcl-format
 msgid ""
 "Branch '%s' already exists.\n"
@@ -774,22 +796,22 @@
 "Non può effettuare un 'fast-forward' a %s.\n"
 "E' necessaria una fusione."
 
-#: lib/checkout_op.tcl:220
+#: lib/checkout_op.tcl:242
 #, tcl-format
 msgid "Merge strategy '%s' not supported."
 msgstr "La strategia di fusione '%s' non è supportata."
 
-#: lib/checkout_op.tcl:239
+#: lib/checkout_op.tcl:261
 #, tcl-format
 msgid "Failed to update '%s'."
 msgstr "Impossibile aggiornare '%s'."
 
-#: lib/checkout_op.tcl:251
+#: lib/checkout_op.tcl:273
 msgid "Staging area (index) is already locked."
 msgstr ""
 "L'area di preparazione per una nuova revisione (indice) è già bloccata."
 
-#: lib/checkout_op.tcl:266
+#: lib/checkout_op.tcl:288
 msgid ""
 "Last scanned state does not match repository state.\n"
 "\n"
@@ -806,30 +828,30 @@
 "\n"
 "La nuova analisi comincerà ora.\n"
 
-#: lib/checkout_op.tcl:322
+#: lib/checkout_op.tcl:344
 #, tcl-format
 msgid "Updating working directory to '%s'..."
 msgstr "Aggiornamento della directory di lavoro a '%s' in corso..."
 
-#: lib/checkout_op.tcl:323
+#: lib/checkout_op.tcl:345
 msgid "files checked out"
 msgstr "file presenti nella directory di lavoro"
 
-#: lib/checkout_op.tcl:353
+#: lib/checkout_op.tcl:375
 #, tcl-format
 msgid "Aborted checkout of '%s' (file level merging is required)."
 msgstr "Attivazione di '%s' fallita (richiesta una fusione a livello file)."
 
-#: lib/checkout_op.tcl:354
+#: lib/checkout_op.tcl:376
 msgid "File level merge required."
 msgstr "E' richiesta una fusione a livello file."
 
-#: lib/checkout_op.tcl:358
+#: lib/checkout_op.tcl:380
 #, tcl-format
 msgid "Staying on branch '%s'."
 msgstr "Si rimarrà sul ramo '%s'."
 
-#: lib/checkout_op.tcl:429
+#: lib/checkout_op.tcl:451
 msgid ""
 "You are no longer on a local branch.\n"
 "\n"
@@ -841,31 +863,31 @@
 "Se si vuole rimanere su un ramo, crearne uno ora a partire da 'Questa "
 "revisione attiva staccata'."
 
-#: lib/checkout_op.tcl:446 lib/checkout_op.tcl:450
+#: lib/checkout_op.tcl:468 lib/checkout_op.tcl:472
 #, tcl-format
 msgid "Checked out '%s'."
 msgstr "Attivazione di '%s' completata."
 
-#: lib/checkout_op.tcl:478
+#: lib/checkout_op.tcl:500
 #, tcl-format
 msgid "Resetting '%s' to '%s' will lose the following commits:"
 msgstr ""
 "Ripristinare '%s' a '%s' comporterà la perdita delle seguenti revisioni:"
 
-#: lib/checkout_op.tcl:500
+#: lib/checkout_op.tcl:522
 msgid "Recovering lost commits may not be easy."
 msgstr "Ricomporre le revisioni perdute potrebbe non essere semplice."
 
-#: lib/checkout_op.tcl:505
+#: lib/checkout_op.tcl:527
 #, tcl-format
 msgid "Reset '%s'?"
 msgstr "Ripristinare '%s'?"
 
-#: lib/checkout_op.tcl:510 lib/merge.tcl:163
+#: lib/checkout_op.tcl:532 lib/merge.tcl:163
 msgid "Visualize"
 msgstr "Visualizza"
 
-#: lib/checkout_op.tcl:578
+#: lib/checkout_op.tcl:600
 #, tcl-format
 msgid ""
 "Failed to set current branch.\n"
@@ -919,7 +941,7 @@
 msgid "New..."
 msgstr "Nuovo..."
 
-#: lib/choose_repository.tcl:94 lib/choose_repository.tcl:460
+#: lib/choose_repository.tcl:94 lib/choose_repository.tcl:458
 msgid "Clone Existing Repository"
 msgstr "Clona archivio esistente"
 
@@ -927,7 +949,7 @@
 msgid "Clone..."
 msgstr "Clona..."
 
-#: lib/choose_repository.tcl:107 lib/choose_repository.tcl:976
+#: lib/choose_repository.tcl:107 lib/choose_repository.tcl:974
 msgid "Open Existing Repository"
 msgstr "Apri archivio esistente"
 
@@ -949,188 +971,188 @@
 msgid "Failed to create repository %s:"
 msgstr "Impossibile creare l'archivio %s:"
 
-#: lib/choose_repository.tcl:381 lib/choose_repository.tcl:478
+#: lib/choose_repository.tcl:381 lib/choose_repository.tcl:476
 msgid "Directory:"
 msgstr "Directory:"
 
-#: lib/choose_repository.tcl:412 lib/choose_repository.tcl:537
-#: lib/choose_repository.tcl:1011
+#: lib/choose_repository.tcl:410 lib/choose_repository.tcl:535
+#: lib/choose_repository.tcl:1007
 msgid "Git Repository"
 msgstr "Archivio Git"
 
-#: lib/choose_repository.tcl:437
+#: lib/choose_repository.tcl:435
 #, tcl-format
 msgid "Directory %s already exists."
 msgstr "La directory %s esiste già."
 
-#: lib/choose_repository.tcl:441
+#: lib/choose_repository.tcl:439
 #, tcl-format
 msgid "File %s already exists."
 msgstr "Il file %s esiste già."
 
-#: lib/choose_repository.tcl:455
+#: lib/choose_repository.tcl:453
 msgid "Clone"
 msgstr "Clona"
 
-#: lib/choose_repository.tcl:468
+#: lib/choose_repository.tcl:466
 msgid "URL:"
 msgstr "URL:"
 
-#: lib/choose_repository.tcl:489
+#: lib/choose_repository.tcl:487
 msgid "Clone Type:"
 msgstr "Tipo di clone:"
 
-#: lib/choose_repository.tcl:495
+#: lib/choose_repository.tcl:493
 msgid "Standard (Fast, Semi-Redundant, Hardlinks)"
 msgstr "Standard (veloce, semi-ridondante, con hardlink)"
 
-#: lib/choose_repository.tcl:501
+#: lib/choose_repository.tcl:499
 msgid "Full Copy (Slower, Redundant Backup)"
 msgstr "Copia completa (più lento, backup ridondante)"
 
-#: lib/choose_repository.tcl:507
+#: lib/choose_repository.tcl:505
 msgid "Shared (Fastest, Not Recommended, No Backup)"
 msgstr "Shared (il più veloce, non raccomandato, nessun backup)"
 
-#: lib/choose_repository.tcl:543 lib/choose_repository.tcl:590
-#: lib/choose_repository.tcl:736 lib/choose_repository.tcl:806
-#: lib/choose_repository.tcl:1017 lib/choose_repository.tcl:1025
+#: lib/choose_repository.tcl:541 lib/choose_repository.tcl:588
+#: lib/choose_repository.tcl:734 lib/choose_repository.tcl:804
+#: lib/choose_repository.tcl:1013 lib/choose_repository.tcl:1021
 #, tcl-format
 msgid "Not a Git repository: %s"
 msgstr "%s non è un archivio Git."
 
-#: lib/choose_repository.tcl:579
+#: lib/choose_repository.tcl:577
 msgid "Standard only available for local repository."
 msgstr "Standard è disponibile solo per archivi locali."
 
-#: lib/choose_repository.tcl:583
+#: lib/choose_repository.tcl:581
 msgid "Shared only available for local repository."
 msgstr "Shared è disponibile solo per archivi locali."
 
-#: lib/choose_repository.tcl:604
+#: lib/choose_repository.tcl:602
 #, tcl-format
 msgid "Location %s already exists."
 msgstr "Il file/directory %s esiste già."
 
-#: lib/choose_repository.tcl:615
+#: lib/choose_repository.tcl:613
 msgid "Failed to configure origin"
 msgstr "Impossibile configurare origin"
 
-#: lib/choose_repository.tcl:627
+#: lib/choose_repository.tcl:625
 msgid "Counting objects"
 msgstr "Calcolo oggetti"
 
-#: lib/choose_repository.tcl:628
+#: lib/choose_repository.tcl:626
 msgid "buckets"
 msgstr ""
 
-#: lib/choose_repository.tcl:652
+#: lib/choose_repository.tcl:650
 #, tcl-format
 msgid "Unable to copy objects/info/alternates: %s"
 msgstr "Impossibile copiare oggetti/info/alternate: %s"
 
-#: lib/choose_repository.tcl:688
+#: lib/choose_repository.tcl:686
 #, tcl-format
 msgid "Nothing to clone from %s."
 msgstr "Niente da clonare da %s."
 
-#: lib/choose_repository.tcl:690 lib/choose_repository.tcl:904
-#: lib/choose_repository.tcl:916
+#: lib/choose_repository.tcl:688 lib/choose_repository.tcl:902
+#: lib/choose_repository.tcl:914
 msgid "The 'master' branch has not been initialized."
 msgstr "Il ramo 'master' non è stato inizializzato."
 
-#: lib/choose_repository.tcl:703
+#: lib/choose_repository.tcl:701
 msgid "Hardlinks are unavailable.  Falling back to copying."
 msgstr "Impossibile utilizzare gli hardlink. Si ricorrerà alla copia."
 
-#: lib/choose_repository.tcl:715
+#: lib/choose_repository.tcl:713
 #, tcl-format
 msgid "Cloning from %s"
 msgstr "Clonazione da %s"
 
-#: lib/choose_repository.tcl:746
+#: lib/choose_repository.tcl:744
 msgid "Copying objects"
 msgstr "Copia degli oggetti"
 
-#: lib/choose_repository.tcl:747
+#: lib/choose_repository.tcl:745
 msgid "KiB"
 msgstr "KiB"
 
-#: lib/choose_repository.tcl:771
+#: lib/choose_repository.tcl:769
 #, tcl-format
 msgid "Unable to copy object: %s"
 msgstr "Impossibile copiare oggetto: %s"
 
-#: lib/choose_repository.tcl:781
+#: lib/choose_repository.tcl:779
 msgid "Linking objects"
 msgstr "Collegamento oggetti"
 
-#: lib/choose_repository.tcl:782
+#: lib/choose_repository.tcl:780
 msgid "objects"
 msgstr "oggetti"
 
-#: lib/choose_repository.tcl:790
+#: lib/choose_repository.tcl:788
 #, tcl-format
 msgid "Unable to hardlink object: %s"
 msgstr "Hardlink impossibile sull'oggetto: %s"
 
-#: lib/choose_repository.tcl:845
+#: lib/choose_repository.tcl:843
 msgid "Cannot fetch branches and objects.  See console output for details."
 msgstr ""
 "Impossibile recuperare rami e oggetti. Controllare i dettagli forniti dalla "
 "console."
 
-#: lib/choose_repository.tcl:856
+#: lib/choose_repository.tcl:854
 msgid "Cannot fetch tags.  See console output for details."
 msgstr ""
 "Impossibile recuperare le etichette. Controllare i dettagli forniti dalla "
 "console."
 
-#: lib/choose_repository.tcl:880
+#: lib/choose_repository.tcl:878
 msgid "Cannot determine HEAD.  See console output for details."
 msgstr ""
 "Impossibile determinare HEAD. Controllare i dettagli forniti dalla console."
 
-#: lib/choose_repository.tcl:889
+#: lib/choose_repository.tcl:887
 #, tcl-format
 msgid "Unable to cleanup %s"
 msgstr "Impossibile ripulire %s"
 
-#: lib/choose_repository.tcl:895
+#: lib/choose_repository.tcl:893
 msgid "Clone failed."
 msgstr "Clonazione non riuscita."
 
-#: lib/choose_repository.tcl:902
+#: lib/choose_repository.tcl:900
 msgid "No default branch obtained."
 msgstr "Non è stato trovato un ramo predefinito."
 
-#: lib/choose_repository.tcl:913
+#: lib/choose_repository.tcl:911
 #, tcl-format
 msgid "Cannot resolve %s as a commit."
 msgstr "Impossibile risolvere %s come una revisione."
 
-#: lib/choose_repository.tcl:925
+#: lib/choose_repository.tcl:923
 msgid "Creating working directory"
 msgstr "Creazione directory di lavoro"
 
-#: lib/choose_repository.tcl:926 lib/index.tcl:65 lib/index.tcl:127
+#: lib/choose_repository.tcl:924 lib/index.tcl:65 lib/index.tcl:127
 #: lib/index.tcl:193
 msgid "files"
 msgstr "file"
 
-#: lib/choose_repository.tcl:955
+#: lib/choose_repository.tcl:953
 msgid "Initial file checkout failed."
 msgstr "Attivazione iniziale non riuscita."
 
-#: lib/choose_repository.tcl:971
+#: lib/choose_repository.tcl:969
 msgid "Open"
 msgstr "Apri"
 
-#: lib/choose_repository.tcl:981
+#: lib/choose_repository.tcl:979
 msgid "Repository:"
 msgstr "Archivio:"
 
-#: lib/choose_repository.tcl:1031
+#: lib/choose_repository.tcl:1027
 #, tcl-format
 msgid "Failed to open repository %s:"
 msgstr "Impossibile accedere all'archivio %s:"
@@ -1423,7 +1445,7 @@
 msgid "Invalid date from Git: %s"
 msgstr "Git ha restituito una data non valida: %s"
 
-#: lib/diff.tcl:42
+#: lib/diff.tcl:44
 #, tcl-format
 msgid ""
 "No differences detected.\n"
@@ -1446,40 +1468,48 @@
 "Si procederà automaticamente ad una nuova analisi per trovare altri file che "
 "potrebbero avere lo stesso stato."
 
-#: lib/diff.tcl:81
+#: lib/diff.tcl:83
 #, tcl-format
 msgid "Loading diff of %s..."
 msgstr "Caricamento delle differenze di %s..."
 
-#: lib/diff.tcl:114 lib/diff.tcl:184
+#: lib/diff.tcl:116 lib/diff.tcl:190
 #, tcl-format
 msgid "Unable to display %s"
 msgstr "Impossibile visualizzare %s"
 
-#: lib/diff.tcl:115
+#: lib/diff.tcl:117
 msgid "Error loading file:"
 msgstr "Errore nel caricamento del file:"
 
-#: lib/diff.tcl:122
+#: lib/diff.tcl:124
 msgid "Git Repository (subproject)"
 msgstr "Archivio Git (sottoprogetto)"
 
-#: lib/diff.tcl:134
+#: lib/diff.tcl:136
 msgid "* Binary file (not showing content)."
 msgstr "* File binario (il contenuto non sarà mostrato)."
 
-#: lib/diff.tcl:185
+#: lib/diff.tcl:191
 msgid "Error loading diff:"
 msgstr "Errore nel caricamento delle differenze:"
 
-#: lib/diff.tcl:303
+#: lib/diff.tcl:313
 msgid "Failed to unstage selected hunk."
 msgstr "Impossibile rimuovere la sezione scelta dalla nuova revisione."
 
-#: lib/diff.tcl:310
+#: lib/diff.tcl:320
 msgid "Failed to stage selected hunk."
 msgstr "Impossibile preparare la sezione scelta per una nuova revisione."
 
+#: lib/diff.tcl:386
+msgid "Failed to unstage selected line."
+msgstr "Impossibile rimuovere la riga scelta dalla nuova revisione."
+
+#: lib/diff.tcl:394
+msgid "Failed to stage selected line."
+msgstr "Impossibile preparare la riga scelta per una nuova revisione."
+
 #: lib/error.tcl:20 lib/error.tcl:114
 msgid "error"
 msgstr "errore"
@@ -1689,11 +1719,11 @@
 msgid "files reset"
 msgstr "ripristino file"
 
-#: lib/merge.tcl:265
+#: lib/merge.tcl:266
 msgid "Abort failed."
 msgstr "Interruzione non riuscita."
 
-#: lib/merge.tcl:267
+#: lib/merge.tcl:268
 msgid "Abort completed.  Ready."
 msgstr "Interruzione completata. Pronto."
 
@@ -1748,42 +1778,62 @@
 msgstr "Appaia duplicati locali di rami remoti"
 
 #: lib/option.tcl:126
+msgid "Blame Copy Only On Changed Files"
+msgstr "Ricerca copie solo nei file modificati"
+
+#: lib/option.tcl:127
+msgid "Minimum Letters To Blame Copy On"
+msgstr "Numero minimo di lettere che attivano la ricerca delle copie"
+
+#: lib/option.tcl:128
 msgid "Number of Diff Context Lines"
 msgstr "Numero di linee di contesto nelle differenze"
 
-#: lib/option.tcl:127
+#: lib/option.tcl:129
 msgid "Commit Message Text Width"
 msgstr "Larghezza del messaggio di revisione"
 
-#: lib/option.tcl:128
+#: lib/option.tcl:130
 msgid "New Branch Name Template"
 msgstr "Modello per il nome di un nuovo ramo"
 
-#: lib/option.tcl:192
+#: lib/option.tcl:194
 msgid "Spelling Dictionary:"
 msgstr "Lingua dizionario:"
 
-#: lib/option.tcl:216
+#: lib/option.tcl:218
 msgid "Change Font"
 msgstr "Cambia caratteri"
 
-#: lib/option.tcl:220
+#: lib/option.tcl:222
 #, tcl-format
 msgid "Choose %s"
 msgstr "Scegli %s"
 
-#: lib/option.tcl:226
+#: lib/option.tcl:228
 msgid "pt."
 msgstr "pt."
 
-#: lib/option.tcl:240
+#: lib/option.tcl:242
 msgid "Preferences"
 msgstr "Preferenze"
 
-#: lib/option.tcl:275
+#: lib/option.tcl:277
 msgid "Failed to completely save options:"
 msgstr "Impossibile salvare completamente le opzioni:"
 
+#: lib/remote.tcl:165
+msgid "Prune from"
+msgstr "Effettua potatura da"
+
+#: lib/remote.tcl:170
+msgid "Fetch from"
+msgstr "Recupera da"
+
+#: lib/remote.tcl:213
+msgid "Push to"
+msgstr "Propaga verso"
+
 #: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34
 msgid "Delete Remote Branch"
 msgstr "Cancella ramo remoto"
@@ -1868,18 +1918,6 @@
 msgid "Scanning %s..."
 msgstr "Analisi in corso %s..."
 
-#: lib/remote.tcl:165
-msgid "Prune from"
-msgstr "Effettua potatura da"
-
-#: lib/remote.tcl:170
-msgid "Fetch from"
-msgstr "Recupera da"
-
-#: lib/remote.tcl:213
-msgid "Push to"
-msgstr "Propaga verso"
-
 #: lib/shortcut.tcl:20 lib/shortcut.tcl:61
 msgid "Cannot write shortcut:"
 msgstr "Impossibile scrivere shortcut:"
@@ -1911,17 +1949,17 @@
 
 #: lib/spellcheck.tcl:80
 msgid "Unrecognized spell checker"
-msgstr "Correttore ortografico sconosciuto"
+msgstr "Correttore ortografico non riconosciuto"
 
-#: lib/spellcheck.tcl:180
+#: lib/spellcheck.tcl:186
 msgid "No Suggestions"
 msgstr "Nessun suggerimento"
 
-#: lib/spellcheck.tcl:381
+#: lib/spellcheck.tcl:387
 msgid "Unexpected EOF from spell checker"
 msgstr "Il correttore ortografico ha mandato un EOF inaspettato"
 
-#: lib/spellcheck.tcl:385
+#: lib/spellcheck.tcl:391
 msgid "Spell Checker Failed"
 msgstr "Errore nel correttore ortografico"
 
diff --git a/git-gui/po/ja.po b/git-gui/po/ja.po
index 28e6d62..5db44a4 100644
--- a/git-gui/po/ja.po
+++ b/git-gui/po/ja.po
@@ -8,41 +8,41 @@
 msgstr ""
 "Project-Id-Version: git-gui\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-03-14 07:18+0100\n"
-"PO-Revision-Date: 2008-03-15 20:12+0900\n"
-"Last-Translator: しらいし ななこ <nanako3@bluebottle.com>\n"
+"POT-Creation-Date: 2008-08-02 14:45-0700\n"
+"PO-Revision-Date: 2008-08-03 17:00+0900\n"
+"Last-Translator: しらいし ななこ <nanako3@lavabit.com>\n"
 "Language-Team: Japanese\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: git-gui.sh:41 git-gui.sh:634 git-gui.sh:648 git-gui.sh:661 git-gui.sh:744
-#: git-gui.sh:763
+#: git-gui.sh:41 git-gui.sh:688 git-gui.sh:702 git-gui.sh:715 git-gui.sh:798
+#: git-gui.sh:817
 msgid "git-gui: fatal error"
 msgstr "git-gui: 致命的なエラー"
 
-#: git-gui.sh:593
+#: git-gui.sh:644
 #, tcl-format
 msgid "Invalid font specified in %s:"
 msgstr "%s に無効なフォントが指定されています:"
 
-#: git-gui.sh:620
+#: git-gui.sh:674
 msgid "Main Font"
 msgstr "主フォント"
 
-#: git-gui.sh:621
+#: git-gui.sh:675
 msgid "Diff/Console Font"
 msgstr "diff/コンソール・フォント"
 
-#: git-gui.sh:635
+#: git-gui.sh:689
 msgid "Cannot find git in PATH."
 msgstr "PATH 中に git が見つかりません"
 
-#: git-gui.sh:662
+#: git-gui.sh:716
 msgid "Cannot parse Git version string:"
 msgstr "Git バージョン名が理解できません:"
 
-#: git-gui.sh:680
+#: git-gui.sh:734
 #, tcl-format
 msgid ""
 "Git version cannot be determined.\n"
@@ -61,380 +61,381 @@
 "\n"
 "'%s' はバージョン 1.5.0 と思って良いですか?\n"
 
-#: git-gui.sh:918
+#: git-gui.sh:972
 msgid "Git directory not found:"
 msgstr "Git ディレクトリが見つかりません:"
 
-#: git-gui.sh:925
+#: git-gui.sh:979
 msgid "Cannot move to top of working directory:"
 msgstr "作業ディレクトリの最上位に移動できません"
 
-#: git-gui.sh:932
+#: git-gui.sh:986
 msgid "Cannot use funny .git directory:"
 msgstr "変な .git ディレクトリは使えません"
 
-#: git-gui.sh:937
+#: git-gui.sh:991
 msgid "No working directory"
 msgstr "作業ディレクトリがありません"
 
-#: git-gui.sh:1084 lib/checkout_op.tcl:283
+#: git-gui.sh:1138 lib/checkout_op.tcl:305
 msgid "Refreshing file status..."
 msgstr "ファイル状態を更新しています…"
 
-#: git-gui.sh:1149
+#: git-gui.sh:1194
 msgid "Scanning for modified files ..."
 msgstr "変更されたファイルをスキャンしています…"
 
-#: git-gui.sh:1324 lib/browser.tcl:246
+#: git-gui.sh:1369 lib/browser.tcl:246
 msgid "Ready."
 msgstr "準備完了"
 
-#: git-gui.sh:1590
+#: git-gui.sh:1635
 msgid "Unmodified"
 msgstr "変更無し"
 
-#: git-gui.sh:1592
+#: git-gui.sh:1637
 msgid "Modified, not staged"
 msgstr "変更あり、コミット未予定"
 
-#: git-gui.sh:1593 git-gui.sh:1598
+#: git-gui.sh:1638 git-gui.sh:1643
 msgid "Staged for commit"
 msgstr "コミット予定済"
 
-#: git-gui.sh:1594 git-gui.sh:1599
+#: git-gui.sh:1639 git-gui.sh:1644
 msgid "Portions staged for commit"
 msgstr "部分的にコミット予定済"
 
-#: git-gui.sh:1595 git-gui.sh:1600
+#: git-gui.sh:1640 git-gui.sh:1645
 msgid "Staged for commit, missing"
 msgstr "コミット予定済、ファイル無し"
 
-#: git-gui.sh:1597
+#: git-gui.sh:1642
 msgid "Untracked, not staged"
 msgstr "管理外、コミット未予定"
 
-#: git-gui.sh:1602
+#: git-gui.sh:1647
 msgid "Missing"
 msgstr "ファイル無し"
 
-#: git-gui.sh:1603
+#: git-gui.sh:1648
 msgid "Staged for removal"
 msgstr "削除予定済"
 
-#: git-gui.sh:1604
+#: git-gui.sh:1649
 msgid "Staged for removal, still present"
 msgstr "削除予定済、ファイル未削除"
 
-#: git-gui.sh:1606 git-gui.sh:1607 git-gui.sh:1608 git-gui.sh:1609
+#: git-gui.sh:1651 git-gui.sh:1652 git-gui.sh:1653 git-gui.sh:1654
 msgid "Requires merge resolution"
 msgstr "要マージ解決"
 
-#: git-gui.sh:1644
+#: git-gui.sh:1689
 msgid "Starting gitk... please wait..."
 msgstr "gitk を起動中…お待ち下さい…"
 
-#: git-gui.sh:1653
-#, tcl-format
-msgid ""
-"Unable to start gitk:\n"
-"\n"
-"%s does not exist"
-msgstr ""
-"gitk を起動できません:\n"
-"\n"
-"%s がありません"
+#: git-gui.sh:1698
+msgid "Couldn't find gitk in PATH"
+msgstr "PATH 中に gitk が見つかりません"
 
-#: git-gui.sh:1860 lib/choose_repository.tcl:36
+#: git-gui.sh:1948 lib/choose_repository.tcl:36
 msgid "Repository"
 msgstr "リポジトリ"
 
-#: git-gui.sh:1861
+#: git-gui.sh:1949
 msgid "Edit"
 msgstr "編集"
 
-#: git-gui.sh:1863 lib/choose_rev.tcl:561
+#: git-gui.sh:1951 lib/choose_rev.tcl:561
 msgid "Branch"
 msgstr "ブランチ"
 
-#: git-gui.sh:1866 lib/choose_rev.tcl:548
+#: git-gui.sh:1954 lib/choose_rev.tcl:548
 msgid "Commit@@noun"
 msgstr "コミット"
 
-#: git-gui.sh:1869 lib/merge.tcl:120 lib/merge.tcl:149 lib/merge.tcl:167
+#: git-gui.sh:1957 lib/merge.tcl:120 lib/merge.tcl:149 lib/merge.tcl:167
 msgid "Merge"
 msgstr "マージ"
 
-#: git-gui.sh:1870 lib/choose_rev.tcl:557
+#: git-gui.sh:1958 lib/choose_rev.tcl:557
 msgid "Remote"
 msgstr "リモート"
 
-#: git-gui.sh:1879
+#: git-gui.sh:1967
 msgid "Browse Current Branch's Files"
 msgstr "現在のブランチのファイルを見る"
 
-#: git-gui.sh:1883
+#: git-gui.sh:1971
 msgid "Browse Branch Files..."
 msgstr "ブランチのファイルを見る…"
 
-#: git-gui.sh:1888
+#: git-gui.sh:1976
 msgid "Visualize Current Branch's History"
 msgstr "現在のブランチの履歴を見る"
 
-#: git-gui.sh:1892
+#: git-gui.sh:1980
 msgid "Visualize All Branch History"
 msgstr "全てのブランチの履歴を見る"
 
-#: git-gui.sh:1899
+#: git-gui.sh:1987
 #, tcl-format
 msgid "Browse %s's Files"
 msgstr "ブランチ %s のファイルを見る"
 
-#: git-gui.sh:1901
+#: git-gui.sh:1989
 #, tcl-format
 msgid "Visualize %s's History"
 msgstr "ブランチ %s の履歴を見る"
 
-#: git-gui.sh:1906 lib/database.tcl:27 lib/database.tcl:67
+#: git-gui.sh:1994 lib/database.tcl:27 lib/database.tcl:67
 msgid "Database Statistics"
 msgstr "データベース統計"
 
-#: git-gui.sh:1909 lib/database.tcl:34
+#: git-gui.sh:1997 lib/database.tcl:34
 msgid "Compress Database"
 msgstr "データベース圧縮"
 
-#: git-gui.sh:1912
+#: git-gui.sh:2000
 msgid "Verify Database"
 msgstr "データベース検証"
 
-#: git-gui.sh:1919 git-gui.sh:1923 git-gui.sh:1927 lib/shortcut.tcl:7
+#: git-gui.sh:2007 git-gui.sh:2011 git-gui.sh:2015 lib/shortcut.tcl:7
 #: lib/shortcut.tcl:39 lib/shortcut.tcl:71
 msgid "Create Desktop Icon"
 msgstr "デスクトップ・アイコンを作る"
 
-#: git-gui.sh:1932 lib/choose_repository.tcl:177 lib/choose_repository.tcl:185
+#: git-gui.sh:2023 lib/choose_repository.tcl:177 lib/choose_repository.tcl:185
 msgid "Quit"
 msgstr "終了"
 
-#: git-gui.sh:1939
+#: git-gui.sh:2031
 msgid "Undo"
 msgstr "元に戻す"
 
-#: git-gui.sh:1942
+#: git-gui.sh:2034
 msgid "Redo"
 msgstr "やり直し"
 
-#: git-gui.sh:1946 git-gui.sh:2443
+#: git-gui.sh:2038 git-gui.sh:2545
 msgid "Cut"
 msgstr "切り取り"
 
-#: git-gui.sh:1949 git-gui.sh:2446 git-gui.sh:2520 git-gui.sh:2614
+#: git-gui.sh:2041 git-gui.sh:2548 git-gui.sh:2622 git-gui.sh:2715
 #: lib/console.tcl:69
 msgid "Copy"
 msgstr "コピー"
 
-#: git-gui.sh:1952 git-gui.sh:2449
+#: git-gui.sh:2044 git-gui.sh:2551
 msgid "Paste"
 msgstr "貼り付け"
 
-#: git-gui.sh:1955 git-gui.sh:2452 lib/branch_delete.tcl:26
+#: git-gui.sh:2047 git-gui.sh:2554 lib/branch_delete.tcl:26
 #: lib/remote_branch_delete.tcl:38
 msgid "Delete"
 msgstr "削除"
 
-#: git-gui.sh:1959 git-gui.sh:2456 git-gui.sh:2618 lib/console.tcl:71
+#: git-gui.sh:2051 git-gui.sh:2558 git-gui.sh:2719 lib/console.tcl:71
 msgid "Select All"
 msgstr "全て選択"
 
-#: git-gui.sh:1968
+#: git-gui.sh:2060
 msgid "Create..."
 msgstr "作成…"
 
-#: git-gui.sh:1974
+#: git-gui.sh:2066
 msgid "Checkout..."
 msgstr "チェックアウト"
 
-#: git-gui.sh:1980
+#: git-gui.sh:2072
 msgid "Rename..."
 msgstr "名前変更…"
 
-#: git-gui.sh:1985 git-gui.sh:2085
+#: git-gui.sh:2077 git-gui.sh:2187
 msgid "Delete..."
 msgstr "削除…"
 
-#: git-gui.sh:1990
+#: git-gui.sh:2082
 msgid "Reset..."
 msgstr "リセット…"
 
-#: git-gui.sh:2002 git-gui.sh:2389
+#: git-gui.sh:2094 git-gui.sh:2491
 msgid "New Commit"
 msgstr "新規コミット"
 
-#: git-gui.sh:2010 git-gui.sh:2396
+#: git-gui.sh:2102 git-gui.sh:2498
 msgid "Amend Last Commit"
 msgstr "最新コミットを訂正"
 
-#: git-gui.sh:2019 git-gui.sh:2356 lib/remote_branch_delete.tcl:99
+#: git-gui.sh:2111 git-gui.sh:2458 lib/remote_branch_delete.tcl:99
 msgid "Rescan"
 msgstr "再スキャン"
 
-#: git-gui.sh:2025
+#: git-gui.sh:2117
 msgid "Stage To Commit"
 msgstr "コミット予定する"
 
-#: git-gui.sh:2031
+#: git-gui.sh:2123
 msgid "Stage Changed Files To Commit"
 msgstr "変更されたファイルをコミット予定"
 
-#: git-gui.sh:2037
+#: git-gui.sh:2129
 msgid "Unstage From Commit"
 msgstr "コミットから降ろす"
 
-#: git-gui.sh:2042 lib/index.tcl:395
+#: git-gui.sh:2134 lib/index.tcl:395
 msgid "Revert Changes"
 msgstr "変更を元に戻す"
 
-#: git-gui.sh:2049 git-gui.sh:2368 git-gui.sh:2467
+#: git-gui.sh:2141 git-gui.sh:2702
+msgid "Show Less Context"
+msgstr "文脈を少なく"
+
+#: git-gui.sh:2145 git-gui.sh:2706
+msgid "Show More Context"
+msgstr "文脈を多く"
+
+#: git-gui.sh:2151 git-gui.sh:2470 git-gui.sh:2569
 msgid "Sign Off"
 msgstr "署名"
 
-#: git-gui.sh:2053 git-gui.sh:2372
+#: git-gui.sh:2155 git-gui.sh:2474
 msgid "Commit@@verb"
 msgstr "コミット"
 
-#: git-gui.sh:2064
+#: git-gui.sh:2166
 msgid "Local Merge..."
 msgstr "ローカル・マージ…"
 
-#: git-gui.sh:2069
+#: git-gui.sh:2171
 msgid "Abort Merge..."
 msgstr "マージ中止…"
 
-#: git-gui.sh:2081
+#: git-gui.sh:2183
 msgid "Push..."
 msgstr "プッシュ…"
 
-#: git-gui.sh:2092 lib/choose_repository.tcl:41
-msgid "Apple"
-msgstr "りんご"
-
-#: git-gui.sh:2095 git-gui.sh:2117 lib/about.tcl:14
+#: git-gui.sh:2197 git-gui.sh:2219 lib/about.tcl:14
 #: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50
 #, tcl-format
 msgid "About %s"
 msgstr "%s について"
 
-#: git-gui.sh:2099
+#: git-gui.sh:2201
 msgid "Preferences..."
 msgstr "設定…"
 
-#: git-gui.sh:2107 git-gui.sh:2639
+#: git-gui.sh:2209 git-gui.sh:2740
 msgid "Options..."
 msgstr "オプション…"
 
-#: git-gui.sh:2113 lib/choose_repository.tcl:47
+#: git-gui.sh:2215 lib/choose_repository.tcl:47
 msgid "Help"
 msgstr "ヘルプ"
 
-#: git-gui.sh:2154
+#: git-gui.sh:2256
 msgid "Online Documentation"
 msgstr "オンライン・ドキュメント"
 
-#: git-gui.sh:2238
+#: git-gui.sh:2340
 #, tcl-format
 msgid "fatal: cannot stat path %s: No such file or directory"
 msgstr ""
 "致命的: パス %s が stat できません。そのようなファイルやディレクトリはありま"
 "せん"
 
-#: git-gui.sh:2271
+#: git-gui.sh:2373
 msgid "Current Branch:"
 msgstr "現在のブランチ"
 
-#: git-gui.sh:2292
+#: git-gui.sh:2394
 msgid "Staged Changes (Will Commit)"
 msgstr "ステージングされた(コミット予定済の)変更"
 
-#: git-gui.sh:2312
+#: git-gui.sh:2414
 msgid "Unstaged Changes"
 msgstr "コミット予定に入っていない変更"
 
-#: git-gui.sh:2362
+#: git-gui.sh:2464
 msgid "Stage Changed"
 msgstr "変更をコミット予定に入れる"
 
-#: git-gui.sh:2378 lib/transport.tcl:93 lib/transport.tcl:182
+#: git-gui.sh:2480 lib/transport.tcl:93 lib/transport.tcl:182
 msgid "Push"
 msgstr "プッシュ"
 
-#: git-gui.sh:2408
+#: git-gui.sh:2510
 msgid "Initial Commit Message:"
 msgstr "最初のコミットメッセージ:"
 
-#: git-gui.sh:2409
+#: git-gui.sh:2511
 msgid "Amended Commit Message:"
 msgstr "訂正したコミットメッセージ:"
 
-#: git-gui.sh:2410
+#: git-gui.sh:2512
 msgid "Amended Initial Commit Message:"
 msgstr "訂正した最初のコミットメッセージ:"
 
-#: git-gui.sh:2411
+#: git-gui.sh:2513
 msgid "Amended Merge Commit Message:"
 msgstr "訂正したマージコミットメッセージ:"
 
-#: git-gui.sh:2412
+#: git-gui.sh:2514
 msgid "Merge Commit Message:"
 msgstr "マージコミットメッセージ:"
 
-#: git-gui.sh:2413
+#: git-gui.sh:2515
 msgid "Commit Message:"
 msgstr "コミットメッセージ:"
 
-#: git-gui.sh:2459 git-gui.sh:2622 lib/console.tcl:73
+#: git-gui.sh:2561 git-gui.sh:2723 lib/console.tcl:73
 msgid "Copy All"
 msgstr "全てコピー"
 
-#: git-gui.sh:2483 lib/blame.tcl:107
+#: git-gui.sh:2585 lib/blame.tcl:100
 msgid "File:"
 msgstr "ファイル:"
 
-#: git-gui.sh:2589
+#: git-gui.sh:2691
 msgid "Apply/Reverse Hunk"
 msgstr "パッチを適用/取り消す"
 
-#: git-gui.sh:2595
-msgid "Show Less Context"
-msgstr "文脈を少なく"
+#: git-gui.sh:2696
+msgid "Apply/Reverse Line"
+msgstr "パッチ行を適用/取り消す"
 
-#: git-gui.sh:2602
-msgid "Show More Context"
-msgstr "文脈を多く"
-
-#: git-gui.sh:2610
+#: git-gui.sh:2711
 msgid "Refresh"
 msgstr "再読み込み"
 
-#: git-gui.sh:2631
+#: git-gui.sh:2732
 msgid "Decrease Font Size"
 msgstr "フォントを小さく"
 
-#: git-gui.sh:2635
+#: git-gui.sh:2736
 msgid "Increase Font Size"
 msgstr "フォントを大きく"
 
-#: git-gui.sh:2646
+#: git-gui.sh:2747
 msgid "Unstage Hunk From Commit"
 msgstr "パッチをコミット予定から外す"
 
-#: git-gui.sh:2648
+#: git-gui.sh:2748
+msgid "Unstage Line From Commit"
+msgstr "コミット予定から行を外す"
+
+#: git-gui.sh:2750
 msgid "Stage Hunk For Commit"
 msgstr "パッチをコミット予定に加える"
 
-#: git-gui.sh:2667
+#: git-gui.sh:2751
+msgid "Stage Line For Commit"
+msgstr "パッチ行をコミット予定に加える"
+
+#: git-gui.sh:2771
 msgid "Initializing..."
 msgstr "初期化しています…"
 
-#: git-gui.sh:2762
+#: git-gui.sh:2876
 #, tcl-format
 msgid ""
 "Possible environment issues exist.\n"
@@ -449,7 +450,7 @@
 "以下の環境変数は %s が起動する Git サブプロセスによって無視されるでしょう:\n"
 "\n"
 
-#: git-gui.sh:2792
+#: git-gui.sh:2906
 msgid ""
 "\n"
 "This is due to a known issue with the\n"
@@ -459,7 +460,7 @@
 "これは Cygwin で配布されている Tcl バイナリに\n"
 "関しての既知の問題によります"
 
-#: git-gui.sh:2797
+#: git-gui.sh:2911
 #, tcl-format
 msgid ""
 "\n"
@@ -478,64 +479,80 @@
 msgid "git-gui - a graphical user interface for Git."
 msgstr "Git のグラフィカルUI git-gui"
 
-#: lib/blame.tcl:77
+#: lib/blame.tcl:70
 msgid "File Viewer"
 msgstr "ファイルピューワ"
 
-#: lib/blame.tcl:81
+#: lib/blame.tcl:74
 msgid "Commit:"
 msgstr "コミット:"
 
-#: lib/blame.tcl:264
+#: lib/blame.tcl:257
 msgid "Copy Commit"
 msgstr "コミットをコピー"
 
-#: lib/blame.tcl:384
+#: lib/blame.tcl:260
+msgid "Do Full Copy Detection"
+msgstr "コピー検知"
+
+#: lib/blame.tcl:388
 #, tcl-format
 msgid "Reading %s..."
 msgstr "%s を読んでいます…"
 
-#: lib/blame.tcl:488
+#: lib/blame.tcl:492
 msgid "Loading copy/move tracking annotations..."
 msgstr "コピー・移動追跡データを読んでいます…"
 
-#: lib/blame.tcl:508
+#: lib/blame.tcl:512
 msgid "lines annotated"
 msgstr "行を注釈しました"
 
-#: lib/blame.tcl:689
+#: lib/blame.tcl:704
 msgid "Loading original location annotations..."
 msgstr "元位置行の注釈データを読んでいます…"
 
-#: lib/blame.tcl:692
+#: lib/blame.tcl:707
 msgid "Annotation complete."
 msgstr "注釈完了しました"
 
-#: lib/blame.tcl:746
+#: lib/blame.tcl:737
+msgid "Busy"
+msgstr "実行中"
+
+#: lib/blame.tcl:738
+msgid "Annotation process is already running."
+msgstr "すでに blame プロセスを実行中です。"
+
+#: lib/blame.tcl:777
+msgid "Running thorough copy detection..."
+msgstr "コピー検知を実行中…"
+
+#: lib/blame.tcl:827
 msgid "Loading annotation..."
 msgstr "注釈を読み込んでいます…"
 
-#: lib/blame.tcl:802
+#: lib/blame.tcl:883
 msgid "Author:"
 msgstr "作者:"
 
-#: lib/blame.tcl:806
+#: lib/blame.tcl:887
 msgid "Committer:"
 msgstr "コミット者:"
 
-#: lib/blame.tcl:811
+#: lib/blame.tcl:892
 msgid "Original File:"
 msgstr "元ファイル"
 
-#: lib/blame.tcl:925
+#: lib/blame.tcl:1006
 msgid "Originally By:"
 msgstr "原作者:"
 
-#: lib/blame.tcl:931
+#: lib/blame.tcl:1012
 msgid "In File:"
 msgstr "ファイル:"
 
-#: lib/blame.tcl:936
+#: lib/blame.tcl:1017
 msgid "Copied Or Moved Here By:"
 msgstr "複写・移動者:"
 
@@ -549,7 +566,7 @@
 
 #: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35
 #: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:282
-#: lib/checkout_op.tcl:522 lib/choose_font.tcl:43 lib/merge.tcl:171
+#: lib/checkout_op.tcl:544 lib/choose_font.tcl:43 lib/merge.tcl:171
 #: lib/option.tcl:103 lib/remote_branch_delete.tcl:42 lib/transport.tcl:97
 msgid "Cancel"
 msgstr "中止"
@@ -558,7 +575,7 @@
 msgid "Revision"
 msgstr "リビジョン"
 
-#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:242
+#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:244
 msgid "Options"
 msgstr "オプション"
 
@@ -610,7 +627,7 @@
 msgid "Fast Forward Only"
 msgstr "早送りのみ"
 
-#: lib/branch_create.tcl:85 lib/checkout_op.tcl:514
+#: lib/branch_create.tcl:85 lib/checkout_op.tcl:536
 msgid "Reset"
 msgstr "リセット"
 
@@ -700,7 +717,7 @@
 msgid "Please select a branch to rename."
 msgstr "名前を変更するブランチを選んで下さい。"
 
-#: lib/branch_rename.tcl:96 lib/checkout_op.tcl:179
+#: lib/branch_rename.tcl:96 lib/checkout_op.tcl:201
 #, tcl-format
 msgid "Branch '%s' already exists."
 msgstr "'%s'というブランチは既に存在します。"
@@ -732,31 +749,36 @@
 msgstr "現在のブランチのファイルを見る"
 
 #: lib/browser.tcl:278 lib/choose_repository.tcl:387
-#: lib/choose_repository.tcl:474 lib/choose_repository.tcl:484
-#: lib/choose_repository.tcl:987
+#: lib/choose_repository.tcl:472 lib/choose_repository.tcl:482
+#: lib/choose_repository.tcl:985
 msgid "Browse"
 msgstr "ブラウズ"
 
-#: lib/checkout_op.tcl:79
+#: lib/checkout_op.tcl:84
 #, tcl-format
 msgid "Fetching %s from %s"
 msgstr "%s から %s をフェッチしています"
 
-#: lib/checkout_op.tcl:127
+#: lib/checkout_op.tcl:132
 #, tcl-format
 msgid "fatal: Cannot resolve %s"
 msgstr "致命的エラー: %s を解決できません"
 
-#: lib/checkout_op.tcl:140 lib/console.tcl:81 lib/database.tcl:31
+#: lib/checkout_op.tcl:145 lib/console.tcl:81 lib/database.tcl:31
 msgid "Close"
 msgstr "閉じる"
 
-#: lib/checkout_op.tcl:169
+#: lib/checkout_op.tcl:174
 #, tcl-format
 msgid "Branch '%s' does not exist."
 msgstr "ブランチ'%s'は存在しません。"
 
-#: lib/checkout_op.tcl:206
+#: lib/checkout_op.tcl:193
+#, tcl-format
+msgid "Failed to configure simplified git-pull for '%s'."
+msgstr "'%s' に簡易 git-pull を設定できませんでした"
+
+#: lib/checkout_op.tcl:228
 #, tcl-format
 msgid ""
 "Branch '%s' already exists.\n"
@@ -769,21 +791,21 @@
 "%s に早送りできません。\n"
 "マージが必要です。"
 
-#: lib/checkout_op.tcl:220
+#: lib/checkout_op.tcl:242
 #, tcl-format
 msgid "Merge strategy '%s' not supported."
 msgstr "'%s' マージ戦略はサポートされていません。"
 
-#: lib/checkout_op.tcl:239
+#: lib/checkout_op.tcl:261
 #, tcl-format
 msgid "Failed to update '%s'."
 msgstr "'%s' の更新に失敗しました。"
 
-#: lib/checkout_op.tcl:251
+#: lib/checkout_op.tcl:273
 msgid "Staging area (index) is already locked."
 msgstr "インデックスは既にロックされています。"
 
-#: lib/checkout_op.tcl:266
+#: lib/checkout_op.tcl:288
 msgid ""
 "Last scanned state does not match repository state.\n"
 "\n"
@@ -799,30 +821,30 @@
 "\n"
 "自動的に再スキャンを開始します。\n"
 
-#: lib/checkout_op.tcl:322
+#: lib/checkout_op.tcl:344
 #, tcl-format
 msgid "Updating working directory to '%s'..."
 msgstr "作業ディレクトリを '%s' に更新しています…"
 
-#: lib/checkout_op.tcl:323
+#: lib/checkout_op.tcl:345
 msgid "files checked out"
 msgstr "チェックアウトされたファイル"
 
-#: lib/checkout_op.tcl:353
+#: lib/checkout_op.tcl:375
 #, tcl-format
 msgid "Aborted checkout of '%s' (file level merging is required)."
 msgstr "'%s' のチェックアウトを中止しました(ファイル毎のマージが必要です)。"
 
-#: lib/checkout_op.tcl:354
+#: lib/checkout_op.tcl:376
 msgid "File level merge required."
 msgstr "ファイル毎のマージが必要です。"
 
-#: lib/checkout_op.tcl:358
+#: lib/checkout_op.tcl:380
 #, tcl-format
 msgid "Staying on branch '%s'."
 msgstr "ブランチ '%s' に滞まります。"
 
-#: lib/checkout_op.tcl:429
+#: lib/checkout_op.tcl:451
 msgid ""
 "You are no longer on a local branch.\n"
 "\n"
@@ -834,30 +856,30 @@
 "ブランチ上に滞まりたいときは、この「分離されたチェックアウト」から新規ブラン"
 "チを開始してください。"
 
-#: lib/checkout_op.tcl:446 lib/checkout_op.tcl:450
+#: lib/checkout_op.tcl:468 lib/checkout_op.tcl:472
 #, tcl-format
 msgid "Checked out '%s'."
 msgstr "'%s' をチェックアウトしました"
 
-#: lib/checkout_op.tcl:478
+#: lib/checkout_op.tcl:500
 #, tcl-format
 msgid "Resetting '%s' to '%s' will lose the following commits:"
 msgstr "'%s' を '%s' にリセットすると、以下のコミットが失なわれます:"
 
-#: lib/checkout_op.tcl:500
+#: lib/checkout_op.tcl:522
 msgid "Recovering lost commits may not be easy."
 msgstr "失なわれたコミットを回復するのは簡単ではありません。"
 
-#: lib/checkout_op.tcl:505
+#: lib/checkout_op.tcl:527
 #, tcl-format
 msgid "Reset '%s'?"
 msgstr "'%s' をリセットしますか?"
 
-#: lib/checkout_op.tcl:510 lib/merge.tcl:163
+#: lib/checkout_op.tcl:532 lib/merge.tcl:163
 msgid "Visualize"
 msgstr "可視化"
 
-#: lib/checkout_op.tcl:578
+#: lib/checkout_op.tcl:600
 #, tcl-format
 msgid ""
 "Failed to set current branch.\n"
@@ -909,7 +931,7 @@
 msgid "New..."
 msgstr "新規…"
 
-#: lib/choose_repository.tcl:94 lib/choose_repository.tcl:460
+#: lib/choose_repository.tcl:94 lib/choose_repository.tcl:458
 msgid "Clone Existing Repository"
 msgstr "既存リポジトリを複製する"
 
@@ -917,7 +939,7 @@
 msgid "Clone..."
 msgstr "複製…"
 
-#: lib/choose_repository.tcl:107 lib/choose_repository.tcl:976
+#: lib/choose_repository.tcl:107 lib/choose_repository.tcl:974
 msgid "Open Existing Repository"
 msgstr "既存リポジトリを開く"
 
@@ -939,183 +961,183 @@
 msgid "Failed to create repository %s:"
 msgstr "リポジトリ %s を作製できません:"
 
-#: lib/choose_repository.tcl:381 lib/choose_repository.tcl:478
+#: lib/choose_repository.tcl:381 lib/choose_repository.tcl:476
 msgid "Directory:"
 msgstr "ディレクトリ:"
 
-#: lib/choose_repository.tcl:412 lib/choose_repository.tcl:537
-#: lib/choose_repository.tcl:1011
+#: lib/choose_repository.tcl:410 lib/choose_repository.tcl:535
+#: lib/choose_repository.tcl:1007
 msgid "Git Repository"
 msgstr "GIT リポジトリ"
 
-#: lib/choose_repository.tcl:437
+#: lib/choose_repository.tcl:435
 #, tcl-format
 msgid "Directory %s already exists."
 msgstr "ディレクトリ '%s' は既に存在します。"
 
-#: lib/choose_repository.tcl:441
+#: lib/choose_repository.tcl:439
 #, tcl-format
 msgid "File %s already exists."
 msgstr "ファイル '%s' は既に存在します。"
 
-#: lib/choose_repository.tcl:455
+#: lib/choose_repository.tcl:453
 msgid "Clone"
 msgstr "複製"
 
-#: lib/choose_repository.tcl:468
+#: lib/choose_repository.tcl:466
 msgid "URL:"
 msgstr "URL:"
 
-#: lib/choose_repository.tcl:489
+#: lib/choose_repository.tcl:487
 msgid "Clone Type:"
 msgstr "複製方式:"
 
-#: lib/choose_repository.tcl:495
+#: lib/choose_repository.tcl:493
 msgid "Standard (Fast, Semi-Redundant, Hardlinks)"
 msgstr "標準(高速・中冗長度・ハードリンク)"
 
-#: lib/choose_repository.tcl:501
+#: lib/choose_repository.tcl:499
 msgid "Full Copy (Slower, Redundant Backup)"
 msgstr "全複写(低速・冗長バックアップ)"
 
-#: lib/choose_repository.tcl:507
+#: lib/choose_repository.tcl:505
 msgid "Shared (Fastest, Not Recommended, No Backup)"
 msgstr "共有(最高速・非推奨・バックアップ無し)"
 
-#: lib/choose_repository.tcl:543 lib/choose_repository.tcl:590
-#: lib/choose_repository.tcl:736 lib/choose_repository.tcl:806
-#: lib/choose_repository.tcl:1017 lib/choose_repository.tcl:1025
+#: lib/choose_repository.tcl:541 lib/choose_repository.tcl:588
+#: lib/choose_repository.tcl:734 lib/choose_repository.tcl:804
+#: lib/choose_repository.tcl:1013 lib/choose_repository.tcl:1021
 #, tcl-format
 msgid "Not a Git repository: %s"
 msgstr "Git リポジトリではありません: %s"
 
-#: lib/choose_repository.tcl:579
+#: lib/choose_repository.tcl:577
 msgid "Standard only available for local repository."
 msgstr "標準方式は同一計算機上のリポジトリにのみ使えます。"
 
-#: lib/choose_repository.tcl:583
+#: lib/choose_repository.tcl:581
 msgid "Shared only available for local repository."
 msgstr "共有方式は同一計算機上のリポジトリにのみ使えます。"
 
-#: lib/choose_repository.tcl:604
+#: lib/choose_repository.tcl:602
 #, tcl-format
 msgid "Location %s already exists."
 msgstr "'%s' は既に存在します。"
 
-#: lib/choose_repository.tcl:615
+#: lib/choose_repository.tcl:613
 msgid "Failed to configure origin"
 msgstr "origin を設定できませんでした"
 
-#: lib/choose_repository.tcl:627
+#: lib/choose_repository.tcl:625
 msgid "Counting objects"
 msgstr "オブジェクトを数えています"
 
-#: lib/choose_repository.tcl:628
+#: lib/choose_repository.tcl:626
 msgid "buckets"
 msgstr "バケツ"
 
-#: lib/choose_repository.tcl:652
+#: lib/choose_repository.tcl:650
 #, tcl-format
 msgid "Unable to copy objects/info/alternates: %s"
 msgstr "objects/info/alternates を複写できません: %s"
 
-#: lib/choose_repository.tcl:688
+#: lib/choose_repository.tcl:686
 #, tcl-format
 msgid "Nothing to clone from %s."
 msgstr "%s から複製する内容はありません"
 
-#: lib/choose_repository.tcl:690 lib/choose_repository.tcl:904
-#: lib/choose_repository.tcl:916
+#: lib/choose_repository.tcl:688 lib/choose_repository.tcl:902
+#: lib/choose_repository.tcl:914
 msgid "The 'master' branch has not been initialized."
 msgstr "'master' ブランチが初期化されていません"
 
-#: lib/choose_repository.tcl:703
+#: lib/choose_repository.tcl:701
 msgid "Hardlinks are unavailable.  Falling back to copying."
 msgstr "ハードリンクが作れないので、コピーします"
 
-#: lib/choose_repository.tcl:715
+#: lib/choose_repository.tcl:713
 #, tcl-format
 msgid "Cloning from %s"
 msgstr "%s から複製しています"
 
-#: lib/choose_repository.tcl:746
+#: lib/choose_repository.tcl:744
 msgid "Copying objects"
 msgstr "オブジェクトを複写しています"
 
-#: lib/choose_repository.tcl:747
+#: lib/choose_repository.tcl:745
 msgid "KiB"
 msgstr "KiB"
 
-#: lib/choose_repository.tcl:771
+#: lib/choose_repository.tcl:769
 #, tcl-format
 msgid "Unable to copy object: %s"
 msgstr "オブジェクトを複写できません: %s"
 
-#: lib/choose_repository.tcl:781
+#: lib/choose_repository.tcl:779
 msgid "Linking objects"
 msgstr "オブジェクトを連結しています"
 
-#: lib/choose_repository.tcl:782
+#: lib/choose_repository.tcl:780
 msgid "objects"
 msgstr "オブジェクト"
 
-#: lib/choose_repository.tcl:790
+#: lib/choose_repository.tcl:788
 #, tcl-format
 msgid "Unable to hardlink object: %s"
 msgstr "オブジェクトをハードリンクできません: %s"
 
-#: lib/choose_repository.tcl:845
+#: lib/choose_repository.tcl:843
 msgid "Cannot fetch branches and objects.  See console output for details."
 msgstr "ブランチやオブジェクトを取得できません。コンソール出力を見て下さい"
 
-#: lib/choose_repository.tcl:856
+#: lib/choose_repository.tcl:854
 msgid "Cannot fetch tags.  See console output for details."
 msgstr "タグを取得できません。コンソール出力を見て下さい"
 
-#: lib/choose_repository.tcl:880
+#: lib/choose_repository.tcl:878
 msgid "Cannot determine HEAD.  See console output for details."
 msgstr "HEAD を確定できません。コンソール出力を見て下さい"
 
-#: lib/choose_repository.tcl:889
+#: lib/choose_repository.tcl:887
 #, tcl-format
 msgid "Unable to cleanup %s"
 msgstr "%s を掃除できません"
 
-#: lib/choose_repository.tcl:895
+#: lib/choose_repository.tcl:893
 msgid "Clone failed."
 msgstr "複写に失敗しました。"
 
-#: lib/choose_repository.tcl:902
+#: lib/choose_repository.tcl:900
 msgid "No default branch obtained."
 msgstr "デフォールト・ブランチが取得されませんでした"
 
-#: lib/choose_repository.tcl:913
+#: lib/choose_repository.tcl:911
 #, tcl-format
 msgid "Cannot resolve %s as a commit."
 msgstr "%s をコミットとして解釈できません"
 
-#: lib/choose_repository.tcl:925
+#: lib/choose_repository.tcl:923
 msgid "Creating working directory"
 msgstr "作業ディレクトリを作成しています"
 
-#: lib/choose_repository.tcl:926 lib/index.tcl:65 lib/index.tcl:127
+#: lib/choose_repository.tcl:924 lib/index.tcl:65 lib/index.tcl:127
 #: lib/index.tcl:193
 msgid "files"
 msgstr "ファイル"
 
-#: lib/choose_repository.tcl:955
+#: lib/choose_repository.tcl:953
 msgid "Initial file checkout failed."
 msgstr "初期チェックアウトに失敗しました"
 
-#: lib/choose_repository.tcl:971
+#: lib/choose_repository.tcl:969
 msgid "Open"
 msgstr "開く"
 
-#: lib/choose_repository.tcl:981
+#: lib/choose_repository.tcl:979
 msgid "Repository:"
 msgstr "リポジトリ:"
 
-#: lib/choose_repository.tcl:1031
+#: lib/choose_repository.tcl:1027
 #, tcl-format
 msgid "Failed to open repository %s:"
 msgstr "リポジトリ %s を開けません:"
@@ -1405,7 +1427,7 @@
 msgid "Invalid date from Git: %s"
 msgstr "Git から出た無効な日付: %s"
 
-#: lib/diff.tcl:42
+#: lib/diff.tcl:44
 #, tcl-format
 msgid ""
 "No differences detected.\n"
@@ -1427,40 +1449,48 @@
 "\n"
 "同様な状態のファイルを探すために、自動的に再スキャンを開始します。"
 
-#: lib/diff.tcl:81
+#: lib/diff.tcl:83
 #, tcl-format
 msgid "Loading diff of %s..."
 msgstr "%s の変更点をロード中…"
 
-#: lib/diff.tcl:114 lib/diff.tcl:184
+#: lib/diff.tcl:116 lib/diff.tcl:190
 #, tcl-format
 msgid "Unable to display %s"
 msgstr "%s を表示できません"
 
-#: lib/diff.tcl:115
+#: lib/diff.tcl:117
 msgid "Error loading file:"
 msgstr "ファイルを読む際のエラーです:"
 
-#: lib/diff.tcl:122
+#: lib/diff.tcl:124
 msgid "Git Repository (subproject)"
 msgstr "Git リポジトリ(サブプロジェクト)"
 
-#: lib/diff.tcl:134
+#: lib/diff.tcl:136
 msgid "* Binary file (not showing content)."
 msgstr "* バイナリファイル(内容は表示しません)"
 
-#: lib/diff.tcl:185
+#: lib/diff.tcl:191
 msgid "Error loading diff:"
 msgstr "diff を読む際のエラーです:"
 
-#: lib/diff.tcl:303
+#: lib/diff.tcl:313
 msgid "Failed to unstage selected hunk."
 msgstr "選択されたパッチをコミット予定から外せません。"
 
-#: lib/diff.tcl:310
+#: lib/diff.tcl:320
 msgid "Failed to stage selected hunk."
 msgstr "選択されたパッチをコミット予定に加えられません。"
 
+#: lib/diff.tcl:386
+msgid "Failed to unstage selected line."
+msgstr "選択されたパッチ行をコミット予定から外せません。"
+
+#: lib/diff.tcl:394
+msgid "Failed to stage selected line."
+msgstr "選択されたパッチ行をコミット予定に加えられません。"
+
 #: lib/error.tcl:20 lib/error.tcl:114
 msgid "error"
 msgstr "エラー"
@@ -1662,11 +1692,11 @@
 msgid "files reset"
 msgstr "リセットしたファイル"
 
-#: lib/merge.tcl:265
+#: lib/merge.tcl:266
 msgid "Abort failed."
 msgstr "中断に失敗しました。"
 
-#: lib/merge.tcl:267
+#: lib/merge.tcl:268
 msgid "Abort completed.  Ready."
 msgstr "中断完了。"
 
@@ -1720,42 +1750,62 @@
 msgstr "トラッキングブランチを合わせる"
 
 #: lib/option.tcl:126
+msgid "Blame Copy Only On Changed Files"
+msgstr "変更されたファイルのみコピー検知を行なう"
+
+#: lib/option.tcl:127
+msgid "Minimum Letters To Blame Copy On"
+msgstr "コピーを検知する最少文字数"
+
+#: lib/option.tcl:128
 msgid "Number of Diff Context Lines"
 msgstr "diff の文脈行数"
 
-#: lib/option.tcl:127
+#: lib/option.tcl:129
 msgid "Commit Message Text Width"
 msgstr "コミットメッセージのテキスト幅"
 
-#: lib/option.tcl:128
+#: lib/option.tcl:130
 msgid "New Branch Name Template"
 msgstr "新しいブランチ名のテンプレート"
 
-#: lib/option.tcl:192
+#: lib/option.tcl:194
 msgid "Spelling Dictionary:"
 msgstr "スペルチェック辞書"
 
-#: lib/option.tcl:216
+#: lib/option.tcl:218
 msgid "Change Font"
 msgstr "フォントを変更"
 
-#: lib/option.tcl:220
+#: lib/option.tcl:222
 #, tcl-format
 msgid "Choose %s"
 msgstr "%s を選択"
 
-#: lib/option.tcl:226
+#: lib/option.tcl:228
 msgid "pt."
 msgstr "ポイント"
 
-#: lib/option.tcl:240
+#: lib/option.tcl:242
 msgid "Preferences"
 msgstr "設定"
 
-#: lib/option.tcl:275
+#: lib/option.tcl:277
 msgid "Failed to completely save options:"
 msgstr "完全にオプションを保存できません:"
 
+#: lib/remote.tcl:165
+msgid "Prune from"
+msgstr "から刈込む…"
+
+#: lib/remote.tcl:170
+msgid "Fetch from"
+msgstr "取得元"
+
+#: lib/remote.tcl:213
+msgid "Push to"
+msgstr "プッシュ先"
+
 #: lib/remote_branch_delete.tcl:29 lib/remote_branch_delete.tcl:34
 msgid "Delete Remote Branch"
 msgstr "リモート・ブランチを削除"
@@ -1840,18 +1890,6 @@
 msgid "Scanning %s..."
 msgstr "%s をスキャンしています…"
 
-#: lib/remote.tcl:165
-msgid "Prune from"
-msgstr "から刈込む…"
-
-#: lib/remote.tcl:170
-msgid "Fetch from"
-msgstr "取得元"
-
-#: lib/remote.tcl:213
-msgid "Push to"
-msgstr "プッシュ先"
-
 #: lib/shortcut.tcl:20 lib/shortcut.tcl:61
 msgid "Cannot write shortcut:"
 msgstr "ショートカットが書けません:"
@@ -1885,15 +1923,15 @@
 msgid "Unrecognized spell checker"
 msgstr "スペルチェッカーが判別できません"
 
-#: lib/spellcheck.tcl:180
+#: lib/spellcheck.tcl:186
 msgid "No Suggestions"
 msgstr "提案なし"
 
-#: lib/spellcheck.tcl:381
+#: lib/spellcheck.tcl:387
 msgid "Unexpected EOF from spell checker"
 msgstr "スペルチェッカーが予想外の EOF を返しました"
 
-#: lib/spellcheck.tcl:385
+#: lib/spellcheck.tcl:391
 msgid "Spell Checker Failed"
 msgstr "スペルチェック失敗"
 
@@ -1964,6 +2002,3 @@
 #: lib/transport.tcl:168
 msgid "Include tags"
 msgstr "タグを含める"
-
-#~ msgid "Not connected to aspell"
-#~ msgstr "aspell に接続していません"
diff --git a/git-gui/po/po2msg.sh b/git-gui/po/po2msg.sh
index b7c4bf3..1e9f992 100644
--- a/git-gui/po/po2msg.sh
+++ b/git-gui/po/po2msg.sh
@@ -11,8 +11,8 @@
 	foreach i [split $s ""] {
 		scan $i %c c
 		if {$c<128} {
-			# escape '[', '\' and ']'
-			if {$c == 0x5b || $c == 0x5d} {
+			# escape '[', '\', '$' and ']'
+			if {$c == 0x5b || $c == 0x5d || $c == 0x24} {
 				append res "\\"
 			}
 			append res $i
diff --git a/git-gui/po/sv.po b/git-gui/po/sv.po
index 4da687b..0196ba8 100644
--- a/git-gui/po/sv.po
+++ b/git-gui/po/sv.po
@@ -3,45 +3,46 @@
 # This file is distributed under the same license as the git-gui package.
 #
 # Peter Karlsson <peter@softwolves.pp.se>, 2007-2008.
+# Mikael Magnusson <mikachu@gmail.com>, 2008.
 msgid ""
 msgstr ""
 "Project-Id-Version: sv\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-03-14 07:18+0100\n"
-"PO-Revision-Date: 2008-03-14 07:23+0100\n"
-"Last-Translator: Peter Karlsson <peter@softwolves.pp.se>\n"
+"POT-Creation-Date: 2008-08-03 01:34+0200\n"
+"PO-Revision-Date: 2008-08-03 01:45+0200\n"
+"Last-Translator: Mikael Magnusson <mikachu@gmail.com>\n"
 "Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit"
+"Content-Transfer-Encoding: 8bit\n"
 
-#: git-gui.sh:41 git-gui.sh:634 git-gui.sh:648 git-gui.sh:661 git-gui.sh:744
-#: git-gui.sh:763
+#: git-gui.sh:41 git-gui.sh:688 git-gui.sh:702 git-gui.sh:715 git-gui.sh:798
+#: git-gui.sh:817
 msgid "git-gui: fatal error"
 msgstr "git-gui: ödesdigert fel"
 
-#: git-gui.sh:593
+#: git-gui.sh:644
 #, tcl-format
 msgid "Invalid font specified in %s:"
 msgstr "Ogiltigt teckensnitt angivet i %s:"
 
-#: git-gui.sh:620
+#: git-gui.sh:674
 msgid "Main Font"
 msgstr "Huvudteckensnitt"
 
-#: git-gui.sh:621
+#: git-gui.sh:675
 msgid "Diff/Console Font"
 msgstr "Diff/konsolteckensnitt"
 
-#: git-gui.sh:635
+#: git-gui.sh:689
 msgid "Cannot find git in PATH."
 msgstr "Hittar inte git i PATH."
 
-#: git-gui.sh:662
+#: git-gui.sh:716
 msgid "Cannot parse Git version string:"
 msgstr "Kan inte tolka versionssträng från Git:"
 
-#: git-gui.sh:680
+#: git-gui.sh:734
 #, tcl-format
 msgid ""
 "Git version cannot be determined.\n"
@@ -60,379 +61,380 @@
 "\n"
 "Anta att \"%s\" är version 1.5.0?\n"
 
-#: git-gui.sh:918
+#: git-gui.sh:972
 msgid "Git directory not found:"
 msgstr "Git-katalogen hittades inte:"
 
-#: git-gui.sh:925
+#: git-gui.sh:979
 msgid "Cannot move to top of working directory:"
 msgstr "Kan inte gå till början på arbetskatalogen:"
 
-#: git-gui.sh:932
+#: git-gui.sh:986
 msgid "Cannot use funny .git directory:"
 msgstr "Kan inte använda underlig .git-katalog:"
 
-#: git-gui.sh:937
+#: git-gui.sh:991
 msgid "No working directory"
 msgstr "Ingen arbetskatalog"
 
-#: git-gui.sh:1084 lib/checkout_op.tcl:283
+#: git-gui.sh:1138 lib/checkout_op.tcl:305
 msgid "Refreshing file status..."
 msgstr "Uppdaterar filstatus..."
 
-#: git-gui.sh:1149
+#: git-gui.sh:1194
 msgid "Scanning for modified files ..."
 msgstr "Söker efter ändrade filer..."
 
-#: git-gui.sh:1324 lib/browser.tcl:246
+#: git-gui.sh:1369 lib/browser.tcl:246
 msgid "Ready."
 msgstr "Klar."
 
-#: git-gui.sh:1590
+#: git-gui.sh:1635
 msgid "Unmodified"
 msgstr "Oförändrade"
 
-#: git-gui.sh:1592
+#: git-gui.sh:1637
 msgid "Modified, not staged"
 msgstr "Förändrade, ej köade"
 
-#: git-gui.sh:1593 git-gui.sh:1598
+#: git-gui.sh:1638 git-gui.sh:1643
 msgid "Staged for commit"
 msgstr "Köade för incheckning"
 
-#: git-gui.sh:1594 git-gui.sh:1599
+#: git-gui.sh:1639 git-gui.sh:1644
 msgid "Portions staged for commit"
 msgstr "Delar köade för incheckning"
 
-#: git-gui.sh:1595 git-gui.sh:1600
+#: git-gui.sh:1640 git-gui.sh:1645
 msgid "Staged for commit, missing"
 msgstr "Köade för incheckning, saknade"
 
-#: git-gui.sh:1597
+#: git-gui.sh:1642
 msgid "Untracked, not staged"
 msgstr "Ej spårade, ej köade"
 
-#: git-gui.sh:1602
+#: git-gui.sh:1647
 msgid "Missing"
 msgstr "Saknade"
 
-#: git-gui.sh:1603
+#: git-gui.sh:1648
 msgid "Staged for removal"
 msgstr "Köade för borttagning"
 
-#: git-gui.sh:1604
+#: git-gui.sh:1649
 msgid "Staged for removal, still present"
 msgstr "Köade för borttagning, fortfarande närvarande"
 
-#: git-gui.sh:1606 git-gui.sh:1607 git-gui.sh:1608 git-gui.sh:1609
+#: git-gui.sh:1651 git-gui.sh:1652 git-gui.sh:1653 git-gui.sh:1654
 msgid "Requires merge resolution"
 msgstr "Kräver konflikthantering efter sammanslagning"
 
-#: git-gui.sh:1644
+#: git-gui.sh:1689
 msgid "Starting gitk... please wait..."
 msgstr "Startar gitk... vänta..."
 
-#: git-gui.sh:1653
-#, tcl-format
-msgid ""
-"Unable to start gitk:\n"
-"\n"
-"%s does not exist"
-msgstr ""
-"Kan inte starta gitk:\n"
-"\n"
-"%s finns inte"
+#: git-gui.sh:1698
+msgid "Couldn't find gitk in PATH"
+msgstr "Hittar inte gitk i PATH."
 
-#: git-gui.sh:1860 lib/choose_repository.tcl:36
+#: git-gui.sh:1948 lib/choose_repository.tcl:36
 msgid "Repository"
 msgstr "Arkiv"
 
-#: git-gui.sh:1861
+#: git-gui.sh:1949
 msgid "Edit"
 msgstr "Redigera"
 
-#: git-gui.sh:1863 lib/choose_rev.tcl:561
+#: git-gui.sh:1951 lib/choose_rev.tcl:561
 msgid "Branch"
 msgstr "Gren"
 
-#: git-gui.sh:1866 lib/choose_rev.tcl:548
+#: git-gui.sh:1954 lib/choose_rev.tcl:548
 msgid "Commit@@noun"
 msgstr "Incheckning"
 
-#: git-gui.sh:1869 lib/merge.tcl:120 lib/merge.tcl:149 lib/merge.tcl:167
+#: git-gui.sh:1957 lib/merge.tcl:120 lib/merge.tcl:149 lib/merge.tcl:167
 msgid "Merge"
 msgstr "Slå ihop"
 
-#: git-gui.sh:1870 lib/choose_rev.tcl:557
+#: git-gui.sh:1958 lib/choose_rev.tcl:557
 msgid "Remote"
 msgstr "Fjärr"
 
-#: git-gui.sh:1879
+#: git-gui.sh:1967
 msgid "Browse Current Branch's Files"
 msgstr "Bläddra i grenens filer"
 
-#: git-gui.sh:1883
+#: git-gui.sh:1971
 msgid "Browse Branch Files..."
 msgstr "Bläddra filer på gren..."
 
-#: git-gui.sh:1888
+#: git-gui.sh:1976
 msgid "Visualize Current Branch's History"
 msgstr "Visualisera grenens historik"
 
-#: git-gui.sh:1892
+#: git-gui.sh:1980
 msgid "Visualize All Branch History"
 msgstr "Visualisera alla grenars historik"
 
-#: git-gui.sh:1899
+#: git-gui.sh:1987
 #, tcl-format
 msgid "Browse %s's Files"
 msgstr "Bläddra i filer för %s"
 
-#: git-gui.sh:1901
+#: git-gui.sh:1989
 #, tcl-format
 msgid "Visualize %s's History"
 msgstr "Visualisera historik för %s"
 
-#: git-gui.sh:1906 lib/database.tcl:27 lib/database.tcl:67
+#: git-gui.sh:1994 lib/database.tcl:27 lib/database.tcl:67
 msgid "Database Statistics"
 msgstr "Databasstatistik"
 
-#: git-gui.sh:1909 lib/database.tcl:34
+#: git-gui.sh:1997 lib/database.tcl:34
 msgid "Compress Database"
 msgstr "Komprimera databas"
 
-#: git-gui.sh:1912
+#: git-gui.sh:2000
 msgid "Verify Database"
 msgstr "Verifiera databas"
 
-#: git-gui.sh:1919 git-gui.sh:1923 git-gui.sh:1927 lib/shortcut.tcl:7
+#: git-gui.sh:2007 git-gui.sh:2011 git-gui.sh:2015 lib/shortcut.tcl:7
 #: lib/shortcut.tcl:39 lib/shortcut.tcl:71
 msgid "Create Desktop Icon"
 msgstr "Skapa skrivbordsikon"
 
-#: git-gui.sh:1932 lib/choose_repository.tcl:177 lib/choose_repository.tcl:185
+#: git-gui.sh:2023 lib/choose_repository.tcl:177 lib/choose_repository.tcl:185
 msgid "Quit"
 msgstr "Avsluta"
 
-#: git-gui.sh:1939
+#: git-gui.sh:2031
 msgid "Undo"
 msgstr "Ångra"
 
-#: git-gui.sh:1942
+#: git-gui.sh:2034
 msgid "Redo"
 msgstr "Gör om"
 
-#: git-gui.sh:1946 git-gui.sh:2443
+#: git-gui.sh:2038 git-gui.sh:2545
 msgid "Cut"
 msgstr "Klipp ut"
 
-#: git-gui.sh:1949 git-gui.sh:2446 git-gui.sh:2520 git-gui.sh:2614
+#: git-gui.sh:2041 git-gui.sh:2548 git-gui.sh:2622 git-gui.sh:2715
 #: lib/console.tcl:69
 msgid "Copy"
 msgstr "Kopiera"
 
-#: git-gui.sh:1952 git-gui.sh:2449
+#: git-gui.sh:2044 git-gui.sh:2551
 msgid "Paste"
 msgstr "Klistra in"
 
-#: git-gui.sh:1955 git-gui.sh:2452 lib/branch_delete.tcl:26
+#: git-gui.sh:2047 git-gui.sh:2554 lib/branch_delete.tcl:26
 #: lib/remote_branch_delete.tcl:38
 msgid "Delete"
 msgstr "Ta bort"
 
-#: git-gui.sh:1959 git-gui.sh:2456 git-gui.sh:2618 lib/console.tcl:71
+#: git-gui.sh:2051 git-gui.sh:2558 git-gui.sh:2719 lib/console.tcl:71
 msgid "Select All"
 msgstr "Markera alla"
 
-#: git-gui.sh:1968
+#: git-gui.sh:2060
 msgid "Create..."
 msgstr "Skapa..."
 
-#: git-gui.sh:1974
+#: git-gui.sh:2066
 msgid "Checkout..."
 msgstr "Checka ut..."
 
-#: git-gui.sh:1980
+#: git-gui.sh:2072
 msgid "Rename..."
 msgstr "Byt namn..."
 
-#: git-gui.sh:1985 git-gui.sh:2085
+#: git-gui.sh:2077 git-gui.sh:2187
 msgid "Delete..."
 msgstr "Ta bort..."
 
-#: git-gui.sh:1990
+#: git-gui.sh:2082
 msgid "Reset..."
 msgstr "Återställ..."
 
-#: git-gui.sh:2002 git-gui.sh:2389
+#: git-gui.sh:2094 git-gui.sh:2491
 msgid "New Commit"
 msgstr "Ny incheckning"
 
-#: git-gui.sh:2010 git-gui.sh:2396
+#: git-gui.sh:2102 git-gui.sh:2498
 msgid "Amend Last Commit"
 msgstr "Lägg till föregående incheckning"
 
-#: git-gui.sh:2019 git-gui.sh:2356 lib/remote_branch_delete.tcl:99
+#: git-gui.sh:2111 git-gui.sh:2458 lib/remote_branch_delete.tcl:99
 msgid "Rescan"
 msgstr "Sök på nytt"
 
-#: git-gui.sh:2025
+#: git-gui.sh:2117
 msgid "Stage To Commit"
 msgstr "Köa för incheckning"
 
-#: git-gui.sh:2031
+#: git-gui.sh:2123
 msgid "Stage Changed Files To Commit"
 msgstr "Köa ändrade filer för incheckning"
 
-#: git-gui.sh:2037
+#: git-gui.sh:2129
 msgid "Unstage From Commit"
 msgstr "Ta bort från incheckningskö"
 
-#: git-gui.sh:2042 lib/index.tcl:395
+#: git-gui.sh:2134 lib/index.tcl:395
 msgid "Revert Changes"
 msgstr "Återställ ändringar"
 
-#: git-gui.sh:2049 git-gui.sh:2368 git-gui.sh:2467
+#: git-gui.sh:2141 git-gui.sh:2702
+msgid "Show Less Context"
+msgstr "Visa mindre sammanhang"
+
+#: git-gui.sh:2145 git-gui.sh:2706
+msgid "Show More Context"
+msgstr "Visa mer sammanhang"
+
+#: git-gui.sh:2151 git-gui.sh:2470 git-gui.sh:2569
 msgid "Sign Off"
 msgstr "Skriv under"
 
-#: git-gui.sh:2053 git-gui.sh:2372
+#: git-gui.sh:2155 git-gui.sh:2474
 msgid "Commit@@verb"
 msgstr "Checka in"
 
-#: git-gui.sh:2064
+#: git-gui.sh:2166
 msgid "Local Merge..."
 msgstr "Lokal sammanslagning..."
 
-#: git-gui.sh:2069
+#: git-gui.sh:2171
 msgid "Abort Merge..."
 msgstr "Avbryt sammanslagning..."
 
-#: git-gui.sh:2081
+#: git-gui.sh:2183
 msgid "Push..."
 msgstr "Sänd..."
 
-#: git-gui.sh:2092 lib/choose_repository.tcl:41
-msgid "Apple"
-msgstr "Äpple"
-
-#: git-gui.sh:2095 git-gui.sh:2117 lib/about.tcl:14
+#: git-gui.sh:2197 git-gui.sh:2219 lib/about.tcl:14
 #: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50
 #, tcl-format
 msgid "About %s"
 msgstr "Om %s"
 
-#: git-gui.sh:2099
+#: git-gui.sh:2201
 msgid "Preferences..."
 msgstr "Inställningar..."
 
-#: git-gui.sh:2107 git-gui.sh:2639
+#: git-gui.sh:2209 git-gui.sh:2740
 msgid "Options..."
 msgstr "Alternativ..."
 
-#: git-gui.sh:2113 lib/choose_repository.tcl:47
+#: git-gui.sh:2215 lib/choose_repository.tcl:47
 msgid "Help"
 msgstr "Hjälp"
 
-#: git-gui.sh:2154
+#: git-gui.sh:2256
 msgid "Online Documentation"
 msgstr "Webbdokumentation"
 
-#: git-gui.sh:2238
+#: git-gui.sh:2340
 #, tcl-format
 msgid "fatal: cannot stat path %s: No such file or directory"
 msgstr ""
 "ödesdigert: kunde inte ta status på sökvägen %s: Fil eller katalog saknas"
 
-#: git-gui.sh:2271
+#: git-gui.sh:2373
 msgid "Current Branch:"
 msgstr "Aktuell gren:"
 
-#: git-gui.sh:2292
+#: git-gui.sh:2394
 msgid "Staged Changes (Will Commit)"
 msgstr "Köade ändringar (kommer att checkas in)"
 
-#: git-gui.sh:2312
+#: git-gui.sh:2414
 msgid "Unstaged Changes"
 msgstr "Oköade ändringar"
 
-#: git-gui.sh:2362
+#: git-gui.sh:2464
 msgid "Stage Changed"
 msgstr "Köa ändrade"
 
-#: git-gui.sh:2378 lib/transport.tcl:93 lib/transport.tcl:182
+#: git-gui.sh:2480 lib/transport.tcl:93 lib/transport.tcl:182
 msgid "Push"
 msgstr "Sänd"
 
-#: git-gui.sh:2408
+#: git-gui.sh:2510
 msgid "Initial Commit Message:"
 msgstr "Inledande incheckningsmeddelande:"
 
-#: git-gui.sh:2409
+#: git-gui.sh:2511
 msgid "Amended Commit Message:"
 msgstr "Utökat incheckningsmeddelande:"
 
-#: git-gui.sh:2410
+#: git-gui.sh:2512
 msgid "Amended Initial Commit Message:"
 msgstr "Utökat inledande incheckningsmeddelande:"
 
-#: git-gui.sh:2411
+#: git-gui.sh:2513
 msgid "Amended Merge Commit Message:"
 msgstr "Utökat incheckningsmeddelande för sammanslagning:"
 
-#: git-gui.sh:2412
+#: git-gui.sh:2514
 msgid "Merge Commit Message:"
 msgstr "Incheckningsmeddelande för sammanslagning:"
 
-#: git-gui.sh:2413
+#: git-gui.sh:2515
 msgid "Commit Message:"
 msgstr "Incheckningsmeddelande:"
 
-#: git-gui.sh:2459 git-gui.sh:2622 lib/console.tcl:73
+#: git-gui.sh:2561 git-gui.sh:2723 lib/console.tcl:73
 msgid "Copy All"
 msgstr "Kopiera alla"
 
-#: git-gui.sh:2483 lib/blame.tcl:107
+#: git-gui.sh:2585 lib/blame.tcl:100
 msgid "File:"
 msgstr "Fil:"
 
-#: git-gui.sh:2589
+#: git-gui.sh:2691
 msgid "Apply/Reverse Hunk"
 msgstr "Använd/återställ del"
 
-#: git-gui.sh:2595
-msgid "Show Less Context"
-msgstr "Visa mindre sammanhang"
+#: git-gui.sh:2696
+msgid "Apply/Reverse Line"
+msgstr "Använd/återställ rad"
 
-#: git-gui.sh:2602
-msgid "Show More Context"
-msgstr "Visa mer sammanhang"
-
-#: git-gui.sh:2610
+#: git-gui.sh:2711
 msgid "Refresh"
 msgstr "Uppdatera"
 
-#: git-gui.sh:2631
+#: git-gui.sh:2732
 msgid "Decrease Font Size"
 msgstr "Minska teckensnittsstorlek"
 
-#: git-gui.sh:2635
+#: git-gui.sh:2736
 msgid "Increase Font Size"
 msgstr "Öka teckensnittsstorlek"
 
-#: git-gui.sh:2646
+#: git-gui.sh:2747
 msgid "Unstage Hunk From Commit"
 msgstr "Ta bort del ur incheckningskö"
 
-#: git-gui.sh:2648
+#: git-gui.sh:2748
+msgid "Unstage Line From Commit"
+msgstr "Ta bort rad ur incheckningskö"
+
+#: git-gui.sh:2750
 msgid "Stage Hunk For Commit"
 msgstr "Ställ del i incheckningskö"
 
-#: git-gui.sh:2667
+#: git-gui.sh:2751
+msgid "Stage Line For Commit"
+msgstr "Ställ rad i incheckningskö"
+
+#: git-gui.sh:2771
 msgid "Initializing..."
 msgstr "Initierar..."
 
-#: git-gui.sh:2762
+#: git-gui.sh:2876
 #, tcl-format
 msgid ""
 "Possible environment issues exist.\n"
@@ -449,7 +451,7 @@
 "av %s:\n"
 "\n"
 
-#: git-gui.sh:2792
+#: git-gui.sh:2906
 msgid ""
 "\n"
 "This is due to a known issue with the\n"
@@ -459,7 +461,7 @@
 "Detta beror på ett känt problem med\n"
 "Tcl-binären som följer med Cygwin."
 
-#: git-gui.sh:2797
+#: git-gui.sh:2911
 #, tcl-format
 msgid ""
 "\n"
@@ -480,64 +482,80 @@
 msgid "git-gui - a graphical user interface for Git."
 msgstr "git-gui - ett grafiskt användargränssnitt för Git."
 
-#: lib/blame.tcl:77
+#: lib/blame.tcl:70
 msgid "File Viewer"
 msgstr "Filvisare"
 
-#: lib/blame.tcl:81
+#: lib/blame.tcl:74
 msgid "Commit:"
 msgstr "Incheckning:"
 
-#: lib/blame.tcl:264
+#: lib/blame.tcl:257
 msgid "Copy Commit"
 msgstr "Kopiera incheckning"
 
-#: lib/blame.tcl:384
+#: lib/blame.tcl:260
+msgid "Do Full Copy Detection"
+msgstr "Gör full kopieringsigenkänning"
+
+#: lib/blame.tcl:388
 #, tcl-format
 msgid "Reading %s..."
 msgstr "Läser %s..."
 
-#: lib/blame.tcl:488
+#: lib/blame.tcl:492
 msgid "Loading copy/move tracking annotations..."
 msgstr "Läser annoteringar för kopiering/flyttning..."
 
-#: lib/blame.tcl:508
+#: lib/blame.tcl:512
 msgid "lines annotated"
 msgstr "rader annoterade"
 
-#: lib/blame.tcl:689
+#: lib/blame.tcl:704
 msgid "Loading original location annotations..."
 msgstr "Läser in annotering av originalplacering..."
 
-#: lib/blame.tcl:692
+#: lib/blame.tcl:707
 msgid "Annotation complete."
 msgstr "Annotering fullbordad."
 
-#: lib/blame.tcl:746
+#: lib/blame.tcl:737
+msgid "Busy"
+msgstr "Upptagen"
+
+#: lib/blame.tcl:738
+msgid "Annotation process is already running."
+msgstr "Annoteringsprocess körs redan."
+
+#: lib/blame.tcl:777
+msgid "Running thorough copy detection..."
+msgstr "Kör grundlig kopieringsigenkänning..."
+
+#: lib/blame.tcl:827
 msgid "Loading annotation..."
 msgstr "Läser in annotering..."
 
-#: lib/blame.tcl:802
+#: lib/blame.tcl:883
 msgid "Author:"
 msgstr "Författare:"
 
-#: lib/blame.tcl:806
+#: lib/blame.tcl:887
 msgid "Committer:"
 msgstr "Incheckare:"
 
-#: lib/blame.tcl:811
+#: lib/blame.tcl:892
 msgid "Original File:"
 msgstr "Ursprunglig fil:"
 
-#: lib/blame.tcl:925
+#: lib/blame.tcl:1006
 msgid "Originally By:"
 msgstr "Ursprungligen av:"
 
-#: lib/blame.tcl:931
+#: lib/blame.tcl:1012
 msgid "In File:"
 msgstr "I filen:"
 
-#: lib/blame.tcl:936
+#: lib/blame.tcl:1017
 msgid "Copied Or Moved Here By:"
 msgstr "Kopierad eller flyttad hit av:"
 
@@ -551,7 +569,7 @@
 
 #: lib/branch_checkout.tcl:27 lib/branch_create.tcl:35
 #: lib/branch_delete.tcl:32 lib/branch_rename.tcl:30 lib/browser.tcl:282
-#: lib/checkout_op.tcl:522 lib/choose_font.tcl:43 lib/merge.tcl:171
+#: lib/checkout_op.tcl:544 lib/choose_font.tcl:43 lib/merge.tcl:171
 #: lib/option.tcl:103 lib/remote_branch_delete.tcl:42 lib/transport.tcl:97
 msgid "Cancel"
 msgstr "Avbryt"
@@ -560,7 +578,7 @@
 msgid "Revision"
 msgstr "Revision"
 
-#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:242
+#: lib/branch_checkout.tcl:36 lib/branch_create.tcl:69 lib/option.tcl:244
 msgid "Options"
 msgstr "Alternativ"
 
@@ -612,7 +630,7 @@
 msgid "Fast Forward Only"
 msgstr "Endast snabbspolning"
 
-#: lib/branch_create.tcl:85 lib/checkout_op.tcl:514
+#: lib/branch_create.tcl:85 lib/checkout_op.tcl:536
 msgid "Reset"
 msgstr "Återställ"
 
@@ -702,7 +720,7 @@
 msgid "Please select a branch to rename."
 msgstr "Välj en gren att byta namn på."
 
-#: lib/branch_rename.tcl:96 lib/checkout_op.tcl:179
+#: lib/branch_rename.tcl:96 lib/checkout_op.tcl:201
 #, tcl-format
 msgid "Branch '%s' already exists."
 msgstr "Grenen \"%s\" finns redan."
@@ -734,31 +752,36 @@
 msgstr "Bläddra filer på grenen"
 
 #: lib/browser.tcl:278 lib/choose_repository.tcl:387
-#: lib/choose_repository.tcl:474 lib/choose_repository.tcl:484
-#: lib/choose_repository.tcl:987
+#: lib/choose_repository.tcl:472 lib/choose_repository.tcl:482
+#: lib/choose_repository.tcl:985
 msgid "Browse"
 msgstr "Bläddra"
 
-#: lib/checkout_op.tcl:79
+#: lib/checkout_op.tcl:84
 #, tcl-format
 msgid "Fetching %s from %s"
 msgstr "Hämtar %s från %s"
 
-#: lib/checkout_op.tcl:127
+#: lib/checkout_op.tcl:132
 #, tcl-format
 msgid "fatal: Cannot resolve %s"
 msgstr "ödesdigert: Kunde inte slå upp %s"
 
-#: lib/checkout_op.tcl:140 lib/console.tcl:81 lib/database.tcl:31
+#: lib/checkout_op.tcl:145 lib/console.tcl:81 lib/database.tcl:31
 msgid "Close"
 msgstr "Stäng"
 
-#: lib/checkout_op.tcl:169
+#: lib/checkout_op.tcl:174
 #, tcl-format
 msgid "Branch '%s' does not exist."
 msgstr "Grenen \"%s\" finns inte."
 
-#: lib/checkout_op.tcl:206
+#: lib/checkout_op.tcl:193
+#, tcl-format
+msgid "Failed to configure simplified git-pull for '%s'."
+msgstr "Kunde inte konfigurera förenklad git-pull för '%s'."
+
+#: lib/checkout_op.tcl:228
 #, tcl-format
 msgid ""
 "Branch '%s' already exists.\n"
@@ -771,21 +794,21 @@
 "Den kan inte snabbspolas till %s.\n"
 "En sammanslagning krävs."
 
-#: lib/checkout_op.tcl:220
+#: lib/checkout_op.tcl:242
 #, tcl-format
 msgid "Merge strategy '%s' not supported."
 msgstr "Sammanslagningsstrategin \"%s\" stöds inte."
 
-#: lib/checkout_op.tcl:239
+#: lib/checkout_op.tcl:261
 #, tcl-format
 msgid "Failed to update '%s'."
 msgstr "Misslyckades med att uppdatera \"%s\"."
 
-#: lib/checkout_op.tcl:251
+#: lib/checkout_op.tcl:273
 msgid "Staging area (index) is already locked."
 msgstr "Köområdet (index) är redan låst."
 
-#: lib/checkout_op.tcl:266
+#: lib/checkout_op.tcl:288
 msgid ""
 "Last scanned state does not match repository state.\n"
 "\n"
@@ -801,30 +824,30 @@
 "\n"
 "Sökningen kommer att startas automatiskt nu.\n"
 
-#: lib/checkout_op.tcl:322
+#: lib/checkout_op.tcl:344
 #, tcl-format
 msgid "Updating working directory to '%s'..."
 msgstr "Uppdaterar arbetskatalogen till \"%s\"..."
 
-#: lib/checkout_op.tcl:323
+#: lib/checkout_op.tcl:345
 msgid "files checked out"
 msgstr "filer utcheckade"
 
-#: lib/checkout_op.tcl:353
+#: lib/checkout_op.tcl:375
 #, tcl-format
 msgid "Aborted checkout of '%s' (file level merging is required)."
 msgstr "Avbryter utcheckning av \"%s\" (sammanslagning på filnivå krävs)."
 
-#: lib/checkout_op.tcl:354
+#: lib/checkout_op.tcl:376
 msgid "File level merge required."
 msgstr "Sammanslagning på filnivå krävs."
 
-#: lib/checkout_op.tcl:358
+#: lib/checkout_op.tcl:380
 #, tcl-format
 msgid "Staying on branch '%s'."
 msgstr "Stannar på grenen \"%s\"."
 
-#: lib/checkout_op.tcl:429
+#: lib/checkout_op.tcl:451
 msgid ""
 "You are no longer on a local branch.\n"
 "\n"
@@ -836,31 +859,31 @@
 "Om du ville vara på en gren skapar du en nu, baserad på \"Denna frånkopplade "
 "utcheckning\"."
 
-#: lib/checkout_op.tcl:446 lib/checkout_op.tcl:450
+#: lib/checkout_op.tcl:468 lib/checkout_op.tcl:472
 #, tcl-format
 msgid "Checked out '%s'."
 msgstr "Checkade ut \"%s\"."
 
-#: lib/checkout_op.tcl:478
+#: lib/checkout_op.tcl:500
 #, tcl-format
 msgid "Resetting '%s' to '%s' will lose the following commits:"
 msgstr ""
 "Om du återställer \"%s\" till \"%s\" går följande incheckningar förlorade:"
 
-#: lib/checkout_op.tcl:500
+#: lib/checkout_op.tcl:522
 msgid "Recovering lost commits may not be easy."
 msgstr "Det kanske inte är så enkelt att återskapa förlorade incheckningar."
 
-#: lib/checkout_op.tcl:505
+#: lib/checkout_op.tcl:527
 #, tcl-format
 msgid "Reset '%s'?"
 msgstr "Återställa \"%s\"?"
 
-#: lib/checkout_op.tcl:510 lib/merge.tcl:163
+#: lib/checkout_op.tcl:532 lib/merge.tcl:163
 msgid "Visualize"
 msgstr "Visualisera"
 
-#: lib/checkout_op.tcl:578
+#: lib/checkout_op.tcl:600
 #, tcl-format
 msgid ""
 "Failed to set current branch.\n"
@@ -913,7 +936,7 @@
 msgid "New..."
 msgstr "Nytt..."
 
-#: lib/choose_repository.tcl:94 lib/choose_repository.tcl:460
+#: lib/choose_repository.tcl:94 lib/choose_repository.tcl:458
 msgid "Clone Existing Repository"
 msgstr "Klona befintligt arkiv"
 
@@ -921,7 +944,7 @@
 msgid "Clone..."
 msgstr "Klona..."
 
-#: lib/choose_repository.tcl:107 lib/choose_repository.tcl:976
+#: lib/choose_repository.tcl:107 lib/choose_repository.tcl:974
 msgid "Open Existing Repository"
 msgstr "Öppna befintligt arkiv"
 
@@ -943,183 +966,183 @@
 msgid "Failed to create repository %s:"
 msgstr "Kunde inte skapa arkivet %s:"
 
-#: lib/choose_repository.tcl:381 lib/choose_repository.tcl:478
+#: lib/choose_repository.tcl:381 lib/choose_repository.tcl:476
 msgid "Directory:"
 msgstr "Katalog:"
 
-#: lib/choose_repository.tcl:412 lib/choose_repository.tcl:537
-#: lib/choose_repository.tcl:1011
+#: lib/choose_repository.tcl:410 lib/choose_repository.tcl:535
+#: lib/choose_repository.tcl:1007
 msgid "Git Repository"
 msgstr "Gitarkiv"
 
-#: lib/choose_repository.tcl:437
+#: lib/choose_repository.tcl:435
 #, tcl-format
 msgid "Directory %s already exists."
 msgstr "Katalogen %s finns redan."
 
-#: lib/choose_repository.tcl:441
+#: lib/choose_repository.tcl:439
 #, tcl-format
 msgid "File %s already exists."
 msgstr "Filen %s finns redan."
 
-#: lib/choose_repository.tcl:455
+#: lib/choose_repository.tcl:453
 msgid "Clone"
 msgstr "Klona"
 
-#: lib/choose_repository.tcl:468
+#: lib/choose_repository.tcl:466
 msgid "URL:"
 msgstr "Webbadress:"
 
-#: lib/choose_repository.tcl:489
+#: lib/choose_repository.tcl:487
 msgid "Clone Type:"
 msgstr "Typ av klon:"
 
-#: lib/choose_repository.tcl:495
+#: lib/choose_repository.tcl:493
 msgid "Standard (Fast, Semi-Redundant, Hardlinks)"
 msgstr "Standard (snabb, semiredundant, hårda länkar)"
 
-#: lib/choose_repository.tcl:501
+#: lib/choose_repository.tcl:499
 msgid "Full Copy (Slower, Redundant Backup)"
 msgstr "Full kopia (långsammare, redundant säkerhetskopia)"
 
-#: lib/choose_repository.tcl:507
+#: lib/choose_repository.tcl:505
 msgid "Shared (Fastest, Not Recommended, No Backup)"
 msgstr "Delad (snabbast, rekommenderas ej, ingen säkerhetskopia)"
 
-#: lib/choose_repository.tcl:543 lib/choose_repository.tcl:590
-#: lib/choose_repository.tcl:736 lib/choose_repository.tcl:806
-#: lib/choose_repository.tcl:1017 lib/choose_repository.tcl:1025
+#: lib/choose_repository.tcl:541 lib/choose_repository.tcl:588
+#: lib/choose_repository.tcl:734 lib/choose_repository.tcl:804
+#: lib/choose_repository.tcl:1013 lib/choose_repository.tcl:1021
 #, tcl-format
 msgid "Not a Git repository: %s"
 msgstr "Inte ett Gitarkiv: %s"
 
-#: lib/choose_repository.tcl:579
+#: lib/choose_repository.tcl:577
 msgid "Standard only available for local repository."
 msgstr "Standard är endast tillgängligt för lokala arkiv."
 
-#: lib/choose_repository.tcl:583
+#: lib/choose_repository.tcl:581
 msgid "Shared only available for local repository."
 msgstr "Delat är endast tillgängligt för lokala arkiv."
 
-#: lib/choose_repository.tcl:604
+#: lib/choose_repository.tcl:602
 #, tcl-format
 msgid "Location %s already exists."
 msgstr "Platsen %s finns redan."
 
-#: lib/choose_repository.tcl:615
+#: lib/choose_repository.tcl:613
 msgid "Failed to configure origin"
 msgstr "Kunde inte konfigurera ursprung"
 
-#: lib/choose_repository.tcl:627
+#: lib/choose_repository.tcl:625
 msgid "Counting objects"
 msgstr "Räknar objekt"
 
-#: lib/choose_repository.tcl:628
+#: lib/choose_repository.tcl:626
 msgid "buckets"
 msgstr "hinkar"
 
-#: lib/choose_repository.tcl:652
+#: lib/choose_repository.tcl:650
 #, tcl-format
 msgid "Unable to copy objects/info/alternates: %s"
 msgstr "Kunde inte kopiera objekt/info/alternativ: %s"
 
-#: lib/choose_repository.tcl:688
+#: lib/choose_repository.tcl:686
 #, tcl-format
 msgid "Nothing to clone from %s."
 msgstr "Ingenting att klona från %s."
 
-#: lib/choose_repository.tcl:690 lib/choose_repository.tcl:904
-#: lib/choose_repository.tcl:916
+#: lib/choose_repository.tcl:688 lib/choose_repository.tcl:902
+#: lib/choose_repository.tcl:914
 msgid "The 'master' branch has not been initialized."
 msgstr "Grenen \"master\" har inte initierats."
 
-#: lib/choose_repository.tcl:703
+#: lib/choose_repository.tcl:701
 msgid "Hardlinks are unavailable.  Falling back to copying."
 msgstr "Hårda länkar är inte tillgängliga. Faller tillbaka på kopiering."
 
-#: lib/choose_repository.tcl:715
+#: lib/choose_repository.tcl:713
 #, tcl-format
 msgid "Cloning from %s"
 msgstr "Klonar från %s"
 
-#: lib/choose_repository.tcl:746
+#: lib/choose_repository.tcl:744
 msgid "Copying objects"
 msgstr "Kopierar objekt"
 
-#: lib/choose_repository.tcl:747
+#: lib/choose_repository.tcl:745
 msgid "KiB"
 msgstr "KiB"
 
-#: lib/choose_repository.tcl:771
+#: lib/choose_repository.tcl:769
 #, tcl-format
 msgid "Unable to copy object: %s"
 msgstr "Kunde inte kopiera objekt: %s"
 
-#: lib/choose_repository.tcl:781
+#: lib/choose_repository.tcl:779
 msgid "Linking objects"
 msgstr "Länkar objekt"
 
-#: lib/choose_repository.tcl:782
+#: lib/choose_repository.tcl:780
 msgid "objects"
 msgstr "objekt"
 
-#: lib/choose_repository.tcl:790
+#: lib/choose_repository.tcl:788
 #, tcl-format
 msgid "Unable to hardlink object: %s"
 msgstr "Kunde inte hårdlänka objekt: %s"
 
-#: lib/choose_repository.tcl:845
+#: lib/choose_repository.tcl:843
 msgid "Cannot fetch branches and objects.  See console output for details."
 msgstr "Kunde inte hämta grenar och objekt. Se konsolutdata för detaljer."
 
-#: lib/choose_repository.tcl:856
+#: lib/choose_repository.tcl:854
 msgid "Cannot fetch tags.  See console output for details."
 msgstr "Kunde inte hämta taggar. Se konsolutdata för detaljer."
 
-#: lib/choose_repository.tcl:880
+#: lib/choose_repository.tcl:878
 msgid "Cannot determine HEAD.  See console output for details."
 msgstr "Kunde inte avgöra HEAD. Se konsolutdata för detaljer."
 
-#: lib/choose_repository.tcl:889
+#: lib/choose_repository.tcl:887
 #, tcl-format
 msgid "Unable to cleanup %s"
 msgstr "Kunde inte städa upp %s"
 
-#: lib/choose_repository.tcl:895
+#: lib/choose_repository.tcl:893
 msgid "Clone failed."
 msgstr "Kloning misslyckades."
 
-#: lib/choose_repository.tcl:902
+#: lib/choose_repository.tcl:900
 msgid "No default branch obtained."
 msgstr "Hämtade ingen standardgren."
 
-#: lib/choose_repository.tcl:913
+#: lib/choose_repository.tcl:911
 #, tcl-format
 msgid "Cannot resolve %s as a commit."
 msgstr "Kunde inte slå upp %s till någon incheckning."
 
-#: lib/choose_repository.tcl:925
+#: lib/choose_repository.tcl:923
 msgid "Creating working directory"
 msgstr "Skapar arbetskatalog"
 
-#: lib/choose_repository.tcl:926 lib/index.tcl:65 lib/index.tcl:127
+#: lib/choose_repository.tcl:924 lib/index.tcl:65 lib/index.tcl:127
 #: lib/index.tcl:193
 msgid "files"
 msgstr "filer"
 
-#: lib/choose_repository.tcl:955
+#: lib/choose_repository.tcl:953
 msgid "Initial file checkout failed."
 msgstr "Inledande filutcheckning misslyckades."
 
-#: lib/choose_repository.tcl:971
+#: lib/choose_repository.tcl:969
 msgid "Open"
 msgstr "Öppna"
 
-#: lib/choose_repository.tcl:981
+#: lib/choose_repository.tcl:979
 msgid "Repository:"
 msgstr "Arkiv:"
 
-#: lib/choose_repository.tcl:1031
+#: lib/choose_repository.tcl:1027
 #, tcl-format
 msgid "Failed to open repository %s:"
 msgstr "Kunde inte öppna arkivet %s:"
@@ -1410,7 +1433,7 @@
 msgid "Invalid date from Git: %s"
 msgstr "Ogiltigt datum från Git: %s"
 
-#: lib/diff.tcl:42
+#: lib/diff.tcl:44
 #, tcl-format
 msgid ""
 "No differences detected.\n"
@@ -1433,40 +1456,48 @@
 "En sökning kommer automatiskt att startas för att hitta andra filer som kan "
 "vara i samma tillstånd."
 
-#: lib/diff.tcl:81
+#: lib/diff.tcl:83
 #, tcl-format
 msgid "Loading diff of %s..."
 msgstr "Läser differens för %s..."
 
-#: lib/diff.tcl:114 lib/diff.tcl:184
+#: lib/diff.tcl:116 lib/diff.tcl:190
 #, tcl-format
 msgid "Unable to display %s"
 msgstr "Kan inte visa %s"
 
-#: lib/diff.tcl:115
+#: lib/diff.tcl:117
 msgid "Error loading file:"
 msgstr "Fel vid läsning av fil:"
 
-#: lib/diff.tcl:122
+#: lib/diff.tcl:124
 msgid "Git Repository (subproject)"
 msgstr "Gitarkiv (underprojekt)"
 
-#: lib/diff.tcl:134
+#: lib/diff.tcl:136
 msgid "* Binary file (not showing content)."
 msgstr "* Binärfil (visar inte innehållet)."
 
-#: lib/diff.tcl:185
+#: lib/diff.tcl:191
 msgid "Error loading diff:"
 msgstr "Fel vid inläsning av differens:"
 
-#: lib/diff.tcl:303
+#: lib/diff.tcl:313
 msgid "Failed to unstage selected hunk."
 msgstr "Kunde inte ta bort den valda delen från kön."
 
-#: lib/diff.tcl:310
+#: lib/diff.tcl:320
 msgid "Failed to stage selected hunk."
 msgstr "Kunde inte lägga till den valda delen till kön."
 
+#: lib/diff.tcl:386
+msgid "Failed to unstage selected line."
+msgstr "Kunde inte ta bort den valda raden från kön."
+
+#: lib/diff.tcl:394
+msgid "Failed to stage selected line."
+msgstr "Kunde inte lägga till den valda raden till kön."
+
 #: lib/error.tcl:20 lib/error.tcl:114
 msgid "error"
 msgstr "fel"
@@ -1673,11 +1704,11 @@
 msgid "files reset"
 msgstr "filer återställda"
 
-#: lib/merge.tcl:265
+#: lib/merge.tcl:266
 msgid "Abort failed."
 msgstr "Misslyckades avbryta."
 
-#: lib/merge.tcl:267
+#: lib/merge.tcl:268
 msgid "Abort completed.  Ready."
 msgstr "Avbrytning fullbordad. Redo."
 
@@ -1731,39 +1762,47 @@
 msgstr "Matcha spårade grenar"
 
 #: lib/option.tcl:126
+msgid "Blame Copy Only On Changed Files"
+msgstr "Klandra kopiering bara i ändrade filer"
+
+#: lib/option.tcl:127
+msgid "Minimum Letters To Blame Copy On"
+msgstr "Minsta antal tecken att klandra kopiering för"
+
+#: lib/option.tcl:128
 msgid "Number of Diff Context Lines"
 msgstr "Antal rader sammanhang i differenser"
 
-#: lib/option.tcl:127
+#: lib/option.tcl:129
 msgid "Commit Message Text Width"
 msgstr "Textbredd för incheckningsmeddelande"
 
-#: lib/option.tcl:128
+#: lib/option.tcl:130
 msgid "New Branch Name Template"
 msgstr "Mall för namn på nya grenar"
 
-#: lib/option.tcl:192
+#: lib/option.tcl:194
 msgid "Spelling Dictionary:"
 msgstr "Stavningsordlista:"
 
-#: lib/option.tcl:216
+#: lib/option.tcl:218
 msgid "Change Font"
 msgstr "Byt teckensnitt"
 
-#: lib/option.tcl:220
+#: lib/option.tcl:222
 #, tcl-format
 msgid "Choose %s"
 msgstr "Välj %s"
 
-#: lib/option.tcl:226
+#: lib/option.tcl:228
 msgid "pt."
 msgstr "p."
 
-#: lib/option.tcl:240
+#: lib/option.tcl:242
 msgid "Preferences"
 msgstr "Inställningar"
 
-#: lib/option.tcl:275
+#: lib/option.tcl:277
 msgid "Failed to completely save options:"
 msgstr "Misslyckades med att helt spara alternativ:"
 
@@ -1896,15 +1935,15 @@
 msgid "Unrecognized spell checker"
 msgstr "Stavningskontrollprogrammet känns inte igen"
 
-#: lib/spellcheck.tcl:180
+#: lib/spellcheck.tcl:186
 msgid "No Suggestions"
 msgstr "Inga förslag"
 
-#: lib/spellcheck.tcl:381
+#: lib/spellcheck.tcl:387
 msgid "Unexpected EOF from spell checker"
 msgstr "Oväntat filslut från stavningskontroll"
 
-#: lib/spellcheck.tcl:385
+#: lib/spellcheck.tcl:391
 msgid "Spell Checker Failed"
 msgstr "Stavningskontroll misslyckades"
 
@@ -1976,5 +2015,17 @@
 msgid "Include tags"
 msgstr "Ta med taggar"
 
+#~ msgid ""
+#~ "Unable to start gitk:\n"
+#~ "\n"
+#~ "%s does not exist"
+#~ msgstr ""
+#~ "Kan inte starta gitk:\n"
+#~ "\n"
+#~ "%s finns inte"
+
+#~ msgid "Apple"
+#~ msgstr "Äpple"
+
 #~ msgid "Not connected to aspell"
 #~ msgstr "Inte ansluten till aspell"
diff --git a/git-gui/windows/git-gui.sh b/git-gui/windows/git-gui.sh
index 98f32c0..53c3a94 100644
--- a/git-gui/windows/git-gui.sh
+++ b/git-gui/windows/git-gui.sh
@@ -8,9 +8,12 @@
 	incr argc -2
 }
 
-set gitguidir [file dirname [info script]]
-regsub -all ";" $gitguidir "\\;" gitguidir
-set env(PATH) "$gitguidir;$env(PATH)"
-unset gitguidir
+set bindir [file dirname \
+            [file dirname \
+             [file dirname [info script]]]]
+set bindir [file join $bindir bin]
+regsub -all ";" $bindir "\\;" bindir
+set env(PATH) "$bindir;$env(PATH)"
+unset bindir
 
 source [file join [file dirname [info script]] git-gui.tcl]
diff --git a/git-instaweb.sh b/git-instaweb.sh
index af0fde5..0843372 100755
--- a/git-instaweb.sh
+++ b/git-instaweb.sh
@@ -6,7 +6,7 @@
 PERL='@@PERL@@'
 OPTIONS_KEEPDASHDASH=
 OPTIONS_SPEC="\
-git-instaweb [options] (--start | --stop | --restart)
+git instaweb [options] (--start | --stop | --restart)
 --
 l,local        only bind on 127.0.0.1
 p,port=        the port to bind to
diff --git a/git-merge-stupid.sh b/git-merge-stupid.sh
deleted file mode 100755
index f612d47..0000000
--- a/git-merge-stupid.sh
+++ /dev/null
@@ -1,80 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2005 Linus Torvalds
-#
-# Resolve two trees, 'stupid merge'.
-
-# The first parameters up to -- are merge bases; the rest are heads.
-bases= head= remotes= sep_seen=
-for arg
-do
-	case ",$sep_seen,$head,$arg," in
-	*,--,)
-		sep_seen=yes
-		;;
-	,yes,,*)
-		head=$arg
-		;;
-	,yes,*)
-		remotes="$remotes$arg "
-		;;
-	*)
-		bases="$bases$arg "
-		;;
-	esac
-done
-
-# Give up if we are given two or more remotes -- not handling octopus.
-case "$remotes" in
-?*' '?*)
-	exit 2 ;;
-esac
-
-# Find an optimum merge base if there are more than one candidates.
-case "$bases" in
-?*' '?*)
-	echo "Trying to find the optimum merge base."
-	G=.tmp-index$$
-	best=
-	best_cnt=-1
-	for c in $bases
-	do
-		rm -f $G
-		GIT_INDEX_FILE=$G git read-tree -m $c $head $remotes \
-			 2>/dev/null ||	continue
-		# Count the paths that are unmerged.
-		cnt=`GIT_INDEX_FILE=$G git ls-files --unmerged | wc -l`
-		if test $best_cnt -le 0 -o $cnt -le $best_cnt
-		then
-			best=$c
-			best_cnt=$cnt
-			if test "$best_cnt" -eq 0
-			then
-				# Cannot do any better than all trivial merge.
-				break
-			fi
-		fi
-	done
-	rm -f $G
-	common="$best"
-	;;
-*)
-	common="$bases"
-	;;
-esac
-
-git update-index --refresh 2>/dev/null
-git read-tree -u -m $common $head $remotes || exit 2
-echo "Trying simple merge."
-if result_tree=$(git write-tree  2>/dev/null)
-then
-	exit 0
-else
-	echo "Simple merge failed, trying Automatic merge."
-	if git-merge-index -o git-merge-one-file -a
-	then
-		exit 0
-	else
-		exit 1
-	fi
-fi
diff --git a/git-mergetool.sh b/git-mergetool.sh
index fcdec4a..d4078a6 100755
--- a/git-mergetool.sh
+++ b/git-mergetool.sh
@@ -141,10 +141,10 @@
     fi
 
     ext="$$$(expr "$MERGED" : '.*\(\.[^/]*\)$')"
-    BACKUP="$MERGED.BACKUP.$ext"
-    LOCAL="$MERGED.LOCAL.$ext"
-    REMOTE="$MERGED.REMOTE.$ext"
-    BASE="$MERGED.BASE.$ext"
+    BACKUP="./$MERGED.BACKUP.$ext"
+    LOCAL="./$MERGED.LOCAL.$ext"
+    REMOTE="./$MERGED.REMOTE.$ext"
+    BASE="./$MERGED.BASE.$ext"
 
     mv -- "$MERGED" "$BACKUP"
     cp -- "$BACKUP" "$MERGED"
@@ -183,29 +183,29 @@
 	kdiff3)
 	    if base_present ; then
 		("$merge_tool_path" --auto --L1 "$MERGED (Base)" --L2 "$MERGED (Local)" --L3 "$MERGED (Remote)" \
-		    -o "$MERGED" -- "$BASE" "$LOCAL" "$REMOTE" > /dev/null 2>&1)
+		    -o "$MERGED" "$BASE" "$LOCAL" "$REMOTE" > /dev/null 2>&1)
 	    else
 		("$merge_tool_path" --auto --L1 "$MERGED (Local)" --L2 "$MERGED (Remote)" \
-		    -o "$MERGED" -- "$LOCAL" "$REMOTE" > /dev/null 2>&1)
+		    -o "$MERGED" "$LOCAL" "$REMOTE" > /dev/null 2>&1)
 	    fi
 	    status=$?
 	    ;;
 	tkdiff)
 	    if base_present ; then
-		"$merge_tool_path" -a "$BASE" -o "$MERGED" -- "$LOCAL" "$REMOTE"
+		"$merge_tool_path" -a "$BASE" -o "$MERGED" "$LOCAL" "$REMOTE"
 	    else
-		"$merge_tool_path" -o "$MERGED" -- "$LOCAL" "$REMOTE"
+		"$merge_tool_path" -o "$MERGED" "$LOCAL" "$REMOTE"
 	    fi
 	    status=$?
 	    ;;
 	meld|vimdiff)
 	    touch "$BACKUP"
-	    "$merge_tool_path" -- "$LOCAL" "$MERGED" "$REMOTE"
+	    "$merge_tool_path" "$LOCAL" "$MERGED" "$REMOTE"
 	    check_unchanged
 	    ;;
 	gvimdiff)
 	    touch "$BACKUP"
-	    "$merge_tool_path" -f -- "$LOCAL" "$MERGED" "$REMOTE"
+	    "$merge_tool_path" -f "$LOCAL" "$MERGED" "$REMOTE"
 	    check_unchanged
 	    ;;
 	xxdiff)
@@ -215,13 +215,13 @@
 		    -R 'Accel.SaveAsMerged: "Ctrl-S"' \
 		    -R 'Accel.Search: "Ctrl+F"' \
 		    -R 'Accel.SearchForward: "Ctrl-G"' \
-		    --merged-file "$MERGED" -- "$LOCAL" "$BASE" "$REMOTE"
+		    --merged-file "$MERGED" "$LOCAL" "$BASE" "$REMOTE"
 	    else
 		"$merge_tool_path" -X --show-merged-pane \
 		    -R 'Accel.SaveAsMerged: "Ctrl-S"' \
 		    -R 'Accel.Search: "Ctrl+F"' \
 		    -R 'Accel.SearchForward: "Ctrl-G"' \
-		    --merged-file "$MERGED" -- "$LOCAL" "$REMOTE"
+		    --merged-file "$MERGED" "$LOCAL" "$REMOTE"
 	    fi
 	    check_unchanged
 	    ;;
@@ -296,6 +296,7 @@
 	    esac
 	    ;;
 	--)
+	    shift
 	    break
 	    ;;
 	-*)
diff --git a/git-pull.sh b/git-pull.sh
index 809e537..664fe34 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -107,9 +107,9 @@
 }
 
 test true = "$rebase" && {
-	git update-index --refresh &&
-	git diff-files --quiet &&
-	git diff-index --cached --quiet HEAD -- ||
+	git update-index --ignore-submodules --refresh &&
+	git diff-files --ignore-submodules --quiet &&
+	git diff-index --ignore-submodules --cached --quiet HEAD -- ||
 	die "refusing to pull with rebase: your working tree is not up-to-date"
 
 	. git-parse-remote &&
@@ -121,10 +121,10 @@
 		"refs/remotes/$origin/$reflist" 2>/dev/null)"
 }
 orig_head=$(git rev-parse --verify HEAD 2>/dev/null)
-git-fetch --update-head-ok "$@" || exit 1
+git fetch --update-head-ok "$@" || exit 1
 
 curr_head=$(git rev-parse --verify HEAD 2>/dev/null)
-if test "$curr_head" != "$orig_head"
+if test -n "$orig_head" && test "$curr_head" != "$orig_head"
 then
 	# The fetch involved updating the current branch.
 
@@ -172,7 +172,7 @@
 
 if test -z "$orig_head"
 then
-	git update-ref -m "initial pull" HEAD $merge_head "" &&
+	git update-ref -m "initial pull" HEAD $merge_head "$curr_head" &&
 	git read-tree --reset -u HEAD || exit 1
 	exit
 fi
diff --git a/git-quiltimport.sh b/git-quiltimport.sh
index 7cd8f71..cebaee1 100755
--- a/git-quiltimport.sh
+++ b/git-quiltimport.sh
@@ -1,7 +1,7 @@
 #!/bin/sh
 OPTIONS_KEEPDASHDASH=
 OPTIONS_SPEC="\
-git-quiltimport [options]
+git quiltimport [options]
 --
 n,dry-run     dry run
 author=       author name and email address for patches without any
@@ -53,7 +53,7 @@
 fi
 
 # Temporary directories
-tmp_dir=.dotest
+tmp_dir="$GIT_DIR"/rebase-apply
 tmp_msg="$tmp_dir/msg"
 tmp_patch="$tmp_dir/patch"
 tmp_info="$tmp_dir/info"
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index e3f65bd..124cb58 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -10,14 +10,28 @@
 # The original idea comes from Eric W. Biederman, in
 # http://article.gmane.org/gmane.comp.version-control.git/22407
 
-USAGE='(--continue | --abort | --skip | [--preserve-merges] [--verbose]
-	[--onto <branch>] <upstream> [<branch>])'
+OPTIONS_KEEPDASHDASH=
+OPTIONS_SPEC="\
+git-rebase [-i] [options] [--] <upstream> [<branch>]
+git-rebase [-i] (--continue | --abort | --skip)
+--
+ Available options are
+v,verbose          display a diffstat of what changed upstream
+onto=              rebase onto given branch instead of upstream
+p,preserve-merges  try to recreate merges instead of ignoring them
+s,strategy=        use the given merge strategy
+m,merge            always used (no-op)
+i,interactive      always used (no-op)
+ Actions:
+continue           continue rebasing process
+abort              abort rebasing process and restore original branch
+skip               skip current patch and continue rebasing process
+"
 
-OPTIONS_SPEC=
 . git-sh-setup
 require_work_tree
 
-DOTEST="$GIT_DIR/.dotest-merge"
+DOTEST="$GIT_DIR/rebase-merge"
 TODO="$DOTEST"/git-rebase-todo
 DONE="$DOTEST"/done
 MSG="$DOTEST"/message
@@ -25,10 +39,8 @@
 REWRITTEN="$DOTEST"/rewritten
 PRESERVE_MERGES=
 STRATEGY=
+ONTO=
 VERBOSE=
-test -d "$REWRITTEN" && PRESERVE_MERGES=t
-test -f "$DOTEST"/strategy && STRATEGY="$(cat "$DOTEST"/strategy)"
-test -f "$DOTEST"/verbose && VERBOSE=t
 
 GIT_CHERRY_PICK_HELP="  After resolving the conflicts,
 mark the corrected paths with 'git add <paths>', and
@@ -53,6 +65,16 @@
 	esac
 }
 
+run_pre_rebase_hook () {
+	if test -x "$GIT_DIR/hooks/pre-rebase"
+	then
+		"$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || {
+			echo >&2 "The pre-rebase hook refused to rebase."
+			exit 1
+		}
+	fi
+}
+
 require_clean_work_tree () {
 	# test if working tree is dirty
 	git rev-parse --verify HEAD > /dev/null &&
@@ -133,7 +155,16 @@
 }
 
 pick_one_preserving_merges () {
-	case "$1" in -n) sha1=$2 ;; *) sha1=$1 ;; esac
+	fast_forward=t
+	case "$1" in
+	-n)
+		fast_forward=f
+		sha1=$2
+		;;
+	*)
+		sha1=$1
+		;;
+	esac
 	sha1=$(git rev-parse $sha1)
 
 	if test -f "$DOTEST"/current-commit
@@ -144,15 +175,14 @@
 		die "Cannot write current commit's replacement sha1"
 	fi
 
+	echo $sha1 > "$DOTEST"/current-commit
+
 	# rewrite parents; if none were rewritten, we can fast-forward.
-	fast_forward=t
-	preserve=t
 	new_parents=
 	for p in $(git rev-list --parents -1 $sha1 | cut -d' ' -f2-)
 	do
 		if test -f "$REWRITTEN"/$p
 		then
-			preserve=f
 			new_p=$(cat "$REWRITTEN"/$p)
 			test $p != $new_p && fast_forward=f
 			case "$new_parents" in
@@ -169,7 +199,8 @@
 	case $fast_forward in
 	t)
 		output warn "Fast forward to $sha1"
-		test $preserve = f || echo $sha1 > "$REWRITTEN"/$sha1
+		output git reset --hard $sha1 ||
+			die "Cannot fast forward to $sha1"
 		;;
 	f)
 		test "a$1" = a-n && die "Refusing to squash a merge: $sha1"
@@ -179,7 +210,6 @@
 		output git checkout $first_parent 2> /dev/null ||
 			die "Cannot move HEAD to $first_parent"
 
-		echo $sha1 > "$DOTEST"/current-commit
 		case "$new_parents" in
 		' '*' '*)
 			# redo merge
@@ -247,7 +277,7 @@
 		"$DOTEST"/amend || exit
 	read command sha1 rest < "$TODO"
 	case "$command" in
-	'#'*|'')
+	'#'*|''|noop)
 		mark_action_done
 		;;
 	pick|p)
@@ -264,8 +294,8 @@
 		pick_one $sha1 ||
 			die_with_patch $sha1 "Could not apply $sha1... $rest"
 		make_patch $sha1
-		: > "$DOTEST"/amend
-		warn
+		git rev-parse --verify HEAD > "$DOTEST"/amend
+		warn "Stopped at $sha1... $rest"
 		warn "You can amend the commit now, with"
 		warn
 		warn "	git commit --amend"
@@ -284,23 +314,28 @@
 
 		mark_action_done
 		make_squash_message $sha1 > "$MSG"
+		failed=f
+		author_script=$(get_author_ident_from_commit HEAD)
+		output git reset --soft HEAD^
+		pick_one -n $sha1 || failed=t
 		case "$(peek_next_command)" in
 		squash|s)
 			EDIT_COMMIT=
 			USE_OUTPUT=output
+			MSG_OPT=-F
+			MSG_FILE="$MSG"
 			cp "$MSG" "$SQUASH_MSG"
 			;;
 		*)
 			EDIT_COMMIT=-e
 			USE_OUTPUT=
+			MSG_OPT=
+			MSG_FILE=
 			rm -f "$SQUASH_MSG" || exit
+			cp "$MSG" "$GIT_DIR"/SQUASH_MSG
+			rm -f "$GIT_DIR"/MERGE_MSG || exit
 			;;
 		esac
-
-		failed=f
-		author_script=$(get_author_ident_from_commit HEAD)
-		output git reset --soft HEAD^
-		pick_one -n $sha1 || failed=t
 		echo "$author_script" > "$DOTEST"/author-script
 		if test $failed = f
 		then
@@ -309,7 +344,7 @@
 			GIT_AUTHOR_NAME="$GIT_AUTHOR_NAME" \
 			GIT_AUTHOR_EMAIL="$GIT_AUTHOR_EMAIL" \
 			GIT_AUTHOR_DATE="$GIT_AUTHOR_DATE" \
-			$USE_OUTPUT git commit --no-verify -F "$MSG" $EDIT_COMMIT || failed=t
+			$USE_OUTPUT git commit --no-verify $MSG_OPT "$MSG_FILE" $EDIT_COMMIT || failed=t
 		fi
 		if test $failed = t
 		then
@@ -368,10 +403,27 @@
 	done
 }
 
+# check if no other options are set
+is_standalone () {
+	test $# -eq 2 -a "$2" = '--' &&
+	test -z "$ONTO" &&
+	test -z "$PRESERVE_MERGES" &&
+	test -z "$STRATEGY" &&
+	test -z "$VERBOSE"
+}
+
+get_saved_options () {
+	test -d "$REWRITTEN" && PRESERVE_MERGES=t
+	test -f "$DOTEST"/strategy && STRATEGY="$(cat "$DOTEST"/strategy)"
+	test -f "$DOTEST"/verbose && VERBOSE=t
+}
+
 while test $# != 0
 do
 	case "$1" in
 	--continue)
+		is_standalone "$@" || usage
+		get_saved_options
 		comment_for_reflog continue
 
 		test -d "$DOTEST" || die "No interactive rebase running"
@@ -390,20 +442,30 @@
 		else
 			. "$DOTEST"/author-script ||
 				die "Cannot find the author identity"
+			amend=
 			if test -f "$DOTEST"/amend
 			then
+				amend=$(git rev-parse --verify HEAD)
+				test "$amend" = $(cat "$DOTEST"/amend) ||
+				die "\
+You have uncommitted changes in your working tree. Please, commit them
+first and then run 'git rebase --continue' again."
 				git reset --soft HEAD^ ||
 				die "Cannot rewind the HEAD"
 			fi
 			export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE &&
-			git commit --no-verify -F "$DOTEST"/message -e ||
-			die "Could not commit staged changes."
+			git commit --no-verify -F "$DOTEST"/message -e || {
+				test -n "$amend" && git reset --soft $amend
+				die "Could not commit staged changes."
+			}
 		fi
 
 		require_clean_work_tree
 		do_rest
 		;;
 	--abort)
+		is_standalone "$@" || usage
+		get_saved_options
 		comment_for_reflog abort
 
 		git rerere clear
@@ -421,6 +483,8 @@
 		exit
 		;;
 	--skip)
+		is_standalone "$@" || usage
+		get_saved_options
 		comment_for_reflog skip
 
 		git rerere clear
@@ -428,7 +492,7 @@
 
 		output git reset --hard && do_rest
 		;;
-	-s|--strategy)
+	-s)
 		case "$#,$1" in
 		*,*=*)
 			STRATEGY="-s "$(expr "z$1" : 'z-[^=]*=\(.*\)') ;;
@@ -439,25 +503,27 @@
 			shift ;;
 		esac
 		;;
-	-m|--merge)
+	-m)
 		# we use merge anyway
 		;;
-	-C*)
-		die "Interactive rebase uses merge, so $1 does not make sense"
-		;;
-	-v|--verbose)
+	-v)
 		VERBOSE=t
 		;;
-	-p|--preserve-merges)
+	-p)
 		PRESERVE_MERGES=t
 		;;
-	-i|--interactive)
+	-i)
 		# yeah, we know
 		;;
-	''|-h)
-		usage
+	--onto)
+		shift
+		ONTO=$(git rev-parse --verify "$1") ||
+			die "Does not point to a valid commit: $1"
 		;;
-	*)
+	--)
+		shift
+		run_pre_rebase_hook ${1+"$@"}
+		test $# -eq 1 -o $# -eq 2 || usage
 		test -d "$DOTEST" &&
 			die "Interactive rebase already started"
 
@@ -466,15 +532,6 @@
 
 		comment_for_reflog start
 
-		ONTO=
-		case "$1" in
-		--onto)
-			ONTO=$(git rev-parse --verify "$2") ||
-				die "Does not point to a valid commit: $2"
-			shift; shift
-			;;
-		esac
-
 		require_clean_work_tree
 
 		UPSTREAM=$(git rev-parse --verify "$1") || die "Invalid base"
@@ -527,6 +584,7 @@
 			--abbrev=7 --reverse --left-right --cherry-pick \
 			$UPSTREAM...$HEAD | \
 			sed -n "s/^>/pick /p" > "$TODO"
+		test -s "$TODO" || echo noop >> "$TODO"
 		cat >> "$TODO" << EOF
 
 # Rebase $SHORTUPSTREAM..$SHORTHEAD onto $SHORTONTO
@@ -551,6 +609,7 @@
 		has_action "$TODO" ||
 			die_abort "Nothing to do"
 
+		git update-ref ORIG_HEAD $HEAD
 		output git checkout $ONTO && do_rest
 		;;
 	esac
diff --git a/git-rebase.sh b/git-rebase.sh
index e2d85ee..a30d40c 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -14,8 +14,8 @@
 completely automatic.  You will have to resolve any such merge failure
 and run git rebase --continue.  Another option is to bypass the commit
 that caused the merge failure with git rebase --skip.  To restore the
-original <branch> and remove the .dotest working files, use the command
-git rebase --abort instead.
+original <branch> and remove the .git/rebase-apply working files, use the
+command git rebase --abort instead.
 
 Note that if <branch> is not specified on the command line, the
 currently checked out branch is used.
@@ -42,7 +42,7 @@
 unset newbase
 strategy=recursive
 do_merge=
-dotest=$GIT_DIR/.dotest-merge
+dotest="$GIT_DIR"/rebase-merge
 prec=4
 verbose=
 git_am_opt=
@@ -144,13 +144,34 @@
 	done && test -n "$1"
 }
 
+run_pre_rebase_hook () {
+	if test -x "$GIT_DIR/hooks/pre-rebase"
+	then
+		"$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || {
+			echo >&2 "The pre-rebase hook refused to rebase."
+			exit 1
+		}
+	fi
+}
+
+test -f "$GIT_DIR"/rebase-apply/applying &&
+	die 'It looks like git-am is in progress. Cannot rebase.'
+
 is_interactive "$@" && exec git-rebase--interactive "$@"
 
+if test $# -eq 0
+then
+	test -d "$dotest" -o -d "$GIT_DIR"/rebase-apply || usage
+	test -d "$dotest" -o -f "$GIT_DIR"/rebase-apply/rebasing &&
+		die 'A rebase is in progress, try --continue, --skip or --abort.'
+	die "No arguments given and $GIT_DIR/rebase-apply already exists."
+fi
+
 while test $# != 0
 do
 	case "$1" in
 	--continue)
-		test -d "$dotest" -o -d .dotest ||
+		test -d "$dotest" -o -d "$GIT_DIR"/rebase-apply ||
 			die "No rebase in progress?"
 
 		git diff-files --quiet --ignore-submodules || {
@@ -173,15 +194,15 @@
 			finish_rb_merge
 			exit
 		fi
-		head_name=$(cat .dotest/head-name) &&
-		onto=$(cat .dotest/onto) &&
-		orig_head=$(cat .dotest/orig-head) &&
+		head_name=$(cat "$GIT_DIR"/rebase-apply/head-name) &&
+		onto=$(cat "$GIT_DIR"/rebase-apply/onto) &&
+		orig_head=$(cat "$GIT_DIR"/rebase-apply/orig-head) &&
 		git am --resolved --3way --resolvemsg="$RESOLVEMSG" &&
 		move_to_original_branch
 		exit
 		;;
 	--skip)
-		test -d "$dotest" -o -d .dotest ||
+		test -d "$dotest" -o -d "$GIT_DIR"/rebase-apply ||
 			die "No rebase in progress?"
 
 		git reset --hard HEAD || exit $?
@@ -201,15 +222,15 @@
 			finish_rb_merge
 			exit
 		fi
-		head_name=$(cat .dotest/head-name) &&
-		onto=$(cat .dotest/onto) &&
-		orig_head=$(cat .dotest/orig-head) &&
+		head_name=$(cat "$GIT_DIR"/rebase-apply/head-name) &&
+		onto=$(cat "$GIT_DIR"/rebase-apply/onto) &&
+		orig_head=$(cat "$GIT_DIR"/rebase-apply/orig-head) &&
 		git am -3 --skip --resolvemsg="$RESOLVEMSG" &&
 		move_to_original_branch
 		exit
 		;;
 	--abort)
-		test -d "$dotest" -o -d .dotest ||
+		test -d "$dotest" -o -d "$GIT_DIR"/rebase-apply ||
 			die "No rebase in progress?"
 
 		git rerere clear
@@ -217,7 +238,7 @@
 		then
 			move_to_original_branch
 		else
-			dotest=.dotest
+			dotest="$GIT_DIR"/rebase-apply
 			move_to_original_branch
 		fi
 		git reset --hard $(cat "$dotest/orig-head")
@@ -265,25 +286,27 @@
 	shift
 done
 
-# Make sure we do not have .dotest
+# Make sure we do not have $GIT_DIR/rebase-apply
 if test -z "$do_merge"
 then
-	if mkdir .dotest
+	if mkdir "$GIT_DIR"/rebase-apply 2>/dev/null
 	then
-		rmdir .dotest
+		rmdir "$GIT_DIR"/rebase-apply
 	else
 		echo >&2 '
-It seems that I cannot create a .dotest directory, and I wonder if you
-are in the middle of patch application or another rebase.  If that is not
-the case, please rm -fr .dotest and run me again.  I am stopping in case
-you still have something valuable there.'
+It seems that I cannot create a rebase-apply directory, and
+I wonder if you are in the middle of patch application or another
+rebase.  If that is not the case, please
+	rm -fr '"$GIT_DIR"'/rebase-apply
+and run me again.  I am stopping in case you still have something
+valuable there.'
 		exit 1
 	fi
 else
 	if test -d "$dotest"
 	then
-		die "previous dotest directory $dotest still exists." \
-			'try git-rebase < --continue | --abort >'
+		die "previous rebase directory $dotest still exists." \
+			'Try git rebase (--continue | --abort | --skip)'
 	fi
 fi
 
@@ -307,13 +330,7 @@
 onto=$(git rev-parse --verify "${onto_name}^0") || exit
 
 # If a hook exists, give it a chance to interrupt
-if test -x "$GIT_DIR/hooks/pre-rebase"
-then
-	"$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || {
-		echo >&2 "The pre-rebase hook refused to rebase."
-		exit 1
-	}
-fi
+run_pre_rebase_hook ${1+"$@"}
 
 # If the branch to rebase is given, that is the branch we will rebase
 # $branch_name -- branch being rebased, or HEAD (already detached)
@@ -376,9 +393,8 @@
 
 # Detach HEAD and reset the tree
 echo "First, rewinding head to replay your work on top of it..."
-git checkout "$onto^0" >/dev/null 2>&1 ||
-	die "could not detach HEAD"
-# git reset --hard "$onto^0"
+git checkout -q "$onto^0" || die "could not detach HEAD"
+git update-ref ORIG_HEAD $branch
 
 # If the $onto is a proper descendant of the tip of the branch, then
 # we just fast forwarded.
@@ -396,10 +412,10 @@
 	git am $git_am_opt --rebasing --resolvemsg="$RESOLVEMSG" &&
 	move_to_original_branch
 	ret=$?
-	test 0 != $ret -a -d .dotest &&
-		echo $head_name > .dotest/head-name &&
-		echo $onto > .dotest/onto &&
-		echo $orig_head > .dotest/orig-head
+	test 0 != $ret -a -d "$GIT_DIR"/rebase-apply &&
+		echo $head_name > "$GIT_DIR"/rebase-apply/head-name &&
+		echo $onto > "$GIT_DIR"/rebase-apply/onto &&
+		echo $orig_head > "$GIT_DIR"/rebase-apply/orig-head
 	exit $ret
 fi
 
diff --git a/git-relink.perl b/git-relink.perl
index 15fb932..937c69a 100755
--- a/git-relink.perl
+++ b/git-relink.perl
@@ -163,7 +163,7 @@
 
 
 sub usage() {
-	print("Usage: $0 [--safe] <dir> [<dir> ...] <master_dir> \n");
+	print("Usage: git relink [--safe] <dir> [<dir> ...] <master_dir> \n");
 	print("All directories should contain a .git/objects/ subdirectory.\n");
 	print("Options\n");
 	print("\t--safe\t" .
diff --git a/git-repack.sh b/git-repack.sh
index 072d1b4..458a497 100755
--- a/git-repack.sh
+++ b/git-repack.sh
@@ -5,12 +5,12 @@
 
 OPTIONS_KEEPDASHDASH=
 OPTIONS_SPEC="\
-git-repack [options]
+git repack [options]
 --
 a               pack everything in a single pack
 A               same as -a, and turn unreachable objects loose
 d               remove redundant packs, and run git-prune-packed
-f               pass --no-reuse-delta to git-pack-objects
+f               pass --no-reuse-object to git-pack-objects
 n               do not run git-update-server-info
 q,quiet         be quiet
 l               pass --local to git-pack-objects
@@ -44,11 +44,7 @@
 	shift
 done
 
-# Later we will default repack.UseDeltaBaseOffset to true
-default_dbo=false
-
-case "`git config --bool repack.usedeltabaseoffset ||
-       echo $default_dbo`" in
+case "`git config --bool repack.usedeltabaseoffset || echo true`" in
 true)
 	extra="$extra --delta-base-offset" ;;
 esac
@@ -75,19 +71,17 @@
 				existing="$existing $e"
 			fi
 		done
-	fi
-	if test -z "$args"
-	then
-		args='--unpacked --incremental'
-	elif test -n "$unpack_unreachable"
-	then
-		args="$args $unpack_unreachable"
+		if test -n "$args" -a -n "$unpack_unreachable" -a \
+			-n "$remove_redundant"
+		then
+			args="$args $unpack_unreachable"
+		fi
 	fi
 	;;
 esac
 
 args="$args $local $quiet $no_reuse$extra"
-names=$(git pack-objects --non-empty --all --reflog $args </dev/null "$PACKTMP") ||
+names=$(git pack-objects --honor-pack-keep --non-empty --all --reflog $args </dev/null "$PACKTMP") ||
 	exit 1
 if [ -z "$names" ]; then
 	if test -z "$quiet"; then
diff --git a/git-request-pull.sh b/git-request-pull.sh
index 068f5e0..a2cf5b8 100755
--- a/git-request-pull.sh
+++ b/git-request-pull.sh
@@ -4,9 +4,9 @@
 # This file is licensed under the GPL v2, or a later version
 # at the discretion of Linus Torvalds.
 
-USAGE='<commit> <url> [<head>]'
-LONG_USAGE='Summarizes the changes since <commit> to the standard output,
-and includes <url> in the message generated.'
+USAGE='<start> <url> [<end>]'
+LONG_USAGE='Summarizes the changes between two commits to the standard output,
+and includes the given URL in the generated summary.'
 SUBDIRECTORY_OK='Yes'
 OPTIONS_SPEC=
 . git-sh-setup
@@ -26,7 +26,7 @@
 die "fatal: No commits in common between $base and $head"
 
 url=$(get_remote_url "$url")
-branch=$(git peek-remote "$url" \
+branch=$(git ls-remote "$url" \
 	| sed -n -e "/^$headrev	refs.heads./{
 		s/^.*	refs.heads.//
 		p
diff --git a/git-send-email.perl b/git-send-email.perl
index 385ff7c..449d938 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -20,6 +20,7 @@
 use warnings;
 use Term::ReadLine;
 use Getopt::Long;
+use Text::ParseWords;
 use Data::Dumper;
 use Term::ANSIColor;
 use Git;
@@ -38,7 +39,7 @@
 
 sub usage {
 	print <<EOT;
-git-send-email [options] <file | directory>...
+git send-email [options] <file | directory>...
 Options:
    --from         Specify the "From:" line of the email to be sent.
 
@@ -84,7 +85,10 @@
 
    --smtp-pass    The password for SMTP-AUTH.
 
-   --smtp-ssl     If set, connects to the SMTP server using SSL.
+   --smtp-encryption Specify 'tls' for STARTTLS encryption, or 'ssl' for SSL.
+                  Any other value disables the feature.
+
+   --smtp-ssl     Synonym for '--smtp-encryption=ssl'.  Deprecated.
 
    --suppress-cc  Suppress the specified category of auto-CC.  The category
 		  can be one of 'author' for the patch author, 'self' to
@@ -184,7 +188,7 @@
 
 # Variables with corresponding config settings
 my ($thread, $chain_reply_to, $suppress_from, $signed_off_cc, $cc_cmd);
-my ($smtp_server, $smtp_server_port, $smtp_authuser, $smtp_ssl);
+my ($smtp_server, $smtp_server_port, $smtp_authuser, $smtp_encryption);
 my ($identity, $aliasfiletype, @alias_files, @smtp_host_parts);
 my ($no_validate);
 my (@suppress_cc);
@@ -194,7 +198,6 @@
     "chainreplyto" => [\$chain_reply_to, 1],
     "suppressfrom" => [\$suppress_from, undef],
     "signedoffcc" => [\$signed_off_cc, undef],
-    "smtpssl" => [\$smtp_ssl, 0],
 );
 
 my %config_settings = (
@@ -249,7 +252,8 @@
 		    "smtp-server-port=s" => \$smtp_server_port,
 		    "smtp-user=s" => \$smtp_authuser,
 		    "smtp-pass:s" => \$smtp_authpass,
-		    "smtp-ssl!" => \$smtp_ssl,
+		    "smtp-ssl" => sub { $smtp_encryption = 'ssl' },
+		    "smtp-encryption=s" => \$smtp_encryption,
 		    "identity=s" => \$identity,
 		    "compose" => \$compose,
 		    "quiet" => \$quiet,
@@ -289,6 +293,15 @@
 			$$target = Git::config(@repo, "$prefix.$setting") unless (defined $$target);
 		}
 	}
+
+	if (!defined $smtp_encryption) {
+		my $enc = Git::config(@repo, "$prefix.smtpencryption");
+		if (defined $enc) {
+			$smtp_encryption = $enc;
+		} elsif (Git::config_bool(@repo, "$prefix.smtpssl")) {
+			$smtp_encryption = 'ssl';
+		}
+	}
 }
 
 # read configuration from [sendemail "$identity"], fall back on [sendemail]
@@ -301,6 +314,9 @@
 	${$setting->[0]} = $setting->[1] unless (defined (${$setting->[0]}));
 }
 
+# 'default' encryption is none -- this only prevents a warning
+$smtp_encryption = '' unless (defined $smtp_encryption);
+
 # Set CC suppressions
 my(%suppress_cc);
 if (@suppress_cc) {
@@ -348,6 +364,10 @@
 	die "Comma in --bcclist entry: $entry'\n" unless $entry !~ m/,/;
 }
 
+sub split_addrs {
+	return parse_line('\s*,\s*', 1, @_);
+}
+
 my %aliases;
 my %parse_alias = (
 	# multiline formats can be supported in the future
@@ -356,7 +376,7 @@
 			my ($alias, $addr) = ($1, $2);
 			$addr =~ s/#.*$//; # mutt allows # comments
 			 # commas delimit multiple addresses
-			$aliases{$alias} = [ split(/\s*,\s*/, $addr) ];
+			$aliases{$alias} = [ split_addrs($addr) ];
 		}}},
 	mailrc => sub { my $fh = shift; while (<$fh>) {
 		if (/^alias\s+(\S+)\s+(.*)$/) {
@@ -365,7 +385,7 @@
 		}}},
 	pine => sub { my $fh = shift; while (<$fh>) {
 		if (/^(\S+)\t.*\t(.*)$/) {
-			$aliases{$1} = [ split(/\s*,\s*/, $2) ];
+			$aliases{$1} = [ split_addrs($2) ];
 		}}},
 	gnus => sub { my $fh = shift; while (<$fh>) {
 		if (/\(define-mail-alias\s+"(\S+?)"\s+"(\S+?)"\)/) {
@@ -392,10 +412,9 @@
 
 		push @files, grep { -f $_ } map { +$f . "/" . $_ }
 				sort readdir(DH);
-
-	} elsif (-f $f) {
+		closedir(DH);
+	} elsif (-f $f or -p $f) {
 		push @files, $f;
-
 	} else {
 		print STDERR "Skipping $f - not found.\n";
 	}
@@ -403,8 +422,10 @@
 
 if (!$no_validate) {
 	foreach my $f (@files) {
-		my $error = validate_patch($f);
-		$error and die "fatal: $f: $error\nwarning: no patches were sent\n";
+		unless (-p $f) {
+			my $error = validate_patch($f);
+			$error and die "fatal: $f: $error\nwarning: no patches were sent\n";
+		}
 	}
 }
 
@@ -442,7 +463,7 @@
 	}
 
 	my $to = $_;
-	push @to, split /,\s*/, $to;
+	push @to, split_addrs($to);
 	$prompting++;
 }
 
@@ -738,7 +759,7 @@
 			die "The required SMTP server is not properly defined."
 		}
 
-		if ($smtp_ssl) {
+		if ($smtp_encryption eq 'ssl') {
 			$smtp_server_port ||= 465; # ssmtp
 			require Net::SMTP::SSL;
 			$smtp ||= Net::SMTP::SSL->new($smtp_server, Port => $smtp_server_port);
@@ -748,6 +769,21 @@
 			$smtp ||= Net::SMTP->new((defined $smtp_server_port)
 						 ? "$smtp_server:$smtp_server_port"
 						 : $smtp_server);
+			if ($smtp_encryption eq 'tls') {
+				require Net::SMTP::SSL;
+				$smtp->command('STARTTLS');
+				$smtp->response();
+				if ($smtp->code == 220) {
+					$smtp = Net::SMTP::SSL->start_SSL($smtp)
+						or die "STARTTLS failed! ".$smtp->message;
+					$smtp_encryption = '';
+					# Send EHLO again to receive fresh
+					# supported commands
+					$smtp->hello();
+				} else {
+					die "Server does not support STARTTLS! ".$smtp->message;
+				}
+			}
 		}
 
 		if (!$smtp) {
diff --git a/git-sh-setup.sh b/git-sh-setup.sh
index a44b1c7..dbdf209 100755
--- a/git-sh-setup.sh
+++ b/git-sh-setup.sh
@@ -32,15 +32,16 @@
 		echo exit $?
 	)"
 else
+	dashless=$(basename "$0" | sed -e 's/-/ /')
 	usage() {
-		die "Usage: $0 $USAGE"
+		die "Usage: $dashless $USAGE"
 	}
 
 	if [ -z "$LONG_USAGE" ]
 	then
-		LONG_USAGE="Usage: $0 $USAGE"
+		LONG_USAGE="Usage: $dashless $USAGE"
 	else
-		LONG_USAGE="Usage: $0 $USAGE
+		LONG_USAGE="Usage: $dashless $USAGE
 
 $LONG_USAGE"
 	fi
@@ -142,3 +143,16 @@
 	}
 	: ${GIT_OBJECT_DIRECTORY="$GIT_DIR/objects"}
 fi
+
+# Fix some commands on Windows
+case $(uname -s) in
+*MINGW*)
+	# Windows has its own (incompatible) sort and find
+	sort () {
+		/usr/bin/sort "$@"
+	}
+	find () {
+		/usr/bin/find "$@"
+	}
+	;;
+esac
diff --git a/git-stash.sh b/git-stash.sh
index 4938ade..b9ace99 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -1,7 +1,13 @@
 #!/bin/sh
 # Copyright (c) 2007, Nanako Shiraishi
 
-USAGE='[  | save | list | show | apply | clear | drop | pop | create ]'
+dashless=$(basename "$0" | sed -e 's/-/ /')
+USAGE="list [<options>]
+   or: $dashless (show | drop | pop ) [<stash>]
+   or: $dashless apply [--index] [<stash>]
+   or: $dashless branch <branchname> [<stash>]
+   or: $dashless [save [--keep-index] [<message>]]
+   or: $dashless clear"
 
 SUBDIRECTORY_OK=Yes
 OPTIONS_SPEC=
@@ -33,6 +39,7 @@
 create_stash () {
 	stash_msg="$1"
 
+	git update-index -q --refresh
 	if no_changes
 	then
 		exit 0
@@ -86,8 +93,16 @@
 }
 
 save_stash () {
-	stash_msg="$1"
+	keep_index=
+	case "$1" in
+	--keep-index)
+		keep_index=t
+		shift
+	esac
 
+	stash_msg="$*"
+
+	git update-index -q --refresh
 	if no_changes
 	then
 		echo 'No local changes to save'
@@ -104,6 +119,13 @@
 	git update-ref -m "$stash_msg" $ref_stash $w_commit ||
 		die "Cannot save the current status"
 	printf 'Saved working directory and index state "%s"\n' "$stash_msg"
+
+	git reset --hard
+
+	if test -n "$keep_index" && test -n $i_tree
+	then
+		git read-tree --reset -u $i_tree
+	fi
 }
 
 have_stash () {
@@ -122,16 +144,16 @@
 	then
 		flags=--stat
 	fi
-	s=$(git rev-parse --revs-only --no-flags --default $ref_stash "$@")
 
-	w_commit=$(git rev-parse --verify "$s") &&
-	b_commit=$(git rev-parse --verify "$s^") &&
+	w_commit=$(git rev-parse --verify --default $ref_stash "$@") &&
+	b_commit=$(git rev-parse --verify "$w_commit^") &&
 	git diff $flags $b_commit $w_commit
 }
 
 apply_stash () {
+	git update-index -q --refresh &&
 	git diff-files --quiet --ignore-submodules ||
-		die 'Cannot restore on top of a dirty state'
+		die 'Cannot apply to a dirty working tree, please stage your changes'
 
 	unstash_index=
 	case "$1" in
@@ -146,14 +168,15 @@
 
 	# stash records the work tree, and is a merge between the
 	# base commit (first parent) and the index tree (second parent).
-	s=$(git rev-parse --revs-only --no-flags --default $ref_stash "$@") &&
+	s=$(git rev-parse --verify --default $ref_stash "$@") &&
 	w_tree=$(git rev-parse --verify "$s:") &&
 	b_tree=$(git rev-parse --verify "$s^1:") &&
 	i_tree=$(git rev-parse --verify "$s^2:") ||
 		die "$*: no valid stashed state found"
 
 	unstashed_index_tree=
-	if test -n "$unstash_index" && test "$b_tree" != "$i_tree"
+	if test -n "$unstash_index" && test "$b_tree" != "$i_tree" &&
+			test "$c_tree" != "$i_tree"
 	then
 		git diff-tree --binary $s^2^..$s^2 | git apply --cached
 		test $? -ne 0 &&
@@ -205,7 +228,7 @@
 		shift
 	fi
 	# Verify supplied argument looks like a stash entry
-	s=$(git rev-parse --revs-only --no-flags "$@") &&
+	s=$(git rev-parse --verify "$@") &&
 	git rev-parse --verify "$s:"   > /dev/null 2>&1 &&
 	git rev-parse --verify "$s^1:" > /dev/null 2>&1 &&
 	git rev-parse --verify "$s^2:" > /dev/null 2>&1 ||
@@ -218,6 +241,23 @@
 	git rev-parse --verify "$ref_stash@{0}" > /dev/null 2>&1 || clear_stash
 }
 
+apply_to_branch () {
+	have_stash || die 'Nothing to apply'
+
+	test -n "$1" || die 'No branch name specified'
+	branch=$1
+
+	if test -z "$2"
+	then
+		set x "$ref_stash@{0}"
+	fi
+	stash=$2
+
+	git-checkout -b $branch $stash^ &&
+	apply_stash --index $stash &&
+	drop_stash $stash
+}
+
 # Main command set
 case "$1" in
 list)
@@ -235,7 +275,7 @@
 	;;
 save)
 	shift
-	save_stash "$*" && git-reset --hard
+	save_stash "$@"
 	;;
 apply)
 	shift
@@ -264,12 +304,15 @@
 		drop_stash "$@"
 	fi
 	;;
+branch)
+	shift
+	apply_to_branch "$@"
+	;;
 *)
 	if test $# -eq 0
 	then
 		save_stash &&
-		echo '(To restore them type "git stash apply")' &&
-		git-reset --hard
+		echo '(To restore them type "git stash apply")'
 	else
 		usage
 	fi
diff --git a/git-submodule.sh b/git-submodule.sh
index 21e5b5b..97e4d9a 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -5,7 +5,7 @@
 # Copyright (c) 2007 Lars Hjemli
 
 USAGE="[--quiet] [--cached] \
-[add <repo> [-b branch]|status|init|update [-i|--init]|summary [-n|--summary-limit <n>] [<commit>]] \
+[add <repo> [-b branch] <path>]|[status|init|update [-i|--init]|summary [-n|--summary-limit <n>] [<commit>]] \
 [--] [<path>...]"
 OPTIONS_SPEC=
 . git-sh-setup
@@ -27,18 +27,6 @@
 	fi
 }
 
-# NEEDSWORK: identical function exists in get_repo_base in clone.sh
-get_repo_base() {
-	(
-		cd "`/bin/pwd`" &&
-		cd "$1" || cd "$1.git" &&
-		{
-			cd .git
-			pwd
-		}
-	) 2>/dev/null
-}
-
 # Resolve relative url by appending to parent's url
 resolve_relative_url ()
 {
@@ -115,7 +103,7 @@
 #
 # Add a new submodule to the working tree, .gitmodules and the index
 #
-# $@ = repo [path]
+# $@ = repo path
 #
 # optional branch is stored in global branch variable
 #
@@ -150,16 +138,27 @@
 	repo=$1
 	path=$2
 
-	if test -z "$repo"; then
+	if test -z "$repo" -o -z "$path"; then
 		usage
 	fi
 
-	# Guess path from repo if not specified or strip trailing slashes
-	if test -z "$path"; then
-		path=$(echo "$repo" | sed -e 's|/*$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g')
-	else
-		path=$(echo "$path" | sed -e 's|/*$||')
-	fi
+	# assure repo is absolute or relative to parent
+	case "$repo" in
+	./*|../*)
+		# dereference source url relative to parent's url
+		realrepo=$(resolve_relative_url "$repo") || exit
+		;;
+	*:*|/*)
+		# absolute url
+		realrepo=$repo
+		;;
+	*)
+		die "repo URL: '$repo' must be absolute or begin with ./|../"
+	;;
+	esac
+
+	# strip trailing slashes from path
+	path=$(echo "$path" | sed -e 's|/*$||')
 
 	git ls-files --error-unmatch "$path" > /dev/null 2>&1 &&
 	die "'$path' already exists in the index"
@@ -173,24 +172,20 @@
 		else
 			die "'$path' already exists and is not a valid git repo"
 		fi
-	else
+
 		case "$repo" in
 		./*|../*)
-			# dereference source url relative to parent's url
-			realrepo=$(resolve_relative_url "$repo") || exit
-			;;
+			url=$(resolve_relative_url "$repo") || exit
+		    ;;
 		*)
-			# Turn the source into an absolute path if
-			# it is local
-			if base=$(get_repo_base "$repo"); then
-				repo="$base"
-			fi
-			realrepo=$repo
+			url="$repo"
 			;;
 		esac
+		git config submodule."$path".url "$url"
+	else
 
 		module_clone "$path" "$realrepo" || exit
-		(unset GIT_DIR; cd "$path" && git checkout -q ${branch:+-b "$branch" "origin/$branch"}) ||
+		(unset GIT_DIR; cd "$path" && git checkout -f -q ${branch:+-b "$branch" "origin/$branch"}) ||
 		die "Unable to checkout submodule '$path'"
 	fi
 
@@ -299,7 +294,7 @@
 			# Only mention uninitialized submodules when its
 			# path have been specified
 			test "$#" != "0" &&
-			say "Submodule path '$path' not initialized"
+			say "Submodule path '$path' not initialized" &&
 			say "Maybe you want to use 'update --init'?"
 			continue
 		fi
@@ -316,8 +311,13 @@
 
 		if test "$subsha1" != "$sha1"
 		then
+			force=
+			if test -z "$subsha1"
+			then
+				force="-f"
+			fi
 			(unset GIT_DIR; cd "$path" && git-fetch &&
-				git-checkout -q "$sha1") ||
+				git-checkout $force -q "$sha1") ||
 			die "Unable to checkout '$sha1' in submodule path '$path'"
 
 			say "Submodule path '$path': checked out '$sha1'"
diff --git a/git-svn.perl b/git-svn.perl
index a366c89..25ed2f4 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -66,7 +66,7 @@
 	$_version, $_fetch_all, $_no_rebase,
 	$_merge, $_strategy, $_dry_run, $_local,
 	$_prefix, $_no_checkout, $_url, $_verbose,
-	$_git_format);
+	$_git_format, $_commit_url);
 $Git::SVN::_follow_parent = 1;
 my %remote_opts = ( 'username=s' => \$Git::SVN::Prompt::_username,
                     'config-dir=s' => \$Git::SVN::Ra::config_dir,
@@ -127,6 +127,8 @@
 			  'verbose|v' => \$_verbose,
 			  'dry-run|n' => \$_dry_run,
 			  'fetch-all|all' => \$_fetch_all,
+			  'commit-url=s' => \$_commit_url,
+			  'revision|r=i' => \$_revision,
 			  'no-rebase' => \$_no_rebase,
 			%cmt_opts, %fc_opts } ],
 	'set-tree' => [ \&cmd_set_tree,
@@ -169,7 +171,8 @@
 			  'color' => \$Git::SVN::Log::color,
 			  'pager=s' => \$Git::SVN::Log::pager
 			} ],
-	'find-rev' => [ \&cmd_find_rev, "Translate between SVN revision numbers and tree-ish",
+	'find-rev' => [ \&cmd_find_rev,
+	                "Translate between SVN revision numbers and tree-ish",
 			{} ],
 	'rebase' => [ \&cmd_rebase, "Fetch and rebase your working directory",
 			{ 'merge|m|M' => \$_merge,
@@ -229,7 +232,9 @@
 my %opts = %{$cmd{$cmd}->[2]} if (defined $cmd);
 
 read_repo_config(\%opts);
-Getopt::Long::Configure('pass_through') if ($cmd && ($cmd eq 'log' || $cmd eq 'blame'));
+if ($cmd && ($cmd eq 'log' || $cmd eq 'blame')) {
+	Getopt::Long::Configure('pass_through');
+}
 my $rv = GetOptions(%opts, 'help|H|h' => \$_help, 'version|V' => \$_version,
                     'minimize-connections' => \$Git::SVN::Migration::_minimize,
                     'id|i=s' => \$Git::SVN::default_ref_id,
@@ -261,7 +266,7 @@
 	my $fd = $exit ? \*STDERR : \*STDOUT;
 	print $fd <<"";
 git-svn - bidirectional operations between a single Subversion tree and git
-Usage: $0 <command> [options] [arguments]\n
+Usage: git svn <command> [options] [arguments]\n
 
 	print $fd "Available commands:\n" unless $cmd;
 
@@ -416,6 +421,8 @@
 	$head ||= 'HEAD';
 	my @refs;
 	my ($url, $rev, $uuid, $gs) = working_head_info($head, \@refs);
+	$url = defined $_commit_url ? $_commit_url : $gs->full_url;
+	my $last_rev = $_revision if defined $_revision;
 	if ($url) {
 		print "Committing to $url ...\n";
 	}
@@ -423,7 +430,6 @@
 		die "Unable to determine upstream SVN information from ",
 		    "$head history.\nPerhaps the repository is empty.";
 	}
-	my $last_rev;
 	my ($linear_refs, $parents) = linearize_history($gs, \@refs);
 	if ($_no_rebase && scalar(@$linear_refs) > 1) {
 		warn "Attempting to commit more than one change while ",
@@ -431,6 +437,8 @@
 		     "If these changes depend on each other, re-running ",
 		     "without --no-rebase may be required."
 	}
+	my $expect_url = $url;
+	Git::SVN::remove_username($expect_url);
 	while (1) {
 		my $d = shift @$linear_refs or last;
 		unless (defined $last_rev) {
@@ -446,7 +454,7 @@
 			my $cmt_rev;
 			my %ed_opts = ( r => $last_rev,
 			                log => get_commit_entry($d)->{log},
-			                ra => Git::SVN::Ra->new($gs->full_url),
+			                ra => Git::SVN::Ra->new($url),
 			                config => SVN::Core::config_get_config(
 			                        $Git::SVN::Ra::config_dir
 			                ),
@@ -505,9 +513,9 @@
 					  $gs->refname,
 					  "\nBefore dcommitting";
 				}
-				if ($url_ ne $url) {
+				if ($url_ ne $expect_url) {
 					fatal "URL mismatch after rebase: ",
-					      "$url_ != $url";
+					      "$url_ != $expect_url";
 				}
 				if ($uuid_ ne $uuid) {
 					fatal "uuid mismatch after rebase: ",
@@ -537,13 +545,13 @@
 		my $head = shift;
 		$head ||= 'HEAD';
 		my @refs;
-		my (undef, undef, undef, $gs) = working_head_info($head, \@refs);
+		my (undef, undef, $uuid, $gs) = working_head_info($head, \@refs);
 		unless ($gs) {
 			die "Unable to determine upstream SVN information from ",
 			    "$head history\n";
 		}
 		my $desired_revision = substr($revision_or_hash, 1);
-		$result = $gs->rev_map_get($desired_revision);
+		$result = $gs->rev_map_get($desired_revision, $uuid);
 	} else {
 		my (undef, $rev, undef) = cmt_metadata($revision_or_hash);
 		$result = $rev;
@@ -796,8 +804,8 @@
 }
 
 sub cmd_info {
-	my $path = canonicalize_path(shift or ".");
-	unless (scalar(@_) == 0) {
+	my $path = canonicalize_path(defined($_[0]) ? $_[0] : ".");
+	if (exists $_[1]) {
 		die "Too many arguments specified\n";
 	}
 
@@ -813,6 +821,10 @@
 		die "Unable to determine upstream SVN information from ",
 		    "working tree history\n";
 	}
+
+	# canonicalize_path() will return "" to make libsvn 1.5.x happy,
+	$path = "." if $path eq "";
+
 	my $full_url = $url . ($path eq "." ? "" : "/$path");
 
 	if ($_url) {
@@ -980,8 +992,10 @@
 	if (length $pfx && $pfx !~ m#/$#) {
 		die "--prefix='$pfx' must have a trailing slash '/'\n";
 	}
-	command_noisy('config', "svn-remote.$gs->{repo_id}.$n",
-				"$remote_path:refs/remotes/$pfx*");
+	command_noisy('config',
+	              "svn-remote.$gs->{repo_id}.$n",
+	              "$remote_path:refs/remotes/$pfx*" .
+	                ('/*' x (($remote_path =~ tr/*/*/) - 1)) );
 }
 
 sub verify_ref {
@@ -1112,7 +1126,7 @@
 		my $v = $opts->{$o};
 		my ($key) = ($o =~ /^([a-zA-Z\-]+)/);
 		$key =~ s/-//g;
-		my $arg = 'git-config';
+		my $arg = 'git config';
 		$arg .= ' --int' if ($o =~ /[:=]i$/);
 		$arg .= ' --bool' if ($o !~ /[:=][sfi]$/);
 		if (ref $v eq 'ARRAY') {
@@ -1162,7 +1176,7 @@
 		if (defined $url && defined $rev) {
 			next if $max{$url} and $max{$url} < $rev;
 			if (my $gs = Git::SVN->find_by_url($url)) {
-				my $c = $gs->rev_map_get($rev);
+				my $c = $gs->rev_map_get($rev, $uuid);
 				if ($c && $c eq $hash) {
 					close $fh; # break the pipe
 					return ($url, $rev, $uuid, $gs);
@@ -1226,7 +1240,7 @@
 
 sub find_file_type_and_diff_status {
 	my ($path) = @_;
-	return ('dir', '') if $path eq '.';
+	return ('dir', '') if $path eq '';
 
 	my $diff_output =
 	    command_oneline(qw(diff --cached --name-status --), $path) || "";
@@ -1253,7 +1267,7 @@
 	my $arg = shift;
 	my $ref = ref $arg;
 	my $md5 = Digest::MD5->new();
-        if ($ref eq 'GLOB' || $ref eq 'IO::File') {
+        if ($ref eq 'GLOB' || $ref eq 'IO::File' || $ref eq 'File::Temp') {
 		$md5->addfile($arg) or croak $!;
 	} elsif ($ref eq 'SCALAR') {
 		$md5->add($$arg) or croak $!;
@@ -1316,6 +1330,7 @@
 	}
 }
 
+
 my (%LOCKFILES, %INDEX_FILES);
 END {
 	unlink keys %LOCKFILES if %LOCKFILES;
@@ -1416,11 +1431,21 @@
 
 sub read_all_remotes {
 	my $r = {};
+	my $use_svm_props = eval { command_oneline(qw/config --bool
+	    svn.useSvmProps/) };
+	$use_svm_props = $use_svm_props eq 'true' if $use_svm_props;
 	foreach (grep { s/^svn-remote\.// } command(qw/config -l/)) {
-		if (m!^(.+)\.fetch=\s*(.*)\s*:\s*refs/remotes/(.+)\s*$!) {
-			my ($remote, $local_ref, $remote_ref) = ($1, $2, $3);
+		if (m!^(.+)\.fetch=\s*(.*)\s*:\s*(.+)\s*$!) {
+			my ($remote, $local_ref, $_remote_ref) = ($1, $2, $3);
+			die("svn-remote.$remote: remote ref '$_remote_ref' "
+			    . "must start with 'refs/remotes/'\n")
+				unless $_remote_ref =~ m{^refs/remotes/(.+)};
+			my $remote_ref = $1;
 			$local_ref =~ s{^/}{};
 			$r->{$remote}->{fetch}->{$local_ref} = $remote_ref;
+			$r->{$remote}->{svm} = {} if $use_svm_props;
+		} elsif (m!^(.+)\.usesvmprops=\s*(.*)\s*$!) {
+			$r->{$1}->{svm} = {};
 		} elsif (m!^(.+)\.url=\s*(.*)\s*$!) {
 			$r->{$1}->{url} = $2;
 		} elsif (m!^(.+)\.(branches|tags)=
@@ -1437,6 +1462,23 @@
 			}
 		}
 	}
+
+	map {
+		if (defined $r->{$_}->{svm}) {
+			my $svm;
+			eval {
+				my $section = "svn-remote.$_";
+				$svm = {
+					source => tmp_config('--get',
+					    "$section.svm-source"),
+					replace => tmp_config('--get',
+					    "$section.svm-replace"),
+				}
+			};
+			$r->{$_}->{svm} = $svm;
+		}
+	} keys %$r;
+
 	$r;
 }
 
@@ -1563,13 +1605,21 @@
 		}
 		my $p = $path;
 		my $rwr = rewrite_root({repo_id => $repo_id});
+		my $svm = $remotes->{$repo_id}->{svm}
+			if defined $remotes->{$repo_id}->{svm};
 		unless (defined $p) {
 			$p = $full_url;
 			my $z = $u;
+			my $prefix = '';
 			if ($rwr) {
 				$z = $rwr;
+			} elsif (defined $svm) {
+				$z = $svm->{source};
+				$prefix = $svm->{replace};
+				$prefix =~ s#^\Q$u\E(?:/|$)##;
+				$prefix =~ s#/$##;
 			}
-			$p =~ s#^\Q$z\E(?:/|$)## or next;
+			$p =~ s#^\Q$z\E(?:/|$)#$prefix# or next;
 		}
 		foreach my $f (keys %$fetch) {
 			next if $f ne $p;
@@ -2152,7 +2202,7 @@
 	}
 	die "Tree is not a valid sha1: $tree\n" if $tree !~ /^$::sha1$/o;
 
-	my @exec = ('git-commit-tree', $tree);
+	my @exec = ('git', 'commit-tree', $tree);
 	foreach ($self->get_commit_parents($log_entry)) {
 		push @exec, '-p', $_;
 	}
@@ -2268,12 +2318,20 @@
 		$gs = Git::SVN->init($u, $p, $repo_id, $ref_id, 1);
 	}
 	my ($r0, $parent) = $gs->find_rev_before($r, 1);
-	if (!defined $r0 || !defined $parent) {
-		my ($base, $head) = parse_revision_argument(0, $r);
-		if ($base <= $r) {
+	{
+		my ($base, $head);
+		if (!defined $r0 || !defined $parent) {
+			($base, $head) = parse_revision_argument(0, $r);
+		} else {
+			if ($r0 < $r) {
+				$gs->ra->get_log([$gs->{path}], $r0 + 1, $r, 1,
+					0, 1, sub { $base = $_[1] - 1 });
+			}
+		}
+		if (defined $base && $base <= $r) {
 			$gs->fetch($base, $r);
 		}
-		($r0, $parent) = $gs->last_rev_commit;
+		($r0, $parent) = $gs->find_rev_before($r, 1);
 	}
 	if (defined $r0 && defined $parent) {
 		print STDERR "Found branch parent: ($self->{ref_id}) $parent\n";
@@ -2521,7 +2579,7 @@
 	my ($self, $tree) = (shift, shift);
 	my $log_entry = ::get_commit_entry($tree);
 	unless ($self->{last_rev}) {
-		fatal("Must have an existing revision to commit");
+		::fatal("Must have an existing revision to commit");
 	}
 	my %ed_opts = ( r => $self->{last_rev},
 	                log => $log_entry->{log},
@@ -3183,13 +3241,11 @@
 
 sub apply_textdelta {
 	my ($self, $fb, $exp) = @_;
-	my $fh = IO::File->new_tmpfile;
-	$fh->autoflush(1);
+	my $fh = Git::temp_acquire('svn_delta');
 	# $fh gets auto-closed() by SVN::TxDelta::apply(),
 	# (but $base does not,) so dup() it for reading in close_file
 	open my $dup, '<&', $fh or croak $!;
-	my $base = IO::File->new_tmpfile;
-	$base->autoflush(1);
+	my $base = Git::temp_acquire('git_blob');
 	if ($fb->{blob}) {
 		print $base 'link ' if ($fb->{mode_a} == 120000);
 		my $size = $::_repository->cat_blob($fb->{blob}, $base);
@@ -3204,9 +3260,9 @@
 		}
 	}
 	seek $base, 0, 0 or croak $!;
-	$fb->{fh} = $dup;
+	$fb->{fh} = $fh;
 	$fb->{base} = $base;
-	[ SVN::TxDelta::apply($base, $fh, undef, $fb->{path}, $fb->{pool}) ];
+	[ SVN::TxDelta::apply($base, $dup, undef, $fb->{path}, $fb->{pool}) ];
 }
 
 sub close_file {
@@ -3222,35 +3278,36 @@
 				    "expected: $exp\n    got: $got\n";
 			}
 		}
-		sysseek($fh, 0, 0) or croak $!;
 		if ($fb->{mode_b} == 120000) {
-			eval {
-				sysread($fh, my $buf, 5) == 5 or croak $!;
-				$buf eq 'link ' or die "$path has mode 120000",
-						       " but is not a link";
-			};
-			if ($@) {
-				warn "$@\n";
-				sysseek($fh, 0, 0) or croak $!;
+			sysseek($fh, 0, 0) or croak $!;
+			sysread($fh, my $buf, 5) == 5 or croak $!;
+
+			unless ($buf eq 'link ') {
+				warn "$path has mode 120000",
+						" but is not a link\n";
+			} else {
+				my $tmp_fh = Git::temp_acquire('svn_hash');
+				my $res;
+				while ($res = sysread($fh, my $str, 1024)) {
+					my $out = syswrite($tmp_fh, $str, $res);
+					defined($out) && $out == $res
+						or croak("write ",
+							Git::temp_path($tmp_fh),
+							": $!\n");
+				}
+				defined $res or croak $!;
+
+				($fh, $tmp_fh) = ($tmp_fh, $fh);
+				Git::temp_release($tmp_fh, 1);
 			}
 		}
 
-		my ($tmp_fh, $tmp_filename) = File::Temp::tempfile(UNLINK => 1);
-		my $result;
-		while ($result = sysread($fh, my $string, 1024)) {
-			my $wrote = syswrite($tmp_fh, $string, $result);
-			defined($wrote) && $wrote == $result
-				or croak("write $tmp_filename: $!\n");
-		}
-		defined $result or croak $!;
-		close $tmp_fh or croak $!;
-
-		close $fh or croak $!;
-
-		$hash = $::_repository->hash_and_insert_object($tmp_filename);
-		unlink($tmp_filename);
+		$hash = $::_repository->hash_and_insert_object(
+				Git::temp_path($fh));
 		$hash =~ /^[a-f\d]{40}$/ or die "not a sha1: $hash\n";
-		close $fb->{base} or croak $!;
+
+		Git::temp_release($fb->{base}, 1);
+		Git::temp_release($fh, 1);
 	} else {
 		$hash = $fb->{blob} or die "no blob information\n";
 	}
@@ -3309,6 +3366,7 @@
 	$self->{rm} = { };
 	$self->{path_prefix} = length $self->{svn_path} ?
 	                       "$self->{svn_path}/" : '';
+	$self->{config} = $opts->{config};
 	return $self;
 }
 
@@ -3497,6 +3555,57 @@
 	return $bat->{$c};
 }
 
+# Subroutine to convert a globbing pattern to a regular expression.
+# From perl cookbook.
+sub glob2pat {
+	my $globstr = shift;
+	my %patmap = ('*' => '.*', '?' => '.', '[' => '[', ']' => ']');
+	$globstr =~ s{(.)} { $patmap{$1} || "\Q$1" }ge;
+	return '^' . $globstr . '$';
+}
+
+sub check_autoprop {
+	my ($self, $pattern, $properties, $file, $fbat) = @_;
+	# Convert the globbing pattern to a regular expression.
+	my $regex = glob2pat($pattern);
+	# Check if the pattern matches the file name.
+	if($file =~ m/($regex)/) {
+		# Parse the list of properties to set.
+		my @props = split(/;/, $properties);
+		foreach my $prop (@props) {
+			# Parse 'name=value' syntax and set the property.
+			if ($prop =~ /([^=]+)=(.*)/) {
+				my ($n,$v) = ($1,$2);
+				for ($n, $v) {
+					s/^\s+//; s/\s+$//;
+				}
+				$self->change_file_prop($fbat, $n, $v);
+			}
+		}
+	}
+}
+
+sub apply_autoprops {
+	my ($self, $file, $fbat) = @_;
+	my $conf_t = ${$self->{config}}{'config'};
+	no warnings 'once';
+	# Check [miscellany]/enable-auto-props in svn configuration.
+	if (SVN::_Core::svn_config_get_bool(
+		$conf_t,
+		$SVN::_Core::SVN_CONFIG_SECTION_MISCELLANY,
+		$SVN::_Core::SVN_CONFIG_OPTION_ENABLE_AUTO_PROPS,
+		0)) {
+		# Auto-props are enabled.  Enumerate them to look for matches.
+		my $callback = sub {
+			$self->check_autoprop($_[0], $_[1], $file, $fbat);
+		};
+		SVN::_Core::svn_config_enumerate(
+			$conf_t,
+			$SVN::_Core::SVN_CONFIG_SECTION_AUTO_PROPS,
+			$callback);
+	}
+}
+
 sub A {
 	my ($self, $m) = @_;
 	my ($dir, $file) = split_path($m->{file_b});
@@ -3504,6 +3613,7 @@
 	my $fbat = $self->add_file($self->repo_path($m->{file_b}), $pbat,
 					undef, -1);
 	print "\tA\t$m->{file_b}\n" unless $::_q;
+	$self->apply_autoprops($file, $fbat);
 	$self->chg_file($fbat, $m);
 	$self->close_file($fbat,undef,$self->{pool});
 }
@@ -3567,7 +3677,7 @@
 	} elsif ($m->{mode_b} !~ /755$/ && $m->{mode_a} =~ /755$/) {
 		$self->change_file_prop($fbat,'svn:executable',undef);
 	}
-	my $fh = IO::File->new_tmpfile or croak $!;
+	my $fh = Git::temp_acquire('git_blob');
 	if ($m->{mode_b} =~ /^120/) {
 		print $fh 'link ' or croak $!;
 		$self->change_file_prop($fbat,'svn:special','*');
@@ -3586,9 +3696,8 @@
 	my $atd = $self->apply_textdelta($fbat, undef, $pool);
 	my $got = SVN::TxDelta::send_stream($fh, @$atd, $pool);
 	die "Checksum mismatch\nexpected: $exp\ngot: $got\n" if ($got ne $exp);
+	Git::temp_release($fh, 1);
 	$pool->clear;
-
-	close $fh or croak $!;
 }
 
 sub D {
@@ -3868,21 +3977,21 @@
 	my $old_url = $full_url;
 	$full_url .= '/' . escape_uri_only($path) if length $path;
 	my ($ra, $reparented);
-	if ($old_url ne $full_url) {
-		if ($old_url !~ m#^svn(\+ssh)?://#) {
-			SVN::_Ra::svn_ra_reparent($self->{session}, $full_url,
-			                          $pool);
-			$self->{url} = $full_url;
-			$reparented = 1;
-		} else {
-			$_[0] = undef;
-			$self = undef;
-			$RA = undef;
-			$ra = Git::SVN::Ra->new($full_url);
-			$ra_invalid = 1;
-		}
+
+	if ($old_url =~ m#^svn(\+ssh)?://#) {
+		$_[0] = undef;
+		$self = undef;
+		$RA = undef;
+		$ra = Git::SVN::Ra->new($full_url);
+		$ra_invalid = 1;
+	} elsif ($old_url ne $full_url) {
+		SVN::_Ra::svn_ra_reparent($self->{session}, $full_url, $pool);
+		$self->{url} = $full_url;
+		$reparented = 1;
 	}
+
 	$ra ||= $self;
+	$url_b = escape_url($url_b);
 	my $reporter = $ra->do_switch($rev_b, '', 1, $url_b, $editor, $pool);
 	my @lock = $SVN::Core::VERSION ge '1.2.0' ? (undef) : ();
 	$reporter->set_path('', $rev_a, 0, @lock, $pool);
@@ -4029,16 +4138,38 @@
 	Git::SVN::gc();
 }
 
+sub get_dir_globbed {
+	my ($self, $left, $depth, $r) = @_;
+
+	my @x = eval { $self->get_dir($left, $r) };
+	return unless scalar @x == 3;
+	my $dirents = $x[0];
+	my @finalents;
+	foreach my $de (keys %$dirents) {
+		next if $dirents->{$de}->{kind} != $SVN::Node::dir;
+		if ($depth > 1) {
+			my @args = ("$left/$de", $depth - 1, $r);
+			foreach my $dir ($self->get_dir_globbed(@args)) {
+				push @finalents, "$de/$dir";
+			}
+		} else {
+			push @finalents, $de;
+		}
+	}
+	@finalents;
+}
+
 sub match_globs {
 	my ($self, $exists, $paths, $globs, $r) = @_;
 
 	sub get_dir_check {
 		my ($self, $exists, $g, $r) = @_;
-		my @x = eval { $self->get_dir($g->{path}->{left}, $r) };
-		return unless scalar @x == 3;
-		my $dirents = $x[0];
-		foreach my $de (keys %$dirents) {
-			next if $dirents->{$de}->{kind} != $SVN::Node::dir;
+
+		my @dirs = $self->get_dir_globbed($g->{path}->{left},
+		                                  $g->{path}->{depth},
+		                                  $r);
+
+		foreach my $de (@dirs) {
 			my $p = $g->{path}->full_path($de);
 			next if $exists->{$p};
 			next if (length $g->{path}->{right} &&
@@ -4260,7 +4391,7 @@
 
 sub run_pager {
 	return unless -t *STDOUT && defined $pager;
-	pipe my $rfd, my $wfd or return;
+	pipe my ($rfd, $wfd) or return;
 	defined(my $pid = fork) or ::fatal "Can't fork: $!";
 	if (!$pid) {
 		open STDOUT, '>&', $wfd or
@@ -4619,7 +4750,7 @@
 	mkpath([$svn_dir]);
 	print STDERR "Data from a previous version of git-svn exists, but\n\t",
 	             "$svn_dir\n\t(required for this version ",
-	             "($::VERSION) of git-svn) does not. exist\n";
+	             "($::VERSION) of git-svn) does not exist.\n";
 	my ($fh, $ctx) = command_output_pipe(qw/rev-parse --symbolic --all/);
 	while (<$fh>) {
 		my $x = $_;
@@ -4820,15 +4951,20 @@
 	my ($class, $glob) = @_;
 	my $re = $glob;
 	$re =~ s!/+$!!g; # no need for trailing slashes
-	my $nr = ($re =~ s!^(.*)\*(.*)$!\(\[^/\]+\)!g);
-	my ($left, $right) = ($1, $2);
-	if ($nr > 1) {
-		die "Only one '*' wildcard expansion ",
-		    "is supported (got $nr): '$glob'\n";
-	} elsif ($nr == 0) {
+	$re =~ m!^([^*]*)(\*(?:/\*)*)([^*]*)$!;
+	my $temp = $re;
+	my ($left, $right) = ($1, $3);
+	$re = $2;
+	my $depth = $re =~ tr/*/*/;
+	if ($depth != $temp =~ tr/*/*/) {
+		die "Only one set of wildcard directories " .
+			"(e.g. '*' or '*/*/*') is supported: '$glob'\n";
+	}
+	if ($depth == 0) {
 		die "One '*' is needed for glob: '$glob'\n";
 	}
-	$re = quotemeta($left) . $re . quotemeta($right);
+	$re =~ s!\*!\[^/\]*!g;
+	$re = quotemeta($left) . "($re)" . quotemeta($right);
 	if (length $left && !($left =~ s!/+$!!g)) {
 		die "Missing trailing '/' on left side of: '$glob' ($left)\n";
 	}
@@ -4837,7 +4973,7 @@
 	}
 	my $left_re = qr/^\/\Q$left\E(\/|$)/;
 	bless { left => $left, right => $right, left_regex => $left_re,
-	        regex => qr/$re/, glob => $glob }, $class;
+	        regex => qr/$re/, glob => $glob, depth => $depth }, $class;
 }
 
 sub full_path {
diff --git a/git.c b/git.c
index 59f0fcc..5582c51 100644
--- a/git.c
+++ b/git.c
@@ -9,6 +9,43 @@
 const char git_more_info_string[] =
 	"See 'git help COMMAND' for more information on a specific command.";
 
+static int use_pager = -1;
+struct pager_config {
+	const char *cmd;
+	int val;
+};
+
+static int pager_command_config(const char *var, const char *value, void *data)
+{
+	struct pager_config *c = data;
+	if (!prefixcmp(var, "pager.") && !strcmp(var + 6, c->cmd))
+		c->val = git_config_bool(var, value);
+	return 0;
+}
+
+/* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */
+int check_pager_config(const char *cmd)
+{
+	struct pager_config c;
+	c.cmd = cmd;
+	c.val = -1;
+	git_config(pager_command_config, &c);
+	return c.val;
+}
+
+static void commit_pager_choice(void) {
+	switch (use_pager) {
+	case 0:
+		setenv("GIT_PAGER", "cat", 1);
+		break;
+	case 1:
+		setup_pager();
+		break;
+	default:
+		break;
+	}
+}
+
 static int handle_options(const char*** argv, int* argc, int* envchanged)
 {
 	int handled = 0;
@@ -38,9 +75,9 @@
 				exit(0);
 			}
 		} else if (!strcmp(cmd, "-p") || !strcmp(cmd, "--paginate")) {
-			setup_pager();
+			use_pager = 1;
 		} else if (!strcmp(cmd, "--no-pager")) {
-			setenv("GIT_PAGER", "cat", 1);
+			use_pager = 0;
 			if (envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "--git-dir")) {
@@ -90,59 +127,6 @@
 	return handled;
 }
 
-static int split_cmdline(char *cmdline, const char ***argv)
-{
-	int src, dst, count = 0, size = 16;
-	char quoted = 0;
-
-	*argv = xmalloc(sizeof(char*) * size);
-
-	/* split alias_string */
-	(*argv)[count++] = cmdline;
-	for (src = dst = 0; cmdline[src];) {
-		char c = cmdline[src];
-		if (!quoted && isspace(c)) {
-			cmdline[dst++] = 0;
-			while (cmdline[++src]
-					&& isspace(cmdline[src]))
-				; /* skip */
-			if (count >= size) {
-				size += 16;
-				*argv = xrealloc(*argv, sizeof(char*) * size);
-			}
-			(*argv)[count++] = cmdline + dst;
-		} else if(!quoted && (c == '\'' || c == '"')) {
-			quoted = c;
-			src++;
-		} else if (c == quoted) {
-			quoted = 0;
-			src++;
-		} else {
-			if (c == '\\' && quoted != '\'') {
-				src++;
-				c = cmdline[src];
-				if (!c) {
-					free(*argv);
-					*argv = NULL;
-					return error("cmdline ends with \\");
-				}
-			}
-			cmdline[dst++] = c;
-			src++;
-		}
-	}
-
-	cmdline[dst] = 0;
-
-	if (quoted) {
-		free(*argv);
-		*argv = NULL;
-		return error("unclosed quote");
-	}
-
-	return count;
-}
-
 static int handle_alias(int *argcp, const char ***argv)
 {
 	int envchanged = 0, ret = 0, saved_errno = errno;
@@ -178,6 +162,8 @@
 			    alias_string + 1, alias_command);
 		}
 		count = split_cmdline(alias_string, &new_argv);
+		if (count < 0)
+			die("Bad alias.%s string", alias_command);
 		option_count = handle_options(&new_argv, &count, &envchanged);
 		if (envchanged)
 			die("alias '%s' changes environment variables\n"
@@ -242,8 +228,13 @@
 	prefix = NULL;
 	if (p->option & RUN_SETUP)
 		prefix = setup_git_directory();
-	if (p->option & USE_PAGER)
-		setup_pager();
+
+	if (use_pager == -1 && p->option & RUN_SETUP)
+		use_pager = check_pager_config(p->cmd);
+	if (use_pager == -1 && p->option & USE_PAGER)
+		use_pager = 1;
+	commit_pager_choice();
+
 	if (p->option & NEED_WORK_TREE)
 		setup_work_tree();
 
@@ -297,7 +288,7 @@
 		{ "count-objects", cmd_count_objects, RUN_SETUP },
 		{ "describe", cmd_describe, RUN_SETUP },
 		{ "diff", cmd_diff },
-		{ "diff-files", cmd_diff_files, RUN_SETUP },
+		{ "diff-files", cmd_diff_files, RUN_SETUP | NEED_WORK_TREE },
 		{ "diff-index", cmd_diff_index, RUN_SETUP },
 		{ "diff-tree", cmd_diff_tree, RUN_SETUP },
 		{ "fast-export", cmd_fast_export, RUN_SETUP },
@@ -324,6 +315,7 @@
 		{ "ls-remote", cmd_ls_remote },
 		{ "mailinfo", cmd_mailinfo },
 		{ "mailsplit", cmd_mailsplit },
+		{ "merge", cmd_merge, RUN_SETUP | NEED_WORK_TREE },
 		{ "merge-base", cmd_merge_base, RUN_SETUP },
 		{ "merge-file", cmd_merge_file },
 		{ "merge-ours", cmd_merge_ours, RUN_SETUP },
@@ -351,7 +343,7 @@
 		{ "shortlog", cmd_shortlog, USE_PAGER },
 		{ "show-branch", cmd_show_branch, RUN_SETUP },
 		{ "show", cmd_show, RUN_SETUP | USE_PAGER },
-		{ "status", cmd_status, RUN_SETUP | NEED_WORK_TREE | USE_PAGER },
+		{ "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
 		{ "stripspace", cmd_stripspace },
 		{ "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
 		{ "tag", cmd_tag, RUN_SETUP },
@@ -369,6 +361,16 @@
 		{ "pack-refs", cmd_pack_refs, RUN_SETUP },
 	};
 	int i;
+	static const char ext[] = STRIP_EXTENSION;
+
+	if (sizeof(ext) > 1) {
+		i = strlen(argv[0]) - strlen(ext);
+		if (i > 0 && !strcmp(argv[0] + i, ext)) {
+			char *argv0 = strdup(argv[0]);
+			argv[0] = cmd = argv0;
+			argv0[i] = '\0';
+		}
+	}
 
 	/* Turn "git cmd --help" into "git help cmd" */
 	if (argc > 1 && !strcmp(argv[1], "--help")) {
@@ -384,11 +386,40 @@
 	}
 }
 
+static void execv_dashed_external(const char **argv)
+{
+	struct strbuf cmd;
+	const char *tmp;
+
+	strbuf_init(&cmd, 0);
+	strbuf_addf(&cmd, "git-%s", argv[0]);
+
+	/*
+	 * argv[0] must be the git command, but the argv array
+	 * belongs to the caller, and may be reused in
+	 * subsequent loop iterations. Save argv[0] and
+	 * restore it on error.
+	 */
+	tmp = argv[0];
+	argv[0] = cmd.buf;
+
+	trace_argv_printf(argv, "trace: exec:");
+
+	/* execvp() can only ever return if it fails */
+	execvp(cmd.buf, (char **)argv);
+
+	trace_printf("trace: exec failed: %s\n", strerror(errno));
+
+	argv[0] = tmp;
+
+	strbuf_release(&cmd);
+}
+
+
 int main(int argc, const char **argv)
 {
-	const char *cmd = argv[0] ? argv[0] : "git-help";
-	char *slash = strrchr(cmd, '/');
-	const char *cmd_path = NULL;
+	const char *cmd = argv[0] && *argv[0] ? argv[0] : "git-help";
+	char *slash = (char *)cmd + strlen(cmd);
 	int done_alias = 0;
 
 	/*
@@ -396,9 +427,12 @@
 	 * name, and the dirname as the default exec_path
 	 * if we don't have anything better.
 	 */
-	if (slash) {
+	do
+		--slash;
+	while (cmd <= slash && !is_dir_sep(*slash));
+	if (cmd <= slash) {
 		*slash++ = 0;
-		cmd_path = cmd;
+		git_set_argv0_path(cmd);
 		cmd = slash;
 	}
 
@@ -423,6 +457,7 @@
 	argv++;
 	argc--;
 	handle_options(&argv, &argc, NULL);
+	commit_pager_choice();
 	if (argc > 0) {
 		if (!prefixcmp(argv[0], "--"))
 			argv[0] += 2;
@@ -441,14 +476,14 @@
 	 * environment, and the $(gitexecdir) from the Makefile at build
 	 * time.
 	 */
-	setup_path(cmd_path);
+	setup_path();
 
 	while (1) {
 		/* See if it's an internal command */
 		handle_internal_command(argc, argv);
 
 		/* .. then try the external ones */
-		execv_git_cmd(argv);
+		execv_dashed_external(argv);
 
 		/* It could be an alias -- this works around the insanity
 		 * of overriding "git log" with "git show" by having
diff --git a/git.spec.in b/git.spec.in
index 3d7f3ef..6733b6f 100644
--- a/git.spec.in
+++ b/git.spec.in
@@ -117,6 +117,7 @@
 find $RPM_BUILD_ROOT -type f -name perllocal.pod -exec rm -f {} ';'
 
 (find $RPM_BUILD_ROOT%{_bindir} -type f | grep -vE "archimport|svn|cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@)               > bin-man-doc-files
+(find $RPM_BUILD_ROOT%{_libexecdir}/git-core -type f | grep -vE "archimport|svn|cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@)               >> bin-man-doc-files
 (find $RPM_BUILD_ROOT%{perl_vendorlib} -type f | sed -e s@^$RPM_BUILD_ROOT@@) >> perl-files
 %if %{!?_without_docs:1}0
 (find $RPM_BUILD_ROOT%{_mandir} $RPM_BUILD_ROOT/Documentation -type f | grep -vE "archimport|svn|git-cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@ -e 's/$/*/' ) >> bin-man-doc-files
@@ -136,7 +137,7 @@
 
 %files svn
 %defattr(-,root,root)
-%{_bindir}/*svn*
+%{_libexecdir}/git-core/*svn*
 %doc Documentation/*svn*.txt
 %{!?_without_docs: %{_mandir}/man1/*svn*.1*}
 %{!?_without_docs: %doc Documentation/*svn*.html }
@@ -144,28 +145,29 @@
 %files cvs
 %defattr(-,root,root)
 %doc Documentation/*git-cvs*.txt
-%{_bindir}/*cvs*
+%{_bindir}/git-cvsserver
+%{_libexecdir}/git-core/*cvs*
 %{!?_without_docs: %{_mandir}/man1/*cvs*.1*}
 %{!?_without_docs: %doc Documentation/*git-cvs*.html }
 
 %files arch
 %defattr(-,root,root)
 %doc Documentation/git-archimport.txt
-%{_bindir}/git-archimport
+%{_libexecdir}/git-core/git-archimport
 %{!?_without_docs: %{_mandir}/man1/git-archimport.1*}
 %{!?_without_docs: %doc Documentation/git-archimport.html }
 
 %files email
 %defattr(-,root,root)
 %doc Documentation/*email*.txt
-%{_bindir}/*email*
+%{_libexecdir}/git-core/*email*
 %{!?_without_docs: %{_mandir}/man1/*email*.1*}
 %{!?_without_docs: %doc Documentation/*email*.html }
 
 %files gui
 %defattr(-,root,root)
-%{_bindir}/git-gui
-%{_bindir}/git-citool
+%{_libexecdir}/git-core/git-gui
+%{_libexecdir}/git-core/git-citool
 %{_datadir}/git-gui/
 %{!?_without_docs: %{_mandir}/man1/git-gui.1*}
 %{!?_without_docs: %doc Documentation/git-gui.html}
@@ -187,6 +189,9 @@
 # No files for you!
 
 %changelog
+* Fri Sep 12 2008 Quy Tonthat <qtonthat@gmail.com>
+- move git-cvsserver to bindir.
+
 * Sun Jun 15 2008 Junio C Hamano <gitster@pobox.com>
 - Remove curl from Requires list.
 
diff --git a/gitk-git/gitk b/gitk-git/gitk
index fddcb45..087c4ac 100644
--- a/gitk-git/gitk
+++ b/gitk-git/gitk
@@ -22,11 +22,11 @@
 # run before X event handlers, so reading from a fast source can
 # make the GUI completely unresponsive.
 proc run args {
-    global isonrunq runq
+    global isonrunq runq currunq
 
     set script $args
     if {[info exists isonrunq($script)]} return
-    if {$runq eq {}} {
+    if {$runq eq {} && ![info exists currunq]} {
 	after idle dorunq
     }
     lappend runq [list {} $script]
@@ -38,10 +38,10 @@
 }
 
 proc filereadable {fd script} {
-    global runq
+    global runq currunq
 
     fileevent $fd readable {}
-    if {$runq eq {}} {
+    if {$runq eq {} && ![info exists currunq]} {
 	after idle dorunq
     }
     lappend runq [list $fd $script]
@@ -60,17 +60,19 @@
 }
 
 proc dorunq {} {
-    global isonrunq runq
+    global isonrunq runq currunq
 
     set tstart [clock clicks -milliseconds]
     set t0 $tstart
     while {[llength $runq] > 0} {
 	set fd [lindex $runq 0 0]
 	set script [lindex $runq 0 1]
+	set currunq [lindex $runq 0]
+	set runq [lrange $runq 1 end]
 	set repeat [eval $script]
+	unset currunq
 	set t1 [clock clicks -milliseconds]
 	set t [expr {$t1 - $t0}]
-	set runq [lrange $runq 1 end]
 	if {$repeat ne {} && $repeat} {
 	    if {$fd eq {} || $repeat == 2} {
 		# script returns 1 if it wants to be readded
@@ -90,6 +92,15 @@
     }
 }
 
+proc reg_instance {fd} {
+    global commfd leftover loginstance
+
+    set i [incr loginstance]
+    set commfd($i) $fd
+    set leftover($i) {}
+    return $i
+}
+
 proc unmerged_files {files} {
     global nr_unmerged
 
@@ -294,11 +305,11 @@
 # Start off a git log process and arrange to read its output
 proc start_rev_list {view} {
     global startmsecs commitidx viewcomplete curview
-    global commfd leftover tclencoding
+    global tclencoding
     global viewargs viewargscmd viewfiles vfilelimit
     global showlocalchanges commitinterest
-    global viewactive loginstance viewinstances vmergeonly
-    global pending_select mainheadid
+    global viewactive viewinstances vmergeonly
+    global mainheadid
     global vcanopt vflags vrevs vorigargs
 
     set startmsecs [clock clicks -milliseconds]
@@ -354,10 +365,8 @@
 	error_popup "[mc "Error executing git log:"] $err"
 	return 0
     }
-    set i [incr loginstance]
+    set i [reg_instance $fd]
     set viewinstances($view) [list $i]
-    set commfd($i) $fd
-    set leftover($i) {}
     if {$showlocalchanges && $mainheadid ne {}} {
 	lappend commitinterest($mainheadid) {dodiffindex}
     }
@@ -367,36 +376,63 @@
     }
     filerun $fd [list getcommitlines $fd $i $view 0]
     nowbusy $view [mc "Reading"]
-    if {$view == $curview} {
-	set pending_select $mainheadid
-    }
     set viewcomplete($view) 0
     set viewactive($view) 1
     return 1
 }
 
-proc stop_rev_list {view} {
-    global commfd viewinstances leftover
+proc stop_instance {inst} {
+    global commfd leftover
 
-    foreach inst $viewinstances($view) {
-	set fd $commfd($inst)
-	catch {
-	    set pid [pid $fd]
+    set fd $commfd($inst)
+    catch {
+	set pid [pid $fd]
+
+	if {$::tcl_platform(platform) eq {windows}} {
+	    exec kill -f $pid
+	} else {
 	    exec kill $pid
 	}
-	catch {close $fd}
-	nukefile $fd
-	unset commfd($inst)
-	unset leftover($inst)
+    }
+    catch {close $fd}
+    nukefile $fd
+    unset commfd($inst)
+    unset leftover($inst)
+}
+
+proc stop_backends {} {
+    global commfd
+
+    foreach inst [array names commfd] {
+	stop_instance $inst
+    }
+}
+
+proc stop_rev_list {view} {
+    global viewinstances
+
+    foreach inst $viewinstances($view) {
+	stop_instance $inst
     }
     set viewinstances($view) {}
 }
 
-proc getcommits {} {
+proc reset_pending_select {selid} {
+    global pending_select mainheadid
+
+    if {$selid ne {}} {
+	set pending_select $selid
+    } else {
+	set pending_select $mainheadid
+    }
+}
+
+proc getcommits {selid} {
     global canv curview need_redisplay viewactive
 
     initlayout
     if {[start_rev_list $curview]} {
+	reset_pending_select $selid
 	show_status [mc "Reading commits..."]
 	set need_redisplay 1
     } else {
@@ -406,8 +442,8 @@
 
 proc updatecommits {} {
     global curview vcanopt vorigargs vfilelimit viewinstances
-    global viewactive viewcomplete loginstance tclencoding
-    global startmsecs commfd showneartags showlocalchanges leftover
+    global viewactive viewcomplete tclencoding
+    global startmsecs showneartags showlocalchanges
     global mainheadid pending_select
     global isworktree
     global varcid vposids vnegids vflags vrevs
@@ -468,10 +504,8 @@
     if {$viewactive($view) == 0} {
 	set startmsecs [clock clicks -milliseconds]
     }
-    set i [incr loginstance]
+    set i [reg_instance $fd]
     lappend viewinstances($view) $i
-    set commfd($i) $fd
-    set leftover($i) {}
     fconfigure $fd -blocking 0 -translation lf -eofchar {}
     if {$tclencoding != {}} {
 	fconfigure $fd -encoding $tclencoding
@@ -479,7 +513,7 @@
     filerun $fd [list getcommitlines $fd $i $view 1]
     incr viewactive($view)
     set viewcomplete($view) 0
-    set pending_select $mainheadid
+    reset_pending_select {}
     nowbusy $view "Reading"
     if {$showneartags} {
 	getallcommits
@@ -491,6 +525,11 @@
     global showneartags treediffs commitinterest cached_commitrow
     global targetid
 
+    set selid {}
+    if {$selectedline ne {}} {
+	set selid $currentid
+    }
+
     if {!$viewcomplete($curview)} {
 	stop_rev_list $curview
     }
@@ -509,7 +548,7 @@
     catch {unset cached_commitrow}
     catch {unset targetid}
     setcanvscroll
-    getcommits
+    getcommits $selid
     return 0
 }
 
@@ -1469,8 +1508,15 @@
 	global numcommits startmsecs
 
 	if {[info exists pending_select]} {
-	    set row [first_real_row]
-	    selectline $row 1
+	    update
+	    reset_pending_select {}
+
+	    if {[commitinview $pending_select $curview]} {
+		selectline [rowofcommit $pending_select] 1
+	    } else {
+		set row [first_real_row]
+		selectline $row 1
+	    }
 	}
 	if {$commitidx($curview) > 0} {
 	    #set ms [expr {[clock clicks -milliseconds] - $startmsecs}]
@@ -2103,6 +2149,7 @@
     bind . <$M1B-minus> {incrfont -1}
     bind . <$M1B-KP_Subtract> {incrfont -1}
     wm protocol . WM_DELETE_WINDOW doquit
+    bind . <Destroy> {stop_backends}
     bind . <Button-1> "click %W"
     bind $fstring <Key-Return> {dofind 1 1}
     bind $sha1entry <Key-Return> gotocommit
@@ -3300,10 +3347,7 @@
 
     run refill_reflist
     if {![info exists viewcomplete($n)]} {
-	if {$selid ne {}} {
-	    set pending_select $selid
-	}
-	getcommits
+	getcommits $selid
 	return
     }
 
@@ -3337,18 +3381,18 @@
     drawvisible
     if {$row ne {}} {
 	selectline $row 0
-    } elseif {$mainheadid ne {} && [commitinview $mainheadid $curview]} {
-	selectline [rowofcommit $mainheadid] 1
     } elseif {!$viewcomplete($n)} {
-	if {$selid ne {}} {
-	    set pending_select $selid
-	} else {
-	    set pending_select $mainheadid
-	}
+	reset_pending_select $selid
     } else {
-	set row [first_real_row]
-	if {$row < $numcommits} {
-	    selectline $row 0
+	reset_pending_select {}
+
+	if {[commitinview $pending_select $curview]} {
+	    selectline [rowofcommit $pending_select] 1
+	} else {
+	    set row [first_real_row]
+	    if {$row < $numcommits} {
+		selectline $row 0
+	    }
 	}
     }
     if {!$viewcomplete($n)} {
@@ -4011,6 +4055,7 @@
     }
     if {[info exists pending_select] &&
 	[commitinview $pending_select $curview]} {
+	update
 	selectline [rowofcommit $pending_select] 1
     }
     drawvisible
@@ -4048,10 +4093,11 @@
     incr lserial
     set fd [open "|git diff-index --cached HEAD" r]
     fconfigure $fd -blocking 0
-    filerun $fd [list readdiffindex $fd $lserial]
+    set i [reg_instance $fd]
+    filerun $fd [list readdiffindex $fd $lserial $i]
 }
 
-proc readdiffindex {fd serial} {
+proc readdiffindex {fd serial inst} {
     global mainheadid nullid nullid2 curview commitinfo commitdata lserial
 
     set isdiff 1
@@ -4062,7 +4108,7 @@
 	set isdiff 0
     }
     # we only need to see one line and we don't really care what it says...
-    close $fd
+    stop_instance $inst
 
     if {$serial != $lserial} {
 	return 0
@@ -4071,7 +4117,8 @@
     # now see if there are any local changes not checked in to the index
     set fd [open "|git diff-files" r]
     fconfigure $fd -blocking 0
-    filerun $fd [list readdifffiles $fd $serial]
+    set i [reg_instance $fd]
+    filerun $fd [list readdifffiles $fd $serial $i]
 
     if {$isdiff && ![commitinview $nullid2 $curview]} {
 	# add the line for the changes in the index to the graph
@@ -4088,7 +4135,7 @@
     return 0
 }
 
-proc readdifffiles {fd serial} {
+proc readdifffiles {fd serial inst} {
     global mainheadid nullid nullid2 curview
     global commitinfo commitdata lserial
 
@@ -4100,7 +4147,7 @@
 	set isdiff 0
     }
     # we only need to see one line and we don't really care what it says...
-    close $fd
+    stop_instance $inst
 
     if {$serial != $lserial} {
 	return 0
@@ -6430,9 +6477,10 @@
 proc gettreediffs {ids} {
     global treediff treepending
 
+    if {[catch {set gdtf [open [diffcmd $ids {--no-commit-id}] r]}]} return
+
     set treepending $ids
     set treediff {}
-    if {[catch {set gdtf [open [diffcmd $ids {--no-commit-id}] r]}]} return
     fconfigure $gdtf -blocking 0
     filerun $gdtf [list gettreediffline $gdtf $ids]
 }
@@ -9945,4 +9993,4 @@
 	addviewmenu $n
     }
 }
-getcommits
+getcommits {}
diff --git a/gitk-git/po/de.po b/gitk-git/po/de.po
index b9867bf..04ee570 100644
--- a/gitk-git/po/de.po
+++ b/gitk-git/po/de.po
@@ -7,19 +7,37 @@
 msgstr ""
 "Project-Id-Version: git-gui\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-05-01 11:54+0200\n"
-"PO-Revision-Date: 2008-05-02 21:12+0200\n"
+"POT-Creation-Date: 2008-05-24 22:32+0200\n"
+"PO-Revision-Date: 2008-05-24 22:40+0200\n"
 "Last-Translator: Christian Stimming <stimming@tuhh.de>\n"
 "Language-Team: German\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: gitk:111
-msgid "Error executing git rev-list:"
-msgstr "Fehler beim Ausführen von git-rev-list:"
+#: gitk:102
+msgid "Couldn't get list of unmerged files:"
+msgstr "Liste der nicht-zusammengeführten Dateien nicht gefunden:"
 
-#: gitk:124
+#: gitk:329
+msgid "No files selected: --merge specified but no files are unmerged."
+msgstr ""
+"Keine Dateien ausgewählt: --merge angegeben, es existieren aber keine nicht-"
+"zusammengeführten Dateien."
+
+#: gitk:332
+msgid ""
+"No files selected: --merge specified but no unmerged files are within file "
+"limit."
+msgstr ""
+"Keine Dateien ausgewähle: --merge angegeben, aber keine nicht-"
+"zusammengeführten Dateien sind in der Dateiauswahl."
+
+#: gitk:354
+msgid "Error executing git log:"
+msgstr "Fehler beim Ausführen von git-log:"
+
+#: gitk:369
 msgid "Reading"
 msgstr "Lesen"
 
@@ -56,7 +74,11 @@
 msgid "Update"
 msgstr "Aktualisieren"
 
-#: gitk:664
+#: gitk:1722
+msgid "Reload"
+msgstr "Neu laden"
+
+#: gitk:1723
 msgid "Reread references"
 msgstr "Zweige neu laden"
 
@@ -112,7 +134,11 @@
 msgid "SHA1 ID: "
 msgstr "SHA1:"
 
-#: gitk:791
+#: gitk:1831
+msgid "Row"
+msgstr "Zeile"
+
+#: gitk:1862
 msgid "Find"
 msgstr "Suche"
 
@@ -126,19 +152,19 @@
 
 #: gitk:794
 msgid "commit"
-msgstr "Version"
+msgstr "Version nach"
 
 #: gitk:797 gitk:799 gitk:2356 gitk:2379 gitk:2403 gitk:4306 gitk:4369
 msgid "containing:"
-msgstr "enthaltend:"
+msgstr "Beschreibung:"
 
 #: gitk:800 gitk:1778 gitk:1783 gitk:2431
 msgid "touching paths:"
-msgstr "Pfad betreffend:"
+msgstr "Dateien:"
 
 #: gitk:801 gitk:2436
 msgid "adding/removing string:"
-msgstr "Zeichenkette ändernd:"
+msgstr "Änderungen:"
 
 #: gitk:810 gitk:812
 msgid "Exact"
@@ -253,23 +279,25 @@
 msgid "Highlight this only"
 msgstr "Nur diesen hervorheben"
 
-#: gitk:1318
+#: gitk:2162
+msgid "External diff"
+msgstr "Externer Vergleich"
+
+#: gitk:2403
 msgid ""
 "\n"
 "Gitk - a commit viewer for git\n"
 "\n"
-"Copyright © 2005-2006 Paul Mackerras\n"
+"Copyright © 2005-2008 Paul Mackerras\n"
 "\n"
 "Use and redistribute under the terms of the GNU General Public License"
 msgstr ""
 "\n"
 "Gitk - eine Visualisierung der Git Historie\n"
 "\n"
-"Copyright © 2005-2006 Paul Mackerras\n"
+"Copyright © 2005-2008 Paul Mackerras\n"
 "\n"
-"Benutzung und Weiterverbreitung gemäß den Bedingungen der GNU General Public "
-"License\n"
-"        "
+"Benutzung und Weiterverbreitung gemäß den Bedingungen der GNU General Public License"
 
 #: gitk:1326 gitk:1387 gitk:6582
 msgid "Close"
@@ -450,11 +478,11 @@
 msgid "Remember this view"
 msgstr "Diese Ansicht speichern"
 
-#: gitk:1928
-msgid "Commits to include (arguments to git rev-list):"
-msgstr "Versionen anzeigen (Argumente von git-rev-list):"
+#: gitk:3126
+msgid "Commits to include (arguments to git log):"
+msgstr "Versionen anzeigen (Argumente von git-log):"
 
-#: gitk:1935
+#: gitk:3133
 msgid "Command to generate more commits to include:"
 msgstr "Versionsliste durch folgendes Kommando erzeugen lassen:"
 
@@ -566,7 +594,11 @@
 msgid "Reset %s branch to here"
 msgstr "Zweig »%s« hierher zurücksetzen"
 
-#: gitk:6050
+#: gitk:7204
+msgid "Detached head: can't reset"
+msgstr "Zweigspitze ist abgetrennt: Zurücksetzen nicht möglich"
+
+#: gitk:7236
 msgid "Top"
 msgstr "Oben"
 
@@ -798,7 +830,15 @@
 msgid "Limit diffs to listed paths"
 msgstr "Vergleich nur für angezeigte Pfade"
 
-#: gitk:8045
+#: gitk:9264
+msgid "External diff tool"
+msgstr "Externes Vergleich-(Diff-)Programm"
+
+#: gitk:9266
+msgid "Choose..."
+msgstr "Wählen..."
+
+#: gitk:9271
 msgid "Colors: press to choose"
 msgstr "Farben: Klicken zum Wählen"
 
@@ -873,22 +913,6 @@
 msgid "Bad arguments to gitk:"
 msgstr "Falsche Kommandozeilen-Parameter für gitk:"
 
-#: gitk:8637
-msgid "Couldn't get list of unmerged files:"
-msgstr "Liste der nicht-zusammengeführten Dateien nicht gefunden:"
-
-#: gitk:8653
-msgid "No files selected: --merge specified but no files are unmerged."
-msgstr "Keine Dateien ausgewählt: --merge angegeben, es existieren aber keine nicht-zusammengeführten Dateien."
-
-#: gitk:8656
-msgid ""
-"No files selected: --merge specified but no unmerged files are within file "
-"limit."
-msgstr ""
-"Keine Dateien ausgewähle: --merge angegeben, aber keine nicht-"
-"zusammengeführten Dateien sind in der Dateiauswahl."
-
-#: gitk:8717
+#: gitk:9915
 msgid "Command line"
 msgstr "Kommandozeile"
diff --git a/gitk-git/po/sv.po b/gitk-git/po/sv.po
index f6b080d..e1ecfb7 100644
--- a/gitk-git/po/sv.po
+++ b/gitk-git/po/sv.po
@@ -3,687 +3,724 @@
 # This file is distributed under the same license as the gitk package.
 #
 # Peter Karlsson <peter@softwolves.pp.se>, 2008.
+# Mikael Magnusson <mikachu@gmail.com>, 2008.
 msgid ""
 msgstr ""
 "Project-Id-Version: sv\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-03-14 15:03+0100\n"
-"PO-Revision-Date: 2008-03-14 16:06CET-1\n"
-"Last-Translator: Peter Karlsson <peter@softwolves.pp.se>\n"
+"POT-Creation-Date: 2008-08-03 18:58+0200\n"
+"PO-Revision-Date: 2008-08-03 19:03+0200\n"
+"Last-Translator: Mikael Magnusson <mikachu@gmail.com>\n"
 "Language-Team: Swedish <sv@li.org>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: 8bit"
+"Content-Transfer-Encoding: 8bit\n"
 
-#: gitk:111
-msgid "Error executing git rev-list:"
-msgstr "Fel vid körning av git rev-list:"
+#: gitk:102
+msgid "Couldn't get list of unmerged files:"
+msgstr "Kunde inta hämta lista över ej sammanslagna filer:"
 
-#: gitk:124
+#: gitk:329
+msgid "No files selected: --merge specified but no files are unmerged."
+msgstr ""
+"Inga filer valdes: --merge angavs men det finns inga filer som inte har "
+"slagits samman."
+
+#: gitk:332
+msgid ""
+"No files selected: --merge specified but no unmerged files are within file "
+"limit."
+msgstr ""
+"Inga filer valdes: --merge angavs men det finns inga filer inom "
+"filbegränsningen."
+
+#: gitk:354
+msgid "Error executing git log:"
+msgstr "Fel vid körning av git log:"
+
+#: gitk:369
 msgid "Reading"
 msgstr "Läser"
 
-#: gitk:151 gitk:2191
+#: gitk:400 gitk:3356
 msgid "Reading commits..."
 msgstr "Läser incheckningar..."
 
-#: gitk:275
-msgid "Can't parse git log output:"
-msgstr "Kan inte tolka utdata från git log:"
-
-#: gitk:386 gitk:2195
+#: gitk:403 gitk:1480 gitk:3359
 msgid "No commits selected"
 msgstr "Inga incheckningar markerade"
 
-#: gitk:500
+#: gitk:1358
+msgid "Can't parse git log output:"
+msgstr "Kan inte tolka utdata från git log:"
+
+#: gitk:1557
 msgid "No commit information available"
 msgstr "Ingen incheckningsinformation är tillgänglig"
 
-#: gitk:599 gitk:621 gitk:1955 gitk:6423 gitk:7923 gitk:8082
+#: gitk:1654 gitk:1676 gitk:3150 gitk:7620 gitk:9149 gitk:9317
 msgid "OK"
 msgstr "OK"
 
-#: gitk:623 gitk:1956 gitk:6107 gitk:6178 gitk:6275 gitk:6321 gitk:6425
-#: gitk:7924 gitk:8083
+#: gitk:1678 gitk:3151 gitk:7296 gitk:7367 gitk:7470 gitk:7516 gitk:7622
+#: gitk:9150 gitk:9318
 msgid "Cancel"
 msgstr "Avbryt"
 
-#: gitk:661
+#: gitk:1716
 msgid "File"
 msgstr "Arkiv"
 
-#: gitk:663
+#: gitk:1718
 msgid "Update"
 msgstr "Uppdatera"
 
-#: gitk:664
+#: gitk:1719
+msgid "Reload"
+msgstr "Ladda om"
+
+#: gitk:1720
 msgid "Reread references"
 msgstr "Läs om referenser"
 
-#: gitk:665
+#: gitk:1721
 msgid "List references"
 msgstr "Visa referenser"
 
-#: gitk:666
+#: gitk:1722
 msgid "Quit"
 msgstr "Avsluta"
 
-#: gitk:668
+#: gitk:1724
 msgid "Edit"
 msgstr "Redigera"
 
-#: gitk:669
+#: gitk:1725
 msgid "Preferences"
 msgstr "Inställningar"
 
-#: gitk:672 gitk:1892
+#: gitk:1728 gitk:3087
 msgid "View"
 msgstr "Visa"
 
-#: gitk:673
+#: gitk:1729
 msgid "New view..."
 msgstr "Ny vy..."
 
-#: gitk:674 gitk:2133 gitk:8722
+#: gitk:1730 gitk:3298 gitk:9932
 msgid "Edit view..."
 msgstr "Ändra vy..."
 
-#: gitk:676 gitk:2134 gitk:8723
+#: gitk:1732 gitk:3299 gitk:9933
 msgid "Delete view"
 msgstr "Ta bort vy"
 
-#: gitk:678
+#: gitk:1734
 msgid "All files"
 msgstr "Alla filer"
 
-#: gitk:682
+#: gitk:1738
 msgid "Help"
 msgstr "Hjälp"
 
-#: gitk:683 gitk:1317
+#: gitk:1739 gitk:2399
 msgid "About gitk"
 msgstr "Om gitk"
 
-#: gitk:684
+#: gitk:1740
 msgid "Key bindings"
 msgstr "Tangentbordsbindningar"
 
-#: gitk:741
+#: gitk:1797
 msgid "SHA1 ID: "
 msgstr "SHA1-id: "
 
-#: gitk:791
+#: gitk:1828
+msgid "Row"
+msgstr "Rad"
+
+#: gitk:1859
 msgid "Find"
 msgstr "Sök"
 
-#: gitk:792
+#: gitk:1860
 msgid "next"
 msgstr "nästa"
 
-#: gitk:793
+#: gitk:1861
 msgid "prev"
 msgstr "föreg"
 
-#: gitk:794
+#: gitk:1862
 msgid "commit"
 msgstr "incheckning"
 
-#: gitk:797 gitk:799 gitk:2356 gitk:2379 gitk:2403 gitk:4306 gitk:4369
+#: gitk:1865 gitk:1867 gitk:3511 gitk:3534 gitk:3558 gitk:5441 gitk:5512
 msgid "containing:"
 msgstr "som innehåller:"
 
-#: gitk:800 gitk:1778 gitk:1783 gitk:2431
+#: gitk:1868 gitk:2866 gitk:2871 gitk:3586
 msgid "touching paths:"
 msgstr "som rör sökväg:"
 
-#: gitk:801 gitk:2436
+#: gitk:1869 gitk:3591
 msgid "adding/removing string:"
 msgstr "som lägger/till tar bort sträng:"
 
-#: gitk:810 gitk:812
+#: gitk:1878 gitk:1880
 msgid "Exact"
 msgstr "Exakt"
 
-#: gitk:812 gitk:2514 gitk:4274
+#: gitk:1880 gitk:3667 gitk:5409
 msgid "IgnCase"
 msgstr "IgnVersaler"
 
-#: gitk:812 gitk:2405 gitk:2512 gitk:4270
+#: gitk:1880 gitk:3560 gitk:3665 gitk:5405
 msgid "Regexp"
 msgstr "Reg.uttr."
 
-#: gitk:814 gitk:815 gitk:2533 gitk:2563 gitk:2570 gitk:4380 gitk:4436
+#: gitk:1882 gitk:1883 gitk:3686 gitk:3716 gitk:3723 gitk:5532 gitk:5599
 msgid "All fields"
 msgstr "Alla fält"
 
-#: gitk:815 gitk:2531 gitk:2563 gitk:4336
+#: gitk:1883 gitk:3684 gitk:3716 gitk:5471
 msgid "Headline"
 msgstr "Rubrik"
 
-#: gitk:816 gitk:2531 gitk:4336 gitk:4436 gitk:4827
+#: gitk:1884 gitk:3684 gitk:5471 gitk:5599 gitk:6000
 msgid "Comments"
 msgstr "Kommentarer"
 
-#: gitk:816 gitk:2531 gitk:2535 gitk:2570 gitk:4336 gitk:4763 gitk:5956
-#: gitk:5971
+#: gitk:1884 gitk:3684 gitk:3688 gitk:3723 gitk:5471 gitk:5936 gitk:7142
+#: gitk:7157
 msgid "Author"
 msgstr "Författare"
 
-#: gitk:816 gitk:2531 gitk:4336 gitk:4765
+#: gitk:1884 gitk:3684 gitk:5471 gitk:5938
 msgid "Committer"
 msgstr "Incheckare"
 
-#: gitk:845
+#: gitk:1913
 msgid "Search"
 msgstr "Sök"
 
-#: gitk:852
+#: gitk:1920
 msgid "Diff"
 msgstr "Diff"
 
-#: gitk:854
+#: gitk:1922
 msgid "Old version"
 msgstr "Gammal version"
 
-#: gitk:856
+#: gitk:1924
 msgid "New version"
 msgstr "Ny version"
 
-#: gitk:858
+#: gitk:1926
 msgid "Lines of context"
 msgstr "Rader sammanhang"
 
-#: gitk:868
+#: gitk:1936
 msgid "Ignore space change"
 msgstr "Ignorera ändringar i blanksteg"
 
-#: gitk:926
+#: gitk:1994
 msgid "Patch"
 msgstr "Patch"
 
-#: gitk:928
+#: gitk:1996
 msgid "Tree"
 msgstr "Träd"
 
-#: gitk:1053 gitk:1068 gitk:6022
+#: gitk:2121 gitk:2136 gitk:7211
 msgid "Diff this -> selected"
 msgstr "Diff denna -> markerad"
 
-#: gitk:1055 gitk:1070 gitk:6023
+#: gitk:2123 gitk:2138 gitk:7212
 msgid "Diff selected -> this"
 msgstr "Diff markerad -> denna"
 
-#: gitk:1057 gitk:1072 gitk:6024
+#: gitk:2125 gitk:2140 gitk:7213
 msgid "Make patch"
 msgstr "Skapa patch"
 
-#: gitk:1058 gitk:6162
+#: gitk:2126 gitk:7351
 msgid "Create tag"
 msgstr "Skapa tagg"
 
-#: gitk:1059 gitk:6255
+#: gitk:2127 gitk:7450
 msgid "Write commit to file"
 msgstr "Skriv incheckning till fil"
 
-#: gitk:1060 gitk:6309
+#: gitk:2128 gitk:7504
 msgid "Create new branch"
 msgstr "Skapa ny gren"
 
-#: gitk:1061
+#: gitk:2129
 msgid "Cherry-pick this commit"
 msgstr "Plocka denna incheckning"
 
-#: gitk:1063
+#: gitk:2131
 msgid "Reset HEAD branch to here"
 msgstr "Återställ HEAD-grenen hit"
 
-#: gitk:1079
+#: gitk:2147
 msgid "Check out this branch"
 msgstr "Checka ut denna gren"
 
-#: gitk:1081
+#: gitk:2149
 msgid "Remove this branch"
 msgstr "Ta bort denna gren"
 
-#: gitk:1087
+#: gitk:2155
 msgid "Highlight this too"
 msgstr "Markera även detta"
 
-#: gitk:1089
+#: gitk:2157
 msgid "Highlight this only"
 msgstr "Markera bara detta"
 
-#: gitk:1318
+#: gitk:2159
+msgid "External diff"
+msgstr "Extern diff"
+
+#: gitk:2400
 msgid ""
 "\n"
 "Gitk - a commit viewer for git\n"
 "\n"
-"Copyright © 2005-2006 Paul Mackerras\n"
+"Copyright © 2005-2008 Paul Mackerras\n"
 "\n"
 "Use and redistribute under the terms of the GNU General Public License"
 msgstr ""
 "\n"
 "Gitk - en incheckningsvisare för git\n"
 "\n"
-"Copyright © 2005-2006 Paul Mackerras\n"
+"Copyright © 2005-2008 Paul Mackerras\n"
 "\n"
 "Använd och vidareförmedla enligt villkoren i GNU General Public License"
 
-#: gitk:1326 gitk:1387 gitk:6581
+#: gitk:2408 gitk:2469 gitk:7799
 msgid "Close"
 msgstr "Stäng"
 
-#: gitk:1345
+#: gitk:2427
 msgid "Gitk key bindings"
 msgstr "Tangentbordsbindningar för Gitk"
 
-#: gitk:1347
+#: gitk:2429
 msgid "Gitk key bindings:"
 msgstr "Tangentbordsbindningar för Gitk:"
 
-#: gitk:1349
+#: gitk:2431
 #, tcl-format
 msgid "<%s-Q>\t\tQuit"
 msgstr "<%s-Q>\t\tAvsluta"
 
-#: gitk:1350
+#: gitk:2432
 msgid "<Home>\t\tMove to first commit"
 msgstr "<Home>\t\tGå till första incheckning"
 
-#: gitk:1351
+#: gitk:2433
 msgid "<End>\t\tMove to last commit"
 msgstr "<End>\t\tGå till sista incheckning"
 
-#: gitk:1352
+#: gitk:2434
 msgid "<Up>, p, i\tMove up one commit"
 msgstr "<Upp>, p, i\tGå en incheckning upp"
 
-#: gitk:1353
+#: gitk:2435
 msgid "<Down>, n, k\tMove down one commit"
 msgstr "<Ned>, n, k\tGå en incheckning ned"
 
-#: gitk:1354
+#: gitk:2436
 msgid "<Left>, z, j\tGo back in history list"
 msgstr "<Vänster>, z, j\tGå bakåt i historiken"
 
-#: gitk:1355
+#: gitk:2437
 msgid "<Right>, x, l\tGo forward in history list"
 msgstr "<Höger>, x, l\tGå framåt i historiken"
 
-#: gitk:1356
+#: gitk:2438
 msgid "<PageUp>\tMove up one page in commit list"
 msgstr "<PageUp>\tGå upp en sida i incheckningslistan"
 
-#: gitk:1357
+#: gitk:2439
 msgid "<PageDown>\tMove down one page in commit list"
 msgstr "<PageDown>\tGå ned en sida i incheckningslistan"
 
-#: gitk:1358
+#: gitk:2440
 #, tcl-format
 msgid "<%s-Home>\tScroll to top of commit list"
 msgstr "<%s-Home>\tRulla till början av incheckningslistan"
 
-#: gitk:1359
+#: gitk:2441
 #, tcl-format
 msgid "<%s-End>\tScroll to bottom of commit list"
 msgstr "<%s-End>\tRulla till slutet av incheckningslistan"
 
-#: gitk:1360
+#: gitk:2442
 #, tcl-format
 msgid "<%s-Up>\tScroll commit list up one line"
 msgstr "<%s-Upp>\tRulla incheckningslistan upp ett steg"
 
-#: gitk:1361
+#: gitk:2443
 #, tcl-format
 msgid "<%s-Down>\tScroll commit list down one line"
 msgstr "<%s-Ned>\tRulla incheckningslistan ned ett steg"
 
-#: gitk:1362
+#: gitk:2444
 #, tcl-format
 msgid "<%s-PageUp>\tScroll commit list up one page"
 msgstr "<%s-PageUp>\tRulla incheckningslistan upp en sida"
 
-#: gitk:1363
+#: gitk:2445
 #, tcl-format
 msgid "<%s-PageDown>\tScroll commit list down one page"
 msgstr "<%s-PageDown>\tRulla incheckningslistan ned en sida"
 
-#: gitk:1364
+#: gitk:2446
 msgid "<Shift-Up>\tFind backwards (upwards, later commits)"
 msgstr "<Skift-Upp>\tSök bakåt (uppåt, senare incheckningar)"
 
-#: gitk:1365
+#: gitk:2447
 msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)"
 msgstr "<Skift-Ned>\tSök framåt (nedåt, tidigare incheckningar)"
 
-#: gitk:1366
+#: gitk:2448
 msgid "<Delete>, b\tScroll diff view up one page"
 msgstr "<Delete>, b\tRulla diffvisningen upp en sida"
 
-#: gitk:1367
+#: gitk:2449
 msgid "<Backspace>\tScroll diff view up one page"
 msgstr "<Baksteg>\tRulla diffvisningen upp en sida"
 
-#: gitk:1368
+#: gitk:2450
 msgid "<Space>\t\tScroll diff view down one page"
 msgstr "<Blanksteg>\tRulla diffvisningen ned en sida"
 
-#: gitk:1369
+#: gitk:2451
 msgid "u\t\tScroll diff view up 18 lines"
 msgstr "u\t\tRulla diffvisningen upp 18 rader"
 
-#: gitk:1370
+#: gitk:2452
 msgid "d\t\tScroll diff view down 18 lines"
 msgstr "d\t\tRulla diffvisningen ned 18 rader"
 
-#: gitk:1371
+#: gitk:2453
 #, tcl-format
 msgid "<%s-F>\t\tFind"
 msgstr "<%s-F>\t\tSök"
 
-#: gitk:1372
+#: gitk:2454
 #, tcl-format
 msgid "<%s-G>\t\tMove to next find hit"
 msgstr "<%s-G>\t\tGå till nästa sökträff"
 
-#: gitk:1373
+#: gitk:2455
 msgid "<Return>\tMove to next find hit"
 msgstr "<Return>\t\tGå till nästa sökträff"
 
-#: gitk:1374
+#: gitk:2456
 msgid "/\t\tMove to next find hit, or redo find"
 msgstr "/\t\tGå till nästa sökträff, eller sök på nytt"
 
-#: gitk:1375
+#: gitk:2457
 msgid "?\t\tMove to previous find hit"
 msgstr "?\t\tGå till föregående sökträff"
 
-#: gitk:1376
+#: gitk:2458
 msgid "f\t\tScroll diff view to next file"
 msgstr "f\t\tRulla diffvisningen till nästa fil"
 
-#: gitk:1377
+#: gitk:2459
 #, tcl-format
 msgid "<%s-S>\t\tSearch for next hit in diff view"
 msgstr "<%s-S>\t\tGå till nästa sökträff i diffvisningen"
 
-#: gitk:1378
+#: gitk:2460
 #, tcl-format
 msgid "<%s-R>\t\tSearch for previous hit in diff view"
 msgstr "<%s-R>\t\tGå till föregående sökträff i diffvisningen"
 
-#: gitk:1379
+#: gitk:2461
 #, tcl-format
 msgid "<%s-KP+>\tIncrease font size"
 msgstr "<%s-Num+>\tÖka teckenstorlek"
 
-#: gitk:1380
+#: gitk:2462
 #, tcl-format
 msgid "<%s-plus>\tIncrease font size"
 msgstr "<%s-plus>\tÖka teckenstorlek"
 
-#: gitk:1381
+#: gitk:2463
 #, tcl-format
 msgid "<%s-KP->\tDecrease font size"
 msgstr "<%s-Num->\tMinska teckenstorlek"
 
-#: gitk:1382
+#: gitk:2464
 #, tcl-format
 msgid "<%s-minus>\tDecrease font size"
 msgstr "<%s-minus>\tMinska teckenstorlek"
 
-#: gitk:1383
+#: gitk:2465
 msgid "<F5>\t\tUpdate"
 msgstr "<F5>\t\tUppdatera"
 
-#: gitk:1896
+#: gitk:3091
 msgid "Gitk view definition"
 msgstr "Definition av Gitk-vy"
 
-#: gitk:1921
+#: gitk:3116
 msgid "Name"
 msgstr "Namn"
 
-#: gitk:1924
+#: gitk:3119
 msgid "Remember this view"
 msgstr "Spara denna vy"
 
-#: gitk:1928
-msgid "Commits to include (arguments to git rev-list):"
-msgstr "Incheckningar att ta med (argument till git rev-list):"
+#: gitk:3123
+msgid "Commits to include (arguments to git log):"
+msgstr "Incheckningar att ta med (argument till git log):"
 
-#: gitk:1935
+#: gitk:3130
 msgid "Command to generate more commits to include:"
 msgstr "Kommando för att generera fler incheckningar att ta med:"
 
-#: gitk:1942
+#: gitk:3137
 msgid "Enter files and directories to include, one per line:"
 msgstr "Ange filer och kataloger att ta med, en per rad:"
 
-#: gitk:1989
+#: gitk:3184
 msgid "Error in commit selection arguments:"
 msgstr "Fel i argument för val av incheckningar:"
 
-#: gitk:2043 gitk:2127 gitk:2583 gitk:2597 gitk:3781 gitk:8688 gitk:8689
+#: gitk:3238 gitk:3290 gitk:3736 gitk:3750 gitk:4951 gitk:9896 gitk:9897
 msgid "None"
 msgstr "Inget"
 
-#: gitk:2531 gitk:4336 gitk:5958 gitk:5973
+#: gitk:3684 gitk:5471 gitk:7144 gitk:7159
 msgid "Date"
 msgstr "Datum"
 
-#: gitk:2531 gitk:4336
+#: gitk:3684 gitk:5471
 msgid "CDate"
 msgstr "Skapat datum"
 
-#: gitk:2680 gitk:2685
+#: gitk:3833 gitk:3838
 msgid "Descendant"
 msgstr "Avkomling"
 
-#: gitk:2681
+#: gitk:3834
 msgid "Not descendant"
 msgstr "Inte avkomling"
 
-#: gitk:2688 gitk:2693
+#: gitk:3841 gitk:3846
 msgid "Ancestor"
 msgstr "Förfader"
 
-#: gitk:2689
+#: gitk:3842
 msgid "Not ancestor"
 msgstr "Inte förfader"
 
-#: gitk:2924
+#: gitk:4078
 msgid "Local changes checked in to index but not committed"
 msgstr "Lokala ändringar sparade i indexet men inte incheckade"
 
-#: gitk:2954
+#: gitk:4111
 msgid "Local uncommitted changes, not checked in to index"
 msgstr "Lokala ändringar, ej sparade i indexet"
 
-#: gitk:4305
+#: gitk:5440
 msgid "Searching"
 msgstr "Söker"
 
-#: gitk:4767
+#: gitk:5940
 msgid "Tags:"
 msgstr "Taggar:"
 
-#: gitk:4784 gitk:4790 gitk:5951
+#: gitk:5957 gitk:5963 gitk:7137
 msgid "Parent"
 msgstr "Förälder"
 
-#: gitk:4795
+#: gitk:5968
 msgid "Child"
 msgstr "Barn"
 
-#: gitk:4804
+#: gitk:5977
 msgid "Branch"
 msgstr "Gren"
 
-#: gitk:4807
+#: gitk:5980
 msgid "Follows"
 msgstr "Följer"
 
-#: gitk:4810
+#: gitk:5983
 msgid "Precedes"
 msgstr "Föregår"
 
-#: gitk:5093
+#: gitk:6267
 msgid "Error getting merge diffs:"
 msgstr "Fel vid hämtning av sammanslagningsdiff:"
 
-#: gitk:5778
+#: gitk:6970
 msgid "Goto:"
 msgstr "Gå till:"
 
-#: gitk:5780
+#: gitk:6972
 msgid "SHA1 ID:"
 msgstr "SHA1-id:"
 
-#: gitk:5805
+#: gitk:6991
 #, tcl-format
 msgid "Short SHA1 id %s is ambiguous"
 msgstr "Förkortat SHA1-id %s är tvetydigt"
 
-#: gitk:5817
+#: gitk:7003
 #, tcl-format
 msgid "SHA1 id %s is not known"
 msgstr "SHA-id:t %s är inte känt"
 
-#: gitk:5819
+#: gitk:7005
 #, tcl-format
 msgid "Tag/Head %s is not known"
 msgstr "Tagg/huvud %s är okänt"
 
-#: gitk:5961
+#: gitk:7147
 msgid "Children"
 msgstr "Barn"
 
-#: gitk:6018
+#: gitk:7204
 #, tcl-format
 msgid "Reset %s branch to here"
 msgstr "Återställ grenen %s hit"
 
-#: gitk:6049
+#: gitk:7206
+msgid "Detached head: can't reset"
+msgstr "Frånkopplad head: kan inte återställa"
+
+#: gitk:7238
 msgid "Top"
 msgstr "Topp"
 
-#: gitk:6050
+#: gitk:7239
 msgid "From"
 msgstr "Från"
 
-#: gitk:6055
+#: gitk:7244
 msgid "To"
 msgstr "Till"
 
-#: gitk:6078
+#: gitk:7267
 msgid "Generate patch"
 msgstr "Generera patch"
 
-#: gitk:6080
+#: gitk:7269
 msgid "From:"
 msgstr "Från:"
 
-#: gitk:6089
+#: gitk:7278
 msgid "To:"
 msgstr "Till:"
 
-#: gitk:6098
+#: gitk:7287
 msgid "Reverse"
 msgstr "Vänd"
 
-#: gitk:6100 gitk:6269
+#: gitk:7289 gitk:7464
 msgid "Output file:"
 msgstr "Utdatafil:"
 
-#: gitk:6106
+#: gitk:7295
 msgid "Generate"
 msgstr "Generera"
 
-#: gitk:6142
+#: gitk:7331
 msgid "Error creating patch:"
 msgstr "Fel vid generering av patch:"
 
-#: gitk:6164 gitk:6257 gitk:6311
+#: gitk:7353 gitk:7452 gitk:7506
 msgid "ID:"
 msgstr "Id:"
 
-#: gitk:6173
+#: gitk:7362
 msgid "Tag name:"
 msgstr "Taggnamn:"
 
-#: gitk:6177 gitk:6320
+#: gitk:7366 gitk:7515
 msgid "Create"
 msgstr "Skapa"
 
-#: gitk:6192
+#: gitk:7381
 msgid "No tag name specified"
 msgstr "Inget taggnamn angavs"
 
-#: gitk:6196
+#: gitk:7385
 #, tcl-format
 msgid "Tag \"%s\" already exists"
 msgstr "Taggen \"%s\" finns redan"
 
-#: gitk:6202
+#: gitk:7391
 msgid "Error creating tag:"
 msgstr "Fel vid skapande av tagg:"
 
-#: gitk:6266
+#: gitk:7461
 msgid "Command:"
 msgstr "Kommando:"
 
-#: gitk:6274
+#: gitk:7469
 msgid "Write"
 msgstr "Skriv"
 
-#: gitk:6290
+#: gitk:7485
 msgid "Error writing commit:"
 msgstr "Fel vid skrivning av incheckning:"
 
-#: gitk:6316
+#: gitk:7511
 msgid "Name:"
 msgstr "Namn:"
 
-#: gitk:6335
+#: gitk:7530
 msgid "Please specify a name for the new branch"
 msgstr "Ange ett namn för den nya grenen"
 
-#: gitk:6364
+#: gitk:7559
 #, tcl-format
 msgid "Commit %s is already included in branch %s -- really re-apply it?"
-msgstr "Incheckningen %s finns redan på grenen %s -- skall den verkligen appliceras på nytt?"
+msgstr ""
+"Incheckningen %s finns redan på grenen %s -- skall den verkligen appliceras "
+"på nytt?"
 
-#: gitk:6369
+#: gitk:7564
 msgid "Cherry-picking"
 msgstr "Plockar"
 
-#: gitk:6381
+#: gitk:7576
 msgid "No changes committed"
 msgstr "Inga ändringar incheckade"
 
-#: gitk:6404
+#: gitk:7601
 msgid "Confirm reset"
 msgstr "Bekräfta återställning"
 
-#: gitk:6406
+#: gitk:7603
 #, tcl-format
 msgid "Reset branch %s to %s?"
 msgstr "Återställa grenen %s till %s?"
 
-#: gitk:6410
+#: gitk:7607
 msgid "Reset type:"
 msgstr "Typ av återställning:"
 
-#: gitk:6414
+#: gitk:7611
 msgid "Soft: Leave working tree and index untouched"
 msgstr "Mjuk: Rör inte utcheckning och index"
 
-#: gitk:6417
+#: gitk:7614
 msgid "Mixed: Leave working tree untouched, reset index"
 msgstr "Blandad: Rör inte utcheckning, återställ index"
 
-#: gitk:6420
+#: gitk:7617
 msgid ""
 "Hard: Reset working tree and index\n"
 "(discard ALL local changes)"
@@ -691,19 +728,19 @@
 "Hård: Återställ utcheckning och index\n"
 "(förkastar ALLA lokala ändringar)"
 
-#: gitk:6436
+#: gitk:7633
 msgid "Resetting"
 msgstr "Återställer"
 
-#: gitk:6493
+#: gitk:7690
 msgid "Checking out"
 msgstr "Checkar ut"
 
-#: gitk:6523
+#: gitk:7741
 msgid "Cannot delete the currently checked-out branch"
 msgstr "Kan inte ta bort den just nu utcheckade grenen"
 
-#: gitk:6529
+#: gitk:7747
 #, tcl-format
 msgid ""
 "The commits on branch %s aren't on any other branch.\n"
@@ -712,16 +749,16 @@
 "Incheckningarna på grenen %s existerar inte på någon annan gren.\n"
 "Vill du verkligen ta bort grenen %s?"
 
-#: gitk:6560
+#: gitk:7778
 #, tcl-format
 msgid "Tags and heads: %s"
 msgstr "Taggar och huvuden: %s"
 
-#: gitk:6574
+#: gitk:7792
 msgid "Filter"
 msgstr "Filter"
 
-#: gitk:6868
+#: gitk:8086
 msgid ""
 "Error reading commit topology information; branch and preceding/following "
 "tag information will be incomplete."
@@ -729,117 +766,125 @@
 "Fel vid läsning av information om incheckningstopologi; information om "
 "grenar och föregående/senare taggar kommer inte vara komplett."
 
-#: gitk:7852
+#: gitk:9072
 msgid "Tag"
 msgstr "Tagg"
 
-#: gitk:7852
+#: gitk:9072
 msgid "Id"
 msgstr "Id"
 
-#: gitk:7892
+#: gitk:9118
 msgid "Gitk font chooser"
 msgstr "Teckensnittsväljare för Gitk"
 
-#: gitk:7909
+#: gitk:9135
 msgid "B"
 msgstr "F"
 
-#: gitk:7912
+#: gitk:9138
 msgid "I"
 msgstr "K"
 
-#: gitk:8005
+#: gitk:9231
 msgid "Gitk preferences"
 msgstr "Inställningar för Gitk"
 
-#: gitk:8006
+#: gitk:9232
 msgid "Commit list display options"
 msgstr "Alternativ för incheckningslistvy"
 
-#: gitk:8009
+#: gitk:9235
 msgid "Maximum graph width (lines)"
 msgstr "Maximal grafbredd (rader)"
 
-#: gitk:8013
+#: gitk:9239
 #, tcl-format
 msgid "Maximum graph width (% of pane)"
 msgstr "Maximal grafbredd (% av ruta)"
 
-#: gitk:8018
+#: gitk:9244
 msgid "Show local changes"
 msgstr "Visa lokala ändringar"
 
-#: gitk:8023
+#: gitk:9249
 msgid "Auto-select SHA1"
 msgstr "Välj SHA1 automatiskt"
 
-#: gitk:8028
+#: gitk:9254
 msgid "Diff display options"
 msgstr "Alternativ för diffvy"
 
-#: gitk:8030
+#: gitk:9256
 msgid "Tab spacing"
 msgstr "Blanksteg för tabulatortecken"
 
-#: gitk:8034
+#: gitk:9260
 msgid "Display nearby tags"
 msgstr "Visa närliggande taggar"
 
-#: gitk:8039
+#: gitk:9265
 msgid "Limit diffs to listed paths"
 msgstr "Begränsa diff till listade sökvägar"
 
-#: gitk:8044
+#: gitk:9272
+msgid "External diff tool"
+msgstr "Externt diff-verktyg"
+
+#: gitk:9274
+msgid "Choose..."
+msgstr "Välj..."
+
+#: gitk:9279
 msgid "Colors: press to choose"
 msgstr "Färger: tryck för att välja"
 
-#: gitk:8047
+#: gitk:9282
 msgid "Background"
 msgstr "Bakgrund"
 
-#: gitk:8051
+#: gitk:9286
 msgid "Foreground"
 msgstr "Förgrund"
 
-#: gitk:8055
+#: gitk:9290
 msgid "Diff: old lines"
 msgstr "Diff: gamla rader"
 
-#: gitk:8060
+#: gitk:9295
 msgid "Diff: new lines"
 msgstr "Diff: nya rader"
 
-#: gitk:8065
+#: gitk:9300
 msgid "Diff: hunk header"
 msgstr "Diff: delhuvud"
 
-#: gitk:8071
+#: gitk:9306
 msgid "Select bg"
 msgstr "Markerad bakgrund"
 
-#: gitk:8075
+#: gitk:9310
 msgid "Fonts: press to choose"
 msgstr "Teckensnitt: tryck för att välja"
 
-#: gitk:8077
+#: gitk:9312
 msgid "Main font"
 msgstr "Huvudteckensnitt"
 
-#: gitk:8078
+#: gitk:9313
 msgid "Diff display font"
 msgstr "Teckensnitt för diffvisning"
 
-#: gitk:8079
+#: gitk:9314
 msgid "User interface font"
 msgstr "Teckensnitt för användargränssnitt"
 
-#: gitk:8095
+#: gitk:9339
 #, tcl-format
 msgid "Gitk: choose color for %s"
 msgstr "Gitk: välj färg för %s"
 
-#: gitk:8476
+#: gitk:9720
 msgid ""
 "Sorry, gitk cannot run with this version of Tcl/Tk.\n"
 " Gitk requires at least Tcl/Tk 8.4."
@@ -847,41 +892,24 @@
 "Gitk kan tyvärr inte köra med denna version av Tcl/Tk.\n"
 " Gitk kräver åtminstone Tcl/Tk 8.4."
 
-#: gitk:8565
+#: gitk:9812
 msgid "Cannot find a git repository here."
 msgstr "Hittar inget gitk-arkiv här."
 
-#: gitk:8569
+#: gitk:9816
 #, tcl-format
 msgid "Cannot find the git directory \"%s\"."
 msgstr "Hittar inte git-katalogen \"%s\"."
 
-#: gitk:8612
+#: gitk:9853
 #, tcl-format
 msgid "Ambiguous argument '%s': both revision and filename"
 msgstr "Tvetydigt argument \"%s\": både revision och filnamn"
 
-#: gitk:8624
+#: gitk:9865
 msgid "Bad arguments to gitk:"
 msgstr "Felaktiga argument till gitk:"
 
-#: gitk:8636
-msgid "Couldn't get list of unmerged files:"
-msgstr "Kunde inta hämta lista över ej sammanslagna filer:"
-
-#: gitk:8652
-msgid "No files selected: --merge specified but no files are unmerged."
-msgstr "Inga filer valdes: --merge angavs men det finns inga filer som inte har slagits samman."
-
-#: gitk:8655
-msgid ""
-"No files selected: --merge specified but no unmerged files are within file "
-"limit."
-msgstr ""
-"Inga filer valdes: --merge angavs men det finns inga filer inom "
-"filbegränsningen."
-
-#: gitk:8716
+#: gitk:9925
 msgid "Command line"
 msgstr "Kommandorad"
-
diff --git a/gitweb/INSTALL b/gitweb/INSTALL
index f7194db..26967e2 100644
--- a/gitweb/INSTALL
+++ b/gitweb/INSTALL
@@ -144,6 +144,12 @@
   Spaces in both project path and project owner have to be encoded as either
   '%20' or '+'.
 
+  Other characters that have to be url-encoded, i.e. replaced by '%'
+  followed by two-digit character number in octal, are: other whitespace
+  characters (because they are field separator in a record), plus sign '+'
+  (because it can be used as replacement for spaces), and percent sign '%'
+  (which is used for encoding / escaping).
+
   You can generate the projects list index file using the project_index
   action (the 'TXT' link on projects list page) directly from gitweb.
 
diff --git a/gitweb/README b/gitweb/README
index 356ab7b..825162a 100644
--- a/gitweb/README
+++ b/gitweb/README
@@ -156,10 +156,11 @@
    set correctly for gitweb to find repositories.
  * $projects_list
    Source of projects list, either directory to scan, or text file
-   with list of repositories (in the "<URI-encoded repository path> SPC
-   <URI-encoded repository owner>" format).  Set to $GITWEB_LIST
-   during installation.  If empty, $projectroot is used to scan for
-   repositories.
+   with list of repositories (in the "<URI-encoded repository path> SP
+   <URI-encoded repository owner>" line format; actually there can be
+   any sequence of whitespace in place of space (SP)).  Set to
+   $GITWEB_LIST during installation.  If empty, $projectroot is used
+   to scan for repositories.
  * $my_url, $my_uri
    URL and absolute URL of gitweb script; you might need to set those
    variables if you are using 'pathinfo' feature: see also below.
@@ -214,6 +215,39 @@
    ('-M'); set it to ('-C') or ('-C', '-C') to also detect copies, or
    set it to () if you don't want to have renames detection.
 
+
+Projects list file format
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Instead of having gitweb find repositories by scanning filesystem starting
+from $projectroot (or $projects_list, if it points to directory), you can
+provide list of projects by setting $projects_list to a text file with list
+of projects (and some additional info).  This file uses the following
+format:
+
+One record (for project / repository) per line, whitespace separated fields;
+does not support (at least for now) lines continuation (newline escaping).
+Leading and trailing whitespace are ignored, any run of whitespace can be
+used as field separator (rules for Perl's "split(' ', $line)").  Keyed by
+the first field, which is project name, i.e. path to repository GIT_DIR
+relative to $projectroot.  Fields use modified URI encoding, defined in
+RFC 3986, section 2.1 (Percent-Encoding), or rather "Query string encoding"
+(see http://en.wikipedia.org/wiki/Query_string#URL_encoding), the difference
+being that SP (' ') can be encoded as '+' (and therefore '+' has to be also
+percent-encoded).  Reserved characters are: '%' (used for encoding), '+'
+(can be used to encode SPACE), all whitespace characters as defined in Perl,
+including SP, TAB and LF, (used to separate fields in a record).
+
+Currently list of fields is
+ * <repository path>  - path to repository GIT_DIR, relative to $projectroot
+ * <repository owner> - displayed as repository owner, preferably full name,
+                        or email, or both
+
+You can additionally use $projects_list file to limit which repositories
+are visible, and together with $strict_export to limit access to
+repositories (see "Gitweb repositories" section in gitweb/INSTALL).
+
+
 Per-repository gitweb configuration
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -225,8 +259,8 @@
  * README.html
    A .html file (HTML fragment) which is included on the gitweb project
    summary page inside <div> block element. You can use it for longer
-   description of a project, to provide links for example to projects
-   homepage, etc.
+   description of a project, to provide links (for example to project's
+   homepage), etc.
  * description (or gitweb.description)
    Short (shortened by default to 25 characters in the projects list page)
    single line description of a project (of a repository). Plain text file;
@@ -243,7 +277,8 @@
  * gitweb.owner
    You can use the gitweb.owner repository configuration variable to set
    repository's owner. It is displayed in the project list and summary
-   page. If it's not set, filesystem directory's owner is used.
+   page. If it's not set, filesystem directory's owner is used
+   (via GECOS field / real name field from getpwiud(3)).
  * various gitweb.* config variables (in config)
    Read description of %feature hash for detailed list, and some
    descriptions.
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index f88ce35..804670c 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -27,6 +27,13 @@
 our $my_url = $cgi->url();
 our $my_uri = $cgi->url(-absolute => 1);
 
+# if we're called with PATH_INFO, we have to strip that
+# from the URL to find our real URL
+if (my $path_info = $ENV{"PATH_INFO"}) {
+	$my_url =~ s,\Q$path_info\E$,,;
+	$my_uri =~ s,\Q$path_info\E$,,;
+}
+
 # core git executable to use
 # this can just be "git" if your webserver has a sensible PATH
 our $GIT = "++GIT_BINDIR++/git";
@@ -225,6 +232,7 @@
 	# $feature{'grep'}{'override'} = 1;
 	# and in project config gitweb.grep = 0|1;
 	'grep' => {
+		'sub' => \&feature_grep,
 		'override' => 0,
 		'default' => [1]},
 
@@ -386,7 +394,7 @@
 our $action = $cgi->param('a');
 if (defined $action) {
 	if ($action =~ m/[^0-9a-zA-Z\.\-_]/) {
-		die_error(undef, "Invalid action parameter");
+		die_error(400, "Invalid action parameter");
 	}
 }
 
@@ -399,21 +407,21 @@
 	    ($export_ok && !(-e "$projectroot/$project/$export_ok")) ||
 	    ($strict_export && !project_in_list($project))) {
 		undef $project;
-		die_error(undef, "No such project");
+		die_error(404, "No such project");
 	}
 }
 
 our $file_name = $cgi->param('f');
 if (defined $file_name) {
 	if (!validate_pathname($file_name)) {
-		die_error(undef, "Invalid file parameter");
+		die_error(400, "Invalid file parameter");
 	}
 }
 
 our $file_parent = $cgi->param('fp');
 if (defined $file_parent) {
 	if (!validate_pathname($file_parent)) {
-		die_error(undef, "Invalid file parent parameter");
+		die_error(400, "Invalid file parent parameter");
 	}
 }
 
@@ -421,21 +429,21 @@
 our $hash = $cgi->param('h');
 if (defined $hash) {
 	if (!validate_refname($hash)) {
-		die_error(undef, "Invalid hash parameter");
+		die_error(400, "Invalid hash parameter");
 	}
 }
 
 our $hash_parent = $cgi->param('hp');
 if (defined $hash_parent) {
 	if (!validate_refname($hash_parent)) {
-		die_error(undef, "Invalid hash parent parameter");
+		die_error(400, "Invalid hash parent parameter");
 	}
 }
 
 our $hash_base = $cgi->param('hb');
 if (defined $hash_base) {
 	if (!validate_refname($hash_base)) {
-		die_error(undef, "Invalid hash base parameter");
+		die_error(400, "Invalid hash base parameter");
 	}
 }
 
@@ -447,10 +455,10 @@
 if (defined @extra_options) {
 	foreach my $opt (@extra_options) {
 		if (not exists $allowed_options{$opt}) {
-			die_error(undef, "Invalid option parameter");
+			die_error(400, "Invalid option parameter");
 		}
 		if (not grep(/^$action$/, @{$allowed_options{$opt}})) {
-			die_error(undef, "Invalid option parameter for this action");
+			die_error(400, "Invalid option parameter for this action");
 		}
 	}
 }
@@ -458,7 +466,7 @@
 our $hash_parent_base = $cgi->param('hpb');
 if (defined $hash_parent_base) {
 	if (!validate_refname($hash_parent_base)) {
-		die_error(undef, "Invalid hash parent base parameter");
+		die_error(400, "Invalid hash parent base parameter");
 	}
 }
 
@@ -466,14 +474,14 @@
 our $page = $cgi->param('pg');
 if (defined $page) {
 	if ($page =~ m/[^0-9]/) {
-		die_error(undef, "Invalid page parameter");
+		die_error(400, "Invalid page parameter");
 	}
 }
 
 our $searchtype = $cgi->param('st');
 if (defined $searchtype) {
 	if ($searchtype =~ m/[^a-z]/) {
-		die_error(undef, "Invalid searchtype parameter");
+		die_error(400, "Invalid searchtype parameter");
 	}
 }
 
@@ -483,7 +491,7 @@
 our $search_regexp;
 if (defined $searchtext) {
 	if (length($searchtext) < 2) {
-		die_error(undef, "At least two characters are required for search parameter");
+		die_error(403, "At least two characters are required for search parameter");
 	}
 	$search_regexp = $search_use_regexp ? $searchtext : quotemeta $searchtext;
 }
@@ -539,7 +547,7 @@
 
 # dispatch
 my %actions = (
-	"blame" => \&git_blame2,
+	"blame" => \&git_blame,
 	"blobdiff" => \&git_blobdiff,
 	"blobdiff_plain" => \&git_blobdiff_plain,
 	"blob" => \&git_blob,
@@ -580,11 +588,11 @@
 	}
 }
 if (!defined($actions{$action})) {
-	die_error(undef, "Unknown action");
+	die_error(400, "Unknown action");
 }
 if ($action !~ m/^(opml|project_list|project_index)$/ &&
     !$project) {
-	die_error(undef, "Project needed");
+	die_error(400, "Project needed");
 }
 $actions{$action}->();
 exit;
@@ -1665,7 +1673,7 @@
 	$path =~ s,/+$,,;
 
 	open my $fd, "-|", git_cmd(), "ls-tree", $base, "--", $path
-		or die_error(undef, "Open git-ls-tree failed");
+		or die_error(500, "Open git-ls-tree failed");
 	my $line = <$fd>;
 	close $fd or return undef;
 
@@ -2092,7 +2100,7 @@
 			last;
 		}
 	}
-	if ($co{'title'} eq "") {
+	if (! defined $co{'title'} || $co{'title'} eq "") {
 		$co{'title'} = $co{'title_short'} = '(no commit message)';
 	}
 	# remove added spaces
@@ -2127,7 +2135,7 @@
 		"--max-count=1",
 		$commit_id,
 		"--",
-		or die_error(undef, "Open git-rev-list failed");
+		or die_error(500, "Open git-rev-list failed");
 	%co = parse_commit_text(<$fd>, 1);
 	close $fd;
 
@@ -2152,7 +2160,7 @@
 		$commit_id,
 		"--",
 		($filename ? ($filename) : ())
-		or die_error(undef, "Open git-rev-list failed");
+		or die_error(500, "Open git-rev-list failed");
 	while (my $line = <$fd>) {
 		my %co = parse_commit_text($line);
 		push @cos, \%co;
@@ -2672,11 +2680,26 @@
 	      "</html>";
 }
 
+# die_error(<http_status_code>, <error_message>)
+# Example: die_error(404, 'Hash not found')
+# By convention, use the following status codes (as defined in RFC 2616):
+# 400: Invalid or missing CGI parameters, or
+#      requested object exists but has wrong type.
+# 403: Requested feature (like "pickaxe" or "snapshot") not enabled on
+#      this server or project.
+# 404: Requested object/revision/project doesn't exist.
+# 500: The server isn't configured properly, or
+#      an internal error occurred (e.g. failed assertions caused by bugs), or
+#      an unknown error occurred (e.g. the git binary died unexpectedly).
 sub die_error {
-	my $status = shift || "403 Forbidden";
-	my $error = shift || "Malformed query, file missing or permission denied";
+	my $status = shift || 500;
+	my $error = shift || "Internal server error";
 
-	git_header_html($status);
+	my %http_responses = (400 => '400 Bad Request',
+			      403 => '403 Forbidden',
+			      404 => '404 Not Found',
+			      500 => '500 Internal Server Error');
+	git_header_html($http_responses{$status});
 	print <<EOF;
 <div class="page_body">
 <br /><br />
@@ -3520,21 +3543,24 @@
 
 # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
 
-sub git_project_list_body {
-	my ($projlist, $order, $from, $to, $extra, $no_header) = @_;
-
-	my ($check_forks) = gitweb_check_feature('forks');
-
+# fills project list info (age, description, owner, forks) for each
+# project in the list, removing invalid projects from returned list
+# NOTE: modifies $projlist, but does not remove entries from it
+sub fill_project_list_info {
+	my ($projlist, $check_forks) = @_;
 	my @projects;
+
+ PROJECT:
 	foreach my $pr (@$projlist) {
-		my (@aa) = git_get_last_activity($pr->{'path'});
-		unless (@aa) {
-			next;
+		my (@activity) = git_get_last_activity($pr->{'path'});
+		unless (@activity) {
+			next PROJECT;
 		}
-		($pr->{'age'}, $pr->{'age_string'}) = @aa;
+		($pr->{'age'}, $pr->{'age_string'}) = @activity;
 		if (!defined $pr->{'descr'}) {
 			my $descr = git_get_project_description($pr->{'path'}) || "";
-			$pr->{'descr_long'} = to_utf8($descr);
+			$descr = to_utf8($descr);
+			$pr->{'descr_long'} = $descr;
 			$pr->{'descr'} = chop_str($descr, $projects_list_description_width, 5);
 		}
 		if (!defined $pr->{'owner'}) {
@@ -3546,14 +3572,52 @@
 			    ($pname !~ /\/$/) &&
 			    (-d "$projectroot/$pname")) {
 				$pr->{'forks'} = "-d $projectroot/$pname";
-			}
-			else {
+			}	else {
 				$pr->{'forks'} = 0;
 			}
 		}
 		push @projects, $pr;
 	}
 
+	return @projects;
+}
+
+# print 'sort by' <th> element, either sorting by $key if $name eq $order
+# (changing $list), or generating 'sort by $name' replay link otherwise
+sub print_sort_th {
+	my ($str_sort, $name, $order, $key, $header, $list) = @_;
+	$key    ||= $name;
+	$header ||= ucfirst($name);
+
+	if ($order eq $name) {
+		if ($str_sort) {
+			@$list = sort {$a->{$key} cmp $b->{$key}} @$list;
+		} else {
+			@$list = sort {$a->{$key} <=> $b->{$key}} @$list;
+		}
+		print "<th>$header</th>\n";
+	} else {
+		print "<th>" .
+		      $cgi->a({-href => href(-replay=>1, order=>$name),
+		               -class => "header"}, $header) .
+		      "</th>\n";
+	}
+}
+
+sub print_sort_th_str {
+	print_sort_th(1, @_);
+}
+
+sub print_sort_th_num {
+	print_sort_th(0, @_);
+}
+
+sub git_project_list_body {
+	my ($projlist, $order, $from, $to, $extra, $no_header) = @_;
+
+	my ($check_forks) = gitweb_check_feature('forks');
+	my @projects = fill_project_list_info($projlist, $check_forks);
+
 	$order ||= $default_projects_order;
 	$from = 0 unless defined $from;
 	$to = $#projects if (!defined $to || $#projects < $to);
@@ -3564,43 +3628,15 @@
 		if ($check_forks) {
 			print "<th></th>\n";
 		}
-		if ($order eq "project") {
-			@projects = sort {$a->{'path'} cmp $b->{'path'}} @projects;
-			print "<th>Project</th>\n";
-		} else {
-			print "<th>" .
-			      $cgi->a({-href => href(project=>undef, order=>'project'),
-			               -class => "header"}, "Project") .
-			      "</th>\n";
-		}
-		if ($order eq "descr") {
-			@projects = sort {$a->{'descr'} cmp $b->{'descr'}} @projects;
-			print "<th>Description</th>\n";
-		} else {
-			print "<th>" .
-			      $cgi->a({-href => href(project=>undef, order=>'descr'),
-			               -class => "header"}, "Description") .
-			      "</th>\n";
-		}
-		if ($order eq "owner") {
-			@projects = sort {$a->{'owner'} cmp $b->{'owner'}} @projects;
-			print "<th>Owner</th>\n";
-		} else {
-			print "<th>" .
-			      $cgi->a({-href => href(project=>undef, order=>'owner'),
-			               -class => "header"}, "Owner") .
-			      "</th>\n";
-		}
-		if ($order eq "age") {
-			@projects = sort {$a->{'age'} <=> $b->{'age'}} @projects;
-			print "<th>Last Change</th>\n";
-		} else {
-			print "<th>" .
-			      $cgi->a({-href => href(project=>undef, order=>'age'),
-			               -class => "header"}, "Last Change") .
-			      "</th>\n";
-		}
-		print "<th></th>\n" .
+		print_sort_th_str('project', $order, 'path',
+		                  'Project', \@projects);
+		print_sort_th_str('descr', $order, 'descr_long',
+		                  'Description', \@projects);
+		print_sort_th_str('owner', $order, 'owner',
+		                  'Owner', \@projects);
+		print_sort_th_num('age', $order, 'age',
+		                  'Last Change', \@projects);
+		print "<th></th>\n" . # for links
 		      "</tr>\n";
 	}
 	my $alternate = 1;
@@ -3924,12 +3960,12 @@
 sub git_project_list {
 	my $order = $cgi->param('o');
 	if (defined $order && $order !~ m/none|project|descr|owner|age/) {
-		die_error(undef, "Unknown order parameter");
+		die_error(400, "Unknown order parameter");
 	}
 
 	my @list = git_get_projects_list();
 	if (!@list) {
-		die_error(undef, "No projects found");
+		die_error(404, "No projects found");
 	}
 
 	git_header_html();
@@ -3947,12 +3983,12 @@
 sub git_forks {
 	my $order = $cgi->param('o');
 	if (defined $order && $order !~ m/none|project|descr|owner|age/) {
-		die_error(undef, "Unknown order parameter");
+		die_error(400, "Unknown order parameter");
 	}
 
 	my @list = git_get_projects_list($project);
 	if (!@list) {
-		die_error(undef, "No forks found");
+		die_error(404, "No forks found");
 	}
 
 	git_header_html();
@@ -4081,7 +4117,7 @@
 	my %tag = parse_tag($hash);
 
 	if (! %tag) {
-		die_error(undef, "Unknown tag object");
+		die_error(404, "Unknown tag object");
 	}
 
 	git_print_header_div('commit', esc_html($tag{'name'}), $hash);
@@ -4113,30 +4149,29 @@
 	git_footer_html();
 }
 
-sub git_blame2 {
+sub git_blame {
 	my $fd;
 	my $ftype;
 
-	my ($have_blame) = gitweb_check_feature('blame');
-	if (!$have_blame) {
-		die_error('403 Permission denied', "Permission denied");
-	}
-	die_error('404 Not Found', "File name not defined") if (!$file_name);
+	gitweb_check_feature('blame')
+	    or die_error(403, "Blame view not allowed");
+
+	die_error(400, "No file name given") unless $file_name;
 	$hash_base ||= git_get_head_hash($project);
-	die_error(undef, "Couldn't find base commit") unless ($hash_base);
+	die_error(404, "Couldn't find base commit") unless ($hash_base);
 	my %co = parse_commit($hash_base)
-		or die_error(undef, "Reading commit failed");
+		or die_error(404, "Commit not found");
 	if (!defined $hash) {
 		$hash = git_get_hash_by_path($hash_base, $file_name, "blob")
-			or die_error(undef, "Error looking up file");
+			or die_error(404, "Error looking up file");
 	}
 	$ftype = git_get_type($hash);
 	if ($ftype !~ "blob") {
-		die_error('400 Bad Request', "Object is not a blob");
+		die_error(400, "Object is not a blob");
 	}
 	open ($fd, "-|", git_cmd(), "blame", '-p', '--',
 	      $file_name, $hash_base)
-		or die_error(undef, "Open git-blame failed");
+		or die_error(500, "Open git-blame failed");
 	git_header_html();
 	my $formats_nav =
 		$cgi->a({-href => href(action=>"blob", -replay=>1)},
@@ -4198,7 +4233,7 @@
 			print "</td>\n";
 		}
 		open (my $dd, "-|", git_cmd(), "rev-parse", "$full_rev^")
-			or die_error(undef, "Open git-rev-parse failed");
+			or die_error(500, "Open git-rev-parse failed");
 		my $parent_commit = <$dd>;
 		close $dd;
 		chomp($parent_commit);
@@ -4221,103 +4256,6 @@
 	git_footer_html();
 }
 
-sub git_blame {
-	my $fd;
-
-	my ($have_blame) = gitweb_check_feature('blame');
-	if (!$have_blame) {
-		die_error('403 Permission denied', "Permission denied");
-	}
-	die_error('404 Not Found', "File name not defined") if (!$file_name);
-	$hash_base ||= git_get_head_hash($project);
-	die_error(undef, "Couldn't find base commit") unless ($hash_base);
-	my %co = parse_commit($hash_base)
-		or die_error(undef, "Reading commit failed");
-	if (!defined $hash) {
-		$hash = git_get_hash_by_path($hash_base, $file_name, "blob")
-			or die_error(undef, "Error lookup file");
-	}
-	open ($fd, "-|", git_cmd(), "annotate", '-l', '-t', '-r', $file_name, $hash_base)
-		or die_error(undef, "Open git-annotate failed");
-	git_header_html();
-	my $formats_nav =
-		$cgi->a({-href => href(action=>"blob", hash=>$hash, hash_base=>$hash_base, file_name=>$file_name)},
-		        "blob") .
-		" | " .
-		$cgi->a({-href => href(action=>"history", hash=>$hash, hash_base=>$hash_base, file_name=>$file_name)},
-			"history") .
-		" | " .
-		$cgi->a({-href => href(action=>"blame", file_name=>$file_name)},
-		        "HEAD");
-	git_print_page_nav('','', $hash_base,$co{'tree'},$hash_base, $formats_nav);
-	git_print_header_div('commit', esc_html($co{'title'}), $hash_base);
-	git_print_page_path($file_name, 'blob', $hash_base);
-	print "<div class=\"page_body\">\n";
-	print <<HTML;
-<table class="blame">
-  <tr>
-    <th>Commit</th>
-    <th>Age</th>
-    <th>Author</th>
-    <th>Line</th>
-    <th>Data</th>
-  </tr>
-HTML
-	my @line_class = (qw(light dark));
-	my $line_class_len = scalar (@line_class);
-	my $line_class_num = $#line_class;
-	while (my $line = <$fd>) {
-		my $long_rev;
-		my $short_rev;
-		my $author;
-		my $time;
-		my $lineno;
-		my $data;
-		my $age;
-		my $age_str;
-		my $age_class;
-
-		chomp $line;
-		$line_class_num = ($line_class_num + 1) % $line_class_len;
-
-		if ($line =~ m/^([0-9a-fA-F]{40})\t\(\s*([^\t]+)\t(\d+) [+-]\d\d\d\d\t(\d+)\)(.*)$/) {
-			$long_rev = $1;
-			$author   = $2;
-			$time     = $3;
-			$lineno   = $4;
-			$data     = $5;
-		} else {
-			print qq(  <tr><td colspan="5" class="error">Unable to parse: $line</td></tr>\n);
-			next;
-		}
-		$short_rev  = substr ($long_rev, 0, 8);
-		$age        = time () - $time;
-		$age_str    = age_string ($age);
-		$age_str    =~ s/ /&nbsp;/g;
-		$age_class  = age_class($age);
-		$author     = esc_html ($author);
-		$author     =~ s/ /&nbsp;/g;
-
-		$data = untabify($data);
-		$data = esc_html ($data);
-
-		print <<HTML;
-  <tr class="$line_class[$line_class_num]">
-    <td class="sha1"><a href="${\href (action=>"commit", hash=>$long_rev)}" class="text">$short_rev..</a></td>
-    <td class="$age_class">$age_str</td>
-    <td>$author</td>
-    <td class="linenr"><a id="$lineno" href="#$lineno" class="linenr">$lineno</a></td>
-    <td class="pre">$data</td>
-  </tr>
-HTML
-	} # while (my $line = <$fd>)
-	print "</table>\n\n";
-	close $fd
-		or print "Reading blob failed.\n";
-	print "</div>";
-	git_footer_html();
-}
-
 sub git_tags {
 	my $head = git_get_head_hash($project);
 	git_header_html();
@@ -4352,9 +4290,9 @@
 		if (defined $file_name) {
 			my $base = $hash_base || git_get_head_hash($project);
 			$hash = git_get_hash_by_path($base, $file_name, "blob")
-				or die_error(undef, "Error lookup file");
+				or die_error(404, "Cannot find file");
 		} else {
-			die_error(undef, "No file name defined");
+			die_error(400, "No file name defined");
 		}
 	} elsif ($hash =~ m/^[0-9a-fA-F]{40}$/) {
 		# blobs defined by non-textual hash id's can be cached
@@ -4362,7 +4300,7 @@
 	}
 
 	open my $fd, "-|", git_cmd(), "cat-file", "blob", $hash
-		or die_error(undef, "Open git-cat-file blob '$hash' failed");
+		or die_error(500, "Open git-cat-file blob '$hash' failed");
 
 	# content-type (can include charset)
 	$type = blob_contenttype($fd, $file_name, $type);
@@ -4394,9 +4332,9 @@
 		if (defined $file_name) {
 			my $base = $hash_base || git_get_head_hash($project);
 			$hash = git_get_hash_by_path($base, $file_name, "blob")
-				or die_error(undef, "Error lookup file");
+				or die_error(404, "Cannot find file");
 		} else {
-			die_error(undef, "No file name defined");
+			die_error(400, "No file name defined");
 		}
 	} elsif ($hash =~ m/^[0-9a-fA-F]{40}$/) {
 		# blobs defined by non-textual hash id's can be cached
@@ -4405,7 +4343,7 @@
 
 	my ($have_blame) = gitweb_check_feature('blame');
 	open my $fd, "-|", git_cmd(), "cat-file", "blob", $hash
-		or die_error(undef, "Couldn't cat $file_name, $hash");
+		or die_error(500, "Couldn't cat $file_name, $hash");
 	my $mimetype = blob_mimetype($fd, $file_name);
 	if ($mimetype !~ m!^(?:text/|image/(?:gif|png|jpeg)$)! && -B $fd) {
 		close $fd;
@@ -4484,11 +4422,12 @@
 			$hash = $hash_base;
 		}
 	}
+	die_error(404, "No such tree") unless defined($hash);
 	$/ = "\0";
 	open my $fd, "-|", git_cmd(), "ls-tree", '-z', $hash
-		or die_error(undef, "Open git-ls-tree failed");
+		or die_error(500, "Open git-ls-tree failed");
 	my @entries = map { chomp; $_ } <$fd>;
-	close $fd or die_error(undef, "Reading tree failed");
+	close $fd or die_error(404, "Reading tree failed");
 	$/ = "\n";
 
 	my $refs = git_get_references();
@@ -4524,8 +4463,8 @@
 		if ($basedir ne '' && substr($basedir, -1) ne '/') {
 			$basedir .= '/';
 		}
+		git_print_page_path($file_name, 'tree', $hash_base);
 	}
-	git_print_page_path($file_name, 'tree', $hash_base);
 	print "<div class=\"page_body\">\n";
 	print "<table class=\"tree\">\n";
 	my $alternate = 1;
@@ -4578,16 +4517,16 @@
 
 	my $format = $cgi->param('sf');
 	if (!@supported_fmts) {
-		die_error('403 Permission denied', "Permission denied");
+		die_error(403, "Snapshots not allowed");
 	}
 	# default to first supported snapshot format
 	$format ||= $supported_fmts[0];
 	if ($format !~ m/^[a-z0-9]+$/) {
-		die_error(undef, "Invalid snapshot format parameter");
+		die_error(400, "Invalid snapshot format parameter");
 	} elsif (!exists($known_snapshot_formats{$format})) {
-		die_error(undef, "Unknown snapshot format");
+		die_error(400, "Unknown snapshot format");
 	} elsif (!grep($_ eq $format, @supported_fmts)) {
-		die_error(undef, "Unsupported snapshot format");
+		die_error(403, "Unsupported snapshot format");
 	}
 
 	if (!defined $hash) {
@@ -4615,7 +4554,7 @@
 		-status => '200 OK');
 
 	open my $fd, "-|", $cmd
-		or die_error(undef, "Execute git-archive failed");
+		or die_error(500, "Execute git-archive failed");
 	binmode STDOUT, ':raw';
 	print <$fd>;
 	binmode STDOUT, ':utf8'; # as set at the beginning of gitweb.cgi
@@ -4683,10 +4622,8 @@
 
 sub git_commit {
 	$hash ||= $hash_base || "HEAD";
-	my %co = parse_commit($hash);
-	if (!%co) {
-		die_error(undef, "Unknown commit object");
-	}
+	my %co = parse_commit($hash)
+	    or die_error(404, "Unknown commit object");
 	my %ad = parse_date($co{'author_epoch'}, $co{'author_tz'});
 	my %cd = parse_date($co{'committer_epoch'}, $co{'committer_tz'});
 
@@ -4726,9 +4663,9 @@
 		@diff_opts,
 		(@$parents <= 1 ? $parent : '-c'),
 		$hash, "--"
-		or die_error(undef, "Open git-diff-tree failed");
+		or die_error(500, "Open git-diff-tree failed");
 	@difftree = map { chomp; $_ } <$fd>;
-	close $fd or die_error(undef, "Reading git-diff-tree failed");
+	close $fd or die_error(404, "Reading git-diff-tree failed");
 
 	# non-textual hash id's can be cached
 	my $expires;
@@ -4821,33 +4758,33 @@
 
 		open my $fd, "-|", quote_command(
 			git_cmd(), 'cat-file', '-t', $object_id) . ' 2> /dev/null'
-			or die_error('404 Not Found', "Object does not exist");
+			or die_error(404, "Object does not exist");
 		$type = <$fd>;
 		chomp $type;
 		close $fd
-			or die_error('404 Not Found', "Object does not exist");
+			or die_error(404, "Object does not exist");
 
 	# - hash_base and file_name
 	} elsif ($hash_base && defined $file_name) {
 		$file_name =~ s,/+$,,;
 
 		system(git_cmd(), "cat-file", '-e', $hash_base) == 0
-			or die_error('404 Not Found', "Base object does not exist");
+			or die_error(404, "Base object does not exist");
 
 		# here errors should not hapen
 		open my $fd, "-|", git_cmd(), "ls-tree", $hash_base, "--", $file_name
-			or die_error(undef, "Open git-ls-tree failed");
+			or die_error(500, "Open git-ls-tree failed");
 		my $line = <$fd>;
 		close $fd;
 
 		#'100644 blob 0fa3f3a66fb6a137f6ec2c19351ed4d807070ffa	panic.c'
 		unless ($line && $line =~ m/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t/) {
-			die_error('404 Not Found', "File or directory for given base does not exist");
+			die_error(404, "File or directory for given base does not exist");
 		}
 		$type = $2;
 		$hash = $3;
 	} else {
-		die_error('404 Not Found', "Not enough information to find object");
+		die_error(400, "Not enough information to find object");
 	}
 
 	print $cgi->redirect(-uri => href(action=>$type, -full=>1,
@@ -4872,12 +4809,12 @@
 			open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts,
 				$hash_parent_base, $hash_base,
 				"--", (defined $file_parent ? $file_parent : ()), $file_name
-				or die_error(undef, "Open git-diff-tree failed");
+				or die_error(500, "Open git-diff-tree failed");
 			@difftree = map { chomp; $_ } <$fd>;
 			close $fd
-				or die_error(undef, "Reading git-diff-tree failed");
+				or die_error(404, "Reading git-diff-tree failed");
 			@difftree
-				or die_error('404 Not Found', "Blob diff not found");
+				or die_error(404, "Blob diff not found");
 
 		} elsif (defined $hash &&
 		         $hash =~ /[0-9a-fA-F]{40}/) {
@@ -4886,23 +4823,23 @@
 			# read filtered raw output
 			open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts,
 				$hash_parent_base, $hash_base, "--"
-				or die_error(undef, "Open git-diff-tree failed");
+				or die_error(500, "Open git-diff-tree failed");
 			@difftree =
 				# ':100644 100644 03b21826... 3b93d5e7... M	ls-files.c'
 				# $hash == to_id
 				grep { /^:[0-7]{6} [0-7]{6} [0-9a-fA-F]{40} $hash/ }
 				map { chomp; $_ } <$fd>;
 			close $fd
-				or die_error(undef, "Reading git-diff-tree failed");
+				or die_error(404, "Reading git-diff-tree failed");
 			@difftree
-				or die_error('404 Not Found', "Blob diff not found");
+				or die_error(404, "Blob diff not found");
 
 		} else {
-			die_error('404 Not Found', "Missing one of the blob diff parameters");
+			die_error(400, "Missing one of the blob diff parameters");
 		}
 
 		if (@difftree > 1) {
-			die_error('404 Not Found', "Ambiguous blob diff specification");
+			die_error(400, "Ambiguous blob diff specification");
 		}
 
 		%diffinfo = parse_difftree_raw_line($difftree[0]);
@@ -4923,7 +4860,7 @@
 			'-p', ($format eq 'html' ? "--full-index" : ()),
 			$hash_parent_base, $hash_base,
 			"--", (defined $file_parent ? $file_parent : ()), $file_name
-			or die_error(undef, "Open git-diff-tree failed");
+			or die_error(500, "Open git-diff-tree failed");
 	}
 
 	# old/legacy style URI -- not generated anymore since 1.4.3.
@@ -4960,7 +4897,7 @@
 		print "X-Git-Url: " . $cgi->self_url() . "\n\n";
 
 	} else {
-		die_error(undef, "Unknown blobdiff format");
+		die_error(400, "Unknown blobdiff format");
 	}
 
 	# patch
@@ -4995,10 +4932,8 @@
 sub git_commitdiff {
 	my $format = shift || 'html';
 	$hash ||= $hash_base || "HEAD";
-	my %co = parse_commit($hash);
-	if (!%co) {
-		die_error(undef, "Unknown commit object");
-	}
+	my %co = parse_commit($hash)
+	    or die_error(404, "Unknown commit object");
 
 	# choose format for commitdiff for merge
 	if (! defined $hash_parent && @{$co{'parents'}} > 1) {
@@ -5080,7 +5015,7 @@
 		open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts,
 			"--no-commit-id", "--patch-with-raw", "--full-index",
 			$hash_parent_param, $hash, "--"
-			or die_error(undef, "Open git-diff-tree failed");
+			or die_error(500, "Open git-diff-tree failed");
 
 		while (my $line = <$fd>) {
 			chomp $line;
@@ -5092,10 +5027,10 @@
 	} elsif ($format eq 'plain') {
 		open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts,
 			'-p', $hash_parent_param, $hash, "--"
-			or die_error(undef, "Open git-diff-tree failed");
+			or die_error(500, "Open git-diff-tree failed");
 
 	} else {
-		die_error(undef, "Unknown commitdiff format");
+		die_error(400, "Unknown commitdiff format");
 	}
 
 	# non-textual hash id's can be cached
@@ -5178,19 +5113,15 @@
 		$page = 0;
 	}
 	my $ftype;
-	my %co = parse_commit($hash_base);
-	if (!%co) {
-		die_error(undef, "Unknown commit object");
-	}
+	my %co = parse_commit($hash_base)
+	    or die_error(404, "Unknown commit object");
 
 	my $refs = git_get_references();
 	my $limit = sprintf("--max-count=%i", (100 * ($page+1)));
 
 	my @commitlist = parse_commits($hash_base, 101, (100 * $page),
-	                               $file_name, "--full-history");
-	if (!@commitlist) {
-		die_error('404 Not Found', "No such file or directory on given branch");
-	}
+	                               $file_name, "--full-history")
+	    or die_error(404, "No such file or directory on given branch");
 
 	if (!defined $hash && defined $file_name) {
 		# some commits could have deleted file in question,
@@ -5204,7 +5135,7 @@
 		$ftype = git_get_type($hash);
 	}
 	if (!defined $ftype) {
-		die_error(undef, "Unknown type of object");
+		die_error(500, "Unknown type of object");
 	}
 
 	my $paging_nav = '';
@@ -5242,19 +5173,16 @@
 }
 
 sub git_search {
-	my ($have_search) = gitweb_check_feature('search');
-	if (!$have_search) {
-		die_error('403 Permission denied', "Permission denied");
-	}
+	gitweb_check_feature('search') or die_error(403, "Search is disabled");
 	if (!defined $searchtext) {
-		die_error(undef, "Text field empty");
+		die_error(400, "Text field is empty");
 	}
 	if (!defined $hash) {
 		$hash = git_get_head_hash($project);
 	}
 	my %co = parse_commit($hash);
 	if (!%co) {
-		die_error(undef, "Unknown commit object");
+		die_error(404, "Unknown commit object");
 	}
 	if (!defined $page) {
 		$page = 0;
@@ -5264,16 +5192,12 @@
 	if ($searchtype eq 'pickaxe') {
 		# pickaxe may take all resources of your box and run for several minutes
 		# with every query - so decide by yourself how public you make this feature
-		my ($have_pickaxe) = gitweb_check_feature('pickaxe');
-		if (!$have_pickaxe) {
-			die_error('403 Permission denied', "Permission denied");
-		}
+		gitweb_check_feature('pickaxe')
+		    or die_error(403, "Pickaxe is disabled");
 	}
 	if ($searchtype eq 'grep') {
-		my ($have_grep) = gitweb_check_feature('grep');
-		if (!$have_grep) {
-			die_error('403 Permission denied', "Permission denied");
-		}
+		gitweb_check_feature('grep')
+		    or die_error(403, "Grep is disabled");
 	}
 
 	git_header_html();
@@ -5547,7 +5471,7 @@
 	# Atom: http://www.atomenabled.org/developers/syndication/
 	# RSS:  http://www.notestips.com/80256B3A007F2692/1/NAMO5P9UPQ
 	if ($format ne 'rss' && $format ne 'atom') {
-		die_error(undef, "Unknown web feed format");
+		die_error(400, "Unknown web feed format");
 	}
 
 	# log/feed of current (HEAD) branch, log of given branch, history of file/directory
diff --git a/grep.c b/grep.c
index f67d671..13c18ff 100644
--- a/grep.c
+++ b/grep.c
@@ -2,6 +2,19 @@
 #include "grep.h"
 #include "xdiff-interface.h"
 
+void append_header_grep_pattern(struct grep_opt *opt, enum grep_header_field field, const char *pat)
+{
+	struct grep_pat *p = xcalloc(1, sizeof(*p));
+	p->pattern = pat;
+	p->origin = "header";
+	p->no = 0;
+	p->token = GREP_PATTERN_HEAD;
+	p->field = field;
+	*opt->pattern_tail = p;
+	opt->pattern_tail = &p->next;
+	p->next = NULL;
+}
+
 void append_grep_pattern(struct grep_opt *opt, const char *pat,
 			 const char *origin, int no, enum grep_pat_token t)
 {
@@ -247,16 +260,53 @@
 	}
 }
 
+static int strip_timestamp(char *bol, char **eol_p)
+{
+	char *eol = *eol_p;
+	int ch;
+
+	while (bol < --eol) {
+		if (*eol != '>')
+			continue;
+		*eol_p = ++eol;
+		ch = *eol;
+		*eol = '\0';
+		return ch;
+	}
+	return 0;
+}
+
+static struct {
+	const char *field;
+	size_t len;
+} header_field[] = {
+	{ "author ", 7 },
+	{ "committer ", 10 },
+};
+
 static int match_one_pattern(struct grep_opt *opt, struct grep_pat *p, char *bol, char *eol, enum grep_context ctx)
 {
 	int hit = 0;
 	int at_true_bol = 1;
+	int saved_ch = 0;
 	regmatch_t pmatch[10];
 
 	if ((p->token != GREP_PATTERN) &&
 	    ((p->token == GREP_PATTERN_HEAD) != (ctx == GREP_CONTEXT_HEAD)))
 		return 0;
 
+	if (p->token == GREP_PATTERN_HEAD) {
+		const char *field;
+		size_t len;
+		assert(p->field < ARRAY_SIZE(header_field));
+		field = header_field[p->field].field;
+		len = header_field[p->field].len;
+		if (strncmp(bol, field, len))
+			return 0;
+		bol += len;
+		saved_ch = strip_timestamp(bol, &eol);
+	}
+
  again:
 	if (!opt->fixed) {
 		regex_t *exp = &p->regexp;
@@ -298,6 +348,8 @@
 			goto again;
 		}
 	}
+	if (p->token == GREP_PATTERN_HEAD && saved_ch)
+		*eol = saved_ch;
 	return hit;
 }
 
@@ -455,7 +507,7 @@
 				if (from <= last_shown)
 					from = last_shown + 1;
 				if (last_shown && from != last_shown + 1)
-					printf(hunk_mark);
+					fputs(hunk_mark, stdout);
 				while (from < lno) {
 					pcl = &prev[lno-from-1];
 					show_line(opt, pcl->bol, pcl->eol,
@@ -465,7 +517,7 @@
 				last_shown = lno-1;
 			}
 			if (last_shown && lno != last_shown + 1)
-				printf(hunk_mark);
+				fputs(hunk_mark, stdout);
 			if (!opt->count)
 				show_line(opt, bol, eol, name, lno, ':');
 			last_shown = last_hit = lno;
@@ -476,7 +528,7 @@
 			 * we need to show this line.
 			 */
 			if (last_shown && lno != last_shown + 1)
-				printf(hunk_mark);
+				fputs(hunk_mark, stdout);
 			show_line(opt, bol, eol, name, lno, '-');
 			last_shown = lno;
 		}
diff --git a/grep.h b/grep.h
index d252dd2..59b3f87 100644
--- a/grep.h
+++ b/grep.h
@@ -17,12 +17,18 @@
 	GREP_CONTEXT_BODY,
 };
 
+enum grep_header_field {
+	GREP_HEADER_AUTHOR = 0,
+	GREP_HEADER_COMMITTER,
+};
+
 struct grep_pat {
 	struct grep_pat *next;
 	const char *origin;
 	int no;
 	enum grep_pat_token token;
 	const char *pattern;
+	enum grep_header_field field;
 	regex_t regexp;
 };
 
@@ -74,6 +80,7 @@
 };
 
 extern void append_grep_pattern(struct grep_opt *opt, const char *pat, const char *origin, int no, enum grep_pat_token t);
+extern void append_header_grep_pattern(struct grep_opt *, enum grep_header_field, const char *);
 extern void compile_grep_patterns(struct grep_opt *opt);
 extern void free_grep_patterns(struct grep_opt *opt);
 extern int grep_buffer(struct grep_opt *opt, const char *name, char *buf, unsigned long size);
diff --git a/hash-object.c b/hash-object.c
index 48d5223..46c06a9 100644
--- a/hash-object.c
+++ b/hash-object.c
@@ -52,7 +52,7 @@
 }
 
 static const char hash_object_usage[] =
-"git-hash-object [ [-t <type>] [-w] [--stdin] <file>... | --stdin-paths < <list-of-paths> ]";
+"git hash-object [ [-t <type>] [-w] [--stdin] <file>... | --stdin-paths < <list-of-paths> ]";
 
 int main(int argc, char **argv)
 {
diff --git a/help.c b/help.c
index 8aff94c..dc0786d 100644
--- a/help.c
+++ b/help.c
@@ -40,7 +40,7 @@
 };
 
 static const char * const builtin_help_usage[] = {
-	"git-help [--all] [--man|--web|--info] [command]",
+	"git help [--all] [--man|--web|--info] [command]",
 	NULL
 };
 
@@ -391,6 +391,32 @@
 	}
 }
 
+static int is_executable(const char *name)
+{
+	struct stat st;
+
+	if (stat(name, &st) || /* stat, not lstat */
+	    !S_ISREG(st.st_mode))
+		return 0;
+
+#ifdef __MINGW32__
+	/* cannot trust the executable bit, peek into the file instead */
+	char buf[3] = { 0 };
+	int n;
+	int fd = open(name, O_RDONLY);
+	st.st_mode &= ~S_IXUSR;
+	if (fd >= 0) {
+		n = read(fd, buf, 2);
+		if (n == 2)
+			/* DOS executables start with "MZ" */
+			if (!strcmp(buf, "#!") || !strcmp(buf, "MZ"))
+				st.st_mode |= S_IXUSR;
+		close(fd);
+	}
+#endif
+	return st.st_mode & S_IXUSR;
+}
+
 static unsigned int list_commands_in_dir(struct cmdnames *cmds,
 					 const char *path)
 {
@@ -399,20 +425,24 @@
 	int prefix_len = strlen(prefix);
 	DIR *dir = opendir(path);
 	struct dirent *de;
+	struct strbuf buf = STRBUF_INIT;
+	int len;
 
-	if (!dir || chdir(path))
+	if (!dir)
 		return 0;
 
+	strbuf_addf(&buf, "%s/", path);
+	len = buf.len;
+
 	while ((de = readdir(dir)) != NULL) {
-		struct stat st;
 		int entlen;
 
 		if (prefixcmp(de->d_name, prefix))
 			continue;
 
-		if (stat(de->d_name, &st) || /* stat, not lstat */
-		    !S_ISREG(st.st_mode) ||
-		    !(st.st_mode & S_IXUSR))
+		strbuf_setlen(&buf, len);
+		strbuf_addstr(&buf, de->d_name);
+		if (!is_executable(buf.buf))
 			continue;
 
 		entlen = strlen(de->d_name) - prefix_len;
@@ -425,6 +455,7 @@
 		add_cmdname(cmds, de->d_name + prefix_len, entlen);
 	}
 	closedir(dir);
+	strbuf_release(&buf);
 
 	return longest;
 }
@@ -447,7 +478,7 @@
 
 	path = paths = xstrdup(env_path);
 	while (1) {
-		if ((colon = strchr(path, ':')))
+		if ((colon = strchr(path, PATH_SEP)))
 			*colon = 0;
 
 		len = list_commands_in_dir(&other_cmds, path);
@@ -524,7 +555,18 @@
 {
 	load_command_list();
 	return is_in_cmdlist(&main_cmds, s) ||
-		is_in_cmdlist(&other_cmds, s);
+		is_in_cmdlist(&other_cmds, s) ||
+		!strcmp(s, "help");
+}
+
+static const char *prepend(const char *prefix, const char *cmd)
+{
+	size_t pre_len = strlen(prefix);
+	size_t cmd_len = strlen(cmd);
+	char *p = xmalloc(pre_len + cmd_len + 1);
+	memcpy(p, prefix, pre_len);
+	strcpy(p + pre_len, cmd);
+	return p;
 }
 
 static const char *cmd_to_page(const char *git_cmd)
@@ -533,14 +575,10 @@
 		return "git";
 	else if (!prefixcmp(git_cmd, "git"))
 		return git_cmd;
-	else {
-		int page_len = strlen(git_cmd) + 4;
-		char *p = xmalloc(page_len + 1);
-		strcpy(p, "git-");
-		strcpy(p + 4, git_cmd);
-		p[page_len] = 0;
-		return p;
-	}
+	else if (is_git_command(git_cmd))
+		return prepend("git-", git_cmd);
+	else
+		return prepend("git", git_cmd);
 }
 
 static void setup_man_path(void)
@@ -604,15 +642,29 @@
 static void get_html_page_path(struct strbuf *page_path, const char *page)
 {
 	struct stat st;
+	const char *html_path = system_path(GIT_HTML_PATH);
 
 	/* Check that we have a git documentation directory. */
-	if (stat(GIT_HTML_PATH "/git.html", &st) || !S_ISREG(st.st_mode))
-		die("'%s': not a documentation directory.", GIT_HTML_PATH);
+	if (stat(mkpath("%s/git.html", html_path), &st)
+	    || !S_ISREG(st.st_mode))
+		die("'%s': not a documentation directory.", html_path);
 
 	strbuf_init(page_path, 0);
-	strbuf_addf(page_path, GIT_HTML_PATH "/%s.html", page);
+	strbuf_addf(page_path, "%s/%s.html", html_path, page);
 }
 
+/*
+ * If open_html is not defined in a platform-specific way (see for
+ * example compat/mingw.h), we use the script web--browse to display
+ * HTML.
+ */
+#ifndef open_html
+void open_html(const char *path)
+{
+	execl_git_cmd("web--browse", "-c", "help.browser", path, NULL);
+}
+#endif
+
 static void show_html_page(const char *git_cmd)
 {
 	const char *page = cmd_to_page(git_cmd);
@@ -620,7 +672,7 @@
 
 	get_html_page_path(&page_path, page);
 
-	execl_git_cmd("web--browse", "-c", "help.browser", page_path.buf, NULL);
+	open_html(page_path.buf);
 }
 
 void help_unknown_cmd(const char *cmd)
diff --git a/http-push.c b/http-push.c
index 665712a..6805288 100644
--- a/http-push.c
+++ b/http-push.c
@@ -14,7 +14,7 @@
 #include <expat.h>
 
 static const char http_push_usage[] =
-"git-http-push [--all] [--dry-run] [--force] [--verbose] <remote> [<head>...]\n";
+"git http-push [--all] [--dry-run] [--force] [--verbose] <remote> [<head>...]\n";
 
 #ifndef XML_STATUS_OK
 enum XML_Status {
@@ -783,7 +783,7 @@
 					lst = &((*lst)->next);
 				*lst = (*lst)->next;
 
-				if (!verify_pack(target, 0))
+				if (!verify_pack(target))
 					install_packed_git(target);
 				else
 					remote->can_update_info_refs = 0;
diff --git a/http-walker.c b/http-walker.c
index 7403306..9dc6b27 100644
--- a/http-walker.c
+++ b/http-walker.c
@@ -797,7 +797,7 @@
 		lst = &((*lst)->next);
 	*lst = (*lst)->next;
 
-	if (verify_pack(target, 0))
+	if (verify_pack(target))
 		return -1;
 	install_packed_git(target);
 
diff --git a/http.c b/http.c
index 1108ab4..c18e30a 100644
--- a/http.c
+++ b/http.c
@@ -24,7 +24,7 @@
 static long curl_low_speed_limit = -1;
 static long curl_low_speed_time = -1;
 static int curl_ftp_no_epsv = 0;
-static char *curl_http_proxy = NULL;
+static const char *curl_http_proxy = NULL;
 
 static struct curl_slist *pragma_header;
 
@@ -149,11 +149,8 @@
 		return 0;
 	}
 	if (!strcmp("http.proxy", var)) {
-		if (curl_http_proxy == NULL) {
-			if (!value)
-				return config_error_nonbool(var);
-			curl_http_proxy = xstrdup(value);
-		}
+		if (curl_http_proxy == NULL)
+			return git_config_string(&curl_http_proxy, var, value);
 		return 0;
 	}
 
@@ -165,7 +162,16 @@
 {
 	CURL* result = curl_easy_init();
 
-	curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, curl_ssl_verify);
+	if (!curl_ssl_verify) {
+		curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, 0);
+		curl_easy_setopt(result, CURLOPT_SSL_VERIFYHOST, 0);
+	} else {
+		/* Verify authenticity of the peer's certificate */
+		curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, 1);
+		/* The name in the cert must match whom we tried to connect */
+		curl_easy_setopt(result, CURLOPT_SSL_VERIFYHOST, 2);
+	}
+
 #if LIBCURL_VERSION_NUM >= 0x070907
 	curl_easy_setopt(result, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
 #endif
@@ -300,7 +306,7 @@
 	pragma_header = NULL;
 
 	if (curl_http_proxy) {
-		free(curl_http_proxy);
+		free((void *)curl_http_proxy);
 		curl_http_proxy = NULL;
 	}
 }
diff --git a/ident.c b/ident.c
index b35504a..09cf0c9 100644
--- a/ident.c
+++ b/ident.c
@@ -204,7 +204,7 @@
 		if ((warn_on_no_name || error_on_no_name) &&
 		    name == git_default_name && env_hint) {
 			fprintf(stderr, env_hint, au_env, co_env);
-			env_hint = NULL; /* warn only once, for "git-var -l" */
+			env_hint = NULL; /* warn only once, for "git var -l" */
 		}
 		if (error_on_no_name)
 			die("empty ident %s <%s> not allowed", name, email);
diff --git a/index-pack.c b/index-pack.c
index 7d5344a..c99a1a1 100644
--- a/index-pack.c
+++ b/index-pack.c
@@ -10,7 +10,7 @@
 #include "fsck.h"
 
 static const char index_pack_usage[] =
-"git-index-pack [-v] [-o <index-file>] [{ ---keep | --keep=<msg> }] [--strict] { <pack-file> | --stdin [--fix-thin] [<pack-file>] }";
+"git index-pack [-v] [-o <index-file>] [{ ---keep | --keep=<msg> }] [--strict] { <pack-file> | --stdin [--fix-thin] [<pack-file>] }";
 
 struct object_entry
 {
@@ -172,7 +172,7 @@
 		if (!pack_name) {
 			static char tmpfile[PATH_MAX];
 			snprintf(tmpfile, sizeof(tmpfile),
-				 "%s/tmp_pack_XXXXXX", get_object_directory());
+				 "%s/pack/tmp_pack_XXXXXX", get_object_directory());
 			output_fd = xmkstemp(tmpfile);
 			pack_name = xstrdup(tmpfile);
 		} else
@@ -200,7 +200,8 @@
 	if (hdr->hdr_signature != htonl(PACK_SIGNATURE))
 		die("pack signature mismatch");
 	if (!pack_version_ok(hdr->hdr_version))
-		die("pack version %d unsupported", ntohl(hdr->hdr_version));
+		die("pack version %"PRIu32" unsupported",
+			ntohl(hdr->hdr_version));
 
 	nr_objects = ntohl(hdr->hdr_entries);
 	use(sizeof(struct pack_header));
@@ -364,8 +365,11 @@
 	data = src;
 	do {
 		ssize_t n = pread(pack_fd, data + rdy, len - rdy, from + rdy);
-		if (n <= 0)
+		if (n < 0)
 			die("cannot pread pack file: %s", strerror(errno));
+		if (!n)
+			die("premature end of pack file, %lu bytes missing",
+			    len - rdy);
 		rdy += n;
 	} while (rdy < len);
 	data = xmalloc(obj->size);
@@ -653,7 +657,7 @@
 	}
 }
 
-static int write_compressed(int fd, void *in, unsigned int size, uint32_t *obj_crc)
+static int write_compressed(struct sha1file *f, void *in, unsigned int size)
 {
 	z_stream stream;
 	unsigned long maxsize;
@@ -673,13 +677,12 @@
 	deflateEnd(&stream);
 
 	size = stream.total_out;
-	write_or_die(fd, out, size);
-	*obj_crc = crc32(*obj_crc, out, size);
+	sha1write(f, out, size);
 	free(out);
 	return size;
 }
 
-static struct object_entry *append_obj_to_pack(
+static struct object_entry *append_obj_to_pack(struct sha1file *f,
 			       const unsigned char *sha1, void *buf,
 			       unsigned long size, enum object_type type)
 {
@@ -695,15 +698,16 @@
 		s >>= 7;
 	}
 	header[n++] = c;
-	write_or_die(output_fd, header, n);
-	obj[0].idx.crc32 = crc32(0, Z_NULL, 0);
-	obj[0].idx.crc32 = crc32(obj[0].idx.crc32, header, n);
+	crc32_begin(f);
+	sha1write(f, header, n);
 	obj[0].size = size;
 	obj[0].hdr_size = n;
 	obj[0].type = type;
 	obj[0].real_type = type;
 	obj[1].idx.offset = obj[0].idx.offset + n;
-	obj[1].idx.offset += write_compressed(output_fd, buf, size, &obj[0].idx.crc32);
+	obj[1].idx.offset += write_compressed(f, buf, size);
+	obj[0].idx.crc32 = crc32_end(f);
+	sha1flush(f);
 	hashcpy(obj->idx.sha1, sha1);
 	return obj;
 }
@@ -715,7 +719,7 @@
 	return a->obj_no - b->obj_no;
 }
 
-static void fix_unresolved_deltas(int nr_unresolved)
+static void fix_unresolved_deltas(struct sha1file *f, int nr_unresolved)
 {
 	struct delta_entry **sorted_by_pos;
 	int i, n = 0;
@@ -753,8 +757,8 @@
 		if (check_sha1_signature(d->base.sha1, base_obj.data,
 				base_obj.size, typename(type)))
 			die("local object %s is corrupt", sha1_to_hex(d->base.sha1));
-		base_obj.obj = append_obj_to_pack(d->base.sha1, base_obj.data,
-			base_obj.size, type);
+		base_obj.obj = append_obj_to_pack(f, d->base.sha1,
+					base_obj.data, base_obj.size, type);
 		link_base_data(NULL, &base_obj);
 
 		find_delta_children(&d->base, &first, &last);
@@ -859,7 +863,8 @@
 	if (!strcmp(k, "pack.indexversion")) {
 		pack_idx_default_version = git_config_int(k, v);
 		if (pack_idx_default_version > 2)
-			die("bad pack.indexversion=%d", pack_idx_default_version);
+			die("bad pack.indexversion=%"PRIu32,
+				pack_idx_default_version);
 		return 0;
 	}
 	return git_default_config(k, v, cb);
@@ -873,9 +878,27 @@
 	const char *keep_name = NULL, *keep_msg = NULL;
 	char *index_name_buf = NULL, *keep_name_buf = NULL;
 	struct pack_idx_entry **idx_objects;
-	unsigned char sha1[20];
+	unsigned char pack_sha1[20];
 
-	git_config(git_index_pack_config, NULL);
+	/*
+	 * We wish to read the repository's config file if any, and
+	 * for that it is necessary to call setup_git_directory_gently().
+	 * However if the cwd was inside .git/objects/pack/ then we need
+	 * to go back there or all the pack name arguments will be wrong.
+	 * And in that case we cannot rely on any prefix returned by
+	 * setup_git_directory_gently() either.
+	 */
+	{
+		char cwd[PATH_MAX+1];
+		int nongit;
+
+		if (!getcwd(cwd, sizeof(cwd)-1))
+			die("Unable to get current working directory");
+		setup_git_directory_gently(&nongit);
+		git_config(git_index_pack_config, NULL);
+		if (chdir(cwd))
+			die("Cannot come back to cwd");
+	}
 
 	for (i = 1; i < argc; i++) {
 		char *arg = argv[i];
@@ -958,13 +981,15 @@
 	parse_pack_header();
 	objects = xmalloc((nr_objects + 1) * sizeof(struct object_entry));
 	deltas = xmalloc(nr_objects * sizeof(struct delta_entry));
-	parse_pack_objects(sha1);
+	parse_pack_objects(pack_sha1);
 	if (nr_deltas == nr_resolved_deltas) {
 		stop_progress(&progress);
 		/* Flush remaining pack final 20-byte SHA1. */
 		flush();
 	} else {
 		if (fix_thin_pack) {
+			struct sha1file *f;
+			unsigned char read_sha1[20], tail_sha1[20];
 			char msg[48];
 			int nr_unresolved = nr_deltas - nr_resolved_deltas;
 			int nr_objects_initial = nr_objects;
@@ -973,12 +998,19 @@
 			objects = xrealloc(objects,
 					   (nr_objects + nr_unresolved + 1)
 					   * sizeof(*objects));
-			fix_unresolved_deltas(nr_unresolved);
+			f = sha1fd(output_fd, curr_pack);
+			fix_unresolved_deltas(f, nr_unresolved);
 			sprintf(msg, "completed with %d local objects",
 				nr_objects - nr_objects_initial);
 			stop_progress_msg(&progress, msg);
-			fixup_pack_header_footer(output_fd, sha1,
-						 curr_pack, nr_objects);
+			sha1close(f, tail_sha1, 0);
+			hashcpy(read_sha1, pack_sha1);
+			fixup_pack_header_footer(output_fd, pack_sha1,
+						 curr_pack, nr_objects,
+						 read_sha1, consumed_bytes-20);
+			if (hashcmp(read_sha1, tail_sha1) != 0)
+				die("Unexpected tail checksum for %s "
+				    "(disk corruption?)", curr_pack);
 		}
 		if (nr_deltas != nr_resolved_deltas)
 			die("pack has %d unresolved deltas",
@@ -991,13 +1023,13 @@
 	idx_objects = xmalloc((nr_objects) * sizeof(struct pack_idx_entry *));
 	for (i = 0; i < nr_objects; i++)
 		idx_objects[i] = &objects[i].idx;
-	curr_index = write_idx_file(index_name, idx_objects, nr_objects, sha1);
+	curr_index = write_idx_file(index_name, idx_objects, nr_objects, pack_sha1);
 	free(idx_objects);
 
 	final(pack_name, curr_pack,
 		index_name, curr_index,
 		keep_name, keep_msg,
-		sha1);
+		pack_sha1);
 	free(objects);
 	free(index_name_buf);
 	free(keep_name_buf);
diff --git a/lockfile.c b/lockfile.c
index 4023797..6d75608 100644
--- a/lockfile.c
+++ b/lockfile.c
@@ -121,15 +121,17 @@
 }
 
 
-static int lock_file(struct lock_file *lk, const char *path)
+static int lock_file(struct lock_file *lk, const char *path, int flags)
 {
-	if (strlen(path) >= sizeof(lk->filename)) return -1;
+	if (strlen(path) >= sizeof(lk->filename))
+		return -1;
 	strcpy(lk->filename, path);
 	/*
 	 * subtract 5 from size to make sure there's room for adding
 	 * ".lock" for the lock file name
 	 */
-	resolve_symlink(lk->filename, sizeof(lk->filename)-5);
+	if (!(flags & LOCK_NODEREF))
+		resolve_symlink(lk->filename, sizeof(lk->filename)-5);
 	strcat(lk->filename, ".lock");
 	lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);
 	if (0 <= lk->fd) {
@@ -155,21 +157,21 @@
 	return lk->fd;
 }
 
-int hold_lock_file_for_update(struct lock_file *lk, const char *path, int die_on_error)
+int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags)
 {
-	int fd = lock_file(lk, path);
-	if (fd < 0 && die_on_error)
+	int fd = lock_file(lk, path, flags);
+	if (fd < 0 && (flags & LOCK_DIE_ON_ERROR))
 		die("unable to create '%s.lock': %s", path, strerror(errno));
 	return fd;
 }
 
-int hold_lock_file_for_append(struct lock_file *lk, const char *path, int die_on_error)
+int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags)
 {
 	int fd, orig_fd;
 
-	fd = lock_file(lk, path);
+	fd = lock_file(lk, path, flags);
 	if (fd < 0) {
-		if (die_on_error)
+		if (flags & LOCK_DIE_ON_ERROR)
 			die("unable to create '%s.lock': %s", path, strerror(errno));
 		return fd;
 	}
@@ -177,13 +179,13 @@
 	orig_fd = open(path, O_RDONLY);
 	if (orig_fd < 0) {
 		if (errno != ENOENT) {
-			if (die_on_error)
+			if (flags & LOCK_DIE_ON_ERROR)
 				die("cannot open '%s' for copying", path);
 			close(fd);
 			return error("cannot open '%s' for copying", path);
 		}
 	} else if (copy_fd(orig_fd, fd)) {
-		if (die_on_error)
+		if (flags & LOCK_DIE_ON_ERROR)
 			exit(128);
 		close(fd);
 		return -1;
@@ -215,7 +217,10 @@
 
 int hold_locked_index(struct lock_file *lk, int die_on_error)
 {
-	return hold_lock_file_for_update(lk, get_index_file(), die_on_error);
+	return hold_lock_file_for_update(lk, get_index_file(),
+					 die_on_error
+					 ? LOCK_DIE_ON_ERROR
+					 : 0);
 }
 
 void set_alternate_index_output(const char *name)
diff --git a/log-tree.c b/log-tree.c
index 5505606..bd8b9e4 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -198,7 +198,7 @@
 		extra_headers = subject_buffer;
 
 		snprintf(buffer, sizeof(buffer) - 1,
-			 "--%s%s\n"
+			 "\n--%s%s\n"
 			 "Content-Type: text/x-patch;"
 			 " name=\"%s.diff\"\n"
 			 "Content-Transfer-Encoding: 8bit\n"
diff --git a/mailmap.c b/mailmap.c
index f017255..88fc6f3 100644
--- a/mailmap.c
+++ b/mailmap.c
@@ -1,8 +1,8 @@
 #include "cache.h"
-#include "path-list.h"
+#include "string-list.h"
 #include "mailmap.h"
 
-int read_mailmap(struct path_list *map, const char *filename, char **repo_abbrev)
+int read_mailmap(struct string_list *map, const char *filename, char **repo_abbrev)
 {
 	char buffer[1024];
 	FILE *f = fopen(filename, "r");
@@ -54,16 +54,16 @@
 		for (i = 0; i < right_bracket - left_bracket - 1; i++)
 			email[i] = tolower(left_bracket[i + 1]);
 		email[right_bracket - left_bracket - 1] = '\0';
-		path_list_insert(email, map)->util = name;
+		string_list_insert(email, map)->util = name;
 	}
 	fclose(f);
 	return 0;
 }
 
-int map_email(struct path_list *map, const char *email, char *name, int maxlen)
+int map_email(struct string_list *map, const char *email, char *name, int maxlen)
 {
 	char *p;
-	struct path_list_item *item;
+	struct string_list_item *item;
 	char buf[1024], *mailbuf;
 	int i;
 
@@ -80,7 +80,7 @@
 	for (i = 0; i < p - email; i++)
 		mailbuf[i] = tolower(email[i]);
 	mailbuf[i] = 0;
-	item = path_list_lookup(mailbuf, map);
+	item = string_list_lookup(mailbuf, map);
 	if (mailbuf != buf)
 		free(mailbuf);
 	if (item != NULL) {
diff --git a/mailmap.h b/mailmap.h
index 3503fd2..6e48f83 100644
--- a/mailmap.h
+++ b/mailmap.h
@@ -1,7 +1,7 @@
 #ifndef MAILMAP_H
 #define MAILMAP_H
 
-int read_mailmap(struct path_list *map, const char *filename, char **repo_abbrev);
-int map_email(struct path_list *mailmap, const char *email, char *name, int maxlen);
+int read_mailmap(struct string_list *map, const char *filename, char **repo_abbrev);
+int map_email(struct string_list *mailmap, const char *email, char *name, int maxlen);
 
 #endif
diff --git a/merge-index.c b/merge-index.c
index 7491c56..7827e87 100644
--- a/merge-index.c
+++ b/merge-index.c
@@ -27,7 +27,7 @@
 	int found;
 
 	if (pos >= active_nr)
-		die("git-merge-index: %s not in the cache", path);
+		die("git merge-index: %s not in the cache", path);
 	arguments[0] = pgm;
 	arguments[1] = "";
 	arguments[2] = "";
@@ -53,7 +53,7 @@
 		arguments[stage + 4] = ownbuf[stage];
 	} while (++pos < active_nr);
 	if (!found)
-		die("git-merge-index: %s not in the cache", path);
+		die("git merge-index: %s not in the cache", path);
 	run_program();
 	return found;
 }
@@ -117,7 +117,7 @@
 				merge_all();
 				continue;
 			}
-			die("git-merge-index: unknown option %s", arg);
+			die("git merge-index: unknown option %s", arg);
 		}
 		merge_file(arg);
 	}
diff --git a/pack-check.c b/pack-check.c
index f489873..f596bf2 100644
--- a/pack-check.c
+++ b/pack-check.c
@@ -4,8 +4,9 @@
 
 struct idx_entry
 {
-	const unsigned char *sha1;
 	off_t                offset;
+	const unsigned char *sha1;
+	unsigned int nr;
 };
 
 static int compare_entries(const void *e1, const void *e2)
@@ -19,6 +20,28 @@
 	return 0;
 }
 
+int check_pack_crc(struct packed_git *p, struct pack_window **w_curs,
+		   off_t offset, off_t len, unsigned int nr)
+{
+	const uint32_t *index_crc;
+	uint32_t data_crc = crc32(0, Z_NULL, 0);
+
+	do {
+		unsigned int avail;
+		void *data = use_pack(p, w_curs, offset, &avail);
+		if (avail > len)
+			avail = len;
+		data_crc = crc32(data_crc, data, avail);
+		offset += avail;
+		len -= avail;
+	} while (len);
+
+	index_crc = p->index_data;
+	index_crc += 2 + 256 + p->num_objects * (20/4) + nr;
+
+	return data_crc != ntohl(*index_crc);
+}
+
 static int verify_packfile(struct packed_git *p,
 		struct pack_window **w_curs)
 {
@@ -61,15 +84,15 @@
 	 * we do not do scan-streaming check on the pack file.
 	 */
 	nr_objects = p->num_objects;
-	entries = xmalloc(nr_objects * sizeof(*entries));
+	entries = xmalloc((nr_objects + 1) * sizeof(*entries));
+	entries[nr_objects].offset = pack_sig_ofs;
 	/* first sort entries by pack offset, since unpacking them is more efficient that way */
 	for (i = 0; i < nr_objects; i++) {
 		entries[i].sha1 = nth_packed_object_sha1(p, i);
 		if (!entries[i].sha1)
 			die("internal error pack-check nth-packed-object");
-		entries[i].offset = find_pack_entry_one(entries[i].sha1, p);
-		if (!entries[i].offset)
-			die("internal error pack-check find-pack-entry-one");
+		entries[i].offset = nth_packed_object_offset(p, i);
+		entries[i].nr = i;
 	}
 	qsort(entries, nr_objects, sizeof(*entries), compare_entries);
 
@@ -78,6 +101,16 @@
 		enum object_type type;
 		unsigned long size;
 
+		if (p->index_version > 1) {
+			off_t offset = entries[i].offset;
+			off_t len = entries[i+1].offset - offset;
+			unsigned int nr = entries[i].nr;
+			if (check_pack_crc(p, w_curs, offset, len, nr))
+				err = error("index CRC mismatch for object %s "
+					    "from %s at offset %"PRIuMAX"",
+					    sha1_to_hex(entries[i].sha1),
+					    p->pack_name, (uintmax_t)offset);
+		}
 		data = unpack_entry(p, entries[i].offset, &type, &size);
 		if (!data) {
 			err = error("cannot unpack %s from %s at offset %"PRIuMAX"",
@@ -98,63 +131,7 @@
 	return err;
 }
 
-
-#define MAX_CHAIN 50
-
-static void show_pack_info(struct packed_git *p)
-{
-	uint32_t nr_objects, i, chain_histogram[MAX_CHAIN+1];
-
-	nr_objects = p->num_objects;
-	memset(chain_histogram, 0, sizeof(chain_histogram));
-	init_pack_revindex();
-
-	for (i = 0; i < nr_objects; i++) {
-		const unsigned char *sha1;
-		unsigned char base_sha1[20];
-		const char *type;
-		unsigned long size;
-		unsigned long store_size;
-		off_t offset;
-		unsigned int delta_chain_length;
-
-		sha1 = nth_packed_object_sha1(p, i);
-		if (!sha1)
-			die("internal error pack-check nth-packed-object");
-		offset = find_pack_entry_one(sha1, p);
-		if (!offset)
-			die("internal error pack-check find-pack-entry-one");
-
-		type = packed_object_info_detail(p, offset, &size, &store_size,
-						 &delta_chain_length,
-						 base_sha1);
-		printf("%s ", sha1_to_hex(sha1));
-		if (!delta_chain_length)
-			printf("%-6s %lu %lu %"PRIuMAX"\n",
-			       type, size, store_size, (uintmax_t)offset);
-		else {
-			printf("%-6s %lu %lu %"PRIuMAX" %u %s\n",
-			       type, size, store_size, (uintmax_t)offset,
-			       delta_chain_length, sha1_to_hex(base_sha1));
-			if (delta_chain_length <= MAX_CHAIN)
-				chain_histogram[delta_chain_length]++;
-			else
-				chain_histogram[0]++;
-		}
-	}
-
-	for (i = 0; i <= MAX_CHAIN; i++) {
-		if (!chain_histogram[i])
-			continue;
-		printf("chain length = %d: %d object%s\n", i,
-		       chain_histogram[i], chain_histogram[i] > 1 ? "s" : "");
-	}
-	if (chain_histogram[0])
-		printf("chain length > %d: %d object%s\n", MAX_CHAIN,
-		       chain_histogram[0], chain_histogram[0] > 1 ? "s" : "");
-}
-
-int verify_pack(struct packed_git *p, int verbose)
+int verify_pack(struct packed_git *p)
 {
 	off_t index_size;
 	const unsigned char *index_base;
@@ -180,14 +157,5 @@
 	err |= verify_packfile(p, &w_curs);
 	unuse_pack(&w_curs);
 
-	if (verbose) {
-		if (err)
-			printf("%s: bad\n", p->pack_name);
-		else {
-			show_pack_info(p);
-			printf("%s: ok\n", p->pack_name);
-		}
-	}
-
 	return err;
 }
diff --git a/pack-redundant.c b/pack-redundant.c
index f5cd0ac..25b81a4 100644
--- a/pack-redundant.c
+++ b/pack-redundant.c
@@ -11,7 +11,7 @@
 #define BLKSIZE 512
 
 static const char pack_redundant_usage[] =
-"git-pack-redundant [ --verbose ] [ --alt-odb ] < --all | <.pack filename> ...>";
+"git pack-redundant [ --verbose ] [ --alt-odb ] < --all | <.pack filename> ...>";
 
 static int load_all_packs, verbose, alt_odb;
 
diff --git a/pack-refs.c b/pack-refs.c
new file mode 100644
index 0000000..2c76fb1
--- /dev/null
+++ b/pack-refs.c
@@ -0,0 +1,118 @@
+#include "cache.h"
+#include "refs.h"
+#include "tag.h"
+#include "pack-refs.h"
+
+struct ref_to_prune {
+	struct ref_to_prune *next;
+	unsigned char sha1[20];
+	char name[FLEX_ARRAY];
+};
+
+struct pack_refs_cb_data {
+	unsigned int flags;
+	struct ref_to_prune *ref_to_prune;
+	FILE *refs_file;
+};
+
+static int do_not_prune(int flags)
+{
+	/* If it is already packed or if it is a symref,
+	 * do not prune it.
+	 */
+	return (flags & (REF_ISSYMREF|REF_ISPACKED));
+}
+
+static int handle_one_ref(const char *path, const unsigned char *sha1,
+			  int flags, void *cb_data)
+{
+	struct pack_refs_cb_data *cb = cb_data;
+	int is_tag_ref;
+
+	/* Do not pack the symbolic refs */
+	if ((flags & REF_ISSYMREF))
+		return 0;
+	is_tag_ref = !prefixcmp(path, "refs/tags/");
+
+	/* ALWAYS pack refs that were already packed or are tags */
+	if (!(cb->flags & PACK_REFS_ALL) && !is_tag_ref && !(flags & REF_ISPACKED))
+		return 0;
+
+	fprintf(cb->refs_file, "%s %s\n", sha1_to_hex(sha1), path);
+	if (is_tag_ref) {
+		struct object *o = parse_object(sha1);
+		if (o->type == OBJ_TAG) {
+			o = deref_tag(o, path, 0);
+			if (o)
+				fprintf(cb->refs_file, "^%s\n",
+					sha1_to_hex(o->sha1));
+		}
+	}
+
+	if ((cb->flags & PACK_REFS_PRUNE) && !do_not_prune(flags)) {
+		int namelen = strlen(path) + 1;
+		struct ref_to_prune *n = xcalloc(1, sizeof(*n) + namelen);
+		hashcpy(n->sha1, sha1);
+		strcpy(n->name, path);
+		n->next = cb->ref_to_prune;
+		cb->ref_to_prune = n;
+	}
+	return 0;
+}
+
+/* make sure nobody touched the ref, and unlink */
+static void prune_ref(struct ref_to_prune *r)
+{
+	struct ref_lock *lock = lock_ref_sha1(r->name + 5, r->sha1);
+
+	if (lock) {
+		unlink(git_path("%s", r->name));
+		unlock_ref(lock);
+	}
+}
+
+static void prune_refs(struct ref_to_prune *r)
+{
+	while (r) {
+		prune_ref(r);
+		r = r->next;
+	}
+}
+
+static struct lock_file packed;
+
+int pack_refs(unsigned int flags)
+{
+	int fd;
+	struct pack_refs_cb_data cbdata;
+
+	memset(&cbdata, 0, sizeof(cbdata));
+	cbdata.flags = flags;
+
+	fd = hold_lock_file_for_update(&packed, git_path("packed-refs"),
+				       LOCK_DIE_ON_ERROR);
+	cbdata.refs_file = fdopen(fd, "w");
+	if (!cbdata.refs_file)
+		die("unable to create ref-pack file structure (%s)",
+		    strerror(errno));
+
+	/* perhaps other traits later as well */
+	fprintf(cbdata.refs_file, "# pack-refs with: peeled \n");
+
+	for_each_ref(handle_one_ref, &cbdata);
+	if (ferror(cbdata.refs_file))
+		die("failed to write ref-pack file");
+	if (fflush(cbdata.refs_file) || fsync(fd) || fclose(cbdata.refs_file))
+		die("failed to write ref-pack file (%s)", strerror(errno));
+	/*
+	 * Since the lock file was fdopen()'ed and then fclose()'ed above,
+	 * assign -1 to the lock file descriptor so that commit_lock_file()
+	 * won't try to close() it.
+	 */
+	packed.fd = -1;
+	if (commit_lock_file(&packed) < 0)
+		die("unable to overwrite old ref-pack file (%s)", strerror(errno));
+	if (cbdata.flags & PACK_REFS_PRUNE)
+		prune_refs(cbdata.ref_to_prune);
+	return 0;
+}
diff --git a/pack-refs.h b/pack-refs.h
new file mode 100644
index 0000000..518acfb
--- /dev/null
+++ b/pack-refs.h
@@ -0,0 +1,18 @@
+#ifndef PACK_REFS_H
+#define PACK_REFS_H
+
+/*
+ * Flags for controlling behaviour of pack_refs()
+ * PACK_REFS_PRUNE: Prune loose refs after packing
+ * PACK_REFS_ALL:   Pack _all_ refs, not just tags and already packed refs
+ */
+#define PACK_REFS_PRUNE 0x0001
+#define PACK_REFS_ALL   0x0002
+
+/*
+ * Write a packed-refs file for the current repository.
+ * flags: Combination of the above PACK_REFS_* flags.
+ */
+int pack_refs(unsigned int flags);
+
+#endif /* PACK_REFS_H */
diff --git a/pack-revindex.c b/pack-revindex.c
index a8aa2cd..6096b62 100644
--- a/pack-revindex.c
+++ b/pack-revindex.c
@@ -40,7 +40,7 @@
 	return -1 - i;
 }
 
-void init_pack_revindex(void)
+static void init_pack_revindex(void)
 {
 	int num;
 	struct packed_git *p;
@@ -118,9 +118,11 @@
 	struct pack_revindex *rix;
 	struct revindex_entry *revindex;
 
+	if (!pack_revindex_hashsz)
+		init_pack_revindex();
 	num = pack_revindex_ix(p);
 	if (num < 0)
-		die("internal error: pack revindex uninitialized");
+		die("internal error: pack revindex fubar");
 
 	rix = &pack_revindex[num];
 	if (!rix->revindex)
@@ -140,3 +142,15 @@
 	} while (lo < hi);
 	die("internal error: pack revindex corrupt");
 }
+
+void discard_revindex(void)
+{
+	if (pack_revindex_hashsz) {
+		int i;
+		for (i = 0; i < pack_revindex_hashsz; i++)
+			if (pack_revindex[i].revindex)
+				free(pack_revindex[i].revindex);
+		free(pack_revindex);
+		pack_revindex_hashsz = 0;
+	}
+}
diff --git a/pack-revindex.h b/pack-revindex.h
index c3527a7..8d5027a 100644
--- a/pack-revindex.h
+++ b/pack-revindex.h
@@ -6,7 +6,7 @@
 	unsigned int nr;
 };
 
-void init_pack_revindex(void);
 struct revindex_entry *find_pack_revindex(struct packed_git *p, off_t ofs);
+void discard_revindex(void);
 
 #endif
diff --git a/pack-write.c b/pack-write.c
index f52cabe..3621f1d 100644
--- a/pack-write.c
+++ b/pack-write.c
@@ -2,7 +2,7 @@
 #include "pack.h"
 #include "csum-file.h"
 
-uint32_t pack_idx_default_version = 1;
+uint32_t pack_idx_default_version = 2;
 uint32_t pack_idx_off32_limit = 0x7fffffff;
 
 static int sha1_compare(const void *_a, const void *_b)
@@ -45,7 +45,7 @@
 	if (!index_name) {
 		static char tmpfile[PATH_MAX];
 		snprintf(tmpfile, sizeof(tmpfile),
-			 "%s/tmp_idx_XXXXXX", get_object_directory());
+			 "%s/pack/tmp_idx_XXXXXX", get_object_directory());
 		fd = xmkstemp(tmpfile);
 		index_name = xstrdup(tmpfile);
 	} else {
@@ -144,41 +144,94 @@
 	return index_name;
 }
 
+/*
+ * Update pack header with object_count and compute new SHA1 for pack data
+ * associated to pack_fd, and write that SHA1 at the end.  That new SHA1
+ * is also returned in new_pack_sha1.
+ *
+ * If partial_pack_sha1 is non null, then the SHA1 of the existing pack
+ * (without the header update) is computed and validated against the
+ * one provided in partial_pack_sha1.  The validation is performed at
+ * partial_pack_offset bytes in the pack file.  The SHA1 of the remaining
+ * data (i.e. from partial_pack_offset to the end) is then computed and
+ * returned in partial_pack_sha1.
+ *
+ * Note that new_pack_sha1 is updated last, so both new_pack_sha1 and
+ * partial_pack_sha1 can refer to the same buffer if the caller is not
+ * interested in the resulting SHA1 of pack data above partial_pack_offset.
+ */
 void fixup_pack_header_footer(int pack_fd,
-			 unsigned char *pack_file_sha1,
+			 unsigned char *new_pack_sha1,
 			 const char *pack_name,
-			 uint32_t object_count)
+			 uint32_t object_count,
+			 unsigned char *partial_pack_sha1,
+			 off_t partial_pack_offset)
 {
-	static const int buf_sz = 128 * 1024;
-	SHA_CTX c;
+	int aligned_sz, buf_sz = 8 * 1024;
+	SHA_CTX old_sha1_ctx, new_sha1_ctx;
 	struct pack_header hdr;
 	char *buf;
 
+	SHA1_Init(&old_sha1_ctx);
+	SHA1_Init(&new_sha1_ctx);
+
 	if (lseek(pack_fd, 0, SEEK_SET) != 0)
-		die("Failed seeking to start: %s", strerror(errno));
+		die("Failed seeking to start of %s: %s", pack_name, strerror(errno));
 	if (read_in_full(pack_fd, &hdr, sizeof(hdr)) != sizeof(hdr))
 		die("Unable to reread header of %s: %s", pack_name, strerror(errno));
 	if (lseek(pack_fd, 0, SEEK_SET) != 0)
-		die("Failed seeking to start: %s", strerror(errno));
+		die("Failed seeking to start of %s: %s", pack_name, strerror(errno));
+	SHA1_Update(&old_sha1_ctx, &hdr, sizeof(hdr));
 	hdr.hdr_entries = htonl(object_count);
+	SHA1_Update(&new_sha1_ctx, &hdr, sizeof(hdr));
 	write_or_die(pack_fd, &hdr, sizeof(hdr));
-
-	SHA1_Init(&c);
-	SHA1_Update(&c, &hdr, sizeof(hdr));
+	partial_pack_offset -= sizeof(hdr);
 
 	buf = xmalloc(buf_sz);
+	aligned_sz = buf_sz - sizeof(hdr);
 	for (;;) {
-		ssize_t n = xread(pack_fd, buf, buf_sz);
+		ssize_t m, n;
+		m = (partial_pack_sha1 && partial_pack_offset < aligned_sz) ?
+			partial_pack_offset : aligned_sz;
+		n = xread(pack_fd, buf, m);
 		if (!n)
 			break;
 		if (n < 0)
 			die("Failed to checksum %s: %s", pack_name, strerror(errno));
-		SHA1_Update(&c, buf, n);
+		SHA1_Update(&new_sha1_ctx, buf, n);
+
+		aligned_sz -= n;
+		if (!aligned_sz)
+			aligned_sz = buf_sz;
+
+		if (!partial_pack_sha1)
+			continue;
+
+		SHA1_Update(&old_sha1_ctx, buf, n);
+		partial_pack_offset -= n;
+		if (partial_pack_offset == 0) {
+			unsigned char sha1[20];
+			SHA1_Final(sha1, &old_sha1_ctx);
+			if (hashcmp(sha1, partial_pack_sha1) != 0)
+				die("Unexpected checksum for %s "
+				    "(disk corruption?)", pack_name);
+			/*
+			 * Now let's compute the SHA1 of the remainder of the
+			 * pack, which also means making partial_pack_offset
+			 * big enough not to matter anymore.
+			 */
+			SHA1_Init(&old_sha1_ctx);
+			partial_pack_offset = ~partial_pack_offset;
+			partial_pack_offset -= MSB(partial_pack_offset, 1);
+		}
 	}
 	free(buf);
 
-	SHA1_Final(pack_file_sha1, &c);
-	write_or_die(pack_fd, pack_file_sha1, 20);
+	if (partial_pack_sha1)
+		SHA1_Final(partial_pack_sha1, &old_sha1_ctx);
+	SHA1_Final(new_pack_sha1, &new_sha1_ctx);
+	write_or_die(pack_fd, new_pack_sha1, 20);
+	fsync_or_die(pack_fd, pack_name);
 }
 
 char *index_pack_lockfile(int ip_out)
diff --git a/pack.h b/pack.h
index b31b376..a883334 100644
--- a/pack.h
+++ b/pack.h
@@ -56,9 +56,9 @@
 };
 
 extern char *write_idx_file(char *index_name, struct pack_idx_entry **objects, int nr_objects, unsigned char *sha1);
-
-extern int verify_pack(struct packed_git *, int);
-extern void fixup_pack_header_footer(int, unsigned char *, const char *, uint32_t);
+extern int check_pack_crc(struct packed_git *p, struct pack_window **w_curs, off_t offset, off_t len, unsigned int nr);
+extern int verify_pack(struct packed_git *);
+extern void fixup_pack_header_footer(int, unsigned char *, const char *, uint32_t, unsigned char *, off_t);
 extern char *index_pack_lockfile(int fd);
 
 #define PH_ERROR_EOF		(-1)
diff --git a/pager.c b/pager.c
index dbd9414..0b7e55f 100644
--- a/pager.c
+++ b/pager.c
@@ -1,12 +1,13 @@
 #include "cache.h"
 
 /*
- * This is split up from the rest of git so that we might do
- * something different on Windows, for example.
+ * This is split up from the rest of git so that we can do
+ * something different on Windows.
  */
 
 static int spawned_pager;
 
+#ifndef __MINGW32__
 static void run_pager(const char *pager)
 {
 	/*
@@ -22,11 +23,31 @@
 	execlp(pager, pager, NULL);
 	execl("/bin/sh", "sh", "-c", pager, NULL);
 }
+#else
+#include "run-command.h"
+
+static const char *pager_argv[] = { "sh", "-c", NULL, NULL };
+static struct child_process pager_process = {
+	.argv = pager_argv,
+	.in = -1
+};
+static void wait_for_pager(void)
+{
+	fflush(stdout);
+	fflush(stderr);
+	/* signal EOF to pager */
+	close(1);
+	close(2);
+	finish_command(&pager_process);
+}
+#endif
 
 void setup_pager(void)
 {
+#ifndef __MINGW32__
 	pid_t pid;
 	int fd[2];
+#endif
 	const char *pager = getenv("GIT_PAGER");
 
 	if (!isatty(1))
@@ -45,6 +66,7 @@
 
 	spawned_pager = 1; /* means we are emitting to terminal */
 
+#ifndef __MINGW32__
 	if (pipe(fd) < 0)
 		return;
 	pid = fork();
@@ -72,6 +94,21 @@
 	run_pager(pager);
 	die("unable to execute pager '%s'", pager);
 	exit(255);
+#else
+	/* spawn the pager */
+	pager_argv[2] = pager;
+	if (start_command(&pager_process))
+		return;
+
+	/* original process continues, but writes to the pipe */
+	dup2(pager_process.in, 1);
+	if (isatty(2))
+		dup2(pager_process.in, 2);
+	close(pager_process.in);
+
+	/* this makes sure that the parent terminates after the pager */
+	atexit(wait_for_pager);
+#endif
 }
 
 int pager_in_use(void)
diff --git a/parse-options.c b/parse-options.c
index 12c8822..fd08bb4 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -1,33 +1,10 @@
 #include "git-compat-util.h"
 #include "parse-options.h"
+#include "cache.h"
 
 #define OPT_SHORT 1
 #define OPT_UNSET 2
 
-struct optparse_t {
-	const char **argv;
-	const char **out;
-	int argc, cpidx;
-	const char *opt;
-};
-
-static inline const char *get_arg(struct optparse_t *p)
-{
-	if (p->opt) {
-		const char *res = p->opt;
-		p->opt = NULL;
-		return res;
-	}
-	p->argc--;
-	return *++p->argv;
-}
-
-static inline const char *skip_prefix(const char *str, const char *prefix)
-{
-	size_t len = strlen(prefix);
-	return strncmp(str, prefix, len) ? NULL : str + len;
-}
-
 static int opterror(const struct option *opt, const char *reason, int flags)
 {
 	if (flags & OPT_SHORT)
@@ -37,8 +14,24 @@
 	return error("option `%s' %s", opt->long_name, reason);
 }
 
-static int get_value(struct optparse_t *p,
-                     const struct option *opt, int flags)
+static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,
+		   int flags, const char **arg)
+{
+	if (p->opt) {
+		*arg = p->opt;
+		p->opt = NULL;
+	} else if (p->argc == 1 && (opt->flags & PARSE_OPT_LASTARG_DEFAULT)) {
+		*arg = (const char *)opt->defval;
+	} else if (p->argc > 1) {
+		p->argc--;
+		*arg = *++p->argv;
+	} else
+		return opterror(opt, "requires a value", flags);
+	return 0;
+}
+
+static int get_value(struct parse_opt_ctx_t *p,
+		     const struct option *opt, int flags)
 {
 	const char *s, *arg;
 	const int unset = flags & OPT_UNSET;
@@ -64,7 +57,6 @@
 		}
 	}
 
-	arg = p->opt ? p->opt : (p->argc > 1 ? p->argv[1] : NULL);
 	switch (opt->type) {
 	case OPTION_BIT:
 		if (unset)
@@ -86,29 +78,24 @@
 		return 0;
 
 	case OPTION_STRING:
-		if (unset) {
+		if (unset)
 			*(const char **)opt->value = NULL;
-			return 0;
-		}
-		if (opt->flags & PARSE_OPT_OPTARG && !p->opt) {
+		else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
 			*(const char **)opt->value = (const char *)opt->defval;
-			return 0;
-		}
-		if (!arg)
-			return opterror(opt, "requires a value", flags);
-		*(const char **)opt->value = get_arg(p);
+		else
+			return get_arg(p, opt, flags, (const char **)opt->value);
 		return 0;
 
 	case OPTION_CALLBACK:
 		if (unset)
-			return (*opt->callback)(opt, NULL, 1);
+			return (*opt->callback)(opt, NULL, 1) ? (-1) : 0;
 		if (opt->flags & PARSE_OPT_NOARG)
-			return (*opt->callback)(opt, NULL, 0);
+			return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
 		if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
-			return (*opt->callback)(opt, NULL, 0);
-		if (!arg)
-			return opterror(opt, "requires a value", flags);
-		return (*opt->callback)(opt, get_arg(p), 0);
+			return (*opt->callback)(opt, NULL, 0) ? (-1) : 0;
+		if (get_arg(p, opt, flags, &arg))
+			return -1;
+		return (*opt->callback)(opt, arg, 0) ? (-1) : 0;
 
 	case OPTION_INTEGER:
 		if (unset) {
@@ -119,9 +106,9 @@
 			*(int *)opt->value = opt->defval;
 			return 0;
 		}
-		if (!arg)
-			return opterror(opt, "requires a value", flags);
-		*(int *)opt->value = strtol(get_arg(p), (char **)&s, 10);
+		if (get_arg(p, opt, flags, &arg))
+			return -1;
+		*(int *)opt->value = strtol(arg, (char **)&s, 10);
 		if (*s)
 			return opterror(opt, "expects a numerical value", flags);
 		return 0;
@@ -131,7 +118,7 @@
 	}
 }
 
-static int parse_short_opt(struct optparse_t *p, const struct option *options)
+static int parse_short_opt(struct parse_opt_ctx_t *p, const struct option *options)
 {
 	for (; options->type != OPTION_END; options++) {
 		if (options->short_name == *p->opt) {
@@ -139,10 +126,10 @@
 			return get_value(p, options, OPT_SHORT);
 		}
 	}
-	return error("unknown switch `%c'", *p->opt);
+	return -2;
 }
 
-static int parse_long_opt(struct optparse_t *p, const char *arg,
+static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
                           const struct option *options)
 {
 	const char *arg_end = strchr(arg, '=');
@@ -224,10 +211,10 @@
 			abbrev_option->long_name);
 	if (abbrev_option)
 		return get_value(p, abbrev_option, abbrev_flags);
-	return error("unknown option `%s'", arg);
+	return -2;
 }
 
-void check_typos(const char *arg, const struct option *options)
+static void check_typos(const char *arg, const struct option *options)
 {
 	if (strlen(arg) < 3)
 		return;
@@ -247,73 +234,136 @@
 	}
 }
 
-static NORETURN void usage_with_options_internal(const char * const *,
-                                                 const struct option *, int);
-
-int parse_options(int argc, const char **argv, const struct option *options,
-                  const char * const usagestr[], int flags)
+void parse_options_start(struct parse_opt_ctx_t *ctx,
+			 int argc, const char **argv, int flags)
 {
-	struct optparse_t args = { argv + 1, argv, argc - 1, 0, NULL };
+	memset(ctx, 0, sizeof(*ctx));
+	ctx->argc = argc - 1;
+	ctx->argv = argv + 1;
+	ctx->out  = argv;
+	ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0);
+	ctx->flags = flags;
+}
 
-	for (; args.argc; args.argc--, args.argv++) {
-		const char *arg = args.argv[0];
+static int usage_with_options_internal(const char * const *,
+				       const struct option *, int);
+
+int parse_options_step(struct parse_opt_ctx_t *ctx,
+		       const struct option *options,
+		       const char * const usagestr[])
+{
+	/* we must reset ->opt, unknown short option leave it dangling */
+	ctx->opt = NULL;
+
+	for (; ctx->argc; ctx->argc--, ctx->argv++) {
+		const char *arg = ctx->argv[0];
 
 		if (*arg != '-' || !arg[1]) {
-			if (flags & PARSE_OPT_STOP_AT_NON_OPTION)
+			if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION)
 				break;
-			args.out[args.cpidx++] = args.argv[0];
+			ctx->out[ctx->cpidx++] = ctx->argv[0];
 			continue;
 		}
 
 		if (arg[1] != '-') {
-			args.opt = arg + 1;
-			if (*args.opt == 'h')
-				usage_with_options(usagestr, options);
-			if (parse_short_opt(&args, options) < 0)
-				usage_with_options(usagestr, options);
-			if (args.opt)
+			ctx->opt = arg + 1;
+			if (*ctx->opt == 'h')
+				return parse_options_usage(usagestr, options);
+			switch (parse_short_opt(ctx, options)) {
+			case -1:
+				return parse_options_usage(usagestr, options);
+			case -2:
+				return PARSE_OPT_UNKNOWN;
+			}
+			if (ctx->opt)
 				check_typos(arg + 1, options);
-			while (args.opt) {
-				if (*args.opt == 'h')
-					usage_with_options(usagestr, options);
-				if (parse_short_opt(&args, options) < 0)
-					usage_with_options(usagestr, options);
+			while (ctx->opt) {
+				if (*ctx->opt == 'h')
+					return parse_options_usage(usagestr, options);
+				switch (parse_short_opt(ctx, options)) {
+				case -1:
+					return parse_options_usage(usagestr, options);
+				case -2:
+					/* fake a short option thing to hide the fact that we may have
+					 * started to parse aggregated stuff
+					 *
+					 * This is leaky, too bad.
+					 */
+					ctx->argv[0] = xstrdup(ctx->opt - 1);
+					*(char *)ctx->argv[0] = '-';
+					return PARSE_OPT_UNKNOWN;
+				}
 			}
 			continue;
 		}
 
 		if (!arg[2]) { /* "--" */
-			if (!(flags & PARSE_OPT_KEEP_DASHDASH)) {
-				args.argc--;
-				args.argv++;
+			if (!(ctx->flags & PARSE_OPT_KEEP_DASHDASH)) {
+				ctx->argc--;
+				ctx->argv++;
 			}
 			break;
 		}
 
 		if (!strcmp(arg + 2, "help-all"))
-			usage_with_options_internal(usagestr, options, 1);
+			return usage_with_options_internal(usagestr, options, 1);
 		if (!strcmp(arg + 2, "help"))
-			usage_with_options(usagestr, options);
-		if (parse_long_opt(&args, arg + 2, options))
-			usage_with_options(usagestr, options);
+			return parse_options_usage(usagestr, options);
+		switch (parse_long_opt(ctx, arg + 2, options)) {
+		case -1:
+			return parse_options_usage(usagestr, options);
+		case -2:
+			return PARSE_OPT_UNKNOWN;
+		}
+	}
+	return PARSE_OPT_DONE;
+}
+
+int parse_options_end(struct parse_opt_ctx_t *ctx)
+{
+	memmove(ctx->out + ctx->cpidx, ctx->argv, ctx->argc * sizeof(*ctx->out));
+	ctx->out[ctx->cpidx + ctx->argc] = NULL;
+	return ctx->cpidx + ctx->argc;
+}
+
+int parse_options(int argc, const char **argv, const struct option *options,
+		  const char * const usagestr[], int flags)
+{
+	struct parse_opt_ctx_t ctx;
+
+	parse_options_start(&ctx, argc, argv, flags);
+	switch (parse_options_step(&ctx, options, usagestr)) {
+	case PARSE_OPT_HELP:
+		exit(129);
+	case PARSE_OPT_DONE:
+		break;
+	default: /* PARSE_OPT_UNKNOWN */
+		if (ctx.argv[0][1] == '-') {
+			error("unknown option `%s'", ctx.argv[0] + 2);
+		} else {
+			error("unknown switch `%c'", *ctx.opt);
+		}
+		usage_with_options(usagestr, options);
 	}
 
-	memmove(args.out + args.cpidx, args.argv, args.argc * sizeof(*args.out));
-	args.out[args.cpidx + args.argc] = NULL;
-	return args.cpidx + args.argc;
+	return parse_options_end(&ctx);
 }
 
 #define USAGE_OPTS_WIDTH 24
 #define USAGE_GAP         2
 
-void usage_with_options_internal(const char * const *usagestr,
-                                 const struct option *opts, int full)
+int usage_with_options_internal(const char * const *usagestr,
+				const struct option *opts, int full)
 {
 	fprintf(stderr, "usage: %s\n", *usagestr++);
 	while (*usagestr && **usagestr)
 		fprintf(stderr, "   or: %s\n", *usagestr++);
-	while (*usagestr)
-		fprintf(stderr, "    %s\n", *usagestr++);
+	while (*usagestr) {
+		fprintf(stderr, "%s%s\n",
+				**usagestr ? "    " : "",
+				*usagestr);
+		usagestr++;
+	}
 
 	if (opts->type != OPTION_GROUP)
 		fputc('\n', stderr);
@@ -388,15 +438,23 @@
 	}
 	fputc('\n', stderr);
 
-	exit(129);
+	return PARSE_OPT_HELP;
 }
 
 void usage_with_options(const char * const *usagestr,
-                        const struct option *opts)
+			const struct option *opts)
 {
 	usage_with_options_internal(usagestr, opts, 0);
+	exit(129);
 }
 
+int parse_options_usage(const char * const *usagestr,
+			const struct option *opts)
+{
+	return usage_with_options_internal(usagestr, opts, 0);
+}
+
+
 /*----- some often used options -----*/
 #include "cache.h"
 
diff --git a/parse-options.h b/parse-options.h
index 13ad158..5199950 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -20,6 +20,7 @@
 enum parse_opt_flags {
 	PARSE_OPT_KEEP_DASHDASH = 1,
 	PARSE_OPT_STOP_AT_NON_OPTION = 2,
+	PARSE_OPT_KEEP_ARGV0 = 4,
 };
 
 enum parse_opt_option_flags {
@@ -27,6 +28,7 @@
 	PARSE_OPT_NOARG   = 2,
 	PARSE_OPT_NONEG   = 4,
 	PARSE_OPT_HIDDEN  = 8,
+	PARSE_OPT_LASTARG_DEFAULT = 16,
 };
 
 struct option;
@@ -111,6 +113,40 @@
 extern NORETURN void usage_with_options(const char * const *usagestr,
                                         const struct option *options);
 
+/*----- incremantal advanced APIs -----*/
+
+enum {
+	PARSE_OPT_HELP = -1,
+	PARSE_OPT_DONE,
+	PARSE_OPT_UNKNOWN,
+};
+
+/*
+ * It's okay for the caller to consume argv/argc in the usual way.
+ * Other fields of that structure are private to parse-options and should not
+ * be modified in any way.
+ */
+struct parse_opt_ctx_t {
+	const char **argv;
+	const char **out;
+	int argc, cpidx;
+	const char *opt;
+	int flags;
+};
+
+extern int parse_options_usage(const char * const *usagestr,
+			       const struct option *opts);
+
+extern void parse_options_start(struct parse_opt_ctx_t *ctx,
+				int argc, const char **argv, int flags);
+
+extern int parse_options_step(struct parse_opt_ctx_t *ctx,
+			      const struct option *options,
+			      const char * const usagestr[]);
+
+extern int parse_options_end(struct parse_opt_ctx_t *ctx);
+
+
 /*----- some often used options -----*/
 extern int parse_opt_abbrev_cb(const struct option *, const char *, int);
 extern int parse_opt_approxidate_cb(const struct option *, const char *, int);
diff --git a/path-list.c b/path-list.c
deleted file mode 100644
index 92e5cf2..0000000
--- a/path-list.c
+++ /dev/null
@@ -1,134 +0,0 @@
-#include "cache.h"
-#include "path-list.h"
-
-/* if there is no exact match, point to the index where the entry could be
- * inserted */
-static int get_entry_index(const struct path_list *list, const char *path,
-		int *exact_match)
-{
-	int left = -1, right = list->nr;
-
-	while (left + 1 < right) {
-		int middle = (left + right) / 2;
-		int compare = strcmp(path, list->items[middle].path);
-		if (compare < 0)
-			right = middle;
-		else if (compare > 0)
-			left = middle;
-		else {
-			*exact_match = 1;
-			return middle;
-		}
-	}
-
-	*exact_match = 0;
-	return right;
-}
-
-/* returns -1-index if already exists */
-static int add_entry(struct path_list *list, const char *path)
-{
-	int exact_match;
-	int index = get_entry_index(list, path, &exact_match);
-
-	if (exact_match)
-		return -1 - index;
-
-	if (list->nr + 1 >= list->alloc) {
-		list->alloc += 32;
-		list->items = xrealloc(list->items, list->alloc
-				* sizeof(struct path_list_item));
-	}
-	if (index < list->nr)
-		memmove(list->items + index + 1, list->items + index,
-				(list->nr - index)
-				* sizeof(struct path_list_item));
-	list->items[index].path = list->strdup_paths ?
-		xstrdup(path) : (char *)path;
-	list->items[index].util = NULL;
-	list->nr++;
-
-	return index;
-}
-
-struct path_list_item *path_list_insert(const char *path, struct path_list *list)
-{
-	int index = add_entry(list, path);
-
-	if (index < 0)
-		index = -1 - index;
-
-	return list->items + index;
-}
-
-int path_list_has_path(const struct path_list *list, const char *path)
-{
-	int exact_match;
-	get_entry_index(list, path, &exact_match);
-	return exact_match;
-}
-
-struct path_list_item *path_list_lookup(const char *path, struct path_list *list)
-{
-	int exact_match, i = get_entry_index(list, path, &exact_match);
-	if (!exact_match)
-		return NULL;
-	return list->items + i;
-}
-
-void path_list_clear(struct path_list *list, int free_util)
-{
-	if (list->items) {
-		int i;
-		if (list->strdup_paths) {
-			for (i = 0; i < list->nr; i++)
-				free(list->items[i].path);
-		}
-		if (free_util) {
-			for (i = 0; i < list->nr; i++)
-				free(list->items[i].util);
-		}
-		free(list->items);
-	}
-	list->items = NULL;
-	list->nr = list->alloc = 0;
-}
-
-void print_path_list(const char *text, const struct path_list *p)
-{
-	int i;
-	if ( text )
-		printf("%s\n", text);
-	for (i = 0; i < p->nr; i++)
-		printf("%s:%p\n", p->items[i].path, p->items[i].util);
-}
-
-struct path_list_item *path_list_append(const char *path, struct path_list *list)
-{
-	ALLOC_GROW(list->items, list->nr + 1, list->alloc);
-	list->items[list->nr].path =
-		list->strdup_paths ? xstrdup(path) : (char *)path;
-	return list->items + list->nr++;
-}
-
-static int cmp_items(const void *a, const void *b)
-{
-	const struct path_list_item *one = a;
-	const struct path_list_item *two = b;
-	return strcmp(one->path, two->path);
-}
-
-void sort_path_list(struct path_list *list)
-{
-	qsort(list->items, list->nr, sizeof(*list->items), cmp_items);
-}
-
-int unsorted_path_list_has_path(struct path_list *list, const char *path)
-{
-	int i;
-	for (i = 0; i < list->nr; i++)
-		if (!strcmp(path, list->items[i].path))
-			return 1;
-	return 0;
-}
-
diff --git a/path-list.h b/path-list.h
deleted file mode 100644
index ca2cbba..0000000
--- a/path-list.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef PATH_LIST_H
-#define PATH_LIST_H
-
-struct path_list_item {
-	char *path;
-	void *util;
-};
-struct path_list
-{
-	struct path_list_item *items;
-	unsigned int nr, alloc;
-	unsigned int strdup_paths:1;
-};
-
-void print_path_list(const char *text, const struct path_list *p);
-void path_list_clear(struct path_list *list, int free_util);
-
-/* Use these functions only on sorted lists: */
-int path_list_has_path(const struct path_list *list, const char *path);
-struct path_list_item *path_list_insert(const char *path, struct path_list *list);
-struct path_list_item *path_list_lookup(const char *path, struct path_list *list);
-
-/* Use these functions only on unsorted lists: */
-struct path_list_item *path_list_append(const char *path, struct path_list *list);
-void sort_path_list(struct path_list *list);
-int unsorted_path_list_has_path(struct path_list *list, const char *path);
-
-#endif /* PATH_LIST_H */
diff --git a/path.c b/path.c
index c1d5679..a074aea 100644
--- a/path.c
+++ b/path.c
@@ -32,6 +32,60 @@
 	return path;
 }
 
+char *mksnpath(char *buf, size_t n, const char *fmt, ...)
+{
+	va_list args;
+	unsigned len;
+
+	va_start(args, fmt);
+	len = vsnprintf(buf, n, fmt, args);
+	va_end(args);
+	if (len >= n) {
+		strlcpy(buf, bad_path, n);
+		return buf;
+	}
+	return cleanup_path(buf);
+}
+
+static char *git_vsnpath(char *buf, size_t n, const char *fmt, va_list args)
+{
+	const char *git_dir = get_git_dir();
+	size_t len;
+
+	len = strlen(git_dir);
+	if (n < len + 1)
+		goto bad;
+	memcpy(buf, git_dir, len);
+	if (len && !is_dir_sep(git_dir[len-1]))
+		buf[len++] = '/';
+	len += vsnprintf(buf + len, n - len, fmt, args);
+	if (len >= n)
+		goto bad;
+	return cleanup_path(buf);
+bad:
+	strlcpy(buf, bad_path, n);
+	return buf;
+}
+
+char *git_snpath(char *buf, size_t n, const char *fmt, ...)
+{
+	va_list args;
+	va_start(args, fmt);
+	(void)git_vsnpath(buf, n, fmt, args);
+	va_end(args);
+	return buf;
+}
+
+char *git_pathdup(const char *fmt, ...)
+{
+	char path[PATH_MAX];
+	va_list args;
+	va_start(args, fmt);
+	(void)git_vsnpath(path, sizeof(path), fmt, args);
+	va_end(args);
+	return xstrdup(path);
+}
+
 char *mkpath(const char *fmt, ...)
 {
 	va_list args;
@@ -291,45 +345,6 @@
 	return 0;
 }
 
-static const char *get_pwd_cwd(void)
-{
-	static char cwd[PATH_MAX + 1];
-	char *pwd;
-	struct stat cwd_stat, pwd_stat;
-	if (getcwd(cwd, PATH_MAX) == NULL)
-		return NULL;
-	pwd = getenv("PWD");
-	if (pwd && strcmp(pwd, cwd)) {
-		stat(cwd, &cwd_stat);
-		if (!stat(pwd, &pwd_stat) &&
-		    pwd_stat.st_dev == cwd_stat.st_dev &&
-		    pwd_stat.st_ino == cwd_stat.st_ino) {
-			strlcpy(cwd, pwd, PATH_MAX);
-		}
-	}
-	return cwd;
-}
-
-const char *make_nonrelative_path(const char *path)
-{
-	static char buf[PATH_MAX + 1];
-
-	if (is_absolute_path(path)) {
-		if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
-			die ("Too long path: %.*s", 60, path);
-	} else {
-		const char *cwd = get_pwd_cwd();
-		if (!cwd)
-			die("Cannot determine the current working directory");
-		if (snprintf(buf, PATH_MAX, "%s/%s", cwd, path) >= PATH_MAX)
-			die ("Too long path: %.*s", 60, path);
-	}
-	return buf;
-}
-
-/* We allow "recursive" symbolic links. Only within reason, though. */
-#define MAXDEPTH 5
-
 const char *make_relative_path(const char *abs, const char *base)
 {
 	static char buf[PATH_MAX + 1];
@@ -347,66 +362,98 @@
 	return buf;
 }
 
-const char *make_absolute_path(const char *path)
+/*
+ * path = absolute path
+ * buf = buffer of at least max(2, strlen(path)+1) bytes
+ * It is okay if buf == path, but they should not overlap otherwise.
+ *
+ * Performs the following normalizations on path, storing the result in buf:
+ * - Removes trailing slashes.
+ * - Removes empty components.
+ * - Removes "." components.
+ * - Removes ".." components, and the components the precede them.
+ * "" and paths that contain only slashes are normalized to "/".
+ * Returns the length of the output.
+ *
+ * Note that this function is purely textual.  It does not follow symlinks,
+ * verify the existence of the path, or make any system calls.
+ */
+int normalize_absolute_path(char *buf, const char *path)
 {
-	static char bufs[2][PATH_MAX + 1], *buf = bufs[0], *next_buf = bufs[1];
-	char cwd[1024] = "";
-	int buf_index = 1, len;
+	const char *comp_start = path, *comp_end = path;
+	char *dst = buf;
+	int comp_len;
+	assert(buf);
+	assert(path);
 
-	int depth = MAXDEPTH;
-	char *last_elem = NULL;
-	struct stat st;
+	while (*comp_start) {
+		assert(*comp_start == '/');
+		while (*++comp_end && *comp_end != '/')
+			; /* nothing */
+		comp_len = comp_end - comp_start;
 
-	if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
-		die ("Too long path: %.*s", 60, path);
+		if (!strncmp("/",  comp_start, comp_len) ||
+		    !strncmp("/.", comp_start, comp_len))
+			goto next;
 
-	while (depth--) {
-		if (stat(buf, &st) || !S_ISDIR(st.st_mode)) {
-			char *last_slash = strrchr(buf, '/');
-			if (last_slash) {
-				*last_slash = '\0';
-				last_elem = xstrdup(last_slash + 1);
-			} else {
-				last_elem = xstrdup(buf);
-				*buf = '\0';
-			}
+		if (!strncmp("/..", comp_start, comp_len)) {
+			while (dst > buf && *--dst != '/')
+				; /* nothing */
+			goto next;
 		}
 
-		if (*buf) {
-			if (!*cwd && !getcwd(cwd, sizeof(cwd)))
-				die ("Could not get current working directory");
-
-			if (chdir(buf))
-				die ("Could not switch to '%s'", buf);
-		}
-		if (!getcwd(buf, PATH_MAX))
-			die ("Could not get current working directory");
-
-		if (last_elem) {
-			int len = strlen(buf);
-			if (len + strlen(last_elem) + 2 > PATH_MAX)
-				die ("Too long path name: '%s/%s'",
-						buf, last_elem);
-			buf[len] = '/';
-			strcpy(buf + len + 1, last_elem);
-			free(last_elem);
-			last_elem = NULL;
-		}
-
-		if (!lstat(buf, &st) && S_ISLNK(st.st_mode)) {
-			len = readlink(buf, next_buf, PATH_MAX);
-			if (len < 0)
-				die ("Invalid symlink: %s", buf);
-			next_buf[len] = '\0';
-			buf = next_buf;
-			buf_index = 1 - buf_index;
-			next_buf = bufs[buf_index];
-		} else
-			break;
+		memmove(dst, comp_start, comp_len);
+		dst += comp_len;
+	next:
+		comp_start = comp_end;
 	}
 
-	if (*cwd && chdir(cwd))
-		die ("Could not change back to '%s'", cwd);
+	if (dst == buf)
+		*dst++ = '/';
 
-	return buf;
+	*dst = '\0';
+	return dst - buf;
+}
+
+/*
+ * path = Canonical absolute path
+ * prefix_list = Colon-separated list of absolute paths
+ *
+ * Determines, for each path in prefix_list, whether the "prefix" really
+ * is an ancestor directory of path.  Returns the length of the longest
+ * ancestor directory, excluding any trailing slashes, or -1 if no prefix
+ * is an ancestor.  (Note that this means 0 is returned if prefix_list is
+ * "/".) "/foo" is not considered an ancestor of "/foobar".  Directories
+ * are not considered to be their own ancestors.  path must be in a
+ * canonical form: empty components, or "." or ".." components are not
+ * allowed.  prefix_list may be null, which is like "".
+ */
+int longest_ancestor_length(const char *path, const char *prefix_list)
+{
+	char buf[PATH_MAX+1];
+	const char *ceil, *colon;
+	int len, max_len = -1;
+
+	if (prefix_list == NULL || !strcmp(path, "/"))
+		return -1;
+
+	for (colon = ceil = prefix_list; *colon; ceil = colon+1) {
+		for (colon = ceil; *colon && *colon != ':'; colon++);
+		len = colon - ceil;
+		if (len == 0 || len > PATH_MAX || !is_absolute_path(ceil))
+			continue;
+		strlcpy(buf, ceil, len+1);
+		len = normalize_absolute_path(buf, buf);
+		/* Strip "trailing slashes" from "/". */
+		if (len == 1)
+			len = 0;
+
+		if (!strncmp(path, buf, len) &&
+		    path[len] == '/' &&
+		    len > max_len) {
+			max_len = len;
+		}
+	}
+
+	return max_len;
 }
diff --git a/perl/Git.pm b/perl/Git.pm
index 97e61ef..ba94453 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -56,7 +56,9 @@
 @EXPORT_OK = qw(command command_oneline command_noisy
                 command_output_pipe command_input_pipe command_close_pipe
                 command_bidi_pipe command_close_bidi_pipe
-                version exec_path hash_object git_cmd_try);
+                version exec_path hash_object git_cmd_try
+                remote_refs
+                temp_acquire temp_release temp_reset temp_path);
 
 
 =head1 DESCRIPTION
@@ -89,7 +91,7 @@
 Currently, the module merely wraps calls to external Git tools. In the future,
 it will provide a much faster way to interact with Git by linking directly
 to libgit. This should be completely opaque to the user, though (performance
-increate nonwithstanding).
+increase notwithstanding).
 
 =cut
 
@@ -98,7 +100,7 @@
 use Error qw(:try);
 use Cwd qw(abs_path);
 use IPC::Open2 qw(open2);
-
+use Fcntl qw(SEEK_SET SEEK_CUR);
 }
 
 
@@ -416,6 +418,7 @@
 =cut
 
 sub command_close_bidi_pipe {
+	local $?;
 	my ($pid, $in, $out, $ctx) = @_;
 	foreach my $fh ($in, $out) {
 		unless (close $fh) {
@@ -668,6 +671,59 @@
 	return $color;
 }
 
+=item remote_refs ( REPOSITORY [, GROUPS [, REFGLOBS ] ] )
+
+This function returns a hashref of refs stored in a given remote repository.
+The hash is in the format C<refname =\> hash>. For tags, the C<refname> entry
+contains the tag object while a C<refname^{}> entry gives the tagged objects.
+
+C<REPOSITORY> has the same meaning as the appropriate C<git-ls-remote>
+argument; either an URL or a remote name (if called on a repository instance).
+C<GROUPS> is an optional arrayref that can contain 'tags' to return all the
+tags and/or 'heads' to return all the heads. C<REFGLOB> is an optional array
+of strings containing a shell-like glob to further limit the refs returned in
+the hash; the meaning is again the same as the appropriate C<git-ls-remote>
+argument.
+
+This function may or may not be called on a repository instance. In the former
+case, remote names as defined in the repository are recognized as repository
+specifiers.
+
+=cut
+
+sub remote_refs {
+	my ($self, $repo, $groups, $refglobs) = _maybe_self(@_);
+	my @args;
+	if (ref $groups eq 'ARRAY') {
+		foreach (@$groups) {
+			if ($_ eq 'heads') {
+				push (@args, '--heads');
+			} elsif ($_ eq 'tags') {
+				push (@args, '--tags');
+			} else {
+				# Ignore unknown groups for future
+				# compatibility
+			}
+		}
+	}
+	push (@args, $repo);
+	if (ref $refglobs eq 'ARRAY') {
+		push (@args, @$refglobs);
+	}
+
+	my @self = $self ? ($self) : (); # Ultra trickery
+	my ($fh, $ctx) = Git::command_output_pipe(@self, 'ls-remote', @args);
+	my %refs;
+	while (<$fh>) {
+		chomp;
+		my ($hash, $ref) = split(/\t/, $_, 2);
+		$refs{$ref} = $hash;
+	}
+	Git::command_close_pipe(@self, $fh, $ctx);
+	return \%refs;
+}
+
+
 =item ident ( TYPE | IDENTSTR )
 
 =item ident_person ( TYPE | IDENTSTR | IDENTARRAY )
@@ -676,7 +732,7 @@
 in the commit and tag objects or produced by C<var GIT_type_IDENT> (thus
 C<TYPE> can be either I<author> or I<committer>; case is insignificant).
 
-The C<ident> method retrieves the ident information from C<git-var>
+The C<ident> method retrieves the ident information from C<git var>
 and either returns it as a scalar string or as an array with the fields parsed.
 Alternatively, it can take a prepared ident string (e.g. from the commit
 object) and just parse it.
@@ -785,8 +841,8 @@
 
 	my @vars = map { 'hash_object_' . $_ } qw(pid in out ctx);
 
-	command_close_bidi_pipe($self->{@vars});
-	delete $self->{@vars};
+	command_close_bidi_pipe(@$self{@vars});
+	delete @$self{@vars};
 }
 
 =item cat_blob ( SHA1, FILEHANDLE )
@@ -874,10 +930,153 @@
 
 	my @vars = map { 'cat_blob_' . $_ } qw(pid in out ctx);
 
-	command_close_bidi_pipe($self->{@vars});
-	delete $self->{@vars};
+	command_close_bidi_pipe(@$self{@vars});
+	delete @$self{@vars};
 }
 
+
+{ # %TEMP_* Lexical Context
+
+my (%TEMP_FILEMAP, %TEMP_FILES);
+
+=item temp_acquire ( NAME )
+
+Attempts to retreive the temporary file mapped to the string C<NAME>. If an
+associated temp file has not been created this session or was closed, it is
+created, cached, and set for autoflush and binmode.
+
+Internally locks the file mapped to C<NAME>. This lock must be released with
+C<temp_release()> when the temp file is no longer needed. Subsequent attempts
+to retrieve temporary files mapped to the same C<NAME> while still locked will
+cause an error. This locking mechanism provides a weak guarantee and is not
+threadsafe. It does provide some error checking to help prevent temp file refs
+writing over one another.
+
+In general, the L<File::Handle> returned should not be closed by consumers as
+it defeats the purpose of this caching mechanism. If you need to close the temp
+file handle, then you should use L<File::Temp> or another temp file faculty
+directly. If a handle is closed and then requested again, then a warning will
+issue.
+
+=cut
+
+sub temp_acquire {
+	my ($self, $name) = _maybe_self(@_);
+
+	my $temp_fd = _temp_cache($name);
+
+	$TEMP_FILES{$temp_fd}{locked} = 1;
+	$temp_fd;
+}
+
+=item temp_release ( NAME )
+
+=item temp_release ( FILEHANDLE )
+
+Releases a lock acquired through C<temp_acquire()>. Can be called either with
+the C<NAME> mapping used when acquiring the temp file or with the C<FILEHANDLE>
+referencing a locked temp file.
+
+Warns if an attempt is made to release a file that is not locked.
+
+The temp file will be truncated before being released. This can help to reduce
+disk I/O where the system is smart enough to detect the truncation while data
+is in the output buffers. Beware that after the temp file is released and
+truncated, any operations on that file may fail miserably until it is
+re-acquired. All contents are lost between each release and acquire mapped to
+the same string.
+
+=cut
+
+sub temp_release {
+	my ($self, $temp_fd, $trunc) = _maybe_self(@_);
+
+	if (exists $TEMP_FILEMAP{$temp_fd}) {
+		$temp_fd = $TEMP_FILES{$temp_fd};
+	}
+	unless ($TEMP_FILES{$temp_fd}{locked}) {
+		carp "Attempt to release temp file '",
+			$temp_fd, "' that has not been locked";
+	}
+	temp_reset($temp_fd) if $trunc and $temp_fd->opened;
+
+	$TEMP_FILES{$temp_fd}{locked} = 0;
+	undef;
+}
+
+sub _temp_cache {
+	my ($name) = @_;
+
+	_verify_require();
+
+	my $temp_fd = \$TEMP_FILEMAP{$name};
+	if (defined $$temp_fd and $$temp_fd->opened) {
+		if ($TEMP_FILES{$$temp_fd}{locked}) {
+			throw Error::Simple("Temp file with moniker '",
+				$name, "' already in use");
+		}
+	} else {
+		if (defined $$temp_fd) {
+			# then we're here because of a closed handle.
+			carp "Temp file '", $name,
+				"' was closed. Opening replacement.";
+		}
+		my $fname;
+		($$temp_fd, $fname) = File::Temp->tempfile(
+			'Git_XXXXXX', UNLINK => 1
+			) or throw Error::Simple("couldn't open new temp file");
+		$$temp_fd->autoflush;
+		binmode $$temp_fd;
+		$TEMP_FILES{$$temp_fd}{fname} = $fname;
+	}
+	$$temp_fd;
+}
+
+sub _verify_require {
+	eval { require File::Temp; require File::Spec; };
+	$@ and throw Error::Simple($@);
+}
+
+=item temp_reset ( FILEHANDLE )
+
+Truncates and resets the position of the C<FILEHANDLE>.
+
+=cut
+
+sub temp_reset {
+	my ($self, $temp_fd) = _maybe_self(@_);
+
+	truncate $temp_fd, 0
+		or throw Error::Simple("couldn't truncate file");
+	sysseek($temp_fd, 0, SEEK_SET) and seek($temp_fd, 0, SEEK_SET)
+		or throw Error::Simple("couldn't seek to beginning of file");
+	sysseek($temp_fd, 0, SEEK_CUR) == 0 and tell($temp_fd) == 0
+		or throw Error::Simple("expected file position to be reset");
+}
+
+=item temp_path ( NAME )
+
+=item temp_path ( FILEHANDLE )
+
+Returns the filename associated with the given tempfile.
+
+=cut
+
+sub temp_path {
+	my ($self, $temp_fd) = _maybe_self(@_);
+
+	if (exists $TEMP_FILEMAP{$temp_fd}) {
+		$temp_fd = $TEMP_FILEMAP{$temp_fd};
+	}
+	$TEMP_FILES{$temp_fd}{fname};
+}
+
+sub END {
+	unlink values %TEMP_FILEMAP if %TEMP_FILEMAP;
+}
+
+} # %TEMP_* Lexical Context
+
 =back
 
 =head1 ERROR HANDLING
@@ -1004,8 +1203,7 @@
 # the method was called upon an instance and (undef, @args) if
 # it was called directly.
 sub _maybe_self {
-	# This breaks inheritance. Oh well.
-	ref $_[0] eq 'Git' ? @_ : (undef, @_);
+	UNIVERSAL::isa($_[0], 'Git') ? @_ : (undef, @_);
 }
 
 # Check if the command id is something reasonable.
diff --git a/perl/Makefile b/perl/Makefile
index 5e079ad..e3dd1a5 100644
--- a/perl/Makefile
+++ b/perl/Makefile
@@ -22,13 +22,18 @@
 ifdef NO_PERL_MAKEMAKER
 instdir_SQ = $(subst ','\'',$(prefix)/lib)
 $(makfile): ../GIT-CFLAGS Makefile
-	echo all: > $@
-	echo '	:' >> $@
+	echo all: private-Error.pm Git.pm > $@
+	echo '	mkdir -p blib/lib' >> $@
+	echo '	$(RM) blib/lib/Git.pm; cp Git.pm blib/lib/' >> $@
+	echo '	$(RM) blib/lib/Error.pm' >> $@
+	'$(PERL_PATH_SQ)' -MError -e 'exit($$Error::VERSION < 0.15009)' || \
+	echo '	cp private-Error.pm blib/lib/Error.pm' >> $@
 	echo install: >> $@
-	echo '	mkdir -p $(instdir_SQ)' >> $@
-	echo '	$(RM) $(instdir_SQ)/Git.pm; cp Git.pm $(instdir_SQ)' >> $@
-	echo '	$(RM) $(instdir_SQ)/Error.pm; \
-	cp private-Error.pm $(instdir_SQ)/Error.pm' >> $@
+	echo '	mkdir -p "$(instdir_SQ)"' >> $@
+	echo '	$(RM) "$(instdir_SQ)/Git.pm"; cp Git.pm "$(instdir_SQ)"' >> $@
+	echo '	$(RM) "$(instdir_SQ)/Error.pm"' >> $@
+	'$(PERL_PATH_SQ)' -MError -e 'exit($$Error::VERSION < 0.15009)' || \
+	echo '	cp private-Error.pm "$(instdir_SQ)/Error.pm"' >> $@
 	echo instlibdir: >> $@
 	echo '	echo $(instdir_SQ)' >> $@
 else
diff --git a/pretty.c b/pretty.c
index 628a520..a29c290 100644
--- a/pretty.c
+++ b/pretty.c
@@ -3,7 +3,7 @@
 #include "utf8.h"
 #include "diff.h"
 #include "revision.h"
-#include "path-list.h"
+#include "string-list.h"
 #include "mailmap.h"
 
 static char *user_format;
@@ -292,7 +292,7 @@
 
 static int mailmap_name(struct strbuf *sb, const char *email)
 {
-	static struct path_list *mail_map;
+	static struct string_list *mail_map;
 	char buffer[1024];
 
 	if (!mail_map) {
@@ -310,7 +310,7 @@
 }
 
 static size_t format_person_part(struct strbuf *sb, char part,
-                               const char *msg, int len)
+				 const char *msg, int len, enum date_mode dmode)
 {
 	/* currently all placeholders have same length */
 	const int placeholder_len = 2;
@@ -377,7 +377,7 @@
 
 	switch (part) {
 	case 'd':	/* date */
-		strbuf_addstr(sb, show_date(date, tz, DATE_NORMAL));
+		strbuf_addstr(sb, show_date(date, tz, dmode));
 		return placeholder_len;
 	case 'D':	/* date, RFC2822 style */
 		strbuf_addstr(sb, show_date(date, tz, DATE_RFC2822));
@@ -409,6 +409,7 @@
 
 struct format_commit_context {
 	const struct commit *commit;
+	enum date_mode dmode;
 
 	/* These offsets are relative to the start of the commit message. */
 	int commit_header_parsed;
@@ -584,10 +585,12 @@
 		return 1;
 	case 'a':	/* author ... */
 		return format_person_part(sb, placeholder[1],
-		                   msg + c->author.off, c->author.len);
+				   msg + c->author.off, c->author.len,
+				   c->dmode);
 	case 'c':	/* committer ... */
 		return format_person_part(sb, placeholder[1],
-		                   msg + c->committer.off, c->committer.len);
+				   msg + c->committer.off, c->committer.len,
+				   c->dmode);
 	case 'e':	/* encoding */
 		strbuf_add(sb, msg + c->encoding.off, c->encoding.len);
 		return 1;
@@ -599,12 +602,14 @@
 }
 
 void format_commit_message(const struct commit *commit,
-                           const void *format, struct strbuf *sb)
+			   const void *format, struct strbuf *sb,
+			   enum date_mode dmode)
 {
 	struct format_commit_context context;
 
 	memset(&context, 0, sizeof(context));
 	context.commit = commit;
+	context.dmode = dmode;
 	strbuf_expand(sb, format, format_commit_item, &context);
 }
 
@@ -770,7 +775,7 @@
 	const char *encoding;
 
 	if (fmt == CMIT_FMT_USERFORMAT) {
-		format_commit_message(commit, user_format, sb);
+		format_commit_message(commit, user_format, sb, dmode);
 		return;
 	}
 
diff --git a/quote.c b/quote.c
index d5cf9d8..6a52085 100644
--- a/quote.c
+++ b/quote.c
@@ -1,6 +1,8 @@
 #include "cache.h"
 #include "quote.h"
 
+int quote_path_fully = 1;
+
 /* Help to copy the thing properly quoted for the shell safety.
  * any single quote is replaced with '\'', any exclamation point
  * is replaced with '\!', and the whole thing is enclosed in a
diff --git a/read-cache.c b/read-cache.c
index f83de8c..525d138 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -38,6 +38,22 @@
 	istate->cache_changed = 1;
 }
 
+void rename_index_entry_at(struct index_state *istate, int nr, const char *new_name)
+{
+	struct cache_entry *old = istate->cache[nr], *new;
+	int namelen = strlen(new_name);
+
+	new = xmalloc(cache_entry_size(namelen));
+	copy_cache_entry(new, old);
+	new->ce_flags &= ~(CE_STATE_MASK | CE_NAMEMASK);
+	new->ce_flags |= (namelen >= CE_NAMEMASK ? CE_NAMEMASK : namelen);
+	memcpy(new->name, new_name, namelen + 1);
+
+	cache_tree_invalidate_path(istate->cache_tree, old->name);
+	remove_index_entry_at(istate, nr);
+	add_index_entry(istate, new, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);
+}
+
 /*
  * This only updates the "non-critical" parts of the directory
  * cache, ie the parts that aren't tracked by GIT, and only used
@@ -131,7 +147,7 @@
 		break;
 	case S_IFDIR:
 		if (S_ISGITLINK(ce->ce_mode))
-			return 0;
+			return ce_compare_gitlink(ce) ? DATA_CHANGED : 0;
 	default:
 		return TYPE_CHANGED;
 	}
@@ -171,6 +187,7 @@
 			changed |= TYPE_CHANGED;
 		break;
 	case S_IFGITLINK:
+		/* We ignore most of the st_xxx fields for gitlinks */
 		if (!S_ISDIR(st->st_mode))
 			changed |= TYPE_CHANGED;
 		else if (ce_compare_gitlink(ce))
@@ -181,7 +198,7 @@
 	}
 	if (ce->ce_mtime != (unsigned int) st->st_mtime)
 		changed |= MTIME_CHANGED;
-	if (ce->ce_ctime != (unsigned int) st->st_ctime)
+	if (trust_ctime && ce->ce_ctime != (unsigned int) st->st_ctime)
 		changed |= CTIME_CHANGED;
 
 	if (ce->ce_uid != (unsigned int) st->st_uid ||
@@ -277,11 +294,22 @@
 	if (changed & (MODE_CHANGED | TYPE_CHANGED))
 		return changed;
 
-	/* Immediately after read-tree or update-index --cacheinfo,
-	 * the length field is zero.  For other cases the ce_size
-	 * should match the SHA1 recorded in the index entry.
+	/*
+	 * Immediately after read-tree or update-index --cacheinfo,
+	 * the length field is zero, as we have never even read the
+	 * lstat(2) information once, and we cannot trust DATA_CHANGED
+	 * returned by ie_match_stat() which in turn was returned by
+	 * ce_match_stat_basic() to signal that the filesize of the
+	 * blob changed.  We have to actually go to the filesystem to
+	 * see if the contents match, and if so, should answer "unchanged".
+	 *
+	 * The logic does not apply to gitlinks, as ce_match_stat_basic()
+	 * already has checked the actual HEAD from the filesystem in the
+	 * subproject.  If ie_match_stat() already said it is different,
+	 * then we know it is.
 	 */
-	if ((changed & DATA_CHANGED) && ce->ce_size != 0)
+	if ((changed & DATA_CHANGED) &&
+	    (S_ISGITLINK(ce->ce_mode) || ce->ce_size != 0))
 		return changed;
 
 	changed_fs = ce_modified_check_fs(ce, st);
@@ -528,7 +556,7 @@
 		ce = create_alias_ce(ce, alias);
 	ce->ce_flags |= CE_ADDED;
 
-	/* It was suspected to be recily clean, but it turns out to be Ok */
+	/* It was suspected to be racily clean, but it turns out to be Ok */
 	was_same = (alias &&
 		    !ce_stage(alias) &&
 		    !hashcmp(alias->sha1, ce->sha1) &&
@@ -980,7 +1008,10 @@
 	int not_new = (flags & REFRESH_IGNORE_MISSING) != 0;
 	int ignore_submodules = (flags & REFRESH_IGNORE_SUBMODULES) != 0;
 	unsigned int options = really ? CE_MATCH_IGNORE_VALID : 0;
+	const char *needs_update_message;
 
+	needs_update_message = ((flags & REFRESH_SAY_CHANGED)
+				? "locally modified" : "needs update");
 	for (i = 0; i < istate->cache_nr; i++) {
 		struct cache_entry *ce, *new;
 		int cache_errno = 0;
@@ -1019,7 +1050,7 @@
 			}
 			if (quiet)
 				continue;
-			printf("%s: needs update\n", ce->name);
+			printf("%s: %s\n", ce->name, needs_update_message);
 			has_errors = 1;
 			continue;
 		}
@@ -1124,7 +1155,7 @@
 	size_t mmap_size;
 
 	errno = EBUSY;
-	if (istate->alloc)
+	if (istate->initialized)
 		return istate->cache_nr;
 
 	errno = ENOENT;
@@ -1164,6 +1195,7 @@
 	 * index size
 	 */
 	istate->alloc = xmalloc(estimate_cache_size(mmap_size, istate->cache_nr));
+	istate->initialized = 1;
 
 	src_offset = sizeof(*hdr);
 	dst_offset = 0;
@@ -1207,15 +1239,22 @@
 	die("index file corrupt");
 }
 
+int is_index_unborn(struct index_state *istate)
+{
+	return (!istate->cache_nr && !istate->alloc && !istate->timestamp);
+}
+
 int discard_index(struct index_state *istate)
 {
 	istate->cache_nr = 0;
 	istate->cache_changed = 0;
 	istate->timestamp = 0;
+	istate->name_hash_initialized = 0;
 	free_hash(&istate->name_hash);
 	cache_tree_free(&(istate->cache_tree));
 	free(istate->alloc);
 	istate->alloc = NULL;
+	istate->initialized = 0;
 
 	/* no need to throw away allocated active_cache */
 	return 0;
@@ -1307,6 +1346,11 @@
 	 * falsely clean entry due to touch-update-touch race, so we leave
 	 * everything else as they are.  We are called for entries whose
 	 * ce_mtime match the index file mtime.
+	 *
+	 * Note that this actually does not do much for gitlinks, for
+	 * which ce_match_stat_basic() always goes to the actual
+	 * contents.  The caller checks with is_racy_timestamp() which
+	 * always says "no" for gitlinks, so we are not called for them ;-)
 	 */
 	struct stat st;
 
@@ -1410,3 +1454,67 @@
 	}
 	return ce_flush(&c, newfd);
 }
+
+/*
+ * Read the index file that is potentially unmerged into given
+ * index_state, dropping any unmerged entries.  Returns true is
+ * the index is unmerged.  Callers who want to refuse to work
+ * from an unmerged state can call this and check its return value,
+ * instead of calling read_cache().
+ */
+int read_index_unmerged(struct index_state *istate)
+{
+	int i;
+	int unmerged = 0;
+
+	read_index(istate);
+	for (i = 0; i < istate->cache_nr; i++) {
+		struct cache_entry *ce = istate->cache[i];
+		struct cache_entry *new_ce;
+		int size, len;
+
+		if (!ce_stage(ce))
+			continue;
+		unmerged = 1;
+		len = strlen(ce->name);
+		size = cache_entry_size(len);
+		new_ce = xcalloc(1, size);
+		hashcpy(new_ce->sha1, ce->sha1);
+		memcpy(new_ce->name, ce->name, len);
+		new_ce->ce_flags = create_ce_flags(len, 0);
+		new_ce->ce_mode = ce->ce_mode;
+		if (add_index_entry(istate, new_ce, 0))
+			return error("%s: cannot drop to stage #0",
+				     ce->name);
+		i = index_name_pos(istate, new_ce->name, len);
+	}
+	return unmerged;
+}
+
+/*
+ * Returns 1 if the path is an "other" path with respect to
+ * the index; that is, the path is not mentioned in the index at all,
+ * either as a file, a directory with some files in the index,
+ * or as an unmerged entry.
+ *
+ * We helpfully remove a trailing "/" from directories so that
+ * the output of read_directory can be used as-is.
+ */
+int index_name_is_other(const struct index_state *istate, const char *name,
+		int namelen)
+{
+	int pos;
+	if (namelen && name[namelen - 1] == '/')
+		namelen--;
+	pos = index_name_pos(istate, name, namelen);
+	if (0 <= pos)
+		return 0;	/* exact match */
+	pos = -pos - 1;
+	if (pos < istate->cache_nr) {
+		struct cache_entry *ce = istate->cache[pos];
+		if (ce_namelen(ce) == namelen &&
+		    !memcmp(ce->name, name, namelen))
+			return 0; /* Yup, this one exists unmerged */
+	}
+	return 1;
+}
diff --git a/receive-pack.c b/receive-pack.c
index b26f2e3..f0145bd 100644
--- a/receive-pack.c
+++ b/receive-pack.c
@@ -222,7 +222,7 @@
 			warning ("Allowing deletion of corrupt ref.");
 			old_sha1 = NULL;
 		}
-		if (delete_ref(name, old_sha1)) {
+		if (delete_ref(name, old_sha1, 0)) {
 			error("failed to delete %s", name);
 			return "failed to delete";
 		}
@@ -370,7 +370,8 @@
 	hdr_err = parse_pack_header(&hdr);
 	if (hdr_err)
 		return hdr_err;
-	snprintf(hdr_arg, sizeof(hdr_arg), "--pack_header=%u,%u",
+	snprintf(hdr_arg, sizeof(hdr_arg),
+			"--pack_header=%"PRIu32",%"PRIu32,
 			ntohl(hdr.hdr_version), ntohl(hdr.hdr_entries));
 
 	if (ntohl(hdr.hdr_entries) < unpack_limit) {
@@ -481,7 +482,7 @@
 	if (!dir)
 		usage(receive_pack_usage);
 
-	setup_path(NULL);
+	setup_path();
 
 	if (!enter_repo(dir, 0))
 		die("'%s': unable to chdir or not a git archive", dir);
diff --git a/reflog-walk.c b/reflog-walk.c
index ee1456b..f751fdc 100644
--- a/reflog-walk.c
+++ b/reflog-walk.c
@@ -3,7 +3,7 @@
 #include "refs.h"
 #include "diff.h"
 #include "revision.h"
-#include "path-list.h"
+#include "string-list.h"
 #include "reflog-walk.h"
 
 struct complete_reflogs {
@@ -127,7 +127,7 @@
 
 struct reflog_walk_info {
 	struct commit_info_lifo reflogs;
-	struct path_list complete_reflogs;
+	struct string_list complete_reflogs;
 	struct commit_reflog *last_commit_reflog;
 };
 
@@ -141,7 +141,7 @@
 {
 	unsigned long timestamp = 0;
 	int recno = -1;
-	struct path_list_item *item;
+	struct string_list_item *item;
 	struct complete_reflogs *reflogs;
 	char *branch, *at = strchr(name, '@');
 	struct commit_reflog *commit_reflog;
@@ -161,7 +161,7 @@
 	} else
 		recno = 0;
 
-	item = path_list_lookup(branch, &info->complete_reflogs);
+	item = string_list_lookup(branch, &info->complete_reflogs);
 	if (item)
 		reflogs = item->util;
 	else {
@@ -189,7 +189,7 @@
 		}
 		if (!reflogs || reflogs->nr == 0)
 			return -1;
-		path_list_insert(branch, &info->complete_reflogs)->util
+		string_list_insert(branch, &info->complete_reflogs)->util
 			= reflogs;
 	}
 
diff --git a/refs.c b/refs.c
index c9bcf14..be095cb 100644
--- a/refs.c
+++ b/refs.c
@@ -401,7 +401,7 @@
 		*flag = 0;
 
 	for (;;) {
-		const char *path = git_path("%s", ref);
+		char path[PATH_MAX];
 		struct stat st;
 		char *buf;
 		int fd;
@@ -409,6 +409,7 @@
 		if (--depth < 0)
 			return NULL;
 
+		git_snpath(path, sizeof(path), "%s", ref);
 		/* Special case: non-existing file.
 		 * Not having the refs/heads/new-branch is OK
 		 * if we are writing into it, so is .git/HEAD
@@ -788,10 +789,10 @@
 	char *ref_file;
 	const char *orig_ref = ref;
 	struct ref_lock *lock;
-	struct stat st;
 	int last_errno = 0;
-	int type;
+	int type, lflags;
 	int mustexist = (old_sha1 && !is_null_sha1(old_sha1));
+	int missing = 0;
 
 	lock = xcalloc(1, sizeof(struct ref_lock));
 	lock->lock_fd = -1;
@@ -819,23 +820,27 @@
 			orig_ref, strerror(errno));
 		goto error_return;
 	}
+	missing = is_null_sha1(lock->old_sha1);
 	/* When the ref did not exist and we are creating it,
 	 * make sure there is no existing ref that is packed
 	 * whose name begins with our refname, nor a ref whose
 	 * name is a proper prefix of our refname.
 	 */
-	if (is_null_sha1(lock->old_sha1) &&
+	if (missing &&
             !is_refname_available(ref, NULL, get_packed_refs(), 0))
 		goto error_return;
 
 	lock->lk = xcalloc(1, sizeof(struct lock_file));
 
-	if (flags & REF_NODEREF)
+	lflags = LOCK_DIE_ON_ERROR;
+	if (flags & REF_NODEREF) {
 		ref = orig_ref;
+		lflags |= LOCK_NODEREF;
+	}
 	lock->ref_name = xstrdup(ref);
 	lock->orig_ref_name = xstrdup(orig_ref);
 	ref_file = git_path("%s", ref);
-	if (lstat(ref_file, &st) && errno == ENOENT)
+	if (missing)
 		lock->force_write = 1;
 	if ((flags & REF_NODEREF) && (type & REF_ISSYMREF))
 		lock->force_write = 1;
@@ -845,8 +850,8 @@
 		error("unable to create directory for %s", ref_file);
 		goto error_return;
 	}
-	lock->lock_fd = hold_lock_file_for_update(lock->lk, ref_file, 1);
 
+	lock->lock_fd = hold_lock_file_for_update(lock->lk, ref_file, lflags);
 	return old_sha1 ? verify_lock(lock, old_sha1, mustexist) : lock;
 
  error_return:
@@ -912,25 +917,33 @@
 	return commit_lock_file(&packlock);
 }
 
-int delete_ref(const char *refname, const unsigned char *sha1)
+int delete_ref(const char *refname, const unsigned char *sha1, int delopt)
 {
 	struct ref_lock *lock;
-	int err, i, ret = 0, flag = 0;
+	int err, i = 0, ret = 0, flag = 0;
 
 	lock = lock_ref_sha1_basic(refname, sha1, 0, &flag);
 	if (!lock)
 		return 1;
-	if (!(flag & REF_ISPACKED)) {
+	if (!(flag & REF_ISPACKED) || flag & REF_ISSYMREF) {
 		/* loose */
-		i = strlen(lock->lk->filename) - 5; /* .lock */
-		lock->lk->filename[i] = 0;
-		err = unlink(lock->lk->filename);
+		const char *path;
+
+		if (!(delopt & REF_NODEREF)) {
+			i = strlen(lock->lk->filename) - 5; /* .lock */
+			lock->lk->filename[i] = 0;
+			path = lock->lk->filename;
+		} else {
+			path = git_path("%s", refname);
+		}
+		err = unlink(path);
 		if (err && errno != ENOENT) {
 			ret = 1;
 			error("unlink(%s) failed: %s",
-			      lock->lk->filename, strerror(errno));
+			      path, strerror(errno));
 		}
-		lock->lk->filename[i] = '.';
+		if (!(delopt & REF_NODEREF))
+			lock->lk->filename[i] = '.';
 	}
 	/* removing the loose one could have resurrected an earlier
 	 * packed one.  Also, if it was not loose we need to repack
@@ -955,11 +968,16 @@
 	struct ref_lock *lock;
 	struct stat loginfo;
 	int log = !lstat(git_path("logs/%s", oldref), &loginfo);
+	const char *symref = NULL;
 
-	if (S_ISLNK(loginfo.st_mode))
+	if (log && S_ISLNK(loginfo.st_mode))
 		return error("reflog for %s is a symlink", oldref);
 
-	if (!resolve_ref(oldref, orig_sha1, 1, &flag))
+	symref = resolve_ref(oldref, orig_sha1, 1, &flag);
+	if (flag & REF_ISSYMREF)
+		return error("refname %s is a symbolic ref, renaming it is not supported",
+			oldref);
+	if (!symref)
 		return error("refname %s not found", oldref);
 
 	if (!is_refname_available(newref, oldref, get_packed_refs(), 0))
@@ -979,12 +997,12 @@
 		return error("unable to move logfile logs/%s to tmp-renamed-log: %s",
 			oldref, strerror(errno));
 
-	if (delete_ref(oldref, orig_sha1)) {
+	if (delete_ref(oldref, orig_sha1, REF_NODEREF)) {
 		error("unable to delete old %s", oldref);
 		goto rollback;
 	}
 
-	if (resolve_ref(newref, sha1, 1, &flag) && delete_ref(newref, sha1)) {
+	if (resolve_ref(newref, sha1, 1, &flag) && delete_ref(newref, sha1, REF_NODEREF)) {
 		if (errno==EISDIR) {
 			if (remove_empty_directories(git_path("%s", newref))) {
 				error("Directory not empty: %s", newref);
@@ -1027,7 +1045,6 @@
 		error("unable to lock %s for update", newref);
 		goto rollback;
 	}
-
 	lock->force_write = 1;
 	hashcpy(lock->old_sha1, orig_sha1);
 	if (write_ref_sha1(lock, orig_sha1, logmsg)) {
@@ -1121,13 +1138,14 @@
 	int logfd, written, oflags = O_APPEND | O_WRONLY;
 	unsigned maxlen, len;
 	int msglen;
-	char *log_file, *logrec;
+	char log_file[PATH_MAX];
+	char *logrec;
 	const char *committer;
 
 	if (log_all_ref_updates < 0)
 		log_all_ref_updates = !is_bare_repository();
 
-	log_file = git_path("logs/%s", ref_name);
+	git_snpath(log_file, sizeof(log_file), "logs/%s", ref_name);
 
 	if (log_all_ref_updates &&
 	    (!prefixcmp(ref_name, "refs/heads/") ||
@@ -1256,7 +1274,7 @@
 	const char *lockpath;
 	char ref[1000];
 	int fd, len, written;
-	char *git_HEAD = xstrdup(git_path("%s", ref_target));
+	char *git_HEAD = git_pathdup("%s", ref_target);
 	unsigned char old_sha1[20], new_sha1[20];
 
 	if (logmsg && read_ref(ref_target, old_sha1))
@@ -1412,6 +1430,10 @@
 	tz = strtoul(tz_c, NULL, 10);
 	if (get_sha1_hex(logdata, sha1))
 		die("Log %s is corrupt.", logfile);
+	if (is_null_sha1(sha1)) {
+		if (get_sha1_hex(logdata + 41, sha1))
+			die("Log %s is corrupt.", logfile);
+	}
 	if (msg)
 		*msg = ref_msg(logdata, logend);
 	munmap(log_mapped, mapsz);
diff --git a/remote.c b/remote.c
index 5f687b2..91f1b7c 100644
--- a/remote.c
+++ b/remote.c
@@ -1,6 +1,9 @@
 #include "cache.h"
 #include "remote.h"
 #include "refs.h"
+#include "commit.h"
+#include "diff.h"
+#include "revision.h"
 
 static struct refspec s_tag_refspec = {
 	0,
@@ -295,6 +298,17 @@
 	}
 	add_url_alias(remote, p);
 	add_fetch_refspec(remote, strbuf_detach(&branch, 0));
+	/*
+	 * Cogito compatible push: push current HEAD to remote #branch
+	 * (master if missing)
+	 */
+	strbuf_init(&branch, 0);
+	strbuf_addstr(&branch, "HEAD");
+	if (frag)
+		strbuf_addf(&branch, ":refs/heads/%s", frag);
+	else
+		strbuf_addstr(&branch, ":refs/heads/master");
+	add_push_refspec(remote, strbuf_detach(&branch, 0));
 	remote->fetch_tags = 1; /* always auto-follow */
 }
 
@@ -339,13 +353,14 @@
 	if (prefixcmp(key,  "remote."))
 		return 0;
 	name = key + 7;
+	if (*name == '/') {
+		warning("Config remote shorthand cannot begin with '/': %s",
+			name);
+		return 0;
+	}
 	subkey = strrchr(name, '.');
 	if (!subkey)
 		return error("Config with no key for remote %s", name);
-	if (*subkey == '/') {
-		warning("Config remote shorthand cannot begin with '/': %s", name);
-		return 0;
-	}
 	remote = make_remote(name, subkey - name);
 	if (!strcmp(subkey, ".mirror"))
 		remote->mirror = git_config_bool(key, value);
@@ -576,8 +591,7 @@
 	struct refspec *refspec;
 
 	refspec = parse_refspec_internal(1, fetch_refspec, 1, 1);
-	if (refspec)
-		free(refspec);
+	free(refspec);
 	return !!refspec;
 }
 
@@ -1238,3 +1252,111 @@
 		}
 	return 1;
 }
+
+/*
+ * Return true if there is anything to report, otherwise false.
+ */
+int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs)
+{
+	unsigned char sha1[20];
+	struct commit *ours, *theirs;
+	char symmetric[84];
+	struct rev_info revs;
+	const char *rev_argv[10], *base;
+	int rev_argc;
+
+	/*
+	 * Nothing to report unless we are marked to build on top of
+	 * somebody else.
+	 */
+	if (!branch ||
+	    !branch->merge || !branch->merge[0] || !branch->merge[0]->dst)
+		return 0;
+
+	/*
+	 * If what we used to build on no longer exists, there is
+	 * nothing to report.
+	 */
+	base = branch->merge[0]->dst;
+	if (!resolve_ref(base, sha1, 1, NULL))
+		return 0;
+	theirs = lookup_commit(sha1);
+	if (!theirs)
+		return 0;
+
+	if (!resolve_ref(branch->refname, sha1, 1, NULL))
+		return 0;
+	ours = lookup_commit(sha1);
+	if (!ours)
+		return 0;
+
+	/* are we the same? */
+	if (theirs == ours)
+		return 0;
+
+	/* Run "rev-list --left-right ours...theirs" internally... */
+	rev_argc = 0;
+	rev_argv[rev_argc++] = NULL;
+	rev_argv[rev_argc++] = "--left-right";
+	rev_argv[rev_argc++] = symmetric;
+	rev_argv[rev_argc++] = "--";
+	rev_argv[rev_argc] = NULL;
+
+	strcpy(symmetric, sha1_to_hex(ours->object.sha1));
+	strcpy(symmetric + 40, "...");
+	strcpy(symmetric + 43, sha1_to_hex(theirs->object.sha1));
+
+	init_revisions(&revs, NULL);
+	setup_revisions(rev_argc, rev_argv, &revs, NULL);
+	prepare_revision_walk(&revs);
+
+	/* ... and count the commits on each side. */
+	*num_ours = 0;
+	*num_theirs = 0;
+	while (1) {
+		struct commit *c = get_revision(&revs);
+		if (!c)
+			break;
+		if (c->object.flags & SYMMETRIC_LEFT)
+			(*num_ours)++;
+		else
+			(*num_theirs)++;
+	}
+
+	/* clear object flags smudged by the above traversal */
+	clear_commit_marks(ours, ALL_REV_FLAGS);
+	clear_commit_marks(theirs, ALL_REV_FLAGS);
+	return 1;
+}
+
+/*
+ * Return true when there is anything to report, otherwise false.
+ */
+int format_tracking_info(struct branch *branch, struct strbuf *sb)
+{
+	int num_ours, num_theirs;
+	const char *base;
+
+	if (!stat_tracking_info(branch, &num_ours, &num_theirs))
+		return 0;
+
+	base = branch->merge[0]->dst;
+	if (!prefixcmp(base, "refs/remotes/")) {
+		base += strlen("refs/remotes/");
+	}
+	if (!num_theirs)
+		strbuf_addf(sb, "Your branch is ahead of '%s' "
+			    "by %d commit%s.\n",
+			    base, num_ours, (num_ours == 1) ? "" : "s");
+	else if (!num_ours)
+		strbuf_addf(sb, "Your branch is behind '%s' "
+			    "by %d commit%s, "
+			    "and can be fast-forwarded.\n",
+			    base, num_theirs, (num_theirs == 1) ? "" : "s");
+	else
+		strbuf_addf(sb, "Your branch and '%s' have diverged,\n"
+			    "and have %d and %d different commit(s) each, "
+			    "respectively.\n",
+			    base, num_ours, num_theirs);
+	return 1;
+}
diff --git a/remote.h b/remote.h
index 8eed87b..091b1d0 100644
--- a/remote.h
+++ b/remote.h
@@ -129,4 +129,8 @@
 	MATCH_REFS_MIRROR	= (1 << 1),
 };
 
+/* Reporting of tracking info */
+int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs);
+int format_tracking_info(struct branch *branch, struct strbuf *sb);
+
 #endif
diff --git a/rerere.c b/rerere.c
new file mode 100644
index 0000000..a0d477a
--- /dev/null
+++ b/rerere.c
@@ -0,0 +1,364 @@
+#include "cache.h"
+#include "string-list.h"
+#include "rerere.h"
+#include "xdiff/xdiff.h"
+#include "xdiff-interface.h"
+
+/* if rerere_enabled == -1, fall back to detection of .git/rr-cache */
+static int rerere_enabled = -1;
+
+/* automatically update cleanly resolved paths to the index */
+static int rerere_autoupdate;
+
+static char *merge_rr_path;
+
+static const char *rr_path(const char *name, const char *file)
+{
+	return git_path("rr-cache/%s/%s", name, file);
+}
+
+static int has_resolution(const char *name)
+{
+	struct stat st;
+	return !stat(rr_path(name, "postimage"), &st);
+}
+
+static void read_rr(struct string_list *rr)
+{
+	unsigned char sha1[20];
+	char buf[PATH_MAX];
+	FILE *in = fopen(merge_rr_path, "r");
+	if (!in)
+		return;
+	while (fread(buf, 40, 1, in) == 1) {
+		int i;
+		char *name;
+		if (get_sha1_hex(buf, sha1))
+			die("corrupt MERGE_RR");
+		buf[40] = '\0';
+		name = xstrdup(buf);
+		if (fgetc(in) != '\t')
+			die("corrupt MERGE_RR");
+		for (i = 0; i < sizeof(buf) && (buf[i] = fgetc(in)); i++)
+			; /* do nothing */
+		if (i == sizeof(buf))
+			die("filename too long");
+		string_list_insert(buf, rr)->util = name;
+	}
+	fclose(in);
+}
+
+static struct lock_file write_lock;
+
+static int write_rr(struct string_list *rr, int out_fd)
+{
+	int i;
+	for (i = 0; i < rr->nr; i++) {
+		const char *path;
+		int length;
+		if (!rr->items[i].util)
+			continue;
+		path = rr->items[i].string;
+		length = strlen(path) + 1;
+		if (write_in_full(out_fd, rr->items[i].util, 40) != 40 ||
+		    write_in_full(out_fd, "\t", 1) != 1 ||
+		    write_in_full(out_fd, path, length) != length)
+			die("unable to write rerere record");
+	}
+	if (commit_lock_file(&write_lock) != 0)
+		die("unable to write rerere record");
+	return 0;
+}
+
+static int handle_file(const char *path,
+	 unsigned char *sha1, const char *output)
+{
+	SHA_CTX ctx;
+	char buf[1024];
+	int hunk = 0, hunk_no = 0;
+	struct strbuf one, two;
+	FILE *f = fopen(path, "r");
+	FILE *out = NULL;
+
+	if (!f)
+		return error("Could not open %s", path);
+
+	if (output) {
+		out = fopen(output, "w");
+		if (!out) {
+			fclose(f);
+			return error("Could not write %s", output);
+		}
+	}
+
+	if (sha1)
+		SHA1_Init(&ctx);
+
+	strbuf_init(&one, 0);
+	strbuf_init(&two,  0);
+	while (fgets(buf, sizeof(buf), f)) {
+		if (!prefixcmp(buf, "<<<<<<< ")) {
+			if (hunk)
+				goto bad;
+			hunk = 1;
+		} else if (!prefixcmp(buf, "=======") && isspace(buf[7])) {
+			if (hunk != 1)
+				goto bad;
+			hunk = 2;
+		} else if (!prefixcmp(buf, ">>>>>>> ")) {
+			if (hunk != 2)
+				goto bad;
+			if (strbuf_cmp(&one, &two) > 0)
+				strbuf_swap(&one, &two);
+			hunk_no++;
+			hunk = 0;
+			if (out) {
+				fputs("<<<<<<<\n", out);
+				fwrite(one.buf, one.len, 1, out);
+				fputs("=======\n", out);
+				fwrite(two.buf, two.len, 1, out);
+				fputs(">>>>>>>\n", out);
+			}
+			if (sha1) {
+				SHA1_Update(&ctx, one.buf ? one.buf : "",
+					    one.len + 1);
+				SHA1_Update(&ctx, two.buf ? two.buf : "",
+					    two.len + 1);
+			}
+			strbuf_reset(&one);
+			strbuf_reset(&two);
+		} else if (hunk == 1)
+			strbuf_addstr(&one, buf);
+		else if (hunk == 2)
+			strbuf_addstr(&two, buf);
+		else if (out)
+			fputs(buf, out);
+		continue;
+	bad:
+		hunk = 99; /* force error exit */
+		break;
+	}
+	strbuf_release(&one);
+	strbuf_release(&two);
+
+	fclose(f);
+	if (out)
+		fclose(out);
+	if (sha1)
+		SHA1_Final(sha1, &ctx);
+	if (hunk) {
+		if (output)
+			unlink(output);
+		return error("Could not parse conflict hunks in %s", path);
+	}
+	return hunk_no;
+}
+
+static int find_conflict(struct string_list *conflict)
+{
+	int i;
+	if (read_cache() < 0)
+		return error("Could not read index");
+	for (i = 0; i+1 < active_nr; i++) {
+		struct cache_entry *e2 = active_cache[i];
+		struct cache_entry *e3 = active_cache[i+1];
+		if (ce_stage(e2) == 2 &&
+		    ce_stage(e3) == 3 &&
+		    ce_same_name(e2, e3) &&
+		    S_ISREG(e2->ce_mode) &&
+		    S_ISREG(e3->ce_mode)) {
+			string_list_insert((const char *)e2->name, conflict);
+			i++; /* skip over both #2 and #3 */
+		}
+	}
+	return 0;
+}
+
+static int merge(const char *name, const char *path)
+{
+	int ret;
+	mmfile_t cur, base, other;
+	mmbuffer_t result = {NULL, 0};
+	xpparam_t xpp = {XDF_NEED_MINIMAL};
+
+	if (handle_file(path, NULL, rr_path(name, "thisimage")) < 0)
+		return 1;
+
+	if (read_mmfile(&cur, rr_path(name, "thisimage")) ||
+			read_mmfile(&base, rr_path(name, "preimage")) ||
+			read_mmfile(&other, rr_path(name, "postimage")))
+		return 1;
+	ret = xdl_merge(&base, &cur, "", &other, "",
+			&xpp, XDL_MERGE_ZEALOUS, &result);
+	if (!ret) {
+		FILE *f = fopen(path, "w");
+		if (!f)
+			return error("Could not write to %s", path);
+		fwrite(result.ptr, result.size, 1, f);
+		fclose(f);
+	}
+
+	free(cur.ptr);
+	free(base.ptr);
+	free(other.ptr);
+	free(result.ptr);
+
+	return ret;
+}
+
+static struct lock_file index_lock;
+
+static int update_paths(struct string_list *update)
+{
+	int i;
+	int fd = hold_locked_index(&index_lock, 0);
+	int status = 0;
+
+	if (fd < 0)
+		return -1;
+
+	for (i = 0; i < update->nr; i++) {
+		struct string_list_item *item = &update->items[i];
+		if (add_file_to_cache(item->string, ADD_CACHE_IGNORE_ERRORS))
+			status = -1;
+	}
+
+	if (!status && active_cache_changed) {
+		if (write_cache(fd, active_cache, active_nr) ||
+		    commit_locked_index(&index_lock))
+			die("Unable to write new index file");
+	} else if (fd >= 0)
+		rollback_lock_file(&index_lock);
+	return status;
+}
+
+static int do_plain_rerere(struct string_list *rr, int fd)
+{
+	struct string_list conflict = { NULL, 0, 0, 1 };
+	struct string_list update = { NULL, 0, 0, 1 };
+	int i;
+
+	find_conflict(&conflict);
+
+	/*
+	 * MERGE_RR records paths with conflicts immediately after merge
+	 * failed.  Some of the conflicted paths might have been hand resolved
+	 * in the working tree since then, but the initial run would catch all
+	 * and register their preimages.
+	 */
+
+	for (i = 0; i < conflict.nr; i++) {
+		const char *path = conflict.items[i].string;
+		if (!string_list_has_string(rr, path)) {
+			unsigned char sha1[20];
+			char *hex;
+			int ret;
+			ret = handle_file(path, sha1, NULL);
+			if (ret < 1)
+				continue;
+			hex = xstrdup(sha1_to_hex(sha1));
+			string_list_insert(path, rr)->util = hex;
+			if (mkdir(git_path("rr-cache/%s", hex), 0755))
+				continue;;
+			handle_file(path, NULL, rr_path(hex, "preimage"));
+			fprintf(stderr, "Recorded preimage for '%s'\n", path);
+		}
+	}
+
+	/*
+	 * Now some of the paths that had conflicts earlier might have been
+	 * hand resolved.  Others may be similar to a conflict already that
+	 * was resolved before.
+	 */
+
+	for (i = 0; i < rr->nr; i++) {
+		int ret;
+		const char *path = rr->items[i].string;
+		const char *name = (const char *)rr->items[i].util;
+
+		if (has_resolution(name)) {
+			if (!merge(name, path)) {
+				if (rerere_autoupdate)
+					string_list_insert(path, &update);
+				fprintf(stderr,
+					"%s '%s' using previous resolution.\n",
+					rerere_autoupdate
+					? "Staged" : "Resolved",
+					path);
+				goto mark_resolved;
+			}
+		}
+
+		/* Let's see if we have resolved it. */
+		ret = handle_file(path, NULL, NULL);
+		if (ret)
+			continue;
+
+		fprintf(stderr, "Recorded resolution for '%s'.\n", path);
+		copy_file(rr_path(name, "postimage"), path, 0666);
+	mark_resolved:
+		rr->items[i].util = NULL;
+	}
+
+	if (update.nr)
+		update_paths(&update);
+
+	return write_rr(rr, fd);
+}
+
+static int git_rerere_config(const char *var, const char *value, void *cb)
+{
+	if (!strcmp(var, "rerere.enabled"))
+		rerere_enabled = git_config_bool(var, value);
+	else if (!strcmp(var, "rerere.autoupdate"))
+		rerere_autoupdate = git_config_bool(var, value);
+	else
+		return git_default_config(var, value, cb);
+	return 0;
+}
+
+static int is_rerere_enabled(void)
+{
+	struct stat st;
+	const char *rr_cache;
+	int rr_cache_exists;
+
+	if (!rerere_enabled)
+		return 0;
+
+	rr_cache = git_path("rr-cache");
+	rr_cache_exists = !stat(rr_cache, &st) && S_ISDIR(st.st_mode);
+	if (rerere_enabled < 0)
+		return rr_cache_exists;
+
+	if (!rr_cache_exists &&
+	    (mkdir(rr_cache, 0777) || adjust_shared_perm(rr_cache)))
+		die("Could not create directory %s", rr_cache);
+	return 1;
+}
+
+int setup_rerere(struct string_list *merge_rr)
+{
+	int fd;
+
+	git_config(git_rerere_config, NULL);
+	if (!is_rerere_enabled())
+		return -1;
+
+	merge_rr_path = git_pathdup("MERGE_RR");
+	fd = hold_lock_file_for_update(&write_lock, merge_rr_path,
+				       LOCK_DIE_ON_ERROR);
+	read_rr(merge_rr);
+	return fd;
+}
+
+int rerere(void)
+{
+	struct string_list merge_rr = { NULL, 0, 0, 1 };
+	int fd;
+
+	fd = setup_rerere(&merge_rr);
+	if (fd < 0)
+		return 0;
+	return do_plain_rerere(&merge_rr, fd);
+}
diff --git a/rerere.h b/rerere.h
new file mode 100644
index 0000000..f9b0386
--- /dev/null
+++ b/rerere.h
@@ -0,0 +1,9 @@
+#ifndef RERERE_H
+#define RERERE_H
+
+#include "string-list.h"
+
+extern int setup_rerere(struct string_list *);
+extern int rerere(void);
+
+#endif
diff --git a/revision.c b/revision.c
index a68abec..45fd7a3 100644
--- a/revision.c
+++ b/revision.c
@@ -10,6 +10,7 @@
 #include "grep.h"
 #include "reflog-walk.h"
 #include "patch-ids.h"
+#include "decorate.h"
 
 volatile show_early_output_fn_t show_early_output;
 
@@ -781,6 +782,10 @@
 
 	revs->commit_format = CMIT_FMT_DEFAULT;
 
+	revs->grep_filter.status_only = 1;
+	revs->grep_filter.pattern_tail = &(revs->grep_filter.pattern_list);
+	revs->grep_filter.regflags = REG_NEWLINE;
+
 	diff_setup(&revs->diffopt);
 	if (prefix && !revs->diffopt.prefix) {
 		revs->diffopt.prefix = prefix;
@@ -926,35 +931,31 @@
 	return 0;
 }
 
-static void add_grep(struct rev_info *revs, const char *ptn, enum grep_pat_token what)
+void read_revisions_from_stdin(struct rev_info *revs)
 {
-	if (!revs->grep_filter) {
-		struct grep_opt *opt = xcalloc(1, sizeof(*opt));
-		opt->status_only = 1;
-		opt->pattern_tail = &(opt->pattern_list);
-		opt->regflags = REG_NEWLINE;
-		revs->grep_filter = opt;
+	char line[1000];
+
+	while (fgets(line, sizeof(line), stdin) != NULL) {
+		int len = strlen(line);
+		if (len && line[len - 1] == '\n')
+			line[--len] = '\0';
+		if (!len)
+			break;
+		if (line[0] == '-')
+			die("options not supported in --stdin mode");
+		if (handle_revision_arg(line, revs, 0, 1))
+			die("bad revision '%s'", line);
 	}
-	append_grep_pattern(revs->grep_filter, ptn,
-			    "command line", 0, what);
 }
 
-static void add_header_grep(struct rev_info *revs, const char *field, const char *pattern)
+static void add_grep(struct rev_info *revs, const char *ptn, enum grep_pat_token what)
 {
-	char *pat;
-	const char *prefix;
-	int patlen, fldlen;
+	append_grep_pattern(&revs->grep_filter, ptn, "command line", 0, what);
+}
 
-	fldlen = strlen(field);
-	patlen = strlen(pattern);
-	pat = xmalloc(patlen + fldlen + 10);
-	prefix = ".*";
-	if (*pattern == '^') {
-		prefix = "";
-		pattern++;
-	}
-	sprintf(pat, "^%s %s%s", field, prefix, pattern);
-	add_grep(revs, pat, GREP_PATTERN_HEAD);
+static void add_header_grep(struct rev_info *revs, enum grep_header_field field, const char *pattern)
+{
+	append_header_grep_pattern(&revs->grep_filter, field, pattern);
 }
 
 static void add_message_grep(struct rev_info *revs, const char *pattern)
@@ -967,11 +968,227 @@
 	int num = ++revs->num_ignore_packed;
 
 	revs->ignore_packed = xrealloc(revs->ignore_packed,
-				       sizeof(const char **) * (num + 1));
+				       sizeof(const char *) * (num + 1));
 	revs->ignore_packed[num-1] = name;
 	revs->ignore_packed[num] = NULL;
 }
 
+static int handle_revision_opt(struct rev_info *revs, int argc, const char **argv,
+			       int *unkc, const char **unkv)
+{
+	const char *arg = argv[0];
+
+	/* pseudo revision arguments */
+	if (!strcmp(arg, "--all") || !strcmp(arg, "--branches") ||
+	    !strcmp(arg, "--tags") || !strcmp(arg, "--remotes") ||
+	    !strcmp(arg, "--reflog") || !strcmp(arg, "--not") ||
+	    !strcmp(arg, "--no-walk") || !strcmp(arg, "--do-walk"))
+	{
+		unkv[(*unkc)++] = arg;
+		return 1;
+	}
+
+	if (!prefixcmp(arg, "--max-count=")) {
+		revs->max_count = atoi(arg + 12);
+	} else if (!prefixcmp(arg, "--skip=")) {
+		revs->skip_count = atoi(arg + 7);
+	} else if ((*arg == '-') && isdigit(arg[1])) {
+	/* accept -<digit>, like traditional "head" */
+		revs->max_count = atoi(arg + 1);
+	} else if (!strcmp(arg, "-n")) {
+		if (argc <= 1)
+			return error("-n requires an argument");
+		revs->max_count = atoi(argv[1]);
+		return 2;
+	} else if (!prefixcmp(arg, "-n")) {
+		revs->max_count = atoi(arg + 2);
+	} else if (!prefixcmp(arg, "--max-age=")) {
+		revs->max_age = atoi(arg + 10);
+	} else if (!prefixcmp(arg, "--since=")) {
+		revs->max_age = approxidate(arg + 8);
+	} else if (!prefixcmp(arg, "--after=")) {
+		revs->max_age = approxidate(arg + 8);
+	} else if (!prefixcmp(arg, "--min-age=")) {
+		revs->min_age = atoi(arg + 10);
+	} else if (!prefixcmp(arg, "--before=")) {
+		revs->min_age = approxidate(arg + 9);
+	} else if (!prefixcmp(arg, "--until=")) {
+		revs->min_age = approxidate(arg + 8);
+	} else if (!strcmp(arg, "--first-parent")) {
+		revs->first_parent_only = 1;
+	} else if (!strcmp(arg, "-g") || !strcmp(arg, "--walk-reflogs")) {
+		init_reflog_walk(&revs->reflog_info);
+	} else if (!strcmp(arg, "--default")) {
+		if (argc <= 1)
+			return error("bad --default argument");
+		revs->def = argv[1];
+		return 2;
+	} else if (!strcmp(arg, "--merge")) {
+		revs->show_merge = 1;
+	} else if (!strcmp(arg, "--topo-order")) {
+		revs->lifo = 1;
+		revs->topo_order = 1;
+	} else if (!strcmp(arg, "--date-order")) {
+		revs->lifo = 0;
+		revs->topo_order = 1;
+	} else if (!prefixcmp(arg, "--early-output")) {
+		int count = 100;
+		switch (arg[14]) {
+		case '=':
+			count = atoi(arg+15);
+			/* Fallthrough */
+		case 0:
+			revs->topo_order = 1;
+		       revs->early_output = count;
+		}
+	} else if (!strcmp(arg, "--parents")) {
+		revs->rewrite_parents = 1;
+		revs->print_parents = 1;
+	} else if (!strcmp(arg, "--dense")) {
+		revs->dense = 1;
+	} else if (!strcmp(arg, "--sparse")) {
+		revs->dense = 0;
+	} else if (!strcmp(arg, "--show-all")) {
+		revs->show_all = 1;
+	} else if (!strcmp(arg, "--remove-empty")) {
+		revs->remove_empty_trees = 1;
+	} else if (!strcmp(arg, "--no-merges")) {
+		revs->no_merges = 1;
+	} else if (!strcmp(arg, "--boundary")) {
+		revs->boundary = 1;
+	} else if (!strcmp(arg, "--left-right")) {
+		revs->left_right = 1;
+	} else if (!strcmp(arg, "--cherry-pick")) {
+		revs->cherry_pick = 1;
+		revs->limited = 1;
+	} else if (!strcmp(arg, "--objects")) {
+		revs->tag_objects = 1;
+		revs->tree_objects = 1;
+		revs->blob_objects = 1;
+	} else if (!strcmp(arg, "--objects-edge")) {
+		revs->tag_objects = 1;
+		revs->tree_objects = 1;
+		revs->blob_objects = 1;
+		revs->edge_hint = 1;
+	} else if (!strcmp(arg, "--unpacked")) {
+		revs->unpacked = 1;
+		free(revs->ignore_packed);
+		revs->ignore_packed = NULL;
+		revs->num_ignore_packed = 0;
+	} else if (!prefixcmp(arg, "--unpacked=")) {
+		revs->unpacked = 1;
+		add_ignore_packed(revs, arg+11);
+	} else if (!strcmp(arg, "-r")) {
+		revs->diff = 1;
+		DIFF_OPT_SET(&revs->diffopt, RECURSIVE);
+	} else if (!strcmp(arg, "-t")) {
+		revs->diff = 1;
+		DIFF_OPT_SET(&revs->diffopt, RECURSIVE);
+		DIFF_OPT_SET(&revs->diffopt, TREE_IN_RECURSIVE);
+	} else if (!strcmp(arg, "-m")) {
+		revs->ignore_merges = 0;
+	} else if (!strcmp(arg, "-c")) {
+		revs->diff = 1;
+		revs->dense_combined_merges = 0;
+		revs->combine_merges = 1;
+	} else if (!strcmp(arg, "--cc")) {
+		revs->diff = 1;
+		revs->dense_combined_merges = 1;
+		revs->combine_merges = 1;
+	} else if (!strcmp(arg, "-v")) {
+		revs->verbose_header = 1;
+	} else if (!strcmp(arg, "--pretty")) {
+		revs->verbose_header = 1;
+		get_commit_format(arg+8, revs);
+	} else if (!prefixcmp(arg, "--pretty=")) {
+		revs->verbose_header = 1;
+		get_commit_format(arg+9, revs);
+	} else if (!strcmp(arg, "--graph")) {
+		revs->topo_order = 1;
+		revs->rewrite_parents = 1;
+		revs->graph = graph_init(revs);
+	} else if (!strcmp(arg, "--root")) {
+		revs->show_root_diff = 1;
+	} else if (!strcmp(arg, "--no-commit-id")) {
+		revs->no_commit_id = 1;
+	} else if (!strcmp(arg, "--always")) {
+		revs->always_show_header = 1;
+	} else if (!strcmp(arg, "--no-abbrev")) {
+		revs->abbrev = 0;
+	} else if (!strcmp(arg, "--abbrev")) {
+		revs->abbrev = DEFAULT_ABBREV;
+	} else if (!prefixcmp(arg, "--abbrev=")) {
+		revs->abbrev = strtoul(arg + 9, NULL, 10);
+		if (revs->abbrev < MINIMUM_ABBREV)
+			revs->abbrev = MINIMUM_ABBREV;
+		else if (revs->abbrev > 40)
+			revs->abbrev = 40;
+	} else if (!strcmp(arg, "--abbrev-commit")) {
+		revs->abbrev_commit = 1;
+	} else if (!strcmp(arg, "--full-diff")) {
+		revs->diff = 1;
+		revs->full_diff = 1;
+	} else if (!strcmp(arg, "--full-history")) {
+		revs->simplify_history = 0;
+	} else if (!strcmp(arg, "--relative-date")) {
+		revs->date_mode = DATE_RELATIVE;
+	} else if (!strncmp(arg, "--date=", 7)) {
+		revs->date_mode = parse_date_format(arg + 7);
+	} else if (!strcmp(arg, "--log-size")) {
+		revs->show_log_size = 1;
+	}
+	/*
+	 * Grepping the commit log
+	 */
+	else if (!prefixcmp(arg, "--author=")) {
+		add_header_grep(revs, GREP_HEADER_AUTHOR, arg+9);
+	} else if (!prefixcmp(arg, "--committer=")) {
+		add_header_grep(revs, GREP_HEADER_COMMITTER, arg+12);
+	} else if (!prefixcmp(arg, "--grep=")) {
+		add_message_grep(revs, arg+7);
+	} else if (!strcmp(arg, "--extended-regexp") || !strcmp(arg, "-E")) {
+		revs->grep_filter.regflags |= REG_EXTENDED;
+	} else if (!strcmp(arg, "--regexp-ignore-case") || !strcmp(arg, "-i")) {
+		revs->grep_filter.regflags |= REG_ICASE;
+	} else if (!strcmp(arg, "--fixed-strings") || !strcmp(arg, "-F")) {
+		revs->grep_filter.fixed = 1;
+	} else if (!strcmp(arg, "--all-match")) {
+		revs->grep_filter.all_match = 1;
+	} else if (!prefixcmp(arg, "--encoding=")) {
+		arg += 11;
+		if (strcmp(arg, "none"))
+			git_log_output_encoding = xstrdup(arg);
+		else
+			git_log_output_encoding = "";
+	} else if (!strcmp(arg, "--reverse")) {
+		revs->reverse ^= 1;
+	} else if (!strcmp(arg, "--children")) {
+		revs->children.name = "children";
+		revs->limited = 1;
+	} else {
+		int opts = diff_opt_parse(&revs->diffopt, argv, argc);
+		if (!opts)
+			unkv[(*unkc)++] = arg;
+		return opts;
+	}
+
+	return 1;
+}
+
+void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ctx,
+			const struct option *options,
+			const char * const usagestr[])
+{
+	int n = handle_revision_opt(revs, ctx->argc, ctx->argv,
+				    &ctx->cpidx, ctx->out);
+	if (n <= 0) {
+		error("unknown option `%s'", ctx->argv[0]);
+		usage_with_options(usagestr, options);
+	}
+	ctx->argv += n;
+	ctx->argc -= n;
+}
+
 /*
  * Parse revision information, filling in the "rev_info" structure,
  * and removing the used arguments from the argument list.
@@ -981,12 +1198,7 @@
  */
 int setup_revisions(int argc, const char **argv, struct rev_info *revs, const char *def)
 {
-	int i, flags, seen_dashdash, show_merge;
-	const char **unrecognized = argv + 1;
-	int left = 1;
-	int all_match = 0;
-	int regflags = 0;
-	int fixed = 0;
+	int i, flags, left, seen_dashdash;
 
 	/* First, search for "--" */
 	seen_dashdash = 0;
@@ -1002,58 +1214,13 @@
 		break;
 	}
 
-	flags = show_merge = 0;
-	for (i = 1; i < argc; i++) {
+	/* Second, deal with arguments and options */
+	flags = 0;
+	for (left = i = 1; i < argc; i++) {
 		const char *arg = argv[i];
 		if (*arg == '-') {
 			int opts;
-			if (!prefixcmp(arg, "--max-count=")) {
-				revs->max_count = atoi(arg + 12);
-				continue;
-			}
-			if (!prefixcmp(arg, "--skip=")) {
-				revs->skip_count = atoi(arg + 7);
-				continue;
-			}
-			/* accept -<digit>, like traditional "head" */
-			if ((*arg == '-') && isdigit(arg[1])) {
-				revs->max_count = atoi(arg + 1);
-				continue;
-			}
-			if (!strcmp(arg, "-n")) {
-				if (argc <= i + 1)
-					die("-n requires an argument");
-				revs->max_count = atoi(argv[++i]);
-				continue;
-			}
-			if (!prefixcmp(arg, "-n")) {
-				revs->max_count = atoi(arg + 2);
-				continue;
-			}
-			if (!prefixcmp(arg, "--max-age=")) {
-				revs->max_age = atoi(arg + 10);
-				continue;
-			}
-			if (!prefixcmp(arg, "--since=")) {
-				revs->max_age = approxidate(arg + 8);
-				continue;
-			}
-			if (!prefixcmp(arg, "--after=")) {
-				revs->max_age = approxidate(arg + 8);
-				continue;
-			}
-			if (!prefixcmp(arg, "--min-age=")) {
-				revs->min_age = atoi(arg + 10);
-				continue;
-			}
-			if (!prefixcmp(arg, "--before=")) {
-				revs->min_age = approxidate(arg + 9);
-				continue;
-			}
-			if (!prefixcmp(arg, "--until=")) {
-				revs->min_age = approxidate(arg + 8);
-				continue;
-			}
+
 			if (!strcmp(arg, "--all")) {
 				handle_refs(revs, flags, for_each_ref);
 				continue;
@@ -1070,265 +1237,14 @@
 				handle_refs(revs, flags, for_each_remote_ref);
 				continue;
 			}
-			if (!strcmp(arg, "--first-parent")) {
-				revs->first_parent_only = 1;
-				continue;
-			}
 			if (!strcmp(arg, "--reflog")) {
 				handle_reflog(revs, flags);
 				continue;
 			}
-			if (!strcmp(arg, "-g") ||
-					!strcmp(arg, "--walk-reflogs")) {
-				init_reflog_walk(&revs->reflog_info);
-				continue;
-			}
 			if (!strcmp(arg, "--not")) {
 				flags ^= UNINTERESTING;
 				continue;
 			}
-			if (!strcmp(arg, "--default")) {
-				if (++i >= argc)
-					die("bad --default argument");
-				def = argv[i];
-				continue;
-			}
-			if (!strcmp(arg, "--merge")) {
-				show_merge = 1;
-				continue;
-			}
-			if (!strcmp(arg, "--topo-order")) {
-				revs->lifo = 1;
-				revs->topo_order = 1;
-				continue;
-			}
-			if (!strcmp(arg, "--date-order")) {
-				revs->lifo = 0;
-				revs->topo_order = 1;
-				continue;
-			}
-			if (!prefixcmp(arg, "--early-output")) {
-				int count = 100;
-				switch (arg[14]) {
-				case '=':
-					count = atoi(arg+15);
-					/* Fallthrough */
-				case 0:
-					revs->topo_order = 1;
-					revs->early_output = count;
-					continue;
-				}
-			}
-			if (!strcmp(arg, "--parents")) {
-				revs->rewrite_parents = 1;
-				revs->print_parents = 1;
-				continue;
-			}
-			if (!strcmp(arg, "--dense")) {
-				revs->dense = 1;
-				continue;
-			}
-			if (!strcmp(arg, "--sparse")) {
-				revs->dense = 0;
-				continue;
-			}
-			if (!strcmp(arg, "--show-all")) {
-				revs->show_all = 1;
-				continue;
-			}
-			if (!strcmp(arg, "--remove-empty")) {
-				revs->remove_empty_trees = 1;
-				continue;
-			}
-			if (!strcmp(arg, "--no-merges")) {
-				revs->no_merges = 1;
-				continue;
-			}
-			if (!strcmp(arg, "--boundary")) {
-				revs->boundary = 1;
-				continue;
-			}
-			if (!strcmp(arg, "--left-right")) {
-				revs->left_right = 1;
-				continue;
-			}
-			if (!strcmp(arg, "--cherry-pick")) {
-				revs->cherry_pick = 1;
-				revs->limited = 1;
-				continue;
-			}
-			if (!strcmp(arg, "--objects")) {
-				revs->tag_objects = 1;
-				revs->tree_objects = 1;
-				revs->blob_objects = 1;
-				continue;
-			}
-			if (!strcmp(arg, "--objects-edge")) {
-				revs->tag_objects = 1;
-				revs->tree_objects = 1;
-				revs->blob_objects = 1;
-				revs->edge_hint = 1;
-				continue;
-			}
-			if (!strcmp(arg, "--unpacked")) {
-				revs->unpacked = 1;
-				free(revs->ignore_packed);
-				revs->ignore_packed = NULL;
-				revs->num_ignore_packed = 0;
-				continue;
-			}
-			if (!prefixcmp(arg, "--unpacked=")) {
-				revs->unpacked = 1;
-				add_ignore_packed(revs, arg+11);
-				continue;
-			}
-			if (!strcmp(arg, "-r")) {
-				revs->diff = 1;
-				DIFF_OPT_SET(&revs->diffopt, RECURSIVE);
-				continue;
-			}
-			if (!strcmp(arg, "-t")) {
-				revs->diff = 1;
-				DIFF_OPT_SET(&revs->diffopt, RECURSIVE);
-				DIFF_OPT_SET(&revs->diffopt, TREE_IN_RECURSIVE);
-				continue;
-			}
-			if (!strcmp(arg, "-m")) {
-				revs->ignore_merges = 0;
-				continue;
-			}
-			if (!strcmp(arg, "-c")) {
-				revs->diff = 1;
-				revs->dense_combined_merges = 0;
-				revs->combine_merges = 1;
-				continue;
-			}
-			if (!strcmp(arg, "--cc")) {
-				revs->diff = 1;
-				revs->dense_combined_merges = 1;
-				revs->combine_merges = 1;
-				continue;
-			}
-			if (!strcmp(arg, "-v")) {
-				revs->verbose_header = 1;
-				continue;
-			}
-			if (!strcmp(arg, "--pretty")) {
-				revs->verbose_header = 1;
-				get_commit_format(arg+8, revs);
-				continue;
-			}
-			if (!prefixcmp(arg, "--pretty=")) {
-				revs->verbose_header = 1;
-				get_commit_format(arg+9, revs);
-				continue;
-			}
-			if (!strcmp(arg, "--graph")) {
-				revs->topo_order = 1;
-				revs->rewrite_parents = 1;
-				revs->graph = graph_init(revs);
-				continue;
-			}
-			if (!strcmp(arg, "--root")) {
-				revs->show_root_diff = 1;
-				continue;
-			}
-			if (!strcmp(arg, "--no-commit-id")) {
-				revs->no_commit_id = 1;
-				continue;
-			}
-			if (!strcmp(arg, "--always")) {
-				revs->always_show_header = 1;
-				continue;
-			}
-			if (!strcmp(arg, "--no-abbrev")) {
-				revs->abbrev = 0;
-				continue;
-			}
-			if (!strcmp(arg, "--abbrev")) {
-				revs->abbrev = DEFAULT_ABBREV;
-				continue;
-			}
-			if (!prefixcmp(arg, "--abbrev=")) {
-				revs->abbrev = strtoul(arg + 9, NULL, 10);
-				if (revs->abbrev < MINIMUM_ABBREV)
-					revs->abbrev = MINIMUM_ABBREV;
-				else if (revs->abbrev > 40)
-					revs->abbrev = 40;
-				continue;
-			}
-			if (!strcmp(arg, "--abbrev-commit")) {
-				revs->abbrev_commit = 1;
-				continue;
-			}
-			if (!strcmp(arg, "--full-diff")) {
-				revs->diff = 1;
-				revs->full_diff = 1;
-				continue;
-			}
-			if (!strcmp(arg, "--full-history")) {
-				revs->simplify_history = 0;
-				continue;
-			}
-			if (!strcmp(arg, "--relative-date")) {
-				revs->date_mode = DATE_RELATIVE;
-				continue;
-			}
-			if (!strncmp(arg, "--date=", 7)) {
-				revs->date_mode = parse_date_format(arg + 7);
-				continue;
-			}
-			if (!strcmp(arg, "--log-size")) {
-				revs->show_log_size = 1;
-				continue;
-			}
-
-			/*
-			 * Grepping the commit log
-			 */
-			if (!prefixcmp(arg, "--author=")) {
-				add_header_grep(revs, "author", arg+9);
-				continue;
-			}
-			if (!prefixcmp(arg, "--committer=")) {
-				add_header_grep(revs, "committer", arg+12);
-				continue;
-			}
-			if (!prefixcmp(arg, "--grep=")) {
-				add_message_grep(revs, arg+7);
-				continue;
-			}
-			if (!strcmp(arg, "--extended-regexp") ||
-			    !strcmp(arg, "-E")) {
-				regflags |= REG_EXTENDED;
-				continue;
-			}
-			if (!strcmp(arg, "--regexp-ignore-case") ||
-			    !strcmp(arg, "-i")) {
-				regflags |= REG_ICASE;
-				continue;
-			}
-			if (!strcmp(arg, "--fixed-strings") ||
-			    !strcmp(arg, "-F")) {
-				fixed = 1;
-				continue;
-			}
-			if (!strcmp(arg, "--all-match")) {
-				all_match = 1;
-				continue;
-			}
-			if (!prefixcmp(arg, "--encoding=")) {
-				arg += 11;
-				if (strcmp(arg, "none"))
-					git_log_output_encoding = xstrdup(arg);
-				else
-					git_log_output_encoding = "";
-				continue;
-			}
-			if (!strcmp(arg, "--reverse")) {
-				revs->reverse ^= 1;
-				continue;
-			}
 			if (!strcmp(arg, "--no-walk")) {
 				revs->no_walk = 1;
 				continue;
@@ -1338,13 +1254,13 @@
 				continue;
 			}
 
-			opts = diff_opt_parse(&revs->diffopt, argv+i, argc-i);
+			opts = handle_revision_opt(revs, argc - i, argv + i, &left, argv);
 			if (opts > 0) {
 				i += opts - 1;
 				continue;
 			}
-			*unrecognized++ = arg;
-			left++;
+			if (opts < 0)
+				exit(128);
 			continue;
 		}
 
@@ -1368,21 +1284,18 @@
 		}
 	}
 
-	if (revs->grep_filter) {
-		revs->grep_filter->regflags |= regflags;
-		revs->grep_filter->fixed = fixed;
-	}
-
-	if (show_merge)
+	if (revs->def == NULL)
+		revs->def = def;
+	if (revs->show_merge)
 		prepare_show_merge(revs);
-	if (def && !revs->pending.nr) {
+	if (revs->def && !revs->pending.nr) {
 		unsigned char sha1[20];
 		struct object *object;
 		unsigned mode;
-		if (get_sha1_with_mode(def, sha1, &mode))
-			die("bad default revision '%s'", def);
-		object = get_reference(revs, def, sha1, 0);
-		add_pending_object_with_mode(revs, object, def, mode);
+		if (get_sha1_with_mode(revs->def, sha1, &mode))
+			die("bad default revision '%s'", revs->def);
+		object = get_reference(revs, revs->def, sha1, 0);
+		add_pending_object_with_mode(revs, object, revs->def, mode);
 	}
 
 	/* Did the user ask for any diff output? Run the diff! */
@@ -1415,13 +1328,12 @@
 	if (diff_setup_done(&revs->diffopt) < 0)
 		die("diff_setup_done failed");
 
-	if (revs->grep_filter) {
-		revs->grep_filter->all_match = all_match;
-		compile_grep_patterns(revs->grep_filter);
-	}
+	compile_grep_patterns(&revs->grep_filter);
 
 	if (revs->reverse && revs->reflog_info)
 		die("cannot combine --reverse with --walk-reflogs");
+	if (revs->rewrite_parents && revs->children.name)
+		die("cannot combine --parents and --children");
 
 	/*
 	 * Limitations on the graph functionality
@@ -1435,6 +1347,26 @@
 	return left;
 }
 
+static void add_child(struct rev_info *revs, struct commit *parent, struct commit *child)
+{
+	struct commit_list *l = xcalloc(1, sizeof(*l));
+
+	l->item = child;
+	l->next = add_decoration(&revs->children, &parent->object, l);
+}
+
+static void set_children(struct rev_info *revs)
+{
+	struct commit_list *l;
+	for (l = revs->commits; l; l = l->next) {
+		struct commit *commit = l->item;
+		struct commit_list *p;
+
+		for (p = commit->parents; p; p = p->next)
+			add_child(revs, p->item, commit);
+	}
+}
+
 int prepare_revision_walk(struct rev_info *revs)
 {
 	int nr = revs->pending.nr;
@@ -1463,6 +1395,8 @@
 			return -1;
 	if (revs->topo_order)
 		sort_in_topological_order(&revs->commits, revs->lifo);
+	if (revs->children.name)
+		set_children(revs);
 	return 0;
 }
 
@@ -1535,13 +1469,18 @@
 
 static int commit_match(struct commit *commit, struct rev_info *opt)
 {
-	if (!opt->grep_filter)
+	if (!opt->grep_filter.pattern_list)
 		return 1;
-	return grep_buffer(opt->grep_filter,
+	return grep_buffer(&opt->grep_filter,
 			   NULL, /* we say nothing, not even filename */
 			   commit->buffer, strlen(commit->buffer));
 }
 
+static inline int want_ancestry(struct rev_info *revs)
+{
+	return (revs->rewrite_parents || revs->children.name);
+}
+
 enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit)
 {
 	if (commit->object.flags & SHOWN)
@@ -1562,13 +1501,13 @@
 		/* Commit without changes? */
 		if (commit->object.flags & TREESAME) {
 			/* drop merges unless we want parenthood */
-			if (!revs->rewrite_parents)
+			if (!want_ancestry(revs))
 				return commit_ignore;
 			/* non-merge - always ignore it */
 			if (!commit->parents || !commit->parents->next)
 				return commit_ignore;
 		}
-		if (revs->rewrite_parents && rewrite_parents(revs, commit) < 0)
+		if (want_ancestry(revs) && rewrite_parents(revs, commit) < 0)
 			return commit_error;
 	}
 	return commit_show;
diff --git a/revision.h b/revision.h
index 31f08c4..91f1944 100644
--- a/revision.h
+++ b/revision.h
@@ -1,6 +1,9 @@
 #ifndef REVISION_H
 #define REVISION_H
 
+#include "parse-options.h"
+#include "grep.h"
+
 #define SEEN		(1u<<0)
 #define UNINTERESTING   (1u<<1)
 #define TREESAME	(1u<<2)
@@ -10,6 +13,7 @@
 #define CHILD_SHOWN	(1u<<6)
 #define ADDED		(1u<<7)	/* Parents already parsed and added? */
 #define SYMMETRIC_LEFT	(1u<<8)
+#define ALL_REV_FLAGS	((1u<<9)-1)
 
 struct rev_info;
 struct log_info;
@@ -24,6 +28,7 @@
 
 	/* Basic information */
 	const char *prefix;
+	const char *def;
 	void *prune_data;
 	unsigned int early_output;
 
@@ -64,6 +69,7 @@
 
 	/* Format info */
 	unsigned int	shown_one:1,
+			show_merge:1,
 			abbrev_commit:1,
 			use_terminator:1,
 			missing_newline:1;
@@ -87,7 +93,7 @@
 	int		show_log_size;
 
 	/* Filter by commit log message */
-	struct grep_opt	*grep_filter;
+	struct grep_opt	grep_filter;
 
 	/* Display history graph */
 	struct git_graph *graph;
@@ -103,6 +109,7 @@
 	struct diff_options pruning;
 
 	struct reflog_walk_info *reflog_info;
+	struct decoration children;
 };
 
 #define REV_TREE_SAME		0
@@ -110,11 +117,16 @@
 #define REV_TREE_DIFFERENT	2
 
 /* revision.c */
+void read_revisions_from_stdin(struct rev_info *revs);
+
 typedef void (*show_early_output_fn_t)(struct rev_info *, struct commit_list *);
-volatile show_early_output_fn_t show_early_output;
+extern volatile show_early_output_fn_t show_early_output;
 
 extern void init_revisions(struct rev_info *revs, const char *prefix);
 extern int setup_revisions(int argc, const char **argv, struct rev_info *revs, const char *def);
+extern void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ctx,
+				 const struct option *options,
+				 const char * const usagestr[]);
 extern int handle_revision_arg(const char *arg, struct rev_info *revs,int flags,int cant_be_filename);
 
 extern int prepare_revision_walk(struct rev_info *revs);
diff --git a/run-command.c b/run-command.c
index 7068ec7..bbb9c77 100644
--- a/run-command.c
+++ b/run-command.c
@@ -67,21 +67,9 @@
 
 	trace_argv_printf(cmd->argv, "trace: run_command:");
 
+#ifndef __MINGW32__
+	fflush(NULL);
 	cmd->pid = fork();
-	if (cmd->pid < 0) {
-		if (need_in)
-			close_pair(fdin);
-		else if (cmd->in)
-			close(cmd->in);
-		if (need_out)
-			close_pair(fdout);
-		else if (cmd->out)
-			close(cmd->out);
-		if (need_err)
-			close_pair(fderr);
-		return -ERR_RUN_COMMAND_FORK;
-	}
-
 	if (!cmd->pid) {
 		if (cmd->no_stdin)
 			dup_devnull(0);
@@ -130,6 +118,85 @@
 		}
 		die("exec %s failed.", cmd->argv[0]);
 	}
+#else
+	int s0 = -1, s1 = -1, s2 = -1;	/* backups of stdin, stdout, stderr */
+	const char **sargv = cmd->argv;
+	char **env = environ;
+
+	if (cmd->no_stdin) {
+		s0 = dup(0);
+		dup_devnull(0);
+	} else if (need_in) {
+		s0 = dup(0);
+		dup2(fdin[0], 0);
+	} else if (cmd->in) {
+		s0 = dup(0);
+		dup2(cmd->in, 0);
+	}
+
+	if (cmd->no_stderr) {
+		s2 = dup(2);
+		dup_devnull(2);
+	} else if (need_err) {
+		s2 = dup(2);
+		dup2(fderr[1], 2);
+	}
+
+	if (cmd->no_stdout) {
+		s1 = dup(1);
+		dup_devnull(1);
+	} else if (cmd->stdout_to_stderr) {
+		s1 = dup(1);
+		dup2(2, 1);
+	} else if (need_out) {
+		s1 = dup(1);
+		dup2(fdout[1], 1);
+	} else if (cmd->out > 1) {
+		s1 = dup(1);
+		dup2(cmd->out, 1);
+	}
+
+	if (cmd->dir)
+		die("chdir in start_command() not implemented");
+	if (cmd->env) {
+		env = copy_environ();
+		for (; *cmd->env; cmd->env++)
+			env = env_setenv(env, *cmd->env);
+	}
+
+	if (cmd->git_cmd) {
+		cmd->argv = prepare_git_cmd(cmd->argv);
+	}
+
+	cmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, env);
+
+	if (cmd->env)
+		free_environ(env);
+	if (cmd->git_cmd)
+		free(cmd->argv);
+
+	cmd->argv = sargv;
+	if (s0 >= 0)
+		dup2(s0, 0), close(s0);
+	if (s1 >= 0)
+		dup2(s1, 1), close(s1);
+	if (s2 >= 0)
+		dup2(s2, 2), close(s2);
+#endif
+
+	if (cmd->pid < 0) {
+		if (need_in)
+			close_pair(fdin);
+		else if (cmd->in)
+			close(cmd->in);
+		if (need_out)
+			close_pair(fdout);
+		else if (cmd->out)
+			close(cmd->out);
+		if (need_err)
+			close_pair(fderr);
+		return -ERR_RUN_COMMAND_FORK;
+	}
 
 	if (need_in)
 		close(fdin[0]);
@@ -221,12 +288,25 @@
 	return run_command(&cmd);
 }
 
+#ifdef __MINGW32__
+static __stdcall unsigned run_thread(void *data)
+{
+	struct async *async = data;
+	return async->proc(async->fd_for_proc, async->data);
+}
+#endif
+
 int start_async(struct async *async)
 {
 	int pipe_out[2];
 
 	if (pipe(pipe_out) < 0)
 		return error("cannot create pipe: %s", strerror(errno));
+	async->out = pipe_out[0];
+
+#ifndef __MINGW32__
+	/* Flush stdio before fork() to avoid cloning buffers */
+	fflush(NULL);
 
 	async->pid = fork();
 	if (async->pid < 0) {
@@ -238,16 +318,33 @@
 		close(pipe_out[0]);
 		exit(!!async->proc(pipe_out[1], async->data));
 	}
-	async->out = pipe_out[0];
 	close(pipe_out[1]);
+#else
+	async->fd_for_proc = pipe_out[1];
+	async->tid = (HANDLE) _beginthreadex(NULL, 0, run_thread, async, 0, NULL);
+	if (!async->tid) {
+		error("cannot create thread: %s", strerror(errno));
+		close_pair(pipe_out);
+		return -1;
+	}
+#endif
 	return 0;
 }
 
 int finish_async(struct async *async)
 {
+#ifndef __MINGW32__
 	int ret = 0;
 
 	if (wait_or_whine(async->pid))
 		ret = error("waitpid (async) failed");
+#else
+	DWORD ret = 0;
+	if (WaitForSingleObject(async->tid, INFINITE) != WAIT_OBJECT_0)
+		ret = error("waiting for thread failed: %lu", GetLastError());
+	else if (!GetExitCodeThread(async->tid, &ret))
+		ret = error("cannot get thread exit code: %lu", GetLastError());
+	CloseHandle(async->tid);
+#endif
 	return ret;
 }
diff --git a/run-command.h b/run-command.h
index debe307..5203a9e 100644
--- a/run-command.h
+++ b/run-command.h
@@ -76,7 +76,12 @@
 	int (*proc)(int fd, void *data);
 	void *data;
 	int out;	/* caller reads from here and closes it */
+#ifndef __MINGW32__
 	pid_t pid;
+#else
+	HANDLE tid;
+	int fd_for_proc;
+#endif
 };
 
 int start_async(struct async *async);
diff --git a/server-info.c b/server-info.c
index c1c073b..66b0d9d 100644
--- a/server-info.c
+++ b/server-info.c
@@ -25,7 +25,7 @@
 
 static int update_info_refs(int force)
 {
-	char *path0 = xstrdup(git_path("info/refs"));
+	char *path0 = git_pathdup("info/refs");
 	int len = strlen(path0);
 	char *path1 = xmalloc(len + 2);
 
diff --git a/setup.c b/setup.c
index 3b111ea..78a8041 100644
--- a/setup.c
+++ b/setup.c
@@ -6,11 +6,17 @@
 
 static int sanitary_path_copy(char *dst, const char *src)
 {
-	char *dst0 = dst;
+	char *dst0;
 
-	if (*src == '/') {
+	if (has_dos_drive_prefix(src)) {
+		*dst++ = *src++;
+		*dst++ = *src++;
+	}
+	dst0 = dst;
+
+	if (is_dir_sep(*src)) {
 		*dst++ = '/';
-		while (*src == '/')
+		while (is_dir_sep(*src))
 			src++;
 	}
 
@@ -26,27 +32,24 @@
 		 * (4) "../"          -- strip one, eat slash and continue.
 		 */
 		if (c == '.') {
-			switch (src[1]) {
-			case '\0':
+			if (!src[1]) {
 				/* (1) */
 				src++;
-				break;
-			case '/':
+			} else if (is_dir_sep(src[1])) {
 				/* (2) */
 				src += 2;
-				while (*src == '/')
+				while (is_dir_sep(*src))
 					src++;
 				continue;
-			case '.':
-				switch (src[2]) {
-				case '\0':
+			} else if (src[1] == '.') {
+				if (!src[2]) {
 					/* (3) */
 					src += 2;
 					goto up_one;
-				case '/':
+				} else if (is_dir_sep(src[2])) {
 					/* (4) */
 					src += 3;
-					while (*src == '/')
+					while (is_dir_sep(*src))
 						src++;
 					goto up_one;
 				}
@@ -54,11 +57,11 @@
 		}
 
 		/* copy up to the next '/', and eat all '/' */
-		while ((c = *src++) != '\0' && c != '/')
+		while ((c = *src++) != '\0' && !is_dir_sep(c))
 			*dst++ = c;
-		if (c == '/') {
-			*dst++ = c;
-			while (c == '/')
+		if (is_dir_sep(c)) {
+			*dst++ = '/';
+			while (is_dir_sep(c))
 				c = *src++;
 			src--;
 		} else if (!c)
@@ -77,7 +80,7 @@
 			if (dst <= dst0)
 				break;
 			c = *dst--;
-			if (c == '/') {
+			if (c == '/') {	/* MinGW: cannot be '\\' anymore */
 				dst += 2;
 				break;
 			}
@@ -107,9 +110,7 @@
 		if (strncmp(sanitized, work_tree, len) ||
 		    (sanitized[len] != '\0' && sanitized[len] != '/')) {
 		error_out:
-			error("'%s' is outside repository", orig);
-			free(sanitized);
-			return NULL;
+			die("'%s' is outside repository", orig);
 		}
 		if (sanitized[len] == '/')
 			len++;
@@ -126,10 +127,23 @@
 const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
 {
 	static char path[PATH_MAX];
+#ifndef __MINGW32__
 	if (!pfx || !*pfx || is_absolute_path(arg))
 		return arg;
 	memcpy(path, pfx, pfx_len);
 	strcpy(path + pfx_len, arg);
+#else
+	char *p;
+	/* don't add prefix to absolute paths, but still replace '\' by '/' */
+	if (is_absolute_path(arg))
+		pfx_len = 0;
+	else
+		memcpy(path, pfx, pfx_len);
+	strcpy(path + pfx_len, arg);
+	for (p = path + pfx_len; *p; p++)
+		if (*p == '\\')
+			*p = '/';
+#endif
 	return path;
 }
 
@@ -200,10 +214,7 @@
 	prefixlen = prefix ? strlen(prefix) : 0;
 	while (*src) {
 		const char *p = prefix_path(prefix, prefixlen, *src);
-		if (p)
-			*(dst++) = p;
-		else
-			exit(128); /* error message already given */
+		*(dst++) = p;
 		src++;
 	}
 	*dst = NULL;
@@ -360,10 +371,11 @@
 const char *setup_git_directory_gently(int *nongit_ok)
 {
 	const char *work_tree_env = getenv(GIT_WORK_TREE_ENVIRONMENT);
+	const char *env_ceiling_dirs = getenv(CEILING_DIRECTORIES_ENVIRONMENT);
 	static char cwd[PATH_MAX+1];
 	const char *gitdirenv;
 	const char *gitfile_dir;
-	int len, offset;
+	int len, offset, ceil_offset;
 
 	/*
 	 * Let's assume that we are in a git repository.
@@ -415,6 +427,10 @@
 	if (!getcwd(cwd, sizeof(cwd)-1))
 		die("Unable to read current working directory");
 
+	ceil_offset = longest_ancestor_length(cwd, env_ceiling_dirs);
+	if (ceil_offset < 0 && has_dos_drive_prefix(cwd))
+		ceil_offset = 1;
+
 	/*
 	 * Test in the following order (relative to the cwd):
 	 * - .git (file containing "gitdir: <path>")
@@ -444,18 +460,17 @@
 			check_repository_format_gently(nongit_ok);
 			return NULL;
 		}
-		chdir("..");
-		do {
-			if (!offset) {
-				if (nongit_ok) {
-					if (chdir(cwd))
-						die("Cannot come back to cwd");
-					*nongit_ok = 1;
-					return NULL;
-				}
-				die("Not a git repository");
+		while (--offset > ceil_offset && cwd[offset] != '/');
+		if (offset <= ceil_offset) {
+			if (nongit_ok) {
+				if (chdir(cwd))
+					die("Cannot come back to cwd");
+				*nongit_ok = 1;
+				return NULL;
 			}
-		} while (cwd[--offset] != '/');
+			die("Not a git repository");
+		}
+		chdir("..");
 	}
 
 	inside_git_dir = 0;
@@ -561,6 +576,8 @@
 		if (retval && chdir(retval))
 			die ("Could not jump back into original cwd");
 		rel = get_relative_cwd(buffer, PATH_MAX, get_git_work_tree());
+		if (rel && *rel && chdir(get_git_work_tree()))
+			die ("Could not jump to working directory");
 		return rel && *rel ? strcat(rel, "/") : NULL;
 	}
 
diff --git a/sha1_file.c b/sha1_file.c
index ff3bb49..88035a0 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -83,14 +83,18 @@
 	return 0;
 }
 
+static inline int offset_1st_component(const char *path)
+{
+	if (has_dos_drive_prefix(path))
+		return 2 + (path[2] == '/');
+	return *path == '/';
+}
+
 int safe_create_leading_directories(char *path)
 {
-	char *pos = path;
+	char *pos = path + offset_1st_component(path);
 	struct stat st;
 
-	if (is_absolute_path(path))
-		pos++;
-
 	while (pos) {
 		pos = strchr(pos, '/');
 		if (!pos)
@@ -381,7 +385,7 @@
 void add_to_alternates_file(const char *reference)
 {
 	struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));
-	int fd = hold_lock_file_for_append(lock, git_path("objects/info/alternates"), 1);
+	int fd = hold_lock_file_for_append(lock, git_path("objects/info/alternates"), LOCK_DIE_ON_ERROR);
 	char *alt = mkpath("%s/objects\n", reference);
 	write_or_die(fd, alt, strlen(alt));
 	if (commit_lock_file(lock))
@@ -401,28 +405,35 @@
 	if (!alt) alt = "";
 
 	alt_odb_tail = &alt_odb_list;
-	link_alt_odb_entries(alt, alt + strlen(alt), ':', NULL, 0);
+	link_alt_odb_entries(alt, alt + strlen(alt), PATH_SEP, NULL, 0);
 
 	read_info_alternates(get_object_directory(), 0);
 }
 
-static int has_loose_object(const unsigned char *sha1)
+static int has_loose_object_local(const unsigned char *sha1)
 {
 	char *name = sha1_file_name(sha1);
-	struct alternate_object_database *alt;
+	return !access(name, F_OK);
+}
 
-	if (!access(name, F_OK))
-		return 1;
+int has_loose_object_nonlocal(const unsigned char *sha1)
+{
+	struct alternate_object_database *alt;
 	prepare_alt_odb();
 	for (alt = alt_odb_list; alt; alt = alt->next) {
-		name = alt->name;
-		fill_sha1_path(name, sha1);
+		fill_sha1_path(alt->name, sha1);
 		if (!access(alt->base, F_OK))
 			return 1;
 	}
 	return 0;
 }
 
+static int has_loose_object(const unsigned char *sha1)
+{
+	return has_loose_object_local(sha1) ||
+	       has_loose_object_nonlocal(sha1);
+}
+
 static unsigned int pack_used_ctr;
 static unsigned int pack_mmap_calls;
 static unsigned int peak_pack_open_windows;
@@ -480,7 +491,7 @@
 		version = ntohl(hdr->idx_version);
 		if (version < 2 || version > 2) {
 			munmap(idx_map, idx_size);
-			return error("index file %s is version %d"
+			return error("index file %s is version %"PRIu32
 				     " and is not supported by this binary"
 				     " (try upgrading GIT to a newer version)",
 				     path, version);
@@ -649,6 +660,37 @@
 }
 
 /*
+ * This is used by git-repack in case a newly created pack happens to
+ * contain the same set of objects as an existing one.  In that case
+ * the resulting file might be different even if its name would be the
+ * same.  It is best to close any reference to the old pack before it is
+ * replaced on disk.  Of course no index pointers nor windows for given pack
+ * must subsist at this point.  If ever objects from this pack are requested
+ * again, the new version of the pack will be reinitialized through
+ * reprepare_packed_git().
+ */
+void free_pack_by_name(const char *pack_name)
+{
+	struct packed_git *p, **pp = &packed_git;
+
+	while (*pp) {
+		p = *pp;
+		if (strcmp(pack_name, p->pack_name) == 0) {
+			close_pack_windows(p);
+			if (p->pack_fd != -1)
+				close(p->pack_fd);
+			if (p->index_data)
+				munmap((void *)p->index_data, p->index_size);
+			free(p->bad_object_sha1);
+			*pp = p->next;
+			free(p);
+			return;
+		}
+		pp = &p->next;
+	}
+}
+
+/*
  * Do not call this directly as this leaks p->pack_fd on error return;
  * call open_packed_git() instead.
  */
@@ -691,14 +733,14 @@
 	if (hdr.hdr_signature != htonl(PACK_SIGNATURE))
 		return error("file %s is not a GIT packfile", p->pack_name);
 	if (!pack_version_ok(hdr.hdr_version))
-		return error("packfile %s is version %u and not supported"
-			" (try upgrading GIT to a newer version)",
+		return error("packfile %s is version %"PRIu32" and not"
+			" supported (try upgrading GIT to a newer version)",
 			p->pack_name, ntohl(hdr.hdr_version));
 
 	/* Verify the pack matches its index. */
 	if (p->num_objects != ntohl(hdr.hdr_entries))
-		return error("packfile %s claims to have %u objects"
-			     " while index indicates %u objects",
+		return error("packfile %s claims to have %"PRIu32" objects"
+			     " while index indicates %"PRIu32" objects",
 			     p->pack_name, ntohl(hdr.hdr_entries),
 			     p->num_objects);
 	if (lseek(p->pack_fd, p->pack_size - sizeof(sha1), SEEK_SET) == -1)
@@ -801,19 +843,34 @@
 	return win->base + offset;
 }
 
+static struct packed_git *alloc_packed_git(int extra)
+{
+	struct packed_git *p = xmalloc(sizeof(*p) + extra);
+	memset(p, 0, sizeof(*p));
+	p->pack_fd = -1;
+	return p;
+}
+
 struct packed_git *add_packed_git(const char *path, int path_len, int local)
 {
 	struct stat st;
-	struct packed_git *p = xmalloc(sizeof(*p) + path_len + 2);
+	struct packed_git *p = alloc_packed_git(path_len + 2);
 
 	/*
 	 * Make sure a corresponding .pack file exists and that
 	 * the index looks sane.
 	 */
 	path_len -= strlen(".idx");
-	if (path_len < 1)
+	if (path_len < 1) {
+		free(p);
 		return NULL;
+	}
 	memcpy(p->pack_name, path, path_len);
+
+	strcpy(p->pack_name + path_len, ".keep");
+	if (!access(p->pack_name, F_OK))
+		p->pack_keep = 1;
+
 	strcpy(p->pack_name + path_len, ".pack");
 	if (stat(p->pack_name, &st) || !S_ISREG(st.st_mode)) {
 		free(p);
@@ -823,14 +880,7 @@
 	/* ok, it looks sane as far as we can check without
 	 * actually mapping the pack file.
 	 */
-	p->index_version = 0;
-	p->index_data = NULL;
-	p->index_size = 0;
-	p->num_objects = 0;
 	p->pack_size = st.st_size;
-	p->next = NULL;
-	p->windows = NULL;
-	p->pack_fd = -1;
 	p->pack_local = local;
 	p->mtime = st.st_mtime;
 	if (path_len < 40 || get_sha1_hex(path + path_len - 40, p->sha1))
@@ -842,19 +892,15 @@
 {
 	const char *idx_path = sha1_pack_index_name(sha1);
 	const char *path = sha1_pack_name(sha1);
-	struct packed_git *p = xmalloc(sizeof(*p) + strlen(path) + 2);
+	struct packed_git *p = alloc_packed_git(strlen(path) + 1);
 
+	strcpy(p->pack_name, path);
+	hashcpy(p->sha1, sha1);
 	if (check_packed_git_idx(idx_path, p)) {
 		free(p);
 		return NULL;
 	}
 
-	strcpy(p->pack_name, path);
-	p->pack_size = 0;
-	p->next = NULL;
-	p->windows = NULL;
-	p->pack_fd = -1;
-	hashcpy(p->sha1, sha1);
 	return p;
 }
 
@@ -987,10 +1033,35 @@
 
 void reprepare_packed_git(void)
 {
+	discard_revindex();
 	prepare_packed_git_run_once = 0;
 	prepare_packed_git();
 }
 
+static void mark_bad_packed_object(struct packed_git *p,
+				   const unsigned char *sha1)
+{
+	unsigned i;
+	for (i = 0; i < p->num_bad_objects; i++)
+		if (!hashcmp(sha1, p->bad_object_sha1 + 20 * i))
+			return;
+	p->bad_object_sha1 = xrealloc(p->bad_object_sha1, 20 * (p->num_bad_objects + 1));
+	hashcpy(p->bad_object_sha1 + 20 * p->num_bad_objects, sha1);
+	p->num_bad_objects++;
+}
+
+static int has_packed_and_bad(const unsigned char *sha1)
+{
+	struct packed_git *p;
+	unsigned i;
+
+	for (p = packed_git; p; p = p->next)
+		for (i = 0; i < p->num_bad_objects; i++)
+			if (!hashcmp(sha1, p->bad_object_sha1 + 20 * i))
+				return 1;
+	return 0;
+}
+
 int check_sha1_signature(const unsigned char *sha1, void *map, unsigned long size, const char *type)
 {
 	unsigned char real_sha1[20];
@@ -1309,20 +1380,17 @@
 		while (c & 128) {
 			base_offset += 1;
 			if (!base_offset || MSB(base_offset, 7))
-				die("offset value overflow for delta base object");
+				return 0;  /* overflow */
 			c = base_info[used++];
 			base_offset = (base_offset << 7) + (c & 127);
 		}
 		base_offset = delta_obj_offset - base_offset;
 		if (base_offset >= delta_obj_offset)
-			die("delta base offset out of bound");
+			return 0;  /* out of bound */
 		*curpos += used;
 	} else if (type == OBJ_REF_DELTA) {
 		/* The base entry _must_ be in the same pack */
 		base_offset = find_pack_entry_one(base_info, p);
-		if (!base_offset)
-			die("failed to find delta-pack base object %s",
-				sha1_to_hex(base_info));
 		*curpos += 20;
 	} else
 		die("I am totally screwed");
@@ -1415,6 +1483,9 @@
 			return typename(type);
 		case OBJ_OFS_DELTA:
 			obj_offset = get_delta_base(p, &w_curs, &curpos, type, obj_offset);
+			if (!obj_offset)
+				die("pack %s contains bad delta base reference of type %s",
+				    p->pack_name, typename(type));
 			if (*delta_chain_length == 0) {
 				revidx = find_pack_revindex(p, obj_offset);
 				hashcpy(base_sha1, nth_packed_object_sha1(p, revidx->nr));
@@ -1609,18 +1680,42 @@
 	off_t base_offset;
 
 	base_offset = get_delta_base(p, w_curs, &curpos, *type, obj_offset);
+	if (!base_offset) {
+		error("failed to validate delta base reference "
+		      "at offset %"PRIuMAX" from %s",
+		      (uintmax_t)curpos, p->pack_name);
+		return NULL;
+	}
 	unuse_pack(w_curs);
 	base = cache_or_unpack_entry(p, base_offset, &base_size, type, 0);
-	if (!base)
-		die("failed to read delta base object"
-		    " at %"PRIuMAX" from %s",
-		    (uintmax_t)base_offset, p->pack_name);
+	if (!base) {
+		/*
+		 * We're probably in deep shit, but let's try to fetch
+		 * the required base anyway from another pack or loose.
+		 * This is costly but should happen only in the presence
+		 * of a corrupted pack, and is better than failing outright.
+		 */
+		struct revindex_entry *revidx = find_pack_revindex(p, base_offset);
+		const unsigned char *base_sha1 =
+					nth_packed_object_sha1(p, revidx->nr);
+		error("failed to read delta base object %s"
+		      " at offset %"PRIuMAX" from %s",
+		      sha1_to_hex(base_sha1), (uintmax_t)base_offset,
+		      p->pack_name);
+		mark_bad_packed_object(p, base_sha1);
+		base = read_object(base_sha1, type, &base_size);
+		if (!base)
+			return NULL;
+	}
 
 	delta_data = unpack_compressed_entry(p, w_curs, curpos, delta_size);
-	if (!delta_data)
-		die("failed to unpack compressed delta"
-		    " at %"PRIuMAX" from %s",
-		    (uintmax_t)curpos, p->pack_name);
+	if (!delta_data) {
+		error("failed to unpack compressed delta "
+		      "at offset %"PRIuMAX" from %s",
+		      (uintmax_t)curpos, p->pack_name);
+		free(base);
+		return NULL;
+	}
 	result = patch_delta(base, base_size,
 			     delta_data, delta_size,
 			     sizep);
@@ -1652,7 +1747,9 @@
 		data = unpack_compressed_entry(p, &w_curs, curpos, *sizep);
 		break;
 	default:
-		die("unknown object type %i in %s", *type, p->pack_name);
+		data = NULL;
+		error("unknown object type %i at offset %"PRIuMAX" in %s",
+		      *type, (uintmax_t)obj_offset, p->pack_name);
 	}
 	unuse_pack(&w_curs);
 	return data;
@@ -1678,7 +1775,7 @@
 	}
 }
 
-static off_t nth_packed_object_offset(const struct packed_git *p, uint32_t n)
+off_t nth_packed_object_offset(const struct packed_git *p, uint32_t n)
 {
 	const unsigned char *index = p->index_data;
 	index += 4 * 256;
@@ -1729,7 +1826,7 @@
 	}
 
 	if (debug_lookup)
-		printf("%02x%02x%02x... lo %u hi %u nr %u\n",
+		printf("%02x%02x%02x... lo %u hi %u nr %"PRIu32"\n",
 		       sha1[0], sha1[1], sha1[2], lo, hi, p->num_objects);
 
 	if (use_lookup < 0)
@@ -1798,6 +1895,13 @@
 				goto next;
 		}
 
+		if (p->num_bad_objects) {
+			unsigned i;
+			for (i = 0; i < p->num_bad_objects; i++)
+				if (!hashcmp(sha1, p->bad_object_sha1 + 20 * i))
+					goto next;
+		}
+
 		offset = find_pack_entry_one(sha1, p);
 		if (offset) {
 			/*
@@ -1869,11 +1973,18 @@
 int sha1_object_info(const unsigned char *sha1, unsigned long *sizep)
 {
 	struct pack_entry e;
+	int status;
 
 	if (!find_pack_entry(sha1, &e, NULL)) {
+		/* Most likely it's a loose object. */
+		status = sha1_loose_object_info(sha1, sizep);
+		if (status >= 0)
+			return status;
+
+		/* Not a loose object; someone else may have just packed it. */
 		reprepare_packed_git();
 		if (!find_pack_entry(sha1, &e, NULL))
-			return sha1_loose_object_info(sha1, sizep);
+			return status;
 	}
 	return packed_object_info(e.p, e.offset, sizep);
 }
@@ -1882,11 +1993,24 @@
 			      enum object_type *type, unsigned long *size)
 {
 	struct pack_entry e;
+	void *data;
 
 	if (!find_pack_entry(sha1, &e, NULL))
 		return NULL;
-	else
-		return cache_or_unpack_entry(e.p, e.offset, size, type, 1);
+	data = cache_or_unpack_entry(e.p, e.offset, size, type, 1);
+	if (!data) {
+		/*
+		 * We're probably in deep shit, but let's try to fetch
+		 * the required object anyway from another pack or loose.
+		 * This should happen only in the presence of a corrupted
+		 * pack, and is better than failing outright.
+		 */
+		error("failed to read object %s at offset %"PRIuMAX" from %s",
+		      sha1_to_hex(sha1), (uintmax_t)e.offset, e.p->pack_name);
+		mark_bad_packed_object(e.p, sha1);
+		data = read_object(sha1, type, size);
+	}
+	return data;
 }
 
 /*
@@ -1949,8 +2073,8 @@
 	return 0;
 }
 
-void *read_sha1_file(const unsigned char *sha1, enum object_type *type,
-		     unsigned long *size)
+void *read_object(const unsigned char *sha1, enum object_type *type,
+		  unsigned long *size)
 {
 	unsigned long mapsize;
 	void *map, *buf;
@@ -1976,6 +2100,16 @@
 	return read_packed_sha1(sha1, type, size);
 }
 
+void *read_sha1_file(const unsigned char *sha1, enum object_type *type,
+		     unsigned long *size)
+{
+	void *data = read_object(sha1, type, size);
+	/* legacy behavior is to die on corrupted objects */
+	if (!data && (has_loose_object(sha1) || has_packed_and_bad(sha1)))
+		die("object %s is corrupted", sha1_to_hex(sha1));
+	return data;
+}
+
 void *read_object_with_reference(const unsigned char *sha1,
 				 const char *required_type_name,
 				 unsigned long *size,
@@ -2045,7 +2179,9 @@
  */
 int move_temp_to_file(const char *tmpfile, const char *filename)
 {
-	int ret = link(tmpfile, filename);
+	int ret = 0;
+	if (link(tmpfile, filename))
+		ret = errno;
 
 	/*
 	 * Coda hack - coda doesn't like cross-directory links,
@@ -2127,7 +2263,7 @@
 	memcpy(buffer, filename, dirlen);
 	strcpy(buffer + dirlen, "tmp_obj_XXXXXX");
 	fd = mkstemp(buffer);
-	if (fd < 0 && dirlen) {
+	if (fd < 0 && dirlen && errno == ENOENT) {
 		/* Make sure the directory exists */
 		memcpy(buffer, filename, dirlen);
 		buffer[dirlen-1] = 0;
@@ -2153,7 +2289,7 @@
 	filename = sha1_file_name(sha1);
 	fd = create_tmpfile(tmpfile, sizeof(tmpfile), filename);
 	if (fd < 0) {
-		if (errno == EPERM)
+		if (errno == EACCES)
 			return error("insufficient permission for adding an object to repository database %s\n", get_object_directory());
 		else
 			return error("unable to create temporary sha1 filename %s: %s\n", tmpfile, strerror(errno));
@@ -2229,6 +2365,7 @@
 	enum object_type type;
 	char hdr[32];
 	int hdrlen;
+	int ret;
 
 	if (has_loose_object(sha1))
 		return 0;
@@ -2236,7 +2373,10 @@
 	if (!buf)
 		return error("cannot read sha1_file for %s", sha1_to_hex(sha1));
 	hdrlen = sprintf(hdr, "%s %lu", typename(type), len) + 1;
-	return write_loose_object(sha1, hdr, hdrlen, buf, len, mtime);
+	ret = write_loose_object(sha1, hdr, hdrlen, buf, len, mtime);
+	free(buf);
+
+	return ret;
 }
 
 int has_pack_index(const unsigned char *sha1)
diff --git a/sha1_name.c b/sha1_name.c
index b0b2167..75a5a7e 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -245,11 +245,13 @@
 
 	*ref = NULL;
 	for (p = ref_rev_parse_rules; *p; p++) {
+		char fullref[PATH_MAX];
 		unsigned char sha1_from_ref[20];
 		unsigned char *this_result;
 
 		this_result = refs_found ? sha1_from_ref : sha1;
-		r = resolve_ref(mkpath(*p, len, str), this_result, 1, NULL);
+		mksnpath(fullref, sizeof(fullref), *p, len, str);
+		r = resolve_ref(fullref, this_result, 1, NULL);
 		if (r) {
 			if (!refs_found++)
 				*ref = xstrdup(r);
@@ -272,8 +274,8 @@
 		char path[PATH_MAX];
 		const char *ref, *it;
 
-		strcpy(path, mkpath(*p, len, str));
-		ref = resolve_ref(path, hash, 0, NULL);
+		mksnpath(path, sizeof(path), *p, len, str);
+		ref = resolve_ref(path, hash, 1, NULL);
 		if (!ref)
 			continue;
 		if (!stat(git_path("logs/%s", path), &st) &&
diff --git a/shell.c b/shell.c
index b27d01c..e339369 100644
--- a/shell.c
+++ b/shell.c
@@ -7,7 +7,7 @@
 {
 	const char *my_argv[4];
 
-	setup_path(NULL);
+	setup_path();
 	if (!arg || !(arg = sq_dequote(arg)))
 		die("bad argument");
 	if (prefixcmp(me, "git-"))
@@ -29,7 +29,7 @@
 	if (!arg || strcmp(arg, "server"))
 		die("git-cvsserver only handles server: %s", arg);
 
-	setup_path(NULL);
+	setup_path();
 	return execv_git_cmd(cvsserver_argv);
 }
 
@@ -48,6 +48,19 @@
 {
 	char *prog;
 	struct commands *cmd;
+	int devnull_fd;
+
+	/*
+	 * Always open file descriptors 0/1/2 to avoid clobbering files
+	 * in die().  It also avoids not messing up when the pipes are
+	 * dup'ed onto stdin/stdout/stderr in the child processes we spawn.
+	 */
+	devnull_fd = open("/dev/null", O_RDWR);
+	while (devnull_fd >= 0 && devnull_fd <= 2)
+		devnull_fd = dup(devnull_fd);
+	if (devnull_fd == -1)
+		die("opening /dev/null failed (%s)", strerror(errno));
+	close (devnull_fd);
 
 	/*
 	 * Special hack to pretend to be a CVS server
diff --git a/shortlog.h b/shortlog.h
index 31ff491..bc02cc2 100644
--- a/shortlog.h
+++ b/shortlog.h
@@ -1,20 +1,21 @@
 #ifndef SHORTLOG_H
 #define SHORTLOG_H
 
-#include "path-list.h"
+#include "string-list.h"
 
 struct shortlog {
-	struct path_list list;
+	struct string_list list;
 	int summary;
 	int wrap_lines;
 	int sort_by_number;
 	int wrap;
 	int in1;
 	int in2;
+	int user_format;
 
 	char *common_repo_prefix;
 	int email;
-	struct path_list mailmap;
+	struct string_list mailmap;
 };
 
 void shortlog_init(struct shortlog *log);
diff --git a/show-index.c b/show-index.c
index 7253991..45bb535 100644
--- a/show-index.c
+++ b/show-index.c
@@ -68,7 +68,8 @@
 						     ntohl(off64[1]);
 				off64_nr++;
 			}
-			printf("%" PRIuMAX " %s (%08x)\n", (uintmax_t) offset,
+			printf("%" PRIuMAX " %s (%08"PRIx32")\n",
+			       (uintmax_t) offset,
 			       sha1_to_hex(entries[i].sha1),
 			       ntohl(entries[i].crc));
 		}
diff --git a/sideband.c b/sideband.c
index b677781..cca3360 100644
--- a/sideband.c
+++ b/sideband.c
@@ -25,6 +25,7 @@
 	unsigned sf;
 	char buf[LARGE_PACKET_MAX + 2*FIX_SIZE];
 	char *suffix, *term;
+	int skip_pf = 0;
 
 	memcpy(buf, PREFIX, pf);
 	term = getenv("TERM");
@@ -54,39 +55,58 @@
 			return SIDEBAND_REMOTE_ERROR;
 		case 2:
 			buf[pf] = ' ';
-			len += pf+1;
-			while (1) {
-				int brk = pf+1;
+			do {
+				char *b = buf;
+				int brk = 0;
 
-				/* Break the buffer into separate lines. */
-				while (brk < len) {
+				/*
+				 * If the last buffer didn't end with a line
+				 * break then we should not print a prefix
+				 * this time around.
+				 */
+				if (skip_pf) {
+					b += pf+1;
+				} else {
+					len += pf+1;
+					brk += pf+1;
+				}
+
+				/* Look for a line break. */
+				for (;;) {
 					brk++;
-					if (buf[brk-1] == '\n' ||
-					    buf[brk-1] == '\r')
+					if (brk > len) {
+						brk = 0;
+						break;
+					}
+					if (b[brk-1] == '\n' ||
+					    b[brk-1] == '\r')
 						break;
 				}
 
 				/*
 				 * Let's insert a suffix to clear the end
-				 * of the screen line, but only if current
-				 * line data actually contains something.
+				 * of the screen line if a line break was
+				 * found.  Also, if we don't skip the
+				 * prefix, then a non-empty string must be
+				 * present too.
 				 */
-				if (brk > pf+1 + 1) {
+				if (brk > (skip_pf ? 0 : (pf+1 + 1))) {
 					char save[FIX_SIZE];
-					memcpy(save, buf + brk, sf);
-					buf[brk + sf - 1] = buf[brk - 1];
-					memcpy(buf + brk - 1, suffix, sf);
-					safe_write(err, buf, brk + sf);
-					memcpy(buf + brk, save, sf);
-				} else
-					safe_write(err, buf, brk);
+					memcpy(save, b + brk, sf);
+					b[brk + sf - 1] = b[brk - 1];
+					memcpy(b + brk - 1, suffix, sf);
+					safe_write(err, b, brk + sf);
+					memcpy(b + brk, save, sf);
+					len -= brk;
+				} else {
+					int l = brk ? brk : len;
+					safe_write(err, b, l);
+					len -= l;
+				}
 
-				if (brk < len) {
-					memmove(buf + pf+1, buf + brk, len - brk);
-					len = len - brk + pf+1;
-				} else
-					break;
-			}
+				skip_pf = !brk;
+				memmove(buf + pf+1, b + brk, len);
+			} while (len);
 			continue;
 		case 1:
 			safe_write(out, buf + pf+1, len);
diff --git a/strbuf.c b/strbuf.c
index 4aed752..720737d 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -60,6 +60,18 @@
 	ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc);
 }
 
+void strbuf_trim(struct strbuf *sb)
+{
+	char *b = sb->buf;
+	while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))
+		sb->len--;
+	while (sb->len > 0 && isspace(*b)) {
+		b++;
+		sb->len--;
+	}
+	memmove(sb->buf, b, sb->len);
+	sb->buf[sb->len] = '\0';
+}
 void strbuf_rtrim(struct strbuf *sb)
 {
 	while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))
@@ -67,7 +79,65 @@
 	sb->buf[sb->len] = '\0';
 }
 
-int strbuf_cmp(struct strbuf *a, struct strbuf *b)
+void strbuf_ltrim(struct strbuf *sb)
+{
+	char *b = sb->buf;
+	while (sb->len > 0 && isspace(*b)) {
+		b++;
+		sb->len--;
+	}
+	memmove(sb->buf, b, sb->len);
+	sb->buf[sb->len] = '\0';
+}
+
+void strbuf_tolower(struct strbuf *sb)
+{
+	int i;
+	for (i = 0; i < sb->len; i++)
+		sb->buf[i] = tolower(sb->buf[i]);
+}
+
+struct strbuf **strbuf_split(const struct strbuf *sb, int delim)
+{
+	int alloc = 2, pos = 0;
+	char *n, *p;
+	struct strbuf **ret;
+	struct strbuf *t;
+
+	ret = xcalloc(alloc, sizeof(struct strbuf *));
+	p = n = sb->buf;
+	while (n < sb->buf + sb->len) {
+		int len;
+		n = memchr(n, delim, sb->len - (n - sb->buf));
+		if (pos + 1 >= alloc) {
+			alloc = alloc * 2;
+			ret = xrealloc(ret, sizeof(struct strbuf *) * alloc);
+		}
+		if (!n)
+			n = sb->buf + sb->len - 1;
+		len = n - p + 1;
+		t = xmalloc(sizeof(struct strbuf));
+		strbuf_init(t, len);
+		strbuf_add(t, p, len);
+		ret[pos] = t;
+		ret[++pos] = NULL;
+		p = ++n;
+	}
+	return ret;
+}
+
+void strbuf_list_free(struct strbuf **sbs)
+{
+	struct strbuf **s = sbs;
+
+	while (*s) {
+		strbuf_release(*s);
+		free(*s++);
+	}
+	free(sbs);
+}
+
+int strbuf_cmp(const struct strbuf *a, const struct strbuf *b)
 {
 	int cmp;
 	if (a->len < b->len) {
diff --git a/strbuf.h b/strbuf.h
index faec229..eba7ba4 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -61,7 +61,7 @@
 }
 
 /*----- strbuf size related -----*/
-static inline size_t strbuf_avail(struct strbuf *sb) {
+static inline size_t strbuf_avail(const struct strbuf *sb) {
 	return sb->alloc ? sb->alloc - sb->len - 1 : 0;
 }
 
@@ -77,8 +77,14 @@
 #define strbuf_reset(sb)  strbuf_setlen(sb, 0)
 
 /*----- content related -----*/
+extern void strbuf_trim(struct strbuf *);
 extern void strbuf_rtrim(struct strbuf *);
-extern int strbuf_cmp(struct strbuf *, struct strbuf *);
+extern void strbuf_ltrim(struct strbuf *);
+extern int strbuf_cmp(const struct strbuf *, const struct strbuf *);
+extern void strbuf_tolower(struct strbuf *);
+
+extern struct strbuf **strbuf_split(const struct strbuf *, int delim);
+extern void strbuf_list_free(struct strbuf **);
 
 /*----- add data in your buffer -----*/
 static inline void strbuf_addch(struct strbuf *sb, int c) {
@@ -98,7 +104,7 @@
 static inline void strbuf_addstr(struct strbuf *sb, const char *s) {
 	strbuf_add(sb, s, strlen(s));
 }
-static inline void strbuf_addbuf(struct strbuf *sb, struct strbuf *sb2) {
+static inline void strbuf_addbuf(struct strbuf *sb, const struct strbuf *sb2) {
 	strbuf_add(sb, sb2->buf, sb2->len);
 }
 extern void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len);
@@ -117,6 +123,6 @@
 extern int strbuf_getline(struct strbuf *, FILE *, int);
 
 extern void stripspace(struct strbuf *buf, int skip_comments);
-extern void launch_editor(const char *path, struct strbuf *buffer, const char *const *env);
+extern int launch_editor(const char *path, struct strbuf *buffer, const char *const *env);
 
 #endif /* STRBUF_H */
diff --git a/string-list.c b/string-list.c
new file mode 100644
index 0000000..ddd83c8
--- /dev/null
+++ b/string-list.c
@@ -0,0 +1,134 @@
+#include "cache.h"
+#include "string-list.h"
+
+/* if there is no exact match, point to the index where the entry could be
+ * inserted */
+static int get_entry_index(const struct string_list *list, const char *string,
+		int *exact_match)
+{
+	int left = -1, right = list->nr;
+
+	while (left + 1 < right) {
+		int middle = (left + right) / 2;
+		int compare = strcmp(string, list->items[middle].string);
+		if (compare < 0)
+			right = middle;
+		else if (compare > 0)
+			left = middle;
+		else {
+			*exact_match = 1;
+			return middle;
+		}
+	}
+
+	*exact_match = 0;
+	return right;
+}
+
+/* returns -1-index if already exists */
+static int add_entry(struct string_list *list, const char *string)
+{
+	int exact_match;
+	int index = get_entry_index(list, string, &exact_match);
+
+	if (exact_match)
+		return -1 - index;
+
+	if (list->nr + 1 >= list->alloc) {
+		list->alloc += 32;
+		list->items = xrealloc(list->items, list->alloc
+				* sizeof(struct string_list_item));
+	}
+	if (index < list->nr)
+		memmove(list->items + index + 1, list->items + index,
+				(list->nr - index)
+				* sizeof(struct string_list_item));
+	list->items[index].string = list->strdup_strings ?
+		xstrdup(string) : (char *)string;
+	list->items[index].util = NULL;
+	list->nr++;
+
+	return index;
+}
+
+struct string_list_item *string_list_insert(const char *string, struct string_list *list)
+{
+	int index = add_entry(list, string);
+
+	if (index < 0)
+		index = -1 - index;
+
+	return list->items + index;
+}
+
+int string_list_has_string(const struct string_list *list, const char *string)
+{
+	int exact_match;
+	get_entry_index(list, string, &exact_match);
+	return exact_match;
+}
+
+struct string_list_item *string_list_lookup(const char *string, struct string_list *list)
+{
+	int exact_match, i = get_entry_index(list, string, &exact_match);
+	if (!exact_match)
+		return NULL;
+	return list->items + i;
+}
+
+void string_list_clear(struct string_list *list, int free_util)
+{
+	if (list->items) {
+		int i;
+		if (list->strdup_strings) {
+			for (i = 0; i < list->nr; i++)
+				free(list->items[i].string);
+		}
+		if (free_util) {
+			for (i = 0; i < list->nr; i++)
+				free(list->items[i].util);
+		}
+		free(list->items);
+	}
+	list->items = NULL;
+	list->nr = list->alloc = 0;
+}
+
+void print_string_list(const char *text, const struct string_list *p)
+{
+	int i;
+	if ( text )
+		printf("%s\n", text);
+	for (i = 0; i < p->nr; i++)
+		printf("%s:%p\n", p->items[i].string, p->items[i].util);
+}
+
+struct string_list_item *string_list_append(const char *string, struct string_list *list)
+{
+	ALLOC_GROW(list->items, list->nr + 1, list->alloc);
+	list->items[list->nr].string =
+		list->strdup_strings ? xstrdup(string) : (char *)string;
+	return list->items + list->nr++;
+}
+
+static int cmp_items(const void *a, const void *b)
+{
+	const struct string_list_item *one = a;
+	const struct string_list_item *two = b;
+	return strcmp(one->string, two->string);
+}
+
+void sort_string_list(struct string_list *list)
+{
+	qsort(list->items, list->nr, sizeof(*list->items), cmp_items);
+}
+
+int unsorted_string_list_has_string(struct string_list *list, const char *string)
+{
+	int i;
+	for (i = 0; i < list->nr; i++)
+		if (!strcmp(string, list->items[i].string))
+			return 1;
+	return 0;
+}
+
diff --git a/string-list.h b/string-list.h
new file mode 100644
index 0000000..4d6a705
--- /dev/null
+++ b/string-list.h
@@ -0,0 +1,28 @@
+#ifndef PATH_LIST_H
+#define PATH_LIST_H
+
+struct string_list_item {
+	char *string;
+	void *util;
+};
+struct string_list
+{
+	struct string_list_item *items;
+	unsigned int nr, alloc;
+	unsigned int strdup_strings:1;
+};
+
+void print_string_list(const char *text, const struct string_list *p);
+void string_list_clear(struct string_list *list, int free_util);
+
+/* Use these functions only on sorted lists: */
+int string_list_has_string(const struct string_list *list, const char *string);
+struct string_list_item *string_list_insert(const char *string, struct string_list *list);
+struct string_list_item *string_list_lookup(const char *string, struct string_list *list);
+
+/* Use these functions only on unsorted lists: */
+struct string_list_item *string_list_append(const char *string, struct string_list *list);
+void sort_string_list(struct string_list *list);
+int unsorted_string_list_has_string(struct string_list *list, const char *string);
+
+#endif /* PATH_LIST_H */
diff --git a/t/.gitattributes b/t/.gitattributes
index ab6edbf..1b97c54 100644
--- a/t/.gitattributes
+++ b/t/.gitattributes
@@ -1,2 +1 @@
-t[0-9][0-9][0-9][0-9]-*.sh -whitespace
 t[0-9][0-9][0-9][0-9]/* -whitespace
diff --git a/t/.gitignore b/t/.gitignore
index 11ffd91..b27e280 100644
--- a/t/.gitignore
+++ b/t/.gitignore
@@ -1 +1,2 @@
 /trash directory
+/test-results
diff --git a/t/Makefile b/t/Makefile
index c6a60ab..0d65ced 100644
--- a/t/Makefile
+++ b/t/Makefile
@@ -14,18 +14,24 @@
 T = $(wildcard t[0-9][0-9][0-9][0-9]-*.sh)
 TSVN = $(wildcard t91[0-9][0-9]-*.sh)
 
-all: $(T) clean
+all: pre-clean $(T) aggregate-results clean
 
 $(T):
 	@echo "*** $@ ***"; GIT_CONFIG=.git/config '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS)
 
+pre-clean:
+	$(RM) -r test-results
+
 clean:
-	$(RM) -r 'trash directory'
+	$(RM) -r 'trash directory' test-results
+
+aggregate-results:
+	'$(SHELL_PATH_SQ)' ./aggregate-results.sh test-results/t*-*
 
 # we can test NO_OPTIMIZE_COMMITS independently of LC_ALL
 full-svn-test:
 	$(MAKE) $(TSVN) GIT_SVN_NO_OPTIMIZE_COMMITS=1 LC_ALL=C
 	$(MAKE) $(TSVN) GIT_SVN_NO_OPTIMIZE_COMMITS=0 LC_ALL=en_US.UTF-8
 
-.PHONY: $(T) clean
+.PHONY: pre-clean $(T) aggregate-results clean
 .NOTPARALLEL:
diff --git a/t/README b/t/README
index 70841a4..8f12d48 100644
--- a/t/README
+++ b/t/README
@@ -54,6 +54,38 @@
 	This causes the test to immediately exit upon the first
 	failed test.
 
+--long-tests::
+	This causes additional long-running tests to be run (where
+	available), for more exhaustive testing.
+
+
+Skipping Tests
+--------------
+
+In some environments, certain tests have no way of succeeding
+due to platform limitation, such as lack of 'unzip' program, or
+filesystem that do not allow arbitrary sequence of non-NUL bytes
+as pathnames.
+
+You should be able to say something like
+
+    $ GIT_SKIP_TESTS=t9200.8 sh ./t9200-git-cvsexport-commit.sh
+
+and even:
+
+    $ GIT_SKIP_TESTS='t[0-4]??? t91?? t9200.8' make
+
+to omit such tests.  The value of the environment variable is a
+SP separated list of patterns that tells which tests to skip,
+and either can match the "t[0-9]{4}" part to skip the whole
+test, or t[0-9]{4} followed by ".$number" to say which
+particular test to skip.
+
+Note that some tests in the existing test suite rely on previous
+test item, so you cannot arbitrarily disable one and expect the
+remainder of test to check what the test originally was intended
+to check.
+
 
 Naming Tests
 ------------
diff --git a/t/aggregate-results.sh b/t/aggregate-results.sh
new file mode 100755
index 0000000..d5bab75
--- /dev/null
+++ b/t/aggregate-results.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+fixed=0
+success=0
+failed=0
+broken=0
+total=0
+
+for file
+do
+	while read type value
+	do
+		case $type in
+		'')
+			continue ;;
+		fixed)
+			fixed=$(($fixed + $value)) ;;
+		success)
+			success=$(($success + $value)) ;;
+		failed)
+			failed=$(($failed + $value)) ;;
+		broken)
+			broken=$(($broken + $value)) ;;
+		total)
+			total=$(($total + $value)) ;;
+		esac
+	done <"$file"
+done
+
+printf "%-8s%d\n" fixed $fixed
+printf "%-8s%d\n" success $success
+printf "%-8s%d\n" failed $failed
+printf "%-8s%d\n" broken $broken
+printf "%-8s%d\n" total $total
diff --git a/t/lib-git-svn.sh b/t/lib-git-svn.sh
index 5d3bd9d..5b5f288 100644
--- a/t/lib-git-svn.sh
+++ b/t/lib-git-svn.sh
@@ -98,7 +98,7 @@
 LoadModule dav_svn_module $SVN_HTTPD_MODULE_PATH/mod_dav_svn.so
 <Location /$repo_base_path>
 	DAV svn
-	SVNPath $rawsvnrepo
+	SVNPath "$rawsvnrepo"
 </Location>
 EOF
 	"$SVN_HTTPD_PATH" -f "$GIT_DIR"/httpd.conf -k start
@@ -135,3 +135,20 @@
 close $rd or die $!;
 EOF
 }
+
+require_svnserve () {
+    if test -z "$SVNSERVE_PORT"
+    then
+        say 'skipping svnserve test. (set $SVNSERVE_PORT to enable)'
+        test_done
+        exit
+    fi
+}
+
+start_svnserve () {
+    svnserve --listen-port $SVNSERVE_PORT \
+             --root "$rawsvnrepo" \
+             --listen-once \
+             --listen-host 127.0.0.1 &
+}
+
diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh
index a5c4436..dc473df 100644
--- a/t/lib-httpd.sh
+++ b/t/lib-httpd.sh
@@ -45,22 +45,22 @@
 	error "Could not identify web server at '$LIB_HTTPD_PATH'"
 fi
 
-HTTPD_PARA="-d $HTTPD_ROOT_PATH -f $TEST_PATH/apache.conf"
+HTTPD_PARA=""
 
 prepare_httpd() {
-	mkdir -p $HTTPD_DOCUMENT_ROOT_PATH
+	mkdir -p "$HTTPD_DOCUMENT_ROOT_PATH"
 
-	ln -s $LIB_HTTPD_MODULE_PATH $HTTPD_ROOT_PATH/modules
+	ln -s "$LIB_HTTPD_MODULE_PATH" "$HTTPD_ROOT_PATH/modules"
 
 	if test -n "$LIB_HTTPD_SSL"
 	then
 		HTTPD_URL=https://127.0.0.1:$LIB_HTTPD_PORT
 
 		RANDFILE_PATH="$HTTPD_ROOT_PATH"/.rnd openssl req \
-			-config $TEST_PATH/ssl.cnf \
+			-config "$TEST_PATH/ssl.cnf" \
 			-new -x509 -nodes \
-			-out $HTTPD_ROOT_PATH/httpd.pem \
-			-keyout $HTTPD_ROOT_PATH/httpd.pem
+			-out "$HTTPD_ROOT_PATH/httpd.pem" \
+			-keyout "$HTTPD_ROOT_PATH/httpd.pem"
 		GIT_SSL_NO_VERIFY=t
 		export GIT_SSL_NO_VERIFY
 		HTTPD_PARA="$HTTPD_PARA -DSSL"
@@ -86,12 +86,14 @@
 
 	trap 'stop_httpd; die' exit
 
-	"$LIB_HTTPD_PATH" $HTTPD_PARA \
+	"$LIB_HTTPD_PATH" -d "$HTTPD_ROOT_PATH" \
+		-f "$TEST_PATH/apache.conf" $HTTPD_PARA \
 		-c "Listen 127.0.0.1:$LIB_HTTPD_PORT" -k start
 }
 
 stop_httpd() {
 	trap 'die' exit
 
-	"$LIB_HTTPD_PATH" $HTTPD_PARA -k stop
+	"$LIB_HTTPD_PATH" -d "$HTTPD_ROOT_PATH" \
+		-f "$TEST_PATH/apache.conf" -k stop
 }
diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf
index a447346..4717c2d 100644
--- a/t/lib-httpd/apache.conf
+++ b/t/lib-httpd/apache.conf
@@ -1,3 +1,4 @@
+ServerName dummy
 PidFile httpd.pid
 DocumentRoot www
 ErrorLog error.log
diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh
index 690f80a..70df15c 100755
--- a/t/t0000-basic.sh
+++ b/t/t0000-basic.sh
@@ -63,7 +63,7 @@
 
 # updating a new file without --add should fail.
 test_expect_success 'git update-index without --add should fail adding.' '
-    ! git update-index should-be-empty
+    test_must_fail git update-index should-be-empty
 '
 
 # and with --add it should succeed, even if it is empty (it used to fail).
@@ -83,7 +83,7 @@
 # Removing paths.
 rm -f should-be-empty full-of-directories
 test_expect_success 'git update-index without --remove should fail removing.' '
-    ! git update-index should-be-empty
+    test_must_fail git update-index should-be-empty
 '
 
 test_expect_success \
@@ -217,7 +217,7 @@
     'git update-index --index-info < badobjects'
 
 test_expect_success 'writing this tree without --missing-ok.' '
-    ! git write-tree
+    test_must_fail git write-tree
 '
 
 test_expect_success \
@@ -301,14 +301,14 @@
 	mkdir third &&
 	dir="$(cd .git; pwd -P)" &&
 	dir2=third/../second/other/.git &&
-	test "$dir" = "$(test-absolute-path $dir2)" &&
+	test "$dir" = "$(test-path-utils make_absolute_path $dir2)" &&
 	file="$dir"/index &&
-	test "$file" = "$(test-absolute-path $dir2/index)" &&
+	test "$file" = "$(test-path-utils make_absolute_path $dir2/index)" &&
 	basename=blub &&
-	test "$dir/$basename" = "$(cd .git && test-absolute-path "$basename")" &&
+	test "$dir/$basename" = "$(cd .git && test-path-utils make_absolute_path "$basename")" &&
 	ln -s ../first/file .git/syml &&
 	sym="$(cd first; pwd -P)"/file &&
-	test "$sym" = "$(test-absolute-path "$dir2/syml")"
+	test "$sym" = "$(test-path-utils make_absolute_path "$dir2/syml")"
 '
 
 test_expect_success 'very long name in the index handled sanely' '
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index c0b781a..5ac0a27 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -83,11 +83,11 @@
 
 	(
 		unset GIT_DIR GIT_WORK_TREE GIT_CONFIG
-		mkdir git-init-bare.git &&
-		cd git-init-bare.git &&
+		mkdir init-bare.git &&
+		cd init-bare.git &&
 		git init --bare
 	) &&
-	check_config git-init-bare.git true unset
+	check_config init-bare.git true unset
 '
 
 test_expect_success 'GIT_DIR non-bare' '
@@ -167,4 +167,36 @@
 	! test -f template-blank/.git/info/exclude
 '
 
+test_expect_success 'init --bare/--shared overrides system/global config' '
+	(
+		HOME="`pwd`" &&
+		export HOME &&
+		test_config="$HOME"/.gitconfig &&
+		unset GIT_CONFIG_NOGLOBAL &&
+		git config -f "$test_config" core.bare false &&
+		git config -f "$test_config" core.sharedRepository 0640 &&
+		mkdir init-bare-shared-override &&
+		cd init-bare-shared-override &&
+		git init --bare --shared=0666
+	) &&
+	check_config init-bare-shared-override true unset &&
+	test x0666 = \
+	x`git config -f init-bare-shared-override/config core.sharedRepository`
+'
+
+test_expect_success 'init honors global core.sharedRepository' '
+	(
+		HOME="`pwd`" &&
+		export HOME &&
+		test_config="$HOME"/.gitconfig &&
+		unset GIT_CONFIG_NOGLOBAL &&
+		git config -f "$test_config" core.sharedRepository 0666 &&
+		mkdir shared-honor-global &&
+		cd shared-honor-global &&
+		git init
+	) &&
+	test x0666 = \
+	x`git config -f shared-honor-global/.git/config core.sharedRepository`
+'
+
 test_done
diff --git a/t/t0002-gitfile.sh b/t/t0002-gitfile.sh
index c5dbc72..4db4ac4 100755
--- a/t/t0002-gitfile.sh
+++ b/t/t0002-gitfile.sh
@@ -66,7 +66,7 @@
 
 test_expect_success 'check cat-file' '
 	git cat-file blob $SHA >actual &&
-	diff -u bar actual
+	test_cmp bar actual
 '
 
 test_expect_success 'check update-index' '
diff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh
index 2bfeac9..1be7446 100755
--- a/t/t0020-crlf.sh
+++ b/t/t0020-crlf.sh
@@ -52,7 +52,7 @@
 	git config core.safecrlf true &&
 
 	for w in I am all CRLF; do echo $w; done | append_cr >allcrlf &&
-	! git add allcrlf
+	test_must_fail git add allcrlf
 '
 
 test_expect_success 'safecrlf: autocrlf=input, mixed LF/CRLF' '
@@ -61,7 +61,7 @@
 	git config core.safecrlf true &&
 
 	for w in Oh here is CRLFQ in text; do echo $w; done | q_to_cr >mixed &&
-	! git add mixed
+	test_must_fail git add mixed
 '
 
 test_expect_success 'safecrlf: autocrlf=true, all LF' '
@@ -70,7 +70,7 @@
 	git config core.safecrlf true &&
 
 	for w in I am all LF; do echo $w; done >alllf &&
-	! git add alllf
+	test_must_fail git add alllf
 '
 
 test_expect_success 'safecrlf: autocrlf=true mixed LF/CRLF' '
@@ -79,7 +79,7 @@
 	git config core.safecrlf true &&
 
 	for w in Oh here is CRLFQ in text; do echo $w; done | q_to_cr >mixed &&
-	! git add mixed
+	test_must_fail git add mixed
 '
 
 test_expect_success 'safecrlf: print warning only once' '
diff --git a/t/t0023-crlf-am.sh b/t/t0023-crlf-am.sh
index 6f8a434..aaed725 100755
--- a/t/t0023-crlf-am.sh
+++ b/t/t0023-crlf-am.sh
@@ -36,7 +36,7 @@
 
 test_expect_success 'am' '
 
-	git am --binary -3 <patchfile &&
+	git am -3 <patchfile &&
 	git diff-files --name-status --exit-code
 
 '
diff --git a/t/t0024-crlf-archive.sh b/t/t0024-crlf-archive.sh
new file mode 100755
index 0000000..e533039
--- /dev/null
+++ b/t/t0024-crlf-archive.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+test_description='respect crlf in git archive'
+
+. ./test-lib.sh
+UNZIP=${UNZIP:-unzip}
+
+test_expect_success setup '
+
+	git config core.autocrlf true
+
+	printf "CRLF line ending\r\nAnd another\r\n" > sample &&
+	git add sample &&
+
+	test_tick &&
+	git commit -m Initial
+
+'
+
+test_expect_success 'tar archive' '
+
+	git archive --format=tar HEAD |
+	( mkdir untarred && cd untarred && "$TAR" -xf - )
+
+	test_cmp sample untarred/sample
+
+'
+
+"$UNZIP" -v >/dev/null 2>&1
+if [ $? -eq 127 ]; then
+	echo "Skipping ZIP test, because unzip was not found"
+	test_done
+	exit
+fi
+
+test_expect_success 'zip archive' '
+
+	git archive --format=zip HEAD >test.zip &&
+
+	( mkdir unzipped && cd unzipped && unzip ../test.zip ) &&
+
+	test_cmp sample unzipped/sample
+
+'
+
+test_done
diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh
index 6309aed..e38241c 100755
--- a/t/t0040-parse-options.sh
+++ b/t/t0040-parse-options.sh
@@ -47,6 +47,7 @@
 cat > expect << EOF
 boolean: 2
 integer: 1729
+timestamp: 0
 string: 123
 abbrev: 7
 verbose: 2
@@ -63,6 +64,7 @@
 cat > expect << EOF
 boolean: 2
 integer: 1729
+timestamp: 0
 string: 321
 abbrev: 10
 verbose: 2
@@ -78,9 +80,17 @@
 	test_cmp expect output
 '
 
+test_expect_success 'missing required value' '
+	test-parse-options -s;
+	test $? = 129 &&
+	test-parse-options --string;
+	test $? = 129
+'
+
 cat > expect << EOF
 boolean: 1
 integer: 13
+timestamp: 0
 string: 123
 abbrev: 7
 verbose: 0
@@ -101,6 +111,7 @@
 cat > expect << EOF
 boolean: 0
 integer: 2
+timestamp: 0
 string: (not set)
 abbrev: 7
 verbose: 0
@@ -128,6 +139,7 @@
 cat > expect << EOF
 boolean: 0
 integer: 0
+timestamp: 0
 string: 123
 abbrev: 7
 verbose: 0
@@ -154,6 +166,7 @@
 cat > expect <<EOF
 boolean: 0
 integer: 0
+timestamp: 0
 string: (not set)
 abbrev: 7
 verbose: 0
@@ -170,7 +183,8 @@
 
 cat > expect <<EOF
 boolean: 0
-integer: 1
+integer: 0
+timestamp: 1
 string: default
 abbrev: 7
 verbose: 0
@@ -190,6 +204,7 @@
 Callback: "four", 0
 boolean: 5
 integer: 4
+timestamp: 0
 string: (not set)
 abbrev: 7
 verbose: 0
@@ -216,6 +231,7 @@
 cat > expect <<EOF
 boolean: 1
 integer: 23
+timestamp: 0
 string: (not set)
 abbrev: 7
 verbose: 0
diff --git a/t/t0050-filesystem.sh b/t/t0050-filesystem.sh
index c5360e2..7edf49d 100755
--- a/t/t0050-filesystem.sh
+++ b/t/t0050-filesystem.sh
@@ -43,7 +43,7 @@
 else
 test_expect_success "detection of case insensitive filesystem during repo init" '
 
-	! git config --bool core.ignorecase >/dev/null ||
+	test_must_fail git config --bool core.ignorecase >/dev/null ||
 	test $(git config --bool core.ignorecase) = false
 '
 fi
@@ -85,7 +85,7 @@
 	rm camelcase &&
 	echo 1 >CamelCase &&
 	git add CamelCase &&
-	test $(git-ls-files | grep -i camelcase | wc -l) = 1
+	test $(git ls-files | grep -i camelcase | wc -l) = 1
 
 '
 
diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
new file mode 100755
index 0000000..6e7501f
--- /dev/null
+++ b/t/t0060-path-utils.sh
@@ -0,0 +1,87 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 David Reiss
+#
+
+test_description='Test various path utilities'
+
+. ./test-lib.sh
+
+norm_abs() {
+	test_expect_success "normalize absolute" \
+	"test \$(test-path-utils normalize_absolute_path '$1') = '$2'"
+}
+
+ancestor() {
+	test_expect_success "longest ancestor" \
+	"test \$(test-path-utils longest_ancestor_length '$1' '$2') = '$3'"
+}
+
+norm_abs "" /
+norm_abs / /
+norm_abs // /
+norm_abs /// /
+norm_abs /. /
+norm_abs /./ /
+norm_abs /./.. /
+norm_abs /../. /
+norm_abs /./../.// /
+norm_abs /dir/.. /
+norm_abs /dir/sub/../.. /
+norm_abs /dir /dir
+norm_abs /dir// /dir
+norm_abs /./dir /dir
+norm_abs /dir/. /dir
+norm_abs /dir///./ /dir
+norm_abs /dir//sub/.. /dir
+norm_abs /dir/sub/../ /dir
+norm_abs //dir/sub/../. /dir
+norm_abs /dir/s1/../s2/ /dir/s2
+norm_abs /d1/s1///s2/..//../s3/ /d1/s3
+norm_abs /d1/s1//../s2/../../d2 /d2
+norm_abs /d1/.../d2 /d1/.../d2
+norm_abs /d1/..././../d2 /d1/d2
+
+ancestor / "" -1
+ancestor / / -1
+ancestor /foo "" -1
+ancestor /foo : -1
+ancestor /foo ::. -1
+ancestor /foo ::..:: -1
+ancestor /foo / 0
+ancestor /foo /fo -1
+ancestor /foo /foo -1
+ancestor /foo /foo/ -1
+ancestor /foo /bar -1
+ancestor /foo /bar/ -1
+ancestor /foo /foo/bar -1
+ancestor /foo /foo:/bar/ -1
+ancestor /foo /foo/:/bar/ -1
+ancestor /foo /foo::/bar/ -1
+ancestor /foo /:/foo:/bar/ 0
+ancestor /foo /foo:/:/bar/ 0
+ancestor /foo /:/bar/:/foo 0
+ancestor /foo/bar "" -1
+ancestor /foo/bar / 0
+ancestor /foo/bar /fo -1
+ancestor /foo/bar foo -1
+ancestor /foo/bar /foo 4
+ancestor /foo/bar /foo/ 4
+ancestor /foo/bar /foo/ba -1
+ancestor /foo/bar /:/fo 0
+ancestor /foo/bar /foo:/foo/ba 4
+ancestor /foo/bar /bar -1
+ancestor /foo/bar /bar/ -1
+ancestor /foo/bar /fo: -1
+ancestor /foo/bar :/fo -1
+ancestor /foo/bar /foo:/bar/ 4
+ancestor /foo/bar /:/foo:/bar/ 4
+ancestor /foo/bar /foo:/:/bar/ 4
+ancestor /foo/bar /:/bar/:/fo 0
+ancestor /foo/bar /:/bar/ 0
+ancestor /foo/bar :://foo/. 4
+ancestor /foo/bar :://foo/.:: 4
+ancestor /foo/bar //foo/./::/bar 4
+ancestor /foo/bar ::/bar -1
+
+test_done
diff --git a/t/t1002-read-tree-m-u-2way.sh b/t/t1002-read-tree-m-u-2way.sh
index e04990e..5e40cec 100755
--- a/t/t1002-read-tree-m-u-2way.sh
+++ b/t/t1002-read-tree-m-u-2way.sh
@@ -14,6 +14,8 @@
 _x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
 compare_change () {
 	sed >current \
+	    -e '1{/^diff --git /d;}' \
+	    -e '2{/^index /d;}' \
 	    -e '/^--- /d; /^+++ /d; /^@@ /d;' \
 	    -e 's/^\(.[0-7][0-7][0-7][0-7][0-7][0-7]\) '"$_x40"' /\1 X /' "$1"
 	test_cmp expected current
@@ -75,7 +77,7 @@
      git update-index --add yomin &&
      git read-tree -m -u $treeH $treeM &&
      git ls-files --stage >4.out || return 1
-     diff -U0 M.out 4.out >4diff.out
+     git diff -U0 --no-index M.out 4.out >4diff.out
      compare_change 4diff.out expected &&
      check_cache_at yomin clean &&
      sum bozbar frotz nitfol >actual4.sum &&
@@ -94,7 +96,7 @@
      echo yomin yomin >yomin &&
      git read-tree -m -u $treeH $treeM &&
      git ls-files --stage >5.out || return 1
-     diff -U0 M.out 5.out >5diff.out
+     git diff -U0 --no-index M.out 5.out >5diff.out
      compare_change 5diff.out expected &&
      check_cache_at yomin dirty &&
      sum bozbar frotz nitfol >actual5.sum &&
@@ -112,7 +114,7 @@
      git update-index --add frotz &&
      git read-tree -m -u $treeH $treeM &&
      git ls-files --stage >6.out &&
-     diff -U0 M.out 6.out &&
+     test_cmp M.out 6.out &&
      check_cache_at frotz clean &&
      sum bozbar frotz nitfol >actual3.sum &&
      cmp M.sum actual3.sum &&
@@ -129,7 +131,7 @@
      echo frotz frotz >frotz &&
      git read-tree -m -u $treeH $treeM &&
      git ls-files --stage >7.out &&
-     diff -U0 M.out 7.out &&
+     test_cmp M.out 7.out &&
      check_cache_at frotz dirty &&
      sum bozbar frotz nitfol >actual7.sum &&
      if cmp M.sum actual7.sum; then false; else :; fi &&
@@ -206,7 +208,7 @@
      git update-index --add nitfol &&
      git read-tree -m -u $treeH $treeM &&
      git ls-files --stage >14.out || return 1
-     diff -U0 M.out 14.out >14diff.out
+     git diff -U0 --no-index M.out 14.out >14diff.out
      compare_change 14diff.out expected &&
      sum bozbar frotz >actual14.sum &&
      grep -v nitfol M.sum > expected14.sum &&
@@ -227,7 +229,7 @@
      echo nitfol nitfol nitfol >nitfol &&
      git read-tree -m -u $treeH $treeM &&
      git ls-files --stage >15.out || return 1
-     diff -U0 M.out 15.out >15diff.out
+     git diff -U0 --no-index M.out 15.out >15diff.out
      compare_change 15diff.out expected &&
      check_cache_at nitfol dirty &&
      sum bozbar frotz >actual15.sum &&
@@ -264,7 +266,7 @@
      git update-index --add bozbar &&
      git read-tree -m -u $treeH $treeM &&
      git ls-files --stage >18.out &&
-     diff -U0 M.out 18.out &&
+     test_cmp M.out 18.out &&
      check_cache_at bozbar clean &&
      sum bozbar frotz nitfol >actual18.sum &&
      cmp M.sum actual18.sum'
@@ -278,7 +280,7 @@
      echo gnusto gnusto >bozbar &&
      git read-tree -m -u $treeH $treeM &&
      git ls-files --stage >19.out &&
-     diff -U0 M.out 19.out &&
+     test_cmp M.out 19.out &&
      check_cache_at bozbar dirty &&
      sum frotz nitfol >actual19.sum &&
      grep -v bozbar  M.sum > expected19.sum &&
@@ -297,7 +299,7 @@
      git update-index --add bozbar &&
      git read-tree -m -u $treeH $treeM &&
      git ls-files --stage >20.out &&
-     diff -U0 M.out 20.out &&
+     test_cmp M.out 20.out &&
      check_cache_at bozbar clean &&
      sum bozbar frotz nitfol >actual20.sum &&
      cmp M.sum actual20.sum'
@@ -338,7 +340,7 @@
      git update-index --add DF &&
      git read-tree -m -u $treeDF $treeDFDF &&
      git ls-files --stage >DFDFcheck.out &&
-     diff -U0 DFDF.out DFDFcheck.out &&
+     test_cmp DFDF.out DFDFcheck.out &&
      check_cache_at DF/DF clean'
 
 test_done
diff --git a/t/t1005-read-tree-reset.sh b/t/t1005-read-tree-reset.sh
index b0d31f5..8499116 100755
--- a/t/t1005-read-tree-reset.sh
+++ b/t/t1005-read-tree-reset.sh
@@ -27,4 +27,64 @@
   test_cmp expect actual
 '
 
+test_expect_success 'reset should remove remnants from a failed merge' '
+  git read-tree --reset -u HEAD &&
+  git ls-files -s >expect &&
+  sha1=$(git rev-parse :new) &&
+  (
+	echo "100644 $sha1 1	old"
+	echo "100644 $sha1 3	old"
+  ) | git update-index --index-info &&
+  >old &&
+  git ls-files -s &&
+  git read-tree --reset -u HEAD &&
+  git ls-files -s >actual &&
+  ! test -f old
+'
+
+test_expect_success 'Porcelain reset should remove remnants too' '
+  git read-tree --reset -u HEAD &&
+  git ls-files -s >expect &&
+  sha1=$(git rev-parse :new) &&
+  (
+	echo "100644 $sha1 1	old"
+	echo "100644 $sha1 3	old"
+  ) | git update-index --index-info &&
+  >old &&
+  git ls-files -s &&
+  git reset --hard &&
+  git ls-files -s >actual &&
+  ! test -f old
+'
+
+test_expect_success 'Porcelain checkout -f should remove remnants too' '
+  git read-tree --reset -u HEAD &&
+  git ls-files -s >expect &&
+  sha1=$(git rev-parse :new) &&
+  (
+	echo "100644 $sha1 1	old"
+	echo "100644 $sha1 3	old"
+  ) | git update-index --index-info &&
+  >old &&
+  git ls-files -s &&
+  git checkout -f &&
+  git ls-files -s >actual &&
+  ! test -f old
+'
+
+test_expect_success 'Porcelain checkout -f HEAD should remove remnants too' '
+  git read-tree --reset -u HEAD &&
+  git ls-files -s >expect &&
+  sha1=$(git rev-parse :new) &&
+  (
+	echo "100644 $sha1 1	old"
+	echo "100644 $sha1 3	old"
+  ) | git update-index --index-info &&
+  >old &&
+  git ls-files -s &&
+  git checkout -f HEAD &&
+  git ls-files -s >actual &&
+  ! test -f old
+'
+
 test_done
diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh
index 0526295..076b082 100755
--- a/t/t1007-hash-object.sh
+++ b/t/t1007-hash-object.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-test_description=git-hash-object
+test_description="git hash-object"
 
 . ./test-lib.sh
 
diff --git a/t/t1200-tutorial.sh b/t/t1200-tutorial.sh
index dcb3108..67e637b 100755
--- a/t/t1200-tutorial.sh
+++ b/t/t1200-tutorial.sh
@@ -78,7 +78,7 @@
 git tag my-first-tag
 test_expect_success 'git tag my-first-tag' 'cmp .git/refs/heads/master .git/refs/tags/my-first-tag'
 
-# TODO: test git-clone
+# TODO: test git clone
 
 git checkout -b mybranch
 test_expect_success 'git checkout -b mybranch' 'cmp .git/refs/heads/master .git/refs/heads/mybranch'
@@ -102,7 +102,7 @@
 git commit -m 'Some fun.' -i hello example
 
 test_expect_success 'git resolve now fails' '
-	! git merge -m "Merge work in mybranch" mybranch
+	test_must_fail git merge -m "Merge work in mybranch" mybranch
 '
 
 cat > hello << EOF
diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index afe7e66..11b82f4 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -201,7 +201,7 @@
 	'test wow = $(git config --get nextsection.nonewline !for)'
 
 test_expect_success 'ambiguous get' '
-	! git config --get nextsection.nonewline
+	test_must_fail git config --get nextsection.nonewline
 '
 
 test_expect_success 'get multivar' \
@@ -223,15 +223,15 @@
 test_expect_success 'multivar replace' 'cmp .git/config expect'
 
 test_expect_success 'ambiguous value' '
-	! git config nextsection.nonewline
+	test_must_fail git config nextsection.nonewline
 '
 
 test_expect_success 'ambiguous unset' '
-	! git config --unset nextsection.nonewline
+	test_must_fail git config --unset nextsection.nonewline
 '
 
 test_expect_success 'invalid unset' '
-	! git config --unset somesection.nonewline
+	test_must_fail git config --unset somesection.nonewline
 '
 
 git config --unset nextsection.nonewline "wow3$"
@@ -248,7 +248,7 @@
 
 test_expect_success 'multivar unset' 'cmp .git/config expect'
 
-test_expect_success 'invalid key' '! git config inval.2key blabla'
+test_expect_success 'invalid key' 'test_must_fail git config inval.2key blabla'
 
 test_expect_success 'correct key' 'git config 123456.a123 987'
 
@@ -430,7 +430,8 @@
 test_expect_success "rename succeeded" "test_cmp expect .git/config"
 
 test_expect_success "rename non-existing section" '
-	! git config --rename-section branch."world domination" branch.drei
+	test_must_fail git config --rename-section \
+		branch."world domination" branch.drei
 '
 
 test_expect_success "rename succeeded" "test_cmp expect .git/config"
@@ -545,11 +546,11 @@
 test_expect_success 'invalid bool (--get)' '
 
 	git config bool.nobool foobar &&
-	! git config --bool --get bool.nobool'
+	test_must_fail git config --bool --get bool.nobool'
 
 test_expect_success 'invalid bool (set)' '
 
-	! git config --bool bool.nobool foobar'
+	test_must_fail git config --bool bool.nobool foobar'
 
 rm .git/config
 
@@ -669,7 +670,7 @@
 test_expect_success 'quoting' 'cmp .git/config expect'
 
 test_expect_success 'key with newline' '
-	! git config "key.with
+	test_must_fail git config "key.with
 newline" 123'
 
 test_expect_success 'value with newline' 'git config key.sub value.with\\\
@@ -740,4 +741,14 @@
 
 '
 
+test_expect_success 'check split_cmdline return' "
+	git config alias.split-cmdline-fix 'echo \"' &&
+	test_must_fail git split-cmdline-fix &&
+	echo foo > foo &&
+	git add foo &&
+	git commit -m 'initial commit' &&
+	git config branch.master.mergeoptions 'echo \"' &&
+	test_must_fail git merge master
+	"
+
 test_done
diff --git a/t/t1301-shared-repo.sh b/t/t1301-shared-repo.sh
index dc85e8b..653362b 100755
--- a/t/t1301-shared-repo.sh
+++ b/t/t1301-shared-repo.sh
@@ -7,6 +7,9 @@
 
 . ./test-lib.sh
 
+# Remove a default ACL from the test dir if possible.
+setfacl -k . 2>/dev/null
+
 # User must have read permissions to the repo -> failure on --shared=0400
 test_expect_success 'shared = 0400 (faulty permission u-w)' '
 	mkdir sub && (
@@ -17,6 +20,10 @@
 	test $ret != "0"
 '
 
+modebits () {
+	ls -l "$1" | sed -e 's|^\(..........\).*|\1|'
+}
+
 for u in 002 022
 do
 	test_expect_success "shared=1 does not clear bits preset by umask $u" '
@@ -82,8 +89,7 @@
 
 		rm -f .git/info/refs &&
 		git update-server-info &&
-		actual="$(ls -l .git/info/refs)" &&
-		actual=${actual%% *} &&
+		actual="$(modebits .git/info/refs)" &&
 		test "x$actual" = "x-$y" || {
 			ls -lt .git/info
 			false
@@ -95,8 +101,7 @@
 
 		rm -f .git/info/refs &&
 		git update-server-info &&
-		actual="$(ls -l .git/info/refs)" &&
-		actual=${actual%% *} &&
+		actual="$(modebits .git/info/refs)" &&
 		test "x$actual" = "x-$x" || {
 			ls -lt .git/info
 			false
diff --git a/t/t1302-repo-version.sh b/t/t1302-repo-version.sh
index 9be0770..8d305b4 100755
--- a/t/t1302-repo-version.sh
+++ b/t/t1302-repo-version.sh
@@ -41,7 +41,7 @@
 	cd test && git apply --check --index ../test.patch)'
 
 test_expect_success 'gitdir required mode on unsupported repo' '
-	(cd test2 && ! git apply --check --index ../test.patch)
+	(cd test2 && test_must_fail git apply --check --index ../test.patch)
 '
 
 test_done
diff --git a/t/t1303-wacky-config.sh b/t/t1303-wacky-config.sh
index f98f4c5..1983076 100755
--- a/t/t1303-wacky-config.sh
+++ b/t/t1303-wacky-config.sh
@@ -35,7 +35,7 @@
 '
 
 SECTION="test.q\"s\\sq'sp e.key"
-test_expect_success 'make sure git-config escapes section names properly' '
+test_expect_success 'make sure git config escapes section names properly' '
 	git config "$SECTION" bar &&
 	check "$SECTION" bar
 '
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index b8b7ab4..bd58926 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -42,6 +42,14 @@
 '
 rm -f .git/$m
 
+test_expect_success "delete $m without oldvalue verification" "
+	git update-ref $m $A &&
+	test $A = \$(cat .git/$m) &&
+	git update-ref -d $m &&
+	! test -f .git/$m
+"
+rm -f .git/$m
+
 test_expect_success \
 	"fail to create $n" \
 	"touch .git/$n_dir
@@ -67,8 +75,26 @@
 '
 rm -f .git/$m
 
+cp -f .git/HEAD .git/HEAD.orig
+test_expect_success "delete symref without dereference" '
+	git update-ref --no-deref -d HEAD &&
+	! test -f .git/HEAD
+'
+cp -f .git/HEAD.orig .git/HEAD
+
+test_expect_success "delete symref without dereference when the referred ref is packed" '
+	echo foo >foo.c &&
+	git add foo.c &&
+	git commit -m foo &&
+	git pack-refs --all &&
+	git update-ref --no-deref -d HEAD &&
+	! test -f .git/HEAD
+'
+cp -f .git/HEAD.orig .git/HEAD
+git update-ref -d $m
+
 test_expect_success '(not) create HEAD with old sha1' "
-	! git update-ref HEAD $A $B
+	test_must_fail git update-ref HEAD $A $B
 "
 test_expect_success "(not) prior created .git/$m" "
 	! test -f .git/$m
@@ -79,7 +105,7 @@
 	"create HEAD" \
 	"git update-ref HEAD $A"
 test_expect_success '(not) change HEAD with wrong SHA1' "
-	! git update-ref HEAD $B $Z
+	test_must_fail git update-ref HEAD $B $Z
 "
 test_expect_success "(not) changed .git/$m" "
 	! test $B"' = $(cat .git/'"$m"')
@@ -147,7 +173,8 @@
 
 git update-ref $m $D
 cat >.git/logs/$m <<EOF
-$C $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150320 -0500
+0000000000000000000000000000000000000000 $C $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150320 -0500
+$C $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150350 -0500
 $A $B $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150380 -0500
 $F $Z $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150680 -0500
 $Z $E $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150980 -0500
@@ -178,6 +205,12 @@
 	'Query "master@{May 26 2005 23:32:00}" (exactly history start)' \
 	'rm -f o e
 	 git rev-parse --verify "master@{May 26 2005 23:32:00}" >o 2>e &&
+	 test '"$C"' = $(cat o) &&
+	 test "" = "$(cat e)"'
+test_expect_success \
+	'Query "master@{May 26 2005 23:32:30}" (first non-creation change)' \
+	'rm -f o e
+	 git rev-parse --verify "master@{May 26 2005 23:32:30}" >o 2>e &&
 	 test '"$A"' = $(cat o) &&
 	 test "" = "$(cat e)"'
 test_expect_success \
@@ -213,21 +246,21 @@
     'echo TEST >F &&
      git add F &&
 	 GIT_AUTHOR_DATE="2005-05-26 23:30" \
-	 GIT_COMMITTER_DATE="2005-05-26 23:30" git-commit -m add -a &&
+	 GIT_COMMITTER_DATE="2005-05-26 23:30" git commit -m add -a &&
 	 h_TEST=$(git rev-parse --verify HEAD)
 	 echo The other day this did not work. >M &&
 	 echo And then Bob told me how to fix it. >>M &&
 	 echo OTHER >F &&
 	 GIT_AUTHOR_DATE="2005-05-26 23:41" \
-	 GIT_COMMITTER_DATE="2005-05-26 23:41" git-commit -F M -a &&
+	 GIT_COMMITTER_DATE="2005-05-26 23:41" git commit -F M -a &&
 	 h_OTHER=$(git rev-parse --verify HEAD) &&
 	 GIT_AUTHOR_DATE="2005-05-26 23:44" \
-	 GIT_COMMITTER_DATE="2005-05-26 23:44" git-commit --amend &&
+	 GIT_COMMITTER_DATE="2005-05-26 23:44" git commit --amend &&
 	 h_FIXED=$(git rev-parse --verify HEAD) &&
 	 echo Merged initial commit and a later commit. >M &&
 	 echo $h_TEST >.git/MERGE_HEAD &&
 	 GIT_AUTHOR_DATE="2005-05-26 23:45" \
-	 GIT_COMMITTER_DATE="2005-05-26 23:45" git-commit -F M &&
+	 GIT_COMMITTER_DATE="2005-05-26 23:45" git commit -F M &&
 	 h_MERGED=$(git rev-parse --verify HEAD) &&
 	 rm -f M'
 
@@ -238,7 +271,7 @@
 $h_FIXED $h_MERGED $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117151100 +0000	commit (merge): Merged initial commit and a later commit.
 EOF
 test_expect_success \
-	'git-commit logged updates' \
+	'git commit logged updates' \
 	"diff expect .git/logs/$m"
 unset h_TEST h_OTHER h_FIXED h_MERGED
 
diff --git a/t/t1501-worktree.sh b/t/t1501-worktree.sh
index 2ee88d8..c039ee3 100755
--- a/t/t1501-worktree.sh
+++ b/t/t1501-worktree.sh
@@ -28,6 +28,7 @@
 	[ $# -eq 0 ] && return
 }
 
+EMPTY_TREE=$(git write-tree)
 mkdir -p work/sub/dir || exit 1
 mv .git repo.git || exit 1
 
@@ -106,12 +107,71 @@
 '
 
 test_expect_success '_gently() groks relative GIT_DIR & GIT_WORK_TREE' '
-	cd repo.git/work/sub/dir &&
+	(cd repo.git/work/sub/dir &&
 	GIT_DIR=../../.. GIT_WORK_TREE=../.. GIT_PAGER= \
 		git diff --exit-code tracked &&
 	echo changed > tracked &&
 	! GIT_DIR=../../.. GIT_WORK_TREE=../.. GIT_PAGER= \
-		git diff --exit-code tracked
+		git diff --exit-code tracked)
+'
+cat > diff-index-cached.expected <<\EOF
+:000000 100644 0000000000000000000000000000000000000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 A	sub/dir/tracked
+EOF
+cat > diff-index.expected <<\EOF
+:000000 100644 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 A	sub/dir/tracked
+EOF
+
+
+test_expect_success 'git diff-index' '
+	GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff-index $EMPTY_TREE > result &&
+	test_cmp diff-index.expected result &&
+	GIT_DIR=repo.git git diff-index --cached $EMPTY_TREE > result &&
+	test_cmp diff-index-cached.expected result
+'
+cat >diff-files.expected <<\EOF
+:100644 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0000000000000000000000000000000000000000 M	sub/dir/tracked
+EOF
+
+test_expect_success 'git diff-files' '
+	GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff-files > result &&
+	test_cmp diff-files.expected result
+'
+
+cat >diff-TREE.expected <<\EOF
+diff --git a/sub/dir/tracked b/sub/dir/tracked
+new file mode 100644
+index 0000000..5ea2ed4
+--- /dev/null
++++ b/sub/dir/tracked
+@@ -0,0 +1 @@
++changed
+EOF
+cat >diff-TREE-cached.expected <<\EOF
+diff --git a/sub/dir/tracked b/sub/dir/tracked
+new file mode 100644
+index 0000000..e69de29
+EOF
+cat >diff-FILES.expected <<\EOF
+diff --git a/sub/dir/tracked b/sub/dir/tracked
+index e69de29..5ea2ed4 100644
+--- a/sub/dir/tracked
++++ b/sub/dir/tracked
+@@ -0,0 +1 @@
++changed
+EOF
+
+test_expect_success 'git diff' '
+	GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff $EMPTY_TREE > result &&
+	test_cmp diff-TREE.expected result &&
+	GIT_DIR=repo.git git diff --cached $EMPTY_TREE > result &&
+	test_cmp diff-TREE-cached.expected result &&
+	GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff > result &&
+	test_cmp diff-FILES.expected result
+'
+
+test_expect_success 'git grep' '
+	(cd repo.git/work/sub &&
+	GIT_DIR=../.. GIT_WORK_TREE=.. git grep -l changed | grep -q dir/tracked)
 '
 
 test_done
diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh
index 3508d0a..997002d 100755
--- a/t/t1502-rev-parse-parseopt.sh
+++ b/t/t1502-rev-parse-parseopt.sh
@@ -5,7 +5,7 @@
 
 cat > expect.err <<EOF
 usage: some-command [options] <args>...
-    
+
     some-command does foo and bar!
 
     -h, --help            show the help
diff --git a/t/t1503-rev-parse-verify.sh b/t/t1503-rev-parse-verify.sh
index 95244c9..cc65394 100755
--- a/t/t1503-rev-parse-verify.sh
+++ b/t/t1503-rev-parse-verify.sh
@@ -23,7 +23,7 @@
     fi
 
     test_tick
-    git-commit --quiet -m "$MSG" $_file
+    git commit --quiet -m "$MSG" $_file
 }
 
 HASH1=
diff --git a/t/t1504-ceiling-dirs.sh b/t/t1504-ceiling-dirs.sh
new file mode 100755
index 0000000..91b704a
--- /dev/null
+++ b/t/t1504-ceiling-dirs.sh
@@ -0,0 +1,163 @@
+#!/bin/sh
+
+test_description='test GIT_CEILING_DIRECTORIES'
+. ./test-lib.sh
+
+test_prefix() {
+	test_expect_success "$1" \
+	"test '$2' = \"\$(git rev-parse --show-prefix)\""
+}
+
+test_fail() {
+	test_expect_code 128 "$1: prefix" \
+	"git rev-parse --show-prefix"
+}
+
+TRASH_ROOT="$(pwd)"
+ROOT_PARENT=$(dirname "$TRASH_ROOT")
+
+
+unset GIT_CEILING_DIRECTORIES
+test_prefix no_ceil ""
+
+export GIT_CEILING_DIRECTORIES
+
+GIT_CEILING_DIRECTORIES=""
+test_prefix ceil_empty ""
+
+GIT_CEILING_DIRECTORIES="$ROOT_PARENT"
+test_prefix ceil_at_parent ""
+
+GIT_CEILING_DIRECTORIES="$ROOT_PARENT/"
+test_prefix ceil_at_parent_slash ""
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT"
+test_prefix ceil_at_trash ""
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/"
+test_prefix ceil_at_trash_slash ""
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub"
+test_prefix ceil_at_sub ""
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/"
+test_prefix ceil_at_sub_slash ""
+
+
+mkdir -p sub/dir || exit 1
+cd sub/dir || exit 1
+
+unset GIT_CEILING_DIRECTORIES
+test_prefix subdir_no_ceil "sub/dir/"
+
+export GIT_CEILING_DIRECTORIES
+
+GIT_CEILING_DIRECTORIES=""
+test_prefix subdir_ceil_empty "sub/dir/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT"
+test_fail subdir_ceil_at_trash
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/"
+test_fail subdir_ceil_at_trash_slash
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub"
+test_fail subdir_ceil_at_sub
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/"
+test_fail subdir_ceil_at_sub_slash
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/dir"
+test_prefix subdir_ceil_at_subdir "sub/dir/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/dir/"
+test_prefix subdir_ceil_at_subdir_slash "sub/dir/"
+
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su"
+test_prefix subdir_ceil_at_su "sub/dir/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su/"
+test_prefix subdir_ceil_at_su_slash "sub/dir/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/di"
+test_prefix subdir_ceil_at_sub_di "sub/dir/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub/di"
+test_prefix subdir_ceil_at_sub_di_slash "sub/dir/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/subdi"
+test_prefix subdir_ceil_at_subdi "sub/dir/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/subdi"
+test_prefix subdir_ceil_at_subdi_slash "sub/dir/"
+
+
+GIT_CEILING_DIRECTORIES="foo:$TRASH_ROOT/sub"
+test_fail second_of_two
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub:bar"
+test_fail first_of_two
+
+GIT_CEILING_DIRECTORIES="foo:$TRASH_ROOT/sub:bar"
+test_fail second_of_three
+
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sub"
+GIT_DIR=../../.git
+export GIT_DIR
+test_prefix git_dir_specified ""
+unset GIT_DIR
+
+
+cd ../.. || exit 1
+mkdir -p s/d || exit 1
+cd s/d || exit 1
+
+unset GIT_CEILING_DIRECTORIES
+test_prefix sd_no_ceil "s/d/"
+
+export GIT_CEILING_DIRECTORIES
+
+GIT_CEILING_DIRECTORIES=""
+test_prefix sd_ceil_empty "s/d/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT"
+test_fail sd_ceil_at_trash
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/"
+test_fail sd_ceil_at_trash_slash
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s"
+test_fail sd_ceil_at_s
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/"
+test_fail sd_ceil_at_s_slash
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/d"
+test_prefix sd_ceil_at_sd "s/d/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/d/"
+test_prefix sd_ceil_at_sd_slash "s/d/"
+
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su"
+test_prefix sd_ceil_at_su "s/d/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/su/"
+test_prefix sd_ceil_at_su_slash "s/d/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/di"
+test_prefix sd_ceil_at_s_di "s/d/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/s/di"
+test_prefix sd_ceil_at_s_di_slash "s/d/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sdi"
+test_prefix sd_ceil_at_sdi "s/d/"
+
+GIT_CEILING_DIRECTORIES="$TRASH_ROOT/sdi"
+test_prefix sd_ceil_at_sdi_slash "s/d/"
+
+
+test_done
diff --git a/t/t2000-checkout-cache-clash.sh b/t/t2000-checkout-cache-clash.sh
index 5141fab..f7e1a73 100755
--- a/t/t2000-checkout-cache-clash.sh
+++ b/t/t2000-checkout-cache-clash.sh
@@ -38,7 +38,7 @@
 
 test_expect_success \
     'git checkout-index without -f should fail on conflicting work tree.' \
-    '! git checkout-index -a'
+    'test_must_fail git checkout-index -a'
 
 test_expect_success \
     'git checkout-index with -f should succeed.' \
diff --git a/t/t2005-checkout-index-symlinks.sh b/t/t2005-checkout-index-symlinks.sh
index a84c5a6..ed12c4d 100755
--- a/t/t2005-checkout-index-symlinks.sh
+++ b/t/t2005-checkout-index-symlinks.sh
@@ -13,7 +13,7 @@
 test_expect_success \
 'preparation' '
 git config core.symlinks false &&
-l=$(echo -n file | git-hash-object -t blob -w --stdin) &&
+l=$(echo -n file | git hash-object -t blob -w --stdin) &&
 echo "120000 $l	symlink" | git update-index --index-info'
 
 test_expect_success \
@@ -23,6 +23,6 @@
 
 test_expect_success \
 'the file must be the blob we added during the setup' '
-test "$(git-hash-object -t blob symlink)" = $l'
+test "$(git hash-object -t blob symlink)" = $l'
 
 test_done
diff --git a/t/t2010-checkout-ambiguous.sh b/t/t2010-checkout-ambiguous.sh
new file mode 100755
index 0000000..7cc0a35
--- /dev/null
+++ b/t/t2010-checkout-ambiguous.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+test_description='checkout and pathspecs/refspecs ambiguities'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+	echo hello >world &&
+	echo hello >all &&
+	git add all world &&
+	git commit -m initial &&
+	git branch world
+'
+
+test_expect_success 'reference must be a tree' '
+	test_must_fail git checkout $(git hash-object ./all) --
+'
+
+test_expect_success 'branch switching' '
+	test "refs/heads/master" = "$(git symbolic-ref HEAD)" &&
+	git checkout world -- &&
+	test "refs/heads/world" = "$(git symbolic-ref HEAD)"
+'
+
+test_expect_success 'checkout world from the index' '
+	echo bye > world &&
+	git checkout -- world &&
+	git diff --exit-code --quiet
+'
+
+test_expect_success 'non ambiguous call' '
+	git checkout all
+'
+
+test_expect_success 'allow the most common case' '
+	git checkout world &&
+	test "refs/heads/world" = "$(git symbolic-ref HEAD)"
+'
+
+test_expect_success 'check ambiguity' '
+	test_must_fail git checkout world all
+'
+
+test_expect_success 'disambiguate checking out from a tree-ish' '
+	echo bye > world &&
+	git checkout world -- world &&
+	git diff --exit-code --quiet
+'
+
+test_done
diff --git a/t/t2011-checkout-invalid-head.sh b/t/t2011-checkout-invalid-head.sh
new file mode 100755
index 0000000..764bb0a
--- /dev/null
+++ b/t/t2011-checkout-invalid-head.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+test_description='checkout switching away from an invalid branch'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+	echo hello >world &&
+	git add world &&
+	git commit -m initial
+'
+
+test_expect_success 'checkout master from invalid HEAD' '
+	echo 0000000000000000000000000000000000000000 >.git/HEAD &&
+	git checkout master --
+'
+
+test_done
diff --git a/t/t2050-git-dir-relative.sh b/t/t2050-git-dir-relative.sh
index 88f268b..b7131d8 100755
--- a/t/t2050-git-dir-relative.sh
+++ b/t/t2050-git-dir-relative.sh
@@ -26,8 +26,8 @@
 
 test_expect_success 'post-commit hook used ordinarily' '
 echo initial >top &&
-git-add top
-git-commit -m initial &&
+git add top
+git commit -m initial &&
 test -r "${COMMIT_FILE}"
 '
 
diff --git a/t/t2100-update-cache-badpath.sh b/t/t2100-update-cache-badpath.sh
index 9beaecd..6ef2dcf 100755
--- a/t/t2100-update-cache-badpath.sh
+++ b/t/t2100-update-cache-badpath.sh
@@ -46,6 +46,6 @@
 do
 	test_expect_success \
 	    "git update-index to add conflicting path $p should fail." \
-	    "! git update-index --add -- $p"
+	    "test_must_fail git update-index --add -- $p"
 done
 test_done
diff --git a/t/t2101-update-index-reupdate.sh b/t/t2101-update-index-reupdate.sh
index 59b560b..648184f 100755
--- a/t/t2101-update-index-reupdate.sh
+++ b/t/t2101-update-index-reupdate.sh
@@ -40,7 +40,7 @@
 	 git ls-files -s >current &&
 	 cmp current expected'
 
-test_expect_success 'first commit' 'git-commit -m initial'
+test_expect_success 'first commit' 'git commit -m initial'
 
 cat > expected <<\EOF
 100644 53ab446c3f4e42ce9bb728a0ccb283a101be4979 0	dir1/file3
diff --git a/t/t2102-update-index-symlinks.sh b/t/t2102-update-index-symlinks.sh
index 19d0894..f195aef 100755
--- a/t/t2102-update-index-symlinks.sh
+++ b/t/t2102-update-index-symlinks.sh
@@ -13,7 +13,7 @@
 test_expect_success \
 'preparation' '
 git config core.symlinks false &&
-l=$(echo -n file | git-hash-object -t blob -w --stdin) &&
+l=$(echo -n file | git hash-object -t blob -w --stdin) &&
 echo "120000 $l	symlink" | git update-index --index-info'
 
 test_expect_success \
diff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh
index f57a6e0..cd9231c 100755
--- a/t/t2200-add-update.sh
+++ b/t/t2200-add-update.sh
@@ -26,7 +26,7 @@
 	echo initial >dir2/sub3 &&
 	git add check dir1 dir2 top foo &&
 	test_tick
-	git-commit -m initial &&
+	git commit -m initial &&
 
 	echo changed >check &&
 	echo changed >top &&
@@ -40,20 +40,20 @@
 '
 
 test_expect_success 'update noticed a removal' '
-	test "$(git-ls-files dir1/sub1)" = ""
+	test "$(git ls-files dir1/sub1)" = ""
 '
 
 test_expect_success 'update touched correct path' '
-	test "$(git-diff-files --name-status dir2/sub3)" = ""
+	test "$(git diff-files --name-status dir2/sub3)" = ""
 '
 
 test_expect_success 'update did not touch other tracked files' '
-	test "$(git-diff-files --name-status check)" = "M	check" &&
-	test "$(git-diff-files --name-status top)" = "M	top"
+	test "$(git diff-files --name-status check)" = "M	check" &&
+	test "$(git diff-files --name-status top)" = "M	top"
 '
 
 test_expect_success 'update did not touch untracked files' '
-	test "$(git-ls-files dir2/other)" = ""
+	test "$(git ls-files dir2/other)" = ""
 '
 
 test_expect_success 'cache tree has not been corrupted' '
diff --git a/t/t2201-add-update-typechange.sh b/t/t2201-add-update-typechange.sh
index e15e3eb..d24c7d9 100755
--- a/t/t2201-add-update-typechange.sh
+++ b/t/t2201-add-update-typechange.sh
@@ -106,12 +106,12 @@
 
 test_expect_success diff-files '
 	git diff-files --raw >actual &&
-	diff -u expect-files actual
+	test_cmp expect-files actual
 '
 
 test_expect_success diff-index '
 	git diff-index --raw HEAD -- >actual &&
-	diff -u expect-index actual
+	test_cmp expect-index actual
 '
 
 test_expect_success 'add -u' '
@@ -119,7 +119,7 @@
 	cp -p ".git/index" ".git/saved-index" &&
 	git add -u &&
 	git ls-files -s >actual &&
-	diff -u expect-final actual
+	test_cmp expect-final actual
 '
 
 test_expect_success 'commit -a' '
@@ -130,11 +130,11 @@
 	fi &&
 	git commit -m "second" -a &&
 	git ls-files -s >actual &&
-	diff -u expect-final actual &&
+	test_cmp expect-final actual &&
 	rm -f .git/index &&
 	git read-tree HEAD &&
 	git ls-files -s >actual &&
-	diff -u expect-final actual
+	test_cmp expect-final actual
 '
 
 test_done
diff --git a/t/t2202-add-addremove.sh b/t/t2202-add-addremove.sh
new file mode 100755
index 0000000..6a81510
--- /dev/null
+++ b/t/t2202-add-addremove.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+test_description='git add --all'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+	(
+		echo .gitignore
+		echo will-remove
+	) >expect &&
+	(
+		echo actual
+		echo expect
+		echo ignored
+	) >.gitignore &&
+	>will-remove &&
+	git add --all &&
+	test_tick &&
+	git commit -m initial &&
+	git ls-files >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'git add --all' '
+	(
+		echo .gitignore
+		echo not-ignored
+		echo "M	.gitignore"
+		echo "A	not-ignored"
+		echo "D	will-remove"
+	) >expect &&
+	>ignored &&
+	>not-ignored &&
+	echo modification >>.gitignore &&
+	rm -f will-remove &&
+	git add --all &&
+	git update-index --refresh &&
+	git ls-files >actual &&
+	git diff-index --name-status --cached HEAD >>actual &&
+	test_cmp expect actual
+'
+
+test_done
diff --git a/t/t3001-ls-files-others-exclude.sh b/t/t3001-ls-files-others-exclude.sh
index 1caeaca..8666946 100755
--- a/t/t3001-ls-files-others-exclude.sh
+++ b/t/t3001-ls-files-others-exclude.sh
@@ -96,7 +96,7 @@
 #	three/
 EOF
 
-test_expect_success 'git-status honours core.excludesfile' \
+test_expect_success 'git status honors core.excludesfile' \
 	'test_cmp expect output'
 
 test_expect_success 'trailing slash in exclude allows directory match(1)' '
diff --git a/t/t3020-ls-files-error-unmatch.sh b/t/t3020-ls-files-error-unmatch.sh
index f4da869..f4066cb 100755
--- a/t/t3020-ls-files-error-unmatch.sh
+++ b/t/t3020-ls-files-error-unmatch.sh
@@ -13,11 +13,11 @@
 
 touch foo bar
 git update-index --add foo bar
-git-commit -m "add foo bar"
+git commit -m "add foo bar"
 
 test_expect_success \
     'git ls-files --error-unmatch should fail with unmatched path.' \
-    '! git ls-files --error-unmatch foo bar-does-not-match'
+    'test_must_fail git ls-files --error-unmatch foo bar-does-not-match'
 
 test_expect_success \
     'git ls-files --error-unmatch should succeed eith matched paths.' \
diff --git a/t/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh
index aff3603..0de613d 100755
--- a/t/t3030-merge-recursive.sh
+++ b/t/t3030-merge-recursive.sh
@@ -241,7 +241,7 @@
 	rm -fr [abcd] &&
 	git checkout -f "$c2" &&
 
-	git-merge-recursive "$c0" -- "$c2" "$c1"
+	git merge-recursive "$c0" -- "$c2" "$c1"
 	status=$?
 	case "$status" in
 	1)
@@ -269,12 +269,23 @@
 
 '
 
+test_expect_success 'fail if the index has unresolved entries' '
+
+	rm -fr [abcd] &&
+	git checkout -f "$c1" &&
+
+	test_must_fail git merge "$c5" &&
+	test_must_fail git merge "$c5" 2> out &&
+	grep "You are in the middle of a conflicted merge" out
+
+'
+
 test_expect_success 'merge-recursive remove conflict' '
 
 	rm -fr [abcd] &&
 	git checkout -f "$c1" &&
 
-	git-merge-recursive "$c0" -- "$c1" "$c5"
+	git merge-recursive "$c0" -- "$c1" "$c5"
 	status=$?
 	case "$status" in
 	1)
@@ -306,7 +317,7 @@
 	git reset --hard &&
 	git checkout -f "$c1" &&
 
-	git-merge-recursive "$c0" -- "$c1" "$c3"
+	git merge-recursive "$c0" -- "$c1" "$c3"
 '
 
 test_expect_success 'merge-recursive result' '
@@ -328,7 +339,7 @@
 	git reset --hard &&
 	git checkout -f "$c1" &&
 
-	git-merge-recursive "$c0" -- "$c1" "$c4"
+	git merge-recursive "$c0" -- "$c1" "$c4"
 	status=$?
 	case "$status" in
 	1)
@@ -362,7 +373,7 @@
 	git reset --hard &&
 	git checkout -f "$c4" &&
 
-	git-merge-recursive "$c0" -- "$c4" "$c1"
+	git merge-recursive "$c0" -- "$c4" "$c1"
 	status=$?
 	case "$status" in
 	1)
@@ -396,7 +407,7 @@
 	git reset --hard &&
 	git checkout -f "$c1" &&
 
-	git-merge-recursive "$c0" -- "$c1" "$c6"
+	git merge-recursive "$c0" -- "$c1" "$c6"
 	status=$?
 	case "$status" in
 	1)
@@ -430,7 +441,7 @@
 	git reset --hard &&
 	git checkout -f "$c6" &&
 
-	git-merge-recursive "$c0" -- "$c6" "$c1"
+	git merge-recursive "$c0" -- "$c6" "$c1"
 	status=$?
 	case "$status" in
 	1)
@@ -524,4 +535,15 @@
 
 '
 
+test_expect_success 'merge removes empty directories' '
+
+	git reset --hard master &&
+	git checkout -b rm &&
+	git rm d/e &&
+	git commit -mremoved-d/e &&
+	git checkout master &&
+	git merge -s recursive rm &&
+	test_must_fail test -d d
+'
+
 test_done
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 8d87686..25e9971 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -14,10 +14,10 @@
     'prepare a trivial repository' \
     'echo Hello > A &&
      git update-index --add A &&
-     git-commit -m "Initial commit." &&
+     git commit -m "Initial commit." &&
      echo World >> A &&
      git update-index --add A &&
-     git-commit -m "Second commit." &&
+     git commit -m "Second commit." &&
      HEAD=$(git rev-parse --verify HEAD)'
 
 test_expect_success \
@@ -78,13 +78,13 @@
 test_expect_success 'git branch -m o/o o should fail when o/p exists' '
 	git branch o/o &&
         git branch o/p &&
-	! git branch -m o/o o
+	test_must_fail git branch -m o/o o
 '
 
 test_expect_success 'git branch -m q r/q should fail when r exists' '
 	git branch q &&
 	git branch r &&
-	! git branch -m q r/q
+	test_must_fail git branch -m q r/q
 '
 
 mv .git/config .git/config-saved
@@ -110,20 +110,29 @@
 
 test_expect_success 'config information was renamed, too' \
 	"test $(git config branch.s.dummy) = Hello &&
-	 ! git config branch.s/s/dummy"
+	 test_must_fail git config branch.s/s/dummy"
+
+test_expect_success 'renaming a symref is not allowed' \
+'
+	git symbolic-ref refs/heads/master2 refs/heads/master &&
+	test_must_fail git branch -m master2 master3 &&
+	git symbolic-ref refs/heads/master2 &&
+	test -f .git/refs/heads/master &&
+	! test -f .git/refs/heads/master3
+'
 
 test_expect_success \
     'git branch -m u v should fail when the reflog for u is a symlink' '
      git branch -l u &&
      mv .git/logs/refs/heads/u real-u &&
      ln -s real-u .git/logs/refs/heads/u &&
-     ! git branch -m u v
+     test_must_fail git branch -m u v
 '
 
 test_expect_success 'test tracking setup via --track' \
     'git config remote.local.url . &&
      git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
-     (git show-ref -q refs/remotes/local/master || git-fetch local) &&
+     (git show-ref -q refs/remotes/local/master || git fetch local) &&
      git branch --track my1 local/master &&
      test $(git config branch.my1.remote) = local &&
      test $(git config branch.my1.merge) = refs/heads/master'
@@ -131,7 +140,7 @@
 test_expect_success 'test tracking setup (non-wildcard, matching)' \
     'git config remote.local.url . &&
      git config remote.local.fetch refs/heads/master:refs/remotes/local/master &&
-     (git show-ref -q refs/remotes/local/master || git-fetch local) &&
+     (git show-ref -q refs/remotes/local/master || git fetch local) &&
      git branch --track my4 local/master &&
      test $(git config branch.my4.remote) = local &&
      test $(git config branch.my4.merge) = refs/heads/master'
@@ -139,7 +148,7 @@
 test_expect_success 'test tracking setup (non-wildcard, not matching)' \
     'git config remote.local.url . &&
      git config remote.local.fetch refs/heads/s:refs/remotes/local/s &&
-     (git show-ref -q refs/remotes/local/master || git-fetch local) &&
+     (git show-ref -q refs/remotes/local/master || git fetch local) &&
      git branch --track my5 local/master &&
      ! test "$(git config branch.my5.remote)" = local &&
      ! test "$(git config branch.my5.merge)" = refs/heads/master'
@@ -148,7 +157,7 @@
     'git config branch.autosetupmerge true &&
      git config remote.local.url . &&
      git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
-     (git show-ref -q refs/remotes/local/master || git-fetch local) &&
+     (git show-ref -q refs/remotes/local/master || git fetch local) &&
      git branch my3 local/master &&
      test $(git config branch.my3.remote) = local &&
      test $(git config branch.my3.merge) = refs/heads/master'
@@ -157,7 +166,7 @@
     'git config branch.autosetupmerge true &&
      git config remote.local.url . &&
      git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
-     (git show-ref -q refs/remotes/local/master || git-fetch local) &&
+     (git show-ref -q refs/remotes/local/master || git fetch local) &&
      git branch --no-track my2 local/master &&
      git config branch.autosetupmerge false &&
      ! test "$(git config branch.my2.remote)" = local &&
@@ -173,7 +182,7 @@
 test_expect_success 'test tracking setup via --track but deeper' \
     'git config remote.local.url . &&
      git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
-     (git show-ref -q refs/remotes/local/o/o || git-fetch local) &&
+     (git show-ref -q refs/remotes/local/o/o || git fetch local) &&
      git branch --track my7 local/o/o &&
      test "$(git config branch.my7.remote)" = local &&
      test "$(git config branch.my7.merge)" = refs/heads/o/o'
@@ -200,7 +209,7 @@
 
 test_expect_success \
     'branch from non-branch HEAD w/--track causes failure' \
-    '!(git branch --track my10 HEAD^)'
+    'test_must_fail git branch --track my10 HEAD^'
 
 # Keep this test last, as it changes the current branch
 cat >expect <<EOF
@@ -209,7 +218,7 @@
 test_expect_success \
     'git checkout -b g/h/i -l should create a branch and a log' \
 	'GIT_COMMITTER_DATE="2005-05-26 23:30" \
-     git-checkout -b g/h/i -l master &&
+     git checkout -b g/h/i -l master &&
 	 test -f .git/refs/heads/g/h/i &&
 	 test -f .git/logs/refs/heads/g/h/i &&
 	 diff expect .git/logs/refs/heads/g/h/i'
@@ -228,7 +237,7 @@
 	git config remote.local.url . &&
 	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
 	git config branch.autosetuprebase local &&
-	(git show-ref -q refs/remotes/local/o || git-fetch local) &&
+	(git show-ref -q refs/remotes/local/o || git fetch local) &&
 	git branch mybase &&
 	git branch --track myr1 mybase &&
 	test "$(git config branch.myr1.remote)" = . &&
@@ -240,7 +249,7 @@
 	git config remote.local.url . &&
 	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
 	git config branch.autosetuprebase always &&
-	(git show-ref -q refs/remotes/local/o || git-fetch local) &&
+	(git show-ref -q refs/remotes/local/o || git fetch local) &&
 	git branch mybase2 &&
 	git branch --track myr2 mybase &&
 	test "$(git config branch.myr2.remote)" = . &&
@@ -252,7 +261,7 @@
 	git config remote.local.url . &&
 	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
 	git config branch.autosetuprebase remote &&
-	(git show-ref -q refs/remotes/local/o || git-fetch local) &&
+	(git show-ref -q refs/remotes/local/o || git fetch local) &&
 	git branch mybase3 &&
 	git branch --track myr3 mybase2 &&
 	test "$(git config branch.myr3.remote)" = . &&
@@ -264,7 +273,7 @@
 	git config remote.local.url . &&
 	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
 	git config branch.autosetuprebase never &&
-	(git show-ref -q refs/remotes/local/o || git-fetch local) &&
+	(git show-ref -q refs/remotes/local/o || git fetch local) &&
 	git branch mybase4 &&
 	git branch --track myr4 mybase2 &&
 	test "$(git config branch.myr4.remote)" = . &&
@@ -276,7 +285,7 @@
 	git config remote.local.url . &&
 	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
 	git config branch.autosetuprebase local &&
-	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	(git show-ref -q refs/remotes/local/master || git fetch local) &&
 	git branch --track myr5 local/master &&
 	test "$(git config branch.myr5.remote)" = local &&
 	test "$(git config branch.myr5.merge)" = refs/heads/master &&
@@ -287,7 +296,7 @@
 	git config remote.local.url . &&
 	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
 	git config branch.autosetuprebase never &&
-	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	(git show-ref -q refs/remotes/local/master || git fetch local) &&
 	git branch --track myr6 local/master &&
 	test "$(git config branch.myr6.remote)" = local &&
 	test "$(git config branch.myr6.merge)" = refs/heads/master &&
@@ -298,7 +307,7 @@
 	git config remote.local.url . &&
 	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
 	git config branch.autosetuprebase remote &&
-	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	(git show-ref -q refs/remotes/local/master || git fetch local) &&
 	git branch --track myr7 local/master &&
 	test "$(git config branch.myr7.remote)" = local &&
 	test "$(git config branch.myr7.merge)" = refs/heads/master &&
@@ -309,7 +318,7 @@
 	git config remote.local.url . &&
 	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
 	git config branch.autosetuprebase remote &&
-	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	(git show-ref -q refs/remotes/local/master || git fetch local) &&
 	git branch --track myr8 local/master &&
 	test "$(git config branch.myr8.remote)" = local &&
 	test "$(git config branch.myr8.merge)" = refs/heads/master &&
@@ -320,7 +329,7 @@
 	git config --unset branch.autosetuprebase &&
 	git config remote.local.url . &&
 	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
-	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	(git show-ref -q refs/remotes/local/master || git fetch local) &&
 	git branch --track myr9 local/master &&
 	test "$(git config branch.myr9.remote)" = local &&
 	test "$(git config branch.myr9.merge)" = refs/heads/master &&
@@ -330,7 +339,7 @@
 test_expect_success 'autosetuprebase unconfigured on a tracked local branch' '
 	git config remote.local.url . &&
 	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
-	(git show-ref -q refs/remotes/local/o || git-fetch local) &&
+	(git show-ref -q refs/remotes/local/o || git fetch local) &&
 	git branch mybase10 &&
 	git branch --track myr10 mybase2 &&
 	test "$(git config branch.myr10.remote)" = . &&
@@ -341,7 +350,7 @@
 test_expect_success 'autosetuprebase unconfigured on untracked local branch' '
 	git config remote.local.url . &&
 	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
-	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	(git show-ref -q refs/remotes/local/master || git fetch local) &&
 	git branch --no-track myr11 mybase2 &&
 	test "z$(git config branch.myr11.remote)" = z &&
 	test "z$(git config branch.myr11.merge)" = z &&
@@ -351,7 +360,7 @@
 test_expect_success 'autosetuprebase unconfigured on untracked remote branch' '
 	git config remote.local.url . &&
 	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
-	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	(git show-ref -q refs/remotes/local/master || git fetch local) &&
 	git branch --no-track myr12 local/master &&
 	test "z$(git config branch.myr12.remote)" = z &&
 	test "z$(git config branch.myr12.merge)" = z &&
@@ -362,7 +371,7 @@
 	git config branch.autosetuprebase never &&
 	git config remote.local.url . &&
 	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
-	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	(git show-ref -q refs/remotes/local/master || git fetch local) &&
 	git branch --no-track myr13 mybase2 &&
 	test "z$(git config branch.myr13.remote)" = z &&
 	test "z$(git config branch.myr13.merge)" = z &&
@@ -373,7 +382,7 @@
 	git config branch.autosetuprebase local &&
 	git config remote.local.url . &&
 	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
-	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	(git show-ref -q refs/remotes/local/master || git fetch local) &&
 	git branch --no-track myr14 mybase2 &&
 	test "z$(git config branch.myr14.remote)" = z &&
 	test "z$(git config branch.myr14.merge)" = z &&
@@ -384,7 +393,7 @@
 	git config branch.autosetuprebase remote &&
 	git config remote.local.url . &&
 	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
-	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	(git show-ref -q refs/remotes/local/master || git fetch local) &&
 	git branch --no-track myr15 mybase2 &&
 	test "z$(git config branch.myr15.remote)" = z &&
 	test "z$(git config branch.myr15.merge)" = z &&
@@ -395,7 +404,7 @@
 	git config branch.autosetuprebase always &&
 	git config remote.local.url . &&
 	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
-	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	(git show-ref -q refs/remotes/local/master || git fetch local) &&
 	git branch --no-track myr16 mybase2 &&
 	test "z$(git config branch.myr16.remote)" = z &&
 	test "z$(git config branch.myr16.merge)" = z &&
@@ -406,7 +415,7 @@
 	git config branch.autosetuprebase never &&
 	git config remote.local.url . &&
 	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
-	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	(git show-ref -q refs/remotes/local/master || git fetch local) &&
 	git branch --no-track myr17 local/master &&
 	test "z$(git config branch.myr17.remote)" = z &&
 	test "z$(git config branch.myr17.merge)" = z &&
@@ -417,7 +426,7 @@
 	git config branch.autosetuprebase local &&
 	git config remote.local.url . &&
 	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
-	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	(git show-ref -q refs/remotes/local/master || git fetch local) &&
 	git branch --no-track myr18 local/master &&
 	test "z$(git config branch.myr18.remote)" = z &&
 	test "z$(git config branch.myr18.merge)" = z &&
@@ -428,7 +437,7 @@
 	git config branch.autosetuprebase remote &&
 	git config remote.local.url . &&
 	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
-	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	(git show-ref -q refs/remotes/local/master || git fetch local) &&
 	git branch --no-track myr19 local/master &&
 	test "z$(git config branch.myr19.remote)" = z &&
 	test "z$(git config branch.myr19.merge)" = z &&
@@ -439,7 +448,7 @@
 	git config branch.autosetuprebase always &&
 	git config remote.local.url . &&
 	git config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
-	(git show-ref -q refs/remotes/local/master || git-fetch local) &&
+	(git show-ref -q refs/remotes/local/master || git fetch local) &&
 	git branch --no-track myr20 local/master &&
 	test "z$(git config branch.myr20.remote)" = z &&
 	test "z$(git config branch.myr20.merge)" = z &&
diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh
index b64ccfb..413019a 100755
--- a/t/t3210-pack-refs.sh
+++ b/t/t3210-pack-refs.sh
@@ -17,7 +17,7 @@
     'prepare a trivial repository' \
     'echo Hello > A &&
      git update-index --add A &&
-     git-commit -m "Initial commit." &&
+     git commit -m "Initial commit." &&
      HEAD=$(git rev-parse --verify HEAD)'
 
 SHA1=
@@ -43,7 +43,7 @@
      git branch c &&
      git pack-refs --all &&
      rm -f .git/refs/heads/c &&
-     ! git branch c/d
+     test_must_fail git branch c/d
 '
 
 test_expect_success \
@@ -72,7 +72,7 @@
 test_expect_success 'git branch i/j/k should barf if branch i exists' '
      git branch i &&
      git pack-refs --all --prune &&
-     ! git branch i/j/k
+     test_must_fail git branch i/j/k
 '
 
 test_expect_success \
@@ -96,8 +96,15 @@
      git branch -d n/o/p &&
      git branch n'
 
+test_expect_success \
+	'see if up-to-date packed refs are preserved' \
+	'git branch q &&
+	 git pack-refs --all --prune &&
+	 git update-ref refs/heads/q refs/heads/q &&
+	 ! test -f .git/refs/heads/q'
+
 test_expect_success 'pack, prune and repack' '
-	git-tag foo &&
+	git tag foo &&
 	git pack-refs --all --prune &&
 	git show-ref >all-of-them &&
 	git pack-refs &&
diff --git a/t/t3300-funny-names.sh b/t/t3300-funny-names.sh
index 0574ef1..db46d53 100755
--- a/t/t3300-funny-names.sh
+++ b/t/t3300-funny-names.sh
@@ -21,7 +21,7 @@
 3. A quick brown fox jumps over the lazy cat, oops dog.
 EOF
 
-cat >"$p1" "$p0"
+cat 2>/dev/null >"$p1" "$p0"
 echo 'Foo Bar Baz' >"$p2"
 
 test -f "$p1" && cmp "$p0" "$p1" || {
diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh
index 91bb5e1..b7a670e 100755
--- a/t/t3400-rebase.sh
+++ b/t/t3400-rebase.sh
@@ -16,15 +16,15 @@
     'prepare repository with topic branches' \
     'echo First > A &&
      git update-index --add A &&
-     git-commit -m "Add A." &&
+     git commit -m "Add A." &&
      git checkout -b my-topic-branch &&
      echo Second > B &&
      git update-index --add B &&
-     git-commit -m "Add B." &&
+     git commit -m "Add B." &&
      git checkout -f master &&
      echo Third >> A &&
      git update-index A &&
-     git-commit -m "Modify A." &&
+     git commit -m "Modify A." &&
      git checkout -b side my-topic-branch &&
      echo Side >> C &&
      git add C &&
diff --git a/t/t3401-rebase-partial.sh b/t/t3401-rebase-partial.sh
index 4934a4e..aea6685 100755
--- a/t/t3401-rebase-partial.sh
+++ b/t/t3401-rebase-partial.sh
@@ -15,29 +15,29 @@
     'prepare repository with topic branch' \
     'echo First > A &&
      git update-index --add A &&
-     git-commit -m "Add A." &&
+     git commit -m "Add A." &&
 
-     git-checkout -b my-topic-branch &&
+     git checkout -b my-topic-branch &&
 
      echo Second > B &&
      git update-index --add B &&
-     git-commit -m "Add B." &&
+     git commit -m "Add B." &&
 
      echo AnotherSecond > C &&
      git update-index --add C &&
-     git-commit -m "Add C." &&
+     git commit -m "Add C." &&
 
-     git-checkout -f master &&
+     git checkout -f master &&
 
      echo Third >> A &&
      git update-index A &&
-     git-commit -m "Modify A."
+     git commit -m "Modify A."
 '
 
 test_expect_success \
     'pick top patch from topic branch into master' \
     'git cherry-pick my-topic-branch^0 &&
-     git-checkout -f my-topic-branch &&
+     git checkout -f my-topic-branch &&
      git branch master-merge master &&
      git branch my-topic-branch-merge my-topic-branch
 '
@@ -49,13 +49,13 @@
 '
 
 test_expect_success \
-    'rebase topic branch against new master and check git-am did not get halted' \
-    'git-rebase master && test ! -d .dotest'
+    'rebase topic branch against new master and check git am did not get halted' \
+    'git rebase master && test ! -d .git/rebase-apply'
 
 test_expect_success \
 	'rebase --merge topic branch that was partially merged upstream' \
-	'git-checkout -f my-topic-branch-merge &&
-	 git-rebase --merge master-merge &&
-	 test ! -d .git/.dotest-merge'
+	'git checkout -f my-topic-branch-merge &&
+	 git rebase --merge master-merge &&
+	 test ! -d .git/rebase-merge'
 
 test_done
diff --git a/t/t3403-rebase-skip.sh b/t/t3403-rebase-skip.sh
index 0a26099..64446e3 100755
--- a/t/t3403-rebase-skip.sh
+++ b/t/t3403-rebase-skip.sh
@@ -7,7 +7,7 @@
 
 . ./test-lib.sh
 
-# we assume the default git-am -3 --skip strategy is tested independently
+# we assume the default git am -3 --skip strategy is tested independently
 # and always works :)
 
 test_expect_success setup '
@@ -32,7 +32,7 @@
 	'
 
 test_expect_success 'rebase with git am -3 (default)' '
-	! git rebase master
+	test_must_fail git rebase master
 '
 
 test_expect_success 'rebase --skip with am -3' '
@@ -43,7 +43,7 @@
 	test refs/heads/skip-reference = $(git symbolic-ref HEAD) &&
 	git branch post-rebase &&
 	git reset --hard pre-rebase &&
-	! git rebase master &&
+	test_must_fail git rebase master &&
 	echo "hello" > hello &&
 	git add hello &&
 	git rebase --continue &&
@@ -53,7 +53,9 @@
 
 test_expect_success 'checkout skip-merge' 'git checkout -f skip-merge'
 
-test_expect_success 'rebase with --merge' '! git rebase --merge master'
+test_expect_success 'rebase with --merge' '
+	test_must_fail git rebase --merge master
+'
 
 test_expect_success 'rebase --skip with --merge' '
 	git rebase --skip
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index b9e3dbd..7d10a27 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -96,6 +96,7 @@
 
 test_expect_success 'no changes are a nop' '
 	git rebase -i F &&
+	test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch2" &&
 	test $(git rev-parse I) = $(git rev-parse HEAD)
 '
 
@@ -104,14 +105,26 @@
 	git rm file6 &&
 	git commit -m "stop here" &&
 	git rebase -i F branch2 &&
+	test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch2" &&
+	test $(git rev-parse I) = $(git rev-parse branch2) &&
 	test $(git rev-parse I) = $(git rev-parse HEAD)
 '
 
+test_expect_success 'test --onto <branch>' '
+	git checkout -b test-onto branch2 &&
+	git rebase -i --onto branch1 F &&
+	test "$(git symbolic-ref -q HEAD)" = "refs/heads/test-onto" &&
+	test $(git rev-parse HEAD^) = $(git rev-parse branch1) &&
+	test $(git rev-parse I) = $(git rev-parse branch2)
+'
+
 test_expect_success 'rebase on top of a non-conflicting commit' '
 	git checkout branch1 &&
 	git tag original-branch1 &&
 	git rebase -i branch2 &&
 	test file6 = $(git diff --name-only original-branch1) &&
+	test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch1" &&
+	test $(git rev-parse I) = $(git rev-parse branch2) &&
 	test $(git rev-parse I) = $(git rev-parse HEAD~2)
 '
 
@@ -144,17 +157,21 @@
 
 test_expect_success 'stop on conflicting pick' '
 	git tag new-branch1 &&
-	! git rebase -i master &&
-	test_cmp expect .git/.dotest-merge/patch &&
+	test_must_fail git rebase -i master &&
+	test "$(git rev-parse HEAD~3)" = "$(git rev-parse master)" &&
+	test_cmp expect .git/rebase-merge/patch &&
 	test_cmp expect2 file1 &&
-	test 4 = $(grep -v "^#" < .git/.dotest-merge/done | wc -l) &&
-	test 0 = $(grep -c "^[^#]" < .git/.dotest-merge/git-rebase-todo)
+	test "$(git diff --name-status |
+		sed -n -e "/^U/s/^U[^a-z]*//p")" = file1 &&
+	test 4 = $(grep -v "^#" < .git/rebase-merge/done | wc -l) &&
+	test 0 = $(grep -c "^[^#]" < .git/rebase-merge/git-rebase-todo)
 '
 
 test_expect_success 'abort' '
 	git rebase --abort &&
 	test $(git rev-parse new-branch1) = $(git rev-parse HEAD) &&
-	! test -d .git/.dotest-merge
+	test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch1" &&
+	! test -d .git/rebase-merge
 '
 
 test_expect_success 'retain authorship' '
@@ -185,6 +202,9 @@
 test_expect_success '-p handles "no changes" gracefully' '
 	HEAD=$(git rev-parse HEAD) &&
 	git rebase -i -p HEAD^ &&
+	git update-index --refresh &&
+	git diff-files --quiet &&
+	git diff-index --quiet --cached HEAD -- &&
 	test $HEAD = $(git rev-parse HEAD)
 '
 
@@ -194,7 +214,7 @@
 	git add unrelated-file &&
 	test_tick &&
 	git commit -m "unrelated" &&
-	git checkout -b to-be-rebased master &&
+	git checkout -b another-branch master &&
 	echo B > file1 &&
 	test_tick &&
 	git commit -m J file1 &&
@@ -203,17 +223,48 @@
 	echo C > file1 &&
 	test_tick &&
 	git commit -m K file1 &&
+	echo D > file1 &&
+	test_tick &&
+	git commit -m L1 file1 &&
+	git checkout HEAD^ &&
+	echo 1 > unrelated-file &&
+	test_tick &&
+	git commit -m L2 unrelated-file &&
+	test_tick &&
+	git merge another-branch &&
+	echo E > file1 &&
+	test_tick &&
+	git commit -m M file1 &&
+	git checkout -b to-be-rebased &&
 	test_tick &&
 	git rebase -i -p --onto branch1 master &&
-	test $(git rev-parse HEAD^^2) = $(git rev-parse to-be-preserved) &&
-	test $(git rev-parse HEAD~3) = $(git rev-parse branch1) &&
-	test $(git show HEAD:file1) = C &&
-	test $(git show HEAD~2:file1) = B
+	git update-index --refresh &&
+	git diff-files --quiet &&
+	git diff-index --quiet --cached HEAD -- &&
+	test $(git rev-parse HEAD~6) = $(git rev-parse branch1) &&
+	test $(git rev-parse HEAD~4^2) = $(git rev-parse to-be-preserved) &&
+	test $(git rev-parse HEAD^^2^) = $(git rev-parse HEAD^^^) &&
+	test $(git show HEAD~5:file1) = B &&
+	test $(git show HEAD~3:file1) = C &&
+	test $(git show HEAD:file1) = E &&
+	test $(git show HEAD:unrelated-file) = 1
+'
+
+test_expect_success 'edit ancestor with -p' '
+	FAKE_LINES="1 edit 2 3 4" git rebase -i -p HEAD~3 &&
+	echo 2 > unrelated-file &&
+	test_tick &&
+	git commit -m L2-modified --amend unrelated-file &&
+	git rebase --continue &&
+	git update-index --refresh &&
+	git diff-files --quiet &&
+	git diff-index --quiet --cached HEAD -- &&
+	test $(git show HEAD:unrelated-file) = 2
 '
 
 test_expect_success '--continue tries to commit' '
 	test_tick &&
-	! git rebase -i --onto new-branch1 HEAD^ &&
+	test_must_fail git rebase -i --onto new-branch1 HEAD^ &&
 	echo resolved > file1 &&
 	git add file1 &&
 	FAKE_COMMIT_MESSAGE="chouette!" git rebase --continue &&
@@ -224,7 +275,7 @@
 test_expect_success 'verbose flag is heeded, even after --continue' '
 	git reset --hard HEAD@{1} &&
 	test_tick &&
-	! git rebase -v -i --onto new-branch1 HEAD^ &&
+	test_must_fail git rebase -v -i --onto new-branch1 HEAD^ &&
 	echo resolved > file1 &&
 	git add file1 &&
 	git rebase --continue > output &&
@@ -259,10 +310,14 @@
 		git commit -m $n
 	done &&
 	one=$(git rev-parse HEAD~3) &&
-	! FAKE_LINES="1 squash 3 2" git rebase -i HEAD~3 &&
+	(
+		FAKE_LINES="1 squash 3 2" &&
+		export FAKE_LINES &&
+		test_must_fail git rebase -i HEAD~3
+	) &&
 	(echo one; echo two; echo four) > conflict &&
 	git add conflict &&
-	! git rebase --continue &&
+	test_must_fail git rebase --continue &&
 	echo resolved > conflict &&
 	git add conflict &&
 	git rebase --continue &&
@@ -277,13 +332,17 @@
 		git commit -m $n
 	done &&
 	one=$(git rev-parse HEAD~3) &&
-	! FAKE_LINES="3 squash 1 2" git rebase -i HEAD~3 &&
+	(
+		FAKE_LINES="3 squash 1 2" &&
+		export FAKE_LINES &&
+		test_must_fail git rebase -i HEAD~3
+	) &&
 	(echo one; echo four) > conflict &&
 	git add conflict &&
-	! git rebase --continue &&
+	test_must_fail git rebase --continue &&
 	(echo one; echo two; echo four) > conflict &&
 	git add conflict &&
-	! git rebase --continue &&
+	test_must_fail git rebase --continue &&
 	echo resolved > conflict &&
 	git add conflict &&
 	git rebase --continue &&
@@ -331,7 +390,7 @@
 	chmod a+x $PRE_COMMIT &&
 	echo "monde! " >> file1 &&
 	test_tick &&
-	! git commit -m doesnt-verify file1 &&
+	test_must_fail git commit -m doesnt-verify file1 &&
 	git commit -m doesnt-verify --no-verify file1 &&
 	test_tick &&
 	FAKE_LINES=2 git rebase -i HEAD~2
@@ -360,4 +419,15 @@
 
 '
 
+test_expect_success 'do "noop" when there is nothing to cherry-pick' '
+
+	git checkout -b branch4 HEAD &&
+	GIT_EDITOR=: git commit --amend \
+		--author="Somebody else <somebody@else.com>" 
+	test $(git rev-parse branch3) != $(git rev-parse branch4) &&
+	git rebase -i branch3 &&
+	test $(git rev-parse branch3) = $(git rev-parse branch4)
+
+'
+
 test_done
diff --git a/t/t3407-rebase-abort.sh b/t/t3407-rebase-abort.sh
index 1777ffe..2999e78 100755
--- a/t/t3407-rebase-abort.sh
+++ b/t/t3407-rebase-abort.sh
@@ -52,7 +52,7 @@
 		test -d "$dotest" &&
 		test_must_fail git rebase --skip &&
 		test $(git rev-parse HEAD) = $(git rev-parse master) &&
-		git-rebase --abort &&
+		git rebase --abort &&
 		test $(git rev-parse to-rebase) = $(git rev-parse pre-rebase) &&
 		test ! -d "$dotest"
 	'
@@ -74,7 +74,7 @@
 	'
 }
 
-testrebase "" .dotest
-testrebase " --merge" .git/.dotest-merge
+testrebase "" .git/rebase-apply
+testrebase " --merge" .git/rebase-merge
 
 test_done
diff --git a/t/t3409-rebase-hook.sh b/t/t3409-rebase-hook.sh
new file mode 100755
index 0000000..bc93dda
--- /dev/null
+++ b/t/t3409-rebase-hook.sh
@@ -0,0 +1,126 @@
+#!/bin/sh
+
+test_description='git rebase with its hook(s)'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+	echo hello >file &&
+	git add file &&
+	test_tick &&
+	git commit -m initial &&
+	echo goodbye >file &&
+	git add file &&
+	test_tick &&
+	git commit -m second &&
+	git checkout -b side HEAD^ &&
+	echo world >git &&
+	git add git &&
+	test_tick &&
+	git commit -m side &&
+	git checkout master &&
+	git log --pretty=oneline --abbrev-commit --graph --all &&
+	git branch test side
+'
+
+test_expect_success 'rebase' '
+	git checkout test &&
+	git reset --hard side &&
+	git rebase master &&
+	test "z$(cat git)" = zworld
+'
+
+test_expect_success 'rebase -i' '
+	git checkout test &&
+	git reset --hard side &&
+	EDITOR=true git rebase -i master &&
+	test "z$(cat git)" = zworld
+'
+
+test_expect_success 'setup pre-rebase hook' '
+	mkdir -p .git/hooks &&
+	cat >.git/hooks/pre-rebase <<EOF &&
+#!$SHELL_PATH
+echo "\$1,\$2" >.git/PRE-REBASE-INPUT
+EOF
+	chmod +x .git/hooks/pre-rebase
+'
+
+test_expect_success 'pre-rebase hook gets correct input (1)' '
+	git checkout test &&
+	git reset --hard side &&
+	git rebase master &&
+	test "z$(cat git)" = zworld &&
+	test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,
+
+'
+
+test_expect_success 'pre-rebase hook gets correct input (2)' '
+	git checkout test &&
+	git reset --hard side &&
+	git rebase master test &&
+	test "z$(cat git)" = zworld &&
+	test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,test
+'
+
+test_expect_success 'pre-rebase hook gets correct input (3)' '
+	git checkout test &&
+	git reset --hard side &&
+	git checkout master &&
+	git rebase master test &&
+	test "z$(cat git)" = zworld &&
+	test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,test
+'
+
+test_expect_success 'pre-rebase hook gets correct input (4)' '
+	git checkout test &&
+	git reset --hard side &&
+	EDITOR=true git rebase -i master &&
+	test "z$(cat git)" = zworld &&
+	test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,
+
+'
+
+test_expect_success 'pre-rebase hook gets correct input (5)' '
+	git checkout test &&
+	git reset --hard side &&
+	EDITOR=true git rebase -i master test &&
+	test "z$(cat git)" = zworld &&
+	test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,test
+'
+
+test_expect_success 'pre-rebase hook gets correct input (6)' '
+	git checkout test &&
+	git reset --hard side &&
+	git checkout master &&
+	EDITOR=true git rebase -i master test &&
+	test "z$(cat git)" = zworld &&
+	test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,test
+'
+
+test_expect_success 'setup pre-rebase hook that fails' '
+	mkdir -p .git/hooks &&
+	cat >.git/hooks/pre-rebase <<EOF &&
+#!$SHELL_PATH
+false
+EOF
+	chmod +x .git/hooks/pre-rebase
+'
+
+test_expect_success 'pre-rebase hook stops rebase (1)' '
+	git checkout test &&
+	git reset --hard side &&
+	test_must_fail git rebase master &&
+	test "z$(git symbolic-ref HEAD)" = zrefs/heads/test &&
+	test 0 = $(git rev-list HEAD...side | wc -l)
+'
+
+test_expect_success 'pre-rebase hook stops rebase (2)' '
+	git checkout test &&
+	git reset --hard side &&
+	EDITOR=true test_must_fail git rebase -i master &&
+	test "z$(git symbolic-ref HEAD)" = zrefs/heads/test &&
+	test 0 = $(git rev-list HEAD...side | wc -l)
+'
+
+test_done
diff --git a/t/t3500-cherry.sh b/t/t3500-cherry.sh
index 4911c48..dadbbc2 100755
--- a/t/t3500-cherry.sh
+++ b/t/t3500-cherry.sh
@@ -17,25 +17,25 @@
     'prepare repository with topic branch, and check cherry finds the 2 patches from there' \
     'echo First > A &&
      git update-index --add A &&
-     git-commit -m "Add A." &&
+     git commit -m "Add A." &&
 
-     git-checkout -b my-topic-branch &&
+     git checkout -b my-topic-branch &&
 
      echo Second > B &&
      git update-index --add B &&
-     git-commit -m "Add B." &&
+     git commit -m "Add B." &&
 
      sleep 2 &&
      echo AnotherSecond > C &&
      git update-index --add C &&
-     git-commit -m "Add C." &&
+     git commit -m "Add C." &&
 
-     git-checkout -f master &&
+     git checkout -f master &&
      rm -f B C &&
 
      echo Third >> A &&
      git update-index A &&
-     git-commit -m "Modify A." &&
+     git commit -m "Modify A." &&
 
      expr "$(echo $(git cherry master my-topic-branch) )" : "+ [^ ]* + .*"
 '
diff --git a/t/t3502-cherry-pick-merge.sh b/t/t3502-cherry-pick-merge.sh
index 7c92e26..0ab52da 100755
--- a/t/t3502-cherry-pick-merge.sh
+++ b/t/t3502-cherry-pick-merge.sh
@@ -35,7 +35,7 @@
 
 	git reset --hard &&
 	git checkout a^0 &&
-	! git cherry-pick -m 1 b &&
+	test_must_fail git cherry-pick -m 1 b &&
 	git diff --exit-code a --
 
 '
@@ -44,7 +44,7 @@
 
 	git reset --hard &&
 	git checkout a^0 &&
-	! git cherry-pick c &&
+	test_must_fail git cherry-pick c &&
 	git diff --exit-code a --
 
 '
@@ -71,7 +71,7 @@
 
 	git reset --hard &&
 	git checkout b^0 &&
-	! git cherry-pick -m 3 c
+	test_must_fail git cherry-pick -m 3 c
 
 '
 
@@ -79,7 +79,7 @@
 
 	git reset --hard &&
 	git checkout c^0 &&
-	! git revert -m 1 b &&
+	test_must_fail git revert -m 1 b &&
 	git diff --exit-code c
 
 '
@@ -88,7 +88,7 @@
 
 	git reset --hard &&
 	git checkout c^0 &&
-	! git revert c &&
+	test_must_fail git revert c &&
 	git diff --exit-code c
 
 '
@@ -115,7 +115,7 @@
 
 	git reset --hard &&
 	git checkout c^0 &&
-	! git revert -m 3 c &&
+	test_must_fail git revert -m 3 c &&
 	git diff --exit-code c
 
 '
diff --git a/t/t3503-cherry-pick-root.sh b/t/t3503-cherry-pick-root.sh
new file mode 100755
index 0000000..b0faa29
--- /dev/null
+++ b/t/t3503-cherry-pick-root.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+test_description='test cherry-picking a root commit'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+
+	echo first > file1 &&
+	git add file1 &&
+	test_tick &&
+	git commit -m "first" &&
+
+	git symbolic-ref HEAD refs/heads/second &&
+	rm .git/index file1 &&
+	echo second > file2 &&
+	git add file2 &&
+	test_tick &&
+	git commit -m "second"
+
+'
+
+test_expect_success 'cherry-pick a root commit' '
+
+	git cherry-pick master &&
+	test first = $(cat file1)
+
+'
+
+test_done
diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh
index 7893d8c..66aca99 100755
--- a/t/t3600-rm.sh
+++ b/t/t3600-rm.sh
@@ -12,14 +12,14 @@
     'Initialize test directory' \
     "touch -- foo bar baz 'space embedded' -q &&
      git add -- foo bar baz 'space embedded' -q &&
-     git-commit -m 'add normal files' &&
+     git commit -m 'add normal files' &&
      test_tabs=y &&
      if touch -- 'tab	embedded' 'newline
 embedded'
      then
      git add -- 'tab	embedded' 'newline
 embedded' &&
-     git-commit -m 'add files with tabs and newlines'
+     git commit -m 'add files with tabs and newlines'
      else
          say 'Your filesystem does not allow tabs in filenames.'
          test_tabs=n
@@ -67,7 +67,7 @@
      echo "other content" > foo
      git add foo
      echo "yet another content" > foo
-     ! git rm --cached foo
+     test_must_fail git rm --cached foo
 '
 
 test_expect_success \
@@ -82,7 +82,7 @@
 
 test_expect_success \
     'Post-check that foo exists but is not in index after git rm foo' \
-    '[ -f foo ] && ! git ls-files --error-unmatch foo'
+    '[ -f foo ] && test_must_fail git ls-files --error-unmatch foo'
 
 test_expect_success \
     'Pre-check that bar exists and is in index before "git rm bar"' \
@@ -94,7 +94,7 @@
 
 test_expect_success \
     'Post-check that bar does not exist and is not in index after "git rm -f bar"' \
-    '! [ -f bar ] && ! git ls-files --error-unmatch bar'
+    '! [ -f bar ] && test_must_fail git ls-files --error-unmatch bar'
 
 test_expect_success \
     'Test that "git rm -- -q" succeeds (remove a file that looks like an option)' \
@@ -109,7 +109,7 @@
 chmod a-w .
 test_expect_success \
     'Test that "git rm -f" fails if its rm fails' \
-    '! git rm -f baz'
+    'test_must_fail git rm -f baz'
 chmod 775 .
 else
     test_expect_success 'skipping removal failure (perhaps running as root?)' :
@@ -151,7 +151,7 @@
 
 test_expect_success 'Modify foo -- rm should refuse' '
 	echo >>foo &&
-	! git rm foo baz &&
+	test_must_fail git rm foo baz &&
 	test -f foo &&
 	test -f baz &&
 	git ls-files --error-unmatch foo baz
@@ -161,8 +161,8 @@
 	git rm -f foo baz &&
 	test ! -f foo &&
 	test ! -f baz &&
-	! git ls-files --error-unmatch foo &&
-	! git ls-files --error-unmatch bar
+	test_must_fail git ls-files --error-unmatch foo &&
+	test_must_fail git ls-files --error-unmatch bar
 '
 
 test_expect_success 'Re-add foo and baz for HEAD tests' '
@@ -173,7 +173,7 @@
 '
 
 test_expect_success 'foo is different in index from HEAD -- rm should refuse' '
-	! git rm foo baz &&
+	test_must_fail git rm foo baz &&
 	test -f foo &&
 	test -f baz &&
 	git ls-files --error-unmatch foo baz
@@ -183,8 +183,8 @@
 	git rm -f foo baz &&
 	test ! -f foo &&
 	test ! -f baz &&
-	! git ls-files --error-unmatch foo
-	! git ls-files --error-unmatch baz
+	test_must_fail git ls-files --error-unmatch foo
+	test_must_fail git ls-files --error-unmatch baz
 '
 
 test_expect_success 'Recursive test setup' '
@@ -195,14 +195,14 @@
 '
 
 test_expect_success 'Recursive without -r fails' '
-	! git rm frotz &&
+	test_must_fail git rm frotz &&
 	test -d frotz &&
 	test -f frotz/nitfol
 '
 
 test_expect_success 'Recursive with -r but dirty' '
 	echo qfwfq >>frotz/nitfol
-	! git rm -r frotz &&
+	test_must_fail git rm -r frotz &&
 	test -d frotz &&
 	test -f frotz/nitfol
 '
@@ -214,19 +214,28 @@
 '
 
 test_expect_success 'Remove nonexistent file returns nonzero exit status' '
-	! git rm nonexistent
+	test_must_fail git rm nonexistent
 '
 
 test_expect_success 'Call "rm" from outside the work tree' '
 	mkdir repo &&
-	cd repo &&
-	git init &&
-	echo something > somefile &&
-	git add somefile &&
-	git commit -m "add a file" &&
-	(cd .. &&
-	 git --git-dir=repo/.git --work-tree=repo rm somefile) &&
-	test_must_fail git ls-files --error-unmatch somefile
+	(cd repo &&
+	 git init &&
+	 echo something > somefile &&
+	 git add somefile &&
+	 git commit -m "add a file" &&
+	 (cd .. &&
+	  git --git-dir=repo/.git --work-tree=repo rm somefile) &&
+	test_must_fail git ls-files --error-unmatch somefile)
+'
+
+test_expect_success 'refresh index before checking if it is up-to-date' '
+
+	git reset --hard &&
+	test-chmtime -86400 frotz/nitfol &&
+	git rm frotz/nitfol &&
+	test ! -f frotz/nitfol
+
 '
 
 test_done
diff --git a/t/t3700-add.sh b/t/t3700-add.sh
index fcbc203..2ac93a3 100755
--- a/t/t3700-add.sh
+++ b/t/t3700-add.sh
@@ -85,12 +85,12 @@
 '
 
 test_expect_success 'error out when attempting to add ignored ones without -f' '
-	! git add a.?? &&
+	test_must_fail git add a.?? &&
 	! (git ls-files | grep "\\.ig")
 '
 
 test_expect_success 'error out when attempting to add ignored ones without -f' '
-	! git add d.?? &&
+	test_must_fail git add d.?? &&
 	! (git ls-files | grep "\\.ig")
 '
 
@@ -222,11 +222,11 @@
 	! ( git ls-files foo1 | grep foo1 )
 '
 
-test_expect_success 'git add '\''fo\?bar'\'' ignores foobar' '
+test_expect_success 'git add '\''fo\[ou\]bar'\'' ignores foobar' '
 	git reset --hard &&
-	touch fo\?bar foobar &&
-	git add '\''fo\?bar'\'' &&
-	git ls-files fo\?bar | grep -F fo\?bar &&
+	touch fo\[ou\]bar foobar &&
+	git add '\''fo\[ou\]bar'\'' &&
+	git ls-files fo\[ou\]bar | grep -F fo\[ou\]bar &&
 	! ( git ls-files foobar | grep foobar )
 '
 
diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh
index fae64ea..e95663d 100755
--- a/t/t3701-add-interactive.sh
+++ b/t/t3701-add-interactive.sh
@@ -66,6 +66,73 @@
 	grep "unchanged *+3/-0 file" output
 '
 
+cat >expected <<EOF
+EOF
+cat >fake_editor.sh <<EOF
+EOF
+chmod a+x fake_editor.sh
+test_set_editor "$(pwd)/fake_editor.sh"
+test_expect_success 'dummy edit works' '
+	(echo e; echo a) | git add -p &&
+	git diff > diff &&
+	test_cmp expected diff
+'
+
+cat >patch <<EOF
+@@ -1,1 +1,4 @@
+ this
++patch
+-doesn't
+ apply
+EOF
+echo "#!$SHELL_PATH" >fake_editor.sh
+cat >>fake_editor.sh <<\EOF
+mv -f "$1" oldpatch &&
+mv -f patch "$1"
+EOF
+chmod a+x fake_editor.sh
+test_set_editor "$(pwd)/fake_editor.sh"
+test_expect_success 'bad edit rejected' '
+	git reset &&
+	(echo e; echo n; echo d) | git add -p >output &&
+	grep "hunk does not apply" output
+'
+
+cat >patch <<EOF
+this patch
+is garbage
+EOF
+test_expect_success 'garbage edit rejected' '
+	git reset &&
+	(echo e; echo n; echo d) | git add -p >output &&
+	grep "hunk does not apply" output
+'
+
+cat >patch <<EOF
+@@ -1,0 +1,0 @@
+ baseline
++content
++newcontent
++lines
+EOF
+cat >expected <<EOF
+diff --git a/file b/file
+index b5dd6c9..f910ae9 100644
+--- a/file
++++ b/file
+@@ -1,4 +1,4 @@
+ baseline
+ content
+-newcontent
++more
+ lines
+EOF
+test_expect_success 'real edit works' '
+	(echo e; echo n; echo d) | git add -p &&
+	git diff >output &&
+	test_cmp expected output
+'
+
 if test "$(git config --bool core.filemode)" = false
 then
     say 'skipping filemode tests (filesystem does not properly support modes)'
diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index df1fd6f..6fb027b 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -2,7 +2,7 @@
 #
 #
 
-test_description='git-mktag: tag object verify test'
+test_description='git mktag: tag object verify test'
 
 . ./test-lib.sh
 
@@ -14,7 +14,7 @@
 check_verify_failure () {
 	expect="$2"
 	test_expect_success "$1" '
-		( test_must_fail git-mktag <tag.sig 2>message ) &&
+		( test_must_fail git mktag <tag.sig 2>message ) &&
 		grep "$expect" message
 	'
 }
@@ -24,7 +24,7 @@
 # for the tag.
 echo Hello >A
 git update-index --add A
-git-commit -m "Initial commit"
+git commit -m "Initial commit"
 head=$(git rev-parse --verify HEAD)
 
 ############################################################
@@ -222,7 +222,7 @@
 
 test_expect_success \
     'allow empty tag email' \
-    'git-mktag <tag.sig >.git/refs/tags/mytag 2>message'
+    'git mktag <tag.sig >.git/refs/tags/mytag 2>message'
 
 ############################################################
 # 16. disallow spaces in tag email
@@ -241,11 +241,11 @@
 ############################################################
 # 17. disallow missing tag timestamp
 
-cat >tag.sig <<EOF
+tr '_' ' ' >tag.sig <<EOF
 object $head
 type commit
 tag mytag
-tagger T A Gger <tagger@example.com>  
+tagger T A Gger <tagger@example.com>__
 
 EOF
 
@@ -350,14 +350,14 @@
 
 test_expect_success \
     'create valid tag' \
-    'git-mktag <tag.sig >.git/refs/tags/mytag 2>message'
+    'git mktag <tag.sig >.git/refs/tags/mytag 2>message'
 
 ############################################################
 # 25. check mytag
 
 test_expect_success \
     'check mytag' \
-    'git-tag -l | grep mytag'
+    'git tag -l | grep mytag'
 
 
 test_done
diff --git a/t/t3900-i18n-commit.sh b/t/t3900-i18n-commit.sh
index 883281d..f313533 100755
--- a/t/t3900-i18n-commit.sh
+++ b/t/t3900-i18n-commit.sh
@@ -18,7 +18,7 @@
 	T=$(git write-tree) &&
 	C=$(git commit-tree $T <../t3900/1-UTF-8.txt) &&
 	git update-ref HEAD $C &&
-	git-tag C0
+	git tag C0
 '
 
 test_expect_success 'no encoding header for base case' '
@@ -30,9 +30,9 @@
 do
 	test_expect_success "$H setup" '
 		git config i18n.commitencoding $H &&
-		git-checkout -b $H C0 &&
+		git checkout -b $H C0 &&
 		echo $H >F &&
-		git-commit -a -F ../t3900/$H.txt
+		git commit -a -F ../t3900/$H.txt
 	'
 done
 
diff --git a/t/t3901-i18n-patch.sh b/t/t3901-i18n-patch.sh
index 235f372..567760e 100755
--- a/t/t3901-i18n-patch.sh
+++ b/t/t3901-i18n-patch.sh
@@ -103,7 +103,7 @@
 	# we want UTF-8 encoded name.
 	. ../t3901-utf8.txt &&
 	git checkout -b test &&
-	git-rebase master &&
+	git rebase master &&
 
 	check_encoding 2
 '
@@ -114,7 +114,7 @@
 	. ../t3901-utf8.txt &&
 
 	git reset --hard side &&
-	git-rebase master &&
+	git rebase master &&
 
 	check_encoding 2
 '
@@ -126,7 +126,7 @@
 	. ../t3901-8859-1.txt &&
 
 	git reset --hard side &&
-	git-rebase master &&
+	git rebase master &&
 
 	check_encoding 2 8859
 '
@@ -139,7 +139,7 @@
 	. ../t3901-8859-1.txt &&
 
 	git reset --hard side &&
-	git-rebase master &&
+	git rebase master &&
 
 	check_encoding 2 8859
 '
@@ -211,7 +211,7 @@
 	. ../t3901-utf8.txt &&
 
 	git reset --hard side &&
-	git-rebase --merge master &&
+	git rebase --merge master &&
 
 	check_encoding 2
 '
@@ -222,7 +222,7 @@
 	. ../t3901-utf8.txt &&
 
 	git reset --hard side &&
-	git-rebase --merge master &&
+	git rebase --merge master &&
 
 	check_encoding 2
 '
@@ -234,7 +234,7 @@
 	. ../t3901-8859-1.txt &&
 
 	git reset --hard side &&
-	git-rebase --merge master &&
+	git rebase --merge master &&
 
 	check_encoding 2 8859
 '
@@ -247,7 +247,7 @@
 	. ../t3901-8859-1.txt &&
 
 	git reset --hard side &&
-	git-rebase --merge master &&
+	git rebase --merge master &&
 
 	check_encoding 2 8859
 '
diff --git a/t/t3902-quoted.sh b/t/t3902-quoted.sh
index fe4fb51..5868052 100755
--- a/t/t3902-quoted.sh
+++ b/t/t3902-quoted.sh
@@ -7,12 +7,6 @@
 
 . ./test-lib.sh
 
-P1='pathname	with HT'
-: >"$P1" 2>&1 && test -f "$P1" && rm -f "$P1" || {
-	echo >&2 'Filesystem does not support HT in names'
-	test_done
-}
-
 FN='濱野'
 GN='純'
 HT='	'
@@ -20,7 +14,7 @@
 '
 DQ='"'
 
-echo foo > "Name and an${HT}HT"
+echo foo 2>/dev/null > "Name and an${HT}HT"
 test -f "Name and an${HT}HT" || {
 	# since FAT/NTFS does not allow tabs in filenames, skip this test
 	say 'Your filesystem does not allow tabs in filenames, test skipped.'
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index 2d3ee3b..7484cbe 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -3,7 +3,7 @@
 # Copyright (c) 2007 Johannes E Schindelin
 #
 
-test_description='Test git-stash'
+test_description='Test git stash'
 
 . ./test-lib.sh
 
@@ -41,7 +41,7 @@
 	echo 4 > other-file &&
 	git add other-file &&
 	echo 5 > other-file &&
- 	test_must_fail git stash apply
+	test_must_fail git stash apply
 '
 
 test_expect_success 'apply stashed changes' '
@@ -117,4 +117,64 @@
 	test 0 = $(git stash list | wc -l)
 '
 
+cat > expect << EOF
+diff --git a/file2 b/file2
+new file mode 100644
+index 0000000..1fe912c
+--- /dev/null
++++ b/file2
+@@ -0,0 +1 @@
++bar2
+EOF
+
+cat > expect1 << EOF
+diff --git a/file b/file
+index 257cc56..5716ca5 100644
+--- a/file
++++ b/file
+@@ -1 +1 @@
+-foo
++bar
+EOF
+
+cat > expect2 << EOF
+diff --git a/file b/file
+index 7601807..5716ca5 100644
+--- a/file
++++ b/file
+@@ -1 +1 @@
+-baz
++bar
+diff --git a/file2 b/file2
+new file mode 100644
+index 0000000..1fe912c
+--- /dev/null
++++ b/file2
+@@ -0,0 +1 @@
++bar2
+EOF
+
+test_expect_success 'stash branch' '
+	echo foo > file &&
+	git commit file -m first
+	echo bar > file &&
+	echo bar2 > file2 &&
+	git add file2 &&
+	git stash &&
+	echo baz > file &&
+	git commit file -m second &&
+	git stash branch stashbranch &&
+	test refs/heads/stashbranch = $(git symbolic-ref HEAD) &&
+	test $(git rev-parse HEAD) = $(git rev-parse master^) &&
+	git diff --cached > output &&
+	test_cmp output expect &&
+	git diff > output &&
+	test_cmp output expect1 &&
+	git add file &&
+	git commit -m alternate\ second &&
+	git diff master..stashbranch > output &&
+	test_cmp output expect2 &&
+	test 0 = $(git stash list | wc -l)
+'
+
 test_done
diff --git a/t/t4012-diff-binary.sh b/t/t4012-diff-binary.sh
index eced1f3..eac1271 100755
--- a/t/t4012-diff-binary.sh
+++ b/t/t4012-diff-binary.sh
@@ -61,7 +61,7 @@
 	 detected=`sed -ne "${detected}p" broken` &&
 	 test "$detected" = xCIT'
 
-test_expect_success 'initial commit' 'git-commit -a -m initial'
+test_expect_success 'initial commit' 'git commit -a -m initial'
 
 # Try removal (b), modification (d), and creation (e).
 test_expect_success 'diff-index with --binary' \
@@ -72,9 +72,30 @@
 	 git apply --stat --summary current'
 
 test_expect_success 'apply binary patch' \
-	'git-reset --hard &&
+	'git reset --hard &&
 	 git apply --binary --index <current &&
 	 tree1=`git write-tree` &&
 	 test "$tree1" = "$tree0"'
 
+q_to_nul() {
+	perl -pe 'y/Q/\000/'
+}
+
+nul_to_q() {
+	perl -pe 'y/\000/Q/'
+}
+
+test_expect_success 'diff --no-index with binary creation' '
+	echo Q | q_to_nul >binary &&
+	(:# hide error code from diff, which just indicates differences
+	 git diff --binary --no-index /dev/null binary >current ||
+	 true
+	) &&
+	rm binary &&
+	git apply --binary <current &&
+	echo Q >expected &&
+	nul_to_q <binary >actual &&
+	test_cmp expected actual
+'
+
 test_done
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index 9337b81..99d9e0b 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -258,6 +258,7 @@
 diff --patch-with-raw -r initial..side
 diff --name-status dir2 dir
 diff --no-index --name-status dir2 dir
+diff master master^ side
 EOF
 
 test_done
diff --git a/t/t4013/diff.diff_master_master^_side b/t/t4013/diff.diff_master_master^_side
new file mode 100644
index 0000000..50ec9ca
--- /dev/null
+++ b/t/t4013/diff.diff_master_master^_side
@@ -0,0 +1,29 @@
+$ git diff master master^ side
+diff --cc dir/sub
+index cead32e,7289e35..992913c
+--- a/dir/sub
++++ b/dir/sub
+@@@ -1,6 -1,4 +1,8 @@@
+  A
+  B
+ +C
+ +D
+ +E
+ +F
++ 1
++ 2
+diff --cc file0
+index b414108,f4615da..10a8a9f
+--- a/file0
++++ b/file0
+@@@ -1,6 -1,6 +1,9 @@@
+  1
+  2
+  3
+ +4
+ +5
+ +6
++ A
++ B
++ C
+$
diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master b/t/t4013/diff.format-patch_--attach_--stdout_initial..master
index cf6891f..43346b9 100644
--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master
+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master
@@ -19,6 +19,8 @@
  file2   |    3 ---
  3 files changed, 5 insertions(+), 3 deletions(-)
  delete mode 100644 file2
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
 Content-Transfer-Encoding: 8bit
@@ -75,6 +77,8 @@
  file1   |    3 +++
  2 files changed, 5 insertions(+), 0 deletions(-)
  create mode 100644 file1
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
 Content-Transfer-Encoding: 8bit
@@ -122,6 +126,8 @@
  file3   |    4 ++++
  3 files changed, 9 insertions(+), 0 deletions(-)
  create mode 100644 file3
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
 Content-Transfer-Encoding: 8bit
diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master^
index fe02587..d7490a9 100644
--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^
+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master^
@@ -19,6 +19,8 @@
  file2   |    3 ---
  3 files changed, 5 insertions(+), 3 deletions(-)
  delete mode 100644 file2
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
 Content-Transfer-Encoding: 8bit
@@ -75,6 +77,8 @@
  file1   |    3 +++
  2 files changed, 5 insertions(+), 0 deletions(-)
  create mode 100644 file1
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
 Content-Transfer-Encoding: 8bit
diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..side b/t/t4013/diff.format-patch_--attach_--stdout_initial..side
index 9ff828e..38f7902 100644
--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..side
+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..side
@@ -17,6 +17,8 @@
  file3   |    4 ++++
  3 files changed, 9 insertions(+), 0 deletions(-)
  create mode 100644 file3
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
 Content-Transfer-Encoding: 8bit
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master
index a8093be..fca5cce 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master
+++ b/t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master
@@ -19,6 +19,8 @@
  file2   |    3 ---
  3 files changed, 5 insertions(+), 3 deletions(-)
  delete mode 100644 file2
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
 Content-Transfer-Encoding: 8bit
@@ -75,6 +77,8 @@
  file1   |    3 +++
  2 files changed, 5 insertions(+), 0 deletions(-)
  create mode 100644 file1
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
 Content-Transfer-Encoding: 8bit
@@ -122,6 +126,8 @@
  file3   |    4 ++++
  3 files changed, 9 insertions(+), 0 deletions(-)
  create mode 100644 file3
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
 Content-Transfer-Encoding: 8bit
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master b/t/t4013/diff.format-patch_--inline_--stdout_initial..master
index aa110c0..6d6fac3 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master
+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master
@@ -19,6 +19,8 @@
  file2   |    3 ---
  3 files changed, 5 insertions(+), 3 deletions(-)
  delete mode 100644 file2
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
 Content-Transfer-Encoding: 8bit
@@ -75,6 +77,8 @@
  file1   |    3 +++
  2 files changed, 5 insertions(+), 0 deletions(-)
  create mode 100644 file1
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
 Content-Transfer-Encoding: 8bit
@@ -122,6 +126,8 @@
  file3   |    4 ++++
  3 files changed, 9 insertions(+), 0 deletions(-)
  create mode 100644 file3
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
 Content-Transfer-Encoding: 8bit
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^
index 95e9ea4..18a1110 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^
+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^
@@ -19,6 +19,8 @@
  file2   |    3 ---
  3 files changed, 5 insertions(+), 3 deletions(-)
  delete mode 100644 file2
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
 Content-Transfer-Encoding: 8bit
@@ -75,6 +77,8 @@
  file1   |    3 +++
  2 files changed, 5 insertions(+), 0 deletions(-)
  create mode 100644 file1
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
 Content-Transfer-Encoding: 8bit
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^
index b8e81e1..4f258b8 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^
+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..master^^
@@ -19,6 +19,8 @@
  file2   |    3 ---
  3 files changed, 5 insertions(+), 3 deletions(-)
  delete mode 100644 file2
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
 Content-Transfer-Encoding: 8bit
diff --git a/t/t4013/diff.format-patch_--inline_--stdout_initial..side b/t/t4013/diff.format-patch_--inline_--stdout_initial..side
index 86ae923..e86dce6 100644
--- a/t/t4013/diff.format-patch_--inline_--stdout_initial..side
+++ b/t/t4013/diff.format-patch_--inline_--stdout_initial..side
@@ -17,6 +17,8 @@
  file3   |    4 ++++
  3 files changed, 9 insertions(+), 0 deletions(-)
  create mode 100644 file3
+
+
 --------------g-i-t--v-e-r-s-i-o-n
 Content-Type: text/x-patch; name="c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a.diff"
 Content-Transfer-Encoding: 8bit
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index 3583e68..7fe853c 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -98,7 +98,7 @@
 	sed -e "/^$/q" patch2 > hdrs2 &&
 	grep "^To: R. E. Cipient <rcipient@example.com>$" hdrs2 &&
 	grep "^Cc: S. E. Cipient <scipient@example.com>$" hdrs2
-	
+
 '
 
 test_expect_success 'extra headers without newlines' '
@@ -109,7 +109,7 @@
 	sed -e "/^$/q" patch3 > hdrs3 &&
 	grep "^To: R. E. Cipient <rcipient@example.com>$" hdrs3 &&
 	grep "^Cc: S. E. Cipient <scipient@example.com>$" hdrs3
-	
+
 '
 
 test_expect_success 'extra headers with multiple To:s' '
@@ -170,7 +170,7 @@
 	git checkout side &&
 	git format-patch --cover-letter --thread -o patches/ master &&
 	FIRST_MID=$(grep "Message-Id:" patches/0000-* | sed "s/^[^<]*\(<[^>]*>\).*$/\1/") &&
-	for i in patches/0001-* patches/0002-* patches/0003-* 
+	for i in patches/0001-* patches/0002-* patches/0003-*
 	do
 	  grep "References: $FIRST_MID" $i &&
 	  grep "In-Reply-To: $FIRST_MID" $i || break
diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh
index ca0302f..b1cbd36 100755
--- a/t/t4015-diff-whitespace.sh
+++ b/t/t4015-diff-whitespace.sh
@@ -62,16 +62,16 @@
 
 git update-index x
 
-cat << EOF > x
+tr '_' ' ' << EOF > x
 	whitespace at beginning
 whitespace 	 change
 white space in the middle
-whitespace at end  
+whitespace at end__
 unchanged line
 CR at end
 EOF
 
-tr 'Q' '\015' << EOF > expect
+tr 'Q_' '\015 ' << EOF > expect
 diff --git a/x b/x
 index d99af23..8b32fb5 100644
 --- a/x
@@ -84,7 +84,7 @@
 +	whitespace at beginning
 +whitespace 	 change
 +white space in the middle
-+whitespace at end  
++whitespace at end__
  unchanged line
 -CR at endQ
 +CR at end
@@ -144,7 +144,7 @@
 test_expect_success 'check with trailing whitespace' '
 
 	echo "foo(); " > x &&
-	! git diff --check
+	test_must_fail git diff --check
 
 '
 
@@ -152,7 +152,7 @@
 
 	# indent has space followed by hard tab
 	echo " 	foo();" > x &&
-	! git diff --check
+	test_must_fail git diff --check
 
 '
 
@@ -181,7 +181,7 @@
 
 	echo "foo(); " > x &&
 	git add x &&
-	! git diff --cached --check
+	test_must_fail git diff --cached --check
 
 '
 
@@ -190,7 +190,7 @@
 	# indent has space followed by hard tab
 	echo " 	foo();" > x &&
 	git add x &&
-	! git diff --cached --check
+	test_must_fail git diff --cached --check
 
 '
 
@@ -206,7 +206,7 @@
 
 	echo "foo(); " > x &&
 	git add x &&
-	! git diff-index --check HEAD
+	test_must_fail git diff-index --check HEAD
 
 '
 
@@ -215,7 +215,7 @@
 	# indent has space followed by hard tab
 	echo " 	foo();" > x &&
 	git add x &&
-	! git diff-index --check HEAD
+	test_must_fail git diff-index --check HEAD
 
 '
 
@@ -231,7 +231,7 @@
 
 	echo "foo(); " > x &&
 	git add x &&
-	! git diff-index --cached --check HEAD
+	test_must_fail git diff-index --cached --check HEAD
 
 '
 
@@ -240,7 +240,7 @@
 	# indent has space followed by hard tab
 	echo " 	foo();" > x &&
 	git add x &&
-	! git diff-index --cached --check HEAD
+	test_must_fail git diff-index --cached --check HEAD
 
 '
 
@@ -256,7 +256,7 @@
 
 	echo "foo(); " > x &&
 	git commit -m "another commit" x &&
-	! git diff-tree --check HEAD^ HEAD
+	test_must_fail git diff-tree --check HEAD^ HEAD
 
 '
 
@@ -265,7 +265,7 @@
 	# indent has space followed by hard tab
 	echo " 	foo();" > x &&
 	git commit -m "yet another" x &&
-	! git diff-tree --check HEAD^ HEAD
+	test_must_fail git diff-tree --check HEAD^ HEAD
 
 '
 
@@ -281,7 +281,7 @@
 
 	git config core.whitespace "trailing-space" &&
 	echo "foo ();   " > x &&
-	! git diff --check
+	test_must_fail git diff --check
 
 '
 
@@ -299,7 +299,7 @@
 	# indent contains space followed by HT
 	git config core.whitespace "space-before-tab" &&
 	echo " 	foo ();   " > x &&
-	! git diff --check
+	test_must_fail git diff --check
 
 '
 
@@ -315,7 +315,7 @@
 
 	git config core.whitespace "indent-with-non-tab" &&
 	echo "        foo ();" > x &&
-	! git diff --check
+	test_must_fail git diff --check
 
 '
 
@@ -323,7 +323,7 @@
 
 	git config core.whitespace "indent-with-non-tab" &&
 	echo "	                foo ();" > x &&
-	! git diff --check
+	test_must_fail git diff --check
 
 '
 
@@ -335,4 +335,37 @@
 
 '
 
+test_expect_success 'checkdiff detects trailing blank lines' '
+	echo "foo();" >x &&
+	echo "" >>x &&
+	git diff --check | grep "ends with blank"
+'
+
+test_expect_success 'checkdiff allows new blank lines' '
+	git checkout x &&
+	mv x y &&
+	(
+		echo "/* This is new */" &&
+		echo "" &&
+		cat y
+	) >x &&
+	git diff --check
+'
+
+test_expect_success 'combined diff with autocrlf conversion' '
+
+	git reset --hard &&
+	echo >x hello &&
+	git commit -m "one side" x &&
+	git checkout HEAD^ &&
+	echo >x goodbye &&
+	git commit -m "the other side" x &&
+	git config core.autocrlf true &&
+	test_must_fail git merge master &&
+
+	git diff | sed -e "1,/^@@@/d" >actual &&
+	! grep "^-" actual
+
+'
+
 test_done
diff --git a/t/t4016-diff-quote.sh b/t/t4016-diff-quote.sh
index 0950250..55eb5f8 100755
--- a/t/t4016-diff-quote.sh
+++ b/t/t4016-diff-quote.sh
@@ -13,8 +13,8 @@
 P2='pathname with SP'
 P3='pathname
 with LF'
-: >"$P1" 2>&1 && test -f "$P1" && rm -f "$P1" || {
-	echo >&2 'Filesystem does not support tabs in names'
+: 2>/dev/null >"$P1" && test -f "$P1" && rm -f "$P1" || {
+	say 'Your filesystem does not allow tabs in filenames, test skipped.'
 	test_done
 }
 
@@ -53,13 +53,13 @@
 '
 
 cat >expect <<\EOF
- pathname.1 => "Rpathname\twith HT.0"            |    0 
- pathname.3 => "Rpathname\nwith LF.0"            |    0 
- "pathname\twith HT.3" => "Rpathname\nwith LF.1" |    0 
- pathname.2 => Rpathname with SP.0               |    0 
- "pathname\twith HT.2" => Rpathname with SP.1    |    0 
- pathname.0 => Rpathname.0                       |    0 
- "pathname\twith HT.0" => Rpathname.1            |    0 
+ pathname.1 => "Rpathname\twith HT.0"            |    0
+ pathname.3 => "Rpathname\nwith LF.0"            |    0
+ "pathname\twith HT.3" => "Rpathname\nwith LF.1" |    0
+ pathname.2 => Rpathname with SP.0               |    0
+ "pathname\twith HT.2" => Rpathname with SP.1    |    0
+ pathname.0 => Rpathname.0                       |    0
+ "pathname\twith HT.0" => Rpathname.1            |    0
  7 files changed, 0 insertions(+), 0 deletions(-)
 EOF
 test_expect_success 'git diff --stat -M HEAD' '
diff --git a/t/t4017-diff-retval.sh b/t/t4017-diff-retval.sh
index 0d0fb87..60dd201 100755
--- a/t/t4017-diff-retval.sh
+++ b/t/t4017-diff-retval.sh
@@ -113,4 +113,18 @@
 
 '
 
+test_expect_success 'check detects leftover conflict markers' '
+	git reset --hard &&
+	git checkout HEAD^ &&
+	echo binary >>b &&
+	git commit -m "side" b &&
+	test_must_fail git merge master &&
+	git add b && (
+		git --no-pager diff --cached --check >test.out
+		test $? = 2
+	) &&
+	test 3 = $(grep "conflict marker" test.out | wc -l) &&
+	git reset --hard
+'
+
 test_done
diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh
index 6d3ef6c..398bf4b 100755
--- a/t/t4018-diff-funcname.sh
+++ b/t/t4018-diff-funcname.sh
@@ -32,7 +32,18 @@
 
 sed 's/beer\\/beer,\\/' < Beer.java > Beer-correct.java
 
+builtin_patterns="bibtex java pascal ruby tex"
+for p in $builtin_patterns
+do
+	test_expect_success "builtin $p pattern compiles" '
+		echo "*.java diff=$p" > .gitattributes &&
+		! ( git diff --no-index Beer.java Beer-correct.java 2>&1 |
+			grep "fatal" > /dev/null )
+	'
+done
+
 test_expect_success 'default behaviour' '
+	rm -f .gitattributes &&
 	git diff --no-index Beer.java Beer-correct.java |
 	grep "^@@.*@@ public class Beer"
 '
@@ -54,7 +65,20 @@
 
 test_expect_success 'last regexp must not be negated' '
 	git config diff.java.funcname "!static" &&
-	! git diff --no-index Beer.java Beer-correct.java
+	git diff --no-index Beer.java Beer-correct.java 2>&1 |
+	grep "fatal: Last expression must not be negated:"
+'
+
+test_expect_success 'pattern which matches to end of line' '
+	git config diff.java.funcname "Beer$" &&
+	git diff --no-index Beer.java Beer-correct.java |
+	grep "^@@.*@@ Beer"
+'
+
+test_expect_success 'alternation in pattern' '
+	git config diff.java.xfuncname "^[ 	]*((public|static).*)$" &&
+	git diff --no-index Beer.java Beer-correct.java |
+	grep "^@@.*@@ public static void main("
 '
 
 test_done
diff --git a/t/t4019-diff-wserror.sh b/t/t4019-diff-wserror.sh
index 0d9cbb6..84a1fe3 100755
--- a/t/t4019-diff-wserror.sh
+++ b/t/t4019-diff-wserror.sh
@@ -13,7 +13,8 @@
 	echo " 	HT and SP indent" >>F &&
 	echo "With trailing SP " >>F &&
 	echo "Carriage ReturnQ" | tr Q "\015" >>F &&
-	echo "No problem" >>F
+	echo "No problem" >>F &&
+	echo >>F
 
 '
 
@@ -160,4 +161,33 @@
 
 '
 
+test_expect_success 'trailing empty lines (1)' '
+
+	rm -f .gitattributes &&
+	test_must_fail git diff --check >output &&
+	grep "ends with blank lines." output &&
+	grep "trailing whitespace" output
+
+'
+
+test_expect_success 'trailing empty lines (2)' '
+
+	echo "F -whitespace" >.gitattributes &&
+	git diff --check >output &&
+	! test -s output
+
+'
+
+test_expect_success 'do not color trailing cr in context' '
+	git config --unset core.whitespace
+	rm -f .gitattributes &&
+	echo AAAQ | tr Q "\015" >G &&
+	git add G &&
+	echo BBBQ | tr Q "\015" >>G
+	git diff --color G | tr "\015" Q >output &&
+	grep "BBB.*${blue_grep}Q" output &&
+	grep "AAA.*\[mQ" output
+
+'
+
 test_done
diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh
index 637b4e1..22ef7d4 100755
--- a/t/t4020-diff-external.sh
+++ b/t/t4020-diff-external.sh
@@ -43,6 +43,13 @@
 
 '
 
+test_expect_success 'GIT_EXTERNAL_DIFF environment and --no-ext-diff' '
+
+	GIT_EXTERNAL_DIFF=echo git diff --no-ext-diff |
+	grep "^diff --git a/file b/file"
+
+'
+
 test_expect_success 'diff attribute' '
 
 	git config diff.parrot.command echo &&
@@ -68,6 +75,13 @@
 
 '
 
+test_expect_success 'diff attribute and --no-ext-diff' '
+
+	git diff --no-ext-diff |
+	grep "^diff --git a/file b/file"
+
+'
+
 test_expect_success 'diff attribute' '
 
 	git config --unset diff.parrot.command &&
@@ -94,6 +108,13 @@
 
 '
 
+test_expect_success 'diff attribute and --no-ext-diff' '
+
+	git diff --no-ext-diff |
+	grep "^diff --git a/file b/file"
+
+'
+
 test_expect_success 'no diff with -diff' '
 	echo >.gitattributes "file -diff" &&
 	git diff | grep Binary
diff --git a/t/t4100-apply-stat.sh b/t/t4100-apply-stat.sh
index 8073a5a..e0c6774 100755
--- a/t/t4100-apply-stat.sh
+++ b/t/t4100-apply-stat.sh
@@ -3,44 +3,38 @@
 # Copyright (c) 2005 Junio C Hamano
 #
 
-test_description='git apply --stat --summary test.
+test_description='git apply --stat --summary test, with --recount
 
 '
 . ./test-lib.sh
 
-test_expect_success \
-    'rename' \
-    'git apply --stat --summary <../t4100/t-apply-1.patch >current &&
-    test_cmp ../t4100/t-apply-1.expect current'
+UNC='s/^\(@@ -[1-9][0-9]*\),[0-9]* \(+[1-9][0-9]*\),[0-9]* @@/\1,999 \2,999 @@/'
 
-test_expect_success \
-    'copy' \
-    'git apply --stat --summary <../t4100/t-apply-2.patch >current &&
-    test_cmp ../t4100/t-apply-2.expect current'
+num=0
+while read title
+do
+	num=$(( $num + 1 ))
+	test_expect_success "$title" '
+		git apply --stat --summary \
+			<"$TEST_DIRECTORY/t4100/t-apply-$num.patch" >current &&
+		test_cmp ../t4100/t-apply-$num.expect current
+	'
 
-test_expect_success \
-    'rewrite' \
-    'git apply --stat --summary <../t4100/t-apply-3.patch >current &&
-    test_cmp ../t4100/t-apply-3.expect current'
-
-test_expect_success \
-    'mode' \
-    'git apply --stat --summary <../t4100/t-apply-4.patch >current &&
-    test_cmp ../t4100/t-apply-4.expect current'
-
-test_expect_success \
-    'non git' \
-    'git apply --stat --summary <../t4100/t-apply-5.patch >current &&
-    test_cmp ../t4100/t-apply-5.expect current'
-
-test_expect_success \
-    'non git' \
-    'git apply --stat --summary <../t4100/t-apply-6.patch >current &&
-    test_cmp ../t4100/t-apply-6.expect current'
-
-test_expect_success \
-    'non git' \
-    'git apply --stat --summary <../t4100/t-apply-7.patch >current &&
-    test_cmp ../t4100/t-apply-7.expect current'
+	test_expect_success "$title with recount" '
+		sed -e "$UNC" <"$TEST_DIRECTORY/t4100/t-apply-$num.patch" |
+		git apply --recount --stat --summary >current &&
+		test_cmp ../t4100/t-apply-$num.expect current
+	'
+done <<\EOF
+rename
+copy
+rewrite
+mode
+non git (1)
+non git (2)
+non git (3)
+incomplete (1)
+incomplete (2)
+EOF
 
 test_done
diff --git a/t/t4100/t-apply-8.expect b/t/t4100/t-apply-8.expect
new file mode 100644
index 0000000..eef7f2e
--- /dev/null
+++ b/t/t4100/t-apply-8.expect
@@ -0,0 +1,2 @@
+ t/t4100-apply-stat.sh |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/t/t4100/t-apply-8.patch b/t/t4100/t-apply-8.patch
new file mode 100644
index 0000000..5ca13e6
--- /dev/null
+++ b/t/t4100/t-apply-8.patch
@@ -0,0 +1,11 @@
+diff --git a/t/t4100-apply-stat.sh b/t/t4100-apply-stat.sh
+index be837bb..0798c64 100755
+--- a/t/t4100-apply-stat.sh
++++ b/t/t4100-apply-stat.sh
+@@ -35,4 +35,4 @@ non git (2)
+ non git (3)
+ EOF
+ 
+-test_done
++test_done
+\ No newline at end of file
diff --git a/t/t4100/t-apply-9.expect b/t/t4100/t-apply-9.expect
new file mode 100644
index 0000000..eef7f2e
--- /dev/null
+++ b/t/t4100/t-apply-9.expect
@@ -0,0 +1,2 @@
+ t/t4100-apply-stat.sh |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/t/t4100/t-apply-9.patch b/t/t4100/t-apply-9.patch
new file mode 100644
index 0000000..875d57d
--- /dev/null
+++ b/t/t4100/t-apply-9.patch
@@ -0,0 +1,11 @@
+diff --git a/t/t4100-apply-stat.sh b/t/t4100-apply-stat.sh
+index 0798c64..be837bb 100755
+--- a/t/t4100-apply-stat.sh
++++ b/t/t4100-apply-stat.sh
+@@ -35,4 +35,4 @@ non git (2)
+ non git (3)
+ EOF
+ 
+-test_done
+\ No newline at end of file
++test_done
diff --git a/t/t4103-apply-binary.sh b/t/t4103-apply-binary.sh
index 1b58233..ad4cc1a 100755
--- a/t/t4103-apply-binary.sh
+++ b/t/t4103-apply-binary.sh
@@ -21,16 +21,16 @@
 cat file1 >file4
 
 git update-index --add --remove file1 file2 file4
-git-commit -m 'Initial Version' 2>/dev/null
+git commit -m 'Initial Version' 2>/dev/null
 
-git-checkout -b binary
+git checkout -b binary
 perl -pe 'y/x/\000/' <file1 >file3
 cat file3 >file4
 git add file2
 perl -pe 'y/\000/v/' <file3 >file1
 rm -f file2
 git update-index --add --remove file1 file2 file3 file4
-git-commit -m 'Second Version'
+git commit -m 'Second Version'
 
 git diff-tree -p master binary >B.diff
 git diff-tree -p -C master binary >C.diff
@@ -39,64 +39,64 @@
 git diff-tree -p --binary -C master binary >CF.diff
 
 test_expect_success 'stat binary diff -- should not fail.' \
-	'git-checkout master
+	'git checkout master
 	 git apply --stat --summary B.diff'
 
 test_expect_success 'stat binary diff (copy) -- should not fail.' \
-	'git-checkout master
+	'git checkout master
 	 git apply --stat --summary C.diff'
 
 test_expect_success 'check binary diff -- should fail.' \
-	'git-checkout master &&
-	 ! git apply --check B.diff'
+	'git checkout master &&
+	 test_must_fail git apply --check B.diff'
 
 test_expect_success 'check binary diff (copy) -- should fail.' \
-	'git-checkout master &&
-	 ! git apply --check C.diff'
+	'git checkout master &&
+	 test_must_fail git apply --check C.diff'
 
 test_expect_success \
 	'check incomplete binary diff with replacement -- should fail.' '
-	git-checkout master &&
-	! git apply --check --allow-binary-replacement B.diff
+	git checkout master &&
+	test_must_fail git apply --check --allow-binary-replacement B.diff
 '
 
 test_expect_success \
     'check incomplete binary diff with replacement (copy) -- should fail.' '
-	 git-checkout master &&
-	 ! git apply --check --allow-binary-replacement C.diff
+	 git checkout master &&
+	 test_must_fail git apply --check --allow-binary-replacement C.diff
 '
 
 test_expect_success 'check binary diff with replacement.' \
-	'git-checkout master
+	'git checkout master
 	 git apply --check --allow-binary-replacement BF.diff'
 
 test_expect_success 'check binary diff with replacement (copy).' \
-	'git-checkout master
+	'git checkout master
 	 git apply --check --allow-binary-replacement CF.diff'
 
 # Now we start applying them.
 
 do_reset () {
 	rm -f file? &&
-	git-reset --hard &&
-	git-checkout -f master
+	git reset --hard &&
+	git checkout -f master
 }
 
 test_expect_success 'apply binary diff -- should fail.' \
 	'do_reset &&
-	 ! git apply B.diff'
+	 test_must_fail git apply B.diff'
 
 test_expect_success 'apply binary diff -- should fail.' \
 	'do_reset &&
-	 ! git apply --index B.diff'
+	 test_must_fail git apply --index B.diff'
 
 test_expect_success 'apply binary diff (copy) -- should fail.' \
 	'do_reset &&
-	 ! git apply C.diff'
+	 test_must_fail git apply C.diff'
 
 test_expect_success 'apply binary diff (copy) -- should fail.' \
 	'do_reset &&
-	 ! git apply --index C.diff'
+	 test_must_fail git apply --index C.diff'
 
 test_expect_success 'apply binary diff without replacement.' \
 	'do_reset &&
diff --git a/t/t4104-apply-boundary.sh b/t/t4104-apply-boundary.sh
index e7e2913..0e3ce36 100755
--- a/t/t4104-apply-boundary.sh
+++ b/t/t4104-apply-boundary.sh
@@ -27,6 +27,15 @@
 	git diff victim >add-a-patch.with &&
 	git diff --unified=0 >add-a-patch.without &&
 
+	: insert at line two
+	for i in b a '"$L"' y
+	do
+		echo $i
+	done >victim &&
+	cat victim >insert-a-expect &&
+	git diff victim >insert-a-patch.with &&
+	git diff --unified=0 >insert-a-patch.without &&
+
 	: modify at the head
 	for i in a '"$L"' y
 	do
@@ -55,7 +64,7 @@
 	git diff --unified=0 >add-z-patch.without &&
 
 	: modify at the tail
-	for i in a '"$L"' y
+	for i in b '"$L"' z
 	do
 		echo $i
 	done >victim &&
@@ -81,7 +90,7 @@
 	with) u= ;;
 	without) u='--unidiff-zero ' ;;
 	esac
-	for kind in add-a add-z mod-a mod-z del-a del-z
+	for kind in add-a add-z insert-a mod-a mod-z del-a del-z
 	do
 		test_expect_success "apply $kind-patch $with context" '
 			cat original >victim &&
@@ -95,7 +104,7 @@
 	done
 done
 
-for kind in add-a add-z mod-a mod-z del-a del-z
+for kind in add-a add-z insert-a mod-a mod-z del-a del-z
 do
 	rm -f $kind-ng.without
 	sed	-e "s/^diff --git /diff /" \
diff --git a/t/t4109-apply-multifrag.sh b/t/t4109-apply-multifrag.sh
index bd40a21..ac58083 100755
--- a/t/t4109-apply-multifrag.sh
+++ b/t/t4109-apply-multifrag.sh
@@ -4,173 +4,32 @@
 # Copyright (c) 2005 Robert Fitzsimons
 #
 
-test_description='git apply test patches with multiple fragments.
+test_description='git apply test patches with multiple fragments.'
 
-'
 . ./test-lib.sh
 
-# setup
+cp "$TEST_DIRECTORY/t4109/patch1.patch" .
+cp "$TEST_DIRECTORY/t4109/patch2.patch" .
+cp "$TEST_DIRECTORY/t4109/patch3.patch" .
+cp "$TEST_DIRECTORY/t4109/patch4.patch" .
 
-cat > patch1.patch <<\EOF
-diff --git a/main.c b/main.c
-new file mode 100644
---- /dev/null
-+++ b/main.c
-@@ -0,0 +1,23 @@
-+#include <stdio.h>
-+
-+int func(int num);
-+void print_int(int num);
-+
-+int main() {
-+	int i;
-+
-+	for (i = 0; i < 10; i++) {
-+		print_int(func(i));
-+	}
-+
-+	return 0;
-+}
-+
-+int func(int num) {
-+	return num * num;
-+}
-+
-+void print_int(int num) {
-+	printf("%d", num);
-+}
-+
-EOF
-cat > patch2.patch <<\EOF
-diff --git a/main.c b/main.c
---- a/main.c
-+++ b/main.c
-@@ -1,7 +1,9 @@
-+#include <stdlib.h>
- #include <stdio.h>
- 
- int func(int num);
- void print_int(int num);
-+void print_ln();
- 
- int main() {
- 	int i;
-@@ -10,6 +12,8 @@
- 		print_int(func(i));
- 	}
- 
-+	print_ln();
-+
- 	return 0;
- }
- 
-@@ -21,3 +25,7 @@
- 	printf("%d", num);
- }
- 
-+void print_ln() {
-+	printf("\n");
-+}
-+
-EOF
-cat > patch3.patch <<\EOF
-diff --git a/main.c b/main.c
---- a/main.c
-+++ b/main.c
-@@ -1,9 +1,7 @@
--#include <stdlib.h>
- #include <stdio.h>
- 
- int func(int num);
- void print_int(int num);
--void print_ln();
- 
- int main() {
- 	int i;
-@@ -12,8 +10,6 @@
- 		print_int(func(i));
- 	}
- 
--	print_ln();
--
- 	return 0;
- }
- 
-@@ -25,7 +21,3 @@
- 	printf("%d", num);
- }
- 
--void print_ln() {
--	printf("\n");
--}
--
-EOF
-cat > patch4.patch <<\EOF
-diff --git a/main.c b/main.c
---- a/main.c
-+++ b/main.c
-@@ -1,13 +1,14 @@
- #include <stdio.h>
- 
- int func(int num);
--void print_int(int num);
-+int func2(int num);
- 
- int main() {
- 	int i;
- 
- 	for (i = 0; i < 10; i++) {
--		print_int(func(i));
-+		printf("%d", func(i));
-+		printf("%d", func3(i));
- 	}
- 
- 	return 0;
-@@ -17,7 +18,7 @@
- 	return num * num;
- }
- 
--void print_int(int num) {
--	printf("%d", num);
-+int func2(int num) {
-+	return num * num * num;
- }
- 
-EOF
+test_expect_success 'git apply (1)' '
+	git apply patch1.patch patch2.patch &&
+	test_cmp "$TEST_DIRECTORY/t4109/expect-1" main.c
+'
+rm -f main.c
 
-test_expect_success "S = git apply (1)" \
-    'git apply patch1.patch patch2.patch'
+test_expect_success 'git apply (2)' '
+	git apply patch1.patch patch2.patch patch3.patch &&
+	test_cmp "$TEST_DIRECTORY/t4109/expect-2" main.c
+'
+rm -f main.c
+
+test_expect_success 'git apply (3)' '
+	git apply patch1.patch patch4.patch &&
+	test_cmp "$TEST_DIRECTORY/t4109/expect-3" main.c
+'
 mv main.c main.c.git
 
-test_expect_success "S = patch (1)" \
-    'cat patch1.patch patch2.patch | patch -p1'
-
-test_expect_success "S = cmp (1)" \
-    'cmp main.c.git main.c'
-
-rm -f main.c main.c.git
-
-test_expect_success "S = git apply (2)" \
-    'git apply patch1.patch patch2.patch patch3.patch'
-mv main.c main.c.git
-
-test_expect_success "S = patch (2)" \
-    'cat patch1.patch patch2.patch patch3.patch | patch -p1'
-
-test_expect_success "S = cmp (2)" \
-    'cmp main.c.git main.c'
-
-rm -f main.c main.c.git
-
-test_expect_success "S = git apply (3)" \
-    'git apply patch1.patch patch4.patch'
-mv main.c main.c.git
-
-test_expect_success "S = patch (3)" \
-    'cat patch1.patch patch4.patch | patch -p1'
-
-test_expect_success "S = cmp (3)" \
-    'cmp main.c.git main.c'
-
 test_done
 
diff --git a/t/t4109/expect-1 b/t/t4109/expect-1
new file mode 100644
index 0000000..1db5ff1
--- /dev/null
+++ b/t/t4109/expect-1
@@ -0,0 +1,31 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+int func(int num);
+void print_int(int num);
+void print_ln();
+
+int main() {
+	int i;
+
+	for (i = 0; i < 10; i++) {
+		print_int(func(i));
+	}
+
+	print_ln();
+
+	return 0;
+}
+
+int func(int num) {
+	return num * num;
+}
+
+void print_int(int num) {
+	printf("%d", num);
+}
+
+void print_ln() {
+	printf("\n");
+}
+
diff --git a/t/t4109/expect-2 b/t/t4109/expect-2
new file mode 100644
index 0000000..bc52924
--- /dev/null
+++ b/t/t4109/expect-2
@@ -0,0 +1,23 @@
+#include <stdio.h>
+
+int func(int num);
+void print_int(int num);
+
+int main() {
+	int i;
+
+	for (i = 0; i < 10; i++) {
+		print_int(func(i));
+	}
+
+	return 0;
+}
+
+int func(int num) {
+	return num * num;
+}
+
+void print_int(int num) {
+	printf("%d", num);
+}
+
diff --git a/t/t4109/expect-3 b/t/t4109/expect-3
new file mode 100644
index 0000000..cd2a475
--- /dev/null
+++ b/t/t4109/expect-3
@@ -0,0 +1,24 @@
+#include <stdio.h>
+
+int func(int num);
+int func2(int num);
+
+int main() {
+	int i;
+
+	for (i = 0; i < 10; i++) {
+		printf("%d", func(i));
+		printf("%d", func3(i));
+	}
+
+	return 0;
+}
+
+int func(int num) {
+	return num * num;
+}
+
+int func2(int num) {
+	return num * num * num;
+}
+
diff --git a/t/t4109/patch1.patch b/t/t4109/patch1.patch
new file mode 100644
index 0000000..1d411fc
--- /dev/null
+++ b/t/t4109/patch1.patch
@@ -0,0 +1,28 @@
+diff --git a/main.c b/main.c
+new file mode 100644
+--- /dev/null
++++ b/main.c
+@@ -0,0 +1,23 @@
++#include <stdio.h>
++
++int func(int num);
++void print_int(int num);
++
++int main() {
++	int i;
++
++	for (i = 0; i < 10; i++) {
++		print_int(func(i));
++	}
++
++	return 0;
++}
++
++int func(int num) {
++	return num * num;
++}
++
++void print_int(int num) {
++	printf("%d", num);
++}
++
diff --git a/t/t4109/patch2.patch b/t/t4109/patch2.patch
new file mode 100644
index 0000000..8c6b06d
--- /dev/null
+++ b/t/t4109/patch2.patch
@@ -0,0 +1,30 @@
+diff --git a/main.c b/main.c
+--- a/main.c
++++ b/main.c
+@@ -1,7 +1,9 @@
++#include <stdlib.h>
+ #include <stdio.h>
+ 
+ int func(int num);
+ void print_int(int num);
++void print_ln();
+ 
+ int main() {
+ 	int i;
+@@ -10,6 +12,8 @@
+ 		print_int(func(i));
+ 	}
+ 
++	print_ln();
++
+ 	return 0;
+ }
+ 
+@@ -21,3 +25,7 @@
+ 	printf("%d", num);
+ }
+ 
++void print_ln() {
++	printf("\n");
++}
++
diff --git a/t/t4109/patch3.patch b/t/t4109/patch3.patch
new file mode 100644
index 0000000..d696c55
--- /dev/null
+++ b/t/t4109/patch3.patch
@@ -0,0 +1,31 @@
+cat > patch3.patch <<\EOF
+diff --git a/main.c b/main.c
+--- a/main.c
++++ b/main.c
+@@ -1,9 +1,7 @@
+-#include <stdlib.h>
+ #include <stdio.h>
+ 
+ int func(int num);
+ void print_int(int num);
+-void print_ln();
+ 
+ int main() {
+ 	int i;
+@@ -12,8 +10,6 @@
+ 		print_int(func(i));
+ 	}
+ 
+-	print_ln();
+-
+ 	return 0;
+ }
+ 
+@@ -25,7 +21,3 @@
+ 	printf("%d", num);
+ }
+ 
+-void print_ln() {
+-	printf("\n");
+-}
+-
diff --git a/t/t4109/patch4.patch b/t/t4109/patch4.patch
new file mode 100644
index 0000000..4b08590
--- /dev/null
+++ b/t/t4109/patch4.patch
@@ -0,0 +1,30 @@
+diff --git a/main.c b/main.c
+--- a/main.c
++++ b/main.c
+@@ -1,13 +1,14 @@
+ #include <stdio.h>
+ 
+ int func(int num);
+-void print_int(int num);
++int func2(int num);
+ 
+ int main() {
+ 	int i;
+ 
+ 	for (i = 0; i < 10; i++) {
+-		print_int(func(i));
++		printf("%d", func(i));
++		printf("%d", func3(i));
+ 	}
+ 
+ 	return 0;
+@@ -17,7 +18,7 @@
+ 	return num * num;
+ }
+ 
+-void print_int(int num) {
+-	printf("%d", num);
++int func2(int num) {
++	return num * num * num;
+ }
+ 
diff --git a/t/t4110-apply-scan.sh b/t/t4110-apply-scan.sh
index db60652..09f5811 100755
--- a/t/t4110-apply-scan.sh
+++ b/t/t4110-apply-scan.sh
@@ -9,92 +9,14 @@
 '
 . ./test-lib.sh
 
-# setup
-
-cat > patch1.patch <<\EOF
-diff --git a/new.txt b/new.txt
-new file mode 100644
---- /dev/null
-+++ b/new.txt
-@@ -0,0 +1,12 @@
-+a1
-+a11
-+a111
-+a1111
-+b1
-+b11
-+b111
-+b1111
-+c1
-+c11
-+c111
-+c1111
-EOF
-cat > patch2.patch <<\EOF
-diff --git a/new.txt b/new.txt
---- a/new.txt
-+++ b/new.txt
-@@ -1,7 +1,3 @@
--a1
--a11
--a111
--a1111
- b1
- b11
- b111
-EOF
-cat > patch3.patch <<\EOF
-diff --git a/new.txt b/new.txt
---- a/new.txt
-+++ b/new.txt
-@@ -6,6 +6,10 @@
- b11
- b111
- b1111
-+b2
-+b22
-+b222
-+b2222
- c1
- c11
- c111
-EOF
-cat > patch4.patch <<\EOF
-diff --git a/new.txt b/new.txt
---- a/new.txt
-+++ b/new.txt
-@@ -1,3 +1,7 @@
-+a1
-+a11
-+a111
-+a1111
- b1
- b11
- b111
-EOF
-cat > patch5.patch <<\EOF
-diff --git a/new.txt b/new.txt
---- a/new.txt
-+++ b/new.txt
-@@ -10,3 +10,7 @@
- c11
- c111
- c1111
-+c2
-+c22
-+c222
-+c2222
-EOF
-
-test_expect_success "S = git apply scan" \
-    'git apply patch1.patch patch2.patch patch3.patch patch4.patch patch5.patch'
-mv new.txt apply.txt
-
-test_expect_success "S = patch scan" \
-    'cat patch1.patch patch2.patch patch3.patch patch4.patch patch5.patch | patch'
-mv new.txt patch.txt
-
-test_expect_success "S = cmp" \
-    'cmp apply.txt patch.txt'
+test_expect_success 'git apply scan' '
+	git apply \
+		"$TEST_DIRECTORY/t4110/patch1.patch" \
+		"$TEST_DIRECTORY/t4110/patch2.patch" \
+		"$TEST_DIRECTORY/t4110/patch3.patch" \
+		"$TEST_DIRECTORY/t4110/patch4.patch" \
+		"$TEST_DIRECTORY/t4110/patch5.patch" &&
+	test_cmp new.txt "$TEST_DIRECTORY/t4110/expect"
+'
 
 test_done
diff --git a/t/t4110/expect b/t/t4110/expect
new file mode 100644
index 0000000..87cc493
--- /dev/null
+++ b/t/t4110/expect
@@ -0,0 +1,20 @@
+a1
+a11
+a111
+a1111
+b1
+b11
+b111
+b1111
+b2
+b22
+b222
+b2222
+c1
+c11
+c111
+c1111
+c2
+c22
+c222
+c2222
diff --git a/t/t4110/patch1.patch b/t/t4110/patch1.patch
new file mode 100644
index 0000000..5613908
--- /dev/null
+++ b/t/t4110/patch1.patch
@@ -0,0 +1,17 @@
+diff --git a/new.txt b/new.txt
+new file mode 100644
+--- /dev/null
++++ b/new.txt
+@@ -0,0 +1,12 @@
++a1
++a11
++a111
++a1111
++b1
++b11
++b111
++b1111
++c1
++c11
++c111
++c1111
diff --git a/t/t4110/patch2.patch b/t/t4110/patch2.patch
new file mode 100644
index 0000000..0497424
--- /dev/null
+++ b/t/t4110/patch2.patch
@@ -0,0 +1,11 @@
+diff --git a/new.txt b/new.txt
+--- a/new.txt
++++ b/new.txt
+@@ -1,7 +1,3 @@
+-a1
+-a11
+-a111
+-a1111
+ b1
+ b11
+ b111
diff --git a/t/t4110/patch3.patch b/t/t4110/patch3.patch
new file mode 100644
index 0000000..26bd442
--- /dev/null
+++ b/t/t4110/patch3.patch
@@ -0,0 +1,14 @@
+diff --git a/new.txt b/new.txt
+--- a/new.txt
++++ b/new.txt
+@@ -6,6 +6,10 @@
+ b11
+ b111
+ b1111
++b2
++b22
++b222
++b2222
+ c1
+ c11
+ c111
diff --git a/t/t4110/patch4.patch b/t/t4110/patch4.patch
new file mode 100644
index 0000000..9ffb9c2
--- /dev/null
+++ b/t/t4110/patch4.patch
@@ -0,0 +1,11 @@
+diff --git a/new.txt b/new.txt
+--- a/new.txt
++++ b/new.txt
+@@ -1,3 +1,7 @@
++a1
++a11
++a111
++a1111
+ b1
+ b11
+ b111
diff --git a/t/t4110/patch5.patch b/t/t4110/patch5.patch
new file mode 100644
index 0000000..c5ac691
--- /dev/null
+++ b/t/t4110/patch5.patch
@@ -0,0 +1,11 @@
+diff --git a/new.txt b/new.txt
+--- a/new.txt
++++ b/new.txt
+@@ -10,3 +10,7 @@
+ c11
+ c111
+ c1111
++c2
++c22
++c222
++c2222
diff --git a/t/t4112-apply-renames.sh b/t/t4112-apply-renames.sh
index 70a1859..f9ad183 100755
--- a/t/t4112-apply-renames.sh
+++ b/t/t4112-apply-renames.sh
@@ -36,6 +36,9 @@
 
 #endif /* _SETJMP_H */
 EOF
+cat >klibc/README <<\EOF
+This is a simple readme file.
+EOF
 
 cat >patch <<\EOF
 diff --git a/klibc/arch/x86_64/include/klibc/archsetjmp.h b/include/arch/cris/klibc/archsetjmp.h
@@ -113,6 +116,23 @@
 
 -#endif /* _SETJMP_H */
 +#endif /* _KLIBC_ARCHSETJMP_H */
+diff --git a/klibc/README b/klibc/README
+--- a/klibc/README
++++ b/klibc/README
+@@ -1,1 +1,4 @@
+ This is a simple readme file.
++And we add a few
++lines at the
++end of it.
+diff --git a/klibc/README b/klibc/arch/README
+copy from klibc/README
+copy to klibc/arch/README
+--- a/klibc/README
++++ b/klibc/arch/README
+@@ -1,1 +1,3 @@
+ This is a simple readme file.
++And we copy it to one level down, and
++add a few lines at the end of it.
 EOF
 
 find klibc -type f -print | xargs git update-index --add --
diff --git a/t/t4113-apply-ending.sh b/t/t4113-apply-ending.sh
index d741039..66fa515 100755
--- a/t/t4113-apply-ending.sh
+++ b/t/t4113-apply-ending.sh
@@ -30,7 +30,7 @@
 # test
 
 test_expect_success 'apply at the end' \
-    '! git apply --index test-patch'
+    'test_must_fail git apply --index test-patch'
 
 cat >test-patch <<\EOF
 diff a/file b/file
@@ -48,6 +48,6 @@
 git update-index file
 
 test_expect_success 'apply at the beginning' \
-	'! git apply --index test-patch'
+	'test_must_fail git apply --index test-patch'
 
 test_done
diff --git a/t/t4116-apply-reverse.sh b/t/t4116-apply-reverse.sh
index 1459a90..2298ece 100755
--- a/t/t4116-apply-reverse.sh
+++ b/t/t4116-apply-reverse.sh
@@ -48,12 +48,12 @@
 
 test_expect_success 'setup separate repository lacking postimage' '
 
-	git tar-tree initial initial | tar xf - &&
+	git tar-tree initial initial | $TAR xf - &&
 	(
 		cd initial && git init && git add .
 	) &&
 
-	git tar-tree second second | tar xf - &&
+	git tar-tree second second | $TAR xf - &&
 	(
 		cd second && git init && git add .
 	)
diff --git a/t/t4119-apply-config.sh b/t/t4119-apply-config.sh
index b540f72..3c73a78 100755
--- a/t/t4119-apply-config.sh
+++ b/t/t4119-apply-config.sh
@@ -19,12 +19,12 @@
 '
 
 # Also handcraft GNU diff output; note this has trailing whitespace.
-cat >gpatch.file <<\EOF &&
+tr '_' ' ' >gpatch.file <<\EOF &&
 --- file1	2007-02-21 01:04:24.000000000 -0800
 +++ file1+	2007-02-21 01:07:44.000000000 -0800
 @@ -1 +1 @@
 -A
-+B 
++B_
 EOF
 
 sed -e 's|file1|sub/&|' gpatch.file >gpatch-sub.file &&
diff --git a/t/t4124-apply-ws-rule.sh b/t/t4124-apply-ws-rule.sh
index 85f3da2..f83322e 100755
--- a/t/t4124-apply-ws-rule.sh
+++ b/t/t4124-apply-ws-rule.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-test_description='core.whitespace rules and git-apply'
+test_description='core.whitespace rules and git apply'
 
 . ./test-lib.sh
 
diff --git a/t/t4127-apply-same-fn.sh b/t/t4127-apply-same-fn.sh
new file mode 100755
index 0000000..3a8202e
--- /dev/null
+++ b/t/t4127-apply-same-fn.sh
@@ -0,0 +1,90 @@
+#!/bin/sh
+
+test_description='apply same filename'
+
+. ./test-lib.sh
+
+modify () {
+	sed -e "$1" < "$2" > "$2".x &&
+	mv "$2".x "$2"
+}
+
+test_expect_success setup '
+	for i in a b c d e f g h i j k l m
+	do
+		echo $i
+	done >same_fn &&
+	cp same_fn other_fn &&
+	git add same_fn other_fn &&
+	git commit -m initial
+'
+test_expect_success 'apply same filename with independent changes' '
+	modify "s/^d/z/" same_fn &&
+	git diff > patch0 &&
+	git add same_fn &&
+	modify "s/^i/y/" same_fn &&
+	git diff >> patch0 &&
+	cp same_fn same_fn2 &&
+	git reset --hard &&
+	git apply patch0 &&
+	diff same_fn same_fn2
+'
+
+test_expect_success 'apply same filename with overlapping changes' '
+	git reset --hard
+	modify "s/^d/z/" same_fn &&
+	git diff > patch0 &&
+	git add same_fn &&
+	modify "s/^e/y/" same_fn &&
+	git diff >> patch0 &&
+	cp same_fn same_fn2 &&
+	git reset --hard &&
+	git apply patch0 &&
+	diff same_fn same_fn2
+'
+
+test_expect_success 'apply same new filename after rename' '
+	git reset --hard
+	git mv same_fn new_fn
+	modify "s/^d/z/" new_fn &&
+	git add new_fn &&
+	git diff -M --cached > patch1 &&
+	modify "s/^e/y/" new_fn &&
+	git diff >> patch1 &&
+	cp new_fn new_fn2 &&
+	git reset --hard &&
+	git apply --index patch1 &&
+	diff new_fn new_fn2
+'
+
+test_expect_success 'apply same old filename after rename -- should fail.' '
+	git reset --hard
+	git mv same_fn new_fn
+	modify "s/^d/z/" new_fn &&
+	git add new_fn &&
+	git diff -M --cached > patch1 &&
+	git mv new_fn same_fn
+	modify "s/^e/y/" same_fn &&
+	git diff >> patch1 &&
+	git reset --hard &&
+	test_must_fail git apply patch1
+'
+
+test_expect_success 'apply A->B (rename), C->A (rename), A->A -- should pass.' '
+	git reset --hard
+	git mv same_fn new_fn
+	modify "s/^d/z/" new_fn &&
+	git add new_fn &&
+	git diff -M --cached > patch1 &&
+	git commit -m "a rename" &&
+	git mv other_fn same_fn
+	modify "s/^e/y/" same_fn &&
+	git add same_fn &&
+	git diff -M --cached >> patch1 &&
+	modify "s/^g/x/" same_fn &&
+	git diff >> patch1 &&
+	git reset --hard HEAD^ &&
+	git apply patch1
+'
+
+test_done
diff --git a/t/t4128-apply-root.sh b/t/t4128-apply-root.sh
new file mode 100755
index 0000000..8f6aea4
--- /dev/null
+++ b/t/t4128-apply-root.sh
@@ -0,0 +1,95 @@
+#!/bin/sh
+
+test_description='apply same filename'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+
+	mkdir -p some/sub/dir &&
+	echo Hello > some/sub/dir/file &&
+	git add some/sub/dir/file &&
+	git commit -m initial &&
+	git tag initial
+
+'
+
+cat > patch << EOF
+diff a/bla/blub/dir/file b/bla/blub/dir/file
+--- a/bla/blub/dir/file
++++ b/bla/blub/dir/file
+@@ -1,1 +1,1 @@
+-Hello
++Bello
+EOF
+
+test_expect_success 'apply --directory -p (1)' '
+
+	git apply --directory=some/sub -p3 --index patch &&
+	test Bello = $(git show :some/sub/dir/file) &&
+	test Bello = $(cat some/sub/dir/file)
+
+'
+
+test_expect_success 'apply --directory -p (2) ' '
+
+	git reset --hard initial &&
+	git apply --directory=some/sub/ -p3 --index patch &&
+	test Bello = $(git show :some/sub/dir/file) &&
+	test Bello = $(cat some/sub/dir/file)
+
+'
+
+cat > patch << EOF
+diff --git a/newfile b/newfile
+new file mode 100644
+index 0000000..d95f3ad
+--- /dev/null
++++ b/newfile
+@@ -0,0 +1 @@
++content
+EOF
+
+test_expect_success 'apply --directory (new file)' '
+	git reset --hard initial &&
+	git apply --directory=some/sub/dir/ --index patch &&
+	test content = $(git show :some/sub/dir/newfile) &&
+	test content = $(cat some/sub/dir/newfile)
+'
+
+cat > patch << EOF
+diff --git a/delfile b/delfile
+deleted file mode 100644
+index d95f3ad..0000000
+--- a/delfile
++++ /dev/null
+@@ -1 +0,0 @@
+-content
+EOF
+
+test_expect_success 'apply --directory (delete file)' '
+	git reset --hard initial &&
+	echo content >some/sub/dir/delfile &&
+	git add some/sub/dir/delfile &&
+	git apply --directory=some/sub/dir/ --index patch &&
+	! (git ls-files | grep delfile)
+'
+
+cat > patch << 'EOF'
+diff --git "a/qu\157tefile" "b/qu\157tefile"
+new file mode 100644
+index 0000000..d95f3ad
+--- /dev/null
++++ "b/qu\157tefile"
+@@ -0,0 +1 @@
++content
+EOF
+
+test_expect_success 'apply --directory (quoted filename)' '
+	git reset --hard initial &&
+	git apply --directory=some/sub/dir/ --index patch &&
+	test content = $(git show :some/sub/dir/quotefile) &&
+	test content = $(cat some/sub/dir/quotefile)
+'
+
+test_done
diff --git a/t/t4150-am.sh b/t/t4150-am.sh
index 722ae96..1be5fb3 100755
--- a/t/t4150-am.sh
+++ b/t/t4150-am.sh
@@ -102,7 +102,7 @@
 	git checkout first &&
 	test_tick &&
 	git am <patch1 &&
-	! test -d .dotest &&
+	! test -d .git/rebase-apply &&
 	test -z "$(git diff second)" &&
 	test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
 	test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
@@ -110,7 +110,7 @@
 
 GIT_AUTHOR_NAME="Another Thor"
 GIT_AUTHOR_EMAIL="a.thor@example.com"
-GIT_COMMITTER_NAME="Co M Miter" 
+GIT_COMMITTER_NAME="Co M Miter"
 GIT_COMMITTER_EMAIL="c.miter@example.com"
 export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL
 
@@ -123,7 +123,7 @@
 	test_tick &&
 	git checkout first &&
 	git am patch2 &&
-	! test -d .dotest &&
+	! test -d .git/rebase-apply &&
 	test "$(git rev-parse master^^)" = "$(git rev-parse HEAD^^)" &&
 	test -z "$(git diff master..HEAD)" &&
 	test -z "$(git diff master^..HEAD^)" &&
@@ -163,8 +163,8 @@
 test_expect_success 'am --keep really keeps the subject' '
 	git checkout HEAD^ &&
 	git am --keep patch4 &&
-	! test -d .dotest &&
-	git-cat-file commit HEAD |
+	! test -d .git/rebase-apply &&
+	git cat-file commit HEAD |
 		grep -q -F "Re: Re: Re: [PATCH 1/5 v2] third"
 '
 
@@ -176,51 +176,51 @@
 	test_tick &&
 	git commit -m "copied stuff" &&
 	git am -3 lorem-move.patch &&
-	! test -d .dotest &&
+	! test -d .git/rebase-apply &&
 	test -z "$(git diff lorem)"
 '
 
 test_expect_success 'am pauses on conflict' '
 	git checkout lorem2^^ &&
-	! git am lorem-move.patch &&
-	test -d .dotest
+	test_must_fail git am lorem-move.patch &&
+	test -d .git/rebase-apply
 '
 
 test_expect_success 'am --skip works' '
 	git am --skip &&
-	! test -d .dotest &&
+	! test -d .git/rebase-apply &&
 	test -z "$(git diff lorem2^^ -- file)" &&
 	test goodbye = "$(cat another)"
 '
 
 test_expect_success 'am --resolved works' '
 	git checkout lorem2^^ &&
-	! git am lorem-move.patch &&
-	test -d .dotest &&
+	test_must_fail git am lorem-move.patch &&
+	test -d .git/rebase-apply &&
 	echo resolved >>file &&
 	git add file &&
 	git am --resolved &&
-	! test -d .dotest &&
+	! test -d .git/rebase-apply &&
 	test goodbye = "$(cat another)"
 '
 
 test_expect_success 'am takes patches from a Pine mailbox' '
 	git checkout first &&
 	cat pine patch1 | git am &&
-	! test -d .dotest &&
+	! test -d .git/rebase-apply &&
 	test -z "$(git diff master^..HEAD)"
 '
 
 test_expect_success 'am fails on mail without patch' '
-	! git am <failmail &&
-	rm -r .dotest/
+	test_must_fail git am <failmail &&
+	rm -r .git/rebase-apply/
 '
 
 test_expect_success 'am fails on empty patch' '
 	echo "---" >>failmail &&
-	! git am <failmail &&
+	test_must_fail git am <failmail &&
 	git am --skip &&
-	! test -d .dotest
+	! test -d .git/rebase-apply
 '
 
 test_expect_success 'am works from stdin in subdirectory' '
diff --git a/t/t4151-am-abort.sh b/t/t4151-am-abort.sh
new file mode 100755
index 0000000..4448aba
--- /dev/null
+++ b/t/t4151-am-abort.sh
@@ -0,0 +1,65 @@
+#!/bin/sh
+
+test_description='am --abort'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+	for i in a b c d e f g
+	do
+		echo $i
+	done >file-1 &&
+	cp file-1 file-2 &&
+	test_tick &&
+	git add file-1 file-2 &&
+	git commit -m initial &&
+	git tag initial &&
+	for i in 2 3 4 5 6
+	do
+		echo $i >>file-1 &&
+		echo $i >otherfile-$i &&
+		git add otherfile-$i &&
+		test_tick &&
+		git commit -a -m $i || break
+	done &&
+	git format-patch initial &&
+	git checkout -b side initial &&
+	echo local change >file-2-expect
+'
+
+for with3 in '' ' -3'
+do
+	test_expect_success "am$with3 stops at a patch that does not apply" '
+
+		git reset --hard initial &&
+		cp file-2-expect file-2 &&
+
+		test_must_fail git am$with3 000[1245]-*.patch &&
+		git log --pretty=tformat:%s >actual &&
+		for i in 3 2 initial
+		do
+			echo $i
+		done >expect &&
+		test_cmp expect actual
+	'
+
+	test_expect_success "am$with3 --skip continue after failed am$with3" '
+		test_must_fail git am$with3 --skip >output &&
+		test "$(grep "^Applying" output)" = "Applying: 6" &&
+		test_cmp file-2-expect file-2 &&
+		test ! -f .git/rr-cache/MERGE_RR
+	'
+
+	test_expect_success "am --abort goes back after failed am$with3" '
+		git am --abort &&
+		git rev-parse HEAD >actual &&
+		git rev-parse initial >expect &&
+		test_cmp expect actual &&
+		test_cmp file-2-expect file-2 &&
+		git diff-index --exit-code --cached HEAD &&
+		test ! -f .git/rr-cache/MERGE_RR
+	'
+
+done
+
+test_done
diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh
index 85d7e3e..b68ab11 100755
--- a/t/t4200-rerere.sh
+++ b/t/t4200-rerere.sh
@@ -9,6 +9,8 @@
 . ./test-lib.sh
 
 cat > a1 << EOF
+Some title
+==========
 Whether 'tis nobler in the mind to suffer
 The slings and arrows of outrageous fortune,
 Or to take arms against a sea of troubles,
@@ -24,6 +26,8 @@
 
 git checkout -b first
 cat >> a1 << EOF
+Some title
+==========
 To die, to sleep;
 To sleep: perchance to dream: ay, there's the rub;
 For in that sleep of death what dreams may come
@@ -35,13 +39,13 @@
 
 git checkout -b second master
 git show first:a1 |
-sed -e 's/To die, t/To die! T/' > a1
+sed -e 's/To die, t/To die! T/' -e 's/Some title/Some Title/' > a1
 echo "* END *" >>a1
 git commit -q -a -m second
 
 test_expect_success 'nothing recorded without rerere' '
 	(rm -rf .git/rr-cache; git config rerere.enabled false) &&
-	! git merge first &&
+	test_must_fail git merge first &&
 	! test -d .git/rr-cache
 '
 
@@ -50,19 +54,19 @@
 	git reset --hard &&
 	mkdir .git/rr-cache &&
 	git config --unset rerere.enabled &&
-	! git merge first
+	test_must_fail git merge first
 '
 
-sha1=$(sed -e 's/	.*//' .git/rr-cache/MERGE_RR)
+sha1=$(sed -e 's/	.*//' .git/MERGE_RR)
 rr=.git/rr-cache/$sha1
-test_expect_success 'recorded preimage' "grep ======= $rr/preimage"
+test_expect_success 'recorded preimage' "grep ^=======$ $rr/preimage"
 
 test_expect_success 'rerere.enabled works, too' '
 	rm -rf .git/rr-cache &&
 	git config rerere.enabled true &&
 	git reset --hard &&
-	! git merge first &&
-	grep ======= $rr/preimage
+	test_must_fail git merge first &&
+	grep ^=======$ $rr/preimage
 '
 
 test_expect_success 'no postimage or thisimage yet' \
@@ -71,7 +75,7 @@
 test_expect_success 'preimage has right number of lines' '
 
 	cnt=$(sed -ne "/^<<<<<<</,/^>>>>>>>/p" $rr/preimage | wc -l) &&
-	test $cnt = 9
+	test $cnt = 13
 
 '
 
@@ -80,13 +84,23 @@
 cat > expect << EOF
 --- a/a1
 +++ b/a1
-@@ -6,17 +6,9 @@
+@@ -1,4 +1,4 @@
+-Some Title
++Some title
+ ==========
+ Whether 'tis nobler in the mind to suffer
+ The slings and arrows of outrageous fortune,
+@@ -8,21 +8,11 @@
  The heart-ache and the thousand natural shocks
  That flesh is heir to, 'tis a consummation
  Devoutly to be wish'd.
 -<<<<<<<
+-Some Title
+-==========
 -To die! To sleep;
 -=======
+ Some title
+ ==========
  To die, to sleep;
 ->>>>>>>
  To sleep: perchance to dream: ay, there's the rub;
@@ -120,16 +134,16 @@
 	git checkout -b third master &&
 	git show second^:a1 | sed "s/To die: t/To die! T/" > a1 &&
 	git commit -q -a -m third &&
-	! git pull . first
+	test_must_fail git pull . first
 '
 
 git show first:a1 | sed 's/To die: t/To die! T/' > expect
-test_expect_success 'rerere kicked in' "! grep ======= a1"
+test_expect_success 'rerere kicked in' "! grep ^=======$ a1"
 
 test_expect_success 'rerere prefers first change' 'test_cmp a1 expect'
 
 rm $rr/postimage
-echo "$sha1	a1" | perl -pe 'y/\012/\000/' > .git/rr-cache/MERGE_RR
+echo "$sha1	a1" | perl -pe 'y/\012/\000/' > .git/MERGE_RR
 
 test_expect_success 'rerere clear' 'git rerere clear'
 
@@ -175,8 +189,8 @@
 	echo Bello > file2 &&
 	git add file2 &&
 	git commit -m version2 &&
-	! git merge fourth &&
-	sha1=$(sed -e "s/	.*//" .git/rr-cache/MERGE_RR) &&
+	test_must_fail git merge fourth &&
+	sha1=$(sed -e "s/	.*//" .git/MERGE_RR) &&
 	rr=.git/rr-cache/$sha1 &&
 	echo Cello > file2 &&
 	git add file2 &&
@@ -193,9 +207,19 @@
 	echo Bello > file3 &&
 	git add file3 &&
 	git commit -m version2 &&
-	! git merge fifth &&
-	git diff-files -q &&
-	test Cello = "$(cat file3)"
+	git tag version2 &&
+	test_must_fail git merge fifth &&
+	test Cello = "$(cat file3)" &&
+	test 0 != $(git ls-files -u | wc -l)
+'
+
+test_expect_success 'rerere.autoupdate' '
+	git config rerere.autoupdate true
+	git reset --hard &&
+	git checkout version2 &&
+	test_must_fail git merge fifth &&
+	test 0 = $(git ls-files -u | wc -l)
+
 '
 
 test_done
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index 4c8af45..0ab925c 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -69,7 +69,29 @@
 
 '
 
+test_expect_success 'setup case sensitivity tests' '
+	echo case >one &&
+	test_tick &&
+	git commit -a -m Second
+'
 
+test_expect_success 'log --grep' '
+	echo second >expect &&
+	git log -1 --pretty="tformat:%s" --grep=sec >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'log -i --grep' '
+	echo Second >expect &&
+	git log -1 --pretty="tformat:%s" -i --grep=sec >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'log --grep -i' '
+	echo Second >expect &&
+	git log -1 --pretty="tformat:%s" --grep=sec -i >actual &&
+	test_cmp expect actual
+'
 
 test_done
 
diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh
index 87902f8..c942c8b 100755
--- a/t/t5000-tar-tree.sh
+++ b/t/t5000-tar-tree.sh
@@ -44,6 +44,11 @@
      (cd a && find .) | sort >a.lst'
 
 test_expect_success \
+    'add ignored file' \
+    'echo ignore me >a/ignored &&
+     echo ignored export-ignore >.gitattributes'
+
+test_expect_success \
     'add files to repository' \
     'find a -type f | xargs git update-index --add &&
      find a -type l | xargs git update-index --add &&
@@ -53,6 +58,15 @@
      git commit-tree $treeid </dev/null)'
 
 test_expect_success \
+    'create bare clone' \
+    'git clone --bare . bare.git &&
+     cp .gitattributes bare.git/info/attributes'
+
+test_expect_success \
+    'remove ignored file' \
+    'rm a/ignored'
+
+test_expect_success \
     'git archive' \
     'git archive HEAD >b.tar'
 
@@ -65,10 +79,18 @@
     'diff b.tar b2.tar'
 
 test_expect_success \
+    'git archive in a bare repo' \
+    '(cd bare.git && git archive HEAD) >b3.tar'
+
+test_expect_success \
+    'git archive vs. the same in a bare repo' \
+    'test_cmp b.tar b3.tar'
+
+test_expect_success \
     'validate file modification time' \
     'mkdir extract &&
      "$TAR" xf b.tar -C extract a/a &&
-     perl -e '\''print((stat("extract/a/a"))[9], "\n")'\'' >b.mtime &&
+     test-chmtime -v +0 extract/a/a |cut -f 1 >b.mtime &&
      echo "1117231200" >expected.mtime &&
      diff expected.mtime b.mtime'
 
@@ -142,6 +164,14 @@
     'git archive --format=zip' \
     'git archive --format=zip HEAD >d.zip'
 
+test_expect_success \
+    'git archive --format=zip in a bare repo' \
+    '(cd bare.git && git archive --format=zip HEAD) >d1.zip'
+
+test_expect_success \
+    'git archive --format=zip vs. the same in a bare repo' \
+    'test_cmp d.zip d1.zip'
+
 $UNZIP -v >/dev/null 2>&1
 if [ $? -eq 127 ]; then
 	echo "Skipping ZIP tests, because unzip was not found"
diff --git a/t/t5100-mailinfo.sh b/t/t5100-mailinfo.sh
index e9f3e72..198e350 100755
--- a/t/t5100-mailinfo.sh
+++ b/t/t5100-mailinfo.sh
@@ -11,7 +11,7 @@
 	'git mailsplit -o. ../t5100/sample.mbox >last &&
 	last=`cat last` &&
 	echo total is $last &&
-	test `cat last` = 10'
+	test `cat last` = 11'
 
 for mail in `echo 00*`
 do
@@ -43,4 +43,15 @@
 
 '
 
+test_expect_success 'mailinfo on from header without name works' '
+
+	mkdir info-from &&
+	git mailsplit -oinfo-from "$TEST_DIRECTORY"/t5100/info-from.in &&
+	test_cmp "$TEST_DIRECTORY"/t5100/info-from.in info-from/0001 &&
+	git mailinfo info-from/msg info-from/patch \
+	  <info-from/0001 >info-from/out &&
+	test_cmp "$TEST_DIRECTORY"/t5100/info-from.expect info-from/out
+
+'
+
 test_done
diff --git a/t/t5100/info-from.expect b/t/t5100/info-from.expect
new file mode 100644
index 0000000..c31d2eb
--- /dev/null
+++ b/t/t5100/info-from.expect
@@ -0,0 +1,5 @@
+Author: bare@example.com
+Email: bare@example.com
+Subject: testing bare address in from header
+Date: Sun, 25 May 2008 00:38:18 -0700
+
diff --git a/t/t5100/info-from.in b/t/t5100/info-from.in
new file mode 100644
index 0000000..4f08209
--- /dev/null
+++ b/t/t5100/info-from.in
@@ -0,0 +1,8 @@
+From 667d8940e719cddee1cfe237cbbe215e20270b09 Mon Sep 17 00:00:00 2001
+From: bare@example.com
+Date: Sun, 25 May 2008 00:38:18 -0700
+Subject: [PATCH] testing bare address in from header
+
+commit message
+---
+patch
diff --git a/t/t5100/info0011 b/t/t5100/info0011
new file mode 100644
index 0000000..da5a605
--- /dev/null
+++ b/t/t5100/info0011
@@ -0,0 +1,5 @@
+Author: A U Thor
+Email: a.u.thor@example.com
+Subject: Xyzzy
+Date: Fri, 8 Aug 2008 13:08:37 +0200 (CEST)
+
diff --git a/t/t5100/msg0011 b/t/t5100/msg0011
new file mode 100644
index 0000000..4667f21
--- /dev/null
+++ b/t/t5100/msg0011
@@ -0,0 +1,2 @@
+Here comes a commit log message, and
+its second line is here.
diff --git a/t/t5100/patch0011 b/t/t5100/patch0011
new file mode 100644
index 0000000..8841d3c
--- /dev/null
+++ b/t/t5100/patch0011
@@ -0,0 +1,22 @@
+---
+ builtin-mailinfo.c  |    4 ++--
+
+diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c
+index 3e5fe51..aabfe5c 100644
+--- a/builtin-mailinfo.c
++++ b/builtin-mailinfo.c
+@@ -758,8 +758,8 @@ static void handle_body(void)
+ 		/* process any boundary lines */
+ 		if (*content_top && is_multipart_boundary(&line)) {
+ 			/* flush any leftover */
+-			if (line.len)
+-				handle_filter(&line);
++			if (prev.len)
++				handle_filter(&prev);
+ 
+ 			if (!handle_boundary())
+ 				goto handle_body_out;
+-- 
+1.6.0.rc2
+
+
diff --git a/t/t5100/sample.mbox b/t/t5100/sample.mbox
index aba57f9..4bf7947 100644
--- a/t/t5100/sample.mbox
+++ b/t/t5100/sample.mbox
@@ -465,3 +465,39 @@
 -- 
 1.5.6.2.455.g1efb2
 
+From nobody Fri Aug  8 22:24:03 2008
+Date: Fri, 8 Aug 2008 13:08:37 +0200 (CEST)
+From: A U Thor <a.u.thor@example.com>
+Subject: [PATCH 3/3 v2] Xyzzy
+MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary="=-=-="
+
+--=-=-=
+Content-Type: text/plain; charset=iso-8859-15
+Content-Transfer-Encoding: quoted-printable
+
+Here comes a commit log message, and
+its second line is here.
+---
+ builtin-mailinfo.c  |    4 ++--
+
+diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c
+index 3e5fe51..aabfe5c 100644
+--- a/builtin-mailinfo.c
++++ b/builtin-mailinfo.c
+@@ -758,8 +758,8 @@ static void handle_body(void)
+ 		/* process any boundary lines */
+ 		if (*content_top && is_multipart_boundary(&line)) {
+ 			/* flush any leftover */
+-			if (line.len)
+-				handle_filter(&line);
++			if (prev.len)
++				handle_filter(&prev);
+=20
+ 			if (!handle_boundary())
+ 				goto handle_body_out;
+--=20
+1.6.0.rc2
+
+--=-=-=--
+
diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh
index 983a393..2852a03 100755
--- a/t/t5300-pack-object.sh
+++ b/t/t5300-pack-object.sh
@@ -3,7 +3,7 @@
 # Copyright (c) 2005 Junio C Hamano
 #
 
-test_description='git-pack-object
+test_description='git pack-object
 
 '
 . ./test-lib.sh
@@ -187,6 +187,12 @@
 			test-3-${packname_3}.idx'
 
 test_expect_success \
+    'verify pack -v' \
+    'git verify-pack -v	test-1-${packname_1}.idx \
+			test-2-${packname_2}.idx \
+			test-3-${packname_3}.idx'
+
+test_expect_success \
     'verify-pack catches mismatched .idx and .pack files' \
     'cat test-1-${packname_1}.idx >test-3.idx &&
      cat test-2-${packname_2}.pack >test-3.pack &&
@@ -236,24 +242,24 @@
 test_expect_success \
     'build pack index for an existing pack' \
     'cat test-1-${packname_1}.pack >test-3.pack &&
-     git-index-pack -o tmp.idx test-3.pack &&
+     git index-pack -o tmp.idx test-3.pack &&
      cmp tmp.idx test-1-${packname_1}.idx &&
 
-     git-index-pack test-3.pack &&
+     git index-pack test-3.pack &&
      cmp test-3.idx test-1-${packname_1}.idx &&
 
      cat test-2-${packname_2}.pack >test-3.pack &&
-     git-index-pack -o tmp.idx test-2-${packname_2}.pack &&
+     git index-pack -o tmp.idx test-2-${packname_2}.pack &&
      cmp tmp.idx test-2-${packname_2}.idx &&
 
-     git-index-pack test-3.pack &&
+     git index-pack test-3.pack &&
      cmp test-3.idx test-2-${packname_2}.idx &&
 
      cat test-3-${packname_3}.pack >test-3.pack &&
-     git-index-pack -o tmp.idx test-3-${packname_3}.pack &&
+     git index-pack -o tmp.idx test-3-${packname_3}.pack &&
      cmp tmp.idx test-3-${packname_3}.idx &&
 
-     git-index-pack test-3.pack &&
+     git index-pack test-3.pack &&
      cmp test-3.idx test-3-${packname_3}.idx &&
 
      :'
@@ -266,7 +272,7 @@
 
 test_expect_success \
     'make sure index-pack detects the SHA1 collision' \
-    '! git-index-pack -o bad.idx test-3.pack'
+    'test_must_fail git index-pack -o bad.idx test-3.pack'
 
 test_expect_success \
     'honor pack.packSizeLimit' \
@@ -369,4 +375,10 @@
 	)
 '
 
+test_expect_success 'tolerate absurdly small packsizelimit' '
+	git config pack.packSizeLimit 2 &&
+	packname_9=$(git pack-objects test-9 <obj-list) &&
+	test $(wc -l <obj-list) = $(ls test-9-*.pack | wc -l)
+'
+
 test_done
diff --git a/t/t5301-sliding-window.sh b/t/t5301-sliding-window.sh
index 073ac0c..0a24e61 100755
--- a/t/t5301-sliding-window.sh
+++ b/t/t5301-sliding-window.sh
@@ -19,7 +19,7 @@
      tree=`git write-tree` &&
      commit1=`git commit-tree $tree </dev/null` &&
      git update-ref HEAD $commit1 &&
-     git-repack -a -d &&
+     git repack -a -d &&
      test "`git count-objects`" = "0 objects, 0 kilobytes" &&
      pack1=`ls .git/objects/pack/*.pack` &&
      test -f "$pack1"'
@@ -45,7 +45,7 @@
      git config core.packedGitLimit 512 &&
      commit2=`git commit-tree $tree -p $commit1 </dev/null` &&
      git update-ref HEAD $commit2 &&
-     git-repack -a -d &&
+     git repack -a -d &&
      test "`git count-objects`" = "0 objects, 0 kilobytes" &&
      pack2=`ls .git/objects/pack/*.pack` &&
      test -f "$pack2"
diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh
index 09fd917..344ab25 100755
--- a/t/t5302-pack-index.sh
+++ b/t/t5302-pack-index.sh
@@ -48,11 +48,11 @@
 
 test_expect_success \
     'index-pack with index version 1' \
-    'git-index-pack --index-version=1 -o 1.idx "test-1-${pack1}.pack"'
+    'git index-pack --index-version=1 -o 1.idx "test-1-${pack1}.pack"'
 
 test_expect_success \
     'index-pack with index version 2' \
-    'git-index-pack --index-version=2 -o 2.idx "test-1-${pack1}.pack"'
+    'git index-pack --index-version=2 -o 2.idx "test-1-${pack1}.pack"'
 
 test_expect_success \
     'index-pack results should match pack-objects ones' \
@@ -85,7 +85,7 @@
 test "$have_64bits" &&
 test_expect_success \
     'index v2: force some 64-bit offsets with index-pack' \
-    'git-index-pack --index-version=2,0x40000 -o 3.idx "test-1-${pack1}.pack"'
+    'git index-pack --index-version=2,0x40000 -o 3.idx "test-1-${pack1}.pack"'
 
 test "$have_64bits" &&
 test_expect_success \
@@ -94,7 +94,7 @@
 
 test_expect_success \
     '[index v1] 1) stream pack to repository' \
-    'git-index-pack --index-version=1 --stdin < "test-1-${pack1}.pack" &&
+    'git index-pack --index-version=1 --stdin < "test-1-${pack1}.pack" &&
      git prune-packed &&
      git count-objects | ( read nr rest && test "$nr" -eq 1 ) &&
      cmp "test-1-${pack1}.pack" ".git/objects/pack/pack-${pack1}.pack" &&
@@ -118,7 +118,7 @@
 
 test_expect_success \
     '[index v1] 4) confirm that the pack is actually corrupted' \
-    '! git fsck --full $commit'
+    'test_must_fail git fsck --full $commit'
 
 test_expect_success \
     '[index v1] 5) pack-objects happily reuses corrupted data' \
@@ -127,12 +127,12 @@
 
 test_expect_success \
     '[index v1] 6) newly created pack is BAD !' \
-    '! git verify-pack -v "test-4-${pack1}.pack"'
+    'test_must_fail git verify-pack -v "test-4-${pack1}.pack"'
 
 test_expect_success \
     '[index v2] 1) stream pack to repository' \
     'rm -f .git/objects/pack/* &&
-     git-index-pack --index-version=2 --stdin < "test-1-${pack1}.pack" &&
+     git index-pack --index-version=2 --stdin < "test-1-${pack1}.pack" &&
      git prune-packed &&
      git count-objects | ( read nr rest && test "$nr" -eq 1 ) &&
      cmp "test-1-${pack1}.pack" ".git/objects/pack/pack-${pack1}.pack" &&
@@ -156,10 +156,35 @@
 
 test_expect_success \
     '[index v2] 4) confirm that the pack is actually corrupted' \
-    '! git fsck --full $commit'
+    'test_must_fail git fsck --full $commit'
 
 test_expect_success \
     '[index v2] 5) pack-objects refuses to reuse corrupted data' \
-    '! git pack-objects test-5 <obj-list'
+    'test_must_fail git pack-objects test-5 <obj-list'
+
+test_expect_success \
+    '[index v2] 6) verify-pack detects CRC mismatch' \
+    'rm -f .git/objects/pack/* &&
+     git index-pack --index-version=2 --stdin < "test-1-${pack1}.pack" &&
+     git verify-pack ".git/objects/pack/pack-${pack1}.pack" &&
+     chmod +w ".git/objects/pack/pack-${pack1}.idx" &&
+     dd if=/dev/zero of=".git/objects/pack/pack-${pack1}.idx" conv=notrunc \
+        bs=1 count=4 seek=$((8 + 256 * 4 + `wc -l <obj-list` * 20 + 0)) &&
+     ( while read obj
+       do git cat-file -p $obj >/dev/null || exit 1
+       done <obj-list ) &&
+     err=$(test_must_fail git verify-pack \
+       ".git/objects/pack/pack-${pack1}.pack" 2>&1) &&
+     echo "$err" | grep "CRC mismatch"'
+
+test_expect_success 'running index-pack in the object store' '
+    rm -f .git/objects/pack/* &&
+    cp test-1-${pack1}.pack .git/objects/pack/pack-${pack1}.pack &&
+    (
+	cd .git/objects/pack
+	git index-pack pack-${pack1}.pack
+    ) &&
+    test -f .git/objects/pack/pack-${pack1}.idx
+'
 
 test_done
diff --git a/t/t5303-pack-corruption-resilience.sh b/t/t5303-pack-corruption-resilience.sh
new file mode 100755
index 0000000..31b20b2
--- /dev/null
+++ b/t/t5303-pack-corruption-resilience.sh
@@ -0,0 +1,194 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Nicolas Pitre
+#
+
+test_description='resilience to pack corruptions with redundant objects'
+. ./test-lib.sh
+
+# Note: the test objects are created with knowledge of their pack encoding
+# to ensure good code path coverage, and to facilitate direct alteration
+# later on.  The assumed characteristics are:
+#
+# 1) blob_2 is a delta with blob_1 for base and blob_3 is a delta with blob2
+#    for base, such that blob_3 delta depth is 2;
+#
+# 2) the bulk of object data is uncompressible so the text part remains
+#    visible;
+#
+# 3) object header is always 2 bytes.
+
+create_test_files() {
+    test-genrandom "foo" 2000 > file_1 &&
+    test-genrandom "foo" 1800 > file_2 &&
+    test-genrandom "foo" 1800 > file_3 &&
+    echo " base " >> file_1 &&
+    echo " delta1 " >> file_2 &&
+    echo " delta delta2 " >> file_3 &&
+    test-genrandom "bar" 150 >> file_2 &&
+    test-genrandom "baz" 100 >> file_3
+}
+
+create_new_pack() {
+    rm -rf .git &&
+    git init &&
+    blob_1=`git hash-object -t blob -w file_1` &&
+    blob_2=`git hash-object -t blob -w file_2` &&
+    blob_3=`git hash-object -t blob -w file_3` &&
+    pack=`printf "$blob_1\n$blob_2\n$blob_3\n" |
+          git pack-objects $@ .git/objects/pack/pack` &&
+    pack=".git/objects/pack/pack-${pack}" &&
+    git verify-pack -v ${pack}.pack
+}
+
+do_corrupt_object() {
+    ofs=`git show-index < ${pack}.idx | grep $1 | cut -f1 -d" "` &&
+    ofs=$(($ofs + $2)) &&
+    chmod +w ${pack}.pack &&
+    dd if=/dev/zero of=${pack}.pack count=1 bs=1 conv=notrunc seek=$ofs &&
+    test_must_fail git verify-pack ${pack}.pack
+}
+
+test_expect_success \
+    'initial setup validation' \
+    'create_test_files &&
+     create_new_pack &&
+     git prune-packed &&
+     git cat-file blob $blob_1 > /dev/null &&
+     git cat-file blob $blob_2 > /dev/null &&
+     git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    'create corruption in header of first object' \
+    'do_corrupt_object $blob_1 0 &&
+     test_must_fail git cat-file blob $blob_1 > /dev/null &&
+     test_must_fail git cat-file blob $blob_2 > /dev/null &&
+     test_must_fail git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    '... but having a loose copy allows for full recovery' \
+    'mv ${pack}.idx tmp &&
+     git hash-object -t blob -w file_1 &&
+     mv tmp ${pack}.idx &&
+     git cat-file blob $blob_1 > /dev/null &&
+     git cat-file blob $blob_2 > /dev/null &&
+     git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    '... and loose copy of first delta allows for partial recovery' \
+    'git prune-packed &&
+     test_must_fail git cat-file blob $blob_2 > /dev/null &&
+     mv ${pack}.idx tmp &&
+     git hash-object -t blob -w file_2 &&
+     mv tmp ${pack}.idx &&
+     test_must_fail git cat-file blob $blob_1 > /dev/null &&
+     git cat-file blob $blob_2 > /dev/null &&
+     git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    'create corruption in data of first object' \
+    'create_new_pack &&
+     git prune-packed &&
+     chmod +w ${pack}.pack &&
+     perl -i.bak -pe "s/ base /abcdef/" ${pack}.pack &&
+     test_must_fail git cat-file blob $blob_1 > /dev/null &&
+     test_must_fail git cat-file blob $blob_2 > /dev/null &&
+     test_must_fail git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    '... but having a loose copy allows for full recovery' \
+    'mv ${pack}.idx tmp &&
+     git hash-object -t blob -w file_1 &&
+     mv tmp ${pack}.idx &&
+     git cat-file blob $blob_1 > /dev/null &&
+     git cat-file blob $blob_2 > /dev/null &&
+     git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    '... and loose copy of second object allows for partial recovery' \
+    'git prune-packed &&
+     test_must_fail git cat-file blob $blob_2 > /dev/null &&
+     mv ${pack}.idx tmp &&
+     git hash-object -t blob -w file_2 &&
+     mv tmp ${pack}.idx &&
+     test_must_fail git cat-file blob $blob_1 > /dev/null &&
+     git cat-file blob $blob_2 > /dev/null &&
+     git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    'create corruption in header of first delta' \
+    'create_new_pack &&
+     git prune-packed &&
+     do_corrupt_object $blob_2 0 &&
+     git cat-file blob $blob_1 > /dev/null &&
+     test_must_fail git cat-file blob $blob_2 > /dev/null &&
+     test_must_fail git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    '... but having a loose copy allows for full recovery' \
+    'mv ${pack}.idx tmp &&
+     git hash-object -t blob -w file_2 &&
+     mv tmp ${pack}.idx &&
+     git cat-file blob $blob_1 > /dev/null &&
+     git cat-file blob $blob_2 > /dev/null &&
+     git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    'create corruption in data of first delta' \
+    'create_new_pack &&
+     git prune-packed &&
+     chmod +w ${pack}.pack &&
+     perl -i.bak -pe "s/ delta1 /abcdefgh/" ${pack}.pack &&
+     git cat-file blob $blob_1 > /dev/null &&
+     test_must_fail git cat-file blob $blob_2 > /dev/null &&
+     test_must_fail git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    '... but having a loose copy allows for full recovery' \
+    'mv ${pack}.idx tmp &&
+     git hash-object -t blob -w file_2 &&
+     mv tmp ${pack}.idx &&
+     git cat-file blob $blob_1 > /dev/null &&
+     git cat-file blob $blob_2 > /dev/null &&
+     git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    'corruption in delta base reference of first delta (OBJ_REF_DELTA)' \
+    'create_new_pack &&
+     git prune-packed &&
+     do_corrupt_object $blob_2 2 &&
+     git cat-file blob $blob_1 > /dev/null &&
+     test_must_fail git cat-file blob $blob_2 > /dev/null &&
+     test_must_fail git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    '... but having a loose copy allows for full recovery' \
+    'mv ${pack}.idx tmp &&
+     git hash-object -t blob -w file_2 &&
+     mv tmp ${pack}.idx &&
+     git cat-file blob $blob_1 > /dev/null &&
+     git cat-file blob $blob_2 > /dev/null &&
+     git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    'corruption in delta base reference of first delta (OBJ_OFS_DELTA)' \
+    'create_new_pack --delta-base-offset &&
+     git prune-packed &&
+     do_corrupt_object $blob_2 2 &&
+     git cat-file blob $blob_1 > /dev/null &&
+     test_must_fail git cat-file blob $blob_2 > /dev/null &&
+     test_must_fail git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    '... and a redundant pack allows for full recovery too' \
+    'mv ${pack}.idx tmp &&
+     git hash-object -t blob -w file_1 &&
+     git hash-object -t blob -w file_2 &&
+     printf "$blob_1\n$blob_2\n" | git pack-objects .git/objects/pack/pack &&
+     git prune-packed &&
+     mv tmp ${pack}.idx &&
+     git cat-file blob $blob_1 > /dev/null &&
+     git cat-file blob $blob_2 > /dev/null &&
+     git cat-file blob $blob_3 > /dev/null'
+
+test_done
diff --git a/t/t5305-include-tag.sh b/t/t5305-include-tag.sh
index fb471a0..b061864 100755
--- a/t/t5305-include-tag.sh
+++ b/t/t5305-include-tag.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-test_description='git-pack-object --include-tag'
+test_description='git pack-object --include-tag'
 . ./test-lib.sh
 
 TRASH=`pwd`
diff --git a/t/t5306-pack-nobase.sh b/t/t5306-pack-nobase.sh
new file mode 100755
index 0000000..f4931c0
--- /dev/null
+++ b/t/t5306-pack-nobase.sh
@@ -0,0 +1,80 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Google Inc.
+#
+
+test_description='git-pack-object with missing base
+
+'
+. ./test-lib.sh
+
+# Create A-B chain
+#
+test_expect_success \
+    'setup base' \
+    'for a in a b c d e f g h i; do echo $a >>text; done &&
+     echo side >side &&
+     git update-index --add text side &&
+     A=$(echo A | git commit-tree $(git write-tree)) &&
+
+     echo m >>text &&
+     git update-index text &&
+     B=$(echo B | git commit-tree $(git write-tree) -p $A) &&
+     git update-ref HEAD $B
+    '
+
+# Create repository with C whose parent is B.
+# Repository contains C, C^{tree}, C:text, B, B^{tree}.
+# Repository is missing B:text (best delta base for C:text).
+# Repository is missing A (parent of B).
+# Repository is missing A:side.
+#
+test_expect_success \
+    'setup patch_clone' \
+    'base_objects=$(pwd)/.git/objects &&
+     (mkdir patch_clone &&
+      cd patch_clone &&
+      git init &&
+      echo "$base_objects" >.git/objects/info/alternates &&
+      echo q >>text &&
+      git read-tree $B &&
+      git update-index text &&
+      git update-ref HEAD $(echo C | git commit-tree $(git write-tree) -p $B) &&
+      rm .git/objects/info/alternates &&
+
+      git --git-dir=../.git cat-file commit $B |
+      git hash-object -t commit -w --stdin &&
+
+      git --git-dir=../.git cat-file tree "$B^{tree}" |
+      git hash-object -t tree -w --stdin
+     ) &&
+     C=$(git --git-dir=patch_clone/.git rev-parse HEAD)
+    '
+
+# Clone patch_clone indirectly by cloning base and fetching.
+#
+test_expect_success \
+    'indirectly clone patch_clone' \
+    '(mkdir user_clone &&
+      cd user_clone &&
+      git init &&
+      git pull ../.git &&
+      test $(git rev-parse HEAD) = $B &&
+
+      git pull ../patch_clone/.git &&
+      test $(git rev-parse HEAD) = $C
+     )
+    '
+
+# Cloning the patch_clone directly should fail.
+#
+test_expect_success \
+    'clone of patch_clone is incomplete' \
+    '(mkdir user_direct &&
+      cd user_direct &&
+      git init &&
+      test_must_fail git fetch ../patch_clone/.git
+     )
+    '
+
+test_done
diff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh
index 68c2ae6..544771d 100755
--- a/t/t5400-send-pack.sh
+++ b/t/t5400-send-pack.sh
@@ -31,7 +31,7 @@
 	    parent=$commit || return 1
 	done &&
 	git update-ref HEAD "$commit" &&
-	git-clone ./. victim &&
+	git clone ./. victim &&
 	cd victim &&
 	git log &&
 	cd .. &&
@@ -68,7 +68,7 @@
 test_expect_success \
         'pushing rewound head should not barf but require --force' '
 	# should not fail but refuse to update.
-	if git-send-pack ./victim/.git/ master
+	if git send-pack ./victim/.git/ master
 	then
 		# now it should fail with Pasky patch
 		echo >&2 Gaah, it should have failed.
@@ -85,7 +85,7 @@
 		true
 	fi &&
 	# this should update
-	git-send-pack --force ./victim/.git/ master &&
+	git send-pack --force ./victim/.git/ master &&
 	cmp victim/.git/refs/heads/master .git/refs/heads/master
 '
 
@@ -95,7 +95,7 @@
 	git branch extra master &&
 	cd .. &&
 	test -f victim/.git/refs/heads/extra &&
-	git-send-pack ./victim/.git/ :extra master &&
+	git send-pack ./victim/.git/ :extra master &&
 	! test -f victim/.git/refs/heads/extra
 '
 
@@ -109,27 +109,27 @@
 	git config receive.denyNonFastforwards true &&
 	cd .. &&
 	git update-ref refs/heads/master master^ || return 1
-	git-send-pack --force ./victim/.git/ master && return 1
+	git send-pack --force ./victim/.git/ master && return 1
 	! test_cmp .git/refs/heads/master victim/.git/refs/heads/master
 '
 
 test_expect_success \
 	'pushing does not include non-head refs' '
 	mkdir parent && cd parent &&
-	git-init && touch file && git-add file && git-commit -m add &&
+	git init && touch file && git add file && git commit -m add &&
 	cd .. &&
-	git-clone parent child && cd child && git-push --all &&
+	git clone parent child && cd child && git push --all &&
 	cd ../parent &&
-	git-branch -a >branches && ! grep origin/master branches
+	git branch -a >branches && ! grep origin/master branches
 '
 
 rewound_push_setup() {
 	rm -rf parent child &&
 	mkdir parent && cd parent &&
-	git-init && echo one >file && git-add file && git-commit -m one &&
-	echo two >file && git-commit -a -m two &&
+	git init && echo one >file && git add file && git commit -m one &&
+	echo two >file && git commit -a -m two &&
 	cd .. &&
-	git-clone parent child && cd child && git-reset --hard HEAD^
+	git clone parent child && cd child && git reset --hard HEAD^
 }
 
 rewound_push_succeeded() {
@@ -148,26 +148,26 @@
 test_expect_success \
 	'pushing explicit refspecs respects forcing' '
 	rewound_push_setup &&
-	if git-send-pack ../parent/.git refs/heads/master:refs/heads/master
+	if git send-pack ../parent/.git refs/heads/master:refs/heads/master
 	then
 		false
 	else
 		true
 	fi && rewound_push_failed &&
-	git-send-pack ../parent/.git +refs/heads/master:refs/heads/master &&
+	git send-pack ../parent/.git +refs/heads/master:refs/heads/master &&
 	rewound_push_succeeded
 '
 
 test_expect_success \
 	'pushing wildcard refspecs respects forcing' '
 	rewound_push_setup &&
-	if git-send-pack ../parent/.git refs/heads/*:refs/heads/*
+	if git send-pack ../parent/.git refs/heads/*:refs/heads/*
 	then
 		false
 	else
 		true
 	fi && rewound_push_failed &&
-	git-send-pack ../parent/.git +refs/heads/*:refs/heads/* &&
+	git send-pack ../parent/.git +refs/heads/*:refs/heads/* &&
 	rewound_push_succeeded
 '
 
diff --git a/t/t5401-update-hooks.sh b/t/t5401-update-hooks.sh
index 2fff300..64f66c9 100755
--- a/t/t5401-update-hooks.sh
+++ b/t/t5401-update-hooks.sh
@@ -17,7 +17,7 @@
 	commit1=$(echo modify | git commit-tree $tree1 -p $commit0) &&
 	git update-ref refs/heads/master $commit0 &&
 	git update-ref refs/heads/tofail $commit1 &&
-	git-clone ./. victim &&
+	git clone ./. victim &&
 	GIT_DIR=victim/.git git update-ref refs/heads/tofail $commit1 &&
 	git update-ref refs/heads/master $commit1 &&
 	git update-ref refs/heads/tofail $commit0
@@ -61,7 +61,8 @@
 chmod u+x victim/.git/hooks/post-update
 
 test_expect_success push '
-    ! git-send-pack --force ./victim/.git master tofail >send.out 2>send.err
+	test_must_fail git send-pack --force ./victim/.git \
+		master tofail >send.out 2>send.err
 '
 
 test_expect_success 'updated as expected' '
diff --git a/t/t5402-post-merge-hook.sh b/t/t5402-post-merge-hook.sh
index 1394047..6eb2ffd 100755
--- a/t/t5402-post-merge-hook.sh
+++ b/t/t5402-post-merge-hook.sh
@@ -16,9 +16,9 @@
 	tree1=$(git write-tree) &&
 	commit1=$(echo modify | git commit-tree $tree1 -p $commit0) &&
         git update-ref refs/heads/master $commit0 &&
-	git-clone ./. clone1 &&
+	git clone ./. clone1 &&
 	GIT_DIR=clone1/.git git update-index --add a &&
-	git-clone ./. clone2 &&
+	git clone ./. clone2 &&
 	GIT_DIR=clone2/.git git update-index --add a
 '
 
diff --git a/t/t5403-post-checkout-hook.sh b/t/t5403-post-checkout-hook.sh
index 823239a..9b2e1a9 100755
--- a/t/t5403-post-checkout-hook.sh
+++ b/t/t5403-post-checkout-hook.sh
@@ -14,8 +14,8 @@
 	 tree0=$(git write-tree) &&
 	 commit0=$(echo setup | git commit-tree $tree0) &&
         git update-ref refs/heads/master $commit0 &&
-	 git-clone ./. clone1 &&
-	 git-clone ./. clone2 &&
+	 git clone ./. clone1 &&
+	 git clone ./. clone2 &&
         GIT_DIR=clone2/.git git branch -a new2 &&
         echo Data for commit1. >clone2/b &&
 	 GIT_DIR=clone2/.git git add clone2/b &&
diff --git a/t/t5404-tracking-branches.sh b/t/t5404-tracking-branches.sh
index 64fe261..c240035 100755
--- a/t/t5404-tracking-branches.sh
+++ b/t/t5404-tracking-branches.sh
@@ -35,7 +35,9 @@
 	git commit -a -m aa-master
 '
 
-test_expect_success 'mixed-success push returns error' '! git push'
+test_expect_success 'mixed-success push returns error' '
+	test_must_fail git push
+'
 
 test_expect_success 'check tracking branches updated correctly after push' '
 	test "$(git rev-parse origin/master)" = "$(git rev-parse master)"
diff --git a/t/t5405-send-pack-rewind.sh b/t/t5405-send-pack-rewind.sh
index 86abc62..cb9aacc 100755
--- a/t/t5405-send-pack-rewind.sh
+++ b/t/t5405-send-pack-rewind.sh
@@ -12,7 +12,7 @@
 	mkdir another && (
 		cd another &&
 		git init &&
-		git fetch .. master:master
+		git fetch --update-head-ok .. master:master
 	) &&
 
 	>file2 && git add file2 && test_tick &&
diff --git a/t/t5406-remote-rejects.sh b/t/t5406-remote-rejects.sh
index 46b2cb4..59e80a5 100755
--- a/t/t5406-remote-rejects.sh
+++ b/t/t5406-remote-rejects.sh
@@ -17,7 +17,7 @@
 	git commit -a -m 2
 '
 
-test_expect_success 'push reports error' '! git push 2>stderr'
+test_expect_success 'push reports error' 'test_must_fail git push 2>stderr'
 
 test_expect_success 'individual ref reports error' 'grep rejected stderr'
 
diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh
index 140e874..448ec71 100755
--- a/t/t5500-fetch-pack.sh
+++ b/t/t5500-fetch-pack.sh
@@ -58,7 +58,7 @@
 
 	cd client
 	test_expect_success "$number pull" \
-		"git-fetch-pack -k -v .. $heads"
+		"git fetch-pack -k -v .. $heads"
 	case "$heads" in *A*) echo $ATIP > .git/refs/heads/A;; esac
 	case "$heads" in *B*) echo $BTIP > .git/refs/heads/B;; esac
 	git symbolic-ref HEAD refs/heads/`echo $heads | sed -e 's/^\(.\).*$/\1/'`
@@ -129,7 +129,7 @@
 
 pull_to_client 3rd "A" $((1*3)) # old fails
 
-test_expect_success "clone shallow" 'git-clone --depth 2 "file://$(pwd)/." shallow'
+test_expect_success "clone shallow" 'git clone --depth 2 "file://$(pwd)/." shallow'
 
 (cd shallow; git count-objects -v) > count.shallow
 
@@ -177,6 +177,6 @@
 	"test \"count: 18\" = \"$(grep count count.shallow)\""
 
 test_expect_success "pull in shallow repo with missing merge base" \
-	"(cd shallow && ! git pull --depth 4 .. A)"
+	"(cd shallow && test_must_fail git pull --depth 4 .. A)"
 
 test_done
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index 1e192a2..0103e1a 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -109,7 +109,7 @@
 
 cat > test/expect << EOF
 * remote origin
-  URL: $(pwd)/one/.git
+  URL: $(pwd)/one
   Remote branch merged with 'git pull' while on branch master
     master
   New remote branch (next fetch will store in remotes/origin)
@@ -140,7 +140,7 @@
 
 cat > test/expect << EOF
 * remote origin
-  URL: $(pwd)/one/.git
+  URL: $(pwd)/one
   Remote branch merged with 'git pull' while on branch master
     master
   Tracked remote branches
@@ -164,12 +164,12 @@
 	 git fetch origin &&
 	 git remote prune origin &&
 	 git rev-parse refs/remotes/origin/side2 &&
-	 ! git rev-parse refs/remotes/origin/side)
+	 test_must_fail git rev-parse refs/remotes/origin/side)
 '
 
 cat > test/expect << EOF
 Pruning origin
-URL: $(pwd)/one/.git
+URL: $(pwd)/one
  * [would prune] origin/side2
 EOF
 
@@ -179,7 +179,7 @@
 	(cd test &&
 	 git remote prune --dry-run origin > output &&
 	 git rev-parse refs/remotes/origin/side2 &&
-	 ! git rev-parse refs/remotes/origin/side &&
+	 test_must_fail git rev-parse refs/remotes/origin/side &&
 	(cd ../one &&
 	 git branch -m side side2) &&
 	 test_cmp expect output)
@@ -188,16 +188,16 @@
 test_expect_success 'add --mirror && prune' '
 	(mkdir mirror &&
 	 cd mirror &&
-	 git init &&
+	 git init --bare &&
 	 git remote add --mirror -f origin ../one) &&
 	(cd one &&
 	 git branch -m side2 side) &&
 	(cd mirror &&
 	 git rev-parse --verify refs/heads/side2 &&
-	 ! git rev-parse --verify refs/heads/side &&
+	 test_must_fail git rev-parse --verify refs/heads/side &&
 	 git fetch origin &&
 	 git remote prune origin &&
-	 ! git rev-parse --verify refs/heads/side2 &&
+	 test_must_fail git rev-parse --verify refs/heads/side2 &&
 	 git rev-parse --verify refs/heads/side)
 '
 
@@ -212,10 +212,10 @@
 	 git branch -m side side2) &&
 	(cd alttst &&
 	 git rev-parse --verify refs/remotes/origin/side &&
-	 ! git rev-parse --verify refs/remotes/origin/side2 &&
+	 test_must_fail git rev-parse --verify refs/remotes/origin/side2 &&
 	 git fetch alt &&
 	 git remote prune alt &&
-	 ! git rev-parse --verify refs/remotes/origin/side &&
+	 test_must_fail git rev-parse --verify refs/remotes/origin/side &&
 	 git rev-parse --verify refs/remotes/origin/side2)
 '
 
@@ -320,7 +320,7 @@
 
 test_expect_success 'reject adding remote with an invalid name' '
 
-	! git remote add some:url desired-name
+	test_must_fail git remote add some:url desired-name
 
 '
 
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index df7750f..52094e7 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -104,20 +104,20 @@
 	cd five &&
 	git init &&
 
-	! git fetch .. anno:five
+	test_must_fail git fetch .. anno:five
 
 '
 
 test_expect_success 'fetch must not resolve short remote name' '
 
 	cd "$D" &&
-	git-update-ref refs/remotes/six/HEAD HEAD
+	git update-ref refs/remotes/six/HEAD HEAD
 
 	mkdir six &&
 	cd six &&
 	git init &&
 
-	! git fetch .. six:six
+	test_must_fail git fetch .. six:six
 
 '
 
@@ -143,7 +143,7 @@
 test_expect_success 'unbundle 1' '
 	cd "$D/bundle" &&
 	git checkout -b some-branch &&
-	! git fetch "$D/bundle1" master:master
+	test_must_fail git fetch "$D/bundle1" master:master
 '
 
 test_expect_success 'bundle 1 has only 3 files ' '
@@ -236,7 +236,7 @@
 
 # the strange name is: a\!'b
 test_expect_success 'quoting of a strangely named repo' '
-	! git fetch "a\\!'\''b" > result 2>&1 &&
+	test_must_fail git fetch "a\\!'\''b" > result 2>&1 &&
 	cat result &&
 	grep "fatal: '\''a\\\\!'\''b'\''" result
 '
@@ -264,7 +264,7 @@
 		git fetch origin master &&
 		n=$(git rev-parse --verify refs/remotes/origin/master) &&
 		test "$o" = "$n" &&
-		! git rev-parse --verify refs/remotes/origin/side
+		test_must_fail git rev-parse --verify refs/remotes/origin/side
 	)
 '
 
@@ -278,7 +278,7 @@
 		git pull origin master &&
 		n=$(git rev-parse --verify refs/remotes/origin/master) &&
 		test "$o" = "$n" &&
-		! git rev-parse --verify refs/remotes/origin/side
+		test_must_fail git rev-parse --verify refs/remotes/origin/side
 	)
 '
 
@@ -303,4 +303,16 @@
 
 '
 
+test_expect_success 'refuse to fetch into the current branch' '
+
+	test_must_fail git fetch . side:master
+
+'
+
+test_expect_success 'fetch into the current branch with --update-head-ok' '
+
+	git fetch --update-head-ok . side:master
+
+'
+
 test_done
diff --git a/t/t5515-fetch-merge-logic.sh b/t/t5515-fetch-merge-logic.sh
index 3def75e..8becbc3 100755
--- a/t/t5515-fetch-merge-logic.sh
+++ b/t/t5515-fetch-merge-logic.sh
@@ -142,9 +142,12 @@
 			set x $cmd; shift
 			git symbolic-ref HEAD refs/heads/$1 ; shift
 			rm -f .git/FETCH_HEAD
-			rm -f .git/refs/heads/*
-			rm -f .git/refs/remotes/rem/*
-			rm -f .git/refs/tags/*
+			git for-each-ref \
+				refs/heads refs/remotes/rem refs/tags |
+			while read val type refname
+			do
+				git update-ref -d "$refname" "$val"
+			done
 			git fetch "$@" >/dev/null
 			cat .git/FETCH_HEAD
 		} >"$actual_f" &&
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 6805032..f9e8780 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -178,7 +178,7 @@
 	mk_test heads/master &&
 	git push testrepo : &&
 	git commit --amend -massaged &&
-	! git push testrepo &&
+	test_must_fail git push testrepo &&
 	check_push_result $the_commit heads/master &&
 	git reset --hard $the_commit
 
@@ -374,7 +374,7 @@
 
 	# Without force rewinding should fail
 	git reset --hard HEAD^ &&
-	! git push testrepo HEAD &&
+	test_must_fail git push testrepo HEAD &&
 	check_push_result $the_commit heads/local &&
 
 	# With force rewinding should succeed
@@ -437,6 +437,37 @@
 
 '
 
+test_expect_success 'push updates up-to-date local refs' '
+
+	rm -rf parent child &&
+	mkdir parent &&
+	(cd parent && git init &&
+		echo one >foo && git add foo && git commit -m one) &&
+	git clone parent child1 &&
+	git clone parent child2 &&
+	(cd child1 &&
+		echo two >foo && git commit -a -m two &&
+		git push) &&
+	(cd child2 &&
+		git pull ../child1 master &&
+		git push &&
+	test $(git rev-parse master) = $(git rev-parse remotes/origin/master))
+
+'
+
+test_expect_success 'push preserves up-to-date packed refs' '
+
+	rm -rf parent child &&
+	mkdir parent &&
+	(cd parent && git init &&
+		echo one >foo && git add foo && git commit -m one) &&
+	git clone parent child &&
+	(cd child &&
+		git push &&
+	! test -f .git/refs/remotes/origin/master)
+
+'
+
 test_expect_success 'push does not update local refs on failure' '
 
 	rm -rf parent child &&
@@ -448,7 +479,7 @@
 	git clone parent child &&
 	(cd child &&
 		echo two >foo && git commit -a -m two &&
-		! git push &&
+		test_must_fail git push &&
 		test $(git rev-parse master) != \
 			$(git rev-parse remotes/origin/master))
 
@@ -459,8 +490,58 @@
 	pwd &&
 	rm -f testrepo/.git/objects/??/* &&
 	git push testrepo :refs/heads/master &&
-	(cd testrepo && ! git rev-parse --verify refs/heads/master)
+	(cd testrepo && test_must_fail git rev-parse --verify refs/heads/master)
 
 '
 
+test_expect_success 'fetch with branches' '
+	mk_empty &&
+	git branch second $the_first_commit &&
+	git checkout second &&
+	echo ".." > testrepo/.git/branches/branch1 &&
+	(cd testrepo &&
+		git fetch branch1 &&
+		r=$(git show-ref -s --verify refs/heads/branch1) &&
+		test "z$r" = "z$the_commit" &&
+		test 1 = $(git for-each-ref refs/heads | wc -l)
+	) &&
+	git checkout master
+'
+
+test_expect_success 'fetch with branches containing #' '
+	mk_empty &&
+	echo "..#second" > testrepo/.git/branches/branch2 &&
+	(cd testrepo &&
+		git fetch branch2 &&
+		r=$(git show-ref -s --verify refs/heads/branch2) &&
+		test "z$r" = "z$the_first_commit" &&
+		test 1 = $(git for-each-ref refs/heads | wc -l)
+	) &&
+	git checkout master
+'
+
+test_expect_success 'push with branches' '
+	mk_empty &&
+	git checkout second &&
+	echo "testrepo" > .git/branches/branch1 &&
+	git push branch1 &&
+	(cd testrepo &&
+		r=$(git show-ref -s --verify refs/heads/master) &&
+		test "z$r" = "z$the_first_commit" &&
+		test 1 = $(git for-each-ref refs/heads | wc -l)
+	)
+'
+
+test_expect_success 'push with branches containing #' '
+	mk_empty &&
+	echo "testrepo#branch3" > .git/branches/branch2 &&
+	git push branch2 &&
+	(cd testrepo &&
+		r=$(git show-ref -s --verify refs/heads/branch3) &&
+		test "z$r" = "z$the_first_commit" &&
+		test 1 = $(git for-each-ref refs/heads | wc -l)
+	) &&
+	git checkout master
+'
+
 test_done
diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh
index 997b2db..725771f 100755
--- a/t/t5520-pull.sh
+++ b/t/t5520-pull.sh
@@ -29,6 +29,18 @@
 	diff file cloned/file
 '
 
+test_expect_success 'pulling into void using master:master' '
+	mkdir cloned-uho &&
+	(
+		cd cloned-uho &&
+		git init &&
+		git pull .. master:master
+	) &&
+	test -f file &&
+	test -f cloned-uho/file &&
+	test_cmp file cloned-uho/file
+'
+
 test_expect_success 'test . as a remote' '
 
 	git branch copy master &&
diff --git a/t/t5530-upload-pack-error.sh b/t/t5530-upload-pack-error.sh
index 8b05091..f5102b9 100755
--- a/t/t5530-upload-pack-error.sh
+++ b/t/t5530-upload-pack-error.sh
@@ -27,14 +27,14 @@
 '
 
 test_expect_success 'fsck fails' '
-	! git fsck
+	test_must_fail git fsck
 '
 
 test_expect_success 'upload-pack fails due to error in pack-objects' '
 
 	! echo "0032want $(git rev-parse HEAD)
 00000009done
-0000" | git-upload-pack . > /dev/null 2> output.err &&
+0000" | git upload-pack . > /dev/null 2> output.err &&
 	grep "pack-objects died" output.err
 '
 
@@ -46,13 +46,13 @@
 '
 
 test_expect_success 'fsck fails' '
-	! git fsck
+	test_must_fail git fsck
 '
 test_expect_success 'upload-pack fails due to error in rev-list' '
 
 	! echo "0032want $(git rev-parse HEAD)
 00000009done
-0000" | git-upload-pack . > /dev/null 2> output.err &&
+0000" | git upload-pack . > /dev/null 2> output.err &&
 	grep "waitpid (async) failed" output.err
 '
 
@@ -66,7 +66,7 @@
 
 test_expect_success 'fetch fails' '
 
-	! git fetch .. master
+	test_must_fail git fetch .. master
 
 '
 
diff --git a/t/t5540-http-push.sh b/t/t5540-http-push.sh
index 7372439..b0d242e 100755
--- a/t/t5540-http-push.sh
+++ b/t/t5540-http-push.sh
@@ -12,6 +12,13 @@
 ROOT_PATH="$PWD"
 LIB_HTTPD_DAV=t
 
+if git http-push > /dev/null 2>&1 || [ $? -eq 128 ]
+then
+	say "skipping test, USE_CURL_MULTI is not defined"
+	test_done
+	exit
+fi
+
 . ../lib-httpd.sh
 
 if ! start_httpd >&3 2>&4
@@ -34,26 +41,27 @@
 	git clone --bare test_repo test_repo.git &&
 	cd test_repo.git &&
 	git --bare update-server-info &&
-	chmod +x hooks/post-update &&
+	mv hooks/post-update.sample hooks/post-update &&
 	cd - &&
-	mv test_repo.git $HTTPD_DOCUMENT_ROOT_PATH
+	mv test_repo.git "$HTTPD_DOCUMENT_ROOT_PATH"
 '
-	
+
 test_expect_success 'clone remote repository' '
 	cd "$ROOT_PATH" &&
 	git clone $HTTPD_URL/test_repo.git test_repo_clone
 '
 
-test_expect_success 'push to remote repository' '
+test_expect_failure 'push to remote repository' '
 	cd "$ROOT_PATH"/test_repo_clone &&
 	: >path2 &&
 	git add path2 &&
 	test_tick &&
 	git commit -m path2 &&
-	git push
+	git push &&
+	[ -f "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/refs/heads/master" ]
 '
 
-test_expect_success 'create and delete remote branch' '
+test_expect_failure 'create and delete remote branch' '
 	cd "$ROOT_PATH"/test_repo_clone &&
 	git checkout -b dev &&
 	: >path3 &&
@@ -65,7 +73,7 @@
 	git push origin :dev &&
 	git branch -d -r origin/dev &&
 	git fetch &&
-	! git show-ref --verify refs/remotes/origin/dev
+	test_must_fail git show-ref --verify refs/remotes/origin/dev
 '
 
 stop_httpd
diff --git a/t/t5600-clone-fail-cleanup.sh b/t/t5600-clone-fail-cleanup.sh
index acf34ce..ee06d28 100755
--- a/t/t5600-clone-fail-cleanup.sh
+++ b/t/t5600-clone-fail-cleanup.sh
@@ -3,9 +3,9 @@
 # Copyright (C) 2006 Carl D. Worth <cworth@cworth.org>
 #
 
-test_description='test git-clone to cleanup after failure
+test_description='test git clone to cleanup after failure
 
-This test covers the fact that if git-clone fails, it should remove
+This test covers the fact that if git clone fails, it should remove
 the directory it created, to avoid the user having to manually
 remove the directory before attempting a clone again.'
 
@@ -13,7 +13,7 @@
 
 test_expect_success \
     'clone of non-existent source should fail' \
-    '! git-clone foo bar'
+    'test_must_fail git clone foo bar'
 
 test_expect_success \
     'failed clone should not leave a directory' \
@@ -25,15 +25,15 @@
 # clone doesn't like it if there is no HEAD. Is that a bug?
 (cd foo && touch file && git add file && git commit -m 'add file' >/dev/null 2>&1)
 
-# source repository given to git-clone should be relative to the
+# source repository given to git clone should be relative to the
 # current path not to the target dir
 test_expect_success \
     'clone of non-existent (relative to $PWD) source should fail' \
-    '! git-clone ../foo baz'
+    'test_must_fail git clone ../foo baz'
 
 test_expect_success \
     'clone should work now that source exists' \
-    'git-clone foo bar'
+    'git clone foo bar'
 
 test_expect_success \
     'successful clone must leave the directory' \
diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh
index d785b3d..78a3fa6 100755
--- a/t/t5601-clone.sh
+++ b/t/t5601-clone.sh
@@ -31,6 +31,12 @@
 
 '
 
+test_expect_success 'output from clone' '
+	rm -fr dst &&
+	git clone -n "file://$(pwd)/src" dst >output &&
+	test $(grep Initialized output | wc -l) = 1
+'
+
 test_expect_success 'clone does not keep pack' '
 
 	rm -fr dst &&
@@ -70,4 +76,53 @@
 
 '
 
+test_expect_success 'clone --mirror' '
+
+	git clone --mirror src mirror &&
+	test -f mirror/HEAD &&
+	test ! -f mirror/file &&
+	FETCH="$(cd mirror && git config remote.origin.fetch)" &&
+	test "+refs/*:refs/*" = "$FETCH" &&
+	MIRROR="$(cd mirror && git config --bool remote.origin.mirror)" &&
+	test "$MIRROR" = true
+
+'
+
+test_expect_success 'clone --bare names the local repository <name>.git' '
+
+	git clone --bare src &&
+	test -d src.git
+
+'
+
+test_expect_success 'clone --mirror does not repeat tags' '
+
+	(cd src &&
+	 git tag some-tag HEAD) &&
+	git clone --mirror src mirror2 &&
+	(cd mirror2 &&
+	 git show-ref 2> clone.err > clone.out) &&
+	test_must_fail grep Duplicate mirror2/clone.err &&
+	grep some-tag mirror2/clone.out
+
+'
+
+test_expect_success 'clone to destination with trailing /' '
+
+	git clone src target-1/ &&
+	T=$( cd target-1 && git rev-parse HEAD ) &&
+	S=$( cd src && git rev-parse HEAD ) &&
+	test "$T" = "$S"
+
+'
+
+test_expect_success 'clone to destination with extra trailing /' '
+
+	git clone src target-2/// &&
+	T=$( cd target-2 && git rev-parse HEAD ) &&
+	S=$( cd src && git rev-parse HEAD ) &&
+	test "$T" = "$S"
+
+'
+
 test_done
diff --git a/t/t5602-clone-remote-exec.sh b/t/t5602-clone-remote-exec.sh
index 8367a68..82b1d1e 100755
--- a/t/t5602-clone-remote-exec.sh
+++ b/t/t5602-clone-remote-exec.sh
@@ -11,13 +11,13 @@
 	chmod +x not_ssh
 '
 
-test_expect_success 'clone calls git-upload-pack unqualified with no -u option' '
+test_expect_success 'clone calls git upload-pack unqualified with no -u option' '
 	GIT_SSH=./not_ssh git clone localhost:/path/to/repo junk
 	echo "localhost git-upload-pack '\''/path/to/repo'\''" >expected
 	test_cmp expected not_ssh_output
 '
 
-test_expect_success 'clone calls specified git-upload-pack with -u option' '
+test_expect_success 'clone calls specified git upload-pack with -u option' '
 	GIT_SSH=./not_ssh git clone -u /something/bin/git-upload-pack localhost:/path/to/repo junk
 	echo "localhost /something/bin/git-upload-pack '\''/path/to/repo'\''" >expected
 	test_cmp expected not_ssh_output
diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh
index 9176484..86bf7e1 100755
--- a/t/t6006-rev-list-format.sh
+++ b/t/t6006-rev-list-format.sh
@@ -6,8 +6,8 @@
 
 test_tick
 test_expect_success 'setup' '
-touch foo && git add foo && git-commit -m "added foo" &&
-  echo changed >foo && git-commit -a -m "changed foo"
+touch foo && git add foo && git commit -m "added foo" &&
+  echo changed >foo && git commit -a -m "changed foo"
 '
 
 # usage: test_format name format_string <expected_output
@@ -110,7 +110,7 @@
 EOF
 test_expect_success 'setup complex body' '
 git config i18n.commitencoding iso8859-1 &&
-  echo change2 >foo && git-commit -a -F commit-msg
+  echo change2 >foo && git commit -a -F commit-msg
 '
 
 test_format complex-encoding %e <<'EOF'
@@ -139,6 +139,12 @@
 commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
 EOF
 
+test_expect_success '%ad respects --date=' '
+	echo 2005-04-07 >expect.ad-short &&
+	git log -1 --date=short --pretty=tformat:%ad >output.ad-short master &&
+	test_cmp expect.ad-short output.ad-short
+'
+
 test_expect_success 'empty email' '
 	test_tick &&
 	C=$(GIT_AUTHOR_EMAIL= git commit-tree HEAD^{tree} </dev/null) &&
diff --git a/t/t6008-rev-list-submodule.sh b/t/t6008-rev-list-submodule.sh
index 88e96fb..c4af9ca 100755
--- a/t/t6008-rev-list-submodule.sh
+++ b/t/t6008-rev-list-submodule.sh
@@ -23,7 +23,7 @@
 
 	: > super-file &&
 	git add super-file &&
-	git submodule add . sub &&
+	git submodule add "$(pwd)" sub &&
 	git symbolic-ref HEAD refs/heads/super &&
 	test_tick &&
 	git commit -m super-initial &&
diff --git a/t/t6011-rev-list-with-bad-commit.sh b/t/t6011-rev-list-with-bad-commit.sh
new file mode 100755
index 0000000..e51eb41
--- /dev/null
+++ b/t/t6011-rev-list-with-bad-commit.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+test_description='git rev-list should notice bad commits'
+
+. ./test-lib.sh
+
+# Note:
+# - compression level is set to zero to make "corruptions" easier to perform
+# - reflog is disabled to avoid extra references which would twart the test
+
+test_expect_success 'setup' \
+   '
+   git init &&
+   git config core.compression 0 &&
+   git config core.logallrefupdates false &&
+   echo "foo" > foo &&
+   git add foo &&
+   git commit -m "first commit" &&
+   echo "bar" > bar &&
+   git add bar &&
+   git commit -m "second commit" &&
+   echo "baz" > baz &&
+   git add baz &&
+   git commit -m "third commit" &&
+   echo "foo again" >> foo &&
+   git add foo &&
+   git commit -m "fourth commit" &&
+   git repack -a -f -d
+   '
+
+test_expect_success 'verify number of revisions' \
+   '
+   revs=$(git rev-list --all | wc -l) &&
+   test $revs -eq 4 &&
+   first_commit=$(git rev-parse HEAD~3)
+   '
+
+test_expect_success 'corrupt second commit object' \
+   '
+   perl -i.bak -pe "s/second commit/socond commit/" .git/objects/pack/*.pack &&
+   test_must_fail git fsck --full
+   '
+
+test_expect_success 'rev-list should fail' \
+   '
+   test_must_fail git rev-list --all > /dev/null
+   '
+
+test_expect_success 'git repack _MUST_ fail' \
+   '
+   test_must_fail git repack -a -f -d
+   '
+
+test_expect_success 'first commit is still available' \
+   '
+   git log $first_commit
+   '
+
+test_done
+
diff --git a/t/t6021-merge-criss-cross.sh b/t/t6021-merge-criss-cross.sh
index 0ab14a6..331b9b0 100755
--- a/t/t6021-merge-criss-cross.sh
+++ b/t/t6021-merge-criss-cross.sh
@@ -89,4 +89,8 @@
 
 test_expect_success 'Criss-cross merge result' 'cmp file file-expect'
 
+test_expect_success 'Criss-cross merge fails (-s resolve)' \
+'git reset --hard A^ &&
+test_must_fail git merge -s resolve -m "final merge" B'
+
 test_done
diff --git a/t/t6023-merge-file.sh b/t/t6023-merge-file.sh
index 74e9e66..f674c48 100755
--- a/t/t6023-merge-file.sh
+++ b/t/t6023-merge-file.sh
@@ -67,7 +67,7 @@
 
 cp test.txt backup.txt
 test_expect_success "merge with conflicts" \
-	"! git merge-file test.txt orig.txt new3.txt"
+	"test_must_fail git merge-file test.txt orig.txt new3.txt"
 
 cat > expect.txt << EOF
 <<<<<<< test.txt
@@ -90,7 +90,7 @@
 
 cp backup.txt test.txt
 test_expect_success "merge with conflicts, using -L" \
-	"! git merge-file -L 1 -L 2 test.txt orig.txt new3.txt"
+	"test_must_fail git merge-file -L 1 -L 2 test.txt orig.txt new3.txt"
 
 cat > expect.txt << EOF
 <<<<<<< 1
@@ -114,7 +114,7 @@
 
 sed "s/ tu / TU /" < new1.txt > new5.txt
 test_expect_success "conflict in removed tail" \
-	"! git merge-file -p orig.txt new1.txt new5.txt > out"
+	"test_must_fail git merge-file -p orig.txt new1.txt new5.txt > out"
 
 cat > expect << EOF
 Dominus regit me,
@@ -135,7 +135,8 @@
 test_expect_success "expected conflict markers" "test_cmp expect out"
 
 test_expect_success 'binary files cannot be merged' '
-	! git merge-file -p orig.txt ../test4012.png new1.txt 2> merge.err &&
+	test_must_fail git merge-file -p \
+		orig.txt ../test4012.png new1.txt 2> merge.err &&
 	grep "Cannot merge binary files" merge.err
 '
 
@@ -144,7 +145,7 @@
 
 test_expect_success 'MERGE_ZEALOUS simplifies non-conflicts' '
 
-	! git merge-file -p new6.txt new5.txt new7.txt > output &&
+	test_must_fail git merge-file -p new6.txt new5.txt new7.txt > output &&
 	test 1 = $(grep ======= < output | wc -l)
 
 '
@@ -154,7 +155,8 @@
 
 test_expect_success 'ZEALOUS_ALNUM' '
 
-	! git merge-file -p new8.txt new5.txt new9.txt > merge.out &&
+	test_must_fail git merge-file -p \
+		new8.txt new5.txt new9.txt > merge.out &&
 	test 1 = $(grep ======= < merge.out | wc -l)
 
 '
diff --git a/t/t6024-recursive-merge.sh b/t/t6024-recursive-merge.sh
index 6a6a130..802d0d0 100755
--- a/t/t6024-recursive-merge.sh
+++ b/t/t6024-recursive-merge.sh
@@ -60,7 +60,9 @@
 GIT_AUTHOR_DATE="2006-12-12 23:00:08" git commit -m F
 '
 
-test_expect_success "combined merge conflicts" "! git merge -m final G"
+test_expect_success "combined merge conflicts" "
+	test_must_fail git merge -m final G
+"
 
 cat > expect << EOF
 <<<<<<< HEAD:a1
@@ -90,7 +92,7 @@
 	printf "\0\0" > binary-file &&
 	git add binary-file &&
 	git commit -m binary2 &&
-	! git merge F > merge.out 2> merge.err &&
+	test_must_fail git merge F > merge.out 2> merge.err &&
 	grep "Cannot merge binary files: HEAD:binary-file vs. F:binary-file" \
 		merge.err
 '
diff --git a/t/t6025-merge-symlinks.sh b/t/t6025-merge-symlinks.sh
index 6004deb..53892a5 100755
--- a/t/t6025-merge-symlinks.sh
+++ b/t/t6025-merge-symlinks.sh
@@ -5,7 +5,7 @@
 
 test_description='merging symlinks on filesystem w/o symlink support.
 
-This tests that git-merge-recursive writes merge results as plain files
+This tests that git merge-recursive writes merge results as plain files
 if core.symlinks is false.'
 
 . ./test-lib.sh
@@ -15,25 +15,25 @@
 git config core.symlinks false &&
 > file &&
 git add file &&
-git-commit -m initial &&
+git commit -m initial &&
 git branch b-symlink &&
 git branch b-file &&
-l=$(echo -n file | git-hash-object -t blob -w --stdin) &&
+l=$(echo -n file | git hash-object -t blob -w --stdin) &&
 echo "120000 $l	symlink" | git update-index --index-info &&
-git-commit -m master &&
-git-checkout b-symlink &&
-l=$(echo -n file-different | git-hash-object -t blob -w --stdin) &&
+git commit -m master &&
+git checkout b-symlink &&
+l=$(echo -n file-different | git hash-object -t blob -w --stdin) &&
 echo "120000 $l	symlink" | git update-index --index-info &&
-git-commit -m b-symlink &&
-git-checkout b-file &&
+git commit -m b-symlink &&
+git checkout b-file &&
 echo plain-file > symlink &&
 git add symlink &&
-git-commit -m b-file'
+git commit -m b-file'
 
 test_expect_success \
 'merge master into b-symlink, which has a different symbolic link' '
-git-checkout b-symlink &&
-! git-merge master'
+git checkout b-symlink &&
+test_must_fail git merge master'
 
 test_expect_success \
 'the merge result must be a file' '
@@ -41,8 +41,8 @@
 
 test_expect_success \
 'merge master into b-file, which has a file instead of a symbolic link' '
-git-reset --hard && git-checkout b-file &&
-! git-merge master'
+git reset --hard && git checkout b-file &&
+test_must_fail git merge master'
 
 test_expect_success \
 'the merge result must be a file' '
@@ -50,9 +50,9 @@
 
 test_expect_success \
 'merge b-file, which has a file instead of a symbolic link, into master' '
-git-reset --hard &&
-git-checkout master &&
-! git-merge b-file'
+git reset --hard &&
+git checkout master &&
+test_must_fail git merge b-file'
 
 test_expect_success \
 'the merge result must be a file' '
diff --git a/t/t6026-merge-attr.sh b/t/t6026-merge-attr.sh
index 56fc341..4b423e9 100755
--- a/t/t6026-merge-attr.sh
+++ b/t/t6026-merge-attr.sh
@@ -106,9 +106,9 @@
 
 	cmp binary union &&
 	sed -e 1,3d text >check-1 &&
-	o=$(git-unpack-file master^:text) &&
-	a=$(git-unpack-file side^:text) &&
-	b=$(git-unpack-file master:text) &&
+	o=$(git unpack-file master^:text) &&
+	a=$(git unpack-file side^:text) &&
+	b=$(git unpack-file master:text) &&
 	sh -c "./custom-merge $o $a $b 0" &&
 	sed -e 1,3d $a >check-2 &&
 	cmp check-1 check-2 &&
@@ -133,9 +133,9 @@
 
 	cmp binary union &&
 	sed -e 1,3d text >check-1 &&
-	o=$(git-unpack-file master^:text) &&
-	a=$(git-unpack-file anchor:text) &&
-	b=$(git-unpack-file master:text) &&
+	o=$(git unpack-file master^:text) &&
+	a=$(git unpack-file anchor:text) &&
+	b=$(git unpack-file master:text) &&
 	sh -c "./custom-merge $o $a $b 0" &&
 	sed -e 1,3d $a >check-2 &&
 	cmp check-1 check-2 &&
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index 0626544..36c9a69 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh
@@ -2,7 +2,7 @@
 #
 # Copyright (c) 2007 Christian Couder
 #
-test_description='Tests git-bisect functionality'
+test_description='Tests git bisect functionality'
 
 exec </dev/null
 
@@ -23,7 +23,7 @@
     fi
 
     test_tick
-    git-commit --quiet -m "$MSG" $_file
+    git commit --quiet -m "$MSG" $_file
 }
 
 HASH1=
@@ -76,7 +76,7 @@
 	test_must_fail git bisect start foo $HASH1 -- &&
 	test_must_fail git bisect start $HASH4 $HASH1 bar -- &&
 	test -z "$(git for-each-ref "refs/bisect/*")" &&
-	test_must_fail ls .git/BISECT_* &&
+	test -z "$(ls .git/BISECT_* 2>/dev/null)" &&
 	git bisect start &&
 	test_must_fail git bisect good foo $HASH1 &&
 	test_must_fail git bisect good $HASH1 bar &&
diff --git a/t/t6040-tracking-info.sh b/t/t6040-tracking-info.sh
new file mode 100755
index 0000000..aac212e
--- /dev/null
+++ b/t/t6040-tracking-info.sh
@@ -0,0 +1,70 @@
+#!/bin/sh
+
+test_description='remote tracking stats'
+
+. ./test-lib.sh
+
+advance () {
+	echo "$1" >"$1" &&
+	git add "$1" &&
+	test_tick &&
+	git commit -m "$1"
+}
+
+test_expect_success setup '
+	for i in a b c;
+	do
+		advance $i || break
+	done &&
+	git clone . test &&
+	(
+		cd test &&
+		git checkout -b b1 origin &&
+		git reset --hard HEAD^ &&
+		advance d &&
+		git checkout -b b2 origin &&
+		git reset --hard b1 &&
+		git checkout -b b3 origin &&
+		git reset --hard HEAD^ &&
+		git checkout -b b4 origin &&
+		advance e &&
+		advance f
+	)
+'
+
+script='s/^..\(b.\)[	 0-9a-f]*\[\([^]]*\)\].*/\1 \2/p'
+cat >expect <<\EOF
+b1 ahead 1, behind 1
+b2 ahead 1, behind 1
+b3 behind 1
+b4 ahead 2
+EOF
+
+test_expect_success 'branch -v' '
+	(
+		cd test &&
+		git branch -v
+	) |
+	sed -n -e "$script" >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'checkout' '
+	(
+		cd test && git checkout b1
+	) >actual &&
+	grep -e "have 1 and 1 different" actual
+'
+
+test_expect_success 'status' '
+	(
+		cd test &&
+		git checkout b1 >/dev/null &&
+		# reports nothing to commit
+		test_must_fail git status
+	) >actual &&
+	grep -e "have 1 and 1 different" actual
+'
+
+
+test_done
diff --git a/t/t6101-rev-parse-parents.sh b/t/t6101-rev-parse-parents.sh
index 2328b69..919552a 100755
--- a/t/t6101-rev-parse-parents.sh
+++ b/t/t6101-rev-parse-parents.sh
@@ -26,8 +26,10 @@
 test_expect_success 'final^1^2' "test $(git rev-parse start2) = $(git rev-parse final^1^2)"
 test_expect_success 'final^1^2 != final^1^1' "test $(git rev-parse final^1^2) != $(git rev-parse final^1^1)"
 test_expect_success 'final^1^3 not valid' "if git rev-parse --verify final^1^3; then false; else :; fi"
-test_expect_success '--verify start2^1' '! git rev-parse --verify start2^1'
+test_expect_success '--verify start2^1' 'test_must_fail git rev-parse --verify start2^1'
 test_expect_success '--verify start2^0' 'git rev-parse --verify start2^0'
+test_expect_success 'final^1^@ = final^1^1 final^1^2' "test \"$(git rev-parse final^1^@)\" = \"$(git rev-parse final^1^1 final^1^2)\""
+test_expect_success 'final^1^! = final^1 ^final^1^1 ^final^1^2' "test \"$(git rev-parse final^1^\!)\" = \"$(git rev-parse final^1 ^final^1^1 ^final^1^2)\""
 
 test_expect_success 'repack for next test' 'git repack -a -d'
 test_expect_success 'short SHA-1 works' '
diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh
index 2fb672c..16cc635 100755
--- a/t/t6120-describe.sh
+++ b/t/t6120-describe.sh
@@ -31,57 +31,57 @@
 test_expect_success setup '
 
 	test_tick &&
-	echo one >file && git add file && git-commit -m initial &&
+	echo one >file && git add file && git commit -m initial &&
 	one=$(git rev-parse HEAD) &&
 
 	test_tick &&
-	echo two >file && git add file && git-commit -m second &&
+	echo two >file && git add file && git commit -m second &&
 	two=$(git rev-parse HEAD) &&
 
 	test_tick &&
-	echo three >file && git add file && git-commit -m third &&
+	echo three >file && git add file && git commit -m third &&
 
 	test_tick &&
-	echo A >file && git add file && git-commit -m A &&
+	echo A >file && git add file && git commit -m A &&
 	test_tick &&
-	git-tag -a -m A A &&
+	git tag -a -m A A &&
 
 	test_tick &&
-	echo c >file && git add file && git-commit -m c &&
+	echo c >file && git add file && git commit -m c &&
 	test_tick &&
-	git-tag c &&
+	git tag c &&
 
 	git reset --hard $two &&
 	test_tick &&
-	echo B >side && git add side && git-commit -m B &&
+	echo B >side && git add side && git commit -m B &&
 	test_tick &&
-	git-tag -a -m B B &&
+	git tag -a -m B B &&
 
 	test_tick &&
-	git-merge -m Merged c &&
+	git merge -m Merged c &&
 	merged=$(git rev-parse HEAD) &&
 
 	git reset --hard $two &&
 	test_tick &&
-	echo D >another && git add another && git-commit -m D &&
+	echo D >another && git add another && git commit -m D &&
 	test_tick &&
-	git-tag -a -m D D &&
+	git tag -a -m D D &&
 
 	test_tick &&
 	echo DD >another && git commit -a -m another &&
 
 	test_tick &&
-	git-tag e &&
+	git tag e &&
 
 	test_tick &&
 	echo DDD >another && git commit -a -m "yet another" &&
 
 	test_tick &&
-	git-merge -m Merged $merged &&
+	git merge -m Merged $merged &&
 
 	test_tick &&
 	echo X >file && echo X >side && git add file side &&
-	git-commit -m x
+	git commit -m x
 
 '
 
diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh
index 91ea85d..26995b3 100755
--- a/t/t6300-for-each-ref.sh
+++ b/t/t6300-for-each-ref.sh
@@ -26,45 +26,98 @@
 	git tag -a -m "Tagging at $datestamp" testtag
 '
 
-test_expect_success 'Check atom names are valid' '
-	bad=
-	for token in \
-		refname objecttype objectsize objectname tree parent \
-		numparent object type author authorname authoremail \
-		authordate committer committername committeremail \
-		committerdate tag tagger taggername taggeremail \
-		taggerdate creator creatordate subject body contents
-	do
-		git for-each-ref --format="$token=%($token)" refs/heads || {
-			bad=$token
-			break
-		}
-	done
-	test -z "$bad"
+test_atom() {
+	case "$1" in
+		head) ref=refs/heads/master ;;
+		 tag) ref=refs/tags/testtag ;;
+	esac
+	printf '%s\n' "$3" >expected
+	test_expect_${4:-success} "basic atom: $1 $2" "
+		git for-each-ref --format='%($2)' $ref >actual &&
+		test_cmp expected actual
+	"
+}
+
+test_atom head refname refs/heads/master
+test_atom head objecttype commit
+test_atom head objectsize 171
+test_atom head objectname 67a36f10722846e891fbada1ba48ed035de75581
+test_atom head tree 0e51c00fcb93dffc755546f27593d511e1bdb46f
+test_atom head parent ''
+test_atom head numparent 0
+test_atom head object ''
+test_atom head type ''
+test_atom head author 'A U Thor <author@example.com> 1151939924 +0200'
+test_atom head authorname 'A U Thor'
+test_atom head authoremail '<author@example.com>'
+test_atom head authordate 'Mon Jul 3 17:18:44 2006 +0200'
+test_atom head committer 'C O Mitter <committer@example.com> 1151939923 +0200'
+test_atom head committername 'C O Mitter'
+test_atom head committeremail '<committer@example.com>'
+test_atom head committerdate 'Mon Jul 3 17:18:43 2006 +0200'
+test_atom head tag ''
+test_atom head tagger ''
+test_atom head taggername ''
+test_atom head taggeremail ''
+test_atom head taggerdate ''
+test_atom head creator 'C O Mitter <committer@example.com> 1151939923 +0200'
+test_atom head creatordate 'Mon Jul 3 17:18:43 2006 +0200'
+test_atom head subject 'Initial'
+test_atom head body ''
+test_atom head contents 'Initial
+'
+
+test_atom tag refname refs/tags/testtag
+test_atom tag objecttype tag
+test_atom tag objectsize 154
+test_atom tag objectname 98b46b1d36e5b07909de1b3886224e3e81e87322
+test_atom tag tree ''
+test_atom tag parent ''
+test_atom tag numparent ''
+test_atom tag object '67a36f10722846e891fbada1ba48ed035de75581'
+test_atom tag type 'commit'
+test_atom tag author ''
+test_atom tag authorname ''
+test_atom tag authoremail ''
+test_atom tag authordate ''
+test_atom tag committer ''
+test_atom tag committername ''
+test_atom tag committeremail ''
+test_atom tag committerdate ''
+test_atom tag tag 'testtag'
+test_atom tag tagger 'C O Mitter <committer@example.com> 1151939925 +0200'
+test_atom tag taggername 'C O Mitter'
+test_atom tag taggeremail '<committer@example.com>'
+test_atom tag taggerdate 'Mon Jul 3 17:18:45 2006 +0200'
+test_atom tag creator 'C O Mitter <committer@example.com> 1151939925 +0200'
+test_atom tag creatordate 'Mon Jul 3 17:18:45 2006 +0200'
+test_atom tag subject 'Tagging at 1151939927'
+test_atom tag body ''
+test_atom tag contents 'Tagging at 1151939927
 '
 
 test_expect_success 'Check invalid atoms names are errors' '
-	! git-for-each-ref --format="%(INVALID)" refs/heads
+	test_must_fail git for-each-ref --format="%(INVALID)" refs/heads
 '
 
 test_expect_success 'Check format specifiers are ignored in naming date atoms' '
-	git-for-each-ref --format="%(authordate)" refs/heads &&
-	git-for-each-ref --format="%(authordate:default) %(authordate)" refs/heads &&
-	git-for-each-ref --format="%(authordate) %(authordate:default)" refs/heads &&
-	git-for-each-ref --format="%(authordate:default) %(authordate:default)" refs/heads
+	git for-each-ref --format="%(authordate)" refs/heads &&
+	git for-each-ref --format="%(authordate:default) %(authordate)" refs/heads &&
+	git for-each-ref --format="%(authordate) %(authordate:default)" refs/heads &&
+	git for-each-ref --format="%(authordate:default) %(authordate:default)" refs/heads
 '
 
 test_expect_success 'Check valid format specifiers for date fields' '
-	git-for-each-ref --format="%(authordate:default)" refs/heads &&
-	git-for-each-ref --format="%(authordate:relative)" refs/heads &&
-	git-for-each-ref --format="%(authordate:short)" refs/heads &&
-	git-for-each-ref --format="%(authordate:local)" refs/heads &&
-	git-for-each-ref --format="%(authordate:iso8601)" refs/heads &&
-	git-for-each-ref --format="%(authordate:rfc2822)" refs/heads
+	git for-each-ref --format="%(authordate:default)" refs/heads &&
+	git for-each-ref --format="%(authordate:relative)" refs/heads &&
+	git for-each-ref --format="%(authordate:short)" refs/heads &&
+	git for-each-ref --format="%(authordate:local)" refs/heads &&
+	git for-each-ref --format="%(authordate:iso8601)" refs/heads &&
+	git for-each-ref --format="%(authordate:rfc2822)" refs/heads
 '
 
 test_expect_success 'Check invalid format specifiers are errors' '
-	! git-for-each-ref --format="%(authordate:INVALID)" refs/heads
+	test_must_fail git for-each-ref --format="%(authordate:INVALID)" refs/heads
 '
 
 cat >expected <<\EOF
@@ -154,7 +207,7 @@
 EOF
 
 test_expect_success 'Verify ascending sort' '
-	git-for-each-ref --format="%(refname)" --sort=refname >actual &&
+	git for-each-ref --format="%(refname)" --sort=refname >actual &&
 	test_cmp expected actual
 '
 
@@ -165,7 +218,7 @@
 EOF
 
 test_expect_success 'Verify descending sort' '
-	git-for-each-ref --format="%(refname)" --sort=-refname >actual &&
+	git for-each-ref --format="%(refname)" --sort=-refname >actual &&
 	test_cmp expected actual
 '
 
@@ -209,4 +262,14 @@
 	"
 done
 
+test_expect_success 'an unusual tag with an incomplete line' '
+
+	git tag -m "bogo" bogo &&
+	bogo=$(git cat-file tag bogo) &&
+	bogo=$(printf "%s" "$bogo" | git mktag) &&
+	git tag -f bogo "$bogo" &&
+	git for-each-ref --format "%(body)" refs/tags/bogo
+
+'
+
 test_done
diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh
index fa382c5..66bb126 100755
--- a/t/t7001-mv.sh
+++ b/t/t7001-mv.sh
@@ -8,7 +8,7 @@
     'mkdir path0 path1 &&
      cp ../../COPYING path0/COPYING &&
      git add path0/COPYING &&
-     git-commit -m add -a'
+     git commit -m add -a'
 
 test_expect_success \
     'moving the file out of subdirectory' \
@@ -17,7 +17,7 @@
 # in path0 currently
 test_expect_success \
     'commiting the change' \
-    'cd .. && git-commit -m move-out -a'
+    'cd .. && git commit -m move-out -a'
 
 test_expect_success \
     'checking the commit' \
@@ -31,7 +31,7 @@
 # in path0 currently
 test_expect_success \
     'commiting the change' \
-    'cd .. && git-commit -m move-in -a'
+    'cd .. && git commit -m move-in -a'
 
 test_expect_success \
     'checking the commit' \
@@ -42,7 +42,7 @@
     'adding another file' \
     'cp ../../README path0/README &&
      git add path0/README &&
-     git-commit -m add2 -a'
+     git commit -m add2 -a'
 
 test_expect_success \
     'moving whole subdirectory' \
@@ -50,7 +50,7 @@
 
 test_expect_success \
     'commiting the change' \
-    'git-commit -m dir-move -a'
+    'git commit -m dir-move -a'
 
 test_expect_success \
     'checking the commit' \
@@ -69,7 +69,7 @@
 
 test_expect_success \
     'commiting the change' \
-    'git-commit -m dir-move -a'
+    'git commit -m dir-move -a'
 
 test_expect_success \
     'checking the commit' \
@@ -80,7 +80,7 @@
 
 test_expect_success \
     'do not move directory over existing directory' \
-    'mkdir path0 && mkdir path0/path2 && ! git mv path2 path0'
+    'mkdir path0 && mkdir path0/path2 && test_must_fail git mv path2 path0'
 
 test_expect_success \
     'move into "."' \
@@ -149,11 +149,65 @@
 	>sub/file &&
 	git add sub/file &&
 
-	! git mv sub "$out/out" &&
+	test_must_fail git mv sub "$out/out" &&
 	test -d sub &&
 	! test -d ../in &&
 	git ls-files --error-unmatch sub/file
 
 )'
 
+test_expect_success 'git mv should not change sha1 of moved cache entry' '
+
+	rm -fr .git &&
+	git init &&
+	echo 1 >dirty &&
+	git add dirty &&
+	entry="$(git ls-files --stage dirty | cut -f 1)"
+	git mv dirty dirty2 &&
+	[ "$entry" = "$(git ls-files --stage dirty2 | cut -f 1)" ] &&
+	echo 2 >dirty2 &&
+	git mv dirty2 dirty &&
+	[ "$entry" = "$(git ls-files --stage dirty | cut -f 1)" ]
+
+'
+
+rm -f dirty dirty2
+
+test_expect_success 'git mv should overwrite symlink to a file' '
+
+	rm -fr .git &&
+	git init &&
+	echo 1 >moved &&
+	ln -s moved symlink &&
+	git add moved symlink &&
+	test_must_fail git mv moved symlink &&
+	git mv -f moved symlink &&
+	! test -e moved &&
+	test -f symlink &&
+	test "$(cat symlink)" = 1 &&
+	git update-index --refresh &&
+	git diff-files --quiet
+
+'
+
+rm -f moved symlink
+
+test_expect_success 'git mv should overwrite file with a symlink' '
+
+	rm -fr .git &&
+	git init &&
+	echo 1 >moved &&
+	ln -s moved symlink &&
+	git add moved symlink &&
+	test_must_fail git mv symlink moved &&
+	git mv -f symlink moved &&
+	! test -e symlink &&
+	test -h moved &&
+	git update-index --refresh &&
+	git diff-files --quiet
+
+'
+
+rm -f moved symlink
+
 test_done
diff --git a/t/t7002-grep.sh b/t/t7002-grep.sh
index c8b4f65..5e359cb 100755
--- a/t/t7002-grep.sh
+++ b/t/t7002-grep.sh
@@ -22,6 +22,7 @@
 	mkdir t &&
 	echo test >t/t &&
 	git add file x y z t/t &&
+	test_tick &&
 	git commit -m initial
 '
 
@@ -113,4 +114,54 @@
 
 done
 
+test_expect_success 'log grep setup' '
+	echo a >>file &&
+	test_tick &&
+	GIT_AUTHOR_NAME="With * Asterisk" \
+	GIT_AUTHOR_EMAIL="xyzzy@frotz.com" \
+	git commit -a -m "second" &&
+
+	echo a >>file &&
+	test_tick &&
+	git commit -a -m "third"
+
+'
+
+test_expect_success 'log grep (1)' '
+	git log --author=author --pretty=tformat:%s >actual &&
+	( echo third ; echo initial ) >expect &&
+	test_cmp expect actual
+'
+
+test_expect_success 'log grep (2)' '
+	git log --author=" * " -F --pretty=tformat:%s >actual &&
+	( echo second ) >expect &&
+	test_cmp expect actual
+'
+
+test_expect_success 'log grep (3)' '
+	git log --author="^A U" --pretty=tformat:%s >actual &&
+	( echo third ; echo initial ) >expect &&
+	test_cmp expect actual
+'
+
+test_expect_success 'log grep (4)' '
+	git log --author="frotz\.com>$" --pretty=tformat:%s >actual &&
+	( echo second ) >expect &&
+	test_cmp expect actual
+'
+
+test_expect_success 'log grep (5)' '
+	git log --author=Thor -F --grep=Thu --pretty=tformat:%s >actual &&
+	( echo third ; echo initial ) >expect &&
+	test_cmp expect actual
+'
+
+test_expect_success 'log grep (6)' '
+	git log --author=-0700  --pretty=tformat:%s >actual &&
+	>expect &&
+	test_cmp expect actual
+
+'
+
 test_done
diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh
index e26f726..182aea4 100755
--- a/t/t7003-filter-branch.sh
+++ b/t/t7003-filter-branch.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-test_description='git-filter-branch'
+test_description='git filter-branch'
 . ./test-lib.sh
 
 make_commit () {
@@ -32,14 +32,22 @@
 H=$(git rev-parse H)
 
 test_expect_success 'rewrite identically' '
-	git-filter-branch branch
+	git filter-branch branch
 '
 test_expect_success 'result is really identical' '
 	test $H = $(git rev-parse HEAD)
 '
 
+test_expect_success 'rewrite bare repository identically' '
+	(git config core.bare true && cd .git && git filter-branch branch)
+'
+git config core.bare false
+test_expect_success 'result is really identical' '
+	test $H = $(git rev-parse HEAD)
+'
+
 test_expect_success 'rewrite, renaming a specific file' '
-	git-filter-branch -f --tree-filter "mv d doh || :" HEAD
+	git filter-branch -f --tree-filter "mv d doh || :" HEAD
 '
 
 test_expect_success 'test that the file was renamed' '
@@ -50,7 +58,7 @@
 '
 
 test_expect_success 'rewrite, renaming a specific directory' '
-	git-filter-branch -f --tree-filter "mv dir diroh || :" HEAD
+	git filter-branch -f --tree-filter "mv dir diroh || :" HEAD
 '
 
 test_expect_success 'test that the directory was renamed' '
@@ -65,7 +73,7 @@
 git tag oldD HEAD~4
 test_expect_success 'rewrite one branch, keeping a side branch' '
 	git branch modD oldD &&
-	git-filter-branch -f --tree-filter "mv b boh || :" D..modD
+	git filter-branch -f --tree-filter "mv b boh || :" D..modD
 '
 
 test_expect_success 'common ancestor is still common (unchanged)' '
@@ -88,7 +96,7 @@
 	test_tick &&
 	git commit -m "again not subdir" &&
 	git branch sub &&
-	git-filter-branch -f --subdirectory-filter subdir refs/heads/sub
+	git filter-branch -f --subdirectory-filter subdir refs/heads/sub
 '
 
 test_expect_success 'subdirectory filter result looks okay' '
@@ -112,7 +120,7 @@
 
 test_expect_success 'use index-filter to move into a subdirectory' '
 	git branch directorymoved &&
-	git-filter-branch -f --index-filter \
+	git filter-branch -f --index-filter \
 		 "git ls-files -s | sed \"s-\\t-&newsubdir/-\" |
 	          GIT_INDEX_FILE=\$GIT_INDEX_FILE.new \
 			git update-index --index-info &&
@@ -121,7 +129,7 @@
 
 test_expect_success 'stops when msg filter fails' '
 	old=$(git rev-parse HEAD) &&
-	test_must_fail git-filter-branch -f --msg-filter false HEAD &&
+	test_must_fail git filter-branch -f --msg-filter false HEAD &&
 	test $old = $(git rev-parse HEAD) &&
 	rm -rf .git-rewrite
 '
@@ -132,7 +140,7 @@
 	test_tick &&
 	GIT_AUTHOR_NAME="B V Uips" git commit -m bvuips &&
 	git branch preserved-author &&
-	git-filter-branch -f --msg-filter "cat; \
+	git filter-branch -f --msg-filter "cat; \
 			test \$GIT_COMMIT != $(git rev-parse master) || \
 			echo Hallo" \
 		preserved-author &&
@@ -144,7 +152,7 @@
 	test_tick &&
 	git commit -m i i &&
 	git branch removed-author &&
-	git-filter-branch -f --commit-filter "\
+	git filter-branch -f --commit-filter "\
 		if [ \"\$GIT_AUTHOR_NAME\" = \"B V Uips\" ];\
 		then\
 			skip_commit \"\$@\";
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index acddbf5..c616deb 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -3,7 +3,7 @@
 # Copyright (c) 2007 Carlos Rica
 #
 
-test_description='git-tag
+test_description='git tag
 
 Tests for operations with tags.'
 
@@ -22,25 +22,25 @@
 '
 
 test_expect_success 'listing all tags in an empty tree should output nothing' '
-	test `git-tag -l | wc -l` -eq 0 &&
-	test `git-tag | wc -l` -eq 0
+	test `git tag -l | wc -l` -eq 0 &&
+	test `git tag | wc -l` -eq 0
 '
 
 test_expect_success 'looking for a tag in an empty tree should fail' \
 	'! (tag_exists mytag)'
 
 test_expect_success 'creating a tag in an empty tree should fail' '
-	! git-tag mynotag &&
+	test_must_fail git tag mynotag &&
 	! tag_exists mynotag
 '
 
 test_expect_success 'creating a tag for HEAD in an empty tree should fail' '
-	! git-tag mytaghead HEAD &&
+	test_must_fail git tag mytaghead HEAD &&
 	! tag_exists mytaghead
 '
 
 test_expect_success 'creating a tag for an unknown revision should fail' '
-	! git-tag mytagnorev aaaaaaaaaaa &&
+	test_must_fail git tag mytagnorev aaaaaaaaaaa &&
 	! tag_exists mytagnorev
 '
 
@@ -54,48 +54,48 @@
 '
 
 test_expect_success 'listing all tags if one exists should succeed' '
-	git-tag -l &&
-	git-tag
+	git tag -l &&
+	git tag
 '
 
 test_expect_success 'listing all tags if one exists should output that tag' '
-	test `git-tag -l` = mytag &&
-	test `git-tag` = mytag
+	test `git tag -l` = mytag &&
+	test `git tag` = mytag
 '
 
 # pattern matching:
 
 test_expect_success 'listing a tag using a matching pattern should succeed' \
-	'git-tag -l mytag'
+	'git tag -l mytag'
 
 test_expect_success \
 	'listing a tag using a matching pattern should output that tag' \
-	'test `git-tag -l mytag` = mytag'
+	'test `git tag -l mytag` = mytag'
 
 # todo: git tag -l now returns always zero, when fixed, change this test
 test_expect_success \
 	'listing tags using a non-matching pattern should suceed' \
-	'git-tag -l xxx'
+	'git tag -l xxx'
 
 test_expect_success \
 	'listing tags using a non-matching pattern should output nothing' \
-	'test `git-tag -l xxx | wc -l` -eq 0'
+	'test `git tag -l xxx | wc -l` -eq 0'
 
 # special cases for creating tags:
 
 test_expect_success \
 	'trying to create a tag with the name of one existing should fail' \
-	'! git tag mytag'
+	'test_must_fail git tag mytag'
 
 test_expect_success \
 	'trying to create a tag with a non-valid name should fail' '
-	test `git-tag -l | wc -l` -eq 1 &&
-	! git tag "" &&
-	! git tag .othertag &&
-	! git tag "other tag" &&
-	! git tag "othertag^" &&
-	! git tag "other~tag" &&
-	test `git-tag -l | wc -l` -eq 1
+	test `git tag -l | wc -l` -eq 1 &&
+	test_must_fail git tag "" &&
+	test_must_fail git tag .othertag &&
+	test_must_fail git tag "other tag" &&
+	test_must_fail git tag "othertag^" &&
+	test_must_fail git tag "other~tag" &&
+	test `git tag -l | wc -l` -eq 1
 '
 
 test_expect_success 'creating a tag using HEAD directly should succeed' '
@@ -107,7 +107,7 @@
 
 test_expect_success 'trying to delete an unknown tag should fail' '
 	! tag_exists unknown-tag &&
-	! git-tag -d unknown-tag
+	test_must_fail git tag -d unknown-tag
 '
 
 cat >expect <<EOF
@@ -117,7 +117,7 @@
 test_expect_success \
 	'trying to delete tags without params should succeed and do nothing' '
 	git tag -l > actual && test_cmp expect actual &&
-	git-tag -d &&
+	git tag -d &&
 	git tag -l > actual && test_cmp expect actual
 '
 
@@ -125,7 +125,7 @@
 	'deleting two existing tags in one command should succeed' '
 	tag_exists mytag &&
 	tag_exists myhead &&
-	git-tag -d mytag myhead &&
+	git tag -d mytag myhead &&
 	! tag_exists mytag &&
 	! tag_exists myhead
 '
@@ -133,7 +133,7 @@
 test_expect_success \
 	'creating a tag with the name of another deleted one should succeed' '
 	! tag_exists mytag &&
-	git-tag mytag &&
+	git tag mytag &&
 	tag_exists mytag
 '
 
@@ -141,13 +141,13 @@
 	'trying to delete two tags, existing and not, should fail in the 2nd' '
 	tag_exists mytag &&
 	! tag_exists myhead &&
-	! git-tag -d mytag anothertag &&
+	test_must_fail git tag -d mytag anothertag &&
 	! tag_exists mytag &&
 	! tag_exists myhead
 '
 
 test_expect_success 'trying to delete an already deleted tag should fail' \
-	'! git-tag -d mytag'
+	'test_must_fail git tag -d mytag'
 
 # listing various tags with pattern matching:
 
@@ -185,7 +185,7 @@
 EOF
 test_expect_success \
 	'listing tags with substring as pattern must print those matching' '
-	git-tag -l "*a*" > actual &&
+	git tag -l "*a*" > actual &&
 	test_cmp expect actual
 '
 
@@ -195,7 +195,7 @@
 EOF
 test_expect_success \
 	'listing tags with a suffix as pattern must print those matching' '
-	git-tag -l "*.1" > actual &&
+	git tag -l "*.1" > actual &&
 	test_cmp expect actual
 '
 
@@ -205,7 +205,7 @@
 EOF
 test_expect_success \
 	'listing tags with a prefix as pattern must print those matching' '
-	git-tag -l "t21*" > actual &&
+	git tag -l "t21*" > actual &&
 	test_cmp expect actual
 '
 
@@ -214,7 +214,7 @@
 EOF
 test_expect_success \
 	'listing tags using a name as pattern must print that one matching' '
-	git-tag -l a1 > actual &&
+	git tag -l a1 > actual &&
 	test_cmp expect actual
 '
 
@@ -223,7 +223,7 @@
 EOF
 test_expect_success \
 	'listing tags using a name as pattern must print that one matching' '
-	git-tag -l v1.0 > actual &&
+	git tag -l v1.0 > actual &&
 	test_cmp expect actual
 '
 
@@ -233,14 +233,14 @@
 EOF
 test_expect_success \
 	'listing tags with ? in the pattern should print those matching' '
-	git-tag -l "v1.?.?" > actual &&
+	git tag -l "v1.?.?" > actual &&
 	test_cmp expect actual
 '
 
 >expect
 test_expect_success \
 	'listing tags using v.* should print nothing because none have v.' '
-	git-tag -l "v.*" > actual &&
+	git tag -l "v.*" > actual &&
 	test_cmp expect actual
 '
 
@@ -252,7 +252,7 @@
 EOF
 test_expect_success \
 	'listing tags using v* should print only those having v' '
-	git-tag -l "v*" > actual &&
+	git tag -l "v*" > actual &&
 	test_cmp expect actual
 '
 
@@ -260,21 +260,21 @@
 
 test_expect_success \
 	'a non-annotated tag created without parameters should point to HEAD' '
-	git-tag non-annotated-tag &&
+	git tag non-annotated-tag &&
 	test $(git cat-file -t non-annotated-tag) = commit &&
 	test $(git rev-parse non-annotated-tag) = $(git rev-parse HEAD)
 '
 
 test_expect_success 'trying to verify an unknown tag should fail' \
-	'! git-tag -v unknown-tag'
+	'test_must_fail git tag -v unknown-tag'
 
 test_expect_success \
 	'trying to verify a non-annotated and non-signed tag should fail' \
-	'! git-tag -v non-annotated-tag'
+	'test_must_fail git tag -v non-annotated-tag'
 
 test_expect_success \
 	'trying to verify many non-annotated or unknown tags, should fail' \
-	'! git-tag -v unknown-tag1 non-annotated-tag unknown-tag2'
+	'test_must_fail git tag -v unknown-tag1 non-annotated-tag unknown-tag2'
 
 # creating annotated tags:
 
@@ -300,7 +300,7 @@
 echo "A message" >>expect
 test_expect_success \
 	'creating an annotated tag with -m message should succeed' '
-	git-tag -m "A message" annotated-tag &&
+	git tag -m "A message" annotated-tag &&
 	get_tag_msg annotated-tag >actual &&
 	test_cmp expect actual
 '
@@ -313,7 +313,7 @@
 cat msgfile >>expect
 test_expect_success \
 	'creating an annotated tag with -F messagefile should succeed' '
-	git-tag -F msgfile file-annotated-tag &&
+	git tag -F msgfile file-annotated-tag &&
 	get_tag_msg file-annotated-tag >actual &&
 	test_cmp expect actual
 '
@@ -325,7 +325,7 @@
 get_tag_header stdin-annotated-tag $commit commit $time >expect
 cat inputmsg >>expect
 test_expect_success 'creating an annotated tag with -F - should succeed' '
-	git-tag -F - stdin-annotated-tag <inputmsg &&
+	git tag -F - stdin-annotated-tag <inputmsg &&
 	get_tag_msg stdin-annotated-tag >actual &&
 	test_cmp expect actual
 '
@@ -334,7 +334,7 @@
 	'trying to create a tag with a non-existing -F file should fail' '
 	! test -f nonexistingfile &&
 	! tag_exists notag &&
-	! git-tag -F nonexistingfile notag &&
+	test_must_fail git tag -F nonexistingfile notag &&
 	! tag_exists notag
 '
 
@@ -343,11 +343,12 @@
 	echo "message file 1" >msgfile1 &&
 	echo "message file 2" >msgfile2 &&
 	! tag_exists msgtag &&
-	! git-tag -m "message 1" -F msgfile1 msgtag &&
+	test_must_fail git tag -m "message 1" -F msgfile1 msgtag &&
 	! tag_exists msgtag &&
-	! git-tag -F msgfile1 -m "message 1" msgtag &&
+	test_must_fail git tag -F msgfile1 -m "message 1" msgtag &&
 	! tag_exists msgtag &&
-	! git-tag -m "message 1" -F msgfile1 -m "message 2" msgtag &&
+	test_must_fail git tag -m "message 1" -F msgfile1 \
+		-m "message 2" msgtag &&
 	! tag_exists msgtag
 '
 
@@ -356,7 +357,7 @@
 get_tag_header empty-annotated-tag $commit commit $time >expect
 test_expect_success \
 	'creating a tag with an empty -m message should succeed' '
-	git-tag -m "" empty-annotated-tag &&
+	git tag -m "" empty-annotated-tag &&
 	get_tag_msg empty-annotated-tag >actual &&
 	test_cmp expect actual
 '
@@ -365,7 +366,7 @@
 get_tag_header emptyfile-annotated-tag $commit commit $time >expect
 test_expect_success \
 	'creating a tag with an empty -F messagefile should succeed' '
-	git-tag -F emptyfile emptyfile-annotated-tag &&
+	git tag -F emptyfile emptyfile-annotated-tag &&
 	get_tag_msg emptyfile-annotated-tag >actual &&
 	test_cmp expect actual
 '
@@ -386,7 +387,7 @@
 EOF
 test_expect_success \
 	'extra blanks in the message for an annotated tag should be removed' '
-	git-tag -F blanksfile blanks-annotated-tag &&
+	git tag -F blanksfile blanks-annotated-tag &&
 	get_tag_msg blanks-annotated-tag >actual &&
 	test_cmp expect actual
 '
@@ -394,7 +395,7 @@
 get_tag_header blank-annotated-tag $commit commit $time >expect
 test_expect_success \
 	'creating a tag with blank -m message with spaces should succeed' '
-	git-tag -m "     " blank-annotated-tag &&
+	git tag -m "     " blank-annotated-tag &&
 	get_tag_msg blank-annotated-tag >actual &&
 	test_cmp expect actual
 '
@@ -405,7 +406,7 @@
 get_tag_header blankfile-annotated-tag $commit commit $time >expect
 test_expect_success \
 	'creating a tag with blank -F messagefile with spaces should succeed' '
-	git-tag -F blankfile blankfile-annotated-tag &&
+	git tag -F blankfile blankfile-annotated-tag &&
 	get_tag_msg blankfile-annotated-tag >actual &&
 	test_cmp expect actual
 '
@@ -414,7 +415,7 @@
 get_tag_header blanknonlfile-annotated-tag $commit commit $time >expect
 test_expect_success \
 	'creating a tag with -F file of spaces and no newline should succeed' '
-	git-tag -F blanknonlfile blanknonlfile-annotated-tag &&
+	git tag -F blanknonlfile blanknonlfile-annotated-tag &&
 	get_tag_msg blanknonlfile-annotated-tag >actual &&
 	test_cmp expect actual
 '
@@ -449,7 +450,7 @@
 EOF
 test_expect_success \
 	'creating a tag using a -F messagefile with #comments should succeed' '
-	git-tag -F commentsfile comments-annotated-tag &&
+	git tag -F commentsfile comments-annotated-tag &&
 	get_tag_msg comments-annotated-tag >actual &&
 	test_cmp expect actual
 '
@@ -457,7 +458,7 @@
 get_tag_header comment-annotated-tag $commit commit $time >expect
 test_expect_success \
 	'creating a tag with a #comment in the -m message should succeed' '
-	git-tag -m "#comment" comment-annotated-tag &&
+	git tag -m "#comment" comment-annotated-tag &&
 	get_tag_msg comment-annotated-tag >actual &&
 	test_cmp expect actual
 '
@@ -468,7 +469,7 @@
 get_tag_header commentfile-annotated-tag $commit commit $time >expect
 test_expect_success \
 	'creating a tag with #comments in the -F messagefile should succeed' '
-	git-tag -F commentfile commentfile-annotated-tag &&
+	git tag -F commentfile commentfile-annotated-tag &&
 	get_tag_msg commentfile-annotated-tag >actual &&
 	test_cmp expect actual
 '
@@ -477,7 +478,7 @@
 get_tag_header commentnonlfile-annotated-tag $commit commit $time >expect
 test_expect_success \
 	'creating a tag with a file of #comment and no newline should succeed' '
-	git-tag -F commentnonlfile commentnonlfile-annotated-tag &&
+	git tag -F commentnonlfile commentnonlfile-annotated-tag &&
 	get_tag_msg commentnonlfile-annotated-tag >actual &&
 	test_cmp expect actual
 '
@@ -486,51 +487,51 @@
 
 test_expect_success \
 	'listing the one-line message of a non-signed tag should succeed' '
-	git-tag -m "A msg" tag-one-line &&
+	git tag -m "A msg" tag-one-line &&
 
 	echo "tag-one-line" >expect &&
-	git-tag -l | grep "^tag-one-line" >actual &&
+	git tag -l | grep "^tag-one-line" >actual &&
 	test_cmp expect actual &&
-	git-tag -n0 -l | grep "^tag-one-line" >actual &&
+	git tag -n0 -l | grep "^tag-one-line" >actual &&
 	test_cmp expect actual &&
-	git-tag -n0 -l tag-one-line >actual &&
+	git tag -n0 -l tag-one-line >actual &&
 	test_cmp expect actual &&
 
 	echo "tag-one-line    A msg" >expect &&
-	git-tag -n1 -l | grep "^tag-one-line" >actual &&
+	git tag -n1 -l | grep "^tag-one-line" >actual &&
 	test_cmp expect actual &&
-	git-tag -n -l | grep "^tag-one-line" >actual &&
+	git tag -n -l | grep "^tag-one-line" >actual &&
 	test_cmp expect actual &&
-	git-tag -n1 -l tag-one-line >actual &&
+	git tag -n1 -l tag-one-line >actual &&
 	test_cmp expect actual &&
-	git-tag -n2 -l tag-one-line >actual &&
+	git tag -n2 -l tag-one-line >actual &&
 	test_cmp expect actual &&
-	git-tag -n999 -l tag-one-line >actual &&
+	git tag -n999 -l tag-one-line >actual &&
 	test_cmp expect actual
 '
 
 test_expect_success \
 	'listing the zero-lines message of a non-signed tag should succeed' '
-	git-tag -m "" tag-zero-lines &&
+	git tag -m "" tag-zero-lines &&
 
 	echo "tag-zero-lines" >expect &&
-	git-tag -l | grep "^tag-zero-lines" >actual &&
+	git tag -l | grep "^tag-zero-lines" >actual &&
 	test_cmp expect actual &&
-	git-tag -n0 -l | grep "^tag-zero-lines" >actual &&
+	git tag -n0 -l | grep "^tag-zero-lines" >actual &&
 	test_cmp expect actual &&
-	git-tag -n0 -l tag-zero-lines >actual &&
+	git tag -n0 -l tag-zero-lines >actual &&
 	test_cmp expect actual &&
 
 	echo "tag-zero-lines  " >expect &&
-	git-tag -n1 -l | grep "^tag-zero-lines" >actual &&
+	git tag -n1 -l | grep "^tag-zero-lines" >actual &&
 	test_cmp expect actual &&
-	git-tag -n -l | grep "^tag-zero-lines" >actual &&
+	git tag -n -l | grep "^tag-zero-lines" >actual &&
 	test_cmp expect actual &&
-	git-tag -n1 -l tag-zero-lines >actual &&
+	git tag -n1 -l tag-zero-lines >actual &&
 	test_cmp expect actual &&
-	git-tag -n2 -l tag-zero-lines >actual &&
+	git tag -n2 -l tag-zero-lines >actual &&
 	test_cmp expect actual &&
-	git-tag -n999 -l tag-zero-lines >actual &&
+	git tag -n999 -l tag-zero-lines >actual &&
 	test_cmp expect actual
 '
 
@@ -539,42 +540,42 @@
 echo 'tag line three' >>annotagmsg
 test_expect_success \
 	'listing many message lines of a non-signed tag should succeed' '
-	git-tag -F annotagmsg tag-lines &&
+	git tag -F annotagmsg tag-lines &&
 
 	echo "tag-lines" >expect &&
-	git-tag -l | grep "^tag-lines" >actual &&
+	git tag -l | grep "^tag-lines" >actual &&
 	test_cmp expect actual &&
-	git-tag -n0 -l | grep "^tag-lines" >actual &&
+	git tag -n0 -l | grep "^tag-lines" >actual &&
 	test_cmp expect actual &&
-	git-tag -n0 -l tag-lines >actual &&
+	git tag -n0 -l tag-lines >actual &&
 	test_cmp expect actual &&
 
 	echo "tag-lines       tag line one" >expect &&
-	git-tag -n1 -l | grep "^tag-lines" >actual &&
+	git tag -n1 -l | grep "^tag-lines" >actual &&
 	test_cmp expect actual &&
-	git-tag -n -l | grep "^tag-lines" >actual &&
+	git tag -n -l | grep "^tag-lines" >actual &&
 	test_cmp expect actual &&
-	git-tag -n1 -l tag-lines >actual &&
+	git tag -n1 -l tag-lines >actual &&
 	test_cmp expect actual &&
 
 	echo "    tag line two" >>expect &&
-	git-tag -n2 -l | grep "^ *tag.line" >actual &&
+	git tag -n2 -l | grep "^ *tag.line" >actual &&
 	test_cmp expect actual &&
-	git-tag -n2 -l tag-lines >actual &&
+	git tag -n2 -l tag-lines >actual &&
 	test_cmp expect actual &&
 
 	echo "    tag line three" >>expect &&
-	git-tag -n3 -l | grep "^ *tag.line" >actual &&
+	git tag -n3 -l | grep "^ *tag.line" >actual &&
 	test_cmp expect actual &&
-	git-tag -n3 -l tag-lines >actual &&
+	git tag -n3 -l tag-lines >actual &&
 	test_cmp expect actual &&
-	git-tag -n4 -l | grep "^ *tag.line" >actual &&
+	git tag -n4 -l | grep "^ *tag.line" >actual &&
 	test_cmp expect actual &&
-	git-tag -n4 -l tag-lines >actual &&
+	git tag -n4 -l tag-lines >actual &&
 	test_cmp expect actual &&
-	git-tag -n99 -l | grep "^ *tag.line" >actual &&
+	git tag -n99 -l | grep "^ *tag.line" >actual &&
 	test_cmp expect actual &&
-	git-tag -n99 -l tag-lines >actual &&
+	git tag -n99 -l tag-lines >actual &&
 	test_cmp expect actual
 '
 
@@ -591,19 +592,19 @@
 test_expect_success \
 	'trying to verify an annotated non-signed tag should fail' '
 	tag_exists annotated-tag &&
-	! git-tag -v annotated-tag
+	test_must_fail git tag -v annotated-tag
 '
 
 test_expect_success \
 	'trying to verify a file-annotated non-signed tag should fail' '
 	tag_exists file-annotated-tag &&
-	! git-tag -v file-annotated-tag
+	test_must_fail git tag -v file-annotated-tag
 '
 
 test_expect_success \
 	'trying to verify two annotated non-signed tags should fail' '
 	tag_exists annotated-tag file-annotated-tag &&
-	! git-tag -v annotated-tag file-annotated-tag
+	test_must_fail git tag -v annotated-tag file-annotated-tag
 '
 
 # creating and verifying signed tags:
@@ -633,7 +634,7 @@
 echo 'A signed tag message' >>expect
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
 test_expect_success 'creating a signed tag with -m message should succeed' '
-	git-tag -s -m "A signed tag message" signed-tag &&
+	git tag -s -m "A signed tag message" signed-tag &&
 	get_tag_msg signed-tag >actual &&
 	test_cmp expect actual
 '
@@ -651,13 +652,14 @@
 
 test_expect_success 'sign with an unknown id (1)' '
 
-	! git tag -u author@example.com -m "Another message" o-signed-tag
+	test_must_fail git tag -u author@example.com \
+		-m "Another message" o-signed-tag
 
 '
 
 test_expect_success 'sign with an unknown id (2)' '
 
-	! git tag -u DEADBEEF -m "Another message" o-signed-tag
+	test_must_fail git tag -u DEADBEEF -m "Another message" o-signed-tag
 
 '
 
@@ -673,7 +675,7 @@
 ./fakeeditor >>expect
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
 test_expect_success '-u implies signed tag' '
-	GIT_EDITOR=./fakeeditor git-tag -u CDDE430D implied-sign &&
+	GIT_EDITOR=./fakeeditor git tag -u CDDE430D implied-sign &&
 	get_tag_msg implied-sign >actual &&
 	test_cmp expect actual
 '
@@ -687,7 +689,7 @@
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
 test_expect_success \
 	'creating a signed tag with -F messagefile should succeed' '
-	git-tag -s -F sigmsgfile file-signed-tag &&
+	git tag -s -F sigmsgfile file-signed-tag &&
 	get_tag_msg file-signed-tag >actual &&
 	test_cmp expect actual
 '
@@ -700,7 +702,7 @@
 cat siginputmsg >>expect
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
 test_expect_success 'creating a signed tag with -F - should succeed' '
-	git-tag -s -F - stdin-signed-tag <siginputmsg &&
+	git tag -s -F - stdin-signed-tag <siginputmsg &&
 	get_tag_msg stdin-signed-tag >actual &&
 	test_cmp expect actual
 '
@@ -709,7 +711,7 @@
 ./fakeeditor >>expect
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
 test_expect_success '-s implies annotated tag' '
-	GIT_EDITOR=./fakeeditor git-tag -s implied-annotate &&
+	GIT_EDITOR=./fakeeditor git tag -s implied-annotate &&
 	get_tag_msg implied-annotate >actual &&
 	test_cmp expect actual
 '
@@ -718,22 +720,23 @@
 	'trying to create a signed tag with non-existing -F file should fail' '
 	! test -f nonexistingfile &&
 	! tag_exists nosigtag &&
-	! git-tag -s -F nonexistingfile nosigtag &&
+	test_must_fail git tag -s -F nonexistingfile nosigtag &&
 	! tag_exists nosigtag
 '
 
 test_expect_success 'verifying a signed tag should succeed' \
-	'git-tag -v signed-tag'
+	'git tag -v signed-tag'
 
 test_expect_success 'verifying two signed tags in one command should succeed' \
-	'git-tag -v signed-tag file-signed-tag'
+	'git tag -v signed-tag file-signed-tag'
 
 test_expect_success \
 	'verifying many signed and non-signed tags should fail' '
-	! git-tag -v signed-tag annotated-tag &&
-	! git-tag -v file-annotated-tag file-signed-tag &&
-	! git-tag -v annotated-tag file-signed-tag file-annotated-tag &&
-	! git-tag -v signed-tag annotated-tag file-signed-tag
+	test_must_fail git tag -v signed-tag annotated-tag &&
+	test_must_fail git tag -v file-annotated-tag file-signed-tag &&
+	test_must_fail git tag -v annotated-tag \
+		file-signed-tag file-annotated-tag &&
+	test_must_fail git tag -v signed-tag annotated-tag file-signed-tag
 '
 
 test_expect_success 'verifying a forged tag should fail' '
@@ -741,7 +744,7 @@
 		sed -e "s/signed-tag/forged-tag/" |
 		git mktag) &&
 	git tag forged-tag $forged &&
-	! git-tag -v forged-tag
+	test_must_fail git tag -v forged-tag
 '
 
 # blank and empty messages for signed tags:
@@ -750,10 +753,10 @@
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
 test_expect_success \
 	'creating a signed tag with an empty -m message should succeed' '
-	git-tag -s -m "" empty-signed-tag &&
+	git tag -s -m "" empty-signed-tag &&
 	get_tag_msg empty-signed-tag >actual &&
 	test_cmp expect actual &&
-	git-tag -v empty-signed-tag
+	git tag -v empty-signed-tag
 '
 
 >sigemptyfile
@@ -761,10 +764,10 @@
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
 test_expect_success \
 	'creating a signed tag with an empty -F messagefile should succeed' '
-	git-tag -s -F sigemptyfile emptyfile-signed-tag &&
+	git tag -s -F sigemptyfile emptyfile-signed-tag &&
 	get_tag_msg emptyfile-signed-tag >actual &&
 	test_cmp expect actual &&
-	git-tag -v emptyfile-signed-tag
+	git tag -v emptyfile-signed-tag
 '
 
 printf '\n\n  \n\t\nLeading blank lines\n' > sigblanksfile
@@ -784,20 +787,20 @@
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
 test_expect_success \
 	'extra blanks in the message for a signed tag should be removed' '
-	git-tag -s -F sigblanksfile blanks-signed-tag &&
+	git tag -s -F sigblanksfile blanks-signed-tag &&
 	get_tag_msg blanks-signed-tag >actual &&
 	test_cmp expect actual &&
-	git-tag -v blanks-signed-tag
+	git tag -v blanks-signed-tag
 '
 
 get_tag_header blank-signed-tag $commit commit $time >expect
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
 test_expect_success \
 	'creating a signed tag with a blank -m message should succeed' '
-	git-tag -s -m "     " blank-signed-tag &&
+	git tag -s -m "     " blank-signed-tag &&
 	get_tag_msg blank-signed-tag >actual &&
 	test_cmp expect actual &&
-	git-tag -v blank-signed-tag
+	git tag -v blank-signed-tag
 '
 
 echo '     ' >sigblankfile
@@ -807,10 +810,10 @@
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
 test_expect_success \
 	'creating a signed tag with blank -F file with spaces should succeed' '
-	git-tag -s -F sigblankfile blankfile-signed-tag &&
+	git tag -s -F sigblankfile blankfile-signed-tag &&
 	get_tag_msg blankfile-signed-tag >actual &&
 	test_cmp expect actual &&
-	git-tag -v blankfile-signed-tag
+	git tag -v blankfile-signed-tag
 '
 
 printf '      ' >sigblanknonlfile
@@ -818,10 +821,10 @@
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
 test_expect_success \
 	'creating a signed tag with spaces and no newline should succeed' '
-	git-tag -s -F sigblanknonlfile blanknonlfile-signed-tag &&
+	git tag -s -F sigblanknonlfile blanknonlfile-signed-tag &&
 	get_tag_msg blanknonlfile-signed-tag >actual &&
 	test_cmp expect actual &&
-	git-tag -v signed-tag
+	git tag -v signed-tag
 '
 
 # messages with commented lines for signed tags:
@@ -855,20 +858,20 @@
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
 test_expect_success \
 	'creating a signed tag with a -F file with #comments should succeed' '
-	git-tag -s -F sigcommentsfile comments-signed-tag &&
+	git tag -s -F sigcommentsfile comments-signed-tag &&
 	get_tag_msg comments-signed-tag >actual &&
 	test_cmp expect actual &&
-	git-tag -v comments-signed-tag
+	git tag -v comments-signed-tag
 '
 
 get_tag_header comment-signed-tag $commit commit $time >expect
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
 test_expect_success \
 	'creating a signed tag with #commented -m message should succeed' '
-	git-tag -s -m "#comment" comment-signed-tag &&
+	git tag -s -m "#comment" comment-signed-tag &&
 	get_tag_msg comment-signed-tag >actual &&
 	test_cmp expect actual &&
-	git-tag -v comment-signed-tag
+	git tag -v comment-signed-tag
 '
 
 echo '#comment' >sigcommentfile
@@ -878,10 +881,10 @@
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
 test_expect_success \
 	'creating a signed tag with #commented -F messagefile should succeed' '
-	git-tag -s -F sigcommentfile commentfile-signed-tag &&
+	git tag -s -F sigcommentfile commentfile-signed-tag &&
 	get_tag_msg commentfile-signed-tag >actual &&
 	test_cmp expect actual &&
-	git-tag -v commentfile-signed-tag
+	git tag -v commentfile-signed-tag
 '
 
 printf '#comment' >sigcommentnonlfile
@@ -889,61 +892,61 @@
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
 test_expect_success \
 	'creating a signed tag with a #comment and no newline should succeed' '
-	git-tag -s -F sigcommentnonlfile commentnonlfile-signed-tag &&
+	git tag -s -F sigcommentnonlfile commentnonlfile-signed-tag &&
 	get_tag_msg commentnonlfile-signed-tag >actual &&
 	test_cmp expect actual &&
-	git-tag -v commentnonlfile-signed-tag
+	git tag -v commentnonlfile-signed-tag
 '
 
 # listing messages for signed tags:
 
 test_expect_success \
 	'listing the one-line message of a signed tag should succeed' '
-	git-tag -s -m "A message line signed" stag-one-line &&
+	git tag -s -m "A message line signed" stag-one-line &&
 
 	echo "stag-one-line" >expect &&
-	git-tag -l | grep "^stag-one-line" >actual &&
+	git tag -l | grep "^stag-one-line" >actual &&
 	test_cmp expect actual &&
-	git-tag -n0 -l | grep "^stag-one-line" >actual &&
+	git tag -n0 -l | grep "^stag-one-line" >actual &&
 	test_cmp expect actual &&
-	git-tag -n0 -l stag-one-line >actual &&
+	git tag -n0 -l stag-one-line >actual &&
 	test_cmp expect actual &&
 
 	echo "stag-one-line   A message line signed" >expect &&
-	git-tag -n1 -l | grep "^stag-one-line" >actual &&
+	git tag -n1 -l | grep "^stag-one-line" >actual &&
 	test_cmp expect actual &&
-	git-tag -n -l | grep "^stag-one-line" >actual &&
+	git tag -n -l | grep "^stag-one-line" >actual &&
 	test_cmp expect actual &&
-	git-tag -n1 -l stag-one-line >actual &&
+	git tag -n1 -l stag-one-line >actual &&
 	test_cmp expect actual &&
-	git-tag -n2 -l stag-one-line >actual &&
+	git tag -n2 -l stag-one-line >actual &&
 	test_cmp expect actual &&
-	git-tag -n999 -l stag-one-line >actual &&
+	git tag -n999 -l stag-one-line >actual &&
 	test_cmp expect actual
 '
 
 test_expect_success \
 	'listing the zero-lines message of a signed tag should succeed' '
-	git-tag -s -m "" stag-zero-lines &&
+	git tag -s -m "" stag-zero-lines &&
 
 	echo "stag-zero-lines" >expect &&
-	git-tag -l | grep "^stag-zero-lines" >actual &&
+	git tag -l | grep "^stag-zero-lines" >actual &&
 	test_cmp expect actual &&
-	git-tag -n0 -l | grep "^stag-zero-lines" >actual &&
+	git tag -n0 -l | grep "^stag-zero-lines" >actual &&
 	test_cmp expect actual &&
-	git-tag -n0 -l stag-zero-lines >actual &&
+	git tag -n0 -l stag-zero-lines >actual &&
 	test_cmp expect actual &&
 
 	echo "stag-zero-lines " >expect &&
-	git-tag -n1 -l | grep "^stag-zero-lines" >actual &&
+	git tag -n1 -l | grep "^stag-zero-lines" >actual &&
 	test_cmp expect actual &&
-	git-tag -n -l | grep "^stag-zero-lines" >actual &&
+	git tag -n -l | grep "^stag-zero-lines" >actual &&
 	test_cmp expect actual &&
-	git-tag -n1 -l stag-zero-lines >actual &&
+	git tag -n1 -l stag-zero-lines >actual &&
 	test_cmp expect actual &&
-	git-tag -n2 -l stag-zero-lines >actual &&
+	git tag -n2 -l stag-zero-lines >actual &&
 	test_cmp expect actual &&
-	git-tag -n999 -l stag-zero-lines >actual &&
+	git tag -n999 -l stag-zero-lines >actual &&
 	test_cmp expect actual
 '
 
@@ -952,42 +955,42 @@
 echo 'stag line three' >>sigtagmsg
 test_expect_success \
 	'listing many message lines of a signed tag should succeed' '
-	git-tag -s -F sigtagmsg stag-lines &&
+	git tag -s -F sigtagmsg stag-lines &&
 
 	echo "stag-lines" >expect &&
-	git-tag -l | grep "^stag-lines" >actual &&
+	git tag -l | grep "^stag-lines" >actual &&
 	test_cmp expect actual &&
-	git-tag -n0 -l | grep "^stag-lines" >actual &&
+	git tag -n0 -l | grep "^stag-lines" >actual &&
 	test_cmp expect actual &&
-	git-tag -n0 -l stag-lines >actual &&
+	git tag -n0 -l stag-lines >actual &&
 	test_cmp expect actual &&
 
 	echo "stag-lines      stag line one" >expect &&
-	git-tag -n1 -l | grep "^stag-lines" >actual &&
+	git tag -n1 -l | grep "^stag-lines" >actual &&
 	test_cmp expect actual &&
-	git-tag -n -l | grep "^stag-lines" >actual &&
+	git tag -n -l | grep "^stag-lines" >actual &&
 	test_cmp expect actual &&
-	git-tag -n1 -l stag-lines >actual &&
+	git tag -n1 -l stag-lines >actual &&
 	test_cmp expect actual &&
 
 	echo "    stag line two" >>expect &&
-	git-tag -n2 -l | grep "^ *stag.line" >actual &&
+	git tag -n2 -l | grep "^ *stag.line" >actual &&
 	test_cmp expect actual &&
-	git-tag -n2 -l stag-lines >actual &&
+	git tag -n2 -l stag-lines >actual &&
 	test_cmp expect actual &&
 
 	echo "    stag line three" >>expect &&
-	git-tag -n3 -l | grep "^ *stag.line" >actual &&
+	git tag -n3 -l | grep "^ *stag.line" >actual &&
 	test_cmp expect actual &&
-	git-tag -n3 -l stag-lines >actual &&
+	git tag -n3 -l stag-lines >actual &&
 	test_cmp expect actual &&
-	git-tag -n4 -l | grep "^ *stag.line" >actual &&
+	git tag -n4 -l | grep "^ *stag.line" >actual &&
 	test_cmp expect actual &&
-	git-tag -n4 -l stag-lines >actual &&
+	git tag -n4 -l stag-lines >actual &&
 	test_cmp expect actual &&
-	git-tag -n99 -l | grep "^ *stag.line" >actual &&
+	git tag -n99 -l | grep "^ *stag.line" >actual &&
 	test_cmp expect actual &&
-	git-tag -n99 -l stag-lines >actual &&
+	git tag -n99 -l stag-lines >actual &&
 	test_cmp expect actual
 '
 
@@ -1002,7 +1005,7 @@
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
 test_expect_success \
 	'creating a signed tag pointing to a tree should succeed' '
-	git-tag -s -m "A message for a tree" tree-signed-tag HEAD^{tree} &&
+	git tag -s -m "A message for a tree" tree-signed-tag HEAD^{tree} &&
 	get_tag_msg tree-signed-tag >actual &&
 	test_cmp expect actual
 '
@@ -1012,7 +1015,7 @@
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
 test_expect_success \
 	'creating a signed tag pointing to a blob should succeed' '
-	git-tag -s -m "A message for a blob" blob-signed-tag HEAD:foo &&
+	git tag -s -m "A message for a blob" blob-signed-tag HEAD:foo &&
 	get_tag_msg blob-signed-tag >actual &&
 	test_cmp expect actual
 '
@@ -1022,7 +1025,7 @@
 echo '-----BEGIN PGP SIGNATURE-----' >>expect
 test_expect_success \
 	'creating a signed tag pointing to another tag should succeed' '
-	git-tag -s -m "A message for another tag" tag-signed-tag signed-tag &&
+	git tag -s -m "A message for another tag" tag-signed-tag signed-tag &&
 	get_tag_msg tag-signed-tag >actual &&
 	test_cmp expect actual
 '
@@ -1030,8 +1033,8 @@
 # try to sign with bad user.signingkey
 git config user.signingkey BobTheMouse
 test_expect_success \
-	'git-tag -s fails if gpg is misconfigured' \
-	'! git tag -s -m tail tag-gpg-failure'
+	'git tag -s fails if gpg is misconfigured' \
+	'test_must_fail git tag -s -m tail tag-gpg-failure'
 git config --unset user.signingkey
 
 # try to verify without gpg:
@@ -1039,10 +1042,10 @@
 rm -rf gpghome
 test_expect_success \
 	'verify signed tag fails when public key is not present' \
-	'! git-tag -v signed-tag'
+	'test_must_fail git tag -v signed-tag'
 
 test_expect_success \
-	'git-tag -a fails if tag annotation is empty' '
+	'git tag -a fails if tag annotation is empty' '
 	! (GIT_EDITOR=cat git tag -a initial-comment)
 '
 
@@ -1087,4 +1090,15 @@
 	git cat-file tag tag-from-subdir-2 | grep "in sub directory"
 '
 
+# mixing modes and options:
+
+test_expect_success 'mixing incompatibles modes and options is forbidden' '
+	test_must_fail git tag -a
+	test_must_fail git tag -l -v
+	test_must_fail git tag -n 100
+	test_must_fail git tag -l -m msg
+	test_must_fail git tag -l -F some file
+	test_must_fail git tag -v -s
+'
+
 test_done
diff --git a/t/t7007-show.sh b/t/t7007-show.sh
new file mode 100755
index 0000000..cce222f
--- /dev/null
+++ b/t/t7007-show.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+test_description='git show'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+	echo hello world >foo &&
+	H=$(git hash-object -w foo) &&
+	git tag -a foo-tag -m "Tags $H" $H &&
+	HH=$(expr "$H" : "\(..\)") &&
+	H38=$(expr "$H" : "..\(.*\)") &&
+	rm -f .git/objects/$HH/$H38
+'
+
+test_expect_success 'showing a tag that point at a missing object' '
+	test_must_fail git --no-pager show foo-tag
+'
+
+test_done
diff --git a/t/t7101-reset.sh b/t/t7101-reset.sh
index 0d9874b..c4ef19e 100755
--- a/t/t7101-reset.sh
+++ b/t/t7101-reset.sh
@@ -3,7 +3,7 @@
 # Copyright (c) 2006 Shawn Pearce
 #
 
-test_description='git-reset should cull empty subdirs'
+test_description='git reset should cull empty subdirs'
 . ./test-lib.sh
 
 test_expect_success \
@@ -11,7 +11,7 @@
     'mkdir path0 &&
      cp ../../COPYING path0/COPYING &&
      git add path0/COPYING &&
-     git-commit -m add -a'
+     git commit -m add -a'
 
 test_expect_success \
     'creating second files' \
@@ -25,11 +25,11 @@
      git add path1/COPYING &&
      git add COPYING &&
      git add path0/COPYING-TOO &&
-     git-commit -m change -a'
+     git commit -m change -a'
 
 test_expect_success \
     'resetting tree HEAD^' \
-    'git-reset --hard HEAD^'
+    'git reset --hard HEAD^'
 
 test_expect_success \
     'checking initial files exist after rewind' \
diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh
index 96d1508..e637c7d 100755
--- a/t/t7102-reset.sh
+++ b/t/t7102-reset.sh
@@ -3,9 +3,9 @@
 # Copyright (c) 2007 Carlos Rica
 #
 
-test_description='git-reset
+test_description='git reset
 
-Documented tests for git-reset'
+Documented tests for git reset'
 
 . ./test-lib.sh
 
@@ -52,10 +52,10 @@
 EOF
 
 test_expect_success 'giving a non existing revision should fail' '
-	! git reset aaaaaa &&
-	! git reset --mixed aaaaaa &&
-	! git reset --soft aaaaaa &&
-	! git reset --hard aaaaaa &&
+	test_must_fail git reset aaaaaa &&
+	test_must_fail git reset --mixed aaaaaa &&
+	test_must_fail git reset --soft aaaaaa &&
+	test_must_fail git reset --hard aaaaaa &&
 	check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
 '
 
@@ -63,29 +63,29 @@
 	touch .git/MERGE_HEAD &&
 	echo "100644 44c5b5884550c17758737edcced463447b91d42b 1	un" |
 		git update-index --index-info &&
-	! git reset --soft HEAD &&
+	test_must_fail git reset --soft HEAD &&
 	rm .git/MERGE_HEAD &&
 	git rm --cached -- un
 '
 
 test_expect_success \
 	'giving paths with options different than --mixed should fail' '
-	! git reset --soft -- first &&
-	! git reset --hard -- first &&
-	! git reset --soft HEAD^ -- first &&
-	! git reset --hard HEAD^ -- first &&
+	test_must_fail git reset --soft -- first &&
+	test_must_fail git reset --hard -- first &&
+	test_must_fail git reset --soft HEAD^ -- first &&
+	test_must_fail git reset --hard HEAD^ -- first &&
 	check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
 '
 
 test_expect_success 'giving unrecognized options should fail' '
-	! git reset --other &&
-	! git reset -o &&
-	! git reset --mixed --other &&
-	! git reset --mixed -o &&
-	! git reset --soft --other &&
-	! git reset --soft -o &&
-	! git reset --hard --other &&
-	! git reset --hard -o &&
+	test_must_fail git reset --other &&
+	test_must_fail git reset -o &&
+	test_must_fail git reset --mixed --other &&
+	test_must_fail git reset --mixed -o &&
+	test_must_fail git reset --soft --other &&
+	test_must_fail git reset --soft -o &&
+	test_must_fail git reset --hard --other &&
+	test_must_fail git reset --hard -o &&
 	check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
 '
 
@@ -102,8 +102,8 @@
 	echo "3rd line in branch2" >>secondfile &&
 	git commit -a -m "change in branch2" &&
 
-	! git merge branch1 &&
-	! git reset --soft &&
+	test_must_fail git merge branch1 &&
+	test_must_fail git reset --soft &&
 
 	printf "1st line 2nd file\n2nd line 2nd file\n3rd line" >secondfile &&
 	git commit -a -m "the change in branch2" &&
@@ -126,7 +126,7 @@
 	echo "3rd line in branch4" >>secondfile &&
 
 	git checkout -m branch3 &&
-	! git reset --soft &&
+	test_must_fail git reset --soft &&
 
 	printf "1st line 2nd file\n2nd line 2nd file\n3rd line" >secondfile &&
 	git commit -a -m "the line in branch3" &&
@@ -326,7 +326,7 @@
 	echo "3rd line in branch2" >>secondfile &&
 	git commit -a -m "change in branch2" &&
 
-	! git pull . branch1 &&
+	test_must_fail git pull . branch1 &&
 	git reset --hard &&
 	check_changes 77abb337073fb4369a7ad69ff6f5ec0e4d6b54bb
 '
@@ -388,7 +388,7 @@
 	echo 4 > file4 &&
 	echo 5 > file1 &&
 	git add file1 file3 file4 &&
-	! git reset HEAD -- file1 file2 file3 &&
+	test_must_fail git reset HEAD -- file1 file2 file3 &&
 	git diff > output &&
 	test_cmp output expect &&
 	git diff --cached > output &&
@@ -402,11 +402,11 @@
 	>sub/file2 &&
 	git update-index --add sub/file1 sub/file2 &&
 	T=$(git write-tree) &&
-	! git reset HEAD sub/file2 &&
+	test_must_fail git reset HEAD sub/file2 &&
 	U=$(git write-tree) &&
 	echo "$T" &&
 	echo "$U" &&
-	! git diff-index --cached --exit-code "$T" &&
+	test_must_fail git diff-index --cached --exit-code "$T" &&
 	test "$T" != "$U"
 
 '
@@ -419,7 +419,7 @@
 '
 
 cat > expect << EOF
-file2: needs update
+file2: locally modified
 EOF
 
 test_expect_success '--mixed refreshes the index' '
diff --git a/t/t7103-reset-bare.sh b/t/t7103-reset-bare.sh
index b25a77f..42bf518 100755
--- a/t/t7103-reset-bare.sh
+++ b/t/t7103-reset-bare.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-test_description='git-reset in a bare repository'
+test_description='git reset in a bare repository'
 . ./test-lib.sh
 
 test_expect_success 'setup non-bare' '
@@ -17,7 +17,7 @@
 '
 
 test_expect_success 'hard reset is not allowed' '
-	! git reset --hard HEAD^
+	test_must_fail  git reset --hard HEAD^
 '
 
 test_expect_success 'soft reset is allowed' '
diff --git a/t/t7201-co.sh b/t/t7201-co.sh
index 3111baa..c9abed6 100755
--- a/t/t7201-co.sh
+++ b/t/t7201-co.sh
@@ -3,7 +3,7 @@
 # Copyright (c) 2006 Junio C Hamano
 #
 
-test_description='git-checkout tests.
+test_description='git checkout tests.
 
 Creates master, forks renamer and side branches from it.
 Test switching across them.
@@ -330,11 +330,57 @@
     test "$(git config branch.track2.merge)"
     git config branch.autosetupmerge false'
 
-test_expect_success \
-    'checkout w/--track from non-branch HEAD fails' '
-    git checkout -b delete-me master &&
-    rm .git/refs/heads/delete-me &&
-    test refs/heads/delete-me = "$(git symbolic-ref HEAD)" &&
-    !(git checkout --track -b track)'
+test_expect_success 'checkout w/--track from non-branch HEAD fails' '
+    git checkout master^0 &&
+    test_must_fail git symbolic-ref HEAD &&
+    test_must_fail git checkout --track -b track &&
+    test_must_fail git rev-parse --verify track &&
+    test_must_fail git symbolic-ref HEAD &&
+    test "z$(git rev-parse master^0)" = "z$(git rev-parse HEAD)"
+'
+
+test_expect_success 'detach a symbolic link HEAD' '
+    git checkout master &&
+    git config --bool core.prefersymlinkrefs yes &&
+    git checkout side &&
+    git checkout master &&
+    it=$(git symbolic-ref HEAD) &&
+    test "z$it" = zrefs/heads/master &&
+    here=$(git rev-parse --verify refs/heads/master) &&
+    git checkout side^ &&
+    test "z$(git rev-parse --verify refs/heads/master)" = "z$here"
+'
+
+test_expect_success 'checkout an unmerged path should fail' '
+	rm -f .git/index &&
+	O=$(echo original | git hash-object -w --stdin) &&
+	A=$(echo ourside | git hash-object -w --stdin) &&
+	B=$(echo theirside | git hash-object -w --stdin) &&
+	(
+		echo "100644 $A 0	fild" &&
+		echo "100644 $O 1	file" &&
+		echo "100644 $A 2	file" &&
+		echo "100644 $B 3	file" &&
+		echo "100644 $A 0	filf"
+	) | git update-index --index-info &&
+	echo "none of the above" >sample &&
+	cat sample >fild &&
+	cat sample >file &&
+	cat sample >filf &&
+	test_must_fail git checkout fild file filf &&
+	test_cmp sample fild &&
+	test_cmp sample filf &&
+	test_cmp sample file
+'
+
+test_expect_success 'failing checkout -b should not break working tree' '
+	git reset --hard master &&
+	git symbolic-ref HEAD refs/heads/master &&
+	test_must_fail git checkout -b renamer side^ &&
+	test $(git symbolic-ref HEAD) = refs/heads/master &&
+	git diff --exit-code &&
+	git diff --cached --exit-code
+
+'
 
 test_done
diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh
index bd77239..1636fac 100755
--- a/t/t7300-clean.sh
+++ b/t/t7300-clean.sh
@@ -3,7 +3,7 @@
 # Copyright (c) 2007 Michael Spang
 #
 
-test_description='git-clean basic tests'
+test_description='git clean basic tests'
 
 . ./test-lib.sh
 
@@ -16,17 +16,17 @@
 	echo build >.gitignore &&
 	echo \*.o >>.gitignore &&
 	git add . &&
-	git-commit -m setup &&
+	git commit -m setup &&
 	touch src/part2.c README &&
 	git add .
 
 '
 
-test_expect_success 'git-clean' '
+test_expect_success 'git clean' '
 
 	mkdir -p build docs &&
 	touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
-	git-clean &&
+	git clean &&
 	test -f Makefile &&
 	test -f README &&
 	test -f src/part1.c &&
@@ -39,11 +39,11 @@
 
 '
 
-test_expect_success 'git-clean src/' '
+test_expect_success 'git clean src/' '
 
 	mkdir -p build docs &&
 	touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
-	git-clean src/ &&
+	git clean src/ &&
 	test -f Makefile &&
 	test -f README &&
 	test -f src/part1.c &&
@@ -56,11 +56,11 @@
 
 '
 
-test_expect_success 'git-clean src/ src/' '
+test_expect_success 'git clean src/ src/' '
 
 	mkdir -p build docs &&
 	touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
-	git-clean src/ src/ &&
+	git clean src/ src/ &&
 	test -f Makefile &&
 	test -f README &&
 	test -f src/part1.c &&
@@ -73,11 +73,11 @@
 
 '
 
-test_expect_success 'git-clean with prefix' '
+test_expect_success 'git clean with prefix' '
 
 	mkdir -p build docs src/test &&
 	touch a.out src/part3.c docs/manual.txt obj.o build/lib.so src/test/1.c &&
-	(cd src/ && git-clean) &&
+	(cd src/ && git clean) &&
 	test -f Makefile &&
 	test -f README &&
 	test -f src/part1.c &&
@@ -91,7 +91,7 @@
 
 '
 
-test_expect_success 'git-clean with relative prefix' '
+test_expect_success 'git clean with relative prefix' '
 
 	mkdir -p build docs &&
 	touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
@@ -106,7 +106,7 @@
 	}
 '
 
-test_expect_success 'git-clean with absolute path' '
+test_expect_success 'git clean with absolute path' '
 
 	mkdir -p build docs &&
 	touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
@@ -121,7 +121,7 @@
 	}
 '
 
-test_expect_success 'git-clean with out of work tree relative path' '
+test_expect_success 'git clean with out of work tree relative path' '
 
 	mkdir -p build docs &&
 	touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
@@ -131,7 +131,7 @@
 	)
 '
 
-test_expect_success 'git-clean with out of work tree absolute path' '
+test_expect_success 'git clean with out of work tree absolute path' '
 
 	mkdir -p build docs &&
 	touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
@@ -142,11 +142,11 @@
 	)
 '
 
-test_expect_success 'git-clean -d with prefix and path' '
+test_expect_success 'git clean -d with prefix and path' '
 
 	mkdir -p build docs src/feature &&
 	touch a.out src/part3.c src/feature/file.c docs/manual.txt obj.o build/lib.so &&
-	(cd src/ && git-clean -d feature/) &&
+	(cd src/ && git clean -d feature/) &&
 	test -f Makefile &&
 	test -f README &&
 	test -f src/part1.c &&
@@ -160,12 +160,12 @@
 
 '
 
-test_expect_success 'git-clean symbolic link' '
+test_expect_success 'git clean symbolic link' '
 
 	mkdir -p build docs &&
 	touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
 	ln -s docs/manual.txt src/part4.c
-	git-clean &&
+	git clean &&
 	test -f Makefile &&
 	test -f README &&
 	test -f src/part1.c &&
@@ -179,10 +179,10 @@
 
 '
 
-test_expect_success 'git-clean with wildcard' '
+test_expect_success 'git clean with wildcard' '
 
 	touch a.clean b.clean other.c &&
-	git-clean "*.clean" &&
+	git clean "*.clean" &&
 	test -f Makefile &&
 	test -f README &&
 	test -f src/part1.c &&
@@ -193,11 +193,11 @@
 
 '
 
-test_expect_success 'git-clean -n' '
+test_expect_success 'git clean -n' '
 
 	mkdir -p build docs &&
 	touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
-	git-clean -n &&
+	git clean -n &&
 	test -f Makefile &&
 	test -f README &&
 	test -f src/part1.c &&
@@ -210,11 +210,11 @@
 
 '
 
-test_expect_success 'git-clean -d' '
+test_expect_success 'git clean -d' '
 
 	mkdir -p build docs &&
 	touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
-	git-clean -d &&
+	git clean -d &&
 	test -f Makefile &&
 	test -f README &&
 	test -f src/part1.c &&
@@ -227,11 +227,11 @@
 
 '
 
-test_expect_success 'git-clean -d src/ examples/' '
+test_expect_success 'git clean -d src/ examples/' '
 
 	mkdir -p build docs examples &&
 	touch a.out src/part3.c docs/manual.txt obj.o build/lib.so examples/1.c &&
-	git-clean -d src/ examples/ &&
+	git clean -d src/ examples/ &&
 	test -f Makefile &&
 	test -f README &&
 	test -f src/part1.c &&
@@ -245,11 +245,11 @@
 
 '
 
-test_expect_success 'git-clean -x' '
+test_expect_success 'git clean -x' '
 
 	mkdir -p build docs &&
 	touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
-	git-clean -x &&
+	git clean -x &&
 	test -f Makefile &&
 	test -f README &&
 	test -f src/part1.c &&
@@ -262,11 +262,11 @@
 
 '
 
-test_expect_success 'git-clean -d -x' '
+test_expect_success 'git clean -d -x' '
 
 	mkdir -p build docs &&
 	touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
-	git-clean -d -x &&
+	git clean -d -x &&
 	test -f Makefile &&
 	test -f README &&
 	test -f src/part1.c &&
@@ -279,11 +279,11 @@
 
 '
 
-test_expect_success 'git-clean -X' '
+test_expect_success 'git clean -X' '
 
 	mkdir -p build docs &&
 	touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
-	git-clean -X &&
+	git clean -X &&
 	test -f Makefile &&
 	test -f README &&
 	test -f src/part1.c &&
@@ -296,11 +296,11 @@
 
 '
 
-test_expect_success 'git-clean -d -X' '
+test_expect_success 'git clean -d -X' '
 
 	mkdir -p build docs &&
 	touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
-	git-clean -d -X &&
+	git clean -d -X &&
 	test -f Makefile &&
 	test -f README &&
 	test -f src/part1.c &&
@@ -316,14 +316,14 @@
 test_expect_success 'clean.requireForce defaults to true' '
 
 	git config --unset clean.requireForce &&
-	! git-clean
+	test_must_fail git clean
 
 '
 
 test_expect_success 'clean.requireForce' '
 
 	git config clean.requireForce true &&
-	! git-clean
+	test_must_fail git clean
 
 '
 
@@ -331,7 +331,7 @@
 
 	mkdir -p build docs &&
 	touch a.out src/part3.c docs/manual.txt obj.o build/lib.so &&
-	git-clean -n &&
+	git clean -n &&
 	test -f Makefile &&
 	test -f README &&
 	test -f src/part1.c &&
@@ -346,7 +346,7 @@
 
 test_expect_success 'clean.requireForce and -f' '
 
-	git-clean -f &&
+	git clean -f &&
 	test -f README &&
 	test -f src/part1.c &&
 	test -f src/part2.c &&
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index 6c7b902..be73f7b 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -6,7 +6,7 @@
 test_description='Basic porcelain support for submodules
 
 This test tries to verify basic sanity of the init, update and status
-subcommands of git-submodule.
+subcommands of git submodule.
 '
 
 . ./test-lib.sh
@@ -22,16 +22,16 @@
 #
 test_expect_success 'Prepare submodule testing' '
 	: > t &&
-	git-add t &&
-	git-commit -m "initial commit" &&
+	git add t &&
+	git commit -m "initial commit" &&
 	git branch initial HEAD &&
 	mkdir init &&
 	cd init &&
 	git init &&
 	echo a >a &&
 	git add a &&
-	git-commit -m "submodule commit 1" &&
-	git-tag -a -m "rev-1" rev-1 &&
+	git commit -m "submodule commit 1" &&
+	git tag -a -m "rev-1" rev-1 &&
 	rev1=$(git rev-parse HEAD) &&
 	if test -z "$rev1"
 	then
@@ -42,13 +42,13 @@
 	echo a >a &&
 	echo z >z &&
 	git add a init z &&
-	git-commit -m "super commit 1" &&
+	git commit -m "super commit 1" &&
 	mv init .subrepo &&
 	GIT_CONFIG=.gitmodules git config submodule.example.url git://example.com/init.git
 '
 
 test_expect_success 'status should fail for unmapped paths' '
-	if git-submodule status
+	if git submodule status
 	then
 		echo "[OOPS] submodule status succeeded"
 		false
@@ -60,22 +60,22 @@
 '
 
 test_expect_success 'status should only print one line' '
-	lines=$(git-submodule status | wc -l) &&
+	lines=$(git submodule status | wc -l) &&
 	test $lines = 1
 '
 
 test_expect_success 'status should initially be "missing"' '
-	git-submodule status | grep "^-$rev1"
+	git submodule status | grep "^-$rev1"
 '
 
 test_expect_success 'init should register submodule url in .git/config' '
-	git-submodule init &&
+	git submodule init &&
 	url=$(git config submodule.example.url) &&
 	if test "$url" != "git://example.com/init.git"
 	then
 		echo "[OOPS] init succeeded but submodule url is wrong"
 		false
-	elif ! git config submodule.example.url ./.subrepo
+	elif test_must_fail git config submodule.example.url ./.subrepo
 	then
 		echo "[OOPS] init succeeded but update of url failed"
 		false
@@ -84,7 +84,7 @@
 
 test_expect_success 'update should fail when path is used by a file' '
 	echo "hello" >init &&
-	if git-submodule update
+	if git submodule update
 	then
 		echo "[OOPS] update should have failed"
 		false
@@ -100,7 +100,7 @@
 test_expect_success 'update should fail when path is used by a nonempty directory' '
 	mkdir init &&
 	echo "hello" >init/a &&
-	if git-submodule update
+	if git submodule update
 	then
 		echo "[OOPS] update should have failed"
 		false
@@ -116,7 +116,7 @@
 test_expect_success 'update should work when path is an empty dir' '
 	rm -rf init &&
 	mkdir init &&
-	git-submodule update &&
+	git submodule update &&
 	head=$(cd init && git rev-parse HEAD) &&
 	if test -z "$head"
 	then
@@ -130,14 +130,14 @@
 '
 
 test_expect_success 'status should be "up-to-date" after update' '
-	git-submodule status | grep "^ $rev1"
+	git submodule status | grep "^ $rev1"
 '
 
 test_expect_success 'status should be "modified" after submodule commit' '
 	cd init &&
 	echo b >b &&
 	git add b &&
-	git-commit -m "submodule commit 2" &&
+	git commit -m "submodule commit 2" &&
 	rev2=$(git rev-parse HEAD) &&
 	cd .. &&
 	if test -z "$rev2"
@@ -145,19 +145,19 @@
 		echo "[OOPS] submodule git rev-parse returned nothing"
 		false
 	fi &&
-	git-submodule status | grep "^+$rev2"
+	git submodule status | grep "^+$rev2"
 '
 
 test_expect_success 'the --cached sha1 should be rev1' '
-	git-submodule --cached status | grep "^+$rev1"
+	git submodule --cached status | grep "^+$rev1"
 '
 
 test_expect_success 'git diff should report the SHA1 of the new submodule commit' '
-	git-diff | grep "^+Subproject commit $rev2"
+	git diff | grep "^+Subproject commit $rev2"
 '
 
 test_expect_success 'update should checkout rev1' '
-	git-submodule update init &&
+	git submodule update init &&
 	head=$(cd init && git rev-parse HEAD) &&
 	if test -z "$head"
 	then
@@ -171,12 +171,12 @@
 '
 
 test_expect_success 'status should be "up-to-date" after update' '
-	git-submodule status | grep "^ $rev1"
+	git submodule status | grep "^ $rev1"
 '
 
 test_expect_success 'checkout superproject with subproject already present' '
-	git-checkout initial &&
-	git-checkout master
+	git checkout initial &&
+	git checkout master
 '
 
 test_expect_success 'apply submodule diff' '
@@ -188,8 +188,8 @@
 		git commit -m "change subproject"
 	) &&
 	git update-index --add init &&
-	git-commit -m "change init" &&
-	git-format-patch -1 --stdout >P.diff &&
+	git commit -m "change init" &&
+	git format-patch -1 --stdout >P.diff &&
 	git checkout second &&
 	git apply --index P.diff &&
 	D=$(git diff --cached master) &&
diff --git a/t/t7401-submodule-summary.sh b/t/t7401-submodule-summary.sh
index bf12dbd..6149829 100755
--- a/t/t7401-submodule-summary.sh
+++ b/t/t7401-submodule-summary.sh
@@ -5,7 +5,7 @@
 
 test_description='Summary support for submodules
 
-This test tries to verify the sanity of summary subcommand of git-submodule.
+This test tries to verify the sanity of summary subcommand of git submodule.
 '
 
 . ./test-lib.sh
diff --git a/t/t7402-submodule-rebase.sh b/t/t7402-submodule-rebase.sh
index 5becb3e..f919c8d 100755
--- a/t/t7402-submodule-rebase.sh
+++ b/t/t7402-submodule-rebase.sh
@@ -71,7 +71,7 @@
 	test_tick &&
 	git commit -m rewrite file &&
 	echo dirty > file &&
-	! git rebase --onto HEAD~2 HEAD^
+	test_must_fail git rebase --onto HEAD~2 HEAD^
 
 '
 
diff --git a/t/t7500-commit.sh b/t/t7500-commit.sh
index 823256a..0fe745e 100755
--- a/t/t7500-commit.sh
+++ b/t/t7500-commit.sh
@@ -3,7 +3,7 @@
 # Copyright (c) 2007 Steven Grimm
 #
 
-test_description='git-commit
+test_description='git commit
 
 Tests for selected commit options.'
 
@@ -23,12 +23,12 @@
 test_expect_success 'nonexistent template file should return error' '
 	echo changes >> foo &&
 	git add foo &&
-	! git commit --template "$PWD"/notexist
+	test_must_fail git commit --template "$PWD"/notexist
 '
 
 test_expect_success 'nonexistent template file in config should return error' '
 	git config commit.template "$PWD"/notexist &&
-	! git commit &&
+	test_must_fail git commit &&
 	git config --unset commit.template
 '
 
@@ -37,12 +37,12 @@
 
 test_expect_success 'unedited template should not commit' '
 	echo "template line" > "$TEMPLATE" &&
-	! git commit --template "$TEMPLATE"
+	test_must_fail git commit --template "$TEMPLATE"
 '
 
 test_expect_success 'unedited template with comments should not commit' '
 	echo "# comment in template" >> "$TEMPLATE" &&
-	! git commit --template "$TEMPLATE"
+	test_must_fail git commit --template "$TEMPLATE"
 '
 
 test_expect_success 'a Signed-off-by line by itself should not commit' '
diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh
index d3370ff..63bfc6d 100755
--- a/t/t7501-commit.sh
+++ b/t/t7501-commit.sh
@@ -6,7 +6,7 @@
 # FIXME: Test the various index usages, -i and -o, test reflog,
 # signoff
 
-test_description='git-commit'
+test_description='git commit'
 . ./test-lib.sh
 
 test_tick
@@ -14,52 +14,52 @@
 test_expect_success \
 	"initial status" \
 	"echo 'bongo bongo' >file &&
-	 git-add file && \
-	 git-status | grep 'Initial commit'"
+	 git add file && \
+	 git status | grep 'Initial commit'"
 
 test_expect_success \
 	"fail initial amend" \
-	"! git-commit --amend"
+	"test_must_fail git commit --amend"
 
 test_expect_success \
 	"initial commit" \
-	"git-commit -m initial"
+	"git commit -m initial"
 
 test_expect_success \
 	"invalid options 1" \
-	"! git-commit -m foo -m bar -F file"
+	"test_must_fail git commit -m foo -m bar -F file"
 
 test_expect_success \
 	"invalid options 2" \
-	"! git-commit -C HEAD -m illegal"
+	"test_must_fail git commit -C HEAD -m illegal"
 
 test_expect_success \
 	"using paths with -a" \
 	"echo King of the bongo >file &&
-	! git-commit -m foo -a file"
+	test_must_fail git commit -m foo -a file"
 
 test_expect_success \
 	"using paths with --interactive" \
 	"echo bong-o-bong >file &&
-	! (echo 7 | git-commit -m foo --interactive file)"
+	! (echo 7 | git commit -m foo --interactive file)"
 
 test_expect_success \
 	"using invalid commit with -C" \
-	"! git-commit -C bogus"
+	"test_must_fail git commit -C bogus"
 
 test_expect_success \
 	"testing nothing to commit" \
-	"! git-commit -m initial"
+	"test_must_fail git commit -m initial"
 
 test_expect_success \
 	"next commit" \
 	"echo 'bongo bongo bongo' >file \
-	 git-commit -m next -a"
+	 git commit -m next -a"
 
 test_expect_success \
 	"commit message from non-existing file" \
 	"echo 'more bongo: bongo bongo bongo bongo' >file && \
-	 ! git-commit -F gah -a"
+	 test_must_fail git commit -F gah -a"
 
 # Empty except stray tabs and spaces on a few lines.
 sed -e 's/@$//' >msg <<EOF
@@ -70,12 +70,12 @@
 EOF
 test_expect_success \
 	"empty commit message" \
-	"! git-commit -F msg -a"
+	"test_must_fail git commit -F msg -a"
 
 test_expect_success \
 	"commit message from file" \
 	"echo 'this is the commit message, coming from a file' >msg && \
-	 git-commit -F msg -a"
+	 git commit -F msg -a"
 
 cat >editor <<\EOF
 #!/bin/sh
@@ -86,16 +86,16 @@
 
 test_expect_success \
 	"amend commit" \
-	"VISUAL=./editor git-commit --amend"
+	"VISUAL=./editor git commit --amend"
 
 test_expect_success \
 	"passing -m and -F" \
 	"echo 'enough with the bongos' >file && \
-	 ! git-commit -F msg -m amending ."
+	 test_must_fail git commit -F msg -m amending ."
 
 test_expect_success \
 	"using message from other commit" \
-	"git-commit -C HEAD^ ."
+	"git commit -C HEAD^ ."
 
 cat >editor <<\EOF
 #!/bin/sh
@@ -107,25 +107,25 @@
 test_expect_success \
 	"editing message from other commit" \
 	"echo 'hula hula' >file && \
-	 VISUAL=./editor git-commit -c HEAD^ -a"
+	 VISUAL=./editor git commit -c HEAD^ -a"
 
 test_expect_success \
 	"message from stdin" \
 	"echo 'silly new contents' >file && \
-	 echo commit message from stdin | git-commit -F - -a"
+	 echo commit message from stdin | git commit -F - -a"
 
 test_expect_success \
 	"overriding author from command line" \
 	"echo 'gak' >file && \
-	 git-commit -m 'author' --author 'Rubber Duck <rduck@convoy.org>' -a"
+	 git commit -m 'author' --author 'Rubber Duck <rduck@convoy.org>' -a"
 
 test_expect_success \
 	"interactive add" \
-	"echo 7 | git-commit --interactive | grep 'What now'"
+	"echo 7 | git commit --interactive | grep 'What now'"
 
 test_expect_success \
 	"showing committed revisions" \
-	"git-rev-list HEAD >current"
+	"git rev-list HEAD >current"
 
 # We could just check the head sha1, but checking each commit makes it
 # easier to isolate bugs.
@@ -140,8 +140,8 @@
 EOF
 
 test_expect_success \
-    'validate git-rev-list output.' \
-    'diff current expected'
+    'validate git rev-list output.' \
+    'test_cmp expected current'
 
 test_expect_success 'partial commit that involves removal (1)' '
 
@@ -151,7 +151,7 @@
 	git commit -m "Partial: add elif" elif &&
 	git diff-tree --name-status HEAD^ HEAD >current &&
 	echo "A	elif" >expected &&
-	diff expected current
+	test_cmp expected current
 
 '
 
@@ -160,7 +160,7 @@
 	git commit -m "Partial: remove file" file &&
 	git diff-tree --name-status HEAD^ HEAD >current &&
 	echo "D	file" >expected &&
-	diff expected current
+	test_cmp expected current
 
 '
 
@@ -171,7 +171,7 @@
 	git commit -m "Partial: modify elif" elif &&
 	git diff-tree --name-status HEAD^ HEAD >current &&
 	echo "M	elif" >expected &&
-	diff expected current
+	test_cmp expected current
 
 '
 
@@ -187,7 +187,7 @@
 		expected &&
 	git commit --amend --author="$author" &&
 	git cat-file -p HEAD > current &&
-	diff expected current
+	test_cmp expected current
 
 '
 
@@ -256,7 +256,7 @@
 		expected &&
 	git commit --amend --author="$author" &&
 	git cat-file -p HEAD > current &&
-	diff expected current
+	test_cmp expected current
 
 '
 
diff --git a/t/t7502-commit.sh b/t/t7502-commit.sh
index c25eff9..3eb9fae 100755
--- a/t/t7502-commit.sh
+++ b/t/t7502-commit.sh
@@ -141,8 +141,8 @@
 
 echo "sample
 
-# Please enter the commit message for your changes.
-# (Comment lines starting with '#' will not be included)" >expect
+# Please enter the commit message for your changes. Lines starting
+# with '#' will be ignored, and an empty message aborts the commit." >expect
 
 test_expect_success 'cleanup commit messages (strip,-F,-e)' '
 
@@ -228,10 +228,12 @@
 
 test_expect_success 'a SIGTERM should break locks' '
 	echo >>negative &&
-	"$SHELL_PATH" -c '\''
+	! "$SHELL_PATH" -c '\''
 	  echo kill -TERM $$ >> .git/FAKE_EDITOR
-	  GIT_EDITOR=.git/FAKE_EDITOR exec git commit -a'\'' && exit 1  # should fail
-	! test -f .git/index.lock
+	  GIT_EDITOR=.git/FAKE_EDITOR
+	  export GIT_EDITOR
+	  exec git commit -a'\'' &&
+	test ! -f .git/index.lock
 '
 
 rm -f .git/MERGE_MSG .git/COMMIT_EDITMSG
diff --git a/t/t7502-status.sh b/t/t7502-status.sh
index 80a438d..187a13e 100755
--- a/t/t7502-status.sh
+++ b/t/t7502-status.sh
@@ -3,7 +3,7 @@
 # Copyright (c) 2007 Johannes E. Schindelin
 #
 
-test_description='git-status'
+test_description='git status'
 
 . ./test-lib.sh
 
@@ -67,6 +67,104 @@
 
 '
 
+cat >expect <<EOF
+# On branch master
+# Changes to be committed:
+#   (use "git reset HEAD <file>..." to unstage)
+#
+#	new file:   dir2/added
+#
+# Changed but not updated:
+#   (use "git add <file>..." to update what will be committed)
+#
+#	modified:   dir1/modified
+#
+# Untracked files not listed (use -u option to show untracked files)
+EOF
+test_expect_success 'status -uno' '
+	mkdir dir3 &&
+	: > dir3/untracked1 &&
+	: > dir3/untracked2 &&
+	git status -uno >output &&
+	test_cmp expect output
+'
+
+test_expect_success 'status (status.showUntrackedFiles no)' '
+	git config status.showuntrackedfiles no
+	git status >output &&
+	test_cmp expect output
+'
+
+cat >expect <<EOF
+# On branch master
+# Changes to be committed:
+#   (use "git reset HEAD <file>..." to unstage)
+#
+#	new file:   dir2/added
+#
+# Changed but not updated:
+#   (use "git add <file>..." to update what will be committed)
+#
+#	modified:   dir1/modified
+#
+# Untracked files:
+#   (use "git add <file>..." to include in what will be committed)
+#
+#	dir1/untracked
+#	dir2/modified
+#	dir2/untracked
+#	dir3/
+#	expect
+#	output
+#	untracked
+EOF
+test_expect_success 'status -unormal' '
+	git status -unormal >output &&
+	test_cmp expect output
+'
+
+test_expect_success 'status (status.showUntrackedFiles normal)' '
+	git config status.showuntrackedfiles normal
+	git status >output &&
+	test_cmp expect output
+'
+
+cat >expect <<EOF
+# On branch master
+# Changes to be committed:
+#   (use "git reset HEAD <file>..." to unstage)
+#
+#	new file:   dir2/added
+#
+# Changed but not updated:
+#   (use "git add <file>..." to update what will be committed)
+#
+#	modified:   dir1/modified
+#
+# Untracked files:
+#   (use "git add <file>..." to include in what will be committed)
+#
+#	dir1/untracked
+#	dir2/modified
+#	dir2/untracked
+#	dir3/untracked1
+#	dir3/untracked2
+#	expect
+#	output
+#	untracked
+EOF
+test_expect_success 'status -uall' '
+	git status -uall >output &&
+	test_cmp expect output
+'
+test_expect_success 'status (status.showUntrackedFiles all)' '
+	git config status.showuntrackedfiles all
+	git status >output &&
+	rm -rf dir3 &&
+	git config --unset status.showuntrackedfiles &&
+	test_cmp expect output
+'
+
 cat > expect << \EOF
 # On branch master
 # Changes to be committed:
@@ -187,6 +285,12 @@
 	test_cmp expect output
 '
 
+# we expect the same as the previous test
+test_expect_success 'status --untracked-files=all does not show submodule' '
+	git status --untracked-files=all >output &&
+	test_cmp expect output
+'
+
 head=$(cd sm && git rev-parse --short=7 --verify HEAD)
 
 cat >expect <<EOF
diff --git a/t/t7503-pre-commit-hook.sh b/t/t7503-pre-commit-hook.sh
index 2dd5a5e..b069095 100755
--- a/t/t7503-pre-commit-hook.sh
+++ b/t/t7503-pre-commit-hook.sh
@@ -56,7 +56,7 @@
 
 	echo "another" >> file &&
 	git add file &&
-	! git commit -m "another"
+	test_must_fail git commit -m "another"
 
 '
 
diff --git a/t/t7504-commit-msg-hook.sh b/t/t7504-commit-msg-hook.sh
index 88577af..47680e6 100755
--- a/t/t7504-commit-msg-hook.sh
+++ b/t/t7504-commit-msg-hook.sh
@@ -105,7 +105,7 @@
 
 	echo "another" >> file &&
 	git add file &&
-	! git commit -m "another"
+	test_must_fail git commit -m "another"
 
 '
 
diff --git a/t/t7505-prepare-commit-msg-hook.sh b/t/t7505-prepare-commit-msg-hook.sh
index cd6c7c8..ff18962 100755
--- a/t/t7505-prepare-commit-msg-hook.sh
+++ b/t/t7505-prepare-commit-msg-hook.sh
@@ -32,7 +32,7 @@
 cat >> "$HOOK" <<'EOF'
 
 if test "$2" = commit; then
-  source=$(git-rev-parse "$3")
+  source=$(git rev-parse "$3")
 else
   source=${2-default}
 fi
diff --git a/t/t7506-status-submodule.sh b/t/t7506-status-submodule.sh
index a75130c..d9a08aa 100755
--- a/t/t7506-status-submodule.sh
+++ b/t/t7506-status-submodule.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-test_description='git-status for submodule'
+test_description='git status for submodule'
 
 . ./test-lib.sh
 
diff --git a/t/t7507-commit-verbose.sh b/t/t7507-commit-verbose.sh
new file mode 100755
index 0000000..519adba
--- /dev/null
+++ b/t/t7507-commit-verbose.sh
@@ -0,0 +1,73 @@
+#!/bin/sh
+
+test_description='verbose commit template'
+. ./test-lib.sh
+
+cat >check-for-diff <<EOF
+#!$SHELL_PATH
+exec grep '^diff --git' "\$1"
+EOF
+chmod +x check-for-diff
+test_set_editor "$PWD/check-for-diff"
+
+cat >message <<'EOF'
+subject
+
+body
+EOF
+
+test_expect_success 'setup' '
+	echo content >file &&
+	git add file &&
+	git commit -F message
+'
+
+test_expect_failure 'initial commit shows verbose diff' '
+	git commit --amend -v
+'
+
+test_expect_success 'second commit' '
+	echo content modified >file &&
+	git add file &&
+	git commit -F message
+'
+
+check_message() {
+	git log -1 --pretty=format:%s%n%n%b >actual &&
+	test_cmp "$1" actual
+}
+
+test_expect_success 'verbose diff is stripped out' '
+	git commit --amend -v &&
+	check_message message
+'
+
+test_expect_success 'verbose diff is stripped out (mnemonicprefix)' '
+	git config diff.mnemonicprefix true &&
+	git commit --amend -v &&
+	check_message message
+'
+
+cat >diff <<'EOF'
+This is an example commit message that contains a diff.
+
+diff --git c/file i/file
+new file mode 100644
+index 0000000..f95c11d
+--- /dev/null
++++ i/file
+@@ -0,0 +1 @@
++this is some content
+EOF
+
+test_expect_success 'diff in message is retained without -v' '
+	git commit --amend -F diff &&
+	check_message diff
+'
+
+test_expect_failure 'diff in message is retained with -v' '
+	git commit --amend -F diff -v &&
+	check_message diff
+'
+
+test_done
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index daf45b7..5abce31 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -3,7 +3,7 @@
 # Copyright (c) 2007 Lars Hjemli
 #
 
-test_description='git-merge
+test_description='git merge
 
 Testing basic merge operations/option parsing.'
 
@@ -126,7 +126,7 @@
 		echo "[OOPS] unmerged files"
 		false
 	fi &&
-	if ! git diff --exit-code
+	if test_must_fail git diff --exit-code
 	then
 		echo "[OOPS] working tree != index"
 		false
@@ -441,11 +441,96 @@
 	git merge --no-log c2 &&
 	git show -s --pretty=format:%b HEAD >msg.act &&
 	verify_diff msg.nolog msg.act "[OOPS] bad merge log message" &&
+
 	git merge --log c3 &&
 	git show -s --pretty=format:%b HEAD >msg.act &&
+	verify_diff msg.log msg.act "[OOPS] bad merge log message" &&
+
+	git reset --hard HEAD^ &&
+	git config merge.log yes &&
+	git merge c3 &&
+	git show -s --pretty=format:%b HEAD >msg.act &&
 	verify_diff msg.log msg.act "[OOPS] bad merge log message"
 '
 
 test_debug 'gitk --all'
 
+test_expect_success 'merge c1 with c0, c2, c0, and c1' '
+       git reset --hard c1 &&
+       git config branch.master.mergeoptions "" &&
+       test_tick &&
+       git merge c0 c2 c0 c1 &&
+       verify_merge file result.1-5 &&
+       verify_parents $c1 $c2
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c1 with c0, c2, c0, and c1' '
+       git reset --hard c1 &&
+       git config branch.master.mergeoptions "" &&
+       test_tick &&
+       git merge c0 c2 c0 c1 &&
+       verify_merge file result.1-5 &&
+       verify_parents $c1 $c2
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c1 with c1 and c2' '
+       git reset --hard c1 &&
+       git config branch.master.mergeoptions "" &&
+       test_tick &&
+       git merge c1 c2 &&
+       verify_merge file result.1-5 &&
+       verify_parents $c1 $c2
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge fast-forward in a dirty tree' '
+       git reset --hard c0 &&
+       mv file file1 &&
+       cat file1 >file &&
+       rm -f file1 &&
+       git merge c2
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'in-index merge' '
+	git reset --hard c0 &&
+	git merge --no-ff -s resolve c1 > out &&
+	grep "Wonderful." out &&
+	verify_parents $c0 $c1
+'
+
+test_debug 'gitk --all'
+
+cat >expected <<EOF
+Merge branch 'c5' (early part)
+EOF
+
+test_expect_success 'merge early part of c2' '
+	git reset --hard c3 &&
+	echo c4 > c4.c &&
+	git add c4.c &&
+	git commit -m c4 &&
+	git tag c4 &&
+	echo c5 > c5.c &&
+	git add c5.c &&
+	git commit -m c5 &&
+	git tag c5 &&
+	git reset --hard c3 &&
+	echo c6 > c6.c &&
+	git add c6.c &&
+	git commit -m c6 &&
+	git tag c6 &&
+	git merge c5~1 &&
+	git show -s --pretty=format:%s HEAD > actual &&
+	test_cmp actual expected
+'
+
+test_debug 'gitk --all'
+
 test_done
diff --git a/t/t7601-merge-pull-config.sh b/t/t7601-merge-pull-config.sh
new file mode 100755
index 0000000..7ba94ea
--- /dev/null
+++ b/t/t7601-merge-pull-config.sh
@@ -0,0 +1,156 @@
+#!/bin/sh
+
+test_description='git merge
+
+Testing pull.* configuration parsing.'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+	echo c0 >c0.c &&
+	git add c0.c &&
+	git commit -m c0 &&
+	git tag c0 &&
+	echo c1 >c1.c &&
+	git add c1.c &&
+	git commit -m c1 &&
+	git tag c1 &&
+	git reset --hard c0 &&
+	echo c2 >c2.c &&
+	git add c2.c &&
+	git commit -m c2 &&
+	git tag c2 &&
+	git reset --hard c0 &&
+	echo c3 >c3.c &&
+	git add c3.c &&
+	git commit -m c3 &&
+	git tag c3
+'
+
+test_expect_success 'merge c1 with c2' '
+	git reset --hard c1 &&
+	test -f c0.c &&
+	test -f c1.c &&
+	test ! -f c2.c &&
+	test ! -f c3.c &&
+	git merge c2 &&
+	test -f c1.c &&
+	test -f c2.c
+'
+
+test_expect_success 'merge c1 with c2 (ours in pull.twohead)' '
+	git reset --hard c1 &&
+	git config pull.twohead ours &&
+	git merge c2 &&
+	test -f c1.c &&
+	! test -f c2.c
+'
+
+test_expect_success 'merge c1 with c2 and c3 (recursive in pull.octopus)' '
+	git reset --hard c1 &&
+	git config pull.octopus "recursive" &&
+	test_must_fail git merge c2 c3 &&
+	test "$(git rev-parse c1)" = "$(git rev-parse HEAD)"
+'
+
+test_expect_success 'merge c1 with c2 and c3 (recursive and octopus in pull.octopus)' '
+	git reset --hard c1 &&
+	git config pull.octopus "recursive octopus" &&
+	git merge c2 c3 &&
+	test "$(git rev-parse c1)" != "$(git rev-parse HEAD)" &&
+	test "$(git rev-parse c1)" = "$(git rev-parse HEAD^1)" &&
+	test "$(git rev-parse c2)" = "$(git rev-parse HEAD^2)" &&
+	test "$(git rev-parse c3)" = "$(git rev-parse HEAD^3)" &&
+	git diff --exit-code &&
+	test -f c0.c &&
+	test -f c1.c &&
+	test -f c2.c &&
+	test -f c3.c
+'
+
+conflict_count()
+{
+	{
+		git diff-files --name-only
+		git ls-files --unmerged
+	} | wc -l
+}
+
+# c4 - c5
+#    \ c6
+#
+# There are two conflicts here:
+#
+# 1) Because foo.c is renamed to bar.c, recursive will handle this,
+# resolve won't.
+#
+# 2) One in conflict.c and that will always fail.
+
+test_expect_success 'setup conflicted merge' '
+	git reset --hard c0 &&
+	echo A >conflict.c &&
+	git add conflict.c &&
+	echo contents >foo.c &&
+	git add foo.c &&
+	git commit -m c4 &&
+	git tag c4 &&
+	echo B >conflict.c &&
+	git add conflict.c &&
+	git mv foo.c bar.c &&
+	git commit -m c5 &&
+	git tag c5 &&
+	git reset --hard c4 &&
+	echo C >conflict.c &&
+	git add conflict.c &&
+	echo secondline >> foo.c &&
+	git add foo.c &&
+	git commit -m c6 &&
+	git tag c6
+'
+
+# First do the merge with resolve and recursive then verify that
+# recusive is choosen.
+
+test_expect_success 'merge picks up the best result' '
+	git config --unset-all pull.twohead &&
+	git reset --hard c5 &&
+	git merge -s resolve c6
+	resolve_count=$(conflict_count) &&
+	git reset --hard c5 &&
+	git merge -s recursive c6
+	recursive_count=$(conflict_count) &&
+	git reset --hard c5 &&
+	git merge -s recursive -s resolve c6
+	auto_count=$(conflict_count) &&
+	test $auto_count = $recursive_count &&
+	test $auto_count != $resolve_count
+'
+
+test_expect_success 'merge picks up the best result (from config)' '
+	git config pull.twohead "recursive resolve" &&
+	git reset --hard c5 &&
+	git merge -s resolve c6
+	resolve_count=$(conflict_count) &&
+	git reset --hard c5 &&
+	git merge -s recursive c6
+	recursive_count=$(conflict_count) &&
+	git reset --hard c5 &&
+	git merge c6
+	auto_count=$(conflict_count) &&
+	test $auto_count = $recursive_count &&
+	test $auto_count != $resolve_count
+'
+
+test_expect_success 'merge errors out on invalid strategy' '
+	git config pull.twohead "foobar" &&
+	git reset --hard c5 &&
+	test_must_fail git merge c6
+'
+
+test_expect_success 'merge errors out on invalid strategy' '
+	git config --unset-all pull.twohead &&
+	git reset --hard c5 &&
+	test_must_fail git merge -s "resolve recursive" c6
+'
+
+test_done
diff --git a/t/t7602-merge-octopus-many.sh b/t/t7602-merge-octopus-many.sh
new file mode 100755
index 0000000..01e5415
--- /dev/null
+++ b/t/t7602-merge-octopus-many.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+
+test_description='git merge
+
+Testing octopus merge with more than 25 refs.'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+	echo c0 > c0.c &&
+	git add c0.c &&
+	git commit -m c0 &&
+	git tag c0 &&
+	i=1 &&
+	while test $i -le 30
+	do
+		git reset --hard c0 &&
+		echo c$i > c$i.c &&
+		git add c$i.c &&
+		git commit -m c$i &&
+		git tag c$i &&
+		i=`expr $i + 1` || return 1
+	done
+'
+
+test_expect_success 'merge c1 with c2, c3, c4, ... c29' '
+	git reset --hard c1 &&
+	i=2 &&
+	refs="" &&
+	while test $i -le 30
+	do
+		refs="$refs c$i"
+		i=`expr $i + 1`
+	done
+	git merge $refs &&
+	test "$(git rev-parse c1)" != "$(git rev-parse HEAD)" &&
+	i=1 &&
+	while test $i -le 30
+	do
+		test "$(git rev-parse c$i)" = "$(git rev-parse HEAD^$i)" &&
+		i=`expr $i + 1` || return 1
+	done &&
+	git diff --exit-code &&
+	i=1 &&
+	while test $i -le 30
+	do
+		test -f c$i.c &&
+		i=`expr $i + 1` || return 1
+	done
+'
+
+test_done
diff --git a/t/t7603-merge-reduce-heads.sh b/t/t7603-merge-reduce-heads.sh
new file mode 100755
index 0000000..b47b7b9
--- /dev/null
+++ b/t/t7603-merge-reduce-heads.sh
@@ -0,0 +1,63 @@
+#!/bin/sh
+
+test_description='git merge
+
+Testing octopus merge when reducing parents to independent branches.'
+
+. ./test-lib.sh
+
+# 0 - 1
+#   \ 2
+#   \ 3
+#   \ 4 - 5
+#
+# So 1, 2, 3 and 5 should be kept, 4 should be avoided.
+
+test_expect_success 'setup' '
+	echo c0 > c0.c &&
+	git add c0.c &&
+	git commit -m c0 &&
+	git tag c0 &&
+	echo c1 > c1.c &&
+	git add c1.c &&
+	git commit -m c1 &&
+	git tag c1 &&
+	git reset --hard c0 &&
+	echo c2 > c2.c &&
+	git add c2.c &&
+	git commit -m c2 &&
+	git tag c2 &&
+	git reset --hard c0 &&
+	echo c3 > c3.c &&
+	git add c3.c &&
+	git commit -m c3 &&
+	git tag c3 &&
+	git reset --hard c0 &&
+	echo c4 > c4.c &&
+	git add c4.c &&
+	git commit -m c4 &&
+	git tag c4 &&
+	echo c5 > c5.c &&
+	git add c5.c &&
+	git commit -m c5 &&
+	git tag c5
+'
+
+test_expect_success 'merge c1 with c2, c3, c4, c5' '
+	git reset --hard c1 &&
+	git merge c2 c3 c4 c5 &&
+	test "$(git rev-parse c1)" != "$(git rev-parse HEAD)" &&
+	test "$(git rev-parse c1)" = "$(git rev-parse HEAD^1)" &&
+	test "$(git rev-parse c2)" = "$(git rev-parse HEAD^2)" &&
+	test "$(git rev-parse c3)" = "$(git rev-parse HEAD^3)" &&
+	test "$(git rev-parse c5)" = "$(git rev-parse HEAD^4)" &&
+	git diff --exit-code &&
+	test -f c0.c &&
+	test -f c1.c &&
+	test -f c2.c &&
+	test -f c3.c &&
+	test -f c4.c &&
+	test -f c5.c
+'
+
+test_done
diff --git a/t/t7604-merge-custom-message.sh b/t/t7604-merge-custom-message.sh
new file mode 100755
index 0000000..de977c5
--- /dev/null
+++ b/t/t7604-merge-custom-message.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+test_description='git merge
+
+Testing merge when using a custom message for the merge commit.'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+	echo c0 > c0.c &&
+	git add c0.c &&
+	git commit -m c0 &&
+	git tag c0 &&
+	echo c1 > c1.c &&
+	git add c1.c &&
+	git commit -m c1 &&
+	git tag c1 &&
+	git reset --hard c0 &&
+	echo c2 > c2.c &&
+	git add c2.c &&
+	git commit -m c2 &&
+	git tag c2
+'
+
+cat >expected <<\EOF
+custom message
+
+Merge commit 'c2'
+EOF
+test_expect_success 'merge c2 with a custom message' '
+	git reset --hard c1 &&
+	git merge -m "custom message" c2 &&
+	git cat-file commit HEAD | sed -e "1,/^$/d" > actual &&
+	test_cmp expected actual
+'
+
+test_done
diff --git a/t/t7605-merge-resolve.sh b/t/t7605-merge-resolve.sh
new file mode 100755
index 0000000..0cb9d11
--- /dev/null
+++ b/t/t7605-merge-resolve.sh
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+test_description='git merge
+
+Testing the resolve strategy.'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+	echo c0 > c0.c &&
+	git add c0.c &&
+	git commit -m c0 &&
+	git tag c0 &&
+	echo c1 > c1.c &&
+	git add c1.c &&
+	git commit -m c1 &&
+	git tag c1 &&
+	git reset --hard c0 &&
+	echo c2 > c2.c &&
+	git add c2.c &&
+	git commit -m c2 &&
+	git tag c2 &&
+	git reset --hard c0 &&
+	echo c3 > c2.c &&
+	git add c2.c &&
+	git commit -m c3 &&
+	git tag c3
+'
+
+test_expect_success 'merge c1 to c2' '
+	git reset --hard c1 &&
+	git merge -s resolve c2 &&
+	test "$(git rev-parse c1)" != "$(git rev-parse HEAD)" &&
+	test "$(git rev-parse c1)" = "$(git rev-parse HEAD^1)" &&
+	test "$(git rev-parse c2)" = "$(git rev-parse HEAD^2)" &&
+	git diff --exit-code &&
+	test -f c0.c &&
+	test -f c1.c &&
+	test -f c2.c &&
+	test 3 = $(git ls-tree -r HEAD | wc -l) &&
+	test 3 = $(git ls-files | wc -l)
+'
+
+test_expect_success 'merge c2 to c3 (fails)' '
+	git reset --hard c2 &&
+	test_must_fail git merge -s resolve c3
+'
+test_done
diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh
index 6b0483f..09fa5f1 100755
--- a/t/t7610-mergetool.sh
+++ b/t/t7610-mergetool.sh
@@ -3,7 +3,7 @@
 # Copyright (c) 2008 Charles Bailey
 #
 
-test_description='git-mergetool
+test_description='git mergetool
 
 Testing basic merge tool invocation'
 
@@ -35,7 +35,7 @@
     git config mergetool.mytool.cmd "cat \"\$REMOTE\" >\"\$MERGED\"" &&
     git config mergetool.mytool.trustExitCode true &&
 	git checkout branch1 &&
-    ! git merge master >/dev/null 2>&1 &&
+    test_must_fail git merge master >/dev/null 2>&1 &&
     ( yes "" | git mergetool file1>/dev/null 2>&1 ) &&
     ( yes "" | git mergetool file2>/dev/null 2>&1 ) &&
     test "$(cat file1)" = "master updated" &&
diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh
new file mode 100755
index 0000000..3f602ea
--- /dev/null
+++ b/t/t7700-repack.sh
@@ -0,0 +1,73 @@
+#!/bin/sh
+
+test_description='git repack works correctly'
+
+. ./test-lib.sh
+
+test_expect_success 'objects in packs marked .keep are not repacked' '
+	echo content1 > file1 &&
+	echo content2 > file2 &&
+	git add . &&
+	git commit -m initial_commit &&
+	# Create two packs
+	# The first pack will contain all of the objects except one
+	git rev-list --objects --all | grep -v file2 |
+		git pack-objects pack > /dev/null &&
+	# The second pack will contain the excluded object
+	packsha1=$(git rev-list --objects --all | grep file2 |
+		git pack-objects pack) &&
+	touch -r pack-$packsha1.pack pack-$packsha1.keep &&
+	objsha1=$(git verify-pack -v pack-$packsha1.idx | head -n 1 |
+		sed -e "s/^\([0-9a-f]\{40\}\).*/\1/") &&
+	mv pack-* .git/objects/pack/ &&
+	git repack -A -d -l &&
+	git prune-packed &&
+	for p in .git/objects/pack/*.idx; do
+		idx=$(basename $p)
+		test "pack-$packsha1.idx" = "$idx" && continue
+		if git verify-pack -v $p | egrep "^$objsha1"; then
+			found_duplicate_object=1
+			echo "DUPLICATE OBJECT FOUND"
+			break
+		fi
+	done &&
+	test -z "$found_duplicate_object"
+'
+
+test_expect_success 'loose objects in alternate ODB are not repacked' '
+	mkdir alt_objects &&
+	echo `pwd`/alt_objects > .git/objects/info/alternates &&
+	echo content3 > file3 &&
+	objsha1=$(GIT_OBJECT_DIRECTORY=alt_objects git hash-object -w file3) &&
+	git add file3 &&
+	git commit -m commit_file3 &&
+	git repack -a -d -l &&
+	git prune-packed &&
+	for p in .git/objects/pack/*.idx; do
+		if git verify-pack -v $p | egrep "^$objsha1"; then
+			found_duplicate_object=1
+			echo "DUPLICATE OBJECT FOUND"
+			break
+		fi
+	done &&
+	test -z "$found_duplicate_object"
+'
+
+test_expect_success 'packed obs in alt ODB are repacked even when local repo is packless' '
+	mkdir alt_objects/pack
+	mv .git/objects/pack/* alt_objects/pack &&
+	git repack -a &&
+	myidx=$(ls -1 .git/objects/pack/*.idx) &&
+	test -f "$myidx" &&
+	for p in alt_objects/pack/*.idx; do
+		git verify-pack -v $p | sed -n -e "/^[0-9a-f]\{40\}/p"
+	done | while read sha1 rest; do
+		if ! ( git verify-pack -v $myidx | grep "^$sha1" ); then
+			echo "Missing object in local pack: $sha1"
+			return 1
+		fi
+	done
+'
+
+test_done
+
diff --git a/t/t7701-repack-unpack-unreachable.sh b/t/t7701-repack-unpack-unreachable.sh
index 6a5211f..9813f11 100755
--- a/t/t7701-repack-unpack-unreachable.sh
+++ b/t/t7701-repack-unpack-unreachable.sh
@@ -1,10 +1,14 @@
 #!/bin/sh
 
-test_description='git-repack works correctly'
+test_description='git repack works correctly'
 
 . ./test-lib.sh
 
-test_expect_success '-A option leaves unreachable objects unpacked' '
+fsha1=
+csha1=
+tsha1=
+
+test_expect_success '-A with -d option leaves unreachable objects unpacked' '
 	echo content > file1 &&
 	git add . &&
 	git commit -m initial_commit &&
@@ -44,4 +48,46 @@
 	git show $tsha1
 '
 
+compare_mtimes ()
+{
+	perl -e 'my $reference = shift;
+		 foreach my $file (@ARGV) {
+			exit(1) unless(-f $file && -M $file == -M $reference);
+		 }
+		 exit(0);
+		' -- "$@"
+}
+
+test_expect_success '-A without -d option leaves unreachable objects packed' '
+	fsha1path=$(echo "$fsha1" | sed -e "s|\(..\)|\1/|") &&
+	fsha1path=".git/objects/$fsha1path" &&
+	csha1path=$(echo "$csha1" | sed -e "s|\(..\)|\1/|") &&
+	csha1path=".git/objects/$csha1path" &&
+	tsha1path=$(echo "$tsha1" | sed -e "s|\(..\)|\1/|") &&
+	tsha1path=".git/objects/$tsha1path" &&
+	git branch transient_branch $csha1 &&
+	git repack -a -d -l &&
+	test ! -f "$fsha1path" &&
+	test ! -f "$csha1path" &&
+	test ! -f "$tsha1path" &&
+	test 1 = $(ls -1 .git/objects/pack/pack-*.pack | wc -l) &&
+	packfile=$(ls .git/objects/pack/pack-*.pack) &&
+	git branch -D transient_branch &&
+	sleep 1 &&
+	git repack -A -l &&
+	test ! -f "$fsha1path" &&
+	test ! -f "$csha1path" &&
+	test ! -f "$tsha1path" &&
+	git show $fsha1 &&
+	git show $csha1 &&
+	git show $tsha1
+'
+
+test_expect_success 'unpacked objects receive timestamp of pack file' '
+	tmppack=".git/objects/pack/tmp_pack" &&
+	ln "$packfile" "$tmppack" &&
+	git repack -A -l -d &&
+	compare_mtimes "$tmppack" "$fsha1path" "$csha1path" "$tsha1path"
+'
+
 test_done
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index 3e4eb63..d098a01 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-test_description='git-send-email'
+test_description='git send-email'
 . ./test-lib.sh
 
 PROG='git send-email'
@@ -13,7 +13,7 @@
 
 test_expect_success \
     'Setup helper tool' \
-    '(echo "#!/bin/sh"
+    '(echo "#!$SHELL_PATH"
       echo shift
       echo output=1
       echo "while test -f commandline\$output; do output=\$((\$output+1)); done"
@@ -91,7 +91,7 @@
 	clean_fake_sendmail &&
 	cp $patches longline.patch &&
 	echo $z512$z512 >>longline.patch &&
-	! git send-email \
+	test_must_fail git send-email \
 		--from="Example <nobody@example.com>" \
 		--to=nobody@example.com \
 		--smtp-server="$(pwd)/fake.sendmail" \
@@ -138,7 +138,7 @@
 '
 
 test_expect_success 'setup fake editor' '
-	(echo "#!/bin/sh" &&
+	(echo "#!$SHELL_PATH" &&
 	 echo "echo fake edit >>\"\$1\""
 	) >fake-editor &&
 	chmod +x fake-editor
@@ -235,7 +235,7 @@
 
 test_expect_success '--compose adds MIME for utf8 body' '
 	clean_fake_sendmail &&
-	(echo "#!/bin/sh" &&
+	(echo "#!$SHELL_PATH" &&
 	 echo "echo utf8 body: àéìöú >>\"\$1\""
 	) >fake-editor-utf8 &&
 	chmod +x fake-editor-utf8 &&
@@ -254,7 +254,7 @@
 
 test_expect_success '--compose respects user mime type' '
 	clean_fake_sendmail &&
-	(echo "#!/bin/sh" &&
+	(echo "#!$SHELL_PATH" &&
 	 echo "(echo MIME-Version: 1.0"
 	 echo " echo Content-Type: text/plain\\; charset=iso-8859-1"
 	 echo " echo Content-Transfer-Encoding: 8bit"
diff --git a/t/t9100-git-svn-basic.sh b/t/t9100-git-svn-basic.sh
index 242cdf0..843a501 100755
--- a/t/t9100-git-svn-basic.sh
+++ b/t/t9100-git-svn-basic.sh
@@ -4,9 +4,9 @@
 #
 
 test_description='git-svn basic tests'
-GIT_SVN_LC_ALL=$LC_ALL
+GIT_SVN_LC_ALL=${LC_ALL:-$LANG}
 
-case "$LC_ALL" in
+case "$GIT_SVN_LC_ALL" in
 *.UTF-8)
 	have_utf8=t
 	;;
@@ -17,7 +17,7 @@
 
 . ./lib-git-svn.sh
 
-echo 'define NO_SVN_TESTS to skip git-svn tests'
+say 'define NO_SVN_TESTS to skip git-svn tests'
 
 test_expect_success \
     'initialize git-svn' '
@@ -63,7 +63,7 @@
 	git update-index --remove dir/file &&
 	git update-index --add dir/file/file &&
 	git commit -m '$name' &&
-	! git-svn set-tree --find-copies-harder --rmdir \
+	test_must_fail git-svn set-tree --find-copies-harder --rmdir \
 		remotes/git-svn..mybranch" || true
 
 
@@ -77,7 +77,7 @@
 	git update-index --remove -- bar/zzz &&
 	git update-index --add -- bar &&
 	git commit -m "$name" &&
-	! git-svn set-tree --find-copies-harder --rmdir \
+	test_must_fail git-svn set-tree --find-copies-harder --rmdir \
 		remotes/git-svn..mybranch2' || true
 
 
@@ -91,7 +91,7 @@
 	echo yyy > bar/zzz/yyy &&
 	git update-index --add bar/zzz/yyy &&
 	git commit -m "$name" &&
-	! git-svn set-tree --find-copies-harder --rmdir \
+	test_must_fail git-svn set-tree --find-copies-harder --rmdir \
 		remotes/git-svn..mybranch3' || true
 
 
@@ -105,7 +105,7 @@
 	echo asdf > dir &&
 	git update-index --add -- dir &&
 	git commit -m "$name" &&
-	! git-svn set-tree --find-copies-harder --rmdir \
+	test_must_fail git-svn set-tree --find-copies-harder --rmdir \
 		remotes/git-svn..mybranch4' || true
 
 
@@ -183,7 +183,7 @@
 		git-svn set-tree HEAD"
 	unset LC_ALL
 else
-	echo "UTF-8 locale not set, test skipped ($GIT_SVN_LC_ALL)"
+	say "UTF-8 locale not set, test skipped ($GIT_SVN_LC_ALL)"
 fi
 
 name='test fetch functionality (svn => git) with alternate GIT_SVN_ID'
@@ -216,7 +216,7 @@
 test_expect_success 'exit if remote refs are ambigious' "
         git config --add svn-remote.svn.fetch \
                               bar:refs/remotes/git-svn &&
-	! git-svn migrate
+	test_must_fail git-svn migrate
 "
 
 test_expect_success 'exit if init-ing a would clobber a URL' '
@@ -224,7 +224,7 @@
         svn mkdir -m "mkdir bar" "${svnrepo}2/bar" &&
         git config --unset svn-remote.svn.fetch \
                                 "^bar:refs/remotes/git-svn$" &&
-	! git-svn init "${svnrepo}2/bar"
+	test_must_fail git-svn init "${svnrepo}2/bar"
         '
 
 test_expect_success \
diff --git a/t/t9104-git-svn-follow-parent.sh b/t/t9104-git-svn-follow-parent.sh
index 4d964e2..d80ea64 100755
--- a/t/t9104-git-svn-follow-parent.sh
+++ b/t/t9104-git-svn-follow-parent.sh
@@ -149,6 +149,48 @@
 	     "`git rev-parse r9270-d~1`"
 	'
 
+test_expect_success "follow-parent is atomic" '
+	(
+		cd wc &&
+		svn up &&
+		svn mkdir stunk &&
+		echo "trunk stunk" > stunk/readme &&
+		svn add stunk/readme &&
+		svn ci -m "trunk stunk" &&
+		echo "stunk like junk" >> stunk/readme &&
+		svn ci -m "really stunk" &&
+		echo "stink stank stunk" >> stunk/readme &&
+		svn ci -m "even the grinch agrees"
+	) &&
+	svn copy -m "stunk flunked" "$svnrepo"/stunk "$svnrepo"/flunk &&
+	{ svn cp -m "early stunk flunked too" \
+		"$svnrepo"/stunk@17 "$svnrepo"/flunked ||
+	svn cp -m "early stunk flunked too" \
+		-r17 "$svnrepo"/stunk "$svnrepo"/flunked; } &&
+	git svn init --minimize-url -i stunk "$svnrepo"/stunk &&
+	git svn fetch -i stunk &&
+	git update-ref refs/remotes/flunk@18 refs/remotes/stunk~2 &&
+	git update-ref -d refs/remotes/stunk &&
+	git config --unset svn-remote.svn.fetch stunk &&
+	mkdir -p "$GIT_DIR"/svn/flunk@18 &&
+	rev_map=$(cd "$GIT_DIR"/svn/stunk && ls .rev_map*) &&
+	dd if="$GIT_DIR"/svn/stunk/$rev_map \
+	   of="$GIT_DIR"/svn/flunk@18/$rev_map bs=24 count=1 &&
+	rm -rf "$GIT_DIR"/svn/stunk &&
+	git svn init --minimize-url -i flunk "$svnrepo"/flunk &&
+	git svn fetch -i flunk &&
+	git svn init --minimize-url -i stunk "$svnrepo"/stunk &&
+	git svn fetch -i stunk &&
+	git svn init --minimize-url -i flunked "$svnrepo"/flunked &&
+	git svn fetch -i flunked
+	test "`git rev-parse --verify refs/remotes/flunk@18`" \
+	   = "`git rev-parse --verify refs/remotes/stunk`" &&
+	test "`git rev-parse --verify refs/remotes/flunk~1`" \
+	   = "`git rev-parse --verify refs/remotes/stunk`" &&
+	test "`git rev-parse --verify refs/remotes/flunked~1`" \
+	   = "`git rev-parse --verify refs/remotes/stunk~1`"
+	'
+
 test_expect_success "track multi-parent paths" '
 	svn cp -m "resurrect /glob" "$svnrepo"/r9270 "$svnrepo"/glob &&
 	git-svn multi-fetch &&
diff --git a/t/t9106-git-svn-commit-diff-clobber.sh b/t/t9106-git-svn-commit-diff-clobber.sh
index 58a3a7b..83896e9 100755
--- a/t/t9106-git-svn-commit-diff-clobber.sh
+++ b/t/t9106-git-svn-commit-diff-clobber.sh
@@ -27,7 +27,7 @@
 test_expect_success 'commit conflicting change from git' '
 	echo second line from git >> file &&
 	git commit -a -m "second line from git" &&
-	! git-svn commit-diff -r1 HEAD~1 HEAD "$svnrepo"
+	test_must_fail git-svn commit-diff -r1 HEAD~1 HEAD "$svnrepo"
 '
 
 test_expect_success 'commit complementing change from git' '
@@ -52,7 +52,7 @@
 	rm -rf t.svn &&
 	echo "fourth line from git" >> file &&
 	git commit -a -m "fourth line from git" &&
-	! git-svn dcommit
+	test_must_fail git-svn dcommit
 	'
 
 test_expect_success 'dcommit does the svn equivalent of an index merge' "
@@ -83,11 +83,13 @@
 	git commit -a -m 'new file' &&
 	echo clobber > file &&
 	git commit -a -m 'clobber' &&
-	! git svn dcommit
+	test_must_fail git svn dcommit
 	"
 
 
-test_expect_success 'check that rebase really failed' 'test -d .dotest'
+test_expect_success 'check that rebase really failed' '
+	test -d .git/rebase-apply
+'
 
 test_expect_success 'resolve, continue the rebase and dcommit' "
 	echo clobber and I really mean it > file &&
diff --git a/t/t9106-git-svn-dcommit-clobber-series.sh b/t/t9106-git-svn-dcommit-clobber-series.sh
index a400dc7..bc37db9 100755
--- a/t/t9106-git-svn-dcommit-clobber-series.sh
+++ b/t/t9106-git-svn-dcommit-clobber-series.sh
@@ -20,8 +20,8 @@
 	test x"`sed -n -e 61p < file`" = x61 &&
 	svn co "$svnrepo" tmp &&
 	cd tmp &&
-		perl -i -p -e "s/^58$/5588/" file &&
-		perl -i -p -e "s/^61$/6611/" file &&
+		perl -i.bak -p -e "s/^58$/5588/" file &&
+		perl -i.bak -p -e "s/^61$/6611/" file &&
 		poke file &&
 		test x"`sed -n -e 58p < file`" = x5588 &&
 		test x"`sed -n -e 61p < file`" = x6611 &&
@@ -40,8 +40,8 @@
 test_expect_success 'change file but in unrelated area' "
 	test x\"\`sed -n -e 4p < file\`\" = x4 &&
 	test x\"\`sed -n -e 7p < file\`\" = x7 &&
-	perl -i -p -e 's/^4\$/4444/' file &&
-	perl -i -p -e 's/^7\$/7777/' file &&
+	perl -i.bak -p -e 's/^4\$/4444/' file &&
+	perl -i.bak -p -e 's/^7\$/7777/' file &&
 	test x\"\`sed -n -e 4p < file\`\" = x4444 &&
 	test x\"\`sed -n -e 7p < file\`\" = x7777 &&
 	git commit -m '4 => 4444, 7 => 7777' file &&
@@ -57,7 +57,7 @@
 test_expect_success 'attempt to dcommit with a dirty index' '
 	echo foo >>file &&
 	git add file &&
-	! git svn dcommit
+	test_must_fail git svn dcommit
 '
 
 test_done
diff --git a/t/t9108-git-svn-glob.sh b/t/t9108-git-svn-glob.sh
index f6f71d0..8b792a1 100755
--- a/t/t9108-git-svn-glob.sh
+++ b/t/t9108-git-svn-glob.sh
@@ -16,7 +16,8 @@
 	echo "goodbye world" > trunk/src/b/readme &&
 	svn import -m "initial" trunk "$svnrepo"/trunk &&
 	svn co "$svnrepo" tmp &&
-	cd tmp &&
+	(
+		cd tmp &&
 		mkdir branches tags &&
 		svn add branches tags &&
 		svn cp trunk branches/start &&
@@ -37,7 +38,7 @@
 		echo "byebye" >> tags/end/src/b/readme &&
 		poke tags/end/src/b/readme &&
 		svn commit -m "nothing to see here"
-		cd .. &&
+	) &&
 	git config --add svn-remote.svn.url "$svnrepo" &&
 	git config --add svn-remote.svn.fetch \
 	                 "trunk/src/a:refs/remotes/trunk" &&
@@ -48,11 +49,12 @@
 	git-svn multi-fetch &&
 	git log --pretty=oneline refs/remotes/tags/end | \
 	    sed -e "s/^.\{41\}//" > output.end &&
-	cmp expect.end output.end &&
+	test_cmp expect.end output.end &&
 	test "`git rev-parse refs/remotes/tags/end~1`" = \
 		"`git rev-parse refs/remotes/branches/start`" &&
 	test "`git rev-parse refs/remotes/branches/start~2`" = \
-		"`git rev-parse refs/remotes/trunk`"
+		"`git rev-parse refs/remotes/trunk`" &&
+	test_must_fail git rev-parse refs/remotes/tags/end@3
 	'
 
 echo try to try > expect.two
@@ -66,11 +68,12 @@
 	                 "branches/*:refs/remotes/two/branches/*" &&
 	git config --add svn-remote.two.tags \
 	                 "tags/*:refs/remotes/two/tags/*" &&
-	cd tmp &&
+	(
+		cd tmp &&
 		echo "try try" >> tags/end/src/b/readme &&
 		poke tags/end/src/b/readme &&
 		svn commit -m "try to try"
-		cd .. &&
+	) &&
 	git-svn fetch two &&
 	test `git rev-list refs/remotes/two/tags/end | wc -l` -eq 6 &&
 	test `git rev-list refs/remotes/two/branches/start | wc -l` -eq 3 &&
@@ -80,7 +83,29 @@
 	     `git rev-parse refs/remotes/two/branches/start` &&
 	git log --pretty=oneline refs/remotes/two/tags/end | \
 	    sed -e "s/^.\{41\}//" > output.two &&
-	cmp expect.two output.two
+	test_cmp expect.two output.two
+	'
+
+echo "Only one set of wildcard directories" \
+     "(e.g. '*' or '*/*/*') is supported: 'branches/*/t/*'" > expect.three
+echo "" >> expect.three
+
+test_expect_success 'test disallow multi-globs' '
+	git config --add svn-remote.three.url "$svnrepo" &&
+	git config --add svn-remote.three.fetch \
+	                 trunk:refs/remotes/three/trunk &&
+	git config --add svn-remote.three.branches \
+	                 "branches/*/t/*:refs/remotes/three/branches/*" &&
+	git config --add svn-remote.three.tags \
+	                 "tags/*/*:refs/remotes/three/tags/*" &&
+	(
+		cd tmp &&
+		echo "try try" >> tags/end/src/b/readme &&
+		poke tags/end/src/b/readme &&
+		svn commit -m "try to try"
+	) &&
+	test_must_fail git-svn fetch three 2> stderr.three &&
+	test_cmp expect.three stderr.three
 	'
 
 test_done
diff --git a/t/t9108-git-svn-multi-glob.sh b/t/t9108-git-svn-multi-glob.sh
new file mode 100755
index 0000000..3583721
--- /dev/null
+++ b/t/t9108-git-svn-multi-glob.sh
@@ -0,0 +1,160 @@
+#!/bin/sh
+# Copyright (c) 2007 Eric Wong
+test_description='git-svn globbing refspecs'
+. ./lib-git-svn.sh
+
+cat > expect.end <<EOF
+the end
+hi
+start a new branch
+initial
+EOF
+
+test_expect_success 'test refspec globbing' '
+	mkdir -p trunk/src/a trunk/src/b trunk/doc &&
+	echo "hello world" > trunk/src/a/readme &&
+	echo "goodbye world" > trunk/src/b/readme &&
+	svn import -m "initial" trunk "$svnrepo"/trunk &&
+	svn co "$svnrepo" tmp &&
+	(
+		cd tmp &&
+		mkdir branches branches/v1 tags &&
+		svn add branches tags &&
+		svn cp trunk branches/v1/start &&
+		svn commit -m "start a new branch" &&
+		svn up &&
+		echo "hi" >> branches/v1/start/src/b/readme &&
+		poke branches/v1/start/src/b/readme &&
+		echo "hey" >> branches/v1/start/src/a/readme &&
+		poke branches/v1/start/src/a/readme &&
+		svn commit -m "hi" &&
+		svn up &&
+		svn cp branches/v1/start tags/end &&
+		echo "bye" >> tags/end/src/b/readme &&
+		poke tags/end/src/b/readme &&
+		echo "aye" >> tags/end/src/a/readme &&
+		poke tags/end/src/a/readme &&
+		svn commit -m "the end" &&
+		echo "byebye" >> tags/end/src/b/readme &&
+		poke tags/end/src/b/readme &&
+		svn commit -m "nothing to see here"
+	) &&
+	git config --add svn-remote.svn.url "$svnrepo" &&
+	git config --add svn-remote.svn.fetch \
+	                 "trunk/src/a:refs/remotes/trunk" &&
+	git config --add svn-remote.svn.branches \
+	                 "branches/*/*/src/a:refs/remotes/branches/*/*" &&
+	git config --add svn-remote.svn.tags\
+	                 "tags/*/src/a:refs/remotes/tags/*" &&
+	git-svn multi-fetch &&
+	git log --pretty=oneline refs/remotes/tags/end | \
+	    sed -e "s/^.\{41\}//" > output.end &&
+	test_cmp expect.end output.end &&
+	test "`git rev-parse refs/remotes/tags/end~1`" = \
+		"`git rev-parse refs/remotes/branches/v1/start`" &&
+	test "`git rev-parse refs/remotes/branches/v1/start~2`" = \
+		"`git rev-parse refs/remotes/trunk`" &&
+	test_must_fail git rev-parse refs/remotes/tags/end@3
+	'
+
+echo try to try > expect.two
+echo nothing to see here >> expect.two
+cat expect.end >> expect.two
+
+test_expect_success 'test left-hand-side only globbing' '
+	git config --add svn-remote.two.url "$svnrepo" &&
+	git config --add svn-remote.two.fetch trunk:refs/remotes/two/trunk &&
+	git config --add svn-remote.two.branches \
+	                 "branches/*/*:refs/remotes/two/branches/*/*" &&
+	git config --add svn-remote.two.tags \
+	                 "tags/*:refs/remotes/two/tags/*" &&
+	(
+		cd tmp &&
+		echo "try try" >> tags/end/src/b/readme &&
+		poke tags/end/src/b/readme &&
+		svn commit -m "try to try"
+	) &&
+	git-svn fetch two &&
+	test `git rev-list refs/remotes/two/tags/end | wc -l` -eq 6 &&
+	test `git rev-list refs/remotes/two/branches/v1/start | wc -l` -eq 3 &&
+	test `git rev-parse refs/remotes/two/branches/v1/start~2` = \
+	     `git rev-parse refs/remotes/two/trunk` &&
+	test `git rev-parse refs/remotes/two/tags/end~3` = \
+	     `git rev-parse refs/remotes/two/branches/v1/start` &&
+	git log --pretty=oneline refs/remotes/two/tags/end | \
+	    sed -e "s/^.\{41\}//" > output.two &&
+	test_cmp expect.two output.two
+	'
+cat > expect.four <<EOF
+adios
+adding more
+Changed 2 in v2/start
+Another versioned branch
+initial
+EOF
+
+test_expect_success 'test another branch' '
+	(
+		cd tmp &&
+		mkdir branches/v2 &&
+		svn add branches/v2 &&
+		svn cp trunk branches/v2/start &&
+		svn commit -m "Another versioned branch" &&
+		svn up &&
+		echo "hello" >> branches/v2/start/src/b/readme &&
+		poke branches/v2/start/src/b/readme &&
+		echo "howdy" >> branches/v2/start/src/a/readme &&
+		poke branches/v2/start/src/a/readme &&
+		svn commit -m "Changed 2 in v2/start" &&
+		svn up &&
+		svn cp branches/v2/start tags/next &&
+		echo "bye" >> tags/next/src/b/readme &&
+		poke tags/next/src/b/readme &&
+		echo "aye" >> tags/next/src/a/readme &&
+		poke tags/next/src/a/readme &&
+		svn commit -m "adding more" &&
+		echo "byebye" >> tags/next/src/b/readme &&
+		poke tags/next/src/b/readme &&
+		svn commit -m "adios"
+	) &&
+	git config --add svn-remote.four.url "$svnrepo" &&
+	git config --add svn-remote.four.fetch trunk:refs/remotes/four/trunk &&
+	git config --add svn-remote.four.branches \
+	                 "branches/*/*:refs/remotes/four/branches/*/*" &&
+	git config --add svn-remote.four.tags \
+	                 "tags/*:refs/remotes/four/tags/*" &&
+	git-svn fetch four &&
+	test `git rev-list refs/remotes/four/tags/next | wc -l` -eq 5 &&
+	test `git rev-list refs/remotes/four/branches/v2/start | wc -l` -eq 3 &&
+	test `git rev-parse refs/remotes/four/branches/v2/start~2` = \
+	     `git rev-parse refs/remotes/four/trunk` &&
+	test `git rev-parse refs/remotes/four/tags/next~2` = \
+	     `git rev-parse refs/remotes/four/branches/v2/start` &&
+	git log --pretty=oneline refs/remotes/four/tags/next | \
+	    sed -e "s/^.\{41\}//" > output.four &&
+	test_cmp expect.four output.four
+	'
+
+echo "Only one set of wildcard directories" \
+     "(e.g. '*' or '*/*/*') is supported: 'branches/*/t/*'" > expect.three
+echo "" >> expect.three
+
+test_expect_success 'test disallow multiple globs' '
+	git config --add svn-remote.three.url "$svnrepo" &&
+	git config --add svn-remote.three.fetch \
+	                 trunk:refs/remotes/three/trunk &&
+	git config --add svn-remote.three.branches \
+	                 "branches/*/t/*:refs/remotes/three/branches/*/*" &&
+	git config --add svn-remote.three.tags \
+	                 "tags/*:refs/remotes/three/tags/*" &&
+	(
+		cd tmp &&
+		echo "try try" >> tags/end/src/b/readme &&
+		poke tags/end/src/b/readme &&
+		svn commit -m "try to try"
+	) &&
+	test_must_fail git-svn fetch three 2> stderr.three &&
+	test_cmp expect.three stderr.three
+	'
+
+test_done
diff --git a/t/t9110-git-svn-use-svm-props.sh b/t/t9110-git-svn-use-svm-props.sh
index 047659f..04d2a65 100755
--- a/t/t9110-git-svn-use-svm-props.sh
+++ b/t/t9110-git-svn-use-svm-props.sh
@@ -49,4 +49,13 @@
 	   grep '^git-svn-id: $dir_url@1 $uuid$'
 	"
 
+test_expect_success 'find commit based on SVN revision number' "
+        git-svn find-rev r12 |
+	    grep `git rev-parse HEAD`
+        "
+
+test_expect_success 'empty rebase' "
+	git-svn rebase
+	"
+
 test_done
diff --git a/t/t9113-git-svn-dcommit-new-file.sh b/t/t9113-git-svn-dcommit-new-file.sh
index 31c929b..c2b24a4 100755
--- a/t/t9113-git-svn-dcommit-new-file.sh
+++ b/t/t9113-git-svn-dcommit-new-file.sh
@@ -7,21 +7,16 @@
 # I don't like the idea of taking a port and possibly leaving a
 # daemon running on a users system if the test fails.
 # Not all git users will need to interact with SVN.
-test -z "$SVNSERVE_PORT" && exit 0
 
 test_description='git-svn dcommit new files over svn:// test'
 
 . ./lib-git-svn.sh
 
-start_svnserve () {
-	svnserve --listen-port $SVNSERVE_PORT \
-	         --root "$rawsvnrepo" \
-	         --listen-once \
-	         --listen-host 127.0.0.1 &
-}
+require_svnserve
 
 test_expect_success 'start tracking an empty repo' '
 	svn mkdir -m "empty dir" "$svnrepo"/empty-dir &&
+	echo "[general]" > "$rawsvnrepo"/conf/svnserve.conf &&
 	echo anon-access = write >> "$rawsvnrepo"/conf/svnserve.conf &&
 	start_svnserve &&
 	git svn init svn://127.0.0.1:$SVNSERVE_PORT &&
diff --git a/t/t9118-git-svn-funky-branch-names.sh b/t/t9118-git-svn-funky-branch-names.sh
index 3281cbd..43ceb75 100755
--- a/t/t9118-git-svn-funky-branch-names.sh
+++ b/t/t9118-git-svn-funky-branch-names.sh
@@ -6,6 +6,10 @@
 test_description='git-svn funky branch names'
 . ./lib-git-svn.sh
 
+# Abo-Uebernahme (Bug #994)
+scary_uri='Abo-Uebernahme%20%28Bug%20%23994%29'
+scary_ref='Abo-Uebernahme%20(Bug%20#994)'
+
 test_expect_success 'setup svnrepo' '
 	mkdir project project/trunk project/branches project/tags &&
 	echo foo > project/trunk/foo &&
@@ -15,6 +19,8 @@
 	                "$svnrepo/pr ject/branches/fun plugin" &&
 	svn cp -m "more fun!" "$svnrepo/pr ject/branches/fun plugin" \
 	                      "$svnrepo/pr ject/branches/more fun plugin!" &&
+	svn cp -m "scary" "$svnrepo/pr ject/branches/fun plugin" \
+	              "$svnrepo/pr ject/branches/$scary_uri" &&
 	start_httpd
 	'
 
@@ -23,6 +29,7 @@
 	cd project &&
 		git rev-parse "refs/remotes/fun%20plugin" &&
 		git rev-parse "refs/remotes/more%20fun%20plugin!" &&
+		git rev-parse "refs/remotes/$scary_ref" &&
 	cd ..
 	'
 
@@ -35,6 +42,15 @@
 	cd ..
 	"
 
+test_expect_success 'test dcommit to scary branch' '
+	cd project &&
+	git reset --hard "refs/remotes/$scary_ref" &&
+	echo urls are scary >> foo &&
+	git commit -m "eep" -- foo &&
+	git svn dcommit &&
+	cd ..
+	'
+
 stop_httpd
 
 test_done
diff --git a/t/t9119-git-svn-info.sh b/t/t9119-git-svn-info.sh
index cc61911..5fd36a1 100755
--- a/t/t9119-git-svn-info.sh
+++ b/t/t9119-git-svn-info.sh
@@ -5,20 +5,38 @@
 test_description='git-svn info'
 
 . ./lib-git-svn.sh
-say 'skipping svn-info test (has a race undiagnosed yet)'
-test_done
+
+set -e
+
+# Tested with: svn, version 1.4.4 (r25188)
+v=`svn --version | sed -n -e 's/^svn, version \(1\.4\.[0-9]\).*$/\1/p'`
+case $v in
+1.4.*)
+	;;
+*)
+	say "skipping svn-info test (SVN version: $v not supported)"
+	test_done
+	;;
+esac
 
 ptouch() {
 	perl -w -e '
 		use strict;
+		use POSIX qw(mktime);
 		die "ptouch requires exactly 2 arguments" if @ARGV != 2;
-		die "$ARGV[0] does not exist" if ! -e $ARGV[0];
-		my @s = stat $ARGV[0];
-		utime $s[8], $s[9], $ARGV[1];
-	' "$1" "$2"
+		my $text_last_updated = shift @ARGV;
+		my $git_file = shift @ARGV;
+		die "\"$git_file\" does not exist" if ! -e $git_file;
+		if ($text_last_updated
+		    =~ /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/) {
+			my $mtime = mktime($6, $5, $4, $3, $2 - 1, $1 - 1900);
+			my $atime = $mtime;
+			utime $atime, $mtime, $git_file;
+		}
+	' "`svn info $2 | grep '^Text Last Updated:'`" "$1"
 }
 
-test_expect_success 'setup repository and import' "
+test_expect_success 'setup repository and import' '
 	mkdir info &&
 	cd info &&
 		echo FIRST > A &&
@@ -27,19 +45,19 @@
 		mkdir directory &&
 		touch directory/.placeholder &&
 		ln -s directory symlink-directory &&
-		svn import -m 'initial' . $svnrepo &&
+		svn import -m "initial" . "$svnrepo" &&
 	cd .. &&
 	mkdir gitwc &&
 	cd gitwc &&
-		git-svn init $svnrepo &&
+		git-svn init "$svnrepo" &&
 		git-svn fetch &&
 	cd .. &&
-	svn co $svnrepo svnwc &&
+	svn co "$svnrepo" svnwc &&
 	ptouch svnwc/file gitwc/file &&
 	ptouch svnwc/directory gitwc/directory &&
 	ptouch svnwc/symlink-file gitwc/symlink-file &&
 	ptouch svnwc/symlink-directory gitwc/symlink-directory
-	"
+	'
 
 test_expect_success 'info' "
 	(cd svnwc; svn info) > expected.info &&
@@ -48,7 +66,7 @@
 	"
 
 test_expect_success 'info --url' '
-	test $(cd gitwc; git-svn info --url) = $svnrepo
+	test "$(cd gitwc; git-svn info --url)" = "$svnrepo"
 	'
 
 test_expect_success 'info .' "
@@ -58,7 +76,7 @@
 	"
 
 test_expect_success 'info --url .' '
-	test $(cd gitwc; git-svn info --url .) = $svnrepo
+	test "$(cd gitwc; git-svn info --url .)" = "$svnrepo"
 	'
 
 test_expect_success 'info file' "
@@ -68,7 +86,7 @@
 	"
 
 test_expect_success 'info --url file' '
-	test $(cd gitwc; git-svn info --url file) = "$svnrepo/file"
+	test "$(cd gitwc; git-svn info --url file)" = "$svnrepo/file"
 	'
 
 test_expect_success 'info directory' "
@@ -78,7 +96,7 @@
 	"
 
 test_expect_success 'info --url directory' '
-	test $(cd gitwc; git-svn info --url directory) = "$svnrepo/directory"
+	test "$(cd gitwc; git-svn info --url directory)" = "$svnrepo/directory"
 	'
 
 test_expect_success 'info symlink-file' "
@@ -88,7 +106,7 @@
 	"
 
 test_expect_success 'info --url symlink-file' '
-	test $(cd gitwc; git-svn info --url symlink-file) \
+	test "$(cd gitwc; git-svn info --url symlink-file)" \
 	     = "$svnrepo/symlink-file"
 	'
 
@@ -101,7 +119,7 @@
 	"
 
 test_expect_success 'info --url symlink-directory' '
-	test $(cd gitwc; git-svn info --url symlink-directory) \
+	test "$(cd gitwc; git-svn info --url symlink-directory)" \
 	     = "$svnrepo/symlink-directory"
 	'
 
@@ -121,7 +139,7 @@
 	"
 
 test_expect_success 'info --url added-file' '
-	test $(cd gitwc; git-svn info --url added-file) \
+	test "$(cd gitwc; git-svn info --url added-file)" \
 	     = "$svnrepo/added-file"
 	'
 
@@ -143,7 +161,7 @@
 	"
 
 test_expect_success 'info --url added-directory' '
-	test $(cd gitwc; git-svn info --url added-directory) \
+	test "$(cd gitwc; git-svn info --url added-directory)" \
 	     = "$svnrepo/added-directory"
 	'
 
@@ -166,7 +184,7 @@
 	"
 
 test_expect_success 'info --url added-symlink-file' '
-	test $(cd gitwc; git-svn info --url added-symlink-file) \
+	test "$(cd gitwc; git-svn info --url added-symlink-file)" \
 	     = "$svnrepo/added-symlink-file"
 	'
 
@@ -189,7 +207,7 @@
 	"
 
 test_expect_success 'info --url added-symlink-directory' '
-	test $(cd gitwc; git-svn info --url added-symlink-directory) \
+	test "$(cd gitwc; git-svn info --url added-symlink-directory)" \
 	     = "$svnrepo/added-symlink-directory"
 	'
 
@@ -215,7 +233,7 @@
 	"
 
 test_expect_success 'info --url file (deleted)' '
-	test $(cd gitwc; git-svn info --url file) \
+	test "$(cd gitwc; git-svn info --url file)" \
 	     = "$svnrepo/file"
 	'
 
@@ -236,7 +254,7 @@
 	"
 
 test_expect_success 'info --url directory (deleted)' '
-	test $(cd gitwc; git-svn info --url directory) \
+	test "$(cd gitwc; git-svn info --url directory)" \
 	     = "$svnrepo/directory"
 	'
 
@@ -258,7 +276,7 @@
 	"
 
 test_expect_success 'info --url symlink-file (deleted)' '
-	test $(cd gitwc; git-svn info --url symlink-file) \
+	test "$(cd gitwc; git-svn info --url symlink-file)" \
 	     = "$svnrepo/symlink-file"
 	'
 
@@ -280,7 +298,7 @@
 	"
 
 test_expect_success 'info --url symlink-directory (deleted)' '
-	test $(cd gitwc; git-svn info --url symlink-directory) \
+	test "$(cd gitwc; git-svn info --url symlink-directory)" \
 	     = "$svnrepo/symlink-directory"
 	'
 
@@ -297,8 +315,8 @@
 	"
 
 test_expect_success 'info --url unknown-file' '
-	test -z $(cd gitwc; git-svn info --url unknown-file \
-			2> ../actual.info--url-unknown-file) &&
+	test -z "$(cd gitwc; git-svn info --url unknown-file \
+			2> ../actual.info--url-unknown-file)" &&
 	git-diff expected.info-unknown-file actual.info--url-unknown-file
 	'
 
@@ -314,8 +332,8 @@
 	"
 
 test_expect_success 'info --url unknown-directory' '
-	test -z $(cd gitwc; git-svn info --url unknown-directory \
-			2> ../actual.info--url-unknown-directory) &&
+	test -z "$(cd gitwc; git-svn info --url unknown-directory \
+			2> ../actual.info--url-unknown-directory)" &&
 	git-diff expected.info-unknown-directory \
 		 actual.info--url-unknown-directory
 	'
@@ -337,8 +355,8 @@
 	"
 
 test_expect_success 'info --url unknown-symlink-file' '
-	test -z $(cd gitwc; git-svn info --url unknown-symlink-file \
-			2> ../actual.info--url-unknown-symlink-file) &&
+	test -z "$(cd gitwc; git-svn info --url unknown-symlink-file \
+			2> ../actual.info--url-unknown-symlink-file)" &&
 	git-diff expected.info-unknown-symlink-file \
 		 actual.info--url-unknown-symlink-file
 	'
@@ -361,8 +379,8 @@
 	"
 
 test_expect_success 'info --url unknown-symlink-directory' '
-	test -z $(cd gitwc; git-svn info --url unknown-symlink-directory \
-			2> ../actual.info--url-unknown-symlink-directory) &&
+	test -z "$(cd gitwc; git-svn info --url unknown-symlink-directory \
+			2> ../actual.info--url-unknown-symlink-directory)" &&
 	git-diff expected.info-unknown-symlink-directory \
 		 actual.info--url-unknown-symlink-directory
 	'
diff --git a/t/t9124-git-svn-dcommit-auto-props.sh b/t/t9124-git-svn-dcommit-auto-props.sh
new file mode 100755
index 0000000..8223c59
--- /dev/null
+++ b/t/t9124-git-svn-dcommit-auto-props.sh
@@ -0,0 +1,86 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Brad King
+
+test_description='git-svn dcommit honors auto-props'
+
+. ./lib-git-svn.sh
+
+generate_auto_props() {
+cat << EOF
+[miscellany]
+enable-auto-props=$1
+[auto-props]
+*.sh  = svn:mime-type=application/x-shellscript; svn:eol-style=LF
+*.txt = svn:mime-type=text/plain; svn:eol-style = native
+EOF
+}
+
+test_expect_success 'initialize git-svn' '
+	mkdir import &&
+	(
+		cd import &&
+		echo foo >foo &&
+		svn import -m "import for git-svn" . "$svnrepo"
+	) &&
+	rm -rf import &&
+	git-svn init "$svnrepo"
+	git-svn fetch
+'
+
+test_expect_success 'enable auto-props config' '
+	cd "$gittestrepo" &&
+	mkdir user &&
+	generate_auto_props yes >user/config
+'
+
+test_expect_success 'add files matching auto-props' '
+	cd "$gittestrepo" &&
+	echo "#!$SHELL_PATH" >exec1.sh &&
+	chmod +x exec1.sh &&
+	echo "hello" >hello.txt &&
+	echo bar >bar &&
+	git add exec1.sh hello.txt bar &&
+	git commit -m "files for enabled auto-props" &&
+	git svn dcommit --config-dir=user
+'
+
+test_expect_success 'disable auto-props config' '
+	cd "$gittestrepo" &&
+	generate_auto_props no >user/config
+'
+
+test_expect_success 'add files matching disabled auto-props' '
+	cd "$gittestrepo" &&
+	echo "#$SHELL_PATH" >exec2.sh &&
+	chmod +x exec2.sh &&
+	echo "world" >world.txt &&
+	echo zot >zot &&
+	git add exec2.sh world.txt zot &&
+	git commit -m "files for disabled auto-props" &&
+	git svn dcommit --config-dir=user
+'
+
+test_expect_success 'check resulting svn repository' '
+	mkdir work &&
+	cd work &&
+	svn co "$svnrepo" &&
+	cd svnrepo &&
+
+	# Check properties from first commit.
+	test "x$(svn propget svn:executable exec1.sh)" = "x*" &&
+	test "x$(svn propget svn:mime-type exec1.sh)" = \
+	     "xapplication/x-shellscript" &&
+	test "x$(svn propget svn:mime-type hello.txt)" = "xtext/plain" &&
+	test "x$(svn propget svn:eol-style hello.txt)" = "xnative" &&
+	test "x$(svn propget svn:mime-type bar)" = "x" &&
+
+	# Check properties from second commit.
+	test "x$(svn propget svn:executable exec2.sh)" = "x*" &&
+	test "x$(svn propget svn:mime-type exec2.sh)" = "x" &&
+	test "x$(svn propget svn:mime-type world.txt)" = "x" &&
+	test "x$(svn propget svn:eol-style world.txt)" = "x" &&
+	test "x$(svn propget svn:mime-type zot)" = "x"
+'
+
+test_done
diff --git a/t/t9125-git-svn-multi-glob-branch-names.sh b/t/t9125-git-svn-multi-glob-branch-names.sh
new file mode 100755
index 0000000..6b62b52
--- /dev/null
+++ b/t/t9125-git-svn-multi-glob-branch-names.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+# Copyright (c) 2008 Marcus Griep
+
+test_description='git-svn multi-glob branch names'
+. ./lib-git-svn.sh
+
+test_expect_success 'setup svnrepo' '
+	mkdir project project/trunk project/branches \
+			project/branches/v14.1 project/tags &&
+	echo foo > project/trunk/foo &&
+	svn import -m "$test_description" project "$svnrepo/project" &&
+	rm -rf project &&
+	svn cp -m "fun" "$svnrepo/project/trunk" \
+	                "$svnrepo/project/branches/v14.1/beta" &&
+	svn cp -m "more fun!" "$svnrepo/project/branches/v14.1/beta" \
+	                      "$svnrepo/project/branches/v14.1/gold"
+	'
+
+test_expect_success 'test clone with multi-glob in branch names' '
+	git svn clone -T trunk -b branches/*/* -t tags \
+	              "$svnrepo/project" project &&
+	cd project &&
+		git rev-parse "refs/remotes/v14.1/beta" &&
+		git rev-parse "refs/remotes/v14.1/gold" &&
+	cd ..
+	'
+
+test_expect_success 'test dcommit to multi-globbed branch' "
+	cd project &&
+	git reset --hard 'refs/remotes/v14.1/gold' &&
+	echo hello >> foo &&
+	git commit -m 'hello' -- foo &&
+	git svn dcommit &&
+	cd ..
+	"
+
+test_done
diff --git a/t/t9126-git-svn-follow-deleted-readded-directory.sh b/t/t9126-git-svn-follow-deleted-readded-directory.sh
new file mode 100755
index 0000000..edec640
--- /dev/null
+++ b/t/t9126-git-svn-follow-deleted-readded-directory.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Alec Berryman
+
+test_description='git svn fetch repository with deleted and readded directory'
+
+. ./lib-git-svn.sh
+
+# Don't run this by default; it opens up a port.
+require_svnserve
+
+test_expect_success 'load repository' '
+    svnadmin load -q "$rawsvnrepo" < "$TEST_DIRECTORY"/t9126/follow-deleted-readded.dump
+    '
+
+test_expect_success 'fetch repository' '
+    start_svnserve &&
+    git svn init svn://127.0.0.1:$SVNSERVE_PORT &&
+    git svn fetch
+    '
+
+test_done
diff --git a/t/t9126/follow-deleted-readded.dump b/t/t9126/follow-deleted-readded.dump
new file mode 100644
index 0000000..19da5d1
--- /dev/null
+++ b/t/t9126/follow-deleted-readded.dump
@@ -0,0 +1,201 @@
+SVN-fs-dump-format-version: 2
+
+UUID: 1807dc6f-c693-4cda-9710-00e1be8c1f21
+
+Revision-number: 0
+Prop-content-length: 56
+Content-length: 56
+
+K 8
+svn:date
+V 27
+2008-09-14T19:53:13.006748Z
+PROPS-END
+
+Revision-number: 1
+Prop-content-length: 111
+Content-length: 111
+
+K 7
+svn:log
+V 12
+Create trunk
+K 10
+svn:author
+V 4
+alec
+K 8
+svn:date
+V 27
+2008-09-14T19:53:13.239689Z
+PROPS-END
+
+Node-path: trunk
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 2
+Prop-content-length: 119
+Content-length: 119
+
+K 7
+svn:log
+V 20
+Create trunk/project
+K 10
+svn:author
+V 4
+alec
+K 8
+svn:date
+V 27
+2008-09-14T19:53:13.548860Z
+PROPS-END
+
+Node-path: trunk/project
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 3
+Prop-content-length: 111
+Content-length: 111
+
+K 7
+svn:log
+V 12
+add new file
+K 10
+svn:author
+V 4
+alec
+K 8
+svn:date
+V 27
+2008-09-14T19:53:15.433630Z
+PROPS-END
+
+Node-path: trunk/project/foo
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 4
+Text-content-md5: d3b07384d113edec49eaa6238ad5ff00
+Content-length: 14
+
+PROPS-END
+foo
+
+
+Revision-number: 4
+Prop-content-length: 116
+Content-length: 116
+
+K 7
+svn:log
+V 17
+change foo to bar
+K 10
+svn:author
+V 4
+alec
+K 8
+svn:date
+V 27
+2008-09-14T19:53:17.339884Z
+PROPS-END
+
+Node-path: trunk/project/foo
+Node-kind: file
+Node-action: change
+Text-content-length: 4
+Text-content-md5: c157a79031e1c40f85931829bc5fc552
+Content-length: 4
+
+bar
+
+
+Revision-number: 5
+Prop-content-length: 114
+Content-length: 114
+
+K 7
+svn:log
+V 15
+don't like that
+K 10
+svn:author
+V 4
+alec
+K 8
+svn:date
+V 27
+2008-09-14T19:53:19.335001Z
+PROPS-END
+
+Node-path: trunk/project
+Node-action: delete
+
+
+Revision-number: 6
+Prop-content-length: 110
+Content-length: 110
+
+K 7
+svn:log
+V 11
+reset trunk
+K 10
+svn:author
+V 4
+alec
+K 8
+svn:date
+V 27
+2008-09-14T19:53:19.845897Z
+PROPS-END
+
+Node-path: trunk/project
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 4
+Node-copyfrom-path: trunk/project
+
+
+Revision-number: 7
+Prop-content-length: 113
+Content-length: 113
+
+K 7
+svn:log
+V 14
+change to quux
+K 10
+svn:author
+V 4
+alec
+K 8
+svn:date
+V 27
+2008-09-14T19:53:21.367947Z
+PROPS-END
+
+Node-path: trunk/project/foo
+Node-kind: file
+Node-action: change
+Text-content-length: 5
+Text-content-md5: d3b07a382ec010c01889250fce66fb13
+Content-length: 5
+
+quux
+
+
diff --git a/t/t9200-git-cvsexportcommit.sh b/t/t9200-git-cvsexportcommit.sh
index b1dc32d..3e32e84 100755
--- a/t/t9200-git-cvsexportcommit.sh
+++ b/t/t9200-git-cvsexportcommit.sh
@@ -100,7 +100,7 @@
      git commit -a -m "generation 2" &&
      id=$(git rev-list --max-count=1 HEAD) &&
      (cd "$CVSWORK" &&
-     ! git cvsexportcommit -c $id
+     test_must_fail git cvsexportcommit -c $id
      )'
 
 #test_expect_success \
@@ -112,7 +112,7 @@
 #     git commit -a -m "generation 3" &&
 #     id=$(git rev-list --max-count=1 HEAD) &&
 #     (cd "$CVSWORK" &&
-#     ! git cvsexportcommit -c $id
+#     test_must_fail git cvsexportcommit -c $id
 #     )'
 
 # We reuse the state from two tests back here
@@ -222,7 +222,7 @@
       git commit -a -m "Update two" &&
       id=$(git rev-list --max-count=1 HEAD) &&
       (cd "$CVSWORK" &&
-      ! git-cvsexportcommit -c $id
+      test_must_fail git-cvsexportcommit -c $id
       )'
 
 case "$(git config --bool core.filemode)" in
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index 5edf56f..8b79de5 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -56,6 +56,12 @@
 M 644 :3 file3
 M 755 :4 file4
 
+tag series-A
+from :5
+data <<EOF
+An annotated tag without a tagger
+EOF
+
 INPUT_END
 test_expect_success \
     'A: create pack from stdin' \
@@ -102,6 +108,18 @@
 	'git cat-file blob master:file4 >actual && test_cmp expect actual'
 
 cat >expect <<EOF
+object $(git rev-parse refs/heads/master)
+type commit
+tag series-A
+
+An annotated tag without a tagger
+EOF
+test_expect_success 'A: verify tag/series-A' '
+	git cat-file tag tags/series-A >actual &&
+	test_cmp expect actual
+'
+
+cat >expect <<EOF
 :2 `git rev-parse --verify master:file2`
 :3 `git rev-parse --verify master:file3`
 :4 `git rev-parse --verify master:file4`
@@ -166,7 +184,7 @@
 
 INPUT_END
 test_expect_success 'B: fail on invalid blob sha1' '
-    ! git-fast-import <input
+    test_must_fail git-fast-import <input
 '
 rm -f .git/objects/pack_* .git/objects/index_*
 
@@ -181,7 +199,7 @@
 
 INPUT_END
 test_expect_success 'B: fail on invalid branch name ".badbranchname"' '
-    ! git-fast-import <input
+    test_must_fail git-fast-import <input
 '
 rm -f .git/objects/pack_* .git/objects/index_*
 
@@ -196,7 +214,7 @@
 
 INPUT_END
 test_expect_success 'B: fail on invalid branch name "bad[branch]name"' '
-    ! git-fast-import <input
+    test_must_fail git-fast-import <input
 '
 rm -f .git/objects/pack_* .git/objects/index_*
 
@@ -340,7 +358,7 @@
 
 INPUT_END
 test_expect_success 'E: rfc2822 date, --date-format=raw' '
-    ! git-fast-import --date-format=raw <input
+    test_must_fail git-fast-import --date-format=raw <input
 '
 test_expect_success \
     'E: rfc2822 date, --date-format=rfc2822' \
@@ -918,4 +936,156 @@
 	 grep "progress " <input >expect &&
 	 test_cmp expect actual'
 
+###
+### series P (gitlinks)
+###
+
+cat >input <<INPUT_END
+blob
+mark :1
+data 10
+test file
+
+reset refs/heads/sub
+commit refs/heads/sub
+mark :2
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data 12
+sub_initial
+M 100644 :1 file
+
+blob
+mark :3
+data <<DATAEND
+[submodule "sub"]
+	path = sub
+	url = "`pwd`/sub"
+DATAEND
+
+commit refs/heads/subuse1
+mark :4
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data 8
+initial
+from refs/heads/master
+M 100644 :3 .gitmodules
+M 160000 :2 sub
+
+blob
+mark :5
+data 20
+test file
+more data
+
+commit refs/heads/sub
+mark :6
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data 11
+sub_second
+from :2
+M 100644 :5 file
+
+commit refs/heads/subuse1
+mark :7
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data 7
+second
+from :4
+M 160000 :6 sub
+
+INPUT_END
+
+test_expect_success \
+	'P: supermodule & submodule mix' \
+	'git-fast-import <input &&
+	 git checkout subuse1 &&
+	 rm -rf sub && mkdir sub && cd sub &&
+	 git init &&
+	 git fetch --update-head-ok .. refs/heads/sub:refs/heads/master &&
+	 git checkout master &&
+	 cd .. &&
+	 git submodule init &&
+	 git submodule update'
+
+SUBLAST=$(git-rev-parse --verify sub)
+SUBPREV=$(git-rev-parse --verify sub^)
+
+cat >input <<INPUT_END
+blob
+mark :1
+data <<DATAEND
+[submodule "sub"]
+	path = sub
+	url = "`pwd`/sub"
+DATAEND
+
+commit refs/heads/subuse2
+mark :2
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data 8
+initial
+from refs/heads/master
+M 100644 :1 .gitmodules
+M 160000 $SUBPREV sub
+
+commit refs/heads/subuse2
+mark :3
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data 7
+second
+from :2
+M 160000 $SUBLAST sub
+
+INPUT_END
+
+test_expect_success \
+	'P: verbatim SHA gitlinks' \
+	'git branch -D sub &&
+	 git gc && git prune &&
+	 git-fast-import <input &&
+	 test $(git-rev-parse --verify subuse2) = $(git-rev-parse --verify subuse1)'
+
+test_tick
+cat >input <<INPUT_END
+commit refs/heads/subuse3
+mark :1
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+corrupt
+COMMIT
+
+from refs/heads/subuse2
+M 160000 inline sub
+data <<DATA
+$SUBPREV
+DATA
+
+INPUT_END
+
+test_expect_success 'P: fail on inline gitlink' '
+    test_must_fail git-fast-import <input'
+
+test_tick
+cat >input <<INPUT_END
+blob
+mark :1
+data <<DATA
+$SUBPREV
+DATA
+
+commit refs/heads/subuse3
+mark :2
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+corrupt
+COMMIT
+
+from refs/heads/subuse2
+M 160000 :1 sub
+
+INPUT_END
+
+test_expect_success 'P: fail on blob mark in gitlink' '
+    test_must_fail git-fast-import <input'
+
 test_done
diff --git a/t/t9301-fast-export.sh b/t/t9301-fast-export.sh
index f09bfb1..3a6509a 100755
--- a/t/t9301-fast-export.sh
+++ b/t/t9301-fast-export.sh
@@ -59,7 +59,7 @@
 		 test $MASTER != $(git rev-parse --verify refs/heads/partial) &&
 		 git diff master..partial &&
 		 git diff master^..partial^ &&
-		 ! git rev-parse partial~2)
+		 test_must_fail git rev-parse partial~2)
 
 '
 
@@ -78,6 +78,29 @@
 		 git cat-file commit i18n | grep "Áéí óú")
 
 '
+test_expect_success 'import/export-marks' '
+
+	git checkout -b marks master &&
+	git fast-export --export-marks=tmp-marks HEAD &&
+	test -s tmp-marks &&
+	test $(wc -l < tmp-marks) -eq 3 &&
+	test $(
+		git fast-export --import-marks=tmp-marks\
+		--export-marks=tmp-marks HEAD |
+		grep ^commit |
+		wc -l) \
+	-eq 0 &&
+	echo change > file &&
+	git commit -m "last commit" file &&
+	test $(
+		git fast-export --import-marks=tmp-marks \
+		--export-marks=tmp-marks HEAD |
+		grep ^commit\  |
+		wc -l) \
+	-eq 1 &&
+	test $(wc -l < tmp-marks) -eq 4
+
+'
 
 cat > signed-tag-import << EOF
 tag sign-your-name
@@ -102,7 +125,7 @@
 
 test_expect_success 'signed-tags=abort' '
 
-	! git fast-export --signed-tags=abort sign-your-name
+	test_must_fail git fast-export --signed-tags=abort sign-your-name
 
 '
 
@@ -120,4 +143,120 @@
 
 '
 
+test_expect_success 'setup submodule' '
+
+	git checkout -f master &&
+	mkdir sub &&
+	cd sub &&
+	git init  &&
+	echo test file > file &&
+	git add file &&
+	git commit -m sub_initial &&
+	cd .. &&
+	git submodule add "`pwd`/sub" sub &&
+	git commit -m initial &&
+	test_tick &&
+	cd sub &&
+	echo more data >> file &&
+	git add file &&
+	git commit -m sub_second &&
+	cd .. &&
+	git add sub &&
+	git commit -m second
+
+'
+
+test_expect_success 'submodule fast-export | fast-import' '
+
+	SUBENT1=$(git ls-tree master^ sub) &&
+	SUBENT2=$(git ls-tree master sub) &&
+	rm -rf new &&
+	mkdir new &&
+	git --git-dir=new/.git init &&
+	git fast-export --signed-tags=strip --all |
+	(cd new &&
+	 git fast-import &&
+	 test "$SUBENT1" = "$(git ls-tree refs/heads/master^ sub)" &&
+	 test "$SUBENT2" = "$(git ls-tree refs/heads/master sub)" &&
+	 git checkout master &&
+	 git submodule init &&
+	 git submodule update &&
+	 cmp sub/file ../sub/file)
+
+'
+
+export GIT_AUTHOR_NAME='A U Thor'
+export GIT_COMMITTER_NAME='C O Mitter'
+
+test_expect_success 'setup copies' '
+
+	git config --unset i18n.commitencoding &&
+	git checkout -b copy rein &&
+	git mv file file3 &&
+	git commit -m move1 &&
+	test_tick &&
+	cp file2 file4 &&
+	git add file4 &&
+	git mv file2 file5 &&
+	git commit -m copy1 &&
+	test_tick &&
+	cp file3 file6 &&
+	git add file6 &&
+	git commit -m copy2 &&
+	test_tick &&
+	echo more text >> file6 &&
+	echo even more text >> file6 &&
+	git add file6 &&
+	git commit -m modify &&
+	test_tick &&
+	cp file6 file7 &&
+	echo test >> file7 &&
+	git add file7 &&
+	git commit -m copy_modify
+
+'
+
+test_expect_success 'fast-export -C -C | fast-import' '
+
+	ENTRY=$(git rev-parse --verify copy) &&
+	rm -rf new &&
+	mkdir new &&
+	git --git-dir=new/.git init &&
+	git fast-export -C -C --signed-tags=strip --all > output &&
+	grep "^C \"file6\" \"file7\"\$" output &&
+	cat output |
+	(cd new &&
+	 git fast-import &&
+	 test $ENTRY = $(git rev-parse --verify refs/heads/copy))
+
+'
+
+test_expect_success 'fast-export | fast-import when master is tagged' '
+
+	git tag -m msg last &&
+	git fast-export -C -C --signed-tags=strip --all > output &&
+	test $(grep -c "^tag " output) = 3
+
+'
+
+cat > tag-content << EOF
+object $(git rev-parse HEAD)
+type commit
+tag rosten
+EOF
+
+test_expect_success 'cope with tagger-less tags' '
+
+	TAG=$(git hash-object -t tag -w tag-content) &&
+	git update-ref refs/tags/sonnenschein $TAG &&
+	git fast-export -C -C --signed-tags=strip --all > output &&
+	test $(grep -c "^tag " output) = 4 &&
+	! grep "Unspecified Tagger" output &&
+	git fast-export -C -C --signed-tags=strip --all \
+		--fake-missing-tagger > output &&
+	test $(grep -c "^tag " output) = 4 &&
+	grep "Unspecified Tagger" output
+
+'
+
 test_done
diff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh
index e97aaa6..c1850d2 100755
--- a/t/t9400-git-cvsserver-server.sh
+++ b/t/t9400-git-cvsserver-server.sh
@@ -438,6 +438,13 @@
     test -z "$(cat failures)"
 '
 
+cd "$WORKDIR"
+test_expect_success 'cvs update (module list supports packed refs)' '
+    GIT_DIR="$SERVERDIR" git pack-refs --all &&
+    GIT_CONFIG="$git_config" cvs -n up -d 2> out &&
+    grep "cvs update: New directory \`master'\''" < out
+'
+
 #------------
 # CVS STATUS
 #------------
@@ -470,4 +477,28 @@
     ! grep / <../out
 '
 
+#------------
+# CVS CHECKOUT
+#------------
+
+cd "$WORKDIR"
+test_expect_success 'cvs co -c (shows module database)' '
+    GIT_CONFIG="$git_config" cvs co -c > out &&
+    grep "^master[	 ]\+master$" < out &&
+    ! grep -v "^master[	 ]\+master$" < out
+'
+
+#------------
+# CVS ANNOTATE
+#------------
+
+cd "$WORKDIR"
+test_expect_success 'cvs annotate' '
+    cd cvswork &&
+    GIT_CONFIG="$git_config" cvs annotate merge >../out &&
+    sed -e "s/ .*//" ../out >../actual &&
+    for i in 3 1 1 1 1 1 1 1 2 4; do echo 1.$i; done >../expect &&
+    test_cmp ../expect ../actual
+'
+
 test_done
diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh
index ae7082b..d8f278f 100755
--- a/t/t9500-gitweb-standalone-no-errors.sh
+++ b/t/t9500-gitweb-standalone-no-errors.sh
@@ -503,6 +503,55 @@
 test_debug 'cat gitweb.log'
 
 # ----------------------------------------------------------------------
+# path_info links
+test_expect_success \
+	'path_info: project' \
+	'gitweb_run "" "/.git"'
+test_debug 'cat gitweb.log'
+
+test_expect_success \
+	'path_info: project/branch' \
+	'gitweb_run "" "/.git/b"'
+test_debug 'cat gitweb.log'
+
+test_expect_success \
+	'path_info: project/branch:file' \
+	'gitweb_run "" "/.git/master:file"'
+test_debug 'cat gitweb.log'
+
+test_expect_success \
+	'path_info: project/branch:dir/' \
+	'gitweb_run "" "/.git/master:foo/"'
+test_debug 'cat gitweb.log'
+
+test_expect_success \
+	'path_info: project/branch:file (non-existent)' \
+	'gitweb_run "" "/.git/master:non-existent"'
+test_debug 'cat gitweb.log'
+
+test_expect_success \
+	'path_info: project/branch:dir/ (non-existent)' \
+	'gitweb_run "" "/.git/master:non-existent/"'
+test_debug 'cat gitweb.log'
+
+
+test_expect_success \
+	'path_info: project/branch:/file' \
+	'gitweb_run "" "/.git/master:/file"'
+test_debug 'cat gitweb.log'
+
+test_expect_success \
+	'path_info: project/:/file (implicit HEAD)' \
+	'gitweb_run "" "/.git/:/file"'
+test_debug 'cat gitweb.log'
+
+test_expect_success \
+	'path_info: project/:/ (implicit HEAD, top tree)' \
+	'gitweb_run "" "/.git/:/"'
+test_debug 'cat gitweb.log'
+
+
+# ----------------------------------------------------------------------
 # feed generation
 
 test_expect_success \
diff --git a/t/t9600-cvsimport.sh b/t/t9600-cvsimport.sh
index 655f882..0d7786a 100755
--- a/t/t9600-cvsimport.sh
+++ b/t/t9600-cvsimport.sh
@@ -5,6 +5,7 @@
 
 CVSROOT=$(pwd)/cvsroot
 export CVSROOT
+unset CVS_SERVER
 # for clean cvsps cache
 HOME=$(pwd)
 export HOME
@@ -18,7 +19,7 @@
 
 cvsps_version=`cvsps -h 2>&1 | sed -ne 's/cvsps version //p'`
 case "$cvsps_version" in
-2.1)
+2.1 | 2.2*)
 	;;
 '')
 	say 'skipping cvsimport tests, cvsps not found'
@@ -26,7 +27,7 @@
 	exit
 	;;
 *)
-	say 'skipping cvsimport tests, cvsps too old'
+	say 'skipping cvsimport tests, unsupported cvsps version'
 	test_done
 	exit
 	;;
diff --git a/t/t9700-perl-git.sh b/t/t9700-perl-git.sh
new file mode 100755
index 0000000..9706ee5
--- /dev/null
+++ b/t/t9700-perl-git.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Lea Wiemann
+#
+
+test_description='perl interface (Git.pm)'
+. ./test-lib.sh
+
+perl -MTest::More -e 0 2>/dev/null || {
+	say_color skip "Perl Test::More unavailable, skipping test"
+	test_done
+}
+
+# set up test repository
+
+test_expect_success \
+    'set up test repository' \
+    'echo "test file 1" > file1 &&
+     echo "test file 2" > file2 &&
+     mkdir directory1 &&
+     echo "in directory1" >> directory1/file &&
+     mkdir directory2 &&
+     echo "in directory2" >> directory2/file &&
+     git add . &&
+     git commit -m "first commit" &&
+
+     echo "changed file 1" > file1 &&
+     git commit -a -m "second commit" &&
+
+     git-config --add color.test.slot1 green &&
+     git-config --add test.string value &&
+     git-config --add test.dupstring value1 &&
+     git-config --add test.dupstring value2 &&
+     git-config --add test.booltrue true &&
+     git-config --add test.boolfalse no &&
+     git-config --add test.boolother other &&
+     git-config --add test.int 2k
+     '
+
+test_external_without_stderr \
+    'Perl API' \
+    perl ../t9700/test.pl
+
+test_done
diff --git a/t/t9700/test.pl b/t/t9700/test.pl
new file mode 100755
index 0000000..504f95a
--- /dev/null
+++ b/t/t9700/test.pl
@@ -0,0 +1,103 @@
+#!/usr/bin/perl
+use lib (split(/:/, $ENV{GITPERLLIB}));
+
+use 5.006002;
+use warnings;
+use strict;
+
+use Test::More qw(no_plan);
+
+use Cwd;
+use File::Basename;
+
+BEGIN { use_ok('Git') }
+
+# set up
+our $repo_dir = "trash directory";
+our $abs_repo_dir = Cwd->cwd;
+die "this must be run by calling the t/t97* shell script(s)\n"
+    if basename(Cwd->cwd) ne $repo_dir;
+ok(our $r = Git->repository(Directory => "."), "open repository");
+
+# config
+is($r->config("test.string"), "value", "config scalar: string");
+is_deeply([$r->config("test.dupstring")], ["value1", "value2"],
+	  "config array: string");
+is($r->config("test.nonexistent"), undef, "config scalar: nonexistent");
+is_deeply([$r->config("test.nonexistent")], [], "config array: nonexistent");
+is($r->config_int("test.int"), 2048, "config_int: integer");
+is($r->config_int("test.nonexistent"), undef, "config_int: nonexistent");
+ok($r->config_bool("test.booltrue"), "config_bool: true");
+ok(!$r->config_bool("test.boolfalse"), "config_bool: false");
+our $ansi_green = "\x1b[32m";
+is($r->get_color("color.test.slot1", "red"), $ansi_green, "get_color");
+# Cannot test $r->get_colorbool("color.foo")) because we do not
+# control whether our STDOUT is a terminal.
+
+# Failure cases for config:
+# Save and restore STDERR; we will probably extract this into a
+# "dies_ok" method and possibly move the STDERR handling to Git.pm.
+open our $tmpstderr, ">&STDERR" or die "cannot save STDERR"; close STDERR;
+eval { $r->config("test.dupstring") };
+ok($@, "config: duplicate entry in scalar context fails");
+eval { $r->config_bool("test.boolother") };
+ok($@, "config_bool: non-boolean values fail");
+open STDERR, ">&", $tmpstderr or die "cannot restore STDERR";
+
+# ident
+like($r->ident("aUthor"), qr/^A U Thor <author\@example.com> [0-9]+ \+0000$/,
+     "ident scalar: author (type)");
+like($r->ident("cOmmitter"), qr/^C O Mitter <committer\@example.com> [0-9]+ \+0000$/,
+     "ident scalar: committer (type)");
+is($r->ident("invalid"), "invalid", "ident scalar: invalid ident string (no parsing)");
+my ($name, $email, $time_tz) = $r->ident('author');
+is_deeply([$name, $email], ["A U Thor", "author\@example.com"],
+	 "ident array: author");
+like($time_tz, qr/[0-9]+ \+0000/, "ident array: author");
+is_deeply([$r->ident("Name <email> 123 +0000")], ["Name", "email", "123 +0000"],
+	  "ident array: ident string");
+is_deeply([$r->ident("invalid")], [], "ident array: invalid ident string");
+
+# ident_person
+is($r->ident_person("aUthor"), "A U Thor <author\@example.com>",
+   "ident_person: author (type)");
+is($r->ident_person("Name <email> 123 +0000"), "Name <email>",
+   "ident_person: ident string");
+is($r->ident_person("Name", "email", "123 +0000"), "Name <email>",
+   "ident_person: array");
+
+# objects and hashes
+ok(our $file1hash = $r->command_oneline('rev-parse', "HEAD:file1"), "(get file hash)");
+my $tmpfile = "file.tmp";
+open TEMPFILE, "+>$tmpfile" or die "Can't open $tmpfile: $!";
+is($r->cat_blob($file1hash, \*TEMPFILE), 15, "cat_blob: size");
+our $blobcontents;
+{ local $/; seek TEMPFILE, 0, 0; $blobcontents = <TEMPFILE>; }
+is($blobcontents, "changed file 1\n", "cat_blob: data");
+close TEMPFILE or die "Failed writing to $tmpfile: $!";
+is(Git::hash_object("blob", $tmpfile), $file1hash, "hash_object: roundtrip");
+open TEMPFILE, ">$tmpfile" or die "Can't open $tmpfile: $!";
+print TEMPFILE my $test_text = "test blob, to be inserted\n";
+close TEMPFILE or die "Failed writing to $tmpfile: $!";
+like(our $newhash = $r->hash_and_insert_object($tmpfile), qr/[0-9a-fA-F]{40}/,
+     "hash_and_insert_object: returns hash");
+open TEMPFILE, "+>$tmpfile" or die "Can't open $tmpfile: $!";
+is($r->cat_blob($newhash, \*TEMPFILE), length $test_text, "cat_blob: roundtrip size");
+{ local $/; seek TEMPFILE, 0, 0; $blobcontents = <TEMPFILE>; }
+is($blobcontents, $test_text, "cat_blob: roundtrip data");
+close TEMPFILE;
+unlink $tmpfile;
+
+# paths
+is($r->repo_path, "./.git", "repo_path");
+is($r->wc_path, $abs_repo_dir . "/", "wc_path");
+is($r->wc_subdir, "", "wc_subdir initial");
+$r->wc_chdir("directory1");
+is($r->wc_subdir, "directory1", "wc_subdir after wc_chdir");
+TODO: {
+	local $TODO = "commands do not work after wc_chdir";
+	# Failure output is active even in non-verbose mode and thus
+	# annoying.  Hence we skip these tests as long as they fail.
+	todo_skip 'config after wc_chdir', 1;
+	is($r->config("color.string"), "value", "config after wc_chdir");
+}
diff --git a/t/test-lib.sh b/t/test-lib.sh
index c861141..689ac2f 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -35,6 +35,7 @@
 unset GIT_EXTERNAL_DIFF
 unset GIT_INDEX_FILE
 unset GIT_OBJECT_DIRECTORY
+unset GIT_CEILING_DIRECTORIES
 unset SHA1_FILE_DIRECTORIES
 unset SHA1_FILE_DIRECTORY
 GIT_MERGE_VERBOSITY=5
@@ -80,6 +81,8 @@
 		debug=t; shift ;;
 	-i|--i|--im|--imm|--imme|--immed|--immedi|--immedia|--immediat|--immediate)
 		immediate=t; shift ;;
+	-l|--l|--lo|--lon|--long|--long-|--long-t|--long-te|--long-tes|--long-test|--long-tests)
+		export GIT_TEST_LONG=t; shift ;;
 	-h|--h|--he|--hel|--help)
 		help=t; shift ;;
 	-v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose)
@@ -109,8 +112,9 @@
 			*) test -n "$quiet" && return;;
 		esac
 		shift
-		echo "* $*"
+		printf "* %s" "$*"
 		tput sgr0
+		echo
 		)
 	}
 else
@@ -152,6 +156,7 @@
 test_count=0
 test_fixed=0
 test_broken=0
+test_success=0
 
 die () {
 	echo >&5 "FATAL: Unexpected exit with code $?"
@@ -193,6 +198,7 @@
 
 test_ok_ () {
 	test_count=$(expr "$test_count" + 1)
+	test_success=$(expr "$test_success" + 1)
 	say_color "" "  ok $test_count: $@"
 }
 
@@ -302,6 +308,64 @@
 	echo >&3 ""
 }
 
+# test_external runs external test scripts that provide continuous
+# test output about their progress, and succeeds/fails on
+# zero/non-zero exit code.  It outputs the test output on stdout even
+# in non-verbose mode, and announces the external script with "* run
+# <n>: ..." before running it.  When providing relative paths, keep in
+# mind that all scripts run in "trash directory".
+# Usage: test_external description command arguments...
+# Example: test_external 'Perl API' perl ../path/to/test.pl
+test_external () {
+	test "$#" -eq 3 ||
+	error >&5 "bug in the test script: not 3 parameters to test_external"
+	descr="$1"
+	shift
+	if ! test_skip "$descr" "$@"
+	then
+		# Announce the script to reduce confusion about the
+		# test output that follows.
+		say_color "" " run $(expr "$test_count" + 1): $descr ($*)"
+		# Run command; redirect its stderr to &4 as in
+		# test_run_, but keep its stdout on our stdout even in
+		# non-verbose mode.
+		"$@" 2>&4
+		if [ "$?" = 0 ]
+		then
+			test_ok_ "$descr"
+		else
+			test_failure_ "$descr" "$@"
+		fi
+	fi
+}
+
+# Like test_external, but in addition tests that the command generated
+# no output on stderr.
+test_external_without_stderr () {
+	# The temporary file has no (and must have no) security
+	# implications.
+	tmp="$TMPDIR"; if [ -z "$tmp" ]; then tmp=/tmp; fi
+	stderr="$tmp/git-external-stderr.$$.tmp"
+	test_external "$@" 4> "$stderr"
+	[ -f "$stderr" ] || error "Internal error: $stderr disappeared."
+	descr="no stderr: $1"
+	shift
+	say >&3 "expecting no stderr from previous command"
+	if [ ! -s "$stderr" ]; then
+		rm "$stderr"
+		test_ok_ "$descr"
+	else
+		if [ "$verbose" = t ]; then
+			output=`echo; echo Stderr is:; cat "$stderr"`
+		else
+			output=
+		fi
+		# rm first in case test_failure exits.
+		rm "$stderr"
+		test_failure_ "$descr" "$@" "$output"
+	fi
+}
+
 # This is not among top-level (test_expect_success | test_expect_failure)
 # but is a prefix that can be used in the test script, like:
 #
@@ -316,7 +380,7 @@
 
 test_must_fail () {
 	"$@"
-	test $? -gt 0 -a $? -le 129
+	test $? -gt 0 -a $? -le 129 -o $? -gt 192
 }
 
 # test_cmp is a helper function to compare actual and expected output.
@@ -345,7 +409,7 @@
 	repo="$1"
 	mkdir "$repo"
 	cd "$repo" || error "Cannot setup test environment"
-	"$GIT_EXEC_PATH/git" init "--template=$GIT_EXEC_PATH/templates/blt/" >/dev/null 2>&1 ||
+	"$GIT_EXEC_PATH/git" init "--template=$GIT_EXEC_PATH/templates/blt/" >&3 2>&4 ||
 	error "cannot run git init -- have you built things yet?"
 	mv .git/hooks .git/hooks-disabled
 	cd "$owd"
@@ -353,6 +417,16 @@
 
 test_done () {
 	trap - exit
+	test_results_dir="$TEST_DIRECTORY/test-results"
+	mkdir -p "$test_results_dir"
+	test_results_path="$test_results_dir/${0%-*}-$$"
+
+	echo "total $test_count" >> $test_results_path
+	echo "success $test_success" >> $test_results_path
+	echo "fixed $test_fixed" >> $test_results_path
+	echo "broken $test_broken" >> $test_results_path
+	echo "failed $test_failure" >> $test_results_path
+	echo "" >> $test_results_path
 
 	if test "$test_fixed" != 0
 	then
@@ -387,7 +461,8 @@
 
 # Test the binaries we have just built.  The tests are kept in
 # t/ subdirectory and are run in 'trash directory' subdirectory.
-PATH=$(pwd)/..:$PATH
+TEST_DIRECTORY=$(pwd)
+PATH=$TEST_DIRECTORY/..:$PATH
 GIT_EXEC_PATH=$(pwd)/..
 GIT_TEMPLATE_DIR=$(pwd)/../templates/blt
 unset GIT_CONFIG
diff --git a/templates/Makefile b/templates/Makefile
index bda9d13..a12c6e2 100644
--- a/templates/Makefile
+++ b/templates/Makefile
@@ -8,12 +8,12 @@
 TAR ?= tar
 RM ?= rm -f
 prefix ?= $(HOME)
-template_dir ?= $(prefix)/share/git-core/templates
+template_instdir ?= $(prefix)/share/git-core/templates
 # DESTDIR=
 
 # Shell quote (do not use $(call) to accommodate ancient setups);
 DESTDIR_SQ = $(subst ','\'',$(DESTDIR))
-template_dir_SQ = $(subst ','\'',$(template_dir))
+template_instdir_SQ = $(subst ','\'',$(template_instdir))
 
 all: boilerplates.made custom
 
@@ -23,17 +23,19 @@
 
 bpsrc = $(filter-out %~,$(wildcard *--*))
 boilerplates.made : $(bpsrc)
-	$(QUIET)ls *--* 2>/dev/null | \
+	$(QUIET)umask 022 && ls *--* 2>/dev/null | \
 	while read boilerplate; \
 	do \
 		case "$$boilerplate" in *~) continue ;; esac && \
 		dst=`echo "$$boilerplate" | sed -e 's|^this|.|;s|--|/|g'` && \
 		dir=`expr "$$dst" : '\(.*\)/'` && \
-		$(INSTALL) -d -m 755 blt/$$dir && \
+		mkdir -p blt/$$dir && \
 		case "$$boilerplate" in \
-		*--) ;; \
-		*) cp -p $$boilerplate blt/$$dst ;; \
-		esac || exit; \
+		*--) continue;; \
+		esac && \
+		cp $$boilerplate blt/$$dst && \
+		if test -x "blt/$$dst"; then rx=rx; else rx=r; fi && \
+		chmod a+$$rx "blt/$$dst" || exit; \
 	done && \
 	date >$@
 
@@ -46,6 +48,6 @@
 	$(RM) -r blt boilerplates.made
 
 install: all
-	$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(template_dir_SQ)'
+	$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(template_instdir_SQ)'
 	(cd blt && $(TAR) cf - .) | \
-	(cd '$(DESTDIR_SQ)$(template_dir_SQ)' && umask 022 && $(TAR) xf -)
+	(cd '$(DESTDIR_SQ)$(template_instdir_SQ)' && umask 022 && $(TAR) xfo -)
diff --git a/templates/hooks--applypatch-msg b/templates/hooks--applypatch-msg.sample
old mode 100644
new mode 100755
similarity index 86%
rename from templates/hooks--applypatch-msg
rename to templates/hooks--applypatch-msg.sample
index 02de1ef..8b2a2fe
--- a/templates/hooks--applypatch-msg
+++ b/templates/hooks--applypatch-msg.sample
@@ -7,7 +7,7 @@
 # appropriate message if it wants to stop the commit.  The hook is
 # allowed to edit the commit message file.
 #
-# To enable this hook, make this file executable.
+# To enable this hook, rename this file to "applypatch-msg".
 
 . git-sh-setup
 test -x "$GIT_DIR/hooks/commit-msg" &&
diff --git a/templates/hooks--commit-msg b/templates/hooks--commit-msg.sample
old mode 100644
new mode 100755
similarity index 93%
rename from templates/hooks--commit-msg
rename to templates/hooks--commit-msg.sample
index 4ef86eb..6ef1d29
--- a/templates/hooks--commit-msg
+++ b/templates/hooks--commit-msg.sample
@@ -6,7 +6,7 @@
 # status after issuing an appropriate message if it wants to stop the
 # commit.  The hook is allowed to edit the commit message file.
 #
-# To enable this hook, make this file executable.
+# To enable this hook, rename this file to "commit-msg".
 
 # Uncomment the below to add a Signed-off-by line to the message.
 # Doing this in a hook is a bad idea in general, but the prepare-commit-msg
diff --git a/templates/hooks--post-commit b/templates/hooks--post-commit.sample
old mode 100644
new mode 100755
similarity index 63%
rename from templates/hooks--post-commit
rename to templates/hooks--post-commit.sample
index 8be6f34..2266821
--- a/templates/hooks--post-commit
+++ b/templates/hooks--post-commit.sample
@@ -3,6 +3,6 @@
 # An example hook script that is called after a successful
 # commit is made.
 #
-# To enable this hook, make this file executable.
+# To enable this hook, rename this file to "post-commit".
 
 : Nothing
diff --git a/templates/hooks--post-receive b/templates/hooks--post-receive
deleted file mode 100644
index b70c8fd..0000000
--- a/templates/hooks--post-receive
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/sh
-#
-# An example hook script for the post-receive event
-#
-# This script is run after receive-pack has accepted a pack and the
-# repository has been updated.  It is passed arguments in through stdin
-# in the form
-#  <oldrev> <newrev> <refname>
-# For example:
-#  aa453216d1b3e49e7f6f98441fa56946ddcd6a20 68f7abf4e6f922807889f52bc043ecd31b79f814 refs/heads/master
-#
-# see contrib/hooks/ for an sample, or uncomment the next line (on debian)
-#
-
-
-#. /usr/share/doc/git-core/contrib/hooks/post-receive-email
diff --git a/templates/hooks--post-receive.sample b/templates/hooks--post-receive.sample
new file mode 100755
index 0000000..18d2e0f
--- /dev/null
+++ b/templates/hooks--post-receive.sample
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# An example hook script for the "post-receive" event.
+#
+# The "post-receive" script is run after receive-pack has accepted a pack
+# and the repository has been updated.  It is passed arguments in through
+# stdin in the form
+#  <oldrev> <newrev> <refname>
+# For example:
+#  aa453216d1b3e49e7f6f98441fa56946ddcd6a20 68f7abf4e6f922807889f52bc043ecd31b79f814 refs/heads/master
+#
+# see contrib/hooks/ for an sample, or uncomment the next line and
+# rename the file to "post-receive".
+
+#. /usr/share/doc/git-core/contrib/hooks/post-receive-email
diff --git a/templates/hooks--post-update b/templates/hooks--post-update.sample
old mode 100644
new mode 100755
similarity index 63%
rename from templates/hooks--post-update
rename to templates/hooks--post-update.sample
index bcba893..5323b56
--- a/templates/hooks--post-update
+++ b/templates/hooks--post-update.sample
@@ -3,6 +3,6 @@
 # An example hook script to prepare a packed repository for use over
 # dumb transports.
 #
-# To enable this hook, make this file executable by "chmod +x post-update".
+# To enable this hook, rename this file to "post-update".
 
 exec git-update-server-info
diff --git a/templates/hooks--pre-applypatch b/templates/hooks--pre-applypatch.sample
old mode 100644
new mode 100755
similarity index 84%
rename from templates/hooks--pre-applypatch
rename to templates/hooks--pre-applypatch.sample
index eeccc93..b1f187c
--- a/templates/hooks--pre-applypatch
+++ b/templates/hooks--pre-applypatch.sample
@@ -6,7 +6,7 @@
 # The hook should exit with non-zero status after issuing an
 # appropriate message if it wants to stop the commit.
 #
-# To enable this hook, make this file executable.
+# To enable this hook, rename this file to "pre-applypatch".
 
 . git-sh-setup
 test -x "$GIT_DIR/hooks/pre-commit" &&
diff --git a/templates/hooks--pre-commit b/templates/hooks--pre-commit
deleted file mode 100644
index b25dce6..0000000
--- a/templates/hooks--pre-commit
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/bin/sh
-#
-# An example hook script to verify what is about to be committed.
-# Called by git-commit with no arguments.  The hook should
-# exit with non-zero status after issuing an appropriate message if
-# it wants to stop the commit.
-#
-# To enable this hook, make this file executable.
-
-# This is slightly modified from Andrew Morton's Perfect Patch.
-# Lines you introduce should not have trailing whitespace.
-# Also check for an indentation that has SP before a TAB.
-
-if git-rev-parse --verify HEAD 2>/dev/null
-then
-	git-diff-index -p -M --cached HEAD --
-else
-	# NEEDSWORK: we should produce a diff with an empty tree here
-	# if we want to do the same verification for the initial import.
-	:
-fi |
-perl -e '
-    my $found_bad = 0;
-    my $filename;
-    my $reported_filename = "";
-    my $lineno;
-    sub bad_line {
-	my ($why, $line) = @_;
-	if (!$found_bad) {
-	    print STDERR "*\n";
-	    print STDERR "* You have some suspicious patch lines:\n";
-	    print STDERR "*\n";
-	    $found_bad = 1;
-	}
-	if ($reported_filename ne $filename) {
-	    print STDERR "* In $filename\n";
-	    $reported_filename = $filename;
-	}
-	print STDERR "* $why (line $lineno)\n";
-	print STDERR "$filename:$lineno:$line\n";
-    }
-    while (<>) {
-	if (m|^diff --git a/(.*) b/\1$|) {
-	    $filename = $1;
-	    next;
-	}
-	if (/^@@ -\S+ \+(\d+)/) {
-	    $lineno = $1 - 1;
-	    next;
-	}
-	if (/^ /) {
-	    $lineno++;
-	    next;
-	}
-	if (s/^\+//) {
-	    $lineno++;
-	    chomp;
-	    if (/\s$/) {
-		bad_line("trailing whitespace", $_);
-	    }
-	    if (/^\s* \t/) {
-		bad_line("indent SP followed by a TAB", $_);
-	    }
-	    if (/^([<>])\1{6} |^={7}$/) {
-		bad_line("unresolved merge conflict", $_);
-	    }
-	}
-    }
-    exit($found_bad);
-'
diff --git a/templates/hooks--pre-commit.sample b/templates/hooks--pre-commit.sample
new file mode 100755
index 0000000..0e49279
--- /dev/null
+++ b/templates/hooks--pre-commit.sample
@@ -0,0 +1,18 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed.
+# Called by git-commit with no arguments.  The hook should
+# exit with non-zero status after issuing an appropriate message if
+# it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-commit".
+
+if git-rev-parse --verify HEAD 2>/dev/null
+then
+	against=HEAD
+else
+	# Initial commit: diff against an empty tree object
+	against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+fi
+
+exec git diff-index --check --cached $against --
diff --git a/templates/hooks--pre-rebase b/templates/hooks--pre-rebase.sample
old mode 100644
new mode 100755
similarity index 83%
rename from templates/hooks--pre-rebase
rename to templates/hooks--pre-rebase.sample
index 981c454..be1b06e
--- a/templates/hooks--pre-rebase
+++ b/templates/hooks--pre-rebase.sample
@@ -1,7 +1,19 @@
 #!/bin/sh
 #
-# Copyright (c) 2006 Junio C Hamano
+# Copyright (c) 2006, 2008 Junio C Hamano
 #
+# The "pre-rebase" hook is run just before "git-rebase" starts doing
+# its job, and can prevent the command from running by exiting with
+# non-zero status.
+#
+# The hook is called with the following parameters:
+#
+# $1 -- the upstream the series was forked from.
+# $2 -- the branch being rebased (or empty when rebasing the current branch).
+#
+# This sample shows how to prevent topic branches that are already
+# merged to 'next' branch from getting rebased, because allowing it
+# would result in rebasing already published history.
 
 publish=next
 basebranch="$1"
@@ -9,11 +21,12 @@
 then
 	topic="refs/heads/$2"
 else
-	topic=`git symbolic-ref HEAD`
+	topic=`git symbolic-ref HEAD` ||
+	exit 0 ;# we do not interrupt rebasing detached HEAD
 fi
 
-case "$basebranch,$topic" in
-master,refs/heads/??/*)
+case "$topic" in
+refs/heads/??/*)
 	;;
 *)
 	exit 0 ;# we do not interrupt others.
@@ -23,6 +36,12 @@
 # Now we are dealing with a topic branch being rebased
 # on top of master.  Is it OK to rebase it?
 
+# Does the topic really exist?
+git show-ref -q "$topic" || {
+	echo >&2 "No such branch $topic"
+	exit 1
+}
+
 # Is topic fully merged to master?
 not_in_master=`git-rev-list --pretty=oneline ^master "$topic"`
 if test -z "$not_in_master"
diff --git a/templates/hooks--prepare-commit-msg b/templates/hooks--prepare-commit-msg.sample
old mode 100644
new mode 100755
similarity index 86%
rename from templates/hooks--prepare-commit-msg
rename to templates/hooks--prepare-commit-msg.sample
index d3c1da3..3652424
--- a/templates/hooks--prepare-commit-msg
+++ b/templates/hooks--prepare-commit-msg.sample
@@ -7,7 +7,7 @@
 # message file.  If the hook fails with a non-zero status,
 # the commit is aborted.
 #
-# To enable this hook, make this file executable.
+# To enable this hook, rename this file to "prepare-commit-msg".
 
 # This hook includes three examples.  The first comments out the
 # "Conflicts:" part of a merge commit.
@@ -22,10 +22,10 @@
 
 case "$2,$3" in
   merge,)
-    perl -i -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;
+    perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;
 
 # ,|template,)
-#   perl -i -pe '
+#   perl -i.bak -pe '
 #      print "\n" . `git diff --cached --name-status -r`
 #	 if /^#/ && $first++ == 0' "$1" ;;
 
diff --git a/templates/hooks--update b/templates/hooks--update.sample
old mode 100644
new mode 100755
similarity index 97%
rename from templates/hooks--update
rename to templates/hooks--update.sample
index 4b69268..93c6055
--- a/templates/hooks--update
+++ b/templates/hooks--update.sample
@@ -3,7 +3,7 @@
 # An example hook script to blocks unannotated tags from entering.
 # Called by git-receive-pack with arguments: refname sha1-old sha1-new
 #
-# To enable this hook, make this file executable by "chmod +x update".
+# To enable this hook, rename this file to "update".
 #
 # Config
 # ------
diff --git a/test-absolute-path.c b/test-absolute-path.c
deleted file mode 100644
index c959ea2..0000000
--- a/test-absolute-path.c
+++ /dev/null
@@ -1,11 +0,0 @@
-#include "cache.h"
-
-int main(int argc, char **argv)
-{
-	while (argc > 1) {
-		puts(make_absolute_path(argv[1]));
-		argc--;
-		argv++;
-	}
-	return 0;
-}
diff --git a/test-chmtime.c b/test-chmtime.c
index 90da448..d5358cb 100644
--- a/test-chmtime.c
+++ b/test-chmtime.c
@@ -1,39 +1,83 @@
+/*
+ * This program can either change modification time of the given
+ * file(s) or just print it. The program does not change atime nor
+ * ctime (their values are explicitely preserved).
+ *
+ * The mtime can be changed to an absolute value:
+ *
+ *	test-chmtime =<seconds> file...
+ *
+ * Relative to the current time as returned by time(3):
+ *
+ *	test-chmtime =+<seconds> (or =-<seconds>) file...
+ *
+ * Or relative to the current mtime of the file:
+ *
+ *	test-chmtime <seconds> file...
+ *	test-chmtime +<seconds> (or -<seconds>) file...
+ *
+ * Examples:
+ *
+ * To just print the mtime use --verbose and set the file mtime offset to 0:
+ *
+ *	test-chmtime -v +0 file
+ *
+ * To set the mtime to current time:
+ *
+ *	test-chmtime =+0 file
+ *
+ */
 #include "git-compat-util.h"
 #include <utime.h>
 
-static const char usage_str[] = "(+|=|=+|=-|-)<seconds> <file>...";
+static const char usage_str[] = "-v|--verbose (+|=|=+|=-|-)<seconds> <file>...";
+
+static int timespec_arg(const char *arg, long int *set_time, int *set_eq)
+{
+	char *test;
+	const char *timespec = arg;
+	*set_eq = (*timespec == '=') ? 1 : 0;
+	if (*set_eq) {
+		timespec++;
+		if (*timespec == '+') {
+			*set_eq = 2; /* relative "in the future" */
+			timespec++;
+		}
+	}
+	*set_time = strtol(timespec, &test, 10);
+	if (*test) {
+		fprintf(stderr, "Not a base-10 integer: %s\n", arg + 1);
+		return 0;
+	}
+	if ((*set_eq && *set_time < 0) || *set_eq == 2) {
+		time_t now = time(NULL);
+		*set_time += now;
+	}
+	return 1;
+}
 
 int main(int argc, const char *argv[])
 {
-	int i;
-	int set_eq;
-	long int set_time;
-	char *test;
-	const char *timespec;
+	static int verbose;
+
+	int i = 1;
+	/* no mtime change by default */
+	int set_eq = 0;
+	long int set_time = 0;
 
 	if (argc < 3)
 		goto usage;
 
-	timespec = argv[1];
-	set_eq = (*timespec == '=') ? 1 : 0;
-	if (set_eq) {
-		timespec++;
-		if (*timespec == '+') {
-			set_eq = 2; /* relative "in the future" */
-			timespec++;
-		}
+	if (strcmp(argv[i], "--verbose") == 0 || strcmp(argv[i], "-v") == 0) {
+		verbose = 1;
+		++i;
 	}
-	set_time = strtol(timespec, &test, 10);
-	if (*test) {
-		fprintf(stderr, "Not a base-10 integer: %s\n", argv[1] + 1);
+	if (timespec_arg(argv[i], &set_time, &set_eq))
+		++i;
+	else
 		goto usage;
-	}
-	if ((set_eq && set_time < 0) || set_eq == 2) {
-		time_t now = time(NULL);
-		set_time += now;
-	}
 
-	for (i = 2; i < argc; i++) {
+	for (; i < argc; i++) {
 		struct stat sb;
 		struct utimbuf utb;
 
@@ -46,7 +90,12 @@
 		utb.actime = sb.st_atime;
 		utb.modtime = set_eq ? set_time : sb.st_mtime + set_time;
 
-		if (utime(argv[i], &utb) < 0) {
+		if (verbose) {
+			uintmax_t mtime = utb.modtime < 0 ? 0: utb.modtime;
+			printf("%"PRIuMAX"\t%s\n", mtime, argv[i]);
+		}
+
+		if (utb.modtime != sb.st_mtime && utime(argv[i], &utb) < 0) {
 			fprintf(stderr, "Failed to modify time on %s: %s\n",
 			        argv[i], strerror(errno));
 			return -1;
diff --git a/test-parse-options.c b/test-parse-options.c
index 2a79e72..61d2c39 100644
--- a/test-parse-options.c
+++ b/test-parse-options.c
@@ -2,7 +2,8 @@
 #include "parse-options.h"
 
 static int boolean = 0;
-static unsigned long integer = 0;
+static int integer = 0;
+static unsigned long timestamp;
 static int abbrev = 7;
 static int verbose = 0, dry_run = 0, quiet = 0;
 static char *string = NULL;
@@ -14,7 +15,7 @@
 	if (unset)
 		return 1; /* do not support unset */
 
-	*(unsigned long *)opt->value = strlen(arg);
+	*(int *)opt->value = strlen(arg);
 	return 0;
 }
 
@@ -32,7 +33,7 @@
 		OPT_INTEGER('i', "integer", &integer, "get a integer"),
 		OPT_INTEGER('j', NULL, &integer, "get a integer, too"),
 		OPT_SET_INT(0, "set23", &integer, "set integer to 23", 23),
-		OPT_DATE('t', NULL, &integer, "get timestamp of <time>"),
+		OPT_DATE('t', NULL, &timestamp, "get timestamp of <time>"),
 		OPT_CALLBACK('L', "length", &integer, "str",
 			"get length of <str>", length_callback),
 		OPT_GROUP("String options"),
@@ -56,7 +57,8 @@
 	argc = parse_options(argc, argv, options, usage, 0);
 
 	printf("boolean: %d\n", boolean);
-	printf("integer: %lu\n", integer);
+	printf("integer: %u\n", integer);
+	printf("timestamp: %lu\n", timestamp);
 	printf("string: %s\n", string ? string : "(not set)");
 	printf("abbrev: %d\n", abbrev);
 	printf("verbose: %d\n", verbose);
diff --git a/test-path-utils.c b/test-path-utils.c
new file mode 100644
index 0000000..a0bcb0e
--- /dev/null
+++ b/test-path-utils.c
@@ -0,0 +1,26 @@
+#include "cache.h"
+
+int main(int argc, char **argv)
+{
+	if (argc == 3 && !strcmp(argv[1], "normalize_absolute_path")) {
+		char *buf = xmalloc(strlen(argv[2])+1);
+		int rv = normalize_absolute_path(buf, argv[2]);
+		assert(strlen(buf) == rv);
+		puts(buf);
+	}
+
+	if (argc >= 2 && !strcmp(argv[1], "make_absolute_path")) {
+		while (argc > 2) {
+			puts(make_absolute_path(argv[2]));
+			argc--;
+			argv++;
+		}
+	}
+
+	if (argc == 4 && !strcmp(argv[1], "longest_ancestor_length")) {
+		int len = longest_ancestor_length(argv[2], argv[3]);
+		printf("%d\n", len);
+	}
+
+	return 0;
+}
diff --git a/transport.c b/transport.c
index b3e3e61..35cac44 100644
--- a/transport.c
+++ b/transport.c
@@ -643,8 +643,8 @@
 	args.use_thin_pack = data->thin;
 	args.include_tag = data->followtags;
 	args.verbose = (transport->verbose > 0);
-	args.quiet = args.no_progress = (transport->verbose < 0);
-	args.no_progress = !isatty(1);
+	args.quiet = (transport->verbose < 0);
+	args.no_progress = args.quiet || !isatty(1);
 	args.depth = data->depth;
 
 	for (i = 0; i < nr_heads; i++)
@@ -708,7 +708,8 @@
 {
 	const char *colon = strchr(url, ':');
 	const char *slash = strchr(url, '/');
-	return !colon || (slash && slash < colon);
+	return !colon || (slash && slash < colon) ||
+		has_dos_drive_prefix(url);
 }
 
 static int is_file(const char *url)
diff --git a/tree-diff.c b/tree-diff.c
index bbb126f..9f67af6 100644
--- a/tree-diff.c
+++ b/tree-diff.c
@@ -303,7 +303,7 @@
 			update_tree_entry(t2);
 			continue;
 		}
-		die("git-diff-tree: internal error");
+		die("git diff-tree: internal error");
 	}
 	return 0;
 }
diff --git a/tree.c b/tree.c
index 4b1825c..03e782a 100644
--- a/tree.c
+++ b/tree.c
@@ -29,7 +29,7 @@
 	return add_cache_entry(ce, opt);
 }
 
-static int read_one_entry(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage)
+static int read_one_entry(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, void *context)
 {
 	return read_one_entry_opt(sha1, base, baselen, pathname, mode, stage,
 				  ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DFCHECK);
@@ -39,7 +39,7 @@
  * This is used when the caller knows there is no existing entries at
  * the stage that will conflict with the entry being added.
  */
-static int read_one_entry_quick(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage)
+static int read_one_entry_quick(const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, void *context)
 {
 	return read_one_entry_opt(sha1, base, baselen, pathname, mode, stage,
 				  ADD_CACHE_JUST_APPEND);
@@ -92,7 +92,7 @@
 int read_tree_recursive(struct tree *tree,
 			const char *base, int baselen,
 			int stage, const char **match,
-			read_tree_fn_t fn)
+			read_tree_fn_t fn, void *context)
 {
 	struct tree_desc desc;
 	struct name_entry entry;
@@ -106,7 +106,7 @@
 		if (!match_tree_entry(base, baselen, entry.path, entry.mode, match))
 			continue;
 
-		switch (fn(entry.sha1, base, baselen, entry.path, entry.mode, stage)) {
+		switch (fn(entry.sha1, base, baselen, entry.path, entry.mode, stage, context)) {
 		case 0:
 			continue;
 		case READ_TREE_RECURSIVE:
@@ -126,7 +126,7 @@
 			retval = read_tree_recursive(lookup_tree(entry.sha1),
 						     newbase,
 						     baselen + pathlen + 1,
-						     stage, match, fn);
+						     stage, match, fn, context);
 			free(newbase);
 			if (retval)
 				return -1;
@@ -174,7 +174,7 @@
 
 	if (!fn)
 		fn = read_one_entry_quick;
-	err = read_tree_recursive(tree, "", 0, stage, match, fn);
+	err = read_tree_recursive(tree, "", 0, stage, match, fn, NULL);
 	if (fn == read_one_entry || err)
 		return err;
 
diff --git a/tree.h b/tree.h
index dd25c53..2ff01a4 100644
--- a/tree.h
+++ b/tree.h
@@ -21,12 +21,12 @@
 struct tree *parse_tree_indirect(const unsigned char *sha1);
 
 #define READ_TREE_RECURSIVE 1
-typedef int (*read_tree_fn_t)(const unsigned char *, const char *, int, const char *, unsigned int, int);
+typedef int (*read_tree_fn_t)(const unsigned char *, const char *, int, const char *, unsigned int, int, void *);
 
 extern int read_tree_recursive(struct tree *tree,
 			       const char *base, int baselen,
 			       int stage, const char **match,
-			       read_tree_fn_t fn);
+			       read_tree_fn_t fn, void *context);
 
 extern int read_tree(struct tree *tree, int stage, const char **paths);
 
diff --git a/unpack-trees.c b/unpack-trees.c
index cba0aca..54f301d 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -352,7 +352,7 @@
 	discard_index(&o->result);
 	if (!o->gently) {
 		if (message)
-			return error(message);
+			return error("%s", message);
 		return -1;
 	}
 	return -1;
@@ -376,12 +376,13 @@
 	state.refresh_cache = 1;
 
 	memset(&o->result, 0, sizeof(o->result));
+	o->result.initialized = 1;
 	if (o->src_index)
 		o->result.timestamp = o->src_index->timestamp;
 	o->merge_size = len;
 
 	if (!dfc)
-		dfc = xcalloc(1, sizeof(struct cache_entry) + 1);
+		dfc = xcalloc(1, cache_entry_size(0));
 	o->df_conflict_entry = dfc;
 
 	if (len) {
@@ -940,8 +941,17 @@
 			return -1;
 		}
 	}
-	else if (newtree)
+	else if (newtree) {
+		if (oldtree && !o->initial_checkout) {
+			/*
+			 * deletion of the path was staged;
+			 */
+			if (same(oldtree, newtree))
+				return 1;
+			return reject_merge(oldtree, o);
+		}
 		return merged_entry(newtree, current, o);
+	}
 	return deleted_entry(oldtree, current, o);
 }
 
diff --git a/unpack-trees.h b/unpack-trees.h
index 94e5672..0d26f3d 100644
--- a/unpack-trees.h
+++ b/unpack-trees.h
@@ -26,6 +26,7 @@
 		     verbose_update:1,
 		     aggressive:1,
 		     skip_unmerged:1,
+		     initial_checkout:1,
 		     gently:1;
 	const char *prefix;
 	int pos;
diff --git a/update-server-info.c b/update-server-info.c
index 0b6c383..7e8209e 100644
--- a/update-server-info.c
+++ b/update-server-info.c
@@ -1,7 +1,7 @@
 #include "cache.h"
 
 static const char update_server_info_usage[] =
-"git-update-server-info [--force]";
+"git update-server-info [--force]";
 
 int main(int ac, char **av)
 {
diff --git a/upload-pack.c b/upload-pack.c
index b46dd36..e5adbc0 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -135,6 +135,8 @@
 		die("revision walk setup failed");
 	mark_edges_uninteresting(revs.commits, &revs, show_edge);
 	traverse_commit_list(&revs, show_commit, show_object);
+	fflush(pack_pipe);
+	fclose(pack_pipe);
 	return 0;
 }
 
@@ -155,7 +157,7 @@
 	/* .data is just a boolean: any non-NULL value will do */
 	rev_list.data = create_full_pack ? &rev_list : NULL;
 	if (start_async(&rev_list))
-		die("git-upload-pack: unable to fork git-rev-list");
+		die("git upload-pack: unable to fork git-rev-list");
 
 	argv[arg++] = "pack-objects";
 	argv[arg++] = "--stdout";
@@ -175,7 +177,7 @@
 	pack_objects.argv = argv;
 
 	if (start_command(&pack_objects))
-		die("git-upload-pack: unable to fork git-pack-objects");
+		die("git upload-pack: unable to fork git-pack-objects");
 
 	/* We read from pack_objects.err to capture stderr output for
 	 * progress bar, and pack_objects.out to capture the pack data.
@@ -269,7 +271,7 @@
 	}
 
 	if (finish_command(&pack_objects)) {
-		error("git-upload-pack: git-pack-objects died with error.");
+		error("git upload-pack: git-pack-objects died with error.");
 		goto fail;
 	}
 	if (finish_async(&rev_list))
@@ -289,7 +291,7 @@
 
  fail:
 	send_client_data(3, abort_msg, sizeof(abort_msg));
-	die("git-upload-pack: %s", abort_msg);
+	die("git upload-pack: %s", abort_msg);
 }
 
 static int got_sha1(char *hex, unsigned char *sha1)
@@ -298,7 +300,7 @@
 	int we_knew_they_have = 0;
 
 	if (get_sha1_hex(hex, sha1))
-		die("git-upload-pack: expected SHA1 object, got '%s'", hex);
+		die("git upload-pack: expected SHA1 object, got '%s'", hex);
 	if (!has_sha1_file(sha1))
 		return -1;
 
@@ -438,7 +440,7 @@
 			packet_write(1, "NAK\n");
 			return -1;
 		}
-		die("git-upload-pack: expected SHA1 list, got '%s'", line);
+		die("git upload-pack: expected SHA1 list, got '%s'", line);
 	}
 }
 
@@ -483,7 +485,7 @@
 		}
 		if (prefixcmp(line, "want ") ||
 		    get_sha1_hex(line+5, sha1_buf))
-			die("git-upload-pack: protocol error, "
+			die("git upload-pack: protocol error, "
 			    "expected to get sha, not '%s'", line);
 		if (strstr(line+45, "multi_ack"))
 			multi_ack = 1;
@@ -510,7 +512,7 @@
 		 */
 		o = lookup_object(sha1_buf);
 		if (!o || !(o->flags & OUR_REF))
-			die("git-upload-pack: not our ref %s", line+5);
+			die("git upload-pack: not our ref %s", line+5);
 		if (!(o->flags & WANTED)) {
 			o->flags |= WANTED;
 			add_object_array(o, NULL, &want_obj);
@@ -575,7 +577,7 @@
 	struct object *o = parse_object(sha1);
 
 	if (!o)
-		die("git-upload-pack: cannot find object %s:", sha1_to_hex(sha1));
+		die("git upload-pack: cannot find object %s:", sha1_to_hex(sha1));
 
 	if (capabilities)
 		packet_write(1, "%s %s%c%s\n", sha1_to_hex(sha1), refname,
@@ -636,7 +638,7 @@
 	if (i != argc-1)
 		usage(upload_pack_usage);
 
-	setup_path(NULL);
+	setup_path();
 
 	dir = argv[i];
 
diff --git a/var.c b/var.c
index 724ba87..f1eb314 100644
--- a/var.c
+++ b/var.c
@@ -5,7 +5,7 @@
  */
 #include "cache.h"
 
-static const char var_usage[] = "git-var [-l | <variable>]";
+static const char var_usage[] = "git var [-l | <variable>]";
 
 struct git_var {
 	const char *name;
diff --git a/wrapper.c b/wrapper.c
new file mode 100644
index 0000000..93562f0
--- /dev/null
+++ b/wrapper.c
@@ -0,0 +1,198 @@
+/*
+ * Various trivial helper wrappers around standard functions
+ */
+#include "cache.h"
+
+char *xstrdup(const char *str)
+{
+	char *ret = strdup(str);
+	if (!ret) {
+		release_pack_memory(strlen(str) + 1, -1);
+		ret = strdup(str);
+		if (!ret)
+			die("Out of memory, strdup failed");
+	}
+	return ret;
+}
+
+void *xmalloc(size_t size)
+{
+	void *ret = malloc(size);
+	if (!ret && !size)
+		ret = malloc(1);
+	if (!ret) {
+		release_pack_memory(size, -1);
+		ret = malloc(size);
+		if (!ret && !size)
+			ret = malloc(1);
+		if (!ret)
+			die("Out of memory, malloc failed");
+	}
+#ifdef XMALLOC_POISON
+	memset(ret, 0xA5, size);
+#endif
+	return ret;
+}
+
+/*
+ * xmemdupz() allocates (len + 1) bytes of memory, duplicates "len" bytes of
+ * "data" to the allocated memory, zero terminates the allocated memory,
+ * and returns a pointer to the allocated memory. If the allocation fails,
+ * the program dies.
+ */
+void *xmemdupz(const void *data, size_t len)
+{
+	char *p = xmalloc(len + 1);
+	memcpy(p, data, len);
+	p[len] = '\0';
+	return p;
+}
+
+char *xstrndup(const char *str, size_t len)
+{
+	char *p = memchr(str, '\0', len);
+	return xmemdupz(str, p ? p - str : len);
+}
+
+void *xrealloc(void *ptr, size_t size)
+{
+	void *ret = realloc(ptr, size);
+	if (!ret && !size)
+		ret = realloc(ptr, 1);
+	if (!ret) {
+		release_pack_memory(size, -1);
+		ret = realloc(ptr, size);
+		if (!ret && !size)
+			ret = realloc(ptr, 1);
+		if (!ret)
+			die("Out of memory, realloc failed");
+	}
+	return ret;
+}
+
+void *xcalloc(size_t nmemb, size_t size)
+{
+	void *ret = calloc(nmemb, size);
+	if (!ret && (!nmemb || !size))
+		ret = calloc(1, 1);
+	if (!ret) {
+		release_pack_memory(nmemb * size, -1);
+		ret = calloc(nmemb, size);
+		if (!ret && (!nmemb || !size))
+			ret = calloc(1, 1);
+		if (!ret)
+			die("Out of memory, calloc failed");
+	}
+	return ret;
+}
+
+void *xmmap(void *start, size_t length,
+	int prot, int flags, int fd, off_t offset)
+{
+	void *ret = mmap(start, length, prot, flags, fd, offset);
+	if (ret == MAP_FAILED) {
+		if (!length)
+			return NULL;
+		release_pack_memory(length, fd);
+		ret = mmap(start, length, prot, flags, fd, offset);
+		if (ret == MAP_FAILED)
+			die("Out of memory? mmap failed: %s", strerror(errno));
+	}
+	return ret;
+}
+
+/*
+ * xread() is the same a read(), but it automatically restarts read()
+ * operations with a recoverable error (EAGAIN and EINTR). xread()
+ * DOES NOT GUARANTEE that "len" bytes is read even if the data is available.
+ */
+ssize_t xread(int fd, void *buf, size_t len)
+{
+	ssize_t nr;
+	while (1) {
+		nr = read(fd, buf, len);
+		if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
+			continue;
+		return nr;
+	}
+}
+
+/*
+ * xwrite() is the same a write(), but it automatically restarts write()
+ * operations with a recoverable error (EAGAIN and EINTR). xwrite() DOES NOT
+ * GUARANTEE that "len" bytes is written even if the operation is successful.
+ */
+ssize_t xwrite(int fd, const void *buf, size_t len)
+{
+	ssize_t nr;
+	while (1) {
+		nr = write(fd, buf, len);
+		if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
+			continue;
+		return nr;
+	}
+}
+
+ssize_t read_in_full(int fd, void *buf, size_t count)
+{
+	char *p = buf;
+	ssize_t total = 0;
+
+	while (count > 0) {
+		ssize_t loaded = xread(fd, p, count);
+		if (loaded <= 0)
+			return total ? total : loaded;
+		count -= loaded;
+		p += loaded;
+		total += loaded;
+	}
+
+	return total;
+}
+
+ssize_t write_in_full(int fd, const void *buf, size_t count)
+{
+	const char *p = buf;
+	ssize_t total = 0;
+
+	while (count > 0) {
+		ssize_t written = xwrite(fd, p, count);
+		if (written < 0)
+			return -1;
+		if (!written) {
+			errno = ENOSPC;
+			return -1;
+		}
+		count -= written;
+		p += written;
+		total += written;
+	}
+
+	return total;
+}
+
+int xdup(int fd)
+{
+	int ret = dup(fd);
+	if (ret < 0)
+		die("dup failed: %s", strerror(errno));
+	return ret;
+}
+
+FILE *xfdopen(int fd, const char *mode)
+{
+	FILE *stream = fdopen(fd, mode);
+	if (stream == NULL)
+		die("Out of memory? fdopen failed: %s", strerror(errno));
+	return stream;
+}
+
+int xmkstemp(char *template)
+{
+	int fd;
+
+	fd = mkstemp(template);
+	if (fd < 0)
+		die("Unable to create temporary file: %s", strerror(errno));
+	return fd;
+}
diff --git a/write_or_die.c b/write_or_die.c
index 630be4c..4c29255 100644
--- a/write_or_die.c
+++ b/write_or_die.c
@@ -34,50 +34,17 @@
 			return;
 	}
 	if (fflush(f)) {
-		if (errno == EPIPE)
+		/*
+		 * On Windows, EPIPE is returned only by the first write()
+		 * after the reading end has closed its handle; subsequent
+		 * write()s return EINVAL.
+		 */
+		if (errno == EPIPE || errno == EINVAL)
 			exit(0);
 		die("write failure on %s: %s", desc, strerror(errno));
 	}
 }
 
-ssize_t read_in_full(int fd, void *buf, size_t count)
-{
-	char *p = buf;
-	ssize_t total = 0;
-
-	while (count > 0) {
-		ssize_t loaded = xread(fd, p, count);
-		if (loaded <= 0)
-			return total ? total : loaded;
-		count -= loaded;
-		p += loaded;
-		total += loaded;
-	}
-
-	return total;
-}
-
-ssize_t write_in_full(int fd, const void *buf, size_t count)
-{
-	const char *p = buf;
-	ssize_t total = 0;
-
-	while (count > 0) {
-		ssize_t written = xwrite(fd, p, count);
-		if (written < 0)
-			return -1;
-		if (!written) {
-			errno = ENOSPC;
-			return -1;
-		}
-		count -= written;
-		p += written;
-		total += written;
-	}
-
-	return total;
-}
-
 void fsync_or_die(int fd, const char *msg)
 {
 	if (fsync(fd) < 0) {
diff --git a/ws.c b/ws.c
index ba7e834..7a7ff13 100644
--- a/ws.c
+++ b/ws.c
@@ -117,9 +117,9 @@
 }
 
 /* If stream is non-NULL, emits the line after checking. */
-unsigned check_and_emit_line(const char *line, int len, unsigned ws_rule,
-			     FILE *stream, const char *set,
-			     const char *reset, const char *ws)
+static unsigned ws_check_emit_1(const char *line, int len, unsigned ws_rule,
+				FILE *stream, const char *set,
+				const char *reset, const char *ws)
 {
 	unsigned result = 0;
 	int written = 0;
@@ -213,6 +213,33 @@
 	return result;
 }
 
+void ws_check_emit(const char *line, int len, unsigned ws_rule,
+		   FILE *stream, const char *set,
+		   const char *reset, const char *ws)
+{
+	(void)ws_check_emit_1(line, len, ws_rule, stream, set, reset, ws);
+}
+
+unsigned ws_check(const char *line, int len, unsigned ws_rule)
+{
+	return ws_check_emit_1(line, len, ws_rule, NULL, NULL, NULL, NULL);
+}
+
+int ws_blank_line(const char *line, int len, unsigned ws_rule)
+{
+	/*
+	 * We _might_ want to treat CR differently from other
+	 * whitespace characters when ws_rule has WS_CR_AT_EOL, but
+	 * for now we just use this stupid definition.
+	 */
+	while (len-- > 0) {
+		if (!isspace(*line))
+			return 0;
+		line++;
+	}
+	return 1;
+}
+
 /* Copy the line to the buffer while fixing whitespaces */
 int ws_fix_copy(char *dst, const char *src, int len, unsigned ws_rule, int *error_count)
 {
diff --git a/wt-status.c b/wt-status.c
index 5b4d74c..64cedfc 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -9,6 +9,7 @@
 #include "diffcore.h"
 #include "quote.h"
 #include "run-command.h"
+#include "remote.h"
 
 int wt_status_relative_paths = 1;
 int wt_status_use_color = -1;
@@ -27,6 +28,7 @@
 "use \"git add/rm <file>...\" to update what will be committed";
 static const char use_add_to_include_msg[] =
 "use \"git add <file>...\" to include in what will be committed";
+enum untracked_status_type show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
 
 static int parse_status_slot(const char *var, int offset)
 {
@@ -273,20 +275,9 @@
 
 	read_directory(&dir, ".", "", 0, NULL);
 	for(i = 0; i < dir.nr; i++) {
-		/* check for matching entry, which is unmerged; lifted from
-		 * builtin-ls-files:show_other_files */
 		struct dir_entry *ent = dir.entries[i];
-		int pos = cache_name_pos(ent->name, ent->len);
-		struct cache_entry *ce;
-		if (0 <= pos)
-			die("bug in wt_status_print_untracked");
-		pos = -pos - 1;
-		if (pos < active_nr) {
-			ce = active_cache[pos];
-			if (ce_namelen(ce) == ent->len &&
-			    !memcmp(ce->name, ent->name, ent->len))
-				continue;
-		}
+		if (!cache_name_is_other(ent->name, ent->len))
+			continue;
 		if (!shown_header) {
 			s->workdir_untracked = 1;
 			wt_status_print_header(s, "Untracked files",
@@ -314,6 +305,25 @@
 	run_diff_index(&rev, 1);
 }
 
+static void wt_status_print_tracking(struct wt_status *s)
+{
+	struct strbuf sb = STRBUF_INIT;
+	const char *cp, *ep;
+	struct branch *branch;
+
+	assert(s->branch && !s->is_initial);
+	if (prefixcmp(s->branch, "refs/heads/"))
+		return;
+	branch = branch_get(s->branch + 11);
+	if (!format_tracking_info(branch, &sb))
+		return;
+
+	for (cp = sb.buf; (ep = strchr(cp, '\n')) != NULL; cp = ep + 1)
+		color_fprintf_ln(s->fp, color(WT_STATUS_HEADER),
+				 "# %.*s", (int)(ep - cp), cp);
+	color_fprintf_ln(s->fp, color(WT_STATUS_HEADER), "#");
+}
+
 void wt_status_print(struct wt_status *s)
 {
 	unsigned char sha1[20];
@@ -332,6 +342,8 @@
 		}
 		color_fprintf(s->fp, color(WT_STATUS_HEADER), "# ");
 		color_fprintf_ln(s->fp, branch_color, "%s%s", on_what, branch_name);
+		if (!s->is_initial)
+			wt_status_print_tracking(s);
 	}
 
 	if (s->is_initial) {
@@ -347,7 +359,10 @@
 	wt_status_print_changed(s);
 	if (wt_status_submodule_summary)
 		wt_status_print_submodule_summary(s);
-	wt_status_print_untracked(s);
+	if (show_untracked_files)
+		wt_status_print_untracked(s);
+	else if (s->commitable)
+		 fprintf(s->fp, "# Untracked files not listed (use -u option to show untracked files)\n");
 
 	if (s->verbose && !s->is_initial)
 		wt_status_print_verbose(s);
@@ -362,6 +377,8 @@
 			printf("nothing added to commit but untracked files present (use \"git add\" to track)\n");
 		else if (s->is_initial)
 			printf("nothing to commit (create/copy files and use \"git add\" to track)\n");
+		else if (!show_untracked_files)
+			printf("nothing to commit (use -u to show untracked files)\n");
 		else
 			printf("nothing to commit (working directory clean)\n");
 	}
@@ -391,5 +408,18 @@
 		wt_status_relative_paths = git_config_bool(k, v);
 		return 0;
 	}
+	if (!strcmp(k, "status.showuntrackedfiles")) {
+		if (!v)
+			return config_error_nonbool(k);
+		else if (!strcmp(v, "no"))
+			show_untracked_files = SHOW_NO_UNTRACKED_FILES;
+		else if (!strcmp(v, "normal"))
+			show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
+		else if (!strcmp(v, "all"))
+			show_untracked_files = SHOW_ALL_UNTRACKED_FILES;
+		else
+			return error("Invalid untracked files mode '%s'", v);
+		return 0;
+	}
 	return git_color_default_config(k, v, cb);
 }
diff --git a/wt-status.h b/wt-status.h
index 597c7ea..78add09 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -11,6 +11,13 @@
 	WT_STATUS_NOBRANCH,
 };
 
+enum untracked_status_type {
+	SHOW_NO_UNTRACKED_FILES,
+	SHOW_NORMAL_UNTRACKED_FILES,
+	SHOW_ALL_UNTRACKED_FILES
+};
+extern enum untracked_status_type show_untracked_files;
+
 struct wt_status {
 	int is_initial;
 	char *branch;
diff --git a/xdiff-interface.c b/xdiff-interface.c
index 61dc5c5..3bf83f8 100644
--- a/xdiff-interface.c
+++ b/xdiff-interface.c
@@ -179,11 +179,21 @@
 static long ff_regexp(const char *line, long len,
 		char *buffer, long buffer_size, void *priv)
 {
-	char *line_buffer = xstrndup(line, len); /* make NUL terminated */
+	char *line_buffer;
 	struct ff_regs *regs = priv;
 	regmatch_t pmatch[2];
 	int result = 0, i;
 
+	/* Exclude terminating newline (and cr) from matching */
+	if (len > 0 && line[len-1] == '\n') {
+		if (len > 1 && line[len-2] == '\r')
+			len -= 2;
+		else
+			len--;
+	}
+
+	line_buffer = xstrndup(line, len); /* make NUL terminated */
+
 	for (i = 0; i < regs->nr; i++) {
 		struct ff_reg *reg = regs->array + i;
 		if (reg->negate ^ !!regexec(&reg->re,
@@ -206,7 +216,7 @@
 	return result;
 }
 
-void xdiff_set_find_func(xdemitconf_t *xecfg, const char *value)
+void xdiff_set_find_func(xdemitconf_t *xecfg, const char *value, int cflags)
 {
 	int i;
 	struct ff_regs *regs;
@@ -231,7 +241,7 @@
 			expression = buffer = xstrndup(value, ep - value);
 		else
 			expression = value;
-		if (regcomp(&reg->re, expression, 0))
+		if (regcomp(&reg->re, expression, cflags))
 			die("Invalid regexp to look for hunk header: %s", expression);
 		free(buffer);
 		value = ep + 1;
diff --git a/xdiff-interface.h b/xdiff-interface.h
index f7f791d..33cab9d 100644
--- a/xdiff-interface.h
+++ b/xdiff-interface.h
@@ -21,6 +21,6 @@
 int read_mmfile(mmfile_t *ptr, const char *filename);
 int buffer_is_binary(const char *ptr, unsigned long size);
 
-extern void xdiff_set_find_func(xdemitconf_t *xecfg, const char *line);
+extern void xdiff_set_find_func(xdemitconf_t *xecfg, const char *line, int cflags);
 
 #endif
diff --git a/xdiff/xprepare.c b/xdiff/xprepare.c
index e87ab57..a43aa72 100644
--- a/xdiff/xprepare.c
+++ b/xdiff/xprepare.c
@@ -23,10 +23,9 @@
 #include "xinclude.h"
 
 
-
 #define XDL_KPDIS_RUN 4
 #define XDL_MAX_EQLIMIT 1024
-
+#define XDL_SIMSCAN_WINDOW 100
 
 
 typedef struct s_xdlclass {
@@ -313,6 +312,18 @@
 	long r, rdis0, rpdis0, rdis1, rpdis1;
 
 	/*
+	 * Limits the window the is examined during the similar-lines
+	 * scan. The loops below stops when dis[i - r] == 1 (line that
+	 * has no match), but there are corner cases where the loop
+	 * proceed all the way to the extremities by causing huge
+	 * performance penalties in case of big files.
+	 */
+	if (i - s > XDL_SIMSCAN_WINDOW)
+		s = i - XDL_SIMSCAN_WINDOW;
+	if (e - i > XDL_SIMSCAN_WINDOW)
+		e = i + XDL_SIMSCAN_WINDOW;
+
+	/*
 	 * Scans the lines before 'i' to find a run of lines that either
 	 * have no match (dis[j] == 0) or have multiple matches (dis[j] > 1).
 	 * Note that we always call this function with dis[i] > 1, so the