Merge branch 'jk/trace-sifter'

* jk/trace-sifter:
  trace: give repo_setup trace its own key
  add packet tracing debug code
  trace: add trace_strbuf
  trace: factor out "do we want to trace" logic
  trace: refactor to support multiple env variables
  trace: add trace_vprintf
diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines
index ba2006d..fe1c1e5 100644
--- a/Documentation/CodingGuidelines
+++ b/Documentation/CodingGuidelines
@@ -152,7 +152,7 @@
  when writing or modifying command usage strings and synopsis sections
  in the manual pages:
 
- Placeholders are enclosed in angle brackets:
+ Placeholders are spelled in lowercase and enclosed in angle brackets:
    <file>
    --sort=<key>
    --abbrev[=<n>]
diff --git a/Documentation/RelNotes/1.7.4.2.txt b/Documentation/RelNotes/1.7.4.2.txt
new file mode 100644
index 0000000..afb3871
--- /dev/null
+++ b/Documentation/RelNotes/1.7.4.2.txt
@@ -0,0 +1,42 @@
+Git v1.7.4.2 Release Notes
+==========================
+
+Fixes since v1.7.4.1
+--------------------
+
+ * Many documentation updates to match "git cmd -h" output and the
+   git-cmd manual page.
+
+ * "git clone /no/such/path" did not fail correctly.
+
+ * "git commit" did not correctly error out when the user asked to use a
+   non existent file as the commit message template.
+
+ * "git diff --stat -B" ran on binary files counted the changes in lines,
+   which was nonsensical.
+
+ * "git diff -M" opportunistically detected copies, which was not
+   necessarily a good thing, especially when it is internally run by
+   recursive merge.
+
+ * "git difftool" didn't tell (g)vimdiff that the files it is reading are
+   to be opened read-only.
+
+ * "git merge" didn't pay attention to prepare-commit-msg hook, even
+   though if a merge is conflicted and manually resolved, the subsequent
+   "git commit" would have triggered the hook, which was inconsistent.
+
+ * "git patch-id" (and commands like "format-patch --ignore-in-upstream"
+   that use it as their internal logic) handled changes to files that end
+   with incomplete lines incorrectly.
+
+ * The official value to tell "git push" to push the current branch back
+   to update the upstream branch it forked from is now called "upstream".
+   The old name "tracking" is and will be supported.
+
+ * gitweb's "highlight" interface mishandled tabs.
+
+ * gitweb had a few forward-incompatible syntactic constructs and
+   also used incorrect variable when showing the file mode in a diff.
+
+And other minor fixes and documentation updates.
diff --git a/Documentation/RelNotes/1.7.5.txt b/Documentation/RelNotes/1.7.5.txt
new file mode 100644
index 0000000..bb0eb40
--- /dev/null
+++ b/Documentation/RelNotes/1.7.5.txt
@@ -0,0 +1,97 @@
+Git v1.7.5 Release Notes (draft)
+========================
+
+Updates since v1.7.4
+--------------------
+
+ * Various MinGW portability fixes.
+
+ * Various git-p4 enhancements (in contrib).
+
+ * Various vcs-svn enhancements.
+
+ * Update to more modern HP-UX port.
+
+ * "git apply -v" reports offset lines when the patch does not apply at
+   the exact location recorded in the diff output.
+
+ * "git branch --track" (and "git checkout --track --branch") used to
+   allow setting up a random non-branch that does not make sense to follow
+   as the "upstream".  The command correctly diagnoses it as an error.
+
+ * "git config" used to be also known as "git repo-config", but the old
+   name is now officially deprecated.
+
+ * "git checkout --detach <commit>" is a more user friendly synonym for
+   "git checkout <commit>^0".
+
+ * "git checkout" performed on detached HEAD gives a warning and
+   advice when the commit being left behind will become unreachable from
+   any branch or tag.
+
+ * "git cherry-pick" and "git revert" can be told to use a custom merge
+   strategy, similar to "git rebase".
+
+ * "git cherry-pick" remembers which commit failed to apply when it is
+   stopped by conflicts, making it unnecessary to use "commit -c $commit"
+   to conclude it.
+
+ * "git cvsimport" bails out immediately when the cvs server cannot be
+   reached, without spewing unnecessary error messages that complain about
+   the server response it never got.
+
+ * "git grep --no-index" did not honor pathspecs correctly, returning
+   paths outside the specified area.
+
+ * "git log" type commands now understand globbing pathspecs.  You
+   can say "git log -- '*.txt'" for example.
+
+ * "git rev-list --objects $revs -- $pathspec" now limits the objects listed
+   in its output properly with the pathspec, in preparation for narrow
+   clones.
+
+ * "git push" with no parameters gives better advice messages when
+   "tracking" is used as the push.default semantics or there is no remote
+   configured yet.
+
+ * "git rerere" learned a new subcommand "remaining" that is similar to
+   "status" and lists the paths that had conflicts which are known to
+   rerere, but excludes the paths that have already been marked as
+   resolved in the index from its output.  "git mergetool" has been
+   updated to use this facility.
+
+ * A possible value to the "push.default" configuration variable,
+   'tracking', gained a synonym that more naturally describes what it
+   does, 'upstream'.
+
+Also contains various documentation updates.
+
+
+Fixes since v1.7.4
+------------------
+
+All of the fixes in the v1.7.4.X maintenance series are included in this
+release, unless otherwise noted.
+
+ * We used to keep one file descriptor open for each and every packfile
+   that we have a mmap window on it (read: "in use"), even when for very
+   tiny packfiles.  We now close the file descriptor early when the entire
+   packfile fits inside one mmap window.
+
+ * "git apply" used to confuse lines updated by previous hunks as lines
+   that existed before when applying a hunk, contributing misapplication
+   of patches with offsets.
+
+ * "git checkout $other_branch" silently removed untracked symbolic links
+   in the working tree that are in the way in order to check out paths
+   under it from the named branch (js/checkout-untracked-symlink).
+
+ * "git submodule update" used to honor the --merge/--rebase option (or
+   corresponding configuration variables) even for a newly cloned
+   subproject, which made no sense (so/submodule-no-update-first-time).
+
+---
+exec >/var/tmp/1
+O=v1.7.4.1-291-g01de349
+echo O=$(git describe 'master')
+git shortlog --no-merges ^maint ^$O master
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 72741eb..c3b0816 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -10,10 +10,18 @@
 	  description (50 characters is the soft limit, see DISCUSSION
 	  in git-commit(1)), and should skip the full stop
 	- the body should provide a meaningful commit message, which:
-		- uses the imperative, present tense: "change",
-		  not "changed" or "changes".
-		- includes motivation for the change, and contrasts
-		  its implementation with previous behaviour
+	  . explains the problem the change tries to solve, iow, what
+	    is wrong with the current code without the change.
+	  . justifies the way the change solves the problem, iow, why
+	    the result with the change is better.
+	  . alternate solutions considered but discarded, if any.
+	- describe changes in imperative mood, e.g. "make xyzzy do frotz"
+	  instead of "[This patch] makes xyzzy do frotz" or "[I] changed
+	  xyzzy to do frotz", as if you are giving orders to the codebase
+	  to change its behaviour.
+	- try to make sure your explanation can be understood without
+	  external resources. Instead of giving a URL to a mailing list
+	  archive, summarize the relevant points of the discussion.
 	- add a "Signed-off-by: Your Name <you@example.com>" line to the
 	  commit message (or just use the option "-s" when committing)
 	  to confirm that you agree to the Developer's Certificate of Origin
@@ -90,7 +98,10 @@
 commit message and generate a series of patches from your
 repository.  It is a good discipline.
 
-Describe the technical detail of the change(s).
+Give an explanation for the change(s) that is detailed enough so
+that people can judge if it is good thing to do, without reading
+the actual patch text to determine how well the code does what
+the explanation promises to do.
 
 If your description starts to get too long, that's a sign that you
 probably need to split up your commit to finer grained pieces.
@@ -99,9 +110,8 @@
 the code, are the most beautiful patches.  Descriptions that summarise
 the point in the subject well, and describe the motivation for the
 change, the approach taken by the change, and if relevant how this
-differs substantially from the prior version, can be found on Usenet
-archives back into the late 80's.  Consider it like good Netiquette,
-but for code.
+differs substantially from the prior version, are all good things
+to have.
 
 Oh, another thing.  I am picky about whitespaces.  Make sure your
 changes do not trigger errors with the sample pre-commit hook shipped
diff --git a/Documentation/config.txt b/Documentation/config.txt
index c5e1835..701fba9 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -376,15 +376,6 @@
 	If true, git will warn you if the ref name you passed it is ambiguous
 	and might match multiple refs in the .git/refs/ tree. True by default.
 
-core.abbrevguard::
-	Even though git makes sure that it uses enough hexdigits to show
-	an abbreviated object name unambiguously, as more objects are
-	added to the repository over time, a short name that used to be
-	unique will stop being unique.  Git uses this many extra hexdigits
-	that are more than necessary to make the object name currently
-	unique, in the hope that its output will stay unique a bit longer.
-	Defaults to 0.
-
 core.compression::
 	An integer -1..9, indicating a default compression level.
 	-1 is the zlib default. 0 means no compression,
@@ -1591,7 +1582,8 @@
 * `matching` - push all matching branches.
   All branches having the same name in both ends are considered to be
   matching. This is the default.
-* `tracking` - push the current branch to its upstream branch.
+* `upstream` - push the current branch to its upstream branch.
+* `tracking` - deprecated synonym for `upstream`.
 * `current` - push the current branch to a branch of the same name.
 
 rebase.stat::
diff --git a/Documentation/diff-generate-patch.txt b/Documentation/diff-generate-patch.txt
index 3ac2bea..c57460c 100644
--- a/Documentation/diff-generate-patch.txt
+++ b/Documentation/diff-generate-patch.txt
@@ -74,10 +74,13 @@
 combined diff format
 --------------------
 
-"git-diff-tree", "git-diff-files" and "git-diff" can take '-c' or
-'--cc' option to produce 'combined diff'.  For showing a merge commit
-with "git log -p", this is the default format; you can force showing
-full diff with the '-m' option.
+Any diff-generating command can take the `-c` or `--cc` option to
+produce a 'combined diff' when showing a merge. This is the default
+format when showing merges with linkgit:git-diff[1] or
+linkgit:git-show[1]. Note also that you can give the `-m' option to any
+of these commands to force generation of diffs with individual parents
+of a merge.
+
 A 'combined diff' format looks like this:
 
 ------------
diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt
index a03448f..7eebbef 100644
--- a/Documentation/git-add.txt
+++ b/Documentation/git-add.txt
@@ -378,14 +378,6 @@
 linkgit:git-commit[1]
 linkgit:git-update-index[1]
 
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt
index 51297d0..621b720 100644
--- a/Documentation/git-am.txt
+++ b/Documentation/git-am.txt
@@ -189,15 +189,6 @@
 --------
 linkgit:git-apply[1].
 
-
-Author
-------
-Written by Junio C Hamano <gitster@pobox.com>
-
-Documentation
---------------
-Documentation by Petr Baudis, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-annotate.txt b/Documentation/git-annotate.txt
index 0590eec..9eb75c3 100644
--- a/Documentation/git-annotate.txt
+++ b/Documentation/git-annotate.txt
@@ -27,10 +27,6 @@
 --------
 linkgit:git-blame[1]
 
-AUTHOR
-------
-Written by Ryan Anderson <ryan@michonline.com>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt
index 881652f..afd2c9a 100644
--- a/Documentation/git-apply.txt
+++ b/Documentation/git-apply.txt
@@ -22,7 +22,7 @@
 -----------
 Reads the supplied diff output (i.e. "a patch") and applies it to files.
 With the `--index` option the patch is also applied to the index, and
-with the `--cache` option the patch is only applied to the index.
+with the `--cached` option the patch is only applied to the index.
 Without these options, the command applies the patch only to files,
 and does not require them to be in a git repository.
 
@@ -246,20 +246,10 @@
 are ignored and only the absence or presence of the corresponding
 subdirectory is checked and (if possible) updated.
 
-
 SEE ALSO
 --------
 linkgit:git-am[1].
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by Junio C Hamano
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-archimport.txt b/Documentation/git-archimport.txt
index 2411ce5..f4504ba 100644
--- a/Documentation/git-archimport.txt
+++ b/Documentation/git-archimport.txt
@@ -107,14 +107,6 @@
 	Archive/branch identifier in a format that `tla log` understands.
 
 
-Author
-------
-Written by Martin Langhoff <martin@laptop.org>.
-
-Documentation
---------------
-Documentation by Junio C Hamano, Martin Langhoff and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-archive.txt b/Documentation/git-archive.txt
index bf5037a..f2b8684 100644
--- a/Documentation/git-archive.txt
+++ b/Documentation/git-archive.txt
@@ -153,14 +153,6 @@
 --------
 linkgit:gitattributes[5]
 
-Author
-------
-Written by Franck Bui-Huu and Rene Scharfe.
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt
index c39d957..4b4b096 100644
--- a/Documentation/git-bisect.txt
+++ b/Documentation/git-bisect.txt
@@ -241,7 +241,12 @@
 
 The special exit code 125 should be used when the current source code
 cannot be tested. If the script exits with this code, the current
-revision will be skipped (see `git bisect skip` above).
+revision will be skipped (see `git bisect skip` above). 125 was chosen
+as the highest sensible value to use for this purpose, because 126 and 127
+are used by POSIX shells to signal specific error status (127 is for
+command not found, 126 is for command found but not executable---these
+details do not matter, as they are normal errors in the script, as far as
+"bisect run" is concerned).
 
 You may often find that during a bisect session you want to have
 temporary modifications (e.g. s/#define DEBUG 0/#define DEBUG 1/ in a
@@ -322,14 +327,6 @@
 +
 Does the same as the previous example, but on a single line.
 
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
--------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 SEE ALSO
 --------
 link:git-bisect-lk2009.html[Fighting regressions with git bisect],
diff --git a/Documentation/git-blame.txt b/Documentation/git-blame.txt
index c71671b..c4d1ff8 100644
--- a/Documentation/git-blame.txt
+++ b/Documentation/git-blame.txt
@@ -198,10 +198,6 @@
 --------
 linkgit:git-annotate[1]
 
-AUTHOR
-------
-Written by Junio C Hamano <gitster@pobox.com>
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index 9106d38..c50f189 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -232,14 +232,6 @@
 link:user-manual.html#what-is-a-branch[``Understanding history: What is
 a branch?''] in the Git User's Manual.
 
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org> and Junio C Hamano <gitster@pobox.com>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-bundle.txt b/Documentation/git-bundle.txt
index 299007b..92b01ec2 100644
--- a/Documentation/git-bundle.txt
+++ b/Documentation/git-bundle.txt
@@ -201,10 +201,6 @@
 $ git ls-remote mybundle
 ----------------
 
-Author
-------
-Written by Mark Levedahl <mdl123@verizon.net>
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt
index 544ba7b..2fb95bb 100644
--- a/Documentation/git-cat-file.txt
+++ b/Documentation/git-cat-file.txt
@@ -100,14 +100,6 @@
 <object> SP missing LF
 ------------
 
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-check-attr.txt b/Documentation/git-check-attr.txt
index 50824e3..30eca6c 100644
--- a/Documentation/git-check-attr.txt
+++ b/Documentation/git-check-attr.txt
@@ -86,15 +86,6 @@
 --------
 linkgit:gitattributes[5].
 
-
-Author
-------
-Written by Junio C Hamano <gitster@pobox.com>
-
-Documentation
---------------
-Documentation by James Bowes.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-checkout-index.txt b/Documentation/git-checkout-index.txt
index 0c0a9c1..4d33e7b 100644
--- a/Documentation/git-checkout-index.txt
+++ b/Documentation/git-checkout-index.txt
@@ -172,18 +172,6 @@
 This will check out the currently cached copy of `Makefile`
 into the file `.merged-Makefile`.
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-
-Documentation
---------------
-Documentation by David Greaves,
-Junio C Hamano and the git-list <git@vger.kernel.org>.
-
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index 880763d..1063f69 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -9,6 +9,7 @@
 --------
 [verse]
 'git checkout' [-q] [-f] [-m] [<branch>]
+'git checkout' [-q] [-f] [-m] [--detach] [<commit>]
 'git checkout' [-q] [-f] [-m] [[-b|-B|--orphan] <new_branch>] [<start_point>]
 'git checkout' [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>...
 'git checkout' --patch [<tree-ish>] [--] [<paths>...]
@@ -22,9 +23,10 @@
 
 'git checkout' [<branch>]::
 'git checkout' -b|-B <new_branch> [<start point>]::
+'git checkout' [--detach] [<commit>]::
 
 	This form switches branches by updating the index, working
-	tree, and HEAD to reflect the specified branch.
+	tree, and HEAD to reflect the specified branch or commit.
 +
 If `-b` is given, a new branch is created as if linkgit:git-branch[1]
 were called and then checked out; in this case you can
@@ -115,6 +117,13 @@
 	Create the new branch's reflog; see linkgit:git-branch[1] for
 	details.
 
+--detach::
+	Rather than checking out a branch to work on it, check out a
+	commit for inspection and discardable experiments.
+	This is the default behavior of "git checkout <commit>" when
+	<commit> is not a branch name.  See the "DETACHED HEAD" section
+	below for details.
+
 --orphan::
 	Create a new 'orphan' branch, named <new_branch>, started from
 	<start_point> and switch to it.  The first commit made on this
@@ -204,43 +213,141 @@
 
 
 
-Detached HEAD
+DETACHED HEAD
 -------------
-
-It is sometimes useful to be able to 'checkout' a commit that is
-not at the tip of one of your branches.  The most obvious
-example is to check out the commit at a tagged official release
-point, like this:
+HEAD normally refers to a named branch (e.g. 'master'). Meanwhile, each
+branch refers to a specific commit. Let's look at a repo with three
+commits, one of them tagged, and with branch 'master' checked out:
 
 ------------
-$ git checkout v2.6.18
+	   HEAD (refers to branch 'master')
+	    |
+	    v
+a---b---c  branch 'master' (refers to commit 'c')
+    ^
+    |
+  tag 'v2.0' (refers to commit 'b')
 ------------
 
-Earlier versions of git did not allow this and asked you to
-create a temporary branch using the `-b` option, but starting from
-version 1.5.0, the above command 'detaches' your HEAD from the
-current branch and directly points at the commit named by the tag
-(`v2.6.18` in the example above).
-
-You can use all git commands while in this state.  You can use
-`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`.
-
-The state you are in while your HEAD is detached is not recorded
-by any branch (which is natural --- you are not on any branch).
-What this means is that you can discard your temporary commits
-and merges by switching back to an existing branch (e.g. `git
-checkout master`), and a later `git prune` or `git gc` would
-garbage-collect them.  If you did this by mistake, you can ask
-the reflog for HEAD where you were, e.g.
+When a commit is created in this state, the branch is updated to refer to
+the new commit. Specifically, 'git commit' creates a new commit 'd', whose
+parent is commit 'c', and then updates branch 'master' to refer to new
+commit 'd'. HEAD still refers to branch 'master' and so indirectly now refers
+to commit 'd':
 
 ------------
+$ edit; git add; git commit
+
+	       HEAD (refers to branch 'master')
+		|
+		v
+a---b---c---d  branch 'master' (refers to commit 'd')
+    ^
+    |
+  tag 'v2.0' (refers to commit 'b')
+------------
+
+It is sometimes useful to be able to checkout a commit that is not at
+the tip of any named branch, or even to create a new commit that is not
+referenced by a named branch. Let's look at what happens when we
+checkout commit 'b' (here we show two ways this may be done):
+
+------------
+$ git checkout v2.0  # or
+$ git checkout master^^
+
+   HEAD (refers to commit 'b')
+    |
+    v
+a---b---c---d  branch 'master' (refers to commit 'd')
+    ^
+    |
+  tag 'v2.0' (refers to commit 'b')
+------------
+
+Notice that regardless of which checkout command we use, HEAD now refers
+directly to commit 'b'. This is known as being in detached HEAD state.
+It means simply that HEAD refers to a specific commit, as opposed to
+referring to a named branch. Let's see what happens when we create a commit:
+
+------------
+$ edit; git add; git commit
+
+     HEAD (refers to commit 'e')
+      |
+      v
+      e
+     /
+a---b---c---d  branch 'master' (refers to commit 'd')
+    ^
+    |
+  tag 'v2.0' (refers to commit 'b')
+------------
+
+There is now a new commit 'e', but it is referenced only by HEAD. We can
+of course add yet another commit in this state:
+
+------------
+$ edit; git add; git commit
+
+	 HEAD (refers to commit 'f')
+	  |
+	  v
+      e---f
+     /
+a---b---c---d  branch 'master' (refers to commit 'd')
+    ^
+    |
+  tag 'v2.0' (refers to commit 'b')
+------------
+
+In fact, we can perform all the normal git operations. But, let's look
+at what happens when we then checkout master:
+
+------------
+$ git checkout master
+
+	       HEAD (refers to branch 'master')
+      e---f     |
+     /          v
+a---b---c---d  branch 'master' (refers to commit 'd')
+    ^
+    |
+  tag 'v2.0' (refers to commit 'b')
+------------
+
+It is important to realize that at this point nothing refers to commit
+'f'. Eventually commit 'f' (and by extension commit 'e') will be deleted
+by the routine git garbage collection process, unless we create a reference
+before that happens. If we have not yet moved away from commit 'f',
+any of these will create a reference to it:
+
+------------
+$ git checkout -b foo   <1>
+$ git branch foo        <2>
+$ git tag foo           <3>
+------------
+
+<1> creates a new branch 'foo', which refers to commit 'f', and then
+updates HEAD to refer to branch 'foo'. In other words, we'll no longer
+be in detached HEAD state after this command.
+
+<2> similarly creates a new branch 'foo', which refers to commit 'f',
+but leaves HEAD detached.
+
+<3> creates a new tag 'foo', which refers to commit 'f',
+leaving HEAD detached.
+
+If we have moved away from commit 'f', then we must first recover its object
+name (typically by using git reflog), and then we can create a reference to
+it. For example, to see the last two commits to which HEAD referred, we
+can use either of these commands:
+
+------------
+$ git reflog -2 HEAD # or
 $ git log -g -2 HEAD
 ------------
 
-
 EXAMPLES
 --------
 
@@ -315,15 +422,6 @@
 $ git add frotz
 ------------
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt
index 749d68a..01db830 100644
--- a/Documentation/git-cherry-pick.txt
+++ b/Documentation/git-cherry-pick.txt
@@ -16,6 +16,25 @@
 introduces, recording a new commit for each.  This requires your
 working tree to be clean (no modifications from the HEAD commit).
 
+When it is not obvious how to apply a change, the following
+happens:
+
+1. The current branch and `HEAD` pointer stay at the last commit
+   successfully made.
+2. The `CHERRY_PICK_HEAD` ref is set to point at the commit that
+   introduced the change that is difficult to apply.
+3. Paths in which the change applied cleanly are updated both
+   in the index file and in your working tree.
+4. For conflicting paths, the index file records up to three
+   versions, as described in the "TRUE MERGE" section of
+   linkgit:git-merge[1].  The working tree files will include
+   a description of the conflict bracketed by the usual
+   conflict markers `<<<<<<<` and `>>>>>>>`.
+5. No other modifications are made.
+
+See linkgit:git-merge[1] for some hints on resolving such
+conflicts.
+
 OPTIONS
 -------
 <commit>...::
@@ -152,14 +171,6 @@
 spending extra time to avoid mistakes based on incorrectly matching
 context lines.
 
-Author
-------
-Written by Junio C Hamano <gitster@pobox.com>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 SEE ALSO
 --------
 linkgit:git-revert[1]
diff --git a/Documentation/git-cherry.txt b/Documentation/git-cherry.txt
index fed115a..79448c5 100644
--- a/Documentation/git-cherry.txt
+++ b/Documentation/git-cherry.txt
@@ -63,14 +63,6 @@
 --------
 linkgit:git-patch-id[1]
 
-Author
-------
-Written by Junio C Hamano <gitster@pobox.com>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-citool.txt b/Documentation/git-citool.txt
index fb2753c..6e5c812 100644
--- a/Documentation/git-citool.txt
+++ b/Documentation/git-citool.txt
@@ -19,14 +19,6 @@
 'git citool' is actually a standard alias for `git gui citool`.
 See linkgit:git-gui[1] for more details.
 
-Author
-------
-Written by Shawn O. Pearce <spearce@spearce.org>.
-
-Documentation
---------------
-Documentation by Shawn O. Pearce <spearce@spearce.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-clean.txt b/Documentation/git-clean.txt
index 60e38e6..974e04e 100644
--- a/Documentation/git-clean.txt
+++ b/Documentation/git-clean.txt
@@ -61,12 +61,6 @@
 	Remove only files ignored by git.  This may be useful to rebuild
 	everything from scratch, but keep manually created files.
 
-
-Author
-------
-Written by Pavel Roskin <proski@gnu.org>
-
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index 42e7021..8577480 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -236,17 +236,6 @@
     /pub/scm/.../me/subsys-2.6.git
 ------------
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-commit-tree.txt b/Documentation/git-commit-tree.txt
index 5dcf427..f524d76 100644
--- a/Documentation/git-commit-tree.txt
+++ b/Documentation/git-commit-tree.txt
@@ -93,15 +93,6 @@
 --------
 linkgit:git-write-tree[1]
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index 8f89f6f..d0534b8 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -84,9 +84,10 @@
 	linkgit:git-rebase[1] for details.
 
 --reset-author::
-	When used with -C/-c/--amend options, declare that the
-	authorship of the resulting commit now belongs of the committer.
-	This also renews the author timestamp.
+	When used with -C/-c/--amend options, or when committing after a
+	a conflicting cherry-pick, declare that the authorship of the
+	resulting commit now belongs of the committer. This also renews
+	the author timestamp.
 
 --short::
 	When doing a dry-run, give the output in the short-format. See
@@ -396,12 +397,6 @@
 linkgit:git-merge[1],
 linkgit:git-commit-tree[1]
 
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org> and
-Junio C Hamano <gitster@pobox.com>
-
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
index 543dd64..8804de3 100644
--- a/Documentation/git-config.txt
+++ b/Documentation/git-config.txt
@@ -336,15 +336,6 @@
 
 include::config.txt[]
 
-
-Author
-------
-Written by Johannes Schindelin <Johannes.Schindelin@gmx.de>
-
-Documentation
---------------
-Documentation by Johannes Schindelin, Petr Baudis and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-count-objects.txt b/Documentation/git-count-objects.txt
index 6bc1c21..a73933a 100644
--- a/Documentation/git-count-objects.txt
+++ b/Documentation/git-count-objects.txt
@@ -25,15 +25,6 @@
 	and number of objects that can be removed by running
 	`git prune-packed`.
 
-
-Author
-------
-Written by Junio C Hamano <gitster@pobox.com>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-cvsexportcommit.txt b/Documentation/git-cvsexportcommit.txt
index d25661e..ad93a3e 100644
--- a/Documentation/git-cvsexportcommit.txt
+++ b/Documentation/git-cvsexportcommit.txt
@@ -112,14 +112,6 @@
 $ git cherry cvshead myhead | sed -n 's/^+ //p' | xargs -l1 git cvsexportcommit -c -p -v
 ------------
 
-Author
-------
-Written by Martin Langhoff <martin@laptop.org> and others.
-
-Documentation
---------------
-Documentation by Martin Langhoff <martin@laptop.org> and others.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-cvsimport.txt b/Documentation/git-cvsimport.txt
index 608cd63..6695ab3 100644
--- a/Documentation/git-cvsimport.txt
+++ b/Documentation/git-cvsimport.txt
@@ -217,15 +217,6 @@
 * cvs2git (part of cvs2svn), `http://cvs2svn.tigris.org`
 * parsecvs, `http://cgit.freedesktop.org/~keithp/parsecvs`
 
-Author
-------
-Written by Matthias Urlichs <smurf@smurf.noris.de>, with help from
-various participants of the git-list <git@vger.kernel.org>.
-
-Documentation
---------------
-Documentation by Matthias Urlichs <smurf@smurf.noris.de>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt
index 70cbb2c..88d814a 100644
--- a/Documentation/git-cvsserver.txt
+++ b/Documentation/git-cvsserver.txt
@@ -391,22 +391,6 @@
 ------------
 'git-cvsserver' depends on DBD::SQLite.
 
-Copyright and Authors
----------------------
-
-This program is copyright The Open University UK - 2006.
-
-Authors:
-
-- Martyn Smith    <martyn@catalyst.net.nz>
-- Martin Langhoff <martin@laptop.org>
-
-with ideas and patches from participants of the git-list <git@vger.kernel.org>.
-
-Documentation
---------------
-Documentation by Martyn Smith <martyn@catalyst.net.nz>, Martin Langhoff <martin@laptop.org>, and Matthias Urlichs <smurf@smurf.noris.de>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-daemon.txt b/Documentation/git-daemon.txt
index d15cb6a..ebd13be 100644
--- a/Documentation/git-daemon.txt
+++ b/Documentation/git-daemon.txt
@@ -279,17 +279,6 @@
 be available in the environment of hooks called when
 services are performed.
 
-
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>, YOSHIFUJI Hideaki
-<yoshfuji@linux-ipv6.org> and the git-list <git@vger.kernel.org>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-describe.txt b/Documentation/git-describe.txt
index 02e015a..039cce2 100644
--- a/Documentation/git-describe.txt
+++ b/Documentation/git-describe.txt
@@ -156,17 +156,6 @@
 the number of commits which would be shown by `git log tag..input`
 will be the smallest number of commits possible.
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>, but somewhat
-butchered by Junio C Hamano <gitster@pobox.com>.  Later significantly
-updated by Shawn Pearce <spearce@spearce.org>.
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-diff-files.txt b/Documentation/git-diff-files.txt
index 9cd8cce..8d48194 100644
--- a/Documentation/git-diff-files.txt
+++ b/Documentation/git-diff-files.txt
@@ -46,15 +46,6 @@
 
 include::diff-format.txt[]
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-diff-index.txt b/Documentation/git-diff-index.txt
index 162cb74..6d18486 100644
--- a/Documentation/git-diff-index.txt
+++ b/Documentation/git-diff-index.txt
@@ -116,15 +116,6 @@
 show a valid sha1, and the "not in sync with the index" ones will
 always have the special all-zero sha1.
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-diff-tree.txt b/Documentation/git-diff-tree.txt
index a7e37b8..4e5f127 100644
--- a/Documentation/git-diff-tree.txt
+++ b/Documentation/git-diff-tree.txt
@@ -162,15 +162,6 @@
 
 include::diff-format.txt[]
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-diff.txt b/Documentation/git-diff.txt
index 4910510..f8d0819 100644
--- a/Documentation/git-diff.txt
+++ b/Documentation/git-diff.txt
@@ -174,14 +174,6 @@
 linkgit:git-format-patch[1],
 linkgit:git-apply[1]
 
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-difftool.txt b/Documentation/git-difftool.txt
index db87f1d..a5d9c12 100644
--- a/Documentation/git-difftool.txt
+++ b/Documentation/git-difftool.txt
@@ -109,15 +109,6 @@
 linkgit:git-config[1]::
 	 Get and set repository or global options
 
-
-AUTHOR
-------
-Written by David Aguilar <davvid@gmail.com>.
-
-Documentation
---------------
-Documentation by David Aguilar and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-fast-export.txt b/Documentation/git-fast-export.txt
index e05b686..781bd6e 100644
--- a/Documentation/git-fast-export.txt
+++ b/Documentation/git-fast-export.txt
@@ -135,15 +135,6 @@
 able to export the linux-2.6.git repository completely, as it contains
 a tag referencing a tree instead of a commit.
 
-
-Author
-------
-Written by Johannes E. Schindelin <johannes.schindelin@gmx.de>.
-
-Documentation
---------------
-Documentation by Johannes E. Schindelin <johannes.schindelin@gmx.de>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt
index c3a2766..2c2ea12 100644
--- a/Documentation/git-fast-import.txt
+++ b/Documentation/git-fast-import.txt
@@ -196,7 +196,8 @@
 Ruby is being used.
 
 fast-import is very strict about its input.  Where we say SP below we mean
-*exactly* one space.  Likewise LF means one (and only one) linefeed.
+*exactly* one space.  Likewise LF means one (and only one) linefeed
+and HT one (and only one) horizontal tab.
 Supplying additional whitespace characters will cause unexpected
 results, such as branch names or file names with leading or trailing
 spaces in their name, or early termination of fast-import when it encounters
@@ -334,6 +335,11 @@
 	format to the file descriptor set with `--cat-blob-fd` or
 	`stdout` if unspecified.
 
+`ls`::
+	Causes fast-import to print a line describing a directory
+	entry in 'ls-tree' format to the file descriptor set with
+	`--cat-blob-fd` or `stdout` if unspecified.
+
 `feature`::
 	Require that fast-import supports the specified feature, or
 	abort if it does not.
@@ -919,6 +925,55 @@
 accepted.  In particular, the `cat-blob` command can be used in the
 middle of a commit but not in the middle of a `data` command.
 
+`ls`
+~~~~
+Prints information about the object at a path to a file descriptor
+previously arranged with the `--cat-blob-fd` argument.  This allows
+printing a blob from the active commit (with `cat-blob`) or copying a
+blob or tree from a previous commit for use in the current one (with
+`filemodify`).
+
+The `ls` command can be used anywhere in the stream that comments are
+accepted, including the middle of a commit.
+
+Reading from the active commit::
+	This form can only be used in the middle of a `commit`.
+	The path names a directory entry within fast-import's
+	active commit.  The path must be quoted in this case.
++
+....
+	'ls' SP <path> LF
+....
+
+Reading from a named tree::
+	The `<dataref>` can be a mark reference (`:<idnum>`) or the
+	full 40-byte SHA-1 of a Git tag, commit, or tree object,
+	preexisting or waiting to be written.
+	The path is relative to the top level of the tree
+	named by `<dataref>`.
++
+....
+	'ls' SP <dataref> SP <path> LF
+....
+
+See `filemodify` above for a detailed description of `<path>`.
+
+Output uses the same format as `git ls-tree <tree> {litdd} <path>`:
+
+====
+	<mode> SP ('blob' | 'tree' | 'commit') SP <dataref> HT <path> LF
+====
+
+The <dataref> represents the blob, tree, or commit object at <path>
+and can be used in later 'cat-blob', 'filemodify', or 'ls' commands.
+
+If there is no file or subtree at that path, 'git fast-import' will
+instead report
+
+====
+	missing SP <path> LF
+====
+
 `feature`
 ~~~~~~~~~
 Require that fast-import supports the specified feature, or abort if
@@ -946,8 +1001,10 @@
 	any "feature import-marks" command in the stream.
 
 cat-blob::
-	Ignored.  Versions of fast-import not supporting the
-	"cat-blob" command will exit with a message indicating so.
+ls::
+	Require that the backend support the 'cat-blob' or 'ls' command.
+	Versions of fast-import not supporting the specified command
+	will exit with a message indicating so.
 	This lets the import error out early with a clear message,
 	rather than wasting time on the early part of an import
 	before the unsupported command is detected.
@@ -1293,14 +1350,6 @@
 import in progress, at the cost of some added running time and worse
 compression.
 
-Author
-------
-Written by Shawn O. Pearce <spearce@spearce.org>.
-
-Documentation
---------------
-Documentation by Shawn O. Pearce <spearce@spearce.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-fetch-pack.txt b/Documentation/git-fetch-pack.txt
index 4a8487c..48d4bf6 100644
--- a/Documentation/git-fetch-pack.txt
+++ b/Documentation/git-fetch-pack.txt
@@ -90,15 +90,6 @@
 	$GIT_DIR (e.g. "HEAD", "refs/heads/master").  When
 	unspecified, update from all heads the remote side has.
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by Junio C Hamano.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-fetch.txt b/Documentation/git-fetch.txt
index c76e313..7146f6b 100644
--- a/Documentation/git-fetch.txt
+++ b/Documentation/git-fetch.txt
@@ -80,16 +80,6 @@
 --------
 linkgit:git-pull[1]
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org> and
-Junio C Hamano <gitster@pobox.com>
-
-Documentation
--------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt
index 796e748..03c76c7 100644
--- a/Documentation/git-filter-branch.txt
+++ b/Documentation/git-filter-branch.txt
@@ -405,16 +405,6 @@
   (or if your git-gc is not new enough to support arguments to
   `\--prune`, use `git repack -ad; git prune` instead).
 
-
-Author
-------
-Written by Petr "Pasky" Baudis <pasky@suse.cz>,
-and the git list <git@vger.kernel.org>
-
-Documentation
---------------
-Documentation by Petr Baudis and the git list.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-fmt-merge-msg.txt b/Documentation/git-fmt-merge-msg.txt
index 75adf7a..32aff95 100644
--- a/Documentation/git-fmt-merge-msg.txt
+++ b/Documentation/git-fmt-merge-msg.txt
@@ -67,15 +67,6 @@
 --------
 linkgit:git-merge[1]
 
-
-Author
-------
-Written by Junio C Hamano <gitster@pobox.com>
-
-Documentation
---------------
-Documentation by Petr Baudis, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt
index fac1cf5..152e695 100644
--- a/Documentation/git-for-each-ref.txt
+++ b/Documentation/git-for-each-ref.txt
@@ -123,7 +123,7 @@
 --------
 
 An example directly producing formatted text.  Show the most recent
-3 tagged commits::
+3 tagged commits:
 
 ------------
 #!/bin/sh
@@ -140,7 +140,7 @@
 
 
 A simple example showing the use of shell eval on the output,
-demonstrating the use of --shell.  List the prefixes of all heads::
+demonstrating the use of --shell.  List the prefixes of all heads:
 ------------
 #!/bin/sh
 
@@ -154,7 +154,7 @@
 
 
 A bit more elaborate report on tags, demonstrating that the format
-may be an entire script::
+may be an entire script:
 ------------
 #!/bin/sh
 
@@ -204,3 +204,15 @@
 	refs/tags`
 eval "$eval"
 ------------
+
+Author
+------
+Written by Junio C Hamano <gitster@pobox.com>.
+
+Documentation
+-------------
+Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
+
+GIT
+---
+Part of the linkgit:git[1] suite
diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt
index 9dcafc6..a5525e9 100644
--- a/Documentation/git-format-patch.txt
+++ b/Documentation/git-format-patch.txt
@@ -278,15 +278,6 @@
 --------
 linkgit:git-am[1], linkgit:git-send-email[1]
 
-
-Author
-------
-Written by Junio C Hamano <gitster@pobox.com>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-fsck-objects.txt b/Documentation/git-fsck-objects.txt
index 965a827..90ebb8a 100644
--- a/Documentation/git-fsck-objects.txt
+++ b/Documentation/git-fsck-objects.txt
@@ -15,3 +15,7 @@
 
 This is a synonym for linkgit:git-fsck[1].  Please refer to the
 documentation of that command.
+
+GIT
+---
+Part of the linkgit:git[1] suite
diff --git a/Documentation/git-fsck.txt b/Documentation/git-fsck.txt
index 86f9b2b..c9ede79 100644
--- a/Documentation/git-fsck.txt
+++ b/Documentation/git-fsck.txt
@@ -140,14 +140,6 @@
 GIT_ALTERNATE_OBJECT_DIRECTORIES::
 	used to specify additional object database roots (usually unset)
 
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-gc.txt b/Documentation/git-gc.txt
index 2663241..4966cb5 100644
--- a/Documentation/git-gc.txt
+++ b/Documentation/git-gc.txt
@@ -151,10 +151,6 @@
 linkgit:git-repack[1]
 linkgit:git-rerere[1]
 
-Author
-------
-Written by Shawn O. Pearce <spearce@spearce.org>
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-get-tar-commit-id.txt b/Documentation/git-get-tar-commit-id.txt
index 790af95..8035736 100644
--- a/Documentation/git-get-tar-commit-id.txt
+++ b/Documentation/git-get-tar-commit-id.txt
@@ -22,15 +22,6 @@
 using 'git archive' or if the first parameter of 'git archive' had been
 a tree ID instead of a commit ID or tag.
 
-
-Author
-------
-Written by Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt
index dab0a78..d4d425e 100644
--- a/Documentation/git-grep.txt
+++ b/Documentation/git-grep.txt
@@ -203,16 +203,6 @@
 	Looks for a line that has `NODE` or `Unexpected` in
 	files that have lines that match both.
 
-Author
-------
-Originally written by Linus Torvalds <torvalds@osdl.org>, later
-revamped by Junio C Hamano.
-
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-gui.txt b/Documentation/git-gui.txt
index 2563710..32a833e 100644
--- a/Documentation/git-gui.txt
+++ b/Documentation/git-gui.txt
@@ -121,14 +121,6 @@
 
 or browsed online at http://repo.or.cz/w/git-gui.git/[].
 
-Author
-------
-Written by Shawn O. Pearce <spearce@spearce.org>.
-
-Documentation
---------------
-Documentation by Shawn O. Pearce <spearce@spearce.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-hash-object.txt b/Documentation/git-hash-object.txt
index 51edeec..4b0a502 100644
--- a/Documentation/git-hash-object.txt
+++ b/Documentation/git-hash-object.txt
@@ -53,14 +53,6 @@
 	conversion. If the file is read from standard input then this
 	is always implied, unless the --path option is given.
 
-Author
-------
-Written by Junio C Hamano <gitster@pobox.com>
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-help.txt b/Documentation/git-help.txt
index eccd0ff..42aa2b0 100644
--- a/Documentation/git-help.txt
+++ b/Documentation/git-help.txt
@@ -171,17 +171,6 @@
 as they are probably more user specific than repository specific.
 See linkgit:git-config[1] for more information about this.
 
-Author
-------
-Written by Junio C Hamano <gitster@pobox.com> and the git-list
-<git@vger.kernel.org>.
-
-Documentation
--------------
-Initial documentation was part of the linkgit:git[1] man page.
-Christian Couder <chriscool@tuxfamily.org> extracted and rewrote it a
-little. Maintenance is done by the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-http-fetch.txt b/Documentation/git-http-fetch.txt
index d91cb7f..fefa752 100644
--- a/Documentation/git-http-fetch.txt
+++ b/Documentation/git-http-fetch.txt
@@ -43,14 +43,6 @@
 	Verify that everything reachable from target is fetched.  Used after
 	an earlier fetch is interrupted.
 
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-http-push.txt b/Documentation/git-http-push.txt
index ddf7a18..82ae34b 100644
--- a/Documentation/git-http-push.txt
+++ b/Documentation/git-http-push.txt
@@ -91,15 +91,6 @@
 Optionally, a <ref> parameter can be prefixed with a plus '+' sign
 to disable the fast-forward check only on that ref.
 
-
-Author
-------
-Written by Nick Hengeveld <nickh@reactrix.com>
-
-Documentation
---------------
-Documentation by Nick Hengeveld
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-imap-send.txt b/Documentation/git-imap-send.txt
index 57aba42..d3013d6 100644
--- a/Documentation/git-imap-send.txt
+++ b/Documentation/git-imap-send.txt
@@ -124,14 +124,6 @@
 users may wish to visit this web page for more information:
   http://kb.mozillazine.org/Plain_text_e-mail_-_Thunderbird#Completely_plain_email
 
-Author
-------
-Derived from isync 1.0.1 by Mike McCormack.
-
-Documentation
---------------
-Documentation by Mike McCormack
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-index-pack.txt b/Documentation/git-index-pack.txt
index c2bb810..909687f 100644
--- a/Documentation/git-index-pack.txt
+++ b/Documentation/git-index-pack.txt
@@ -85,15 +85,6 @@
 .keep file used as a lock to prevent the race with 'git repack'
 mentioned above.
 
-
-Author
-------
-Written by Sergey Vlasov <vsu@altlinux.ru>
-
-Documentation
--------------
-Documentation by Sergey Vlasov
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-init-db.txt b/Documentation/git-init-db.txt
index eba3cb4..2c4c716 100644
--- a/Documentation/git-init-db.txt
+++ b/Documentation/git-init-db.txt
@@ -16,3 +16,7 @@
 
 This is a synonym for linkgit:git-init[1].  Please refer to the
 documentation of that command.
+
+GIT
+---
+Part of the linkgit:git[1] suite
diff --git a/Documentation/git-init.txt b/Documentation/git-init.txt
index 00d4a12..5931925 100644
--- a/Documentation/git-init.txt
+++ b/Documentation/git-init.txt
@@ -134,15 +134,6 @@
 <1> prepare /path/to/my/codebase/.git directory
 <2> add all existing file to the index
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-instaweb.txt b/Documentation/git-instaweb.txt
index 7477ce8..08f85ba 100644
--- a/Documentation/git-instaweb.txt
+++ b/Documentation/git-instaweb.txt
@@ -84,14 +84,6 @@
 'web.browser' will be used instead if it is defined. See
 linkgit:git-web{litdd}browse[1] for more information about this.
 
-Author
-------
-Written by Eric Wong <normalperson@yhbt.net>
-
-Documentation
---------------
-Documentation by Eric Wong <normalperson@yhbt.net>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt
index ff41784..7fb8423 100644
--- a/Documentation/git-log.txt
+++ b/Documentation/git-log.txt
@@ -181,14 +181,6 @@
 overridden by the 'GIT_NOTES_DISPLAY_REF' environment variable,
 and supplemented by the `--show-notes` option.
 
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-lost-found.txt b/Documentation/git-lost-found.txt
index 602b8d5..adf7e1c 100644
--- a/Documentation/git-lost-found.txt
+++ b/Documentation/git-lost-found.txt
@@ -67,15 +67,6 @@
 1ef2b196d909eed523d4f3c9bf54b78cdd6843c6
 ------------
 
-Author
-------
-Written by Junio C Hamano <gitster@pobox.com>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt
index 86abd13..4b28292 100644
--- a/Documentation/git-ls-files.txt
+++ b/Documentation/git-ls-files.txt
@@ -209,15 +209,6 @@
 --------
 linkgit:git-read-tree[1], linkgit:gitignore[5]
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano, Josh Triplett, and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-ls-remote.txt b/Documentation/git-ls-remote.txt
index abe7bf9..c3df8c0 100644
--- a/Documentation/git-ls-remote.txt
+++ b/Documentation/git-ls-remote.txt
@@ -10,7 +10,7 @@
 --------
 [verse]
 'git ls-remote' [--heads] [--tags]  [-u <exec> | --upload-pack <exec>]
-	      <repository> <refs>...
+	      <repository> [<refs>...]
 
 DESCRIPTION
 -----------
@@ -67,10 +67,6 @@
 	c5db5456ae3b0873fc659c19fafdde22313cc441	refs/tags/v0.99.2
 	7ceca275d047c90c0c7d5afb13ab97efdf51bd6e	refs/tags/v0.99.3
 
-Author
-------
-Written by Junio C Hamano <gitster@pobox.com>
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-ls-tree.txt b/Documentation/git-ls-tree.txt
index 76ed625..16e87fd 100644
--- a/Documentation/git-ls-tree.txt
+++ b/Documentation/git-ls-tree.txt
@@ -95,18 +95,6 @@
 with minimum width of 7 characters.  Object size is given only for blobs
 (file) entries; for other entries `-` character is used in place of size.
 
-
-Author
-------
-Written by Petr Baudis <pasky@suse.cz>
-Completely rewritten from scratch by Junio C Hamano <gitster@pobox.com>,
-another major rewrite by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list
-<git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-mailinfo.txt b/Documentation/git-mailinfo.txt
index 3ea5aad..ed45662 100644
--- a/Documentation/git-mailinfo.txt
+++ b/Documentation/git-mailinfo.txt
@@ -80,17 +80,6 @@
 <patch>::
 	The patch extracted from e-mail.
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org> and
-Junio C Hamano <gitster@pobox.com>
-
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-mailsplit.txt b/Documentation/git-mailsplit.txt
index 71912a1..9b2049d 100644
--- a/Documentation/git-mailsplit.txt
+++ b/Documentation/git-mailsplit.txt
@@ -46,16 +46,6 @@
 --keep-cr::
 	Do not remove `\r` from lines ending with `\r\n`.
 
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-and Junio C Hamano <gitster@pobox.com>
-
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-merge-base.txt b/Documentation/git-merge-base.txt
index eedef1b..ba36ec0 100644
--- a/Documentation/git-merge-base.txt
+++ b/Documentation/git-merge-base.txt
@@ -102,14 +102,6 @@
 the other (both are 'best' merge bases).  When the `--all` option is not given,
 it is unspecified which best one is output.
 
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 See also
 --------
 linkgit:git-rev-list[1],
diff --git a/Documentation/git-merge-file.txt b/Documentation/git-merge-file.txt
index f334d69..635c669 100644
--- a/Documentation/git-merge-file.txt
+++ b/Documentation/git-merge-file.txt
@@ -86,17 +86,6 @@
 	merges tmp/a123 and tmp/c345 with the base tmp/b234, but uses labels
 	`a` and `c` instead of `tmp/a123` and `tmp/c345`.
 
-
-Author
-------
-Written by Johannes Schindelin <johannes.schindelin@gmx.de>
-
-
-Documentation
---------------
-Documentation by Johannes Schindelin and the git-list <git@vger.kernel.org>,
-with parts copied from the original documentation of RCS 'merge'.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-merge-index.txt b/Documentation/git-merge-index.txt
index 921b38f..6ce5467 100644
--- a/Documentation/git-merge-index.txt
+++ b/Documentation/git-merge-index.txt
@@ -73,15 +73,6 @@
 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).
 
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-One-shot merge by Petr Baudis <pasky@ucw.cz>
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-merge-one-file.txt b/Documentation/git-merge-one-file.txt
index a163cfc..ee059de 100644
--- a/Documentation/git-merge-one-file.txt
+++ b/Documentation/git-merge-one-file.txt
@@ -15,15 +15,6 @@
 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
-------
-Written by Linus Torvalds <torvalds@osdl.org>,
-Junio C Hamano <gitster@pobox.com> and Petr Baudis <pasky@suse.cz>.
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt
index f869a7f..3bfa7b4 100644
--- a/Documentation/git-merge-tree.txt
+++ b/Documentation/git-merge-tree.txt
@@ -23,14 +23,6 @@
 index.  For this reason, the output from the command omits
 entries that match the <branch1> tree.
 
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt
index c1efaaa..fb4c05b 100644
--- a/Documentation/git-merge.txt
+++ b/Documentation/git-merge.txt
@@ -312,15 +312,6 @@
 linkgit:git-add[1], linkgit:git-rm[1],
 linkgit:git-mergetool[1]
 
-Author
-------
-Written by Junio C Hamano <gitster@pobox.com>
-
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-mergetool--lib.txt b/Documentation/git-mergetool--lib.txt
index d8df553..63edede 100644
--- a/Documentation/git-mergetool--lib.txt
+++ b/Documentation/git-mergetool--lib.txt
@@ -41,14 +41,6 @@
 	'$MERGED', '$LOCAL', '$REMOTE', and '$BASE' must be defined
 	for use by the merge tool.
 
-Author
-------
-Written by David Aguilar <davvid@gmail.com>
-
-Documentation
---------------
-Documentation by David Aguilar and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-mergetool.txt b/Documentation/git-mergetool.txt
index 1f75a84..1834adb 100644
--- a/Documentation/git-mergetool.txt
+++ b/Documentation/git-mergetool.txt
@@ -82,14 +82,6 @@
 causes `git mergetool` to automatically remove the backup as files
 are successfully merged.
 
-Author
-------
-Written by Theodore Y Ts'o <tytso@mit.edu>
-
-Documentation
---------------
-Documentation by Theodore Y Ts'o.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt
index 8bcc114..037ab10 100644
--- a/Documentation/git-mktag.txt
+++ b/Documentation/git-mktag.txt
@@ -32,15 +32,6 @@
 message part may contain a signature that git itself doesn't
 care about, but that can be verified with gpg.
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-mktree.txt b/Documentation/git-mktree.txt
index 81e3326..afe21be 100644
--- a/Documentation/git-mktree.txt
+++ b/Documentation/git-mktree.txt
@@ -34,14 +34,6 @@
 	optional.  Note - if the '-z' option is used, lines are terminated
 	with NUL.
 
-Author
-------
-Written by Junio C Hamano <gitster@pobox.com>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-mv.txt b/Documentation/git-mv.txt
index bdcb585..db0e030 100644
--- a/Documentation/git-mv.txt
+++ b/Documentation/git-mv.txt
@@ -39,17 +39,6 @@
 --dry-run::
 	Do nothing; only show what would happen
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-Rewritten by Ryan Anderson <ryan@michonline.com>
-Move functionality added by Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-name-rev.txt b/Documentation/git-name-rev.txt
index 2108237..ad1d146 100644
--- a/Documentation/git-name-rev.txt
+++ b/Documentation/git-name-rev.txt
@@ -70,15 +70,6 @@
 % git log | git name-rev --stdin
 ------------
 
-
-Author
-------
-Written by Johannes Schindelin <Johannes.Schindelin@gmx.de>
-
-Documentation
---------------
-Documentation by Johannes Schindelin.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt
index 65eff66..a51071e 100644
--- a/Documentation/git-pack-objects.txt
+++ b/Documentation/git-pack-objects.txt
@@ -219,15 +219,6 @@
 	With this option, parents that are hidden by grafts are packed
 	nevertheless.
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
--------------
-Documentation by Junio C Hamano
-
 SEE ALSO
 --------
 linkgit:git-rev-list[1]
diff --git a/Documentation/git-pack-redundant.txt b/Documentation/git-pack-redundant.txt
index d060787..db9f0f7 100644
--- a/Documentation/git-pack-redundant.txt
+++ b/Documentation/git-pack-redundant.txt
@@ -38,14 +38,6 @@
 --verbose::
 	Outputs some statistics to stderr. Has a small performance penalty.
 
-Author
-------
-Written by Lukas Sandström <lukass@etek.chalmers.se>
-
-Documentation
---------------
-Documentation by Lukas Sandström <lukass@etek.chalmers.se>
-
 SEE ALSO
 --------
 linkgit:git-pack-objects[1]
diff --git a/Documentation/git-pack-refs.txt b/Documentation/git-pack-refs.txt
index 1ee99c2..54b9253 100644
--- a/Documentation/git-pack-refs.txt
+++ b/Documentation/git-pack-refs.txt
@@ -56,11 +56,6 @@
 The command usually removes loose refs under `$GIT_DIR/refs`
 hierarchy after packing them.  This option tells it not to.
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-parse-remote.txt b/Documentation/git-parse-remote.txt
index 39d9daa..02217f6 100644
--- a/Documentation/git-parse-remote.txt
+++ b/Documentation/git-parse-remote.txt
@@ -17,14 +17,6 @@
 $GIT_DIR/branches/ and configuration variables that are related
 to fetching, pulling and pushing.
 
-Author
-------
-Written by Junio C Hamano.
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-patch-id.txt b/Documentation/git-patch-id.txt
index 4dae139..50e26f4 100644
--- a/Documentation/git-patch-id.txt
+++ b/Documentation/git-patch-id.txt
@@ -29,14 +29,6 @@
 <patch>::
 	The diff to create the ID of.
 
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-peek-remote.txt b/Documentation/git-peek-remote.txt
index 87dacd7..a34d62f 100644
--- a/Documentation/git-peek-remote.txt
+++ b/Documentation/git-peek-remote.txt
@@ -37,14 +37,6 @@
 	The repository to sync from.
 
 
-Author
-------
-Written by Junio C Hamano <gitster@pobox.com>
-
-Documentation
---------------
-Documentation by Junio C Hamano.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-prune-packed.txt b/Documentation/git-prune-packed.txt
index abfc6b6..9e6202c 100644
--- a/Documentation/git-prune-packed.txt
+++ b/Documentation/git-prune-packed.txt
@@ -36,14 +36,6 @@
 --quiet::
 	Squelch the progress indicator.
 
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by Ryan Anderson <ryan@michonline.com>
-
 SEE ALSO
 --------
 linkgit:git-pack-objects[1]
diff --git a/Documentation/git-prune.txt b/Documentation/git-prune.txt
index 4d673a5..f616a73 100644
--- a/Documentation/git-prune.txt
+++ b/Documentation/git-prune.txt
@@ -78,14 +78,6 @@
 linkgit:git-gc[1],
 linkgit:git-reflog[1]
 
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt
index b33e6be..c2a7f10 100644
--- a/Documentation/git-pull.txt
+++ b/Documentation/git-pull.txt
@@ -224,18 +224,6 @@
 --------
 linkgit:git-fetch[1], linkgit:git-merge[1], linkgit:git-config[1]
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-and Junio C Hamano <gitster@pobox.com>
-
-Documentation
---------------
-Documentation by Jon Loeliger,
-David Greaves,
-Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index e11660a..88acfcd 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -406,16 +406,6 @@
 and so would be unreachable.  As such, these commits would be removed by
 a `git gc` command on the origin repository.
 
-
-Author
-------
-Written by Junio C Hamano <gitster@pobox.com>, later rewritten in C
-by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-quiltimport.txt b/Documentation/git-quiltimport.txt
index 579e8d2..7f112f3 100644
--- a/Documentation/git-quiltimport.txt
+++ b/Documentation/git-quiltimport.txt
@@ -49,14 +49,6 @@
 or the value of the $QUILT_PATCHES environment
 variable.
 
-Author
-------
-Written by Eric Biederman <ebiederm@lnxi.com>
-
-Documentation
---------------
-Documentation by Eric Biederman <ebiederm@lnxi.com>
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-read-tree.txt b/Documentation/git-read-tree.txt
index 634423a..26fdadc 100644
--- a/Documentation/git-read-tree.txt
+++ b/Documentation/git-read-tree.txt
@@ -421,15 +421,6 @@
 linkgit:git-write-tree[1]; linkgit:git-ls-files[1];
 linkgit:gitignore[5]
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 96680c8..620d50e 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -66,8 +66,9 @@
     D---E---F---G master
 ------------
 
-The latter form is just a short-hand of `git checkout topic`
-followed by `git rebase master`.
+*NOTE:* The latter form is just a short-hand of `git checkout topic`
+followed by `git rebase master`. When rebase exits `topic` will
+remain the checked-out branch.
 
 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
@@ -658,7 +659,6 @@
 'everyone' downstream from 'topic' will now have to perform a "hard
 case" recovery too!
 
-
 BUGS
 ----
 The todo list presented by `--preserve-merges --interactive` does not
@@ -681,15 +681,6 @@
 1 --- 2 --- 4 --- 5
 ------------
 
-Authors
-------
-Written by Junio C Hamano <gitster@pobox.com> and
-Johannes E. Schindelin <johannes.schindelin@gmx.de>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-receive-pack.txt b/Documentation/git-receive-pack.txt
index 2790eeb..f34e0ae 100644
--- a/Documentation/git-receive-pack.txt
+++ b/Documentation/git-receive-pack.txt
@@ -151,15 +151,6 @@
 --------
 linkgit:git-send-pack[1]
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by Junio C Hamano.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-reflog.txt b/Documentation/git-reflog.txt
index e50bd9b..09057bf 100644
--- a/Documentation/git-reflog.txt
+++ b/Documentation/git-reflog.txt
@@ -90,14 +90,6 @@
 --verbose::
 	Print extra information on screen.
 
-Author
-------
-Written by Junio C Hamano <gitster@pobox.com>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-relink.txt b/Documentation/git-relink.txt
index 8fc809f..9893376 100644
--- a/Documentation/git-relink.txt
+++ b/Documentation/git-relink.txt
@@ -24,14 +24,6 @@
 <dir>::
 	Directories containing a .git/objects/ subdirectory.
 
-Author
-------
-Written by Ryan Anderson <ryan@michonline.com>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-remote-ext.txt b/Documentation/git-remote-ext.txt
index 2d65cfe..68263a6 100644
--- a/Documentation/git-remote-ext.txt
+++ b/Documentation/git-remote-ext.txt
@@ -7,17 +7,17 @@
 
 SYNOPSIS
 --------
-git remote add nick "ext::<command>[ <arguments>...]"
+git remote add <nick> "ext::<command>[ <arguments>...]"
 
 DESCRIPTION
 -----------
-This remote helper uses the specified 'program' to connect
+This remote helper uses the specified '<command>' to connect
 to a remote git server.
 
-Data written to stdin of this specified 'program' is assumed
+Data written to stdin of the specified '<command>' is assumed
 to be sent to a git:// server, git-upload-pack, git-receive-pack
 or git-upload-archive (depending on situation), and data read
-from stdout of this program is assumed to be received from
+from stdout of <command> is assumed to be received from
 the same service.
 
 Command and arguments are separated by an unescaped space.
@@ -40,7 +40,7 @@
 	git wants to invoke.
 
 '%G' (must be the first characters in an argument)::
-	This argument will not be passed to 'program'. Instead, it
+	This argument will not be passed to '<command>'. Instead, it
 	will cause the helper to start by sending git:// service requests to
 	the remote side with the service field set to an appropriate value and
 	the repository field set to rest of the argument. Default is not to send
@@ -50,7 +50,7 @@
 some tunnel.
 
 '%V' (must be first characters in argument)::
-	This argument will not be passed to 'program'. Instead it sets
+	This argument will not be passed to '<command>'. Instead it sets
 	the vhost field in the git:// service request (to rest of the argument).
 	Default is not to send vhost in such request (if sent).
 
@@ -76,7 +76,7 @@
 ---------
 This remote helper is transparently used by git when
 you use commands such as "git fetch <URL>", "git clone <URL>",
-, "git push <URL>" or "git remote add nick <URL>", where <URL>
+, "git push <URL>" or "git remote add <nick> <URL>", where <URL>
 begins with `ext::`.  Examples:
 
 "ext::ssh -i /home/foo/.ssh/somekey user&#64;host.example %S 'foo/repo'"::
diff --git a/Documentation/git-remote-helpers.txt b/Documentation/git-remote-helpers.txt
index 3a23477..87cd11f 100644
--- a/Documentation/git-remote-helpers.txt
+++ b/Documentation/git-remote-helpers.txt
@@ -201,12 +201,12 @@
 
 OPTIONS
 -------
-'option verbosity' <N>::
+'option verbosity' <n>::
 	Changes the verbosity of messages displayed by the helper.
-	A value of 0 for N means that processes operate
+	A value of 0 for <n> means that processes operate
 	quietly, and the helper produces only error output.
 	1 is the default level of verbosity, and higher values
-	of N correspond to the number of -v flags passed on the
+	of <n> correspond to the number of -v flags passed on the
 	command line.
 
 'option progress' \{'true'|'false'\}::
@@ -239,10 +239,6 @@
 --------
 linkgit:git-remote[1]
 
-Documentation
--------------
-Documentation by Daniel Barkalow and Ilari Liusvaara
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt
index c258ea4..37bd3e5 100644
--- a/Documentation/git-remote.txt
+++ b/Documentation/git-remote.txt
@@ -214,16 +214,6 @@
 linkgit:git-branch[1]
 linkgit:git-config[1]
 
-Author
-------
-Written by Junio Hamano
-
-
-Documentation
---------------
-Documentation by J. Bruce Fields and the git-list <git@vger.kernel.org>.
-
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-repack.txt b/Documentation/git-repack.txt
index 27f7865..0decee2 100644
--- a/Documentation/git-repack.txt
+++ b/Documentation/git-repack.txt
@@ -123,15 +123,6 @@
 is unaffected by this option as the conversion is performed on the fly
 as needed in that case.
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by Ryan Anderson <ryan@michonline.com>
-
 SEE ALSO
 --------
 linkgit:git-pack-objects[1]
diff --git a/Documentation/git-replace.txt b/Documentation/git-replace.txt
index fde2092..17df525 100644
--- a/Documentation/git-replace.txt
+++ b/Documentation/git-replace.txt
@@ -80,17 +80,6 @@
 linkgit:git-branch[1]
 linkgit:git[1]
 
-Author
-------
-Written by Christian Couder <chriscool@tuxfamily.org> and Junio C
-Hamano <gitster@pobox.com>, based on 'git tag' by Kristian Hogsberg
-<krh@redhat.com> and Carlos Rica <jasampler@gmail.com>.
-
-Documentation
---------------
-Documentation by Christian Couder <chriscool@tuxfamily.org> and the
-git-list <git@vger.kernel.org>, based on 'git tag' documentation.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-repo-config.txt b/Documentation/git-repo-config.txt
index e5bdb55..a0d1fa6 100644
--- a/Documentation/git-repo-config.txt
+++ b/Documentation/git-repo-config.txt
@@ -16,3 +16,7 @@
 
 This is a synonym for linkgit:git-config[1].  Please refer to the
 documentation of that command.
+
+GIT
+---
+Part of the linkgit:git[1] suite
diff --git a/Documentation/git-request-pull.txt b/Documentation/git-request-pull.txt
index 400f61f..3521d8e 100644
--- a/Documentation/git-request-pull.txt
+++ b/Documentation/git-request-pull.txt
@@ -29,14 +29,6 @@
 <end>::
 	Commit to end at; defaults to HEAD.
 
-Author
-------
-Written by Ryan Anderson <ryan@michonline.com> and Junio C Hamano <gitster@pobox.com>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-rerere.txt b/Documentation/git-rerere.txt
index db99d47..161ecad 100644
--- a/Documentation/git-rerere.txt
+++ b/Documentation/git-rerere.txt
@@ -205,11 +205,6 @@
 'git rerere' will be run by 'git rebase' to help you resolve this
 conflict.
 
-
-Author
-------
-Written by Junio C Hamano <gitster@pobox.com>
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-reset.txt b/Documentation/git-reset.txt
index 927ecee..8481f9d 100644
--- a/Documentation/git-reset.txt
+++ b/Documentation/git-reset.txt
@@ -397,15 +397,6 @@
 
 X means any state and U means an unmerged index.
 
-
-Author
-------
-Written by Junio C Hamano <gitster@pobox.com> and Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt
index 8e1e329..5ce4d7f 100644
--- a/Documentation/git-rev-list.txt
+++ b/Documentation/git-rev-list.txt
@@ -105,16 +105,6 @@
 
 include::pretty-formats.txt[]
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano, Jonas Fonseca
-and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt
index ff23cb0..02c44c9 100644
--- a/Documentation/git-rev-parse.txt
+++ b/Documentation/git-rev-parse.txt
@@ -308,16 +308,6 @@
 +
 but if $REV is empty, the commit object name from master will be printed.
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org> .
-Junio C Hamano <gitster@pobox.com> and Pierre Habouzit <madcoder@debian.org>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-revert.txt b/Documentation/git-revert.txt
index 45be851..ac10cfb 100644
--- a/Documentation/git-revert.txt
+++ b/Documentation/git-revert.txt
@@ -105,14 +105,6 @@
 	changes. The revert only modifies the working tree and the
 	index.
 
-Author
-------
-Written by Junio C Hamano <gitster@pobox.com>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 SEE ALSO
 --------
 linkgit:git-cherry-pick[1]
diff --git a/Documentation/git-rm.txt b/Documentation/git-rm.txt
index 0adbe8b..8c0554f 100644
--- a/Documentation/git-rm.txt
+++ b/Documentation/git-rm.txt
@@ -153,14 +153,6 @@
 --------
 linkgit:git-add[1]
 
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt
index 7ec9dab..ee14f74 100644
--- a/Documentation/git-send-email.txt
+++ b/Documentation/git-send-email.txt
@@ -348,7 +348,6 @@
 	one of 'always', 'never', 'cc', 'compose', or 'auto'. See '--confirm'
 	in the previous section for the meaning of these values.
 
-
 Use gmail as the smtp server
 ----------------------------
 
@@ -363,20 +362,6 @@
 Note: the following perl modules are required
       Net::SMTP::SSL, MIME::Base64 and Authen::SASL
 
-
-Author
-------
-Written by Ryan Anderson <ryan@michonline.com>
-
-git-send-email is originally based upon
-send_lots_of_email.pl by Greg Kroah-Hartman.
-
-
-Documentation
---------------
-Documentation by Ryan Anderson
-
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-send-pack.txt b/Documentation/git-send-pack.txt
index deaa7d9..17f8f55 100644
--- a/Documentation/git-send-pack.txt
+++ b/Documentation/git-send-pack.txt
@@ -114,15 +114,6 @@
 Optionally, a <ref> parameter can be prefixed with a plus '+' sign
 to disable the fast-forward check only on that ref.
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by Junio C Hamano.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-sh-setup.txt b/Documentation/git-sh-setup.txt
index 3da2413..053df50 100644
--- a/Documentation/git-sh-setup.txt
+++ b/Documentation/git-sh-setup.txt
@@ -66,15 +66,6 @@
 	outputs code for use with eval to set the GIT_AUTHOR_NAME,
 	GIT_AUTHOR_EMAIL and GIT_AUTHOR_DATE variables for a given commit.
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-shell.txt b/Documentation/git-shell.txt
index 6403126..d7d4b92 100644
--- a/Documentation/git-shell.txt
+++ b/Documentation/git-shell.txt
@@ -28,14 +28,6 @@
 programs in it. The programs are executed with a cwd of $HOME, and
 <argument> is parsed as a command-line string.
 
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by Petr Baudis and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-shortlog.txt b/Documentation/git-shortlog.txt
index 5cc3baf..ff3755b 100644
--- a/Documentation/git-shortlog.txt
+++ b/Documentation/git-shortlog.txt
@@ -68,15 +68,6 @@
 
 include::mailmap.txt[]
 
-
-Author
-------
-Written by Jeff Garzik <jgarzik@pobox.com>
-
-Documentation
---------------
-Documentation by Junio C Hamano.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-show-branch.txt b/Documentation/git-show-branch.txt
index 3b0c882..ee4559b 100644
--- a/Documentation/git-show-branch.txt
+++ b/Documentation/git-show-branch.txt
@@ -200,17 +200,6 @@
 Without `--list`, the output also shows how these tips are
 topologically related with each other.
 
-
-Author
-------
-Written by Junio C Hamano <gitster@pobox.com>
-
-
-Documentation
---------------
-Documentation by Junio C Hamano.
-
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-show-index.txt b/Documentation/git-show-index.txt
index 8382fbe..c4d99f1 100644
--- a/Documentation/git-show-index.txt
+++ b/Documentation/git-show-index.txt
@@ -20,15 +20,6 @@
 'git verify-pack -v'; this command only shows the packfile
 offset and SHA1 of each object.
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by Junio C Hamano
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-show-ref.txt b/Documentation/git-show-ref.txt
index be0ec18..3c45895 100644
--- a/Documentation/git-show-ref.txt
+++ b/Documentation/git-show-ref.txt
@@ -177,11 +177,6 @@
 linkgit:git-update-ref[1],
 linkgit:gitrepository-layout[5]
 
-AUTHORS
--------
-Written by Linus Torvalds <torvalds@osdl.org>.
-Man page by Jonas Fonseca <fonseca@diku.dk>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-show.txt b/Documentation/git-show.txt
index f0a8a1a..7f075e8 100644
--- a/Documentation/git-show.txt
+++ b/Documentation/git-show.txt
@@ -72,17 +72,6 @@
 
 include::i18n.txt[]
 
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org> and
-Junio C Hamano <gitster@pobox.com>.  Significantly enhanced by
-Johannes Schindelin <Johannes.Schindelin@gmx.de>.
-
-
-Documentation
--------------
-Documentation by David Greaves, Petr Baudis and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-stage.txt b/Documentation/git-stage.txt
index 7f251a5..ba3fe0d 100644
--- a/Documentation/git-stage.txt
+++ b/Documentation/git-stage.txt
@@ -17,3 +17,7 @@
 
 This is a synonym for linkgit:git-add[1].  Please refer to the
 documentation of that command.
+
+GIT
+---
+Part of the linkgit:git[1] suite
diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt
index 8728f7a..79abc38 100644
--- a/Documentation/git-stash.txt
+++ b/Documentation/git-stash.txt
@@ -257,10 +257,6 @@
 linkgit:git-reflog[1],
 linkgit:git-reset[1]
 
-AUTHOR
-------
-Written by Nanako Shiraishi <nanako3@bluebottle.com>
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt
index 5102a23..00b699f 100644
--- a/Documentation/git-status.txt
+++ b/Documentation/git-status.txt
@@ -174,14 +174,6 @@
 --------
 linkgit:gitignore[5]
 
-Author
-------
-Written by Junio C Hamano <gitster@pobox.com>.
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-stripspace.txt b/Documentation/git-stripspace.txt
index 7508c0e..10509cc 100644
--- a/Documentation/git-stripspace.txt
+++ b/Documentation/git-stripspace.txt
@@ -23,14 +23,6 @@
 <stream>::
 	Byte stream to act on.
 
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index 1ed331c..3a5aa01 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -257,11 +257,6 @@
 to each submodule url is "submodule.$name.url".  See linkgit:gitmodules[5]
 for details.
 
-
-AUTHOR
-------
-Written by Lars Hjemli <hjemli@gmail.com>
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index 0ade2ce..ea8fafd 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -66,7 +66,7 @@
 	Set the 'rewriteRoot' option in the [svn-remote] config.
 --rewrite-uuid=<UUID>;;
 	Set the 'rewriteUUID' option in the [svn-remote] config.
---username=<USER>;;
+--username=<user>;;
 	For transports that SVN handles authentication for (http,
 	https, and plain svn), specify the username.  For other
 	transports (eg svn+ssh://), you must include the username in
@@ -443,8 +443,8 @@
 	Only used with the 'init' command.
 	These are passed directly to 'git init'.
 
--r <ARG>::
---revision <ARG>::
+-r <arg>::
+--revision <arg>::
 	   Used with the 'fetch' command.
 +
 This allows revision ranges for partial/cauterized history
@@ -878,10 +878,6 @@
 --------
 linkgit:git-rebase[1]
 
-Author
-------
-Written by Eric Wong <normalperson@yhbt.net>.
-
-Documentation
--------------
-Written by Eric Wong <normalperson@yhbt.net>.
+GIT
+---
+Part of the linkgit:git[1] suite
diff --git a/Documentation/git-symbolic-ref.txt b/Documentation/git-symbolic-ref.txt
index 33a1536..d7795ed 100644
--- a/Documentation/git-symbolic-ref.txt
+++ b/Documentation/git-symbolic-ref.txt
@@ -53,10 +53,6 @@
 symbolic ref were printed correctly, with status 1 if the requested
 name is not a symbolic ref, or 128 if another error occurs.
 
-Author
-------
-Written by Junio C Hamano <gitster@pobox.com>
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt
index 65f76c5..61263fa 100644
--- a/Documentation/git-tag.txt
+++ b/Documentation/git-tag.txt
@@ -262,15 +262,6 @@
 --------
 linkgit:git-check-ref-format[1].
 
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>,
-Junio C Hamano <gitster@pobox.com> and Chris Wright <chrisw@osdl.org>.
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-tar-tree.txt b/Documentation/git-tar-tree.txt
index 3c786bd..5f15754 100644
--- a/Documentation/git-tar-tree.txt
+++ b/Documentation/git-tar-tree.txt
@@ -76,14 +76,6 @@
 	Put everything in the current head's Documentation/ directory
 	into 'git-1.4.0-docs.tar', with the prefix 'git-docs/'.
 
-Author
-------
-Written by Rene Scharfe.
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-unpack-file.txt b/Documentation/git-unpack-file.txt
index 995db9f..c49d727 100644
--- a/Documentation/git-unpack-file.txt
+++ b/Documentation/git-unpack-file.txt
@@ -22,14 +22,6 @@
 <blob>::
 	Must be a blob id
 
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-unpack-objects.txt b/Documentation/git-unpack-objects.txt
index 36d1038..dd77990 100644
--- a/Documentation/git-unpack-objects.txt
+++ b/Documentation/git-unpack-objects.txt
@@ -43,15 +43,6 @@
 --strict::
 	Don't write objects with broken content or links.
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
--------------
-Documentation by Junio C Hamano
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.txt
index 1ca56c8..d393129 100644
--- a/Documentation/git-update-index.txt
+++ b/Documentation/git-update-index.txt
@@ -365,15 +365,6 @@
 linkgit:git-config[1],
 linkgit:git-add[1]
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-update-ref.txt b/Documentation/git-update-ref.txt
index 9639f70..e25a65a 100644
--- a/Documentation/git-update-ref.txt
+++ b/Documentation/git-update-ref.txt
@@ -84,10 +84,6 @@
 unable to create a new log file, append to the existing log file
 or does not have committer information available.
 
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-update-server-info.txt b/Documentation/git-update-server-info.txt
index 035cc30..775024d 100644
--- a/Documentation/git-update-server-info.txt
+++ b/Documentation/git-update-server-info.txt
@@ -38,15 +38,6 @@
 
 * info/refs
 
-
-Author
-------
-Written by Junio C Hamano <gitster@pobox.com>
-
-Documentation
---------------
-Documentation by Junio C Hamano.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-upload-archive.txt b/Documentation/git-upload-archive.txt
index f5f2b39..acbf634 100644
--- a/Documentation/git-upload-archive.txt
+++ b/Documentation/git-upload-archive.txt
@@ -24,14 +24,6 @@
 <directory>::
 	The repository to get a tar archive from.
 
-Author
-------
-Written by Franck Bui-Huu.
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-upload-pack.txt b/Documentation/git-upload-pack.txt
index 71ca4ef..4c0ca9d 100644
--- a/Documentation/git-upload-pack.txt
+++ b/Documentation/git-upload-pack.txt
@@ -33,14 +33,6 @@
 <directory>::
 	The repository to sync from.
 
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by Junio C Hamano.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-var.txt b/Documentation/git-var.txt
index 458f3e2..6498f7c 100644
--- a/Documentation/git-var.txt
+++ b/Documentation/git-var.txt
@@ -65,14 +65,6 @@
 linkgit:git-tag[1]
 linkgit:git-config[1]
 
-Author
-------
-Written by Eric Biederman <ebiederm@xmission.com>
-
-Documentation
---------------
-Documentation by Eric Biederman and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-verify-pack.txt b/Documentation/git-verify-pack.txt
index 916a38a..7c2428d 100644
--- a/Documentation/git-verify-pack.txt
+++ b/Documentation/git-verify-pack.txt
@@ -8,7 +8,7 @@
 
 SYNOPSIS
 --------
-'git verify-pack' [-v|--verbose] [--] <pack>.idx ...
+'git verify-pack' [-v|--verbose] [-s|--stat-only] [--] <pack>.idx ...
 
 
 DESCRIPTION
@@ -47,14 +47,6 @@
 
 for objects that are deltified.
 
-Author
-------
-Written by Junio C Hamano <gitster@pobox.com>
-
-Documentation
---------------
-Documentation by Junio C Hamano
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-verify-tag.txt b/Documentation/git-verify-tag.txt
index 7112197..8c9a718 100644
--- a/Documentation/git-verify-tag.txt
+++ b/Documentation/git-verify-tag.txt
@@ -22,14 +22,6 @@
 <tag>...::
 	SHA1 identifiers of git tag objects.
 
-Author
-------
-Written by Jan Harkes <jaharkes@cs.cmu.edu> and Eric W. Biederman <ebiederm@xmission.com>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-web--browse.txt b/Documentation/git-web--browse.txt
index c0416e5..69d92fa 100644
--- a/Documentation/git-web--browse.txt
+++ b/Documentation/git-web--browse.txt
@@ -116,16 +116,6 @@
 as they are probably more user specific than repository specific.
 See linkgit:git-config[1] for more information about this.
 
-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.
-
-Documentation
--------------
-Documentation by Christian Couder <chriscool@tuxfamily.org> and the
-git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-whatchanged.txt b/Documentation/git-whatchanged.txt
index ea753cd..31f3663 100644
--- a/Documentation/git-whatchanged.txt
+++ b/Documentation/git-whatchanged.txt
@@ -63,17 +63,6 @@
 	The "--" is necessary to avoid confusion with the *branch* named
 	'gitk'
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org> and
-Junio C Hamano <gitster@pobox.com>
-
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-write-tree.txt b/Documentation/git-write-tree.txt
index bfceaca..e8c94c1 100644
--- a/Documentation/git-write-tree.txt
+++ b/Documentation/git-write-tree.txt
@@ -36,15 +36,6 @@
 	`<prefix>`.  This can be used to write the tree object
 	for a subproject that is in the named subdirectory.
 
-
-Author
-------
-Written by Linus Torvalds <torvalds@osdl.org>
-
-Documentation
---------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 0c32d45..5e57f69 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -745,16 +745,12 @@
 
 Authors
 -------
-* git's founding father is Linus Torvalds <torvalds@osdl.org>.
-* The current git nurse is Junio C Hamano <gitster@pobox.com>.
-* The git potty was written by Andreas Ericsson <ae@op5.se>.
-* General upbringing is handled by the git-list <git@vger.kernel.org>.
-
-Documentation
---------------
-The documentation for git suite was started by David Greaves
-<david@dgreaves.com>, and later enhanced greatly by the
-contributors on the git-list <git@vger.kernel.org>.
+Git was started by Linus Torvalds, and is currently maintained by Junio
+C Hamano. Numerous contributions have come from the git mailing list
+<git@vger.kernel.org>. For a more complete list of contributors, see
+http://git-scm.com/about. If you have a clone of git.git itself, the
+output of linkgit:git-shortlog[1] and linkgit:git-blame[1] can show you
+the authors for specific parts of the project.
 
 Reporting Bugs
 --------------
diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt
index 7e7e121..15aebc6 100644
--- a/Documentation/gitattributes.txt
+++ b/Documentation/gitattributes.txt
@@ -632,7 +632,7 @@
 `merge`
 ^^^^^^^
 
-The attribute `merge` affects how three versions of a file is
+The attribute `merge` affects how three versions of a file are
 merged when a file-level merge is necessary during `git merge`,
 and other commands such as `git revert` and `git cherry-pick`.
 
@@ -646,15 +646,15 @@
 
 	Take the version from the current branch as the
 	tentative merge result, and declare that the merge has
-	conflicts.  This is suitable for binary files that does
+	conflicts.  This is suitable for binary files that do
 	not have a well-defined merge semantics.
 
 Unspecified::
 
 	By default, this uses the same built-in 3-way merge
-	driver as is the case the `merge` attribute is set.
-	However, `merge.default` configuration variable can name
-	different merge driver to be used for paths to which the
+	driver as is the case when the `merge` attribute is set.
+	However, the `merge.default` configuration variable can name
+	different merge driver to be used with paths for which the
 	`merge` attribute is unspecified.
 
 String::
diff --git a/Documentation/gitcli.txt b/Documentation/gitcli.txt
index 6928724..f734f97 100644
--- a/Documentation/gitcli.txt
+++ b/Documentation/gitcli.txt
@@ -169,10 +169,6 @@
 http://marc.info/?l=git&m=119150393620273 for further
 information.
 
-Documentation
--------------
-Documentation by Pierre Habouzit and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/gitignore.txt b/Documentation/gitignore.txt
index 8416f34..2e7328b 100644
--- a/Documentation/gitignore.txt
+++ b/Documentation/gitignore.txt
@@ -156,11 +156,6 @@
 linkgit:git-rm[1], linkgit:git-update-index[1],
 linkgit:gitrepository-layout[5]
 
-Documentation
--------------
-Documentation by David Greaves, Junio C Hamano, Josh Triplett,
-Frank Lichtenheld, and the git-list <git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/gitk.txt b/Documentation/gitk.txt
index e21bac4..e10ac58 100644
--- a/Documentation/gitk.txt
+++ b/Documentation/gitk.txt
@@ -113,15 +113,6 @@
 	A minimal repository browser and git tool output highlighter written
 	in C using Ncurses.
 
-Author
-------
-Written by Paul Mackerras <paulus@samba.org>.
-
-Documentation
---------------
-Documentation by Junio C Hamano, Jonas Fonseca, and the git-list
-<git@vger.kernel.org>.
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt
index 6897794..15a2186 100644
--- a/Documentation/gitmodules.txt
+++ b/Documentation/gitmodules.txt
@@ -90,10 +90,6 @@
 --------
 linkgit:git-submodule[1] linkgit:git-config[1]
 
-DOCUMENTATION
--------------
-Documentation by Lars Hjemli <hjemli@gmail.com>
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt
index f04b48e..33716a3 100644
--- a/Documentation/glossary-content.txt
+++ b/Documentation/glossary-content.txt
@@ -273,6 +273,29 @@
 	<<def_pack,pack>>, to assist in efficiently accessing the contents of a
 	pack.
 
+[[def_pathspec]]pathspec::
+       Pattern used to specify paths.
++
+Pathspecs are used on the command line of "git ls-files", "git
+ls-tree", "git grep", "git checkout", and many other commands to
+limit the scope of operations to some subset of the tree or
+worktree.  See the documentation of each command for whether
+paths are relative to the current directory or toplevel.  The
+pathspec syntax is as follows:
+
+* any path matches itself
+* the pathspec up to the last slash represents a
+  directory prefix.  The scope of that pathspec is
+  limited to that subtree.
+* the rest of the pathspec is a pattern for the remainder
+  of the pathname.  Paths relative to the directory
+  prefix will be matched against that pattern using fnmatch(3);
+  in particular, '*' and '?' _can_ match directory separators.
++
+For example, Documentation/*.jpg will match all .jpg files
+in the Documentation subtree,
+including Documentation/chapter_1/figure_1.jpg.
+
 [[def_parent]]parent::
 	A <<def_commit_object,commit object>> contains a (possibly empty) list
 	of the logical predecessor(s) in the line of development, i.e. its
diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt
index e33e0f8..b613d4e 100644
--- a/Documentation/merge-options.txt
+++ b/Documentation/merge-options.txt
@@ -75,9 +75,17 @@
 ifndef::git-pull[]
 -q::
 --quiet::
-	Operate quietly.
+	Operate quietly. Implies --no-progress.
 
 -v::
 --verbose::
 	Be verbose.
+
+--progress::
+--no-progress::
+	Turn progress on/off explicitly. If neither is specified,
+	progress is shown if standard error is connected to a terminal.
+	Note that not all merge strategies may support progress
+	reporting.
+
 endif::git-pull[]
diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt
index 44a2ef1..9c47ad8 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -165,7 +165,7 @@
 -n 'number'::
 --max-count=<number>::
 
-	Limit the number of commits output.
+	Limit the number of commits to output.
 
 --skip=<number>::
 
diff --git a/Documentation/revisions.txt b/Documentation/revisions.txt
index 9e92734..04fceee 100644
--- a/Documentation/revisions.txt
+++ b/Documentation/revisions.txt
@@ -25,7 +25,8 @@
   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`, `ORIG_HEAD` and `MERGE_HEAD`);
+    useful only for `HEAD`, `FETCH_HEAD`, `ORIG_HEAD`, `MERGE_HEAD`
+    and `CHERRY_PICK_HEAD`);
 
   . otherwise, `refs/<name>` if exists;
 
@@ -46,6 +47,8 @@
 them easily.
 MERGE_HEAD records the commit(s) you are merging into your branch
 when you run 'git merge'.
+CHERRY_PICK_HEAD records the commit you are cherry-picking
+when you run 'git cherry-pick'.
 +
 Note that any of the `refs/*` cases above may come either from
 the `$GIT_DIR/refs` directory or from the `$GIT_DIR/packed-refs` file.
diff --git a/Makefile b/Makefile
index ade7923..5c2b797 100644
--- a/Makefile
+++ b/Makefile
@@ -1042,6 +1042,7 @@
 	NO_UNSETENV = YesPlease
 	NO_HSTRERROR = YesPlease
 	NO_SYS_SELECT_H = YesPlease
+	NO_FNMATCH_CASEFOLD = YesPlease
 	SNPRINTF_RETURNS_BOGUS = YesPlease
 	NO_NSEC = YesPlease
 	ifeq ($(uname_R),B.11.00)
diff --git a/RelNotes b/RelNotes
index b942e49..540b756 120000
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/1.7.4.txt
\ No newline at end of file
+Documentation/RelNotes/1.7.5.txt
\ No newline at end of file
diff --git a/abspath.c b/abspath.c
index 91ca00f..3005aed 100644
--- a/abspath.c
+++ b/abspath.c
@@ -14,7 +14,14 @@
 /* We allow "recursive" symbolic links. Only within reason, though. */
 #define MAXDEPTH 5
 
-const char *make_absolute_path(const char *path)
+/*
+ * Use this to get the real path, i.e. resolve links. If you want an
+ * absolute path but don't mind links, use absolute_path.
+ *
+ * If path is our buffer, then return path, as it's already what the
+ * user wants.
+ */
+const char *real_path(const char *path)
 {
 	static char bufs[2][PATH_MAX + 1], *buf = bufs[0], *next_buf = bufs[1];
 	char cwd[1024] = "";
@@ -24,6 +31,10 @@
 	char *last_elem = NULL;
 	struct stat st;
 
+	/* We've already done it */
+	if (path == buf || path == next_buf)
+		return path;
+
 	if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
 		die ("Too long path: %.*s", 60, path);
 
@@ -100,7 +111,14 @@
 	return cwd;
 }
 
-const char *make_nonrelative_path(const char *path)
+/*
+ * Use this to get an absolute path from a relative one. If you want
+ * to resolve links, you should use real_path.
+ *
+ * If the path is already absolute, then return path. As the user is
+ * never meant to free the return value, we're safe.
+ */
+const char *absolute_path(const char *path)
 {
 	static char buf[PATH_MAX + 1];
 
diff --git a/branch.c b/branch.c
index 93dc866..c0c865a 100644
--- a/branch.c
+++ b/branch.c
@@ -175,9 +175,14 @@
 			die("Cannot setup tracking information; starting point is not a branch.");
 		break;
 	case 1:
-		/* Unique completion -- good, only if it is a real ref */
-		if (explicit_tracking && !strcmp(real_ref, "HEAD"))
-			die("Cannot setup tracking information; starting point is not a branch.");
+		/* Unique completion -- good, only if it is a real branch */
+		if (prefixcmp(real_ref, "refs/heads/") &&
+		    prefixcmp(real_ref, "refs/remotes/")) {
+			if (explicit_tracking)
+				die("Cannot setup tracking information; starting point is not a branch.");
+			else
+				real_ref = NULL;
+		}
 		break;
 	default:
 		die("Ambiguous object name: '%s'.", start_name);
@@ -217,6 +222,7 @@
 
 void remove_branch_state(void)
 {
+	unlink(git_path("CHERRY_PICK_HEAD"));
 	unlink(git_path("MERGE_HEAD"));
 	unlink(git_path("MERGE_RR"));
 	unlink(git_path("MERGE_MSG"));
diff --git a/builtin/add.c b/builtin/add.c
index 42c906e..e127d5a 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -21,8 +21,7 @@
 static int patch_interactive, add_interactive, edit_interactive;
 static int take_worktree_changes;
 
-struct update_callback_data
-{
+struct update_callback_data {
 	int flags;
 	int add_errors;
 };
@@ -86,7 +85,7 @@
 	struct rev_info rev;
 	init_revisions(&rev, prefix);
 	setup_revisions(0, NULL, &rev, NULL);
-	rev.prune_data = pathspec;
+	init_pathspec(&rev.prune_data, pathspec);
 	rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
 	rev.diffopt.format_callback = update_callback;
 	data.flags = flags;
@@ -322,7 +321,7 @@
 	OPT__FORCE(&ignored_too, "allow adding otherwise ignored files"),
 	OPT_BOOLEAN('u', "update", &take_worktree_changes, "update tracked files"),
 	OPT_BOOLEAN('N', "intent-to-add", &intent_to_add, "record only the fact that the path will be added later"),
-	OPT_BOOLEAN('A', "all", &addremove, "add all, noticing removal of tracked files"),
+	OPT_BOOLEAN('A', "all", &addremove, "add changes from all tracked and untracked 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_BOOLEAN( 0 , "ignore-missing", &ignore_missing, "check if - even missing - files are ignored in dry run"),
diff --git a/builtin/apply.c b/builtin/apply.c
index 14951da..36e1507 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -204,6 +204,7 @@
 	unsigned hash : 24;
 	unsigned flag : 8;
 #define LINE_COMMON     1
+#define LINE_PATCHED	2
 };
 
 /*
@@ -2085,7 +2086,8 @@
 
 	/* Quick hash check */
 	for (i = 0; i < preimage_limit; i++)
-		if (preimage->line[i].hash != img->line[try_lno + i].hash)
+		if ((img->line[try_lno + i].flag & LINE_PATCHED) ||
+		    (preimage->line[i].hash != img->line[try_lno + i].hash))
 			return 0;
 
 	if (preimage_limit == preimage->nr) {
@@ -2428,11 +2430,15 @@
 	memcpy(img->line + applied_pos,
 	       postimage->line,
 	       postimage->nr * sizeof(*img->line));
+	for (i = 0; i < postimage->nr; i++)
+		img->line[applied_pos + i].flag |= LINE_PATCHED;
+
 	img->nr = nr;
 }
 
 static int apply_one_fragment(struct image *img, struct fragment *frag,
-			      int inaccurate_eof, unsigned ws_rule)
+			      int inaccurate_eof, unsigned ws_rule,
+			      int nth_fragment)
 {
 	int match_beginning, match_end;
 	const char *patch = frag->patch;
@@ -2638,6 +2644,15 @@
 				apply = 0;
 		}
 
+		if (apply_verbosely && applied_pos != pos) {
+			int offset = applied_pos - pos;
+			if (apply_in_reverse)
+				offset = 0 - offset;
+			fprintf(stderr,
+				"Hunk #%d succeeded at %d (offset %d lines).\n",
+				nth_fragment, applied_pos + 1, offset);
+		}
+
 		/*
 		 * Warn if it was necessary to reduce the number
 		 * of context lines.
@@ -2785,12 +2800,14 @@
 	const char *name = patch->old_name ? patch->old_name : patch->new_name;
 	unsigned ws_rule = patch->ws_rule;
 	unsigned inaccurate_eof = patch->inaccurate_eof;
+	int nth = 0;
 
 	if (patch->is_binary)
 		return apply_binary(img, patch);
 
 	while (frag) {
-		if (apply_one_fragment(img, frag, inaccurate_eof, ws_rule)) {
+		nth++;
+		if (apply_one_fragment(img, frag, inaccurate_eof, ws_rule, nth)) {
 			error("patch failed: %s:%ld", name, frag->oldpos);
 			if (!apply_with_reject)
 				return -1;
diff --git a/builtin/blame.c b/builtin/blame.c
index aa30ec5..f6b03f7 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -1312,8 +1312,7 @@
 /*
  * Information on commits, used for output.
  */
-struct commit_info
-{
+struct commit_info {
 	const char *author;
 	const char *author_mail;
 	unsigned long author_time;
diff --git a/builtin/branch.c b/builtin/branch.c
index 9e546e4..b9ba011 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -134,7 +134,7 @@
 	    in_merge_bases(rev, &head_rev, 1) != merged) {
 		if (merged)
 			warning("deleting branch '%s' that has been merged to\n"
-				"         '%s', but it is not yet merged to HEAD.",
+				"         '%s', but not yet been merged to HEAD.",
 				name, reference_name);
 		else
 			warning("not deleting branch '%s' that is not yet merged to\n"
@@ -390,6 +390,30 @@
 	return (is_merged == (merge_filter == SHOW_MERGED));
 }
 
+static void add_verbose_info(struct strbuf *out, struct ref_item *item,
+			     int verbose, int abbrev)
+{
+	struct strbuf subject = STRBUF_INIT, stat = STRBUF_INIT;
+	const char *sub = " **** invalid ref ****";
+	struct commit *commit = item->commit;
+
+	if (commit && !parse_commit(commit)) {
+		struct pretty_print_context ctx = {0};
+		pretty_print_commit(CMIT_FMT_ONELINE, commit,
+				    &subject, &ctx);
+		sub = subject.buf;
+	}
+
+	if (item->kind == REF_LOCAL_BRANCH)
+		fill_tracking_info(&stat, item->name, verbose > 1);
+
+	strbuf_addf(out, " %s %s%s",
+		find_unique_abbrev(item->commit->object.sha1, abbrev),
+		stat.buf, sub);
+	strbuf_release(&stat);
+	strbuf_release(&subject);
+}
+
 static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
 			   int abbrev, int current, char *prefix)
 {
@@ -430,27 +454,9 @@
 
 	if (item->dest)
 		strbuf_addf(&out, " -> %s", item->dest);
-	else if (verbose) {
-		struct strbuf subject = STRBUF_INIT, stat = STRBUF_INIT;
-		const char *sub = " **** invalid ref ****";
-
-		commit = item->commit;
-		if (commit && !parse_commit(commit)) {
-			struct pretty_print_context ctx = {0};
-			pretty_print_commit(CMIT_FMT_ONELINE, commit,
-					    &subject, &ctx);
-			sub = subject.buf;
-		}
-
-		if (item->kind == REF_LOCAL_BRANCH)
-			fill_tracking_info(&stat, item->name, verbose > 1);
-
-		strbuf_addf(&out, " %s %s%s",
-			find_unique_abbrev(item->commit->object.sha1, abbrev),
-			stat.buf, sub);
-		strbuf_release(&stat);
-		strbuf_release(&subject);
-	}
+	else if (verbose)
+		/* " f7c0c00 [ahead 58, behind 197] vcs-svn: drop obj_pool.h" */
+		add_verbose_info(&out, item, verbose, abbrev);
 	printf("%s\n", out.buf);
 	strbuf_release(&name);
 	strbuf_release(&out);
diff --git a/builtin/checkout.c b/builtin/checkout.c
index bef324e..2bf02f2 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -30,6 +30,7 @@
 	int quiet;
 	int merge;
 	int force;
+	int force_detach;
 	int writeout_stage;
 	int writeout_error;
 
@@ -541,7 +542,17 @@
 	strbuf_addf(&msg, "checkout: moving from %s to %s",
 		    old_desc ? old_desc : "(invalid)", new->name);
 
-	if (new->path) {
+	if (!strcmp(new->name, "HEAD") && !new->path && !opts->force_detach) {
+		/* Nothing to do. */
+	} else if (opts->force_detach || !new->path) {	/* No longer on any branch. */
+		update_ref(msg.buf, "HEAD", new->commit->object.sha1, NULL,
+			   REF_NODEREF, DIE_ON_ERR);
+		if (!opts->quiet) {
+			if (old->path && advice_detached_head)
+				detach_advice(old->path, new->name);
+			describe_detached_head("HEAD is now at", new->commit);
+		}
+	} else if (new->path) {	/* Switch branches. */
 		create_symref("HEAD", new->path, msg.buf);
 		if (!opts->quiet) {
 			if (old->path && !strcmp(new->path, old->path))
@@ -563,21 +574,108 @@
 			if (!file_exists(ref_file) && file_exists(log_file))
 				remove_path(log_file);
 		}
-	} else if (strcmp(new->name, "HEAD")) {
-		update_ref(msg.buf, "HEAD", new->commit->object.sha1, NULL,
-			   REF_NODEREF, DIE_ON_ERR);
-		if (!opts->quiet) {
-			if (old->path && advice_detached_head)
-				detach_advice(old->path, new->name);
-			describe_detached_head("HEAD is now at", new->commit);
-		}
 	}
 	remove_branch_state();
 	strbuf_release(&msg);
-	if (!opts->quiet && (new->path || !strcmp(new->name, "HEAD")))
+	if (!opts->quiet &&
+	    (new->path || (!opts->force_detach && !strcmp(new->name, "HEAD"))))
 		report_tracking(new);
 }
 
+struct rev_list_args {
+	int argc;
+	int alloc;
+	const char **argv;
+};
+
+static void add_one_rev_list_arg(struct rev_list_args *args, const char *s)
+{
+	ALLOC_GROW(args->argv, args->argc + 1, args->alloc);
+	args->argv[args->argc++] = s;
+}
+
+static int add_one_ref_to_rev_list_arg(const char *refname,
+				       const unsigned char *sha1,
+				       int flags,
+				       void *cb_data)
+{
+	add_one_rev_list_arg(cb_data, refname);
+	return 0;
+}
+
+
+static void describe_one_orphan(struct strbuf *sb, struct commit *commit)
+{
+	struct pretty_print_context ctx = { 0 };
+
+	parse_commit(commit);
+	strbuf_addstr(sb, " - ");
+	pretty_print_commit(CMIT_FMT_ONELINE, commit, sb, &ctx);
+	strbuf_addch(sb, '\n');
+}
+
+#define ORPHAN_CUTOFF 4
+static void suggest_reattach(struct commit *commit, struct rev_info *revs)
+{
+	struct commit *c, *last = NULL;
+	struct strbuf sb = STRBUF_INIT;
+	int lost = 0;
+	while ((c = get_revision(revs)) != NULL) {
+		if (lost < ORPHAN_CUTOFF)
+			describe_one_orphan(&sb, c);
+		last = c;
+		lost++;
+	}
+	if (ORPHAN_CUTOFF < lost) {
+		int more = lost - ORPHAN_CUTOFF;
+		if (more == 1)
+			describe_one_orphan(&sb, last);
+		else
+			strbuf_addf(&sb, " ... and %d more.\n", more);
+	}
+
+	fprintf(stderr,
+		"Warning: you are leaving %d commit%s behind, "
+		"not connected to\n"
+		"any of your branches:\n\n"
+		"%s\n"
+		"If you want to keep them by creating a new branch, "
+		"this may be a good time\nto do so with:\n\n"
+		" git branch new_branch_name %s\n\n",
+		lost, ((1 < lost) ? "s" : ""),
+		sb.buf,
+		sha1_to_hex(commit->object.sha1));
+	strbuf_release(&sb);
+}
+
+/*
+ * We are about to leave commit that was at the tip of a detached
+ * HEAD.  If it is not reachable from any ref, this is the last chance
+ * for the user to do so without resorting to reflog.
+ */
+static void orphaned_commit_warning(struct commit *commit)
+{
+	struct rev_list_args args = { 0, 0, NULL };
+	struct rev_info revs;
+
+	add_one_rev_list_arg(&args, "(internal)");
+	add_one_rev_list_arg(&args, sha1_to_hex(commit->object.sha1));
+	add_one_rev_list_arg(&args, "--not");
+	for_each_ref(add_one_ref_to_rev_list_arg, &args);
+	add_one_rev_list_arg(&args, "--");
+	add_one_rev_list_arg(&args, NULL);
+
+	init_revisions(&revs, NULL);
+	if (setup_revisions(args.argc - 1, args.argv, &revs, NULL) != 1)
+		die("internal error: only -- alone should have been left");
+	if (prepare_revision_walk(&revs))
+		die("internal error in revision walk");
+	if (!(commit->object.flags & UNINTERESTING))
+		suggest_reattach(commit, &revs);
+	else
+		describe_detached_head("Previous HEAD position was", commit);
+}
+
 static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
 {
 	int ret = 0;
@@ -605,13 +703,8 @@
 	if (ret)
 		return ret;
 
-	/*
-	 * If we were on a detached HEAD, but have now moved to
-	 * a new commit, we want to mention the old commit once more
-	 * to remind the user that it might be lost.
-	 */
 	if (!opts->quiet && !old.path && old.commit && new->commit != old.commit)
-		describe_detached_head("Previous HEAD position was", old.commit);
+		orphaned_commit_warning(old.commit);
 
 	update_refs_for_switch(opts, &old, new);
 
@@ -675,11 +768,123 @@
 	return NULL;
 }
 
+static int parse_branchname_arg(int argc, const char **argv,
+				int dwim_new_local_branch_ok,
+				struct branch_info *new,
+				struct tree **source_tree,
+				unsigned char rev[20],
+				const char **new_branch)
+{
+	int argcount = 0;
+	unsigned char branch_rev[20];
+	const char *arg;
+	int has_dash_dash;
+
+	/*
+	 * 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.  As a special case,
+	 *   if <something> is A...B (missing A or B means HEAD but you can
+	 *   omit at most one side), and if there is a unique merge base
+	 *   between A and B, A...B names that merge base.
+	 *
+	 *   With no paths, if <something> is _not_ a commit, no -t nor -b
+	 *   was given, and there is a tracking branch whose name is
+	 *   <something> in one and only one remote, then this is a short-hand
+	 *   to fork local <something> from that remote-tracking branch.
+	 *
+	 *   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)
+		return 0;
+
+	if (!strcmp(argv[0], "--"))	/* case (2) */
+		return 1;
+
+	arg = argv[0];
+	has_dash_dash = (argc > 1) && !strcmp(argv[1], "--");
+
+	if (!strcmp(arg, "-"))
+		arg = "@{-1}";
+
+	if (get_sha1_mb(arg, rev)) {
+		if (has_dash_dash)          /* case (1) */
+			die("invalid reference: %s", arg);
+		if (dwim_new_local_branch_ok &&
+		    !check_filename(NULL, arg) &&
+		    argc == 1) {
+			const char *remote = unique_tracking_name(arg);
+			if (!remote || get_sha1(remote, rev))
+				return argcount;
+			*new_branch = arg;
+			arg = remote;
+			/* DWIMmed to create local branch */
+		} else {
+			return argcount;
+		}
+	}
+
+	/* we can't end up being in (2) anymore, eat the argument */
+	argcount++;
+	argv++;
+	argc--;
+
+	new->name = arg;
+	setup_branch_path(new);
+
+	if (check_ref_format(new->path) == CHECK_REF_FORMAT_OK &&
+	    resolve_ref(new->path, branch_rev, 1, NULL))
+		hashcpy(rev, branch_rev);
+	else
+		new->path = NULL; /* not an existing branch */
+
+	new->commit = lookup_commit_reference_gently(rev, 1);
+	if (!new->commit) {
+		/* not a commit */
+		*source_tree = parse_tree_indirect(rev);
+	} else {
+		parse_commit(new->commit);
+		*source_tree = new->commit->tree;
+	}
+
+	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 {
+		argcount++;
+		argv++;
+		argc--;
+	}
+
+	return argcount;
+}
+
 int cmd_checkout(int argc, const char **argv, const char *prefix)
 {
 	struct checkout_opts opts;
 	unsigned char rev[20];
-	const char *arg;
 	struct branch_info new;
 	struct tree *source_tree = NULL;
 	char *conflict_style = NULL;
@@ -692,6 +897,7 @@
 		OPT_STRING('B', NULL, &opts.new_branch_force, "branch",
 			   "create/reset and checkout a branch"),
 		OPT_BOOLEAN('l', NULL, &opts.new_branch_log, "create reflog for new branch"),
+		OPT_BOOLEAN(0, "detach", &opts.force_detach, "detach the HEAD at named commit"),
 		OPT_SET_INT('t', "track",  &opts.track, "set upstream info for new branch",
 			BRANCH_TRACK_EXPLICIT),
 		OPT_STRING(0, "orphan", &opts.new_orphan_branch, "new branch", "new unparented branch"),
@@ -709,7 +915,6 @@
 		  PARSE_OPT_NOARG | PARSE_OPT_HIDDEN },
 		OPT_END(),
 	};
-	int has_dash_dash;
 
 	memset(&opts, 0, sizeof(opts));
 	memset(&new, 0, sizeof(new));
@@ -731,9 +936,15 @@
 		opts.new_branch = opts.new_branch_force;
 
 	if (patch_mode && (opts.track > 0 || opts.new_branch
-			   || opts.new_branch_log || opts.merge || opts.force))
+			   || opts.new_branch_log || opts.merge || opts.force
+			   || opts.force_detach))
 		die ("--patch is incompatible with all other options");
 
+	if (opts.force_detach && (opts.new_branch || opts.new_orphan_branch))
+		die("--detach cannot be used with -b/-B/--orphan");
+	if (opts.force_detach && 0 < opts.track)
+		die("--detach cannot be used with -t");
+
 	/* --track without -b should DWIM */
 	if (0 < opts.track && !opts.new_branch) {
 		const char *argv0 = argv[0];
@@ -766,105 +977,30 @@
 		die("git checkout: -f and -m are incompatible");
 
 	/*
-	 * case 1: git checkout <ref> -- [<paths>]
+	 * Extract branch name from command line arguments, so
+	 * all that is left is pathspecs.
 	 *
-	 *   <ref> must be a valid tree, everything after the '--' must be
-	 *   a path.
+	 * Handle
 	 *
-	 * case 2: git checkout -- [<paths>]
+	 *  1) git checkout <tree> -- [<paths>]
+	 *  2) git checkout -- [<paths>]
+	 *  3) git checkout <something> [<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.  As a special case,
-	 *   if <something> is A...B (missing A or B means HEAD but you can
-	 *   omit at most one side), and if there is a unique merge base
-	 *   between A and B, A...B names that merge base.
-	 *
-	 *   With no paths, if <something> is _not_ a commit, no -t nor -b
-	 *   was given, and there is a remote-tracking branch whose name is
-	 *   <something> in one and only one remote, then this is a short-hand
-	 *   to fork local <something> from that remote-tracking branch.
-	 *
-	 *   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.
-	 *
+	 * including "last branch" syntax and DWIM-ery for names of
+	 * remote branches, erroring out for invalid or ambiguous cases.
 	 */
 	if (argc) {
-		if (!strcmp(argv[0], "--")) {       /* case (2) */
-			argv++;
-			argc--;
-			goto no_reference;
-		}
-
-		arg = argv[0];
-		has_dash_dash = (argc > 1) && !strcmp(argv[1], "--");
-
-		if (!strcmp(arg, "-"))
-			arg = "@{-1}";
-
-		if (get_sha1_mb(arg, rev)) {
-			if (has_dash_dash)          /* case (1) */
-				die("invalid reference: %s", arg);
-			if (!patch_mode &&
-			    dwim_new_local_branch &&
-			    opts.track == BRANCH_TRACK_UNSPECIFIED &&
-			    !opts.new_branch &&
-			    !check_filename(NULL, arg) &&
-			    argc == 1) {
-				const char *remote = unique_tracking_name(arg);
-				if (!remote || get_sha1(remote, rev))
-					goto no_reference;
-				opts.new_branch = arg;
-				arg = remote;
-				/* DWIMmed to create local branch */
-			}
-			else
-				goto no_reference;
-		}
-
-		/* we can't end up being in (2) anymore, eat the argument */
-		argv++;
-		argc--;
-
-		new.name = arg;
-		if ((new.commit = lookup_commit_reference_gently(rev, 1))) {
-			setup_branch_path(&new);
-
-			if ((check_ref_format(new.path) == CHECK_REF_FORMAT_OK) &&
-			    resolve_ref(new.path, rev, 1, NULL))
-				;
-			else
-				new.path = NULL;
-			parse_commit(new.commit);
-			source_tree = new.commit->tree;
-		} 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--;
-		}
+		int dwim_ok =
+			!patch_mode &&
+			dwim_new_local_branch &&
+			opts.track == BRANCH_TRACK_UNSPECIFIED &&
+			!opts.new_branch;
+		int n = parse_branchname_arg(argc, argv, dwim_ok,
+				&new, &source_tree, rev, &opts.new_branch);
+		argv += n;
+		argc -= n;
 	}
 
-no_reference:
-
 	if (opts.track == BRANCH_TRACK_UNSPECIFIED)
 		opts.track = git_branch_track;
 
@@ -886,6 +1022,9 @@
 			}
 		}
 
+		if (opts.force_detach)
+			die("git checkout: --detach does not take a path argument");
+
 		if (1 < !!opts.writeout_stage + !!opts.force + !!opts.merge)
 			die("git checkout: --ours/--theirs, --force and --merge are incompatible when\nchecking out of the index.");
 
diff --git a/builtin/clone.c b/builtin/clone.c
index 38b4b71..02547ad 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -100,7 +100,7 @@
 		path = mkpath("%s%s", repo, suffix[i]);
 		if (is_directory(path)) {
 			*is_bundle = 0;
-			return xstrdup(make_nonrelative_path(path));
+			return xstrdup(absolute_path(path));
 		}
 	}
 
@@ -109,7 +109,7 @@
 		path = mkpath("%s%s", repo, bundle_suffix[i]);
 		if (!stat(path, &st) && S_ISREG(st.st_mode)) {
 			*is_bundle = 1;
-			return xstrdup(make_nonrelative_path(path));
+			return xstrdup(absolute_path(path));
 		}
 	}
 
@@ -203,7 +203,7 @@
 	struct transport *transport;
 	const struct ref *extra;
 
-	ref_git = make_absolute_path(option_reference);
+	ref_git = real_path(option_reference);
 
 	if (is_directory(mkpath("%s/.git/objects", ref_git)))
 		ref_git = mkpath("%s/.git", ref_git);
@@ -412,9 +412,9 @@
 
 	path = get_repo_path(repo_name, &is_bundle);
 	if (path)
-		repo = xstrdup(make_nonrelative_path(repo_name));
+		repo = xstrdup(absolute_path(repo_name));
 	else if (!strchr(repo_name, ':'))
-		repo = xstrdup(make_absolute_path(repo_name));
+		die("repository '%s' does not exist", repo_name);
 	else
 		repo = repo_name;
 	is_local = path && !is_bundle;
@@ -467,7 +467,7 @@
 
 	if (safe_create_leading_directories_const(git_dir) < 0)
 		die("could not create leading directories of '%s'", git_dir);
-	set_git_dir(make_absolute_path(git_dir));
+	set_git_dir(real_path(git_dir));
 
 	if (0 <= option_verbosity)
 		printf("Cloning into %s%s...\n",
diff --git a/builtin/commit.c b/builtin/commit.c
index d7f55e3..de0e111 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -54,9 +54,17 @@
 "it empty. You can repeat your command with --allow-empty, or you can\n"
 "remove the commit entirely with \"git reset HEAD^\".\n";
 
+static const char empty_cherry_pick_advice[] =
+"The previous cherry-pick is now empty, possibly due to conflict resolution.\n"
+"If you wish to commit it anyway, use:\n"
+"\n"
+"    git commit --allow-empty\n"
+"\n"
+"Otherwise, please use 'git reset'\n";
+
 static unsigned char head_sha1[20];
 
-static char *use_message_buffer;
+static const char *use_message_buffer;
 static const char commit_editmsg[] = "COMMIT_EDITMSG";
 static struct lock_file index_lock; /* real index */
 static struct lock_file false_lock; /* used only for partial commits */
@@ -68,6 +76,11 @@
 
 static const char *logfile, *force_author;
 static const char *template_file;
+/*
+ * The _message variables are commit names from which to take
+ * the commit message and/or authorship.
+ */
+static const char *author_message, *author_message_buffer;
 static char *edit_message, *use_message;
 static char *fixup_message, *squash_message;
 static int all, edit_flag, also, interactive, only, amend, signoff;
@@ -88,7 +101,8 @@
 } cleanup_mode;
 static char *cleanup_arg;
 
-static int use_editor = 1, initial_commit, in_merge, include_status = 1;
+static enum commit_whence whence;
+static int use_editor = 1, initial_commit, include_status = 1;
 static int show_ignored_in_status;
 static const char *only_include_assumed;
 static struct strbuf message;
@@ -119,13 +133,13 @@
 
 	OPT_GROUP("Commit message options"),
 	OPT_FILENAME('F', "file", &logfile, "read message from file"),
-	OPT_STRING(0, "author", &force_author, "AUTHOR", "override author for commit"),
-	OPT_STRING(0, "date", &force_date, "DATE", "override date for commit"),
-	OPT_CALLBACK('m', "message", &message, "MESSAGE", "commit message", opt_parse_m),
-	OPT_STRING('c', "reedit-message", &edit_message, "COMMIT", "reuse and edit message from specified commit"),
-	OPT_STRING('C', "reuse-message", &use_message, "COMMIT", "reuse message from specified commit"),
-	OPT_STRING(0, "fixup", &fixup_message, "COMMIT", "use autosquash formatted message to fixup specified commit"),
-	OPT_STRING(0, "squash", &squash_message, "COMMIT", "use autosquash formatted message to squash specified commit"),
+	OPT_STRING(0, "author", &force_author, "author", "override author for commit"),
+	OPT_STRING(0, "date", &force_date, "date", "override date for commit"),
+	OPT_CALLBACK('m', "message", &message, "message", "commit message", opt_parse_m),
+	OPT_STRING('c', "reedit-message", &edit_message, "commit", "reuse and edit message from specified commit"),
+	OPT_STRING('C', "reuse-message", &use_message, "commit", "reuse message from specified commit"),
+	OPT_STRING(0, "fixup", &fixup_message, "commit", "use autosquash formatted message to fixup specified commit"),
+	OPT_STRING(0, "squash", &squash_message, "commit", "use autosquash formatted message to squash specified commit"),
 	OPT_BOOLEAN(0, "reset-author", &renew_authorship, "the commit is authored by me now (used with -C-c/--amend)"),
 	OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
 	OPT_FILENAME('t', "template", &template_file, "use specified template file"),
@@ -163,6 +177,36 @@
 	OPT_END()
 };
 
+static void determine_whence(struct wt_status *s)
+{
+	if (file_exists(git_path("MERGE_HEAD")))
+		whence = FROM_MERGE;
+	else if (file_exists(git_path("CHERRY_PICK_HEAD")))
+		whence = FROM_CHERRY_PICK;
+	else
+		whence = FROM_COMMIT;
+	if (s)
+		s->whence = whence;
+}
+
+static const char *whence_s(void)
+{
+	char *s = "";
+
+	switch (whence) {
+	case FROM_COMMIT:
+		break;
+	case FROM_MERGE:
+		s = "merge";
+		break;
+	case FROM_CHERRY_PICK:
+		s = "cherry-pick";
+		break;
+	}
+
+	return s;
+}
+
 static void rollback_index_files(void)
 {
 	switch (commit_style) {
@@ -378,8 +422,8 @@
 	 */
 	commit_style = COMMIT_PARTIAL;
 
-	if (in_merge)
-		die("cannot do a partial commit during a merge.");
+	if (whence != FROM_COMMIT)
+		die("cannot do a partial commit during a %s.", whence_s());
 
 	memset(&partial, 0, sizeof(partial));
 	partial.strdup_strings = 1;
@@ -469,18 +513,18 @@
 	email = getenv("GIT_AUTHOR_EMAIL");
 	date = getenv("GIT_AUTHOR_DATE");
 
-	if (use_message && !renew_authorship) {
+	if (author_message) {
 		const char *a, *lb, *rb, *eol;
 
-		a = strstr(use_message_buffer, "\nauthor ");
+		a = strstr(author_message_buffer, "\nauthor ");
 		if (!a)
-			die("invalid commit: %s", use_message);
+			die("invalid commit: %s", author_message);
 
 		lb = strchrnul(a + strlen("\nauthor "), '<');
 		rb = strchrnul(lb, '>');
 		eol = strchrnul(rb, '\n');
 		if (!*lb || !*rb || !*eol)
-			die("invalid commit: %s", use_message);
+			die("invalid commit: %s", author_message);
 
 		if (lb == a + strlen("\nauthor "))
 			/* \nauthor <foo@example.com> */
@@ -634,18 +678,22 @@
 		if (strbuf_read_file(&sb, git_path("SQUASH_MSG"), 0) < 0)
 			die_errno("could not read SQUASH_MSG");
 		hook_arg1 = "squash";
-	} else if (template_file && !stat(template_file, &statbuf)) {
+	} else if (template_file) {
 		if (strbuf_read_file(&sb, template_file, 0) < 0)
 			die_errno("could not read '%s'", template_file);
 		hook_arg1 = "template";
 	}
 
 	/*
-	 * This final case does not modify the template message,
-	 * it just sets the argument to the prepare-commit-msg hook.
+	 * The remaining cases don't modify the template message, but
+	 * just set the argument(s) to the prepare-commit-msg hook.
 	 */
-	else if (in_merge)
+	else if (whence == FROM_MERGE)
 		hook_arg1 = "merge";
+	else if (whence == FROM_CHERRY_PICK) {
+		hook_arg1 = "commit";
+		hook_arg2 = "CHERRY_PICK_HEAD";
+	}
 
 	if (squash_message) {
 		/*
@@ -694,16 +742,18 @@
 	strbuf_addstr(&committer_ident, git_committer_info(0));
 	if (use_editor && include_status) {
 		char *ai_tmp, *ci_tmp;
-		if (in_merge)
+		if (whence != FROM_COMMIT)
 			fprintf(fp,
 				"#\n"
-				"# It looks like you may be committing a MERGE.\n"
+				"# It looks like you may be committing a %s.\n"
 				"# If this is not correct, please remove the file\n"
 				"#	%s\n"
 				"# and try again.\n"
 				"#\n",
-				git_path("MERGE_HEAD"));
-
+				whence_s(),
+				git_path(whence == FROM_MERGE
+					 ? "MERGE_HEAD"
+					 : "CHERRY_PICK_HEAD"));
 		fprintf(fp,
 			"\n"
 			"# Please enter the commit message for your changes.");
@@ -766,11 +816,18 @@
 
 	fclose(fp);
 
-	if (!commitable && !in_merge && !allow_empty &&
+	/*
+	 * Reject an attempt to record a non-merge empty commit without
+	 * explicit --allow-empty. In the cherry-pick case, it may be
+	 * empty due to conflict resolution, which the user should okay.
+	 */
+	if (!commitable && whence != FROM_MERGE && !allow_empty &&
 	    !(amend && is_a_merge(head_sha1))) {
 		run_status(stdout, index_file, prefix, 0, s);
 		if (amend)
 			fputs(empty_amend_advice, stderr);
+		else if (whence == FROM_CHERRY_PICK)
+			fputs(empty_cherry_pick_advice, stderr);
 		return 0;
 	}
 
@@ -898,6 +955,28 @@
 		die("Invalid untracked files mode '%s'", untracked_files_arg);
 }
 
+static const char *read_commit_message(const char *name)
+{
+	const char *out_enc, *out;
+	struct commit *commit;
+
+	commit = lookup_commit_reference_by_name(name);
+	if (!commit)
+		die("could not lookup commit %s", name);
+	out_enc = get_commit_output_encoding();
+	out = logmsg_reencode(commit, out_enc);
+
+	/*
+	 * If we failed to reencode the buffer, just copy it
+	 * byte for byte so the user can try to fix it up.
+	 * This also handles the case where input and output
+	 * encodings are identical.
+	 */
+	if (out == NULL)
+		out = xstrdup(commit->buffer);
+	return out;
+}
+
 static int parse_and_validate_options(int argc, const char *argv[],
 				      const char * const usage[],
 				      const char *prefix,
@@ -927,8 +1006,8 @@
 	/* Sanity check options */
 	if (amend && initial_commit)
 		die("You have nothing to amend.");
-	if (amend && in_merge)
-		die("You are in the middle of a merge -- cannot amend.");
+	if (amend && whence != FROM_COMMIT)
+		die("You are in the middle of a %s -- cannot amend.", whence_s());
 	if (fixup_message && squash_message)
 		die("Options --squash and --fixup cannot be used together");
 	if (use_message)
@@ -947,26 +1026,18 @@
 		use_message = edit_message;
 	if (amend && !use_message && !fixup_message)
 		use_message = "HEAD";
-	if (!use_message && renew_authorship)
+	if (!use_message && whence != FROM_CHERRY_PICK && renew_authorship)
 		die("--reset-author can be used only with -C, -c or --amend.");
 	if (use_message) {
-		const char *out_enc;
-		struct commit *commit;
-
-		commit = lookup_commit_reference_by_name(use_message);
-		if (!commit)
-			die("could not lookup commit %s", use_message);
-		out_enc = get_commit_output_encoding();
-		use_message_buffer = logmsg_reencode(commit, out_enc);
-
-		/*
-		 * If we failed to reencode the buffer, just copy it
-		 * byte for byte so the user can try to fix it up.
-		 * This also handles the case where input and output
-		 * encodings are identical.
-		 */
-		if (use_message_buffer == NULL)
-			use_message_buffer = xstrdup(commit->buffer);
+		use_message_buffer = read_commit_message(use_message);
+		if (!renew_authorship) {
+			author_message = use_message;
+			author_message_buffer = use_message_buffer;
+		}
+	}
+	if (whence == FROM_CHERRY_PICK && !renew_authorship) {
+		author_message = "CHERRY_PICK_HEAD";
+		author_message_buffer = read_commit_message(author_message);
 	}
 
 	if (!!also + !!only + !!all + !!interactive > 1)
@@ -1117,7 +1188,7 @@
 	wt_status_prepare(&s);
 	gitmodules_config();
 	git_config(git_status_config, &s);
-	in_merge = file_exists(git_path("MERGE_HEAD"));
+	determine_whence(&s);
 	argc = parse_options(argc, argv, prefix,
 			     builtin_status_options,
 			     builtin_status_usage, 0);
@@ -1140,7 +1211,6 @@
 	}
 
 	s.is_initial = get_sha1(s.reference, sha1) ? 1 : 0;
-	s.in_merge = in_merge;
 	s.ignore_submodule_arg = ignore_submodule_arg;
 	wt_status_collect(&s);
 
@@ -1215,7 +1285,6 @@
 	get_commit_format(format.buf, &rev);
 	rev.always_show_header = 0;
 	rev.diffopt.detect_rename = 1;
-	rev.diffopt.rename_limit = 100;
 	rev.diffopt.break_opt = 0;
 	diff_setup_done(&rev.diffopt);
 
@@ -1302,8 +1371,7 @@
 
 	wt_status_prepare(&s);
 	git_config(git_commit_config, &s);
-	in_merge = file_exists(git_path("MERGE_HEAD"));
-	s.in_merge = in_merge;
+	determine_whence(&s);
 
 	if (s.use_color == -1)
 		s.use_color = git_use_color_default;
@@ -1340,7 +1408,7 @@
 
 		for (c = commit->parents; c; c = c->next)
 			pptr = &commit_list_insert(c->item, pptr)->next;
-	} else if (in_merge) {
+	} else if (whence == FROM_MERGE) {
 		struct strbuf m = STRBUF_INIT;
 		FILE *fp;
 
@@ -1369,7 +1437,9 @@
 			parents = reduce_heads(parents);
 	} else {
 		if (!reflog_msg)
-			reflog_msg = "commit";
+			reflog_msg = (whence == FROM_CHERRY_PICK)
+					? "commit (cherry-pick)"
+					: "commit";
 		pptr = &commit_list_insert(lookup_commit(head_sha1), pptr)->next;
 	}
 
@@ -1424,6 +1494,7 @@
 		die("cannot update HEAD ref");
 	}
 
+	unlink(git_path("CHERRY_PICK_HEAD"));
 	unlink(git_path("MERGE_HEAD"));
 	unlink(git_path("MERGE_MSG"));
 	unlink(git_path("MERGE_MODE"));
diff --git a/builtin/config.c b/builtin/config.c
index dad86fe..76be0b7 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -52,7 +52,7 @@
 	OPT_BOOLEAN(0, "global", &use_global_config, "use global config file"),
 	OPT_BOOLEAN(0, "system", &use_system_config, "use system config file"),
 	OPT_BOOLEAN(0, "local", &use_local_config, "use repository config file"),
-	OPT_STRING('f', "file", &given_config_file, "FILE", "use given config file"),
+	OPT_STRING('f', "file", &given_config_file, "file", "use given config file"),
 	OPT_GROUP("Action"),
 	OPT_BIT(0, "get", &actions, "get value: name [value-regex]", ACTION_GET),
 	OPT_BIT(0, "get-all", &actions, "get all values: key [value-regex]", ACTION_GET_ALL),
@@ -153,7 +153,6 @@
 static int get_value(const char *key_, const char *regex_)
 {
 	int ret = -1;
-	char *tl;
 	char *global = NULL, *repo_config = NULL;
 	const char *system_wide = NULL, *local;
 
@@ -167,18 +166,32 @@
 			system_wide = git_etc_gitconfig();
 	}
 
-	key = xstrdup(key_);
-	for (tl=key+strlen(key)-1; tl >= key && *tl != '.'; --tl)
-		*tl = tolower(*tl);
-	for (tl=key; *tl && *tl != '.'; ++tl)
-		*tl = tolower(*tl);
-
 	if (use_key_regexp) {
+		char *tl;
+
+		/*
+		 * NEEDSWORK: this naive pattern lowercasing obviously does not
+		 * work for more complex patterns like "^[^.]*Foo.*bar".
+		 * Perhaps we should deprecate this altogether someday.
+		 */
+
+		key = xstrdup(key_);
+		for (tl = key + strlen(key) - 1;
+		     tl >= key && *tl != '.';
+		     tl--)
+			*tl = tolower(*tl);
+		for (tl = key; *tl && *tl != '.'; tl++)
+			*tl = tolower(*tl);
+
 		key_regexp = (regex_t*)xmalloc(sizeof(regex_t));
 		if (regcomp(key_regexp, key, REG_EXTENDED)) {
 			fprintf(stderr, "Invalid key pattern: %s\n", key_);
+			free(key);
 			goto free_strings;
 		}
+	} else {
+		if (git_config_parse_key(key_, &key, NULL))
+			goto free_strings;
 	}
 
 	if (regex_) {
diff --git a/builtin/describe.c b/builtin/describe.c
index 342129f..3ba26dc 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -63,7 +63,7 @@
 	return n;
 }
 
-static int set_util(void *chain)
+static int set_util(void *chain, void *data)
 {
 	struct commit_name *n;
 	for (n = chain; n; n = n->next) {
@@ -289,7 +289,7 @@
 		fprintf(stderr, "searching to describe %s\n", arg);
 
 	if (!have_util) {
-		for_each_hash(&names, set_util);
+		for_each_hash(&names, set_util, NULL);
 		have_util = 1;
 	}
 
diff --git a/builtin/diff-files.c b/builtin/diff-files.c
index 951c7c8..46085f8 100644
--- a/builtin/diff-files.c
+++ b/builtin/diff-files.c
@@ -61,7 +61,7 @@
 	    (rev.diffopt.output_format & DIFF_FORMAT_PATCH))
 		rev.combine_merges = rev.dense_combined_merges = 1;
 
-	if (read_cache_preload(rev.diffopt.paths) < 0) {
+	if (read_cache_preload(rev.diffopt.pathspec.raw) < 0) {
 		perror("read_cache_preload");
 		return -1;
 	}
diff --git a/builtin/diff.c b/builtin/diff.c
index 42822cd..4c9deb2 100644
--- a/builtin/diff.c
+++ b/builtin/diff.c
@@ -135,7 +135,7 @@
 	    revs->max_count != -1 || revs->min_age != -1 ||
 	    revs->max_age != -1)
 		usage(builtin_diff_usage);
-	if (read_cache_preload(revs->diffopt.paths) < 0) {
+	if (read_cache_preload(revs->diffopt.pathspec.raw) < 0) {
 		perror("read_cache_preload");
 		return -1;
 	}
@@ -237,7 +237,7 @@
 		revs->combine_merges = revs->dense_combined_merges = 1;
 
 	setup_work_tree();
-	if (read_cache_preload(revs->diffopt.paths) < 0) {
+	if (read_cache_preload(revs->diffopt.pathspec.raw) < 0) {
 		perror("read_cache_preload");
 		return -1;
 	}
@@ -374,14 +374,10 @@
 		}
 		die("unhandled object '%s' given.", name);
 	}
-	if (rev.prune_data) {
-		const char **pathspec = rev.prune_data;
-		while (*pathspec) {
-			if (!path)
-				path = *pathspec;
-			paths++;
-			pathspec++;
-		}
+	if (rev.prune_data.nr) {
+		if (!path)
+			path = rev.prune_data.items[0].match;
+		paths += rev.prune_data.nr;
 	}
 
 	/*
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index c8fd46b..daf1945 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -619,9 +619,9 @@
 		OPT_CALLBACK(0, "tag-of-filtered-object", &tag_of_filtered_mode, "mode",
 			     "select handling of tags that tag filtered objects",
 			     parse_opt_tag_of_filtered_mode),
-		OPT_STRING(0, "export-marks", &export_filename, "FILE",
+		OPT_STRING(0, "export-marks", &export_filename, "file",
 			     "Dump marks to this file"),
-		OPT_STRING(0, "import-marks", &import_filename, "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"),
@@ -651,7 +651,7 @@
 	if (import_filename)
 		import_marks(import_filename);
 
-	if (import_filename && revs.prune_data)
+	if (import_filename && revs.prune_data.nr)
 		full_tree = 1;
 
 	get_tags_and_duplicates(&revs.pending, &extra_refs);
diff --git a/builtin/fetch.c b/builtin/fetch.c
index e94e001..1b6d4be 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -49,7 +49,7 @@
 		    "fetch from all remotes"),
 	OPT_BOOLEAN('a', "append", &append,
 		    "append to .git/FETCH_HEAD instead of overwriting"),
-	OPT_STRING(0, "upload-pack", &upload_pack, "PATH",
+	OPT_STRING(0, "upload-pack", &upload_pack, "path",
 		   "path to upload pack on remote end"),
 	OPT__FORCE(&force, "force overwrite of local branch"),
 	OPT_BOOLEAN('m', "multiple", &multiple,
@@ -69,9 +69,9 @@
 	OPT_BOOLEAN('u', "update-head-ok", &update_head_ok,
 		    "allow updating of HEAD ref"),
 	OPT_BOOLEAN(0, "progress", &progress, "force progress reporting"),
-	OPT_STRING(0, "depth", &depth, "DEPTH",
+	OPT_STRING(0, "depth", &depth, "depth",
 		   "deepen history of shallow clone"),
-	{ OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, "DIR",
+	{ OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, "dir",
 		   "prepend this to submodule path output", PARSE_OPT_HIDDEN },
 	OPT_END()
 };
diff --git a/builtin/grep.c b/builtin/grep.c
index fdf7131..0bf8c01 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -40,8 +40,7 @@
  * threads. The producer adds struct work_items to 'todo' and the
  * consumers pick work items from the same array.
  */
-struct work_item
-{
+struct work_item {
 	enum work_type type;
 	char *name;
 
@@ -329,106 +328,6 @@
 	return 0;
 }
 
-/*
- * Return non-zero if max_depth is negative or path has no more then max_depth
- * slashes.
- */
-static int accept_subdir(const char *path, int max_depth)
-{
-	if (max_depth < 0)
-		return 1;
-
-	while ((path = strchr(path, '/')) != NULL) {
-		max_depth--;
-		if (max_depth < 0)
-			return 0;
-		path++;
-	}
-	return 1;
-}
-
-/*
- * Return non-zero if name is a subdirectory of match and is not too deep.
- */
-static int is_subdir(const char *name, int namelen,
-		const char *match, int matchlen, int max_depth)
-{
-	if (matchlen > namelen || strncmp(name, match, matchlen))
-		return 0;
-
-	if (name[matchlen] == '\0') /* exact match */
-		return 1;
-
-	if (!matchlen || match[matchlen-1] == '/' || name[matchlen] == '/')
-		return accept_subdir(name + matchlen + 1, max_depth);
-
-	return 0;
-}
-
-/*
- * git grep pathspecs are somewhat different from diff-tree pathspecs;
- * pathname wildcards are allowed.
- */
-static int pathspec_matches(const char **paths, const char *name, int max_depth)
-{
-	int namelen, i;
-	if (!paths || !*paths)
-		return accept_subdir(name, max_depth);
-	namelen = strlen(name);
-	for (i = 0; paths[i]; i++) {
-		const char *match = paths[i];
-		int matchlen = strlen(match);
-		const char *cp, *meta;
-
-		if (is_subdir(name, namelen, match, matchlen, max_depth))
-			return 1;
-		if (!fnmatch(match, name, 0))
-			return 1;
-		if (name[namelen-1] != '/')
-			continue;
-
-		/* We are being asked if the directory ("name") is worth
-		 * descending into.
-		 *
-		 * Find the longest leading directory name that does
-		 * not have metacharacter in the pathspec; the name
-		 * we are looking at must overlap with that directory.
-		 */
-		for (cp = match, meta = NULL; cp - match < matchlen; cp++) {
-			char ch = *cp;
-			if (ch == '*' || ch == '[' || ch == '?') {
-				meta = cp;
-				break;
-			}
-		}
-		if (!meta)
-			meta = cp; /* fully literal */
-
-		if (namelen <= meta - match) {
-			/* Looking at "Documentation/" and
-			 * the pattern says "Documentation/howto/", or
-			 * "Documentation/diff*.txt".  The name we
-			 * have should match prefix.
-			 */
-			if (!memcmp(match, name, namelen))
-				return 1;
-			continue;
-		}
-
-		if (meta - match < namelen) {
-			/* Looking at "Documentation/howto/" and
-			 * the pattern says "Documentation/h*";
-			 * match up to "Do.../h"; this avoids descending
-			 * into "Documentation/technical/".
-			 */
-			if (!memcmp(match, name, meta - match))
-				return 1;
-			continue;
-		}
-	}
-	return 0;
-}
-
 static void *lock_and_read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size)
 {
 	void *data;
@@ -581,7 +480,7 @@
 	free(argv);
 }
 
-static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
+static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int cached)
 {
 	int hit = 0;
 	int nr;
@@ -591,7 +490,7 @@
 		struct cache_entry *ce = active_cache[nr];
 		if (!S_ISREG(ce->ce_mode))
 			continue;
-		if (!pathspec_matches(paths, ce->name, opt->max_depth))
+		if (!match_pathspec_depth(pathspec, ce->name, ce_namelen(ce), 0, NULL))
 			continue;
 		/*
 		 * If CE_VALID is on, we assume worktree file and its cache entry
@@ -618,44 +517,29 @@
 	return hit;
 }
 
-static int grep_tree(struct grep_opt *opt, const char **paths,
-		     struct tree_desc *tree,
-		     const char *tree_name, const char *base)
+static int grep_tree(struct grep_opt *opt, const struct pathspec *pathspec,
+		     struct tree_desc *tree, struct strbuf *base, int tn_len)
 {
-	int len;
-	int hit = 0;
+	int hit = 0, matched = 0;
 	struct name_entry entry;
-	char *down;
-	int tn_len = strlen(tree_name);
-	struct strbuf pathbuf;
-
-	strbuf_init(&pathbuf, PATH_MAX + tn_len);
-
-	if (tn_len) {
-		strbuf_add(&pathbuf, tree_name, tn_len);
-		strbuf_addch(&pathbuf, ':');
-		tn_len = pathbuf.len;
-	}
-	strbuf_addstr(&pathbuf, base);
-	len = pathbuf.len;
+	int old_baselen = base->len;
 
 	while (tree_entry(tree, &entry)) {
 		int te_len = tree_entry_len(entry.path, entry.sha1);
-		pathbuf.len = len;
-		strbuf_add(&pathbuf, entry.path, te_len);
 
-		if (S_ISDIR(entry.mode))
-			/* Match "abc/" against pathspec to
-			 * decide if we want to descend into "abc"
-			 * directory.
-			 */
-			strbuf_addch(&pathbuf, '/');
+		if (matched != 2) {
+			matched = tree_entry_interesting(&entry, base, tn_len, pathspec);
+			if (matched == -1)
+				break; /* no more matches */
+			if (!matched)
+				continue;
+		}
 
-		down = pathbuf.buf + tn_len;
-		if (!pathspec_matches(paths, down, opt->max_depth))
-			;
-		else if (S_ISREG(entry.mode))
-			hit |= grep_sha1(opt, entry.sha1, pathbuf.buf, tn_len);
+		strbuf_add(base, entry.path, te_len);
+
+		if (S_ISREG(entry.mode)) {
+			hit |= grep_sha1(opt, entry.sha1, base->buf, tn_len);
+		}
 		else if (S_ISDIR(entry.mode)) {
 			enum object_type type;
 			struct tree_desc sub;
@@ -666,18 +550,21 @@
 			if (!data)
 				die("unable to read tree (%s)",
 				    sha1_to_hex(entry.sha1));
+
+			strbuf_addch(base, '/');
 			init_tree_desc(&sub, data, size);
-			hit |= grep_tree(opt, paths, &sub, tree_name, down);
+			hit |= grep_tree(opt, pathspec, &sub, base, tn_len);
 			free(data);
 		}
+		strbuf_setlen(base, old_baselen);
+
 		if (hit && opt->status_only)
 			break;
 	}
-	strbuf_release(&pathbuf);
 	return hit;
 }
 
-static int grep_object(struct grep_opt *opt, const char **paths,
+static int grep_object(struct grep_opt *opt, const struct pathspec *pathspec,
 		       struct object *obj, const char *name)
 {
 	if (obj->type == OBJ_BLOB)
@@ -686,20 +573,30 @@
 		struct tree_desc tree;
 		void *data;
 		unsigned long size;
-		int hit;
+		struct strbuf base;
+		int hit, len;
+
 		data = read_object_with_reference(obj->sha1, tree_type,
 						  &size, NULL);
 		if (!data)
 			die("unable to read tree (%s)", sha1_to_hex(obj->sha1));
+
+		len = name ? strlen(name) : 0;
+		strbuf_init(&base, PATH_MAX + len + 1);
+		if (len) {
+			strbuf_add(&base, name, len);
+			strbuf_addch(&base, ':');
+		}
 		init_tree_desc(&tree, data, size);
-		hit = grep_tree(opt, paths, &tree, name, "");
+		hit = grep_tree(opt, pathspec, &tree, &base, base.len);
+		strbuf_release(&base);
 		free(data);
 		return hit;
 	}
 	die("unable to grep from object of type %s", typename(obj->type));
 }
 
-static int grep_objects(struct grep_opt *opt, const char **paths,
+static int grep_objects(struct grep_opt *opt, const struct pathspec *pathspec,
 			const struct object_array *list)
 {
 	unsigned int i;
@@ -709,7 +606,7 @@
 	for (i = 0; i < nr; i++) {
 		struct object *real_obj;
 		real_obj = deref_tag(list->objects[i].item, NULL, 0);
-		if (grep_object(opt, paths, real_obj, list->objects[i].name)) {
+		if (grep_object(opt, pathspec, real_obj, list->objects[i].name)) {
 			hit = 1;
 			if (opt->status_only)
 				break;
@@ -718,7 +615,7 @@
 	return hit;
 }
 
-static int grep_directory(struct grep_opt *opt, const char **paths)
+static int grep_directory(struct grep_opt *opt, const struct pathspec *pathspec)
 {
 	struct dir_struct dir;
 	int i, hit = 0;
@@ -726,8 +623,12 @@
 	memset(&dir, 0, sizeof(dir));
 	setup_standard_excludes(&dir);
 
-	fill_directory(&dir, paths);
+	fill_directory(&dir, pathspec->raw);
 	for (i = 0; i < dir.nr; i++) {
+		const char *name = dir.entries[i]->name;
+		int namelen = strlen(name);
+		if (!match_pathspec_depth(pathspec, name, namelen, 0, NULL))
+			continue;
 		hit |= grep_file(opt, dir.entries[i]->name);
 		if (hit && opt->status_only)
 			break;
@@ -758,11 +659,12 @@
 static int file_callback(const struct option *opt, const char *arg, int unset)
 {
 	struct grep_opt *grep_opt = opt->value;
+	int from_stdin = !strcmp(arg, "-");
 	FILE *patterns;
 	int lno = 0;
 	struct strbuf sb = STRBUF_INIT;
 
-	patterns = fopen(arg, "r");
+	patterns = from_stdin ? stdin : fopen(arg, "r");
 	if (!patterns)
 		die_errno("cannot open '%s'", arg);
 	while (strbuf_getline(&sb, patterns, '\n') == 0) {
@@ -776,7 +678,8 @@
 		s = strbuf_detach(&sb, &len);
 		append_grep_pat(grep_opt, s, len, arg, ++lno, GREP_PATTERN);
 	}
-	fclose(patterns);
+	if (!from_stdin)
+		fclose(patterns);
 	strbuf_release(&sb);
 	return 0;
 }
@@ -832,6 +735,7 @@
 	struct grep_opt opt;
 	struct object_array list = OBJECT_ARRAY_INIT;
 	const char **paths = NULL;
+	struct pathspec pathspec;
 	struct string_list path_list = STRING_LIST_INIT_NODUP;
 	int i;
 	int dummy;
@@ -1059,6 +963,9 @@
 		paths[0] = prefix;
 		paths[1] = NULL;
 	}
+	init_pathspec(&pathspec, paths);
+	pathspec.max_depth = opt.max_depth;
+	pathspec.recursive = 1;
 
 	if (show_in_pager && (cached || list.nr))
 		die("--open-files-in-pager only works on the worktree");
@@ -1089,16 +996,16 @@
 			die("--cached cannot be used with --no-index.");
 		if (list.nr)
 			die("--no-index cannot be used with revs.");
-		hit = grep_directory(&opt, paths);
+		hit = grep_directory(&opt, &pathspec);
 	} else if (!list.nr) {
 		if (!cached)
 			setup_work_tree();
 
-		hit = grep_cache(&opt, paths, cached);
+		hit = grep_cache(&opt, &pathspec, cached);
 	} else {
 		if (cached)
 			die("both --cached and trees are given.");
-		hit = grep_objects(&opt, paths, &list);
+		hit = grep_objects(&opt, &pathspec, &list);
 	}
 
 	if (use_threads)
diff --git a/builtin/hash-object.c b/builtin/hash-object.c
index 080af1a..c90acdd 100644
--- a/builtin/hash-object.c
+++ b/builtin/hash-object.c
@@ -15,7 +15,7 @@
 	struct stat st;
 	unsigned char sha1[20];
 	if (fstat(fd, &st) < 0 ||
-	    index_fd(sha1, fd, &st, write_object, type_from_string(type), path))
+	    index_fd(sha1, fd, &st, write_object, type_from_string(type), path, 1))
 		die(write_object
 		    ? "Unable to add %s to database"
 		    : "Unable to hash %s", path);
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 8dc5c0b..c7e600d 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -13,8 +13,7 @@
 static const char index_pack_usage[] =
 "git index-pack [-v] [-o <index-file>] [ --keep | --keep=<msg> ] [--strict] (<pack-file> | --stdin [--fix-thin] [<pack-file>])";
 
-struct object_entry
-{
+struct object_entry {
 	struct pack_idx_entry idx;
 	unsigned long size;
 	unsigned int hdr_size;
@@ -44,8 +43,7 @@
 #define FLAG_LINK (1u<<20)
 #define FLAG_CHECKED (1u<<21)
 
-struct delta_entry
-{
+struct delta_entry {
 	union delta_base base;
 	int obj_no;
 };
diff --git a/builtin/init-db.c b/builtin/init-db.c
index 4f5348e..8f5cfd7 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -498,13 +498,11 @@
 		is_bare_repository_cfg = guess_repository_type(git_dir);
 
 	if (!is_bare_repository_cfg) {
-		if (git_dir) {
-			const char *git_dir_parent = strrchr(git_dir, '/');
-			if (git_dir_parent) {
-				char *rel = xstrndup(git_dir, git_dir_parent - git_dir);
-				git_work_tree_cfg = xstrdup(make_absolute_path(rel));
-				free(rel);
-			}
+		const char *git_dir_parent = strrchr(git_dir, '/');
+		if (git_dir_parent) {
+			char *rel = xstrndup(git_dir, git_dir_parent - git_dir);
+			git_work_tree_cfg = xstrdup(real_path(rel));
+			free(rel);
 		}
 		if (!git_work_tree_cfg) {
 			git_work_tree_cfg = xcalloc(PATH_MAX, 1);
@@ -512,7 +510,7 @@
 				die_errno ("Cannot access current working directory");
 		}
 		if (work_tree)
-			set_git_work_tree(make_absolute_path(work_tree));
+			set_git_work_tree(real_path(work_tree));
 		else
 			set_git_work_tree(git_work_tree_cfg);
 		if (access(get_git_work_tree(), X_OK))
@@ -521,10 +519,10 @@
 	}
 	else {
 		if (work_tree)
-			set_git_work_tree(make_absolute_path(work_tree));
+			set_git_work_tree(real_path(work_tree));
 	}
 
-	set_git_dir(make_absolute_path(git_dir));
+	set_git_dir(real_path(git_dir));
 
 	return init_db(template_dir, flags);
 }
diff --git a/builtin/log.c b/builtin/log.c
index d8c6c28..99e33b3 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -89,7 +89,7 @@
 		rev->always_show_header = 0;
 	if (DIFF_OPT_TST(&rev->diffopt, FOLLOW_RENAMES)) {
 		rev->always_show_header = 0;
-		if (rev->diffopt.nr_paths != 1)
+		if (rev->diffopt.pathspec.nr != 1)
 			usage("git logs can only follow renames on one pathname at a time");
 	}
 	for (i = 1; i < argc; i++) {
@@ -1352,6 +1352,23 @@
 	NULL
 };
 
+static void print_commit(char sign, struct commit *commit, int verbose,
+			 int abbrev)
+{
+	if (!verbose) {
+		printf("%c %s\n", sign,
+		       find_unique_abbrev(commit->object.sha1, abbrev));
+	} else {
+		struct strbuf buf = STRBUF_INIT;
+		struct pretty_print_context ctx = {0};
+		pretty_print_commit(CMIT_FMT_ONELINE, commit, &buf, &ctx);
+		printf("%c %s %s\n", sign,
+		       find_unique_abbrev(commit->object.sha1, abbrev),
+		       buf.buf);
+		strbuf_release(&buf);
+	}
+}
+
 int cmd_cherry(int argc, const char **argv, const char *prefix)
 {
 	struct rev_info revs;
@@ -1436,22 +1453,7 @@
 		commit = list->item;
 		if (has_commit_patch_id(commit, &ids))
 			sign = '-';
-
-		if (verbose) {
-			struct strbuf buf = STRBUF_INIT;
-			struct pretty_print_context ctx = {0};
-			pretty_print_commit(CMIT_FMT_ONELINE, commit,
-					    &buf, &ctx);
-			printf("%c %s %s\n", sign,
-			       find_unique_abbrev(commit->object.sha1, abbrev),
-			       buf.buf);
-			strbuf_release(&buf);
-		}
-		else {
-			printf("%c %s\n", sign,
-			       find_unique_abbrev(commit->object.sha1, abbrev));
-		}
-
+		print_commit(sign, commit, verbose, abbrev);
 		list = list->next;
 	}
 
diff --git a/builtin/merge.c b/builtin/merge.c
index 8c58c3c..aa3453c 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -58,6 +58,7 @@
 static int verbosity;
 static int allow_rerere_auto;
 static int abort_current_merge;
+static int show_progress = -1;
 
 static struct strategy all_strategy[] = {
 	{ "recursive",  DEFAULT_TWOHEAD | NO_TRIVIAL },
@@ -194,12 +195,13 @@
 		"merge strategy to use", option_parse_strategy),
 	OPT_CALLBACK('X', "strategy-option", &xopts, "option=value",
 		"option for selected merge strategy", option_parse_x),
-	OPT_CALLBACK('m', "message", &merge_msg, "MESSAGE",
+	OPT_CALLBACK('m', "message", &merge_msg, "message",
 		"merge commit message (for a non-fast-forward merge)",
 		option_parse_message),
 	OPT__VERBOSITY(&verbosity),
 	OPT_BOOLEAN(0, "abort", &abort_current_merge,
 		"abort the current in-progress merge"),
+	OPT_SET_INT(0, "progress", &show_progress, "force progress reporting", 1),
 	OPT_END()
 };
 
@@ -660,6 +662,8 @@
 			o.subtree_shift = "";
 
 		o.renormalize = option_renormalize;
+		o.show_rename_progress =
+			show_progress == -1 ? isatty(2) : show_progress;
 
 		for (x = 0; x < xopts_nr; x++)
 			if (parse_merge_opt(&o, xopts[x]))
@@ -797,6 +801,32 @@
 
 }
 
+static void write_merge_msg(void)
+{
+	int fd = open(git_path("MERGE_MSG"), O_WRONLY | O_CREAT, 0666);
+	if (fd < 0)
+		die_errno("Could not open '%s' for writing",
+			  git_path("MERGE_MSG"));
+	if (write_in_full(fd, merge_msg.buf, merge_msg.len) != merge_msg.len)
+		die_errno("Could not write to '%s'", git_path("MERGE_MSG"));
+	close(fd);
+}
+
+static void read_merge_msg(void)
+{
+	strbuf_reset(&merge_msg);
+	if (strbuf_read_file(&merge_msg, git_path("MERGE_MSG"), 0) < 0)
+		die_errno("Could not read from '%s'", git_path("MERGE_MSG"));
+}
+
+static void run_prepare_commit_msg(void)
+{
+	write_merge_msg();
+	run_hook(get_index_file(), "prepare-commit-msg",
+		 git_path("MERGE_MSG"), "merge", NULL, NULL);
+	read_merge_msg();
+}
+
 static int merge_trivial(void)
 {
 	unsigned char result_tree[20], result_commit[20];
@@ -808,6 +838,7 @@
 	parent->next = xmalloc(sizeof(*parent->next));
 	parent->next->item = remoteheads->item;
 	parent->next->next = NULL;
+	run_prepare_commit_msg();
 	commit_tree(merge_msg.buf, result_tree, parent, result_commit, NULL);
 	finish(result_commit, "In-index merge");
 	drop_save();
@@ -837,6 +868,7 @@
 	}
 	free_commit_list(remoteheads);
 	strbuf_addch(&merge_msg, '\n');
+	run_prepare_commit_msg();
 	commit_tree(merge_msg.buf, result_tree, parents, result_commit, NULL);
 	strbuf_addf(&buf, "Merge made by %s.", wt_strategy);
 	finish(result_commit, buf.buf);
@@ -946,6 +978,9 @@
 	argc = parse_options(argc, argv, prefix, builtin_merge_options,
 			builtin_merge_usage, 0);
 
+	if (verbosity < 0 && show_progress == -1)
+		show_progress = 0;
+
 	if (abort_current_merge) {
 		int nargc = 2;
 		const char *nargv[] = {"reset", "--merge", NULL};
@@ -971,6 +1006,13 @@
 		else
 			die("You have not concluded your merge (MERGE_HEAD exists).");
 	}
+	if (file_exists(git_path("CHERRY_PICK_HEAD"))) {
+		if (advice_resolve_conflict)
+			die("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
+			    "Please, commit your changes before you can merge.");
+		else
+			die("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).");
+	}
 	resolve_undo_clear();
 
 	if (verbosity < 0)
@@ -1318,14 +1360,7 @@
 			die_errno("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_errno("Could not open '%s' for writing",
-				  git_path("MERGE_MSG"));
-		if (write_in_full(fd, merge_msg.buf, merge_msg.len) !=
-			merge_msg.len)
-			die_errno("Could not write to '%s'", git_path("MERGE_MSG"));
-		close(fd);
+		write_merge_msg();
 		fd = open(git_path("MERGE_MODE"), O_WRONLY | O_CREAT | O_TRUNC, 0666);
 		if (fd < 0)
 			die_errno("Could not open '%s' for writing",
diff --git a/builtin/notes.c b/builtin/notes.c
index 4d5556e..0aab150 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -537,16 +537,16 @@
 	const unsigned char *note;
 	struct msg_arg msg = { 0, 0, STRBUF_INIT };
 	struct option options[] = {
-		{ OPTION_CALLBACK, 'm', "message", &msg, "MSG",
+		{ OPTION_CALLBACK, 'm', "message", &msg, "msg",
 			"note contents as a string", PARSE_OPT_NONEG,
 			parse_msg_arg},
-		{ OPTION_CALLBACK, 'F', "file", &msg, "FILE",
+		{ OPTION_CALLBACK, 'F', "file", &msg, "file",
 			"note contents in a file", PARSE_OPT_NONEG,
 			parse_file_arg},
-		{ OPTION_CALLBACK, 'c', "reedit-message", &msg, "OBJECT",
+		{ OPTION_CALLBACK, 'c', "reedit-message", &msg, "object",
 			"reuse and edit specified note object", PARSE_OPT_NONEG,
 			parse_reedit_arg},
-		{ OPTION_CALLBACK, 'C', "reuse-message", &msg, "OBJECT",
+		{ OPTION_CALLBACK, 'C', "reuse-message", &msg, "object",
 			"reuse specified note object", PARSE_OPT_NONEG,
 			parse_reuse_arg},
 		OPT__FORCE(&force, "replace existing notes"),
@@ -682,16 +682,16 @@
 	const char * const *usage;
 	struct msg_arg msg = { 0, 0, STRBUF_INIT };
 	struct option options[] = {
-		{ OPTION_CALLBACK, 'm', "message", &msg, "MSG",
+		{ OPTION_CALLBACK, 'm', "message", &msg, "msg",
 			"note contents as a string", PARSE_OPT_NONEG,
 			parse_msg_arg},
-		{ OPTION_CALLBACK, 'F', "file", &msg, "FILE",
+		{ OPTION_CALLBACK, 'F', "file", &msg, "file",
 			"note contents in a file", PARSE_OPT_NONEG,
 			parse_file_arg},
-		{ OPTION_CALLBACK, 'c', "reedit-message", &msg, "OBJECT",
+		{ OPTION_CALLBACK, 'c', "reedit-message", &msg, "object",
 			"reuse and edit specified note object", PARSE_OPT_NONEG,
 			parse_reedit_arg},
-		{ OPTION_CALLBACK, 'C', "reuse-message", &msg, "OBJECT",
+		{ OPTION_CALLBACK, 'C', "reuse-message", &msg, "object",
 			"reuse specified note object", PARSE_OPT_NONEG,
 			parse_reuse_arg},
 		OPT_END()
diff --git a/builtin/patch-id.c b/builtin/patch-id.c
index 5125300..49a0472 100644
--- a/builtin/patch-id.c
+++ b/builtin/patch-id.c
@@ -73,6 +73,8 @@
 			p += 7;
 		else if (!memcmp(line, "From ", 5))
 			p += 5;
+		else if (!memcmp(line, "\\ ", 2) && 12 < strlen(line))
+			continue;
 
 		if (!get_sha1_hex(p, next_sha1)) {
 			found_next = 1;
diff --git a/builtin/push.c b/builtin/push.c
index 26171ff..6f6a66f 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -64,23 +64,33 @@
 	}
 }
 
-static void setup_push_tracking(void)
+static void setup_push_upstream(struct remote *remote)
 {
 	struct strbuf refspec = STRBUF_INIT;
 	struct branch *branch = branch_get(NULL);
 	if (!branch)
-		die("You are not currently on a branch.");
+		die("You are not currently on a branch.\n"
+		    "To push the history leading to the current (detached HEAD)\n"
+		    "state now, use\n"
+		    "\n"
+		    "    git push %s HEAD:<name-of-remote-branch>\n",
+		    remote->name);
 	if (!branch->merge_nr || !branch->merge)
-		die("The current branch %s is not tracking anything.",
+		die("The current branch %s has no upstream branch.\n"
+		    "To push the current branch and set the remote as upstream, use\n"
+		    "\n"
+		    "    git push --set-upstream %s %s\n",
+		    branch->name,
+		    remote->name,
 		    branch->name);
 	if (branch->merge_nr != 1)
-		die("The current branch %s is tracking multiple branches, "
+		die("The current branch %s has multiple upstream branches, "
 		    "refusing to push.", branch->name);
 	strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src);
 	add_refspec(refspec.buf);
 }
 
-static void setup_default_push_refspecs(void)
+static void setup_default_push_refspecs(struct remote *remote)
 {
 	switch (push_default) {
 	default:
@@ -88,8 +98,8 @@
 		add_refspec(":");
 		break;
 
-	case PUSH_DEFAULT_TRACKING:
-		setup_push_tracking();
+	case PUSH_DEFAULT_UPSTREAM:
+		setup_push_upstream(remote);
 		break;
 
 	case PUSH_DEFAULT_CURRENT:
@@ -147,7 +157,14 @@
 	if (!remote) {
 		if (repo)
 			die("bad repository '%s'", repo);
-		die("No destination configured to push to.");
+		die("No configured push destination.\n"
+		    "Either specify the URL from the command-line or configure a remote repository using\n"
+		    "\n"
+		    "    git remote add <name> <url>\n"
+		    "\n"
+		    "and then push using the remote name\n"
+		    "\n"
+		    "    git push <name>\n");
 	}
 
 	if (remote->mirror)
@@ -175,7 +192,7 @@
 			refspec = remote->push_refspec;
 			refspec_nr = remote->push_refspec_nr;
 		} else if (!(flags & TRANSPORT_PUSH_MIRROR))
-			setup_default_push_refspecs();
+			setup_default_push_refspecs(remote);
 	}
 	errs = 0;
 	if (remote->pushurl_nr) {
diff --git a/builtin/read-tree.c b/builtin/read-tree.c
index 73c89ed..93c9281 100644
--- a/builtin/read-tree.c
+++ b/builtin/read-tree.c
@@ -104,8 +104,8 @@
 	struct unpack_trees_options opts;
 	int prefix_set = 0;
 	const struct option read_tree_options[] = {
-		{ OPTION_CALLBACK, 0, "index-output", NULL, "FILE",
-		  "write resulting index to <FILE>",
+		{ OPTION_CALLBACK, 0, "index-output", NULL, "file",
+		  "write resulting index to <file>",
 		  PARSE_OPT_NONEG, index_output_cb },
 		OPT_SET_INT(0, "empty", &read_empty,
 			    "only empty the index", 1),
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 5fa4be8..d8e2c5f 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -740,7 +740,7 @@
 	const struct ref *extra;
 
 	e->name[-1] = '\0';
-	other = xstrdup(make_absolute_path(e->base));
+	other = xstrdup(real_path(e->base));
 	e->name[-1] = '/';
 	len = strlen(other);
 
diff --git a/builtin/rerere.c b/builtin/rerere.c
index 642bf35..67cbfeb 100644
--- a/builtin/rerere.c
+++ b/builtin/rerere.c
@@ -8,7 +8,7 @@
 #include "xdiff-interface.h"
 
 static const char * const rerere_usage[] = {
-	"git rerere [clear | status | diff | gc]",
+	"git rerere [clear | status | remaining | diff | gc]",
 	NULL,
 };
 
@@ -156,7 +156,17 @@
 	else if (!strcmp(argv[0], "status"))
 		for (i = 0; i < merge_rr.nr; i++)
 			printf("%s\n", merge_rr.items[i].string);
-	else if (!strcmp(argv[0], "diff"))
+	else if (!strcmp(argv[0], "remaining")) {
+		rerere_remaining(&merge_rr);
+		for (i = 0; i < merge_rr.nr; i++) {
+			if (merge_rr.items[i].util != RERERE_RESOLVED)
+				printf("%s\n", merge_rr.items[i].string);
+			else
+				/* prepare for later call to
+				 * string_list_clear() */
+				merge_rr.items[i].util = NULL;
+		}
+	} else if (!strcmp(argv[0], "diff"))
 		for (i = 0; i < merge_rr.nr; i++) {
 			const char *path = merge_rr.items[i].string;
 			const char *name = (const char *)merge_rr.items[i].util;
diff --git a/builtin/revert.c b/builtin/revert.c
index dc1b702..c57b872 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -3,7 +3,6 @@
 #include "object.h"
 #include "commit.h"
 #include "tag.h"
-#include "wt-status.h"
 #include "run-command.h"
 #include "exec_cmd.h"
 #include "utf8.h"
@@ -198,54 +197,20 @@
 	strbuf_addstr(msgbuf, p);
 }
 
-static void set_author_ident_env(const char *message)
+static void write_cherry_pick_head(void)
 {
-	const char *p = message;
-	if (!p)
-		die ("Could not read commit message of %s",
-				sha1_to_hex(commit->object.sha1));
-	while (*p && *p != '\n') {
-		const char *eol;
+	int fd;
+	struct strbuf buf = STRBUF_INIT;
 
-		for (eol = p; *eol && *eol != '\n'; eol++)
-			; /* do nothing */
-		if (!prefixcmp(p, "author ")) {
-			char *line, *pend, *email, *timestamp;
+	strbuf_addf(&buf, "%s\n", sha1_to_hex(commit->object.sha1));
 
-			p += 7;
-			line = xmemdupz(p, eol - p);
-			email = strchr(line, '<');
-			if (!email)
-				die ("Could not extract author email from %s",
-					sha1_to_hex(commit->object.sha1));
-			if (email == line)
-				pend = line;
-			else
-				for (pend = email; pend != line + 1 &&
-						isspace(pend[-1]); pend--);
-					; /* do nothing */
-			*pend = '\0';
-			email++;
-			timestamp = strchr(email, '>');
-			if (!timestamp)
-				die ("Could not extract author time from %s",
-					sha1_to_hex(commit->object.sha1));
-			*timestamp = '\0';
-			for (timestamp++; *timestamp && isspace(*timestamp);
-					timestamp++)
-				; /* do nothing */
-			setenv("GIT_AUTHOR_NAME", line, 1);
-			setenv("GIT_AUTHOR_EMAIL", email, 1);
-			setenv("GIT_AUTHOR_DATE", timestamp, 1);
-			free(line);
-			return;
-		}
-		p = eol;
-		if (*p == '\n')
-			p++;
-	}
-	die ("No author information found in %s",
-			sha1_to_hex(commit->object.sha1));
+	fd = open(git_path("CHERRY_PICK_HEAD"), O_WRONLY | O_CREAT, 0666);
+	if (fd < 0)
+		die_errno("Could not open '%s' for writing",
+			  git_path("CHERRY_PICK_HEAD"));
+	if (write_in_full(fd, buf.buf, buf.len) != buf.len || close(fd))
+		die_errno("Could not write to '%s'", git_path("CHERRY_PICK_HEAD"));
+	strbuf_release(&buf);
 }
 
 static void advise(const char *advice, ...)
@@ -263,15 +228,18 @@
 
 	if (msg) {
 		fprintf(stderr, "%s\n", msg);
+		/*
+		 * A conflict has occured but the porcelain
+		 * (typically rebase --interactive) wants to take care
+		 * of the commit itself so remove CHERRY_PICK_HEAD
+		 */
+		unlink(git_path("CHERRY_PICK_HEAD"));
 		return;
 	}
 
 	advise("after resolving the conflicts, mark the corrected paths");
 	advise("with 'git add <paths>' or 'git rm <paths>'");
-
-	if (action == CHERRY_PICK)
-		advise("and commit the result with 'git commit -c %s'",
-		       find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV));
+	advise("and commit the result with 'git commit'");
 }
 
 static void write_message(struct strbuf *msgbuf, const char *filename)
@@ -497,13 +465,14 @@
 		base_label = msg.parent_label;
 		next = commit;
 		next_label = msg.label;
-		set_author_ident_env(msg.message);
 		add_message_to_msg(&msgbuf, msg.message);
 		if (no_replay) {
 			strbuf_addstr(&msgbuf, "(cherry picked from commit ");
 			strbuf_addstr(&msgbuf, sha1_to_hex(commit->object.sha1));
 			strbuf_addstr(&msgbuf, ")\n");
 		}
+		if (!no_commit)
+			write_cherry_pick_head();
 	}
 
 	if (!strategy || !strcmp(strategy, "recursive") || action == REVERT) {
diff --git a/builtin/tag.c b/builtin/tag.c
index 246a2bc..7cf48ab 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -376,7 +376,7 @@
 		OPT_GROUP("Tag creation options"),
 		OPT_BOOLEAN('a', NULL, &annotate,
 					"annotated tag, needs a message"),
-		OPT_CALLBACK('m', NULL, &msg, "MESSAGE",
+		OPT_CALLBACK('m', NULL, &msg, "message",
 			     "tag message", parse_msg_arg),
 		OPT_FILENAME('F', NULL, &msgfile, "read message from file"),
 		OPT_BOOLEAN('s', NULL, &sign, "annotated and GPG-signed tag"),
diff --git a/builtin/update-index.c b/builtin/update-index.c
index 56baf27..d7850c6 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -546,7 +546,10 @@
 	 */
 	int pos;
 	int has_head = 1;
-	const char **pathspec = get_pathspec(prefix, av + 1);
+	const char **paths = get_pathspec(prefix, av + 1);
+	struct pathspec pathspec;
+
+	init_pathspec(&pathspec, paths);
 
 	if (read_ref("HEAD", head_sha1))
 		/* If there is no HEAD, that means it is an initial
@@ -559,7 +562,7 @@
 		struct cache_entry *old = NULL;
 		int save_nr;
 
-		if (ce_stage(ce) || !ce_path_match(ce, pathspec))
+		if (ce_stage(ce) || !ce_path_match(ce, &pathspec))
 			continue;
 		if (has_head)
 			old = read_one_ent(NULL, head_sha1,
@@ -578,6 +581,7 @@
 		if (save_nr != active_nr)
 			goto redo;
 	}
+	free_pathspec(&pathspec);
 	return 0;
 }
 
diff --git a/cache.h b/cache.h
index 2e59aae..fad2117 100644
--- a/cache.h
+++ b/cache.h
@@ -500,8 +500,23 @@
 extern int ie_match_stat(const struct index_state *, struct cache_entry *, struct stat *, unsigned int);
 extern int ie_modified(const struct index_state *, struct cache_entry *, struct stat *, unsigned int);
 
-extern int ce_path_match(const struct cache_entry *ce, const char **pathspec);
-extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, enum object_type type, const char *path);
+struct pathspec {
+	const char **raw; /* get_pathspec() result, not freed by free_pathspec() */
+	int nr;
+	unsigned int has_wildcard:1;
+	unsigned int recursive:1;
+	int max_depth;
+	struct pathspec_item {
+		const char *match;
+		int len;
+		unsigned int has_wildcard:1;
+	} *items;
+};
+
+extern int init_pathspec(struct pathspec *, const char **);
+extern void free_pathspec(struct pathspec *);
+extern int ce_path_match(const struct cache_entry *ce, const struct pathspec *pathspec);
+extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, enum object_type type, const char *path, int format_check);
 extern int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object);
 extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);
 
@@ -545,7 +560,6 @@
 extern int prefer_symlink_refs;
 extern int log_all_ref_updates;
 extern int warn_ambiguous_refs;
-extern int unique_abbrev_extra_length;
 extern int shared_repository;
 extern const char *apply_default_whitespace;
 extern const char *apply_default_ignorewhitespace;
@@ -571,7 +585,7 @@
 enum auto_crlf {
 	AUTO_CRLF_FALSE = 0,
 	AUTO_CRLF_TRUE = 1,
-	AUTO_CRLF_INPUT = -1,
+	AUTO_CRLF_INPUT = -1
 };
 
 extern enum auto_crlf auto_crlf;
@@ -608,7 +622,7 @@
 enum push_default_type {
 	PUSH_DEFAULT_NOTHING = 0,
 	PUSH_DEFAULT_MATCHING,
-	PUSH_DEFAULT_TRACKING,
+	PUSH_DEFAULT_UPSTREAM,
 	PUSH_DEFAULT_CURRENT
 };
 
@@ -717,9 +731,9 @@
 	return path[0] == '/' || has_dos_drive_prefix(path);
 }
 int is_directory(const char *);
-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);
+const char *real_path(const char *path);
+const char *absolute_path(const char *path);
+const char *relative_path(const char *abs, const char *base);
 int normalize_path_copy(char *dst, const char *src);
 int longest_ancestor_length(const char *path, const char *prefix_list);
 char *strip_path_suffix(const char *path, const char *suffix);
@@ -899,7 +913,8 @@
 	time_t mtime;
 	int pack_fd;
 	unsigned pack_local:1,
-		 pack_keep:1;
+		 pack_keep:1,
+		 do_not_close:1;
 	unsigned char sha1[20];
 	/* something like ".git/objects/pack/xxxxx.pack" */
 	char pack_name[FLEX_ARRAY]; /* more */
@@ -999,6 +1014,7 @@
 extern int git_config_string(const char **, const char *, const char *);
 extern int git_config_pathname(const char **, const char *, const char *);
 extern int git_config_set(const char *, const char *);
+extern int git_config_parse_key(const char *, char **, int *);
 extern int git_config_set_multivar(const char *, const char *, const char *, int);
 extern int git_config_rename_section(const char *, const char *);
 extern const char *git_etc_gitconfig(void);
diff --git a/commit.h b/commit.h
index 659c87c..4198513 100644
--- a/commit.h
+++ b/commit.h
@@ -68,8 +68,7 @@
 	CMIT_FMT_UNSPECIFIED
 };
 
-struct pretty_print_context
-{
+struct pretty_print_context {
 	int abbrev;
 	const char *subject;
 	const char *after_subject;
diff --git a/compat/bswap.h b/compat/bswap.h
index 54756db..5061214 100644
--- a/compat/bswap.h
+++ b/compat/bswap.h
@@ -21,14 +21,16 @@
 
 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
 
-#define bswap32(x) ({ \
-	uint32_t __res; \
-	if (__builtin_constant_p(x)) { \
-		__res = default_swab32(x); \
-	} else { \
-		__asm__("bswap %0" : "=r" (__res) : "0" ((uint32_t)(x))); \
-	} \
-	__res; })
+#define bswap32 git_bswap32
+static inline uint32_t git_bswap32(uint32_t x)
+{
+	uint32_t result;
+	if (__builtin_constant_p(x))
+		result = default_swab32(x);
+	else
+		__asm__("bswap %0" : "=r" (result) : "0" (x));
+	return result;
+}
 
 #elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
 
diff --git a/compat/mingw.c b/compat/mingw.c
index bee6054..878b1de 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -2,6 +2,9 @@
 #include "win32.h"
 #include <conio.h>
 #include "../strbuf.h"
+#include "../run-command.h"
+
+static const int delay[] = { 0, 1, 10, 20, 40 };
 
 int err_win_to_posix(DWORD winerr)
 {
@@ -116,6 +119,165 @@
 	return error;
 }
 
+static inline int is_file_in_use_error(DWORD errcode)
+{
+	switch (errcode) {
+	case ERROR_SHARING_VIOLATION:
+	case ERROR_ACCESS_DENIED:
+		return 1;
+	}
+
+	return 0;
+}
+
+static int read_yes_no_answer(void)
+{
+	char answer[1024];
+
+	if (fgets(answer, sizeof(answer), stdin)) {
+		size_t answer_len = strlen(answer);
+		int got_full_line = 0, c;
+
+		/* remove the newline */
+		if (answer_len >= 2 && answer[answer_len-2] == '\r') {
+			answer[answer_len-2] = '\0';
+			got_full_line = 1;
+		} else if (answer_len >= 1 && answer[answer_len-1] == '\n') {
+			answer[answer_len-1] = '\0';
+			got_full_line = 1;
+		}
+		/* flush the buffer in case we did not get the full line */
+		if (!got_full_line)
+			while ((c = getchar()) != EOF && c != '\n')
+				;
+	} else
+		/* we could not read, return the
+		 * default answer which is no */
+		return 0;
+
+	if (tolower(answer[0]) == 'y' && !answer[1])
+		return 1;
+	if (!strncasecmp(answer, "yes", sizeof(answer)))
+		return 1;
+	if (tolower(answer[0]) == 'n' && !answer[1])
+		return 0;
+	if (!strncasecmp(answer, "no", sizeof(answer)))
+		return 0;
+
+	/* did not find an answer we understand */
+	return -1;
+}
+
+static int ask_yes_no_if_possible(const char *format, ...)
+{
+	char question[4096];
+	const char *retry_hook[] = { NULL, NULL, NULL };
+	va_list args;
+
+	va_start(args, format);
+	vsnprintf(question, sizeof(question), format, args);
+	va_end(args);
+
+	if ((retry_hook[0] = getenv("GIT_ASK_YESNO"))) {
+		retry_hook[1] = question;
+		return !run_command_v_opt(retry_hook, 0);
+	}
+
+	if (!isatty(_fileno(stdin)) || !isatty(_fileno(stderr)))
+		return 0;
+
+	while (1) {
+		int answer;
+		fprintf(stderr, "%s (y/n) ", question);
+
+		if ((answer = read_yes_no_answer()) >= 0)
+			return answer;
+
+		fprintf(stderr, "Sorry, I did not understand your answer. "
+				"Please type 'y' or 'n'\n");
+	}
+}
+
+#undef unlink
+int mingw_unlink(const char *pathname)
+{
+	int ret, tries = 0;
+
+	/* read-only files cannot be removed */
+	chmod(pathname, 0666);
+	while ((ret = unlink(pathname)) == -1 && tries < ARRAY_SIZE(delay)) {
+		if (!is_file_in_use_error(GetLastError()))
+			break;
+		/*
+		 * We assume that some other process had the source or
+		 * destination file open at the wrong moment and retry.
+		 * In order to give the other process a higher chance to
+		 * complete its operation, we give up our time slice now.
+		 * If we have to retry again, we do sleep a bit.
+		 */
+		Sleep(delay[tries]);
+		tries++;
+	}
+	while (ret == -1 && is_file_in_use_error(GetLastError()) &&
+	       ask_yes_no_if_possible("Unlink of file '%s' failed. "
+			"Should I try again?", pathname))
+	       ret = unlink(pathname);
+	return ret;
+}
+
+static int is_dir_empty(const char *path)
+{
+	struct strbuf buf = STRBUF_INIT;
+	WIN32_FIND_DATAA findbuf;
+	HANDLE handle;
+
+	strbuf_addf(&buf, "%s\\*", path);
+	handle = FindFirstFileA(buf.buf, &findbuf);
+	if (handle == INVALID_HANDLE_VALUE) {
+		strbuf_release(&buf);
+		return GetLastError() == ERROR_NO_MORE_FILES;
+	}
+
+	while (!strcmp(findbuf.cFileName, ".") ||
+			!strcmp(findbuf.cFileName, ".."))
+		if (!FindNextFile(handle, &findbuf)) {
+			strbuf_release(&buf);
+			return GetLastError() == ERROR_NO_MORE_FILES;
+		}
+	FindClose(handle);
+	strbuf_release(&buf);
+	return 0;
+}
+
+#undef rmdir
+int mingw_rmdir(const char *pathname)
+{
+	int ret, tries = 0;
+
+	while ((ret = rmdir(pathname)) == -1 && tries < ARRAY_SIZE(delay)) {
+		if (!is_file_in_use_error(GetLastError()))
+			break;
+		if (!is_dir_empty(pathname)) {
+			errno = ENOTEMPTY;
+			break;
+		}
+		/*
+		 * We assume that some other process had the source or
+		 * destination file open at the wrong moment and retry.
+		 * In order to give the other process a higher chance to
+		 * complete its operation, we give up our time slice now.
+		 * If we have to retry again, we do sleep a bit.
+		 */
+		Sleep(delay[tries]);
+		tries++;
+	}
+	while (ret == -1 && is_file_in_use_error(GetLastError()) &&
+	       ask_yes_no_if_possible("Deletion of directory '%s' failed. "
+			"Should I try again?", pathname))
+	       ret = rmdir(pathname);
+	return ret;
+}
+
 #undef open
 int mingw_open (const char *filename, int oflags, ...)
 {
@@ -1249,7 +1411,6 @@
 {
 	DWORD attrs, gle;
 	int tries = 0;
-	static const int delay[] = { 0, 1, 10, 20, 40 };
 
 	/*
 	 * Try native rename() first to get errno right.
@@ -1291,6 +1452,11 @@
 		tries++;
 		goto repeat;
 	}
+	if (gle == ERROR_ACCESS_DENIED &&
+	       ask_yes_no_if_possible("Rename from '%s' to '%s' failed. "
+		       "Should I try again?", pold, pnew))
+		goto repeat;
+
 	errno = EACCES;
 	return -1;
 }
diff --git a/compat/mingw.h b/compat/mingw.h
index cafc1eb..62eccd3 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -119,14 +119,6 @@
 }
 #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
-
 #define WNOHANG 1
 pid_t waitpid(pid_t pid, int *status, unsigned options);
 
@@ -174,6 +166,12 @@
  * replacements of existing functions
  */
 
+int mingw_unlink(const char *pathname);
+#define unlink mingw_unlink
+
+int mingw_rmdir(const char *path);
+#define rmdir mingw_rmdir
+
 int mingw_open (const char *filename, int oflags, ...);
 #define open mingw_open
 
@@ -233,6 +231,22 @@
 #define getpagesize mingw_getpagesize
 #endif
 
+struct rlimit {
+	unsigned int rlim_cur;
+};
+#define RLIMIT_NOFILE 0
+
+static inline int getrlimit(int resource, struct rlimit *rlp)
+{
+	if (resource != RLIMIT_NOFILE) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	rlp->rlim_cur = 2048;
+	return 0;
+}
+
 /* Use mingw_lstat() instead of lstat()/stat() and
  * mingw_fstat() instead of fstat() on Windows.
  */
diff --git a/config.c b/config.c
index 625e051..fa740a6 100644
--- a/config.c
+++ b/config.c
@@ -20,8 +20,7 @@
 
 const char *config_exclusive_filename = NULL;
 
-struct config_item
-{
+struct config_item {
 	struct config_item *next;
 	char *name;
 	char *value;
@@ -499,13 +498,6 @@
 		return 0;
 	}
 
-	if (!strcmp(var, "core.abbrevguard")) {
-		unique_abbrev_extra_length = git_config_int(var, value);
-		if (unique_abbrev_extra_length < 0)
-			unique_abbrev_extra_length = 0;
-		return 0;
-	}
-
 	if (!strcmp(var, "core.bare")) {
 		is_bare_repository_cfg = git_config_bool(var, value);
 		return 0;
@@ -737,8 +729,10 @@
 			push_default = PUSH_DEFAULT_NOTHING;
 		else if (!strcmp(value, "matching"))
 			push_default = PUSH_DEFAULT_MATCHING;
-		else if (!strcmp(value, "tracking"))
-			push_default = PUSH_DEFAULT_TRACKING;
+		else if (!strcmp(value, "upstream"))
+			push_default = PUSH_DEFAULT_UPSTREAM;
+		else if (!strcmp(value, "tracking")) /* deprecated */
+			push_default = PUSH_DEFAULT_UPSTREAM;
 		else if (!strcmp(value, "current"))
 			push_default = PUSH_DEFAULT_CURRENT;
 		else {
@@ -1099,6 +1093,75 @@
 }
 
 /*
+ * Auxiliary function to sanity-check and split the key into the section
+ * identifier and variable name.
+ *
+ * Returns 0 on success, -1 when there is an invalid character in the key and
+ * -2 if there is no section name in the key.
+ *
+ * store_key - pointer to char* which will hold a copy of the key with
+ *             lowercase section and variable name
+ * baselen - pointer to int which will hold the length of the
+ *           section + subsection part, can be NULL
+ */
+int git_config_parse_key(const char *key, char **store_key, int *baselen_)
+{
+	int i, dot, baselen;
+	const char *last_dot = strrchr(key, '.');
+
+	/*
+	 * Since "key" actually contains the section name and the real
+	 * key name separated by a dot, we have to know where the dot is.
+	 */
+
+	if (last_dot == NULL || last_dot == key) {
+		error("key does not contain a section: %s", key);
+		return -2;
+	}
+
+	if (!last_dot[1]) {
+		error("key does not contain variable name: %s", key);
+		return -2;
+	}
+
+	baselen = last_dot - key;
+	if (baselen_)
+		*baselen_ = baselen;
+
+	/*
+	 * Validate the key and while at it, lower case it for matching.
+	 */
+	*store_key = xmalloc(strlen(key) + 1);
+
+	dot = 0;
+	for (i = 0; key[i]; i++) {
+		unsigned char c = key[i];
+		if (c == '.')
+			dot = 1;
+		/* Leave the extended basename untouched.. */
+		if (!dot || i > baselen) {
+			if (!iskeychar(c) ||
+			    (i == baselen + 1 && !isalpha(c))) {
+				error("invalid key: %s", key);
+				goto out_free_ret_1;
+			}
+			c = tolower(c);
+		} else if (c == '\n') {
+			error("invalid key (newline): %s", key);
+			goto out_free_ret_1;
+		}
+		(*store_key)[i] = c;
+	}
+	(*store_key)[i] = 0;
+
+	return 0;
+
+out_free_ret_1:
+	free(*store_key);
+	return -1;
+}
+
+/*
  * If value==NULL, unset in (remove from) config,
  * if value_regex!=NULL, disregard key/value pairs where value does not match.
  * if multi_replace==0, nothing, or only one matching key/value is replaced,
@@ -1124,59 +1187,23 @@
 int git_config_set_multivar(const char *key, const char *value,
 	const char *value_regex, int multi_replace)
 {
-	int i, dot;
 	int fd = -1, in_fd;
 	int ret;
 	char *config_filename;
 	struct lock_file *lock = NULL;
-	const char *last_dot = strrchr(key, '.');
 
 	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
-	 * key name separated by a dot, we have to know where the dot is.
-	 */
-
-	if (last_dot == NULL) {
-		error("key does not contain a section: %s", key);
-		ret = 2;
+	/* parse-key returns negative; flip the sign to feed exit(3) */
+	ret = 0 - git_config_parse_key(key, &store.key, &store.baselen);
+	if (ret)
 		goto out_free;
-	}
-	store.baselen = last_dot - key;
 
 	store.multi_replace = multi_replace;
 
-	/*
-	 * Validate the key and while at it, lower case it for matching.
-	 */
-	store.key = xmalloc(strlen(key) + 1);
-	dot = 0;
-	for (i = 0; key[i]; i++) {
-		unsigned char c = key[i];
-		if (c == '.')
-			dot = 1;
-		/* Leave the extended basename untouched.. */
-		if (!dot || i > store.baselen) {
-			if (!iskeychar(c) || (i == store.baselen+1 && !isalpha(c))) {
-				error("invalid key: %s", key);
-				free(store.key);
-				ret = 1;
-				goto out_free;
-			}
-			c = tolower(c);
-		} else if (c == '\n') {
-			error("invalid key (newline): %s", key);
-			free(store.key);
-			ret = 1;
-			goto out_free;
-		}
-		store.key[i] = c;
-	}
-	store.key[i] = 0;
 
 	/*
 	 * The lock serves a purpose in addition to locking: the new
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 893b771..0b0b913 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -246,6 +246,8 @@
 				fi
 			elif [ -f "$g/MERGE_HEAD" ]; then
 				r="|MERGING"
+			elif [ -f "$g/CHERRY_PICK_HEAD" ]; then
+				r="|CHERRY-PICKING"
 			elif [ -f "$g/BISECT_LOG" ]; then
 				r="|BISECTING"
 			fi
diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4
index a92beb6..7cb479c 100755
--- a/contrib/fast-import/git-p4
+++ b/contrib/fast-import/git-p4
@@ -543,13 +543,13 @@
         self.options = [
                 optparse.make_option("--verbose", dest="verbose", action="store_true"),
                 optparse.make_option("--origin", dest="origin"),
-                optparse.make_option("-M", dest="detectRename", action="store_true"),
+                optparse.make_option("-M", dest="detectRenames", action="store_true"),
         ]
         self.description = "Submit changes from git to the perforce depot."
         self.usage += " [name of git branch to submit into perforce depot]"
         self.interactive = True
         self.origin = ""
-        self.detectRename = False
+        self.detectRenames = False
         self.verbose = False
         self.isWindows = (platform.system() == "Windows")
 
@@ -570,7 +570,7 @@
                 continue
 
             if inDescriptionSection:
-                if line.startswith("Files:"):
+                if line.startswith("Files:") or line.startswith("Jobs:"):
                     inDescriptionSection = False
                 else:
                     continue
@@ -613,7 +613,22 @@
 
     def applyCommit(self, id):
         print "Applying %s" % (read_pipe("git log --max-count=1 --pretty=oneline %s" % id))
-        diffOpts = ("", "-M")[self.detectRename]
+
+        if not self.detectRenames:
+            # If not explicitly set check the config variable
+            self.detectRenames = gitConfig("git-p4.detectRenames").lower() == "true"
+
+        if self.detectRenames:
+            diffOpts = "-M"
+        else:
+            diffOpts = ""
+
+        if gitConfig("git-p4.detectCopies").lower() == "true":
+            diffOpts += " -C"
+
+        if gitConfig("git-p4.detectCopiesHarder").lower() == "true":
+            diffOpts += " --find-copies-harder"
+
         diff = read_pipe_lines("git diff-tree -r %s \"%s^\" \"%s\"" % (diffOpts, id, id))
         filesToAdd = set()
         filesToDelete = set()
@@ -637,11 +652,23 @@
                 filesToDelete.add(path)
                 if path in filesToAdd:
                     filesToAdd.remove(path)
+            elif modifier == "C":
+                src, dest = diff['src'], diff['dst']
+                p4_system("integrate -Dt \"%s\" \"%s\"" % (src, dest))
+                if diff['src_sha1'] != diff['dst_sha1']:
+                    p4_system("edit \"%s\"" % (dest))
+                if isModeExecChanged(diff['src_mode'], diff['dst_mode']):
+                    p4_system("edit \"%s\"" % (dest))
+                    filesToChangeExecBit[dest] = diff['dst_mode']
+                os.unlink(dest)
+                editedFiles.add(dest)
             elif modifier == "R":
                 src, dest = diff['src'], diff['dst']
                 p4_system("integrate -Dt \"%s\" \"%s\"" % (src, dest))
-                p4_system("edit \"%s\"" % (dest))
+                if diff['src_sha1'] != diff['dst_sha1']:
+                    p4_system("edit \"%s\"" % (dest))
                 if isModeExecChanged(diff['src_mode'], diff['dst_mode']):
+                    p4_system("edit \"%s\"" % (dest))
                     filesToChangeExecBit[dest] = diff['dst_mode']
                 os.unlink(dest)
                 editedFiles.add(dest)
@@ -834,6 +861,8 @@
         return True
 
 class P4Sync(Command):
+    delete_actions = ( "delete", "move/delete", "purge" )
+
     def __init__(self):
         Command.__init__(self)
         self.options = [
@@ -882,6 +911,23 @@
         if gitConfig("git-p4.syncFromOrigin") == "false":
             self.syncWithOrigin = False
 
+    #
+    # P4 wildcards are not allowed in filenames.  P4 complains
+    # if you simply add them, but you can force it with "-f", in
+    # which case it translates them into %xx encoding internally.
+    # Search for and fix just these four characters.  Do % last so
+    # that fixing it does not inadvertently create new %-escapes.
+    #
+    def wildcard_decode(self, path):
+        # Cannot have * in a filename in windows; untested as to
+        # what p4 would do in such a case.
+        if not self.isWindows:
+            path = path.replace("%2A", "*")
+        path = path.replace("%23", "#") \
+                   .replace("%40", "@") \
+                   .replace("%25", "%")
+        return path
+
     def extractFilesFromCommit(self, commit):
         self.cloneExclude = [re.sub(r"\.\.\.$", "", path)
                              for path in self.cloneExclude]
@@ -976,6 +1022,7 @@
 	    return
 
         relPath = self.stripRepoPath(file['depotFile'], self.branchPrefixes)
+        relPath = self.wildcard_decode(relPath)
         if verbose:
             sys.stderr.write("%s\n" % relPath)
 
@@ -1054,10 +1101,10 @@
 
             if includeFile:
                 filesForCommit.append(f)
-                if f['action'] not in ('delete', 'move/delete', 'purge'):
-                    filesToRead.append(f)
-                else:
+                if f['action'] in self.delete_actions:
                     filesToDelete.append(f)
+                else:
+                    filesToRead.append(f)
 
         # deleted files...
         for f in filesToDelete:
@@ -1143,7 +1190,7 @@
 
                 cleanedFiles = {}
                 for info in files:
-                    if info["action"] in ("delete", "purge"):
+                    if info["action"] in self.delete_actions:
                         continue
                     cleanedFiles[info["depotFile"]] = info["rev"]
 
@@ -1445,7 +1492,7 @@
         print "Doing initial import of %s from revision %s into %s" % (' '.join(self.depotPaths), revision, self.branch)
 
         details = { "user" : "git perforce import user", "time" : int(time.time()) }
-        details["desc"] = ("Initial import of %s from the state at revision %s"
+        details["desc"] = ("Initial import of %s from the state at revision %s\n"
                            % (' '.join(self.depotPaths), revision))
         details["change"] = revision
         newestRevision = 0
@@ -1456,9 +1503,16 @@
                                            % (p, revision)
                                            for p in self.depotPaths])):
 
-            if info['code'] == 'error':
+            if 'code' in info and info['code'] == 'error':
                 sys.stderr.write("p4 returned an error: %s\n"
                                  % info['data'])
+                if info['data'].find("must refer to client") >= 0:
+                    sys.stderr.write("This particular p4 error is misleading.\n")
+                    sys.stderr.write("Perhaps the depot path was misspelled.\n");
+                    sys.stderr.write("Depot path:  %s\n" % " ".join(self.depotPaths))
+                sys.exit(1)
+            if 'p4ExitCode' in info:
+                sys.stderr.write("p4 exitcode: %s\n" % info['p4ExitCode'])
                 sys.exit(1)
 
 
@@ -1466,7 +1520,7 @@
             if change > newestRevision:
                 newestRevision = change
 
-            if info["action"] in ("delete", "purge"):
+            if info["action"] in self.delete_actions:
                 # don't increase the file cnt, otherwise details["depotFile123"] will have gaps!
                 #fileCnt = fileCnt + 1
                 continue
@@ -1709,6 +1763,8 @@
 
                 changes.sort()
             else:
+                if not isinstance(self, P4Clone) and not self.p4BranchesInGit:
+                    die("No remote p4 branches.  Perhaps you never did \"git p4 clone\" in here.");
                 if self.verbose:
                     print "Getting p4 changes for %s...%s" % (', '.join(self.depotPaths),
                                                               self.changeRange)
@@ -1789,10 +1845,13 @@
                                  help="where to leave result of the clone"),
             optparse.make_option("-/", dest="cloneExclude",
                                  action="append", type="string",
-                                 help="exclude depot path")
+                                 help="exclude depot path"),
+            optparse.make_option("--bare", dest="cloneBare",
+                                 action="store_true", default=False),
         ]
         self.cloneDestination = None
         self.needsGit = False
+        self.cloneBare = False
 
     # This is required for the "append" cloneExclude action
     def ensure_value(self, attr, value):
@@ -1832,11 +1891,16 @@
             self.cloneDestination = self.defaultDestination(args)
 
         print "Importing from %s into %s" % (', '.join(depotPaths), self.cloneDestination)
+
         if not os.path.exists(self.cloneDestination):
             os.makedirs(self.cloneDestination)
         chdir(self.cloneDestination)
-        system("git init")
-        self.gitdir = os.getcwd() + "/.git"
+
+        init_cmd = [ "git", "init" ]
+        if self.cloneBare:
+            init_cmd.append("--bare")
+        subprocess.check_call(init_cmd)
+
         if not P4Sync.run(self, depotPaths):
             return False
         if self.branch != "master":
@@ -1846,7 +1910,8 @@
                 masterbranch = "refs/heads/p4/master"
             if gitBranchExists(masterbranch):
                 system("git branch master %s" % masterbranch)
-                system("git checkout -f")
+                if not self.cloneBare:
+                    system("git checkout -f")
             else:
                 print "Could not detect main branch. No checkout/master branch created."
 
diff --git a/contrib/svn-fe/svn-fe.c b/contrib/svn-fe/svn-fe.c
index a2677b0..35db24f 100644
--- a/contrib/svn-fe/svn-fe.c
+++ b/contrib/svn-fe/svn-fe.c
@@ -8,7 +8,8 @@
 
 int main(int argc, char **argv)
 {
-	svndump_init(NULL);
+	if (svndump_init(NULL))
+		return 1;
 	svndump_read((argc > 1) ? argv[1] : NULL);
 	svndump_deinit();
 	svndump_reset();
diff --git a/convert.c b/convert.c
index d5aebed..7eb51b1 100644
--- a/convert.c
+++ b/convert.c
@@ -18,7 +18,7 @@
 	CRLF_TEXT,
 	CRLF_INPUT,
 	CRLF_CRLF,
-	CRLF_AUTO,
+	CRLF_AUTO
 };
 
 struct text_stat {
diff --git a/diff-lib.c b/diff-lib.c
index 392ce2b..1e22992 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -106,7 +106,7 @@
 			DIFF_OPT_TST(&revs->diffopt, HAS_CHANGES))
 			break;
 
-		if (!ce_path_match(ce, revs->prune_data))
+		if (!ce_path_match(ce, &revs->prune_data))
 			continue;
 
 		if (ce_stage(ce)) {
@@ -427,7 +427,7 @@
 	if (tree == o->df_conflict_entry)
 		tree = NULL;
 
-	if (ce_path_match(idx ? idx : tree, revs->prune_data))
+	if (ce_path_match(idx ? idx : tree, &revs->prune_data))
 		do_oneway_diff(o, idx, tree);
 
 	return 0;
@@ -501,7 +501,7 @@
 	active_nr = dst - active_cache;
 
 	init_revisions(&revs, NULL);
-	revs.prune_data = opt->paths;
+	init_pathspec(&revs.prune_data, opt->pathspec.raw);
 	tree = parse_tree_indirect(tree_sha1);
 	if (!tree)
 		die("bad tree object %s", sha1_to_hex(tree_sha1));
diff --git a/diff-no-index.c b/diff-no-index.c
index ce9e783..3a36144 100644
--- a/diff-no-index.c
+++ b/diff-no-index.c
@@ -231,8 +231,9 @@
 
 	if (prefix) {
 		int len = strlen(prefix);
+		const char *paths[3];
+		memset(paths, 0, sizeof(paths));
 
-		revs->diffopt.paths = xcalloc(2, sizeof(char *));
 		for (i = 0; i < 2; i++) {
 			const char *p = argv[argc - 2 + i];
 			/*
@@ -242,12 +243,12 @@
 			p = (strcmp(p, "-")
 			     ? xstrdup(prefix_filename(prefix, len, p))
 			     : p);
-			revs->diffopt.paths[i] = p;
+			paths[i] = p;
 		}
+		diff_tree_setup_paths(paths, &revs->diffopt);
 	}
 	else
-		revs->diffopt.paths = argv + argc - 2;
-	revs->diffopt.nr_paths = 2;
+		diff_tree_setup_paths(argv + argc - 2, &revs->diffopt);
 	revs->diffopt.skip_stat_unmatch = 1;
 	if (!revs->diffopt.output_format)
 		revs->diffopt.output_format = DIFF_FORMAT_PATCH;
@@ -259,8 +260,8 @@
 	if (diff_setup_done(&revs->diffopt) < 0)
 		die("diff_setup_done failed");
 
-	if (queue_diff(&revs->diffopt, revs->diffopt.paths[0],
-		       revs->diffopt.paths[1]))
+	if (queue_diff(&revs->diffopt, revs->diffopt.pathspec.raw[0],
+		       revs->diffopt.pathspec.raw[1]))
 		exit(1);
 	diff_set_mnemonic_prefix(&revs->diffopt, "1/", "2/");
 	diffcore_std(&revs->diffopt);
diff --git a/diff.c b/diff.c
index 5422c43..42a107c 100644
--- a/diff.c
+++ b/diff.c
@@ -23,7 +23,7 @@
 #endif
 
 static int diff_detect_rename_default;
-static int diff_rename_limit_default = 200;
+static int diff_rename_limit_default = 400;
 static int diff_suppress_blank_empty;
 int diff_use_color_default = -1;
 static const char *diff_word_regex_cfg;
@@ -245,6 +245,15 @@
 	return 0;
 }
 
+/* like fill_mmfile, but only for size, so we can avoid retrieving blob */
+static unsigned long diff_filespec_size(struct diff_filespec *one)
+{
+	if (!DIFF_FILE_VALID(one))
+		return 0;
+	diff_populate_filespec(one, 1);
+	return one->size;
+}
+
 static int count_trailing_blank(mmfile_t *mf, unsigned ws_rule)
 {
 	char *ptr = mf->ptr;
@@ -606,16 +615,14 @@
 	buffer->text.ptr[buffer->text.size] = '\0';
 }
 
-struct diff_words_style_elem
-{
+struct diff_words_style_elem {
 	const char *prefix;
 	const char *suffix;
 	const char *color; /* NULL; filled in by the setup code if
 			    * color is enabled */
 };
 
-struct diff_words_style
-{
+struct diff_words_style {
 	enum diff_words_type type;
 	struct diff_words_style_elem new, old, ctx;
 	const char *newline;
@@ -2079,25 +2086,28 @@
 		data->is_unmerged = 1;
 		return;
 	}
-	if (complete_rewrite) {
+
+	if (diff_filespec_is_binary(one) || diff_filespec_is_binary(two)) {
+		data->is_binary = 1;
+		data->added = diff_filespec_size(two);
+		data->deleted = diff_filespec_size(one);
+	}
+
+	else if (complete_rewrite) {
 		diff_populate_filespec(one, 0);
 		diff_populate_filespec(two, 0);
 		data->deleted = count_lines(one->data, one->size);
 		data->added = count_lines(two->data, two->size);
-		goto free_and_return;
 	}
-	if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
-		die("unable to read files to diff");
 
-	if (diff_filespec_is_binary(one) || diff_filespec_is_binary(two)) {
-		data->is_binary = 1;
-		data->added = mf2.size;
-		data->deleted = mf1.size;
-	} else {
+	else {
 		/* Crazy xdl interfaces.. */
 		xpparam_t xpp;
 		xdemitconf_t xecfg;
 
+		if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
+			die("unable to read files to diff");
+
 		memset(&xpp, 0, sizeof(xpp));
 		memset(&xecfg, 0, sizeof(xecfg));
 		xpp.flags = o->xdl_opts;
@@ -2105,7 +2115,6 @@
 			      &xpp, &xecfg);
 	}
 
- free_and_return:
 	diff_free_filespec_data(one);
 	diff_free_filespec_data(two);
 }
diff --git a/diff.h b/diff.h
index 0083d92..007a055 100644
--- a/diff.h
+++ b/diff.h
@@ -110,7 +110,8 @@
 	int pickaxe_opts;
 	int rename_score;
 	int rename_limit;
-	int warn_on_too_large_rename;
+	int needed_rename_limit;
+	int show_rename_progress;
 	int dirstat_percent;
 	int setup;
 	int abbrev;
@@ -133,9 +134,7 @@
 	FILE *file;
 	int close_file;
 
-	int nr_paths;
-	const char **paths;
-	int *pathlens;
+	struct pathspec pathspec;
 	change_fn_t change;
 	add_remove_fn_t add_remove;
 	diff_format_fn_t format_callback;
diff --git a/diffcore-rename.c b/diffcore-rename.c
index df41be5..d40e40a 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -5,6 +5,7 @@
 #include "diff.h"
 #include "diffcore.h"
 #include "hash.h"
+#include "progress.h"
 
 /* Table of rename/copy destinations */
 
@@ -170,7 +171,7 @@
 	 * and the final score computation below would not have a
 	 * divide-by-zero issue.
 	 */
-	if (base_size * (MAX_SCORE-minimum_score) < delta_size * MAX_SCORE)
+	if (max_size * (MAX_SCORE-minimum_score) < delta_size * MAX_SCORE)
 		return 0;
 
 	if (!src->cnt_data && diff_populate_filespec(src, 0))
@@ -247,7 +248,8 @@
 };
 
 static int find_identical_files(struct file_similarity *src,
-				struct file_similarity *dst)
+				struct file_similarity *dst,
+				struct diff_options *options)
 {
 	int renames = 0;
 
@@ -277,6 +279,8 @@
 			}
 			/* Give higher scores to sources that haven't been used already */
 			score = !source->rename_used;
+			if (source->rename_used && options->detect_rename != DIFF_DETECT_COPY)
+				continue;
 			score += basename_same(source, target);
 			if (score > best_score) {
 				best = p;
@@ -306,11 +310,12 @@
 	}
 }
 
-static int find_same_files(void *ptr)
+static int find_same_files(void *ptr, void *data)
 {
 	int ret;
 	struct file_similarity *p = ptr;
 	struct file_similarity *src = NULL, *dst = NULL;
+	struct diff_options *options = data;
 
 	/* Split the hash list up into sources and destinations */
 	do {
@@ -329,7 +334,7 @@
 	 * If we have both sources *and* destinations, see if
 	 * we can match them up
 	 */
-	ret = (src && dst) ? find_identical_files(src, dst) : 0;
+	ret = (src && dst) ? find_identical_files(src, dst, options) : 0;
 
 	/* Free the hashes and return the number of renames found */
 	free_similarity_list(src);
@@ -377,7 +382,7 @@
  * and then during the second round we try to match
  * cache-dirty entries as well.
  */
-static int find_exact_renames(void)
+static int find_exact_renames(struct diff_options *options)
 {
 	int i;
 	struct hash_table file_table;
@@ -390,7 +395,7 @@
 		insert_file_table(&file_table, 1, i, rename_dst[i].two);
 
 	/* Find the renames */
-	i = for_each_hash(&file_table, find_same_files);
+	i = for_each_hash(&file_table, find_same_files, options);
 
 	/* .. and free the hash data structure */
 	free_hash(&file_table);
@@ -414,6 +419,27 @@
 		m[worst] = *o;
 }
 
+static int find_renames(struct diff_score *mx, int dst_cnt, int minimum_score, int copies)
+{
+	int count = 0, i;
+
+	for (i = 0; i < dst_cnt * NUM_CANDIDATE_PER_DST; i++) {
+		struct diff_rename_dst *dst;
+
+		if ((mx[i].dst < 0) ||
+		    (mx[i].score < minimum_score))
+			break; /* there is no more usable pair. */
+		dst = &rename_dst[mx[i].dst];
+		if (dst->pair)
+			continue; /* already done, either exact or fuzzy. */
+		if (!copies && rename_src[mx[i].src].one->rename_used)
+			continue;
+		record_rename_pair(mx[i].dst, mx[i].src, mx[i].score);
+		count++;
+	}
+	return count;
+}
+
 void diffcore_rename(struct diff_options *options)
 {
 	int detect_rename = options->detect_rename;
@@ -424,6 +450,7 @@
 	struct diff_score *mx;
 	int i, j, rename_count;
 	int num_create, num_src, dst_cnt;
+	struct progress *progress = NULL;
 
 	if (!minimum_score)
 		minimum_score = DEFAULT_RENAME_SCORE;
@@ -467,7 +494,7 @@
 	 * We really want to cull the candidates list early
 	 * with cheap tests in order to avoid doing deltas.
 	 */
-	rename_count = find_exact_renames();
+	rename_count = find_exact_renames(options);
 
 	/* Did we only want exact renames? */
 	if (minimum_score == MAX_SCORE)
@@ -493,15 +520,22 @@
 	 * but handles the potential overflow case specially (and we
 	 * assume at least 32-bit integers)
 	 */
+	options->needed_rename_limit = 0;
 	if (rename_limit <= 0 || rename_limit > 32767)
 		rename_limit = 32767;
 	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 (created: %d deleted: %d), skipping inexact rename detection", num_create, num_src);
+		options->needed_rename_limit =
+			num_src > num_create ? num_src : num_create;
 		goto cleanup;
 	}
 
+	if (options->show_rename_progress) {
+		progress = start_progress_delay(
+				"Performing inexact rename detection",
+				rename_dst_nr * rename_src_nr, 50, 1);
+	}
+
 	mx = xcalloc(num_create * NUM_CANDIDATE_PER_DST, sizeof(*mx));
 	for (dst_cnt = i = 0; i < rename_dst_nr; i++) {
 		struct diff_filespec *two = rename_dst[i].two;
@@ -531,38 +565,16 @@
 			diff_free_filespec_blob(two);
 		}
 		dst_cnt++;
+		display_progress(progress, (i+1)*rename_src_nr);
 	}
+	stop_progress(&progress);
 
 	/* cost matrix sorted by most to least similar pair */
 	qsort(mx, dst_cnt * NUM_CANDIDATE_PER_DST, sizeof(*mx), score_compare);
 
-	for (i = 0; i < dst_cnt * NUM_CANDIDATE_PER_DST; i++) {
-		struct diff_rename_dst *dst;
-
-		if ((mx[i].dst < 0) ||
-		    (mx[i].score < minimum_score))
-			break; /* there is no more usable pair. */
-		dst = &rename_dst[mx[i].dst];
-		if (dst->pair)
-			continue; /* already done, either exact or fuzzy. */
-		if (rename_src[mx[i].src].one->rename_used)
-			continue;
-		record_rename_pair(mx[i].dst, mx[i].src, mx[i].score);
-		rename_count++;
-	}
-
-	for (i = 0; i < dst_cnt * NUM_CANDIDATE_PER_DST; i++) {
-		struct diff_rename_dst *dst;
-
-		if ((mx[i].dst < 0) ||
-		    (mx[i].score < minimum_score))
-			break; /* there is no more usable pair. */
-		dst = &rename_dst[mx[i].dst];
-		if (dst->pair)
-			continue; /* already done, either exact or fuzzy. */
-		record_rename_pair(mx[i].dst, mx[i].src, mx[i].score);
-		rename_count++;
-	}
+	rename_count += find_renames(mx, dst_cnt, minimum_score, 0);
+	if (detect_rename == DIFF_DETECT_COPY)
+		rename_count += find_renames(mx, dst_cnt, minimum_score, 1);
 	free(mx);
 
  cleanup:
diff --git a/dir.c b/dir.c
index 570b651..325fb56 100644
--- a/dir.c
+++ b/dir.c
@@ -87,6 +87,21 @@
 	return len;
 }
 
+int within_depth(const char *name, int namelen,
+			int depth, int max_depth)
+{
+	const char *cp = name, *cpe = name + namelen;
+
+	while (cp < cpe) {
+		if (*cp++ != '/')
+			continue;
+		depth++;
+		if (depth > max_depth)
+			return 0;
+	}
+	return 1;
+}
+
 /*
  * Does 'match' match the given name?
  * A match is found if
@@ -184,6 +199,95 @@
 	return retval;
 }
 
+/*
+ * Does 'match' match the given name?
+ * A match is found if
+ *
+ * (1) the 'match' string is leading directory of 'name', or
+ * (2) the 'match' string is a wildcard and matches 'name', or
+ * (3) the 'match' string is exactly the same as 'name'.
+ *
+ * and the return value tells which case it was.
+ *
+ * It returns 0 when there is no match.
+ */
+static int match_pathspec_item(const struct pathspec_item *item, int prefix,
+			       const char *name, int namelen)
+{
+	/* name/namelen has prefix cut off by caller */
+	const char *match = item->match + prefix;
+	int matchlen = item->len - prefix;
+
+	/* If the match was just the prefix, we matched */
+	if (!*match)
+		return MATCHED_RECURSIVELY;
+
+	if (matchlen <= namelen && !strncmp(match, name, matchlen)) {
+		if (matchlen == namelen)
+			return MATCHED_EXACTLY;
+
+		if (match[matchlen-1] == '/' || name[matchlen] == '/')
+			return MATCHED_RECURSIVELY;
+	}
+
+	if (item->has_wildcard && !fnmatch(match, name, 0))
+		return MATCHED_FNMATCH;
+
+	return 0;
+}
+
+/*
+ * Given a name and a list of pathspecs, see if the name matches
+ * any of the pathspecs.  The caller is also interested in seeing
+ * all pathspec matches some names it calls this function with
+ * (otherwise the user could have mistyped the unmatched pathspec),
+ * and a mark is left in seen[] array for pathspec element that
+ * actually matched anything.
+ */
+int match_pathspec_depth(const struct pathspec *ps,
+			 const char *name, int namelen,
+			 int prefix, char *seen)
+{
+	int i, retval = 0;
+
+	if (!ps->nr) {
+		if (!ps->recursive || ps->max_depth == -1)
+			return MATCHED_RECURSIVELY;
+
+		if (within_depth(name, namelen, 0, ps->max_depth))
+			return MATCHED_EXACTLY;
+		else
+			return 0;
+	}
+
+	name += prefix;
+	namelen -= prefix;
+
+	for (i = ps->nr - 1; i >= 0; i--) {
+		int how;
+		if (seen && seen[i] == MATCHED_EXACTLY)
+			continue;
+		how = match_pathspec_item(ps->items+i, prefix, name, namelen);
+		if (ps->recursive && ps->max_depth != -1 &&
+		    how && how != MATCHED_FNMATCH) {
+			int len = ps->items[i].len;
+			if (name[len] == '/')
+				len++;
+			if (within_depth(name+len, namelen-len, 0, ps->max_depth))
+				how = MATCHED_EXACTLY;
+			else
+				how = 0;
+		}
+		if (how) {
+			if (retval < how)
+				retval = how;
+			if (seen && seen[i] < how)
+				seen[i] = how;
+		}
+	}
+	return retval;
+}
+
 static int no_wildcard(const char *string)
 {
 	return string[strcspn(string, "*?[{\\")] == '\0';
@@ -1024,7 +1128,7 @@
 		die_errno("can't find the current directory");
 
 	if (!is_absolute_path(dir))
-		dir = make_absolute_path(dir);
+		dir = real_path(dir);
 
 	while (*dir && *dir == *cwd) {
 		dir++;
@@ -1151,3 +1255,50 @@
 	return 0;
 }
 
+static int pathspec_item_cmp(const void *a_, const void *b_)
+{
+	struct pathspec_item *a, *b;
+
+	a = (struct pathspec_item *)a_;
+	b = (struct pathspec_item *)b_;
+	return strcmp(a->match, b->match);
+}
+
+int init_pathspec(struct pathspec *pathspec, const char **paths)
+{
+	const char **p = paths;
+	int i;
+
+	memset(pathspec, 0, sizeof(*pathspec));
+	if (!p)
+		return 0;
+	while (*p)
+		p++;
+	pathspec->raw = paths;
+	pathspec->nr = p - paths;
+	if (!pathspec->nr)
+		return 0;
+
+	pathspec->items = xmalloc(sizeof(struct pathspec_item)*pathspec->nr);
+	for (i = 0; i < pathspec->nr; i++) {
+		struct pathspec_item *item = pathspec->items+i;
+		const char *path = paths[i];
+
+		item->match = path;
+		item->len = strlen(path);
+		item->has_wildcard = !no_wildcard(path);
+		if (item->has_wildcard)
+			pathspec->has_wildcard = 1;
+	}
+
+	qsort(pathspec->items, pathspec->nr,
+	      sizeof(struct pathspec_item), pathspec_item_cmp);
+
+	return 0;
+}
+
+void free_pathspec(struct pathspec *pathspec)
+{
+	free(pathspec->items);
+	pathspec->items = NULL;
+}
diff --git a/dir.h b/dir.h
index 72a764e..aa511da 100644
--- a/dir.h
+++ b/dir.h
@@ -65,6 +65,10 @@
 #define MATCHED_FNMATCH 2
 #define MATCHED_EXACTLY 3
 extern int match_pathspec(const char **pathspec, const char *name, int namelen, int prefix, char *seen);
+extern int match_pathspec_depth(const struct pathspec *pathspec,
+				const char *name, int namelen,
+				int prefix, char *seen);
+extern int within_depth(const char *name, int namelen, int depth, int max_depth);
 
 extern int fill_directory(struct dir_struct *dir, const char **pathspec);
 extern int read_directory(struct dir_struct *, const char *path, int len, const char **pathspec);
diff --git a/environment.c b/environment.c
index 9564475..cc670b1 100644
--- a/environment.c
+++ b/environment.c
@@ -21,7 +21,6 @@
 int is_bare_repository_cfg = -1; /* unspecified */
 int log_all_ref_updates = -1; /* unspecified */
 int warn_ambiguous_refs = 1;
-int unique_abbrev_extra_length;
 int repository_format_version;
 const char *git_commit_encoding;
 const char *git_log_output_encoding;
@@ -140,7 +139,7 @@
 void set_git_work_tree(const char *new_work_tree)
 {
 	if (git_work_tree_initialized) {
-		new_work_tree = make_absolute_path(new_work_tree);
+		new_work_tree = real_path(new_work_tree);
 		if (strcmp(new_work_tree, work_tree))
 			die("internal error: work tree has already been set\n"
 			    "Current worktree: %s\nNew worktree: %s",
@@ -148,7 +147,7 @@
 		return;
 	}
 	git_work_tree_initialized = 1;
-	work_tree = xstrdup(make_absolute_path(new_work_tree));
+	work_tree = xstrdup(real_path(new_work_tree));
 }
 
 const char *get_git_work_tree(void)
diff --git a/exec_cmd.c b/exec_cmd.c
index 38545e8..171e841 100644
--- a/exec_cmd.c
+++ b/exec_cmd.c
@@ -89,7 +89,7 @@
 		if (is_absolute_path(path))
 			strbuf_addstr(out, path);
 		else
-			strbuf_addstr(out, make_nonrelative_path(path));
+			strbuf_addstr(out, absolute_path(path));
 
 		strbuf_addch(out, PATH_SEP);
 	}
diff --git a/fast-import.c b/fast-import.c
index 3886a1b..d9f9a3f 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -24,10 +24,12 @@
     commit_msg
     ('from' sp committish lf)?
     ('merge' sp committish lf)*
-    file_change*
+    (file_change | ls)*
     lf?;
   commit_msg ::= data;
 
+  ls ::= 'ls' sp '"' quoted(path) '"' lf;
+
   file_change ::= file_clr
     | file_del
     | file_rnm
@@ -132,7 +134,7 @@
   ts    ::= # time since the epoch in seconds, ascii base10 notation;
   tz    ::= # GIT style timezone;
 
-     # note: comments and cat requests may appear anywhere
+     # note: comments, ls and cat requests may appear anywhere
      # in the input, except within a data command.  Any form
      # of the data command always escapes the related input
      # from comment processing.
@@ -141,7 +143,9 @@
      # must be the first character on that line (an lf
      # preceded it).
      #
+
   cat_blob ::= 'cat-blob' sp (hexsha1 | idnum) lf;
+  ls_tree  ::= 'ls' sp (hexsha1 | idnum) sp path_str lf;
 
   comment ::= '#' not_lf* lf;
   not_lf  ::= # Any byte that is not ASCII newline (LF);
@@ -166,8 +170,7 @@
 #define DEPTH_BITS 13
 #define MAX_DEPTH ((1<<DEPTH_BITS)-1)
 
-struct object_entry
-{
+struct object_entry {
 	struct pack_idx_entry idx;
 	struct object_entry *next;
 	uint32_t type : TYPE_BITS,
@@ -175,16 +178,14 @@
 		depth : DEPTH_BITS;
 };
 
-struct object_entry_pool
-{
+struct object_entry_pool {
 	struct object_entry_pool *next_pool;
 	struct object_entry *next_free;
 	struct object_entry *end;
 	struct object_entry entries[FLEX_ARRAY]; /* more */
 };
 
-struct mark_set
-{
+struct mark_set {
 	union {
 		struct object_entry *marked[1024];
 		struct mark_set *sets[1024];
@@ -192,57 +193,49 @@
 	unsigned int shift;
 };
 
-struct last_object
-{
+struct last_object {
 	struct strbuf data;
 	off_t offset;
 	unsigned int depth;
 	unsigned no_swap : 1;
 };
 
-struct mem_pool
-{
+struct mem_pool {
 	struct mem_pool *next_pool;
 	char *next_free;
 	char *end;
 	uintmax_t space[FLEX_ARRAY]; /* more */
 };
 
-struct atom_str
-{
+struct atom_str {
 	struct atom_str *next_atom;
 	unsigned short str_len;
 	char str_dat[FLEX_ARRAY]; /* more */
 };
 
 struct tree_content;
-struct tree_entry
-{
+struct tree_entry {
 	struct tree_content *tree;
 	struct atom_str *name;
-	struct tree_entry_ms
-	{
+	struct tree_entry_ms {
 		uint16_t mode;
 		unsigned char sha1[20];
 	} versions[2];
 };
 
-struct tree_content
-{
+struct tree_content {
 	unsigned int entry_capacity; /* must match avail_tree_content */
 	unsigned int entry_count;
 	unsigned int delta_depth;
 	struct tree_entry *entries[FLEX_ARRAY]; /* more */
 };
 
-struct avail_tree_content
-{
+struct avail_tree_content {
 	unsigned int entry_capacity; /* must match tree_content */
 	struct avail_tree_content *next_avail;
 };
 
-struct branch
-{
+struct branch {
 	struct branch *table_next_branch;
 	struct branch *active_next_branch;
 	const char *name;
@@ -254,16 +247,14 @@
 	unsigned char sha1[20];
 };
 
-struct tag
-{
+struct tag {
 	struct tag *next_tag;
 	const char *name;
 	unsigned int pack_id;
 	unsigned char sha1[20];
 };
 
-struct hash_list
-{
+struct hash_list {
 	struct hash_list *next;
 	unsigned char sha1[20];
 };
@@ -274,8 +265,7 @@
 	WHENSPEC_NOW
 } whenspec_type;
 
-struct recent_command
-{
+struct recent_command {
 	struct recent_command *prev;
 	struct recent_command *next;
 	char *buf;
@@ -374,6 +364,7 @@
 
 static void parse_argv(void);
 static void parse_cat_blob(void);
+static void parse_ls(struct branch *b);
 
 static void write_branch_report(FILE *rpt, struct branch *b)
 {
@@ -872,6 +863,7 @@
 	p = xcalloc(1, sizeof(*p) + strlen(tmpfile) + 2);
 	strcpy(p->pack_name, tmpfile);
 	p->pack_fd = pack_fd;
+	p->do_not_close = 1;
 	pack_file = sha1fd(pack_fd, p->pack_name);
 
 	hdr.hdr_signature = htonl(PACK_SIGNATURE);
@@ -2614,6 +2606,8 @@
 			note_change_n(b, prev_fanout);
 		else if (!strcmp("deleteall", command_buf.buf))
 			file_change_deleteall(b);
+		else if (!prefixcmp(command_buf.buf, "ls "))
+			parse_ls(b);
 		else {
 			unread_command_buf = 1;
 			break;
@@ -2837,6 +2831,153 @@
 	cat_blob(oe, sha1);
 }
 
+static struct object_entry *dereference(struct object_entry *oe,
+					unsigned char sha1[20])
+{
+	unsigned long size;
+	char *buf = NULL;
+	if (!oe) {
+		enum object_type type = sha1_object_info(sha1, NULL);
+		if (type < 0)
+			die("object not found: %s", sha1_to_hex(sha1));
+		/* cache it! */
+		oe = insert_object(sha1);
+		oe->type = type;
+		oe->pack_id = MAX_PACK_ID;
+		oe->idx.offset = 1;
+	}
+	switch (oe->type) {
+	case OBJ_TREE:	/* easy case. */
+		return oe;
+	case OBJ_COMMIT:
+	case OBJ_TAG:
+		break;
+	default:
+		die("Not a treeish: %s", command_buf.buf);
+	}
+
+	if (oe->pack_id != MAX_PACK_ID) {	/* in a pack being written */
+		buf = gfi_unpack_entry(oe, &size);
+	} else {
+		enum object_type unused;
+		buf = read_sha1_file(sha1, &unused, &size);
+	}
+	if (!buf)
+		die("Can't load object %s", sha1_to_hex(sha1));
+
+	/* Peel one layer. */
+	switch (oe->type) {
+	case OBJ_TAG:
+		if (size < 40 + strlen("object ") ||
+		    get_sha1_hex(buf + strlen("object "), sha1))
+			die("Invalid SHA1 in tag: %s", command_buf.buf);
+		break;
+	case OBJ_COMMIT:
+		if (size < 40 + strlen("tree ") ||
+		    get_sha1_hex(buf + strlen("tree "), sha1))
+			die("Invalid SHA1 in commit: %s", command_buf.buf);
+	}
+
+	free(buf);
+	return find_object(sha1);
+}
+
+static struct object_entry *parse_treeish_dataref(const char **p)
+{
+	unsigned char sha1[20];
+	struct object_entry *e;
+
+	if (**p == ':') {	/* <mark> */
+		char *endptr;
+		e = find_mark(strtoumax(*p + 1, &endptr, 10));
+		if (endptr == *p + 1)
+			die("Invalid mark: %s", command_buf.buf);
+		if (!e)
+			die("Unknown mark: %s", command_buf.buf);
+		*p = endptr;
+		hashcpy(sha1, e->idx.sha1);
+	} else {	/* <sha1> */
+		if (get_sha1_hex(*p, sha1))
+			die("Invalid SHA1: %s", command_buf.buf);
+		e = find_object(sha1);
+		*p += 40;
+	}
+
+	while (!e || e->type != OBJ_TREE)
+		e = dereference(e, sha1);
+	return e;
+}
+
+static void print_ls(int mode, const unsigned char *sha1, const char *path)
+{
+	static struct strbuf line = STRBUF_INIT;
+
+	/* See show_tree(). */
+	const char *type =
+		S_ISGITLINK(mode) ? commit_type :
+		S_ISDIR(mode) ? tree_type :
+		blob_type;
+
+	if (!mode) {
+		/* missing SP path LF */
+		strbuf_reset(&line);
+		strbuf_addstr(&line, "missing ");
+		quote_c_style(path, &line, NULL, 0);
+		strbuf_addch(&line, '\n');
+	} else {
+		/* mode SP type SP object_name TAB path LF */
+		strbuf_reset(&line);
+		strbuf_addf(&line, "%06o %s %s\t",
+				mode, type, sha1_to_hex(sha1));
+		quote_c_style(path, &line, NULL, 0);
+		strbuf_addch(&line, '\n');
+	}
+	cat_blob_write(line.buf, line.len);
+}
+
+static void parse_ls(struct branch *b)
+{
+	const char *p;
+	struct tree_entry *root = NULL;
+	struct tree_entry leaf = {0};
+
+	/* ls SP (<treeish> SP)? <path> */
+	p = command_buf.buf + strlen("ls ");
+	if (*p == '"') {
+		if (!b)
+			die("Not in a commit: %s", command_buf.buf);
+		root = &b->branch_tree;
+	} else {
+		struct object_entry *e = parse_treeish_dataref(&p);
+		root = new_tree_entry();
+		hashcpy(root->versions[1].sha1, e->idx.sha1);
+		load_tree(root);
+		if (*p++ != ' ')
+			die("Missing space after tree-ish: %s", command_buf.buf);
+	}
+	if (*p == '"') {
+		static struct strbuf uq = STRBUF_INIT;
+		const char *endp;
+		strbuf_reset(&uq);
+		if (unquote_c_style(&uq, p, &endp))
+			die("Invalid path: %s", command_buf.buf);
+		if (*endp)
+			die("Garbage after path in: %s", command_buf.buf);
+		p = uq.buf;
+	}
+	tree_content_get(root, p, &leaf);
+	/*
+	 * A directory in preparation would have a sha1 of zero
+	 * until it is saved.  Save, for simplicity.
+	 */
+	if (S_ISDIR(leaf.versions[1].mode))
+		store_tree(&leaf);
+
+	print_ls(leaf.versions[1].mode, leaf.versions[1].sha1, p);
+	if (!b || root != &b->branch_tree)
+		release_tree_entry(root);
+}
+
 static void checkpoint(void)
 {
 	checkpoint_requested = 0;
@@ -3001,7 +3142,7 @@
 		relative_marks_paths = 0;
 	} else if (!prefixcmp(feature, "force")) {
 		force_update = 1;
-	} else if (!strcmp(feature, "notes")) {
+	} else if (!strcmp(feature, "notes") || !strcmp(feature, "ls")) {
 		; /* do nothing; we have the feature */
 	} else {
 		return 0;
@@ -3142,6 +3283,8 @@
 	while (read_next_command() != EOF) {
 		if (!strcmp("blob", command_buf.buf))
 			parse_new_blob();
+		else if (!prefixcmp(command_buf.buf, "ls "))
+			parse_ls(NULL);
 		else if (!prefixcmp(command_buf.buf, "commit "))
 			parse_new_commit();
 		else if (!prefixcmp(command_buf.buf, "tag "))
diff --git a/fetch-pack.h b/fetch-pack.h
index fbe85ac..0608eda 100644
--- a/fetch-pack.h
+++ b/fetch-pack.h
@@ -1,8 +1,7 @@
 #ifndef FETCH_PACK_H
 #define FETCH_PACK_H
 
-struct fetch_pack_args
-{
+struct fetch_pack_args {
 	const char *uploadpack;
 	int unpacklimit;
 	int depth;
diff --git a/generate-cmdlist.sh b/generate-cmdlist.sh
index 75c68d9..3ef4861 100755
--- a/generate-cmdlist.sh
+++ b/generate-cmdlist.sh
@@ -1,8 +1,7 @@
 #!/bin/sh
 
 echo "/* Automatically generated by $0 */
-struct cmdname_help
-{
+struct cmdname_help {
     char name[16];
     char help[80];
 };
diff --git a/git-compat-util.h b/git-compat-util.h
index f4cb0a9..49b50ee 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -214,7 +214,10 @@
 #define is_dir_sep(c) ((c) == '/')
 #endif
 
-#ifdef __GNUC__
+#if __HP_cc >= 61000
+#define NORETURN __attribute__((noreturn))
+#define NORETURN_PTR
+#elif defined(__GNUC__)
 #define NORETURN __attribute__((__noreturn__))
 #define NORETURN_PTR __attribute__((__noreturn__))
 #elif defined(_MSC_VER)
diff --git a/git-cvsimport.perl b/git-cvsimport.perl
index 8e683e5..bbf327f 100755
--- a/git-cvsimport.perl
+++ b/git-cvsimport.perl
@@ -366,7 +366,9 @@
 	$self->{'socketo'}->write("valid-requests\n");
 	$self->{'socketo'}->flush();
 
-	chomp(my $rep=$self->readline());
+	my $rep=$self->readline();
+	die "Failed to read from server" unless defined $rep;
+	chomp($rep);
 	if ($rep !~ s/^Valid-requests\s*//) {
 		$rep="<unknown>" unless $rep;
 		die "Expected Valid-requests from server, but got: $rep\n";
diff --git a/git-instaweb.sh b/git-instaweb.sh
index 10fcebb..8bfa8a0 100755
--- a/git-instaweb.sh
+++ b/git-instaweb.sh
@@ -558,12 +558,14 @@
 
 # make it runnable as standalone app,
 # like it would be run via 'plackup' utility
-if (__FILE__ eq \$0) {
+if (caller) {
+	return \$app;
+} else {
 	require Plack::Runner;
 
 	my \$runner = Plack::Runner->new();
 	\$runner->parse_options(qw(--env deployment --port $port),
-			       "$local" ? qw(--host 127.0.0.1) : ());
+				"$local" ? qw(--host 127.0.0.1) : ());
 	\$runner->run(\$app);
 }
 __END__
diff --git a/git-mergetool--lib.sh b/git-mergetool--lib.sh
index 77d4aee..78ce49e 100644
--- a/git-mergetool--lib.sh
+++ b/git-mergetool--lib.sh
@@ -182,7 +182,7 @@
 			fi
 			check_unchanged
 		else
-			"$merge_tool_path" -f -d -c "wincmd l" \
+			"$merge_tool_path" -R -f -d -c "wincmd l" \
 				"$LOCAL" "$REMOTE"
 		fi
 		;;
@@ -193,7 +193,7 @@
 				"$LOCAL" "$MERGED" "$REMOTE"
 			check_unchanged
 		else
-			"$merge_tool_path" -f -d -c "wincmd l" \
+			"$merge_tool_path" -R -f -d -c "wincmd l" \
 				"$LOCAL" "$REMOTE"
 		fi
 		;;
diff --git a/git-mergetool.sh b/git-mergetool.sh
index 2f8dc44..bacbda2 100755
--- a/git-mergetool.sh
+++ b/git-mergetool.sh
@@ -269,7 +269,7 @@
 files_to_merge() {
     if test "$rerere" = true
     then
-	git rerere status
+	git rerere remaining
     else
 	git ls-files -u | sed -e 's/^[^	]*	//' | sort -u
     fi
diff --git a/git-pull.sh b/git-pull.sh
index f6b7b84..63b063a 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -53,6 +53,8 @@
 		verbosity="$verbosity -v" ;;
 	--progress)
 		progress=--progress ;;
+	--no-progress)
+		progress=--no-progress ;;
 	-n|--no-stat|--no-summary)
 		diffstat=--no-stat ;;
 	--stat|--summary)
@@ -293,8 +295,8 @@
 	;;
 *)
 	eval="git-merge $diffstat $no_commit $squash $no_ff $ff_only"
-	eval="$eval  $log_arg $strategy_args $merge_args"
-	eval="$eval \"\$merge_name\" HEAD $merge_head $verbosity"
+	eval="$eval  $log_arg $strategy_args $merge_args $verbosity $progress"
+	eval="$eval \"\$merge_name\" HEAD $merge_head"
 	;;
 esac
 eval "exec $eval"
diff --git a/git-submodule.sh b/git-submodule.sh
index 8b90589..3a13397 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -423,6 +423,7 @@
 		cmd_init "--" "$@" || return
 	fi
 
+	cloned_modules=
 	module_list "$@" |
 	while read mode sha1 stage path
 	do
@@ -442,6 +443,7 @@
 		if ! test -d "$path"/.git -o -f "$path"/.git
 		then
 			module_clone "$path" "$url" "$reference"|| exit
+			cloned_modules="$cloned_modules;$name"
 			subsha1=
 		else
 			subsha1=$(clear_local_git_env; cd "$path" &&
@@ -469,6 +471,13 @@
 				die "Unable to fetch in submodule path '$path'"
 			fi
 
+			# Is this something we just cloned?
+			case ";$cloned_modules;" in
+			*";$name;"*)
+				# then there is no local change to integrate
+				update_module= ;;
+			esac
+
 			case "$update_module" in
 			rebase)
 				command="git rebase"
diff --git a/git.c b/git.c
index 65ed68f..ef598c3 100644
--- a/git.c
+++ b/git.c
@@ -313,7 +313,6 @@
 	const char *cmd = argv[0];
 	static struct cmd_struct commands[] = {
 		{ "add", cmd_add, RUN_SETUP | NEED_WORK_TREE },
-		{ "stage", cmd_add, RUN_SETUP | NEED_WORK_TREE },
 		{ "annotate", cmd_annotate, RUN_SETUP },
 		{ "apply", cmd_apply, RUN_SETUP_GENTLY },
 		{ "archive", cmd_archive },
@@ -322,15 +321,15 @@
 		{ "branch", cmd_branch, RUN_SETUP },
 		{ "bundle", cmd_bundle, RUN_SETUP_GENTLY },
 		{ "cat-file", cmd_cat_file, RUN_SETUP },
+		{ "check-attr", cmd_check_attr, RUN_SETUP },
+		{ "check-ref-format", cmd_check_ref_format },
 		{ "checkout", cmd_checkout, RUN_SETUP | NEED_WORK_TREE },
 		{ "checkout-index", cmd_checkout_index,
 			RUN_SETUP | NEED_WORK_TREE},
-		{ "check-ref-format", cmd_check_ref_format },
-		{ "check-attr", cmd_check_attr, RUN_SETUP },
 		{ "cherry", cmd_cherry, RUN_SETUP },
 		{ "cherry-pick", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE },
-		{ "clone", cmd_clone },
 		{ "clean", cmd_clean, RUN_SETUP | NEED_WORK_TREE },
+		{ "clone", cmd_clone },
 		{ "commit", cmd_commit, RUN_SETUP | NEED_WORK_TREE },
 		{ "commit-tree", cmd_commit_tree, RUN_SETUP },
 		{ "config", cmd_config, RUN_SETUP_GENTLY },
@@ -358,8 +357,8 @@
 		{ "init-db", cmd_init_db },
 		{ "log", cmd_log, RUN_SETUP },
 		{ "ls-files", cmd_ls_files, RUN_SETUP },
-		{ "ls-tree", cmd_ls_tree, RUN_SETUP },
 		{ "ls-remote", cmd_ls_remote, RUN_SETUP_GENTLY },
+		{ "ls-tree", cmd_ls_tree, RUN_SETUP },
 		{ "mailinfo", cmd_mailinfo },
 		{ "mailsplit", cmd_mailsplit },
 		{ "merge", cmd_merge, RUN_SETUP | NEED_WORK_TREE },
@@ -379,6 +378,7 @@
 		{ "notes", cmd_notes, RUN_SETUP },
 		{ "pack-objects", cmd_pack_objects, RUN_SETUP },
 		{ "pack-redundant", cmd_pack_redundant, RUN_SETUP },
+		{ "pack-refs", cmd_pack_refs, RUN_SETUP },
 		{ "patch-id", cmd_patch_id },
 		{ "peek-remote", cmd_ls_remote, RUN_SETUP_GENTLY },
 		{ "pickaxe", cmd_blame, RUN_SETUP },
@@ -401,8 +401,10 @@
 		{ "rm", cmd_rm, RUN_SETUP },
 		{ "send-pack", cmd_send_pack, RUN_SETUP },
 		{ "shortlog", cmd_shortlog, RUN_SETUP_GENTLY | USE_PAGER },
-		{ "show-branch", cmd_show_branch, RUN_SETUP },
 		{ "show", cmd_show, RUN_SETUP },
+		{ "show-branch", cmd_show_branch, RUN_SETUP },
+		{ "show-ref", cmd_show_ref, RUN_SETUP },
+		{ "stage", cmd_add, RUN_SETUP | NEED_WORK_TREE },
 		{ "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
 		{ "stripspace", cmd_stripspace },
 		{ "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
@@ -415,13 +417,11 @@
 		{ "update-server-info", cmd_update_server_info, RUN_SETUP },
 		{ "upload-archive", cmd_upload_archive },
 		{ "var", cmd_var, RUN_SETUP_GENTLY },
+		{ "verify-pack", cmd_verify_pack },
 		{ "verify-tag", cmd_verify_tag, RUN_SETUP },
 		{ "version", cmd_version },
 		{ "whatchanged", cmd_whatchanged, RUN_SETUP },
 		{ "write-tree", cmd_write_tree, RUN_SETUP },
-		{ "verify-pack", cmd_verify_pack },
-		{ "show-ref", cmd_show_ref, RUN_SETUP },
-		{ "pack-refs", cmd_pack_refs, RUN_SETUP },
 	};
 	int i;
 	static const char ext[] = STRIP_EXTENSION;
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 1b9369d..9dccfb0 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -3468,7 +3468,7 @@
 	close $fd;
 	open $fd, quote_command(git_cmd(), "cat-file", "blob", $hash)." | ".
 	          quote_command($highlight_bin).
-	          " --fragment --syntax $syntax |"
+	          " --replace-tabs=8 --fragment --syntax $syntax |"
 		or die_error(500, "Couldn't open file or run syntax highlighter");
 	return $fd;
 }
@@ -4906,7 +4906,6 @@
 		next if !%co;
 		my $commit = $co{'id'};
 		my $ref = format_ref_marker($refs, $commit);
-		my %ad = parse_date($co{'author_epoch'});
 		git_print_header_div('commit',
 		               "<span class=\"age\">$co{'age_string'}</span>" .
 		               esc_html($co{'title'}) . $ref,
@@ -7064,7 +7063,7 @@
 	if (defined($commitlist[0])) {
 		%latest_commit = %{$commitlist[0]};
 		my $latest_epoch = $latest_commit{'committer_epoch'};
-		%latest_date   = parse_date($latest_epoch);
+		%latest_date   = parse_date($latest_epoch, $latest_commit{'comitter_tz'});
 		my $if_modified = $cgi->http('IF_MODIFIED_SINCE');
 		if (defined $if_modified) {
 			my $since;
@@ -7195,7 +7194,7 @@
 		if (($i >= 20) && ((time - $co{'author_epoch'}) > 48*60*60)) {
 			last;
 		}
-		my %cd = parse_date($co{'author_epoch'});
+		my %cd = parse_date($co{'author_epoch'}, $co{'author_tz'});
 
 		# get list of changed files
 		open my $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts,
diff --git a/hash.c b/hash.c
index 1cd4c9d..749ecfe 100644
--- a/hash.c
+++ b/hash.c
@@ -81,7 +81,7 @@
 	return insert_hash_entry(hash, ptr, table);
 }
 
-int for_each_hash(const struct hash_table *table, int (*fn)(void *))
+int for_each_hash(const struct hash_table *table, int (*fn)(void *, void *), void *data)
 {
 	int sum = 0;
 	unsigned int i;
@@ -92,7 +92,7 @@
 		void *ptr = array->ptr;
 		array++;
 		if (ptr) {
-			int val = fn(ptr);
+			int val = fn(ptr, data);
 			if (val < 0)
 				return val;
 			sum += val;
diff --git a/hash.h b/hash.h
index 69e33a4..b875ce6 100644
--- a/hash.h
+++ b/hash.h
@@ -30,7 +30,7 @@
 
 extern void *lookup_hash(unsigned int hash, const struct hash_table *table);
 extern void **insert_hash(unsigned int hash, void *ptr, struct hash_table *table);
-extern int for_each_hash(const struct hash_table *table, int (*fn)(void *));
+extern int for_each_hash(const struct hash_table *table, int (*fn)(void *, void *), void *data);
 extern void free_hash(struct hash_table *table);
 
 static inline void init_hash(struct hash_table *table)
diff --git a/http-push.c b/http-push.c
index ff41a0e..d18346c 100644
--- a/http-push.c
+++ b/http-push.c
@@ -82,8 +82,7 @@
 
 static struct object_list *objects;
 
-struct repo
-{
+struct repo {
 	char *url;
 	char *path;
 	int path_len;
@@ -108,8 +107,7 @@
 	COMPLETE
 };
 
-struct transfer_request
-{
+struct transfer_request {
 	struct object *obj;
 	char *url;
 	char *dest;
@@ -127,8 +125,7 @@
 
 static struct transfer_request *request_queue_head;
 
-struct xml_ctx
-{
+struct xml_ctx {
 	char *name;
 	int len;
 	char *cdata;
@@ -136,8 +133,7 @@
 	void *userData;
 };
 
-struct remote_lock
-{
+struct remote_lock {
 	char *url;
 	char *owner;
 	char *token;
@@ -156,8 +152,7 @@
 /* Flags that remote_ls passes to callback functions */
 #define IS_DIR (1u << 0)
 
-struct remote_ls_ctx
-{
+struct remote_ls_ctx {
 	char *path;
 	void (*userFunc)(struct remote_ls_ctx *ls);
 	void *userData;
diff --git a/http-walker.c b/http-walker.c
index 18bd650..9bc8114 100644
--- a/http-walker.c
+++ b/http-walker.c
@@ -3,8 +3,7 @@
 #include "walker.h"
 #include "http.h"
 
-struct alt_base
-{
+struct alt_base {
 	char *base;
 	int got_indices;
 	struct packed_git *packs;
@@ -18,8 +17,7 @@
 	COMPLETE
 };
 
-struct object_request
-{
+struct object_request {
 	struct walker *walker;
 	unsigned char sha1[20];
 	struct alt_base *repo;
diff --git a/http.h b/http.h
index 5c6e243..e9ed3c2 100644
--- a/http.h
+++ b/http.h
@@ -42,14 +42,12 @@
 #define NO_CURL_IOCTL
 #endif
 
-struct slot_results
-{
+struct slot_results {
 	CURLcode curl_result;
 	long http_code;
 };
 
-struct active_request_slot
-{
+struct active_request_slot {
 	CURL *curl;
 	FILE *local;
 	int in_use;
@@ -62,8 +60,7 @@
 	struct active_request_slot *next;
 };
 
-struct buffer
-{
+struct buffer {
 	struct strbuf buf;
 	size_t posn;
 };
@@ -149,8 +146,7 @@
 extern int http_get_info_packs(const char *base_url,
 	struct packed_git **packs_head);
 
-struct http_pack_request
-{
+struct http_pack_request {
 	char *url;
 	struct packed_git *target;
 	struct packed_git **lst;
@@ -166,8 +162,7 @@
 extern void release_http_pack_request(struct http_pack_request *preq);
 
 /* Helpers for fetching object */
-struct http_object_request
-{
+struct http_object_request {
 	char *url;
 	char tmpfile[PATH_MAX];
 	int localfile;
diff --git a/list-objects.c b/list-objects.c
index 8953548..61f6cc9 100644
--- a/list-objects.c
+++ b/list-objects.c
@@ -61,12 +61,15 @@
 			 struct tree *tree,
 			 show_object_fn show,
 			 struct name_path *path,
+			 struct strbuf *base,
 			 const char *name)
 {
 	struct object *obj = &tree->object;
 	struct tree_desc desc;
 	struct name_entry entry;
 	struct name_path me;
+	int all_interesting = (revs->diffopt.pathspec.nr == 0);
+	int baselen = base->len;
 
 	if (!revs->tree_objects)
 		return;
@@ -82,13 +85,32 @@
 	me.elem = name;
 	me.elem_len = strlen(name);
 
+	if (!all_interesting) {
+		strbuf_addstr(base, name);
+		if (base->len)
+			strbuf_addch(base, '/');
+	}
+
 	init_tree_desc(&desc, tree->buffer, tree->size);
 
 	while (tree_entry(&desc, &entry)) {
+		if (!all_interesting) {
+			int showit = tree_entry_interesting(&entry,
+							    base, 0,
+							    &revs->diffopt.pathspec);
+
+			if (showit < 0)
+				break;
+			else if (!showit)
+				continue;
+			else if (showit == 2)
+				all_interesting = 1;
+		}
+
 		if (S_ISDIR(entry.mode))
 			process_tree(revs,
 				     lookup_tree(entry.sha1),
-				     show, &me, entry.path);
+				     show, &me, base, entry.path);
 		else if (S_ISGITLINK(entry.mode))
 			process_gitlink(revs, entry.sha1,
 					show, &me, entry.path);
@@ -97,6 +119,7 @@
 				     lookup_blob(entry.sha1),
 				     show, &me, entry.path);
 	}
+	strbuf_setlen(base, baselen);
 	free(tree->buffer);
 	tree->buffer = NULL;
 }
@@ -146,7 +169,9 @@
 {
 	int i;
 	struct commit *commit;
+	struct strbuf base;
 
+	strbuf_init(&base, PATH_MAX);
 	while ((commit = get_revision(revs)) != NULL) {
 		add_pending_tree(revs, commit->tree);
 		show_commit(commit, data);
@@ -164,7 +189,7 @@
 		}
 		if (obj->type == OBJ_TREE) {
 			process_tree(revs, (struct tree *)obj, show_object,
-				     NULL, name);
+				     NULL, &base, name);
 			continue;
 		}
 		if (obj->type == OBJ_BLOB) {
@@ -181,4 +206,5 @@
 		revs->pending.alloc = 0;
 		revs->pending.objects = NULL;
 	}
+	strbuf_release(&base);
 }
diff --git a/lockfile.c b/lockfile.c
index b0d74cd..c6fb77b 100644
--- a/lockfile.c
+++ b/lockfile.c
@@ -164,10 +164,10 @@
 		    "If no other git process is currently running, this probably means a\n"
 		    "git process crashed in this repository earlier. Make sure no other git\n"
 		    "process is running and remove the file manually to continue.",
-			    make_nonrelative_path(path), strerror(err));
+			    absolute_path(path), strerror(err));
 	} else
 		strbuf_addf(&buf, "Unable to create '%s.lock': %s",
-			    make_nonrelative_path(path), strerror(err));
+			    absolute_path(path), strerror(err));
 	return strbuf_detach(&buf, NULL);
 }
 
diff --git a/merge-recursive.c b/merge-recursive.c
index 2a4f739..8e82a8b 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -22,6 +22,11 @@
 #include "dir.h"
 #include "submodule.h"
 
+static const char rename_limit_advice[] =
+"inexact rename detection was skipped because there were too many\n"
+"  files. You may want to set your merge.renamelimit variable to at least\n"
+"  %d and retry this merge.";
+
 static struct tree *shift_tree_object(struct tree *one, struct tree *two,
 				      const char *subtree_shift)
 {
@@ -83,10 +88,8 @@
  * Since we want to write the index eventually, we cannot reuse the index
  * for these (temporary) data.
  */
-struct stage_data
-{
-	struct
-	{
+struct stage_data {
+	struct {
 		unsigned mode;
 		unsigned char sha[20];
 	} stages[4];
@@ -390,8 +393,7 @@
 	}
 }
 
-struct rename
-{
+struct rename {
 	struct diff_filepair *pair;
 	struct stage_data *src_entry;
 	struct stage_data *dst_entry;
@@ -421,14 +423,16 @@
 	opts.detect_rename = DIFF_DETECT_RENAME;
 	opts.rename_limit = o->merge_rename_limit >= 0 ? o->merge_rename_limit :
 			    o->diff_rename_limit >= 0 ? o->diff_rename_limit :
-			    500;
+			    1000;
 	opts.rename_score = o->rename_score;
-	opts.warn_on_too_large_rename = 1;
+	opts.show_rename_progress = o->show_rename_progress;
 	opts.output_format = DIFF_FORMAT_NO_OUTPUT;
 	if (diff_setup_done(&opts) < 0)
 		die("diff setup failed");
 	diff_tree_sha1(o_tree->object.sha1, tree->object.sha1, "", &opts);
 	diffcore_std(&opts);
+	if (opts.needed_rename_limit > o->needed_rename_limit)
+		o->needed_rename_limit = opts.needed_rename_limit;
 	for (i = 0; i < diff_queued_diff.nr; ++i) {
 		struct string_list_item *item;
 		struct rename *re;
@@ -704,8 +708,7 @@
 
 /* Low level file merging, update and removal */
 
-struct merge_file_info
-{
+struct merge_file_info {
 	unsigned char sha[20];
 	unsigned mode;
 	unsigned clean:1,
@@ -1653,6 +1656,8 @@
 		commit_list_insert(h2, &(*result)->parents->next);
 	}
 	flush_output(o);
+	if (o->needed_rename_limit)
+		warning(rename_limit_advice, o->needed_rename_limit);
 	return clean;
 }
 
diff --git a/merge-recursive.h b/merge-recursive.h
index 981ed6a..7e1e972 100644
--- a/merge-recursive.h
+++ b/merge-recursive.h
@@ -20,6 +20,8 @@
 	int diff_rename_limit;
 	int merge_rename_limit;
 	int rename_score;
+	int needed_rename_limit;
+	int show_rename_progress;
 	int call_depth;
 	struct strbuf obuf;
 	struct string_list current_file_set;
diff --git a/object.h b/object.h
index 4d1d615..b6618d9 100644
--- a/object.h
+++ b/object.h
@@ -6,11 +6,6 @@
 	struct object_list *next;
 };
 
-struct object_refs {
-	unsigned count;
-	struct object *ref[FLEX_ARRAY]; /* more */
-};
-
 struct object_array {
 	unsigned int nr;
 	unsigned int alloc;
diff --git a/pack-check.c b/pack-check.c
index 9d0cb9a..c3bf21d 100644
--- a/pack-check.c
+++ b/pack-check.c
@@ -2,8 +2,7 @@
 #include "pack.h"
 #include "pack-revindex.h"
 
-struct idx_entry
-{
+struct idx_entry {
 	off_t                offset;
 	const unsigned char *sha1;
 	unsigned int nr;
diff --git a/parse-options.h b/parse-options.h
index 31ec5d2..d1b12fe 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -141,7 +141,7 @@
 	{ OPTION_NUMBER, 0, NULL, (v), NULL, (h), \
 	  PARSE_OPT_NOARG | PARSE_OPT_NONEG, (f) }
 #define OPT_FILENAME(s, l, v, h)    { OPTION_FILENAME, (s), (l), (v), \
-				       "FILE", (h) }
+				       "file", (h) }
 #define OPT_COLOR_FLAG(s, l, v, h) \
 	{ OPTION_CALLBACK, (s), (l), (v), "when", (h), PARSE_OPT_OPTARG, \
 		parse_opt_color_flag_cb, (intptr_t)"always" }
diff --git a/path.c b/path.c
index 8951333..4d73cc9 100644
--- a/path.c
+++ b/path.c
@@ -397,7 +397,7 @@
 	return 0;
 }
 
-const char *make_relative_path(const char *abs, const char *base)
+const char *relative_path(const char *abs, const char *base)
 {
 	static char buf[PATH_MAX + 1];
 	int i = 0, j = 0;
diff --git a/perl/Git.pm b/perl/Git.pm
index 205e48a..a86ab70 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -99,7 +99,7 @@
 
 use Carp qw(carp croak); # but croak is bad - throw instead
 use Error qw(:try);
-use Cwd qw(abs_path);
+use Cwd qw(abs_path cwd);
 use IPC::Open2 qw(open2);
 use Fcntl qw(SEEK_SET SEEK_CUR);
 }
@@ -396,7 +396,16 @@
 
 sub command_bidi_pipe {
 	my ($pid, $in, $out);
+	my ($self) = _maybe_self(@_);
+	local %ENV = %ENV;
+	my $cwd_save = undef;
+	if ($self) {
+		shift;
+		$cwd_save = cwd();
+		_setup_git_cmd_env($self);
+	}
 	$pid = open2($in, $out, 'git', @_);
+	chdir($cwd_save) if $cwd_save;
 	return ($pid, $in, $out, join(' ', @_));
 }
 
@@ -843,7 +852,7 @@
 
 	($self->{hash_object_pid}, $self->{hash_object_in},
 	 $self->{hash_object_out}, $self->{hash_object_ctx}) =
-		command_bidi_pipe(qw(hash-object -w --stdin-paths --no-filters));
+		$self->command_bidi_pipe(qw(hash-object -w --stdin-paths --no-filters));
 }
 
 sub _close_hash_and_insert_object {
@@ -932,7 +941,7 @@
 
 	($self->{cat_blob_pid}, $self->{cat_blob_in},
 	 $self->{cat_blob_out}, $self->{cat_blob_ctx}) =
-		command_bidi_pipe(qw(cat-file --batch));
+		$self->command_bidi_pipe(qw(cat-file --batch));
 }
 
 sub _close_cat_blob {
@@ -1279,6 +1288,14 @@
 # for the given repository and execute the git command.
 sub _cmd_exec {
 	my ($self, @args) = @_;
+	_setup_git_cmd_env($self);
+	_execv_git_cmd(@args);
+	die qq[exec "@args" failed: $!];
+}
+
+# set up the appropriate state for git command
+sub _setup_git_cmd_env {
+	my $self = shift;
 	if ($self) {
 		$self->repo_path() and $ENV{'GIT_DIR'} = $self->repo_path();
 		$self->repo_path() and $self->wc_path()
@@ -1286,8 +1303,6 @@
 		$self->wc_path() and chdir($self->wc_path());
 		$self->wc_subdir() and chdir($self->wc_subdir());
 	}
-	_execv_git_cmd(@args);
-	die qq[exec "@args" failed: $!];
 }
 
 # Execute the given Git command ($_[0]) with arguments ($_[1..])
diff --git a/preload-index.c b/preload-index.c
index e3d0bda..49cb08d 100644
--- a/preload-index.c
+++ b/preload-index.c
@@ -35,7 +35,9 @@
 	struct index_state *index = p->index;
 	struct cache_entry **cep = index->cache + p->offset;
 	struct cache_def cache;
+	struct pathspec pathspec;
 
+	init_pathspec(&pathspec, p->pathspec);
 	memset(&cache, 0, sizeof(cache));
 	nr = p->nr;
 	if (nr + p->offset > index->cache_nr)
@@ -51,7 +53,7 @@
 			continue;
 		if (ce_uptodate(ce))
 			continue;
-		if (!ce_path_match(ce, p->pathspec))
+		if (!ce_path_match(ce, &pathspec))
 			continue;
 		if (threaded_has_symlink_leading_path(&cache, ce->name, ce_namelen(ce)))
 			continue;
@@ -61,6 +63,7 @@
 			continue;
 		ce_mark_uptodate(ce);
 	} while (--nr > 0);
+	free_pathspec(&pathspec);
 	return NULL;
 }
 
diff --git a/pretty.c b/pretty.c
index 8549934..65d20a7 100644
--- a/pretty.c
+++ b/pretty.c
@@ -216,36 +216,53 @@
 static void add_rfc2047(struct strbuf *sb, const char *line, int len,
 		       const char *encoding)
 {
-	int i, last;
+	static const int max_length = 78; /* per rfc2822 */
+	int i;
+	int line_len;
+
+	/* How many bytes are already used on the current line? */
+	for (i = sb->len - 1; i >= 0; i--)
+		if (sb->buf[i] == '\n')
+			break;
+	line_len = sb->len - (i+1);
 
 	for (i = 0; i < len; i++) {
 		int ch = line[i];
-		if (non_ascii(ch))
+		if (non_ascii(ch) || ch == '\n')
 			goto needquote;
 		if ((i + 1 < len) && (ch == '=' && line[i+1] == '?'))
 			goto needquote;
 	}
-	strbuf_add(sb, line, len);
+	strbuf_add_wrapped_bytes(sb, line, len, 0, 1, max_length - line_len);
 	return;
 
 needquote:
 	strbuf_grow(sb, len * 3 + strlen(encoding) + 100);
 	strbuf_addf(sb, "=?%s?q?", encoding);
-	for (i = last = 0; i < len; i++) {
+	line_len += strlen(encoding) + 5; /* 5 for =??q? */
+	for (i = 0; i < len; i++) {
 		unsigned ch = line[i] & 0xFF;
+
+		if (line_len >= max_length - 2) {
+			strbuf_addf(sb, "?=\n =?%s?q?", encoding);
+			line_len = strlen(encoding) + 5 + 1; /* =??q? plus SP */
+		}
+
 		/*
 		 * We encode ' ' using '=20' even though rfc2047
 		 * allows using '_' for readability.  Unfortunately,
 		 * many programs do not understand this and just
 		 * leave the underscore in place.
 		 */
-		if (is_rfc2047_special(ch) || ch == ' ') {
-			strbuf_add(sb, line + last, i - last);
+		if (is_rfc2047_special(ch) || ch == ' ' || ch == '\n') {
 			strbuf_addf(sb, "=%02X", ch);
-			last = i + 1;
+			line_len += 3;
+		}
+		else {
+			strbuf_addch(sb, ch);
+			line_len++;
 		}
 	}
-	strbuf_add(sb, line + last, len - last);
 	strbuf_addstr(sb, "?=");
 }
 
@@ -1106,11 +1123,10 @@
 		   const char *encoding,
 		   int need_8bit_cte)
 {
-	const char *line_separator = (fmt == CMIT_FMT_EMAIL) ? "\n " : " ";
 	struct strbuf title;
 
 	strbuf_init(&title, 80);
-	*msg_p = format_subject(&title, *msg_p, line_separator);
+	*msg_p = format_subject(&title, *msg_p, " ");
 
 	strbuf_grow(sb, title.len + 1024);
 	if (subject) {
diff --git a/read-cache.c b/read-cache.c
index 15b0a73..98d526b 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -92,7 +92,7 @@
 
 	if (fd >= 0) {
 		unsigned char sha1[20];
-		if (!index_fd(sha1, fd, st, 0, OBJ_BLOB, ce->name))
+		if (!index_fd(sha1, fd, st, 0, OBJ_BLOB, ce->name, 0))
 			match = hashcmp(sha1, ce->sha1);
 		/* index_fd() closed the file descriptor already */
 	}
@@ -706,30 +706,9 @@
 	return ce_namelen(b) == len && !memcmp(a->name, b->name, len);
 }
 
-int ce_path_match(const struct cache_entry *ce, const char **pathspec)
+int ce_path_match(const struct cache_entry *ce, const struct pathspec *pathspec)
 {
-	const char *match, *name;
-	int len;
-
-	if (!pathspec)
-		return 1;
-
-	len = ce_namelen(ce);
-	name = ce->name;
-	while ((match = *pathspec++) != NULL) {
-		int matchlen = strlen(match);
-		if (matchlen > len)
-			continue;
-		if (memcmp(name, match, matchlen))
-			continue;
-		if (matchlen && name[matchlen-1] == '/')
-			return 1;
-		if (name[matchlen] == '/' || !name[matchlen])
-			return 1;
-		if (!matchlen)
-			return 1;
-	}
-	return 0;
+	return match_pathspec_depth(pathspec, ce->name, ce_namelen(ce), 0, NULL);
 }
 
 /*
diff --git a/remote-curl.c b/remote-curl.c
index 04d4813..775d614 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -356,14 +356,59 @@
 	return size;
 }
 
+static int run_slot(struct active_request_slot *slot)
+{
+	int err = 0;
+	struct slot_results results;
+
+	slot->results = &results;
+	slot->curl_result = curl_easy_perform(slot->curl);
+	finish_active_slot(slot);
+
+	if (results.curl_result != CURLE_OK) {
+		err |= error("RPC failed; result=%d, HTTP code = %ld",
+			results.curl_result, results.http_code);
+	}
+
+	return err;
+}
+
+static int probe_rpc(struct rpc_state *rpc)
+{
+	struct active_request_slot *slot;
+	struct curl_slist *headers = NULL;
+	struct strbuf buf = STRBUF_INIT;
+	int err;
+
+	slot = get_active_slot();
+
+	headers = curl_slist_append(headers, rpc->hdr_content_type);
+	headers = curl_slist_append(headers, rpc->hdr_accept);
+
+	curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
+	curl_easy_setopt(slot->curl, CURLOPT_POST, 1);
+	curl_easy_setopt(slot->curl, CURLOPT_URL, rpc->service_url);
+	curl_easy_setopt(slot->curl, CURLOPT_ENCODING, "");
+	curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, "0000");
+	curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, 4);
+	curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers);
+	curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
+	curl_easy_setopt(slot->curl, CURLOPT_FILE, &buf);
+
+	err = run_slot(slot);
+
+	curl_slist_free_all(headers);
+	strbuf_release(&buf);
+	return err;
+}
+
 static int post_rpc(struct rpc_state *rpc)
 {
 	struct active_request_slot *slot;
-	struct slot_results results;
 	struct curl_slist *headers = NULL;
 	int use_gzip = rpc->gzip_request;
 	char *gzip_body = NULL;
-	int err = 0, large_request = 0;
+	int err, large_request = 0;
 
 	/* Try to load the entire request, if we can fit it into the
 	 * allocated buffer space we can use HTTP/1.0 and avoid the
@@ -386,8 +431,13 @@
 		rpc->len += n;
 	}
 
+	if (large_request) {
+		err = probe_rpc(rpc);
+		if (err)
+			return err;
+	}
+
 	slot = get_active_slot();
-	slot->results = &results;
 
 	curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
 	curl_easy_setopt(slot->curl, CURLOPT_POST, 1);
@@ -396,12 +446,12 @@
 
 	headers = curl_slist_append(headers, rpc->hdr_content_type);
 	headers = curl_slist_append(headers, rpc->hdr_accept);
+	headers = curl_slist_append(headers, "Expect:");
 
 	if (large_request) {
 		/* The request body is large and the size cannot be predicted.
 		 * We must use chunked encoding to send it.
 		 */
-		headers = curl_slist_append(headers, "Expect: 100-continue");
 		headers = curl_slist_append(headers, "Transfer-Encoding: chunked");
 		rpc->initial_buffer = 1;
 		curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, rpc_out);
@@ -475,13 +525,7 @@
 	curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, rpc_in);
 	curl_easy_setopt(slot->curl, CURLOPT_FILE, rpc);
 
-	slot->curl_result = curl_easy_perform(slot->curl);
-	finish_active_slot(slot);
-
-	if (results.curl_result != CURLE_OK) {
-		err |= error("RPC failed; result=%d, HTTP code = %ld",
-			results.curl_result, results.http_code);
-	}
+	err = run_slot(slot);
 
 	curl_slist_free_all(headers);
 	free(gzip_body);
diff --git a/rerere.c b/rerere.c
index d260843..22996bd 100644
--- a/rerere.c
+++ b/rerere.c
@@ -7,6 +7,11 @@
 #include "ll-merge.h"
 #include "attr.h"
 
+#define RESOLVED 0
+#define PUNTED 1
+#define THREE_STAGED 2
+void *RERERE_RESOLVED = &RERERE_RESOLVED;
+
 /* if rerere_enabled == -1, fall back to detection of .git/rr-cache */
 static int rerere_enabled = -1;
 
@@ -345,21 +350,74 @@
 	return hunk_no;
 }
 
+static int check_one_conflict(int i, int *type)
+{
+	struct cache_entry *e = active_cache[i];
+
+	if (!ce_stage(e)) {
+		*type = RESOLVED;
+		return i + 1;
+	}
+
+	*type = PUNTED;
+	if (ce_stage(e) == 1) {
+		if (active_nr <= ++i)
+			return i + 1;
+	}
+
+	/* Only handle regular files with both stages #2 and #3 */
+	if (i + 1 < active_nr) {
+		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(e, e3) &&
+		    S_ISREG(e2->ce_mode) &&
+		    S_ISREG(e3->ce_mode))
+			*type = THREE_STAGED;
+	}
+
+	/* Skip the entries with the same name */
+	while (i < active_nr && ce_same_name(e, active_cache[i]))
+		i++;
+	return i;
+}
+
 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(conflict, (const char *)e2->name);
-			i++; /* skip over both #2 and #3 */
+
+	for (i = 0; i < active_nr;) {
+		int conflict_type;
+		struct cache_entry *e = active_cache[i];
+		i = check_one_conflict(i, &conflict_type);
+		if (conflict_type == THREE_STAGED)
+			string_list_insert(conflict, (const char *)e->name);
+	}
+	return 0;
+}
+
+int rerere_remaining(struct string_list *merge_rr)
+{
+	int i;
+	if (read_cache() < 0)
+		return error("Could not read index");
+
+	for (i = 0; i < active_nr;) {
+		int conflict_type;
+		struct cache_entry *e = active_cache[i];
+		i = check_one_conflict(i, &conflict_type);
+		if (conflict_type == PUNTED)
+			string_list_insert(merge_rr, (const char *)e->name);
+		else if (conflict_type == RESOLVED) {
+			struct string_list_item *it;
+			it = string_list_lookup(merge_rr, (const char *)e->name);
+			if (it != NULL) {
+				free(it->util);
+				it->util = RERERE_RESOLVED;
+			}
 		}
 	}
 	return 0;
diff --git a/rerere.h b/rerere.h
index eaa9004..595f49f 100644
--- a/rerere.h
+++ b/rerere.h
@@ -6,11 +6,19 @@
 #define RERERE_AUTOUPDATE   01
 #define RERERE_NOAUTOUPDATE 02
 
+/*
+ * Marks paths that have been hand-resolved and added to the
+ * index. Set in the util field of such paths after calling
+ * rerere_remaining.
+ */
+extern void *RERERE_RESOLVED;
+
 extern int setup_rerere(struct string_list *, int);
 extern int rerere(int);
 extern const char *rerere_path(const char *hex, const char *file);
 extern int has_rerere_resolution(const char *hex);
 extern int rerere_forget(const char **);
+extern int rerere_remaining(struct string_list *);
 
 #define OPT_RERERE_AUTOUPDATE(v) OPT_UYN(0, "rerere-autoupdate", (v), \
 	"update the index with reused conflict resolution if possible")
diff --git a/revision.c b/revision.c
index 7b9eaef..86d2470 100644
--- a/revision.c
+++ b/revision.c
@@ -323,7 +323,7 @@
 		 * tagged commit by specifying both --simplify-by-decoration
 		 * and pathspec.
 		 */
-		if (!revs->prune_data)
+		if (!revs->prune_data.nr)
 			return REV_TREE_SAME;
 	}
 
@@ -553,11 +553,7 @@
 
 	left_first = left_count < right_count;
 	init_patch_ids(&ids);
-	if (revs->diffopt.nr_paths) {
-		ids.diffopts.nr_paths = revs->diffopt.nr_paths;
-		ids.diffopts.paths = revs->diffopt.paths;
-		ids.diffopts.pathlens = revs->diffopt.pathlens;
-	}
+	ids.diffopts.pathspec = revs->diffopt.pathspec;
 
 	/* Compute patch-ids for one side */
 	for (p = list; p; p = p->next) {
@@ -973,7 +969,7 @@
 		struct cache_entry *ce = active_cache[i];
 		if (!ce_stage(ce))
 			continue;
-		if (ce_path_match(ce, revs->prune_data)) {
+		if (ce_path_match(ce, &revs->prune_data)) {
 			prune_num++;
 			prune = xrealloc(prune, sizeof(*prune) * prune_num);
 			prune[prune_num-2] = ce->name;
@@ -983,7 +979,8 @@
 		       ce_same_name(ce, active_cache[i+1]))
 			i++;
 	}
-	revs->prune_data = prune;
+	free_pathspec(&revs->prune_data);
+	init_pathspec(&revs->prune_data, prune);
 	revs->limited = 1;
 }
 
@@ -1620,7 +1617,7 @@
 	}
 
 	if (prune_data)
-		revs->prune_data = get_pathspec(revs->prefix, prune_data);
+		init_pathspec(&revs->prune_data, get_pathspec(revs->prefix, prune_data));
 
 	if (revs->def == NULL)
 		revs->def = opt ? opt->def : NULL;
@@ -1651,13 +1648,13 @@
 	if (revs->topo_order)
 		revs->limited = 1;
 
-	if (revs->prune_data) {
-		diff_tree_setup_paths(revs->prune_data, &revs->pruning);
+	if (revs->prune_data.nr) {
+		diff_tree_setup_paths(revs->prune_data.raw, &revs->pruning);
 		/* Can't prune commits with rename following: the paths change.. */
 		if (!DIFF_OPT_TST(&revs->diffopt, FOLLOW_RENAMES))
 			revs->prune = 1;
 		if (!revs->full_diff)
-			diff_tree_setup_paths(revs->prune_data, &revs->diffopt);
+			diff_tree_setup_paths(revs->prune_data.raw, &revs->diffopt);
 	}
 	if (revs->combine_merges)
 		revs->ignore_merges = 0;
diff --git a/revision.h b/revision.h
index 05659c6..82509dd 100644
--- a/revision.h
+++ b/revision.h
@@ -34,7 +34,7 @@
 	/* Basic information */
 	const char *prefix;
 	const char *def;
-	void *prune_data;
+	struct pathspec prune_data;
 	unsigned int early_output;
 
 	/* Traversal flags */
diff --git a/setup.c b/setup.c
index 021d013..03cd84f 100644
--- a/setup.c
+++ b/setup.c
@@ -9,7 +9,7 @@
 	const char *orig = path;
 	char *sanitized;
 	if (is_absolute_path(orig)) {
-		const char *temp = make_absolute_path(path);
+		const char *temp = real_path(path);
 		sanitized = xmalloc(len + strlen(temp) + 1);
 		strcpy(sanitized, temp);
 	} else {
@@ -221,7 +221,7 @@
 	work_tree = get_git_work_tree();
 	git_dir = get_git_dir();
 	if (!is_absolute_path(git_dir))
-		git_dir = make_absolute_path(git_dir);
+		git_dir = real_path(get_git_dir());
 	if (!work_tree || chdir(work_tree))
 		die("This operation must be run in a work tree");
 
@@ -232,7 +232,7 @@
 	if (getenv(GIT_WORK_TREE_ENVIRONMENT))
 		setenv(GIT_WORK_TREE_ENVIRONMENT, ".", 1);
 
-	set_git_dir(make_relative_path(git_dir, work_tree));
+	set_git_dir(relative_path(git_dir, work_tree));
 	initialized = 1;
 }
 
@@ -312,7 +312,7 @@
 
 	if (!is_git_directory(dir))
 		die("Not a git repository: %s", dir);
-	path = make_absolute_path(dir);
+	path = real_path(dir);
 
 	free(buf);
 	return path;
@@ -392,7 +392,7 @@
 
 	if (!prefixcmp(cwd, worktree) &&
 	    cwd[strlen(worktree)] == '/') { /* cwd inside worktree */
-		set_git_dir(make_absolute_path(gitdirenv));
+		set_git_dir(real_path(gitdirenv));
 		if (chdir(worktree))
 			die_errno("Could not chdir to '%s'", worktree);
 		cwd[len++] = '/';
@@ -417,7 +417,7 @@
 	/* --work-tree is set without --git-dir; use discovered one */
 	if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) {
 		if (offset != len && !is_absolute_path(gitdir))
-			gitdir = xstrdup(make_absolute_path(gitdir));
+			gitdir = xstrdup(real_path(gitdir));
 		if (chdir(cwd))
 			die_errno("Could not come back to cwd");
 		return setup_explicit_git_dir(gitdir, cwd, len, nongit_ok);
@@ -425,7 +425,7 @@
 
 	/* #16.2, #17.2, #20.2, #21.2, #24, #25, #28, #29 (see t1510) */
 	if (is_bare_repository_cfg > 0) {
-		set_git_dir(offset == len ? gitdir : make_absolute_path(gitdir));
+		set_git_dir(offset == len ? gitdir : real_path(gitdir));
 		if (chdir(cwd))
 			die_errno("Could not come back to cwd");
 		return NULL;
diff --git a/sha1_file.c b/sha1_file.c
index 27730c3..b4fcca8 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -13,6 +13,7 @@
 #include "commit.h"
 #include "tag.h"
 #include "tree.h"
+#include "tree-walk.h"
 #include "refs.h"
 #include "pack-revindex.h"
 #include "sha1-lookup.h"
@@ -417,6 +418,8 @@
 static unsigned int pack_mmap_calls;
 static unsigned int peak_pack_open_windows;
 static unsigned int pack_open_windows;
+static unsigned int pack_open_fds;
+static unsigned int pack_max_fds;
 static size_t peak_pack_mapped;
 static size_t pack_mapped;
 struct packed_git *packed_git;
@@ -594,8 +597,10 @@
 			lru_l->next = lru_w->next;
 		else {
 			lru_p->windows = lru_w->next;
-			if (!lru_p->windows && lru_p->pack_fd != keep_fd) {
+			if (!lru_p->windows && lru_p->pack_fd != -1
+				&& lru_p->pack_fd != keep_fd) {
 				close(lru_p->pack_fd);
+				pack_open_fds--;
 				lru_p->pack_fd = -1;
 			}
 		}
@@ -680,8 +685,10 @@
 		if (strcmp(pack_name, p->pack_name) == 0) {
 			clear_delta_base_cache();
 			close_pack_windows(p);
-			if (p->pack_fd != -1)
+			if (p->pack_fd != -1) {
 				close(p->pack_fd);
+				pack_open_fds--;
+			}
 			close_pack_index(p);
 			free(p->bad_object_sha1);
 			*pp = p->next;
@@ -707,9 +714,29 @@
 	if (!p->index_data && open_pack_index(p))
 		return error("packfile %s index unavailable", p->pack_name);
 
+	if (!pack_max_fds) {
+		struct rlimit lim;
+		unsigned int max_fds;
+
+		if (getrlimit(RLIMIT_NOFILE, &lim))
+			die_errno("cannot get RLIMIT_NOFILE");
+
+		max_fds = lim.rlim_cur;
+
+		/* Save 3 for stdin/stdout/stderr, 22 for work */
+		if (25 < max_fds)
+			pack_max_fds = max_fds - 25;
+		else
+			pack_max_fds = 1;
+	}
+
+	while (pack_max_fds <= pack_open_fds && unuse_one_window(NULL, -1))
+		; /* nothing */
+
 	p->pack_fd = git_open_noatime(p->pack_name, p);
 	if (p->pack_fd < 0 || fstat(p->pack_fd, &st))
 		return -1;
+	pack_open_fds++;
 
 	/* If we created the struct before we had the pack we lack size. */
 	if (!p->pack_size) {
@@ -761,6 +788,7 @@
 		return 0;
 	if (p->pack_fd != -1) {
 		close(p->pack_fd);
+		pack_open_fds--;
 		p->pack_fd = -1;
 	}
 	return -1;
@@ -786,14 +814,13 @@
 {
 	struct pack_window *win = *w_cursor;
 
-	if (p->pack_fd == -1 && open_packed_git(p))
-		die("packfile %s cannot be accessed", p->pack_name);
-
 	/* Since packfiles end in a hash of their content and it's
 	 * pointless to ask for an offset into the middle of that
 	 * hash, and the in_window function above wouldn't match
 	 * don't allow an offset too close to the end of the file.
 	 */
+	if (!p->pack_size && p->pack_fd == -1 && open_packed_git(p))
+		die("packfile %s cannot be accessed", p->pack_name);
 	if (offset > (p->pack_size - 20))
 		die("offset beyond end of packfile (truncated pack?)");
 
@@ -807,6 +834,10 @@
 		if (!win) {
 			size_t window_align = packed_git_window_size / 2;
 			off_t len;
+
+			if (p->pack_fd == -1 && open_packed_git(p))
+				die("packfile %s cannot be accessed", p->pack_name);
+
 			win = xcalloc(1, sizeof(*win));
 			win->offset = (offset / window_align) * window_align;
 			len = p->pack_size - win->offset;
@@ -824,6 +855,12 @@
 				die("packfile %s cannot be mapped: %s",
 					p->pack_name,
 					strerror(errno));
+			if (!win->offset && win->len == p->pack_size
+				&& !p->do_not_close) {
+				close(p->pack_fd);
+				pack_open_fds--;
+				p->pack_fd = -1;
+			}
 			pack_mmap_calls++;
 			pack_open_windows++;
 			if (pack_mapped > peak_pack_mapped)
@@ -918,6 +955,9 @@
 
 void install_packed_git(struct packed_git *pack)
 {
+	if (pack->pack_fd != -1)
+		pack_open_fds++;
+
 	pack->next = packed_git;
 	packed_git = pack;
 }
@@ -935,8 +975,6 @@
 	sprintf(path, "%s/pack", objdir);
 	len = strlen(path);
 	dir = opendir(path);
-	while (!dir && errno == EMFILE && unuse_one_window(NULL, -1))
-		dir = opendir(path);
 	if (!dir) {
 		if (errno != ENOENT)
 			error("unable to open object pack directory: %s: %s",
@@ -1092,14 +1130,6 @@
 		if (fd >= 0)
 			return fd;
 
-		/* Might the failure be insufficient file descriptors? */
-		if (errno == EMFILE) {
-			if (unuse_one_window(p, -1))
-				continue;
-			else
-				return -1;
-		}
-
 		/* Might the failure be due to O_NOATIME? */
 		if (errno != ENOENT && sha1_file_open_flag) {
 			sha1_file_open_flag = 0;
@@ -1931,6 +1961,27 @@
 	return 0;
 }
 
+static int is_pack_valid(struct packed_git *p)
+{
+	/* An already open pack is known to be valid. */
+	if (p->pack_fd != -1)
+		return 1;
+
+	/* If the pack has one window completely covering the
+	 * file size, the pack is known to be valid even if
+	 * the descriptor is not currently open.
+	 */
+	if (p->windows) {
+		struct pack_window *w = p->windows;
+
+		if (!w->offset && w->len == p->pack_size)
+			return 1;
+	}
+
+	/* Force the pack to open to prove its valid. */
+	return !open_packed_git(p);
+}
+
 static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
 {
 	static struct packed_git *last_found = (void *)1;
@@ -1960,7 +2011,7 @@
 			 * it may have been deleted since the index
 			 * was loaded!
 			 */
-			if (p->pack_fd == -1 && open_packed_git(p)) {
+			if (!is_pack_valid(p)) {
 				error("packfile %s cannot be accessed", p->pack_name);
 				goto next;
 			}
@@ -2359,8 +2410,6 @@
 
 	filename = sha1_file_name(sha1);
 	fd = create_tmpfile(tmpfile, sizeof(tmpfile), filename);
-	while (fd < 0 && errno == EMFILE && unuse_one_window(NULL, -1))
-		fd = create_tmpfile(tmpfile, sizeof(tmpfile), filename);
 	if (fd < 0) {
 		if (errno == EACCES)
 			return error("insufficient permission for adding an object to repository database %s\n", get_object_directory());
@@ -2479,8 +2528,37 @@
 	return has_loose_object(sha1);
 }
 
+static void check_tree(const void *buf, size_t size)
+{
+	struct tree_desc desc;
+	struct name_entry entry;
+
+	init_tree_desc(&desc, buf, size);
+	while (tree_entry(&desc, &entry))
+		/* do nothing
+		 * tree_entry() will die() on malformed entries */
+		;
+}
+
+static void check_commit(const void *buf, size_t size)
+{
+	struct commit c;
+	memset(&c, 0, sizeof(c));
+	if (parse_commit_buffer(&c, buf, size))
+		die("corrupt commit");
+}
+
+static void check_tag(const void *buf, size_t size)
+{
+	struct tag t;
+	memset(&t, 0, sizeof(t));
+	if (parse_tag_buffer(&t, buf, size))
+		die("corrupt tag");
+}
+
 static int index_mem(unsigned char *sha1, void *buf, size_t size,
-		     int write_object, enum object_type type, const char *path)
+		     int write_object, enum object_type type,
+		     const char *path, int format_check)
 {
 	int ret, re_allocated = 0;
 
@@ -2498,6 +2576,14 @@
 			re_allocated = 1;
 		}
 	}
+	if (format_check) {
+		if (type == OBJ_TREE)
+			check_tree(buf, size);
+		if (type == OBJ_COMMIT)
+			check_commit(buf, size);
+		if (type == OBJ_TAG)
+			check_tag(buf, size);
+	}
 
 	if (write_object)
 		ret = write_sha1_file(buf, size, typename(type), sha1);
@@ -2511,7 +2597,7 @@
 #define SMALL_FILE_SIZE (32*1024)
 
 int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object,
-	     enum object_type type, const char *path)
+	     enum object_type type, const char *path, int format_check)
 {
 	int ret;
 	size_t size = xsize_t(st->st_size);
@@ -2520,23 +2606,25 @@
 		struct strbuf sbuf = STRBUF_INIT;
 		if (strbuf_read(&sbuf, fd, 4096) >= 0)
 			ret = index_mem(sha1, sbuf.buf, sbuf.len, write_object,
-					type, path);
+					type, path, format_check);
 		else
 			ret = -1;
 		strbuf_release(&sbuf);
 	} else if (!size) {
-		ret = index_mem(sha1, NULL, size, write_object, type, path);
+		ret = index_mem(sha1, NULL, size, write_object, type, path,
+				format_check);
 	} else if (size <= SMALL_FILE_SIZE) {
 		char *buf = xmalloc(size);
 		if (size == read_in_full(fd, buf, size))
 			ret = index_mem(sha1, buf, size, write_object, type,
-					path);
+					path, format_check);
 		else
 			ret = error("short read %s", strerror(errno));
 		free(buf);
 	} else {
 		void *buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
-		ret = index_mem(sha1, buf, size, write_object, type, path);
+		ret = index_mem(sha1, buf, size, write_object, type, path,
+				format_check);
 		munmap(buf, size);
 	}
 	close(fd);
@@ -2554,7 +2642,7 @@
 		if (fd < 0)
 			return error("open(\"%s\"): %s", path,
 				     strerror(errno));
-		if (index_fd(sha1, fd, st, write_object, OBJ_BLOB, path) < 0)
+		if (index_fd(sha1, fd, st, write_object, OBJ_BLOB, path, 0) < 0)
 			return error("%s: failed to insert into database",
 				     path);
 		break;
diff --git a/sha1_name.c b/sha1_name.c
index 709ff2e..faea58d 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -208,9 +208,7 @@
 		if (exists
 		    ? !status
 		    : status == SHORT_NAME_NOT_FOUND) {
-			int cut_at = len + unique_abbrev_extra_length;
-			cut_at = (cut_at < 40) ? cut_at : 40;
-			hex[cut_at] = 0;
+			hex[len] = 0;
 			return hex;
 		}
 		len++;
diff --git a/string-list.h b/string-list.h
index 4946938..bda6983 100644
--- a/string-list.h
+++ b/string-list.h
@@ -5,8 +5,7 @@
 	char *string;
 	void *util;
 };
-struct string_list
-{
+struct string_list {
 	struct string_list_item *items;
 	unsigned int nr, alloc;
 	unsigned int strdup_strings:1;
diff --git a/submodule.c b/submodule.c
index 6f1c107..e9f2b19 100644
--- a/submodule.c
+++ b/submodule.c
@@ -152,17 +152,69 @@
 		die("bad --ignore-submodules argument: %s", arg);
 }
 
+static int prepare_submodule_summary(struct rev_info *rev, const char *path,
+		struct commit *left, struct commit *right,
+		int *fast_forward, int *fast_backward)
+{
+	struct commit_list *merge_bases, *list;
+
+	init_revisions(rev, NULL);
+	setup_revisions(0, NULL, rev, NULL);
+	rev->left_right = 1;
+	rev->first_parent_only = 1;
+	left->object.flags |= SYMMETRIC_LEFT;
+	add_pending_object(rev, &left->object, path);
+	add_pending_object(rev, &right->object, path);
+	merge_bases = get_merge_bases(left, right, 1);
+	if (merge_bases) {
+		if (merge_bases->item == left)
+			*fast_forward = 1;
+		else if (merge_bases->item == right)
+			*fast_backward = 1;
+	}
+	for (list = merge_bases; list; list = list->next) {
+		list->item->object.flags |= UNINTERESTING;
+		add_pending_object(rev, &list->item->object,
+			sha1_to_hex(list->item->object.sha1));
+	}
+	return prepare_revision_walk(rev);
+}
+
+static void print_submodule_summary(struct rev_info *rev, FILE *f,
+		const char *del, const char *add, const char *reset)
+{
+	static const char format[] = "  %m %s";
+	struct strbuf sb = STRBUF_INIT;
+	struct commit *commit;
+
+	while ((commit = get_revision(rev))) {
+		struct pretty_print_context ctx = {0};
+		ctx.date_mode = rev->date_mode;
+		strbuf_setlen(&sb, 0);
+		if (commit->object.flags & SYMMETRIC_LEFT) {
+			if (del)
+				strbuf_addstr(&sb, del);
+		}
+		else if (add)
+			strbuf_addstr(&sb, add);
+		format_commit_message(commit, format, &sb, &ctx);
+		if (reset)
+			strbuf_addstr(&sb, reset);
+		strbuf_addch(&sb, '\n');
+		fprintf(f, "%s", sb.buf);
+	}
+	strbuf_release(&sb);
+}
+
 void show_submodule_summary(FILE *f, const char *path,
 		unsigned char one[20], unsigned char two[20],
 		unsigned dirty_submodule,
 		const char *del, const char *add, const char *reset)
 {
 	struct rev_info rev;
-	struct commit *commit, *left = left, *right = right;
-	struct commit_list *merge_bases, *list;
+	struct commit *left = left, *right = right;
 	const char *message = NULL;
 	struct strbuf sb = STRBUF_INIT;
-	static const char *format = "  %m %s";
 	int fast_forward = 0, fast_backward = 0;
 
 	if (is_null_sha1(two))
@@ -175,29 +227,10 @@
 		 !(right = lookup_commit_reference(two)))
 		message = "(commits not present)";
 
-	if (!message) {
-		init_revisions(&rev, NULL);
-		setup_revisions(0, NULL, &rev, NULL);
-		rev.left_right = 1;
-		rev.first_parent_only = 1;
-		left->object.flags |= SYMMETRIC_LEFT;
-		add_pending_object(&rev, &left->object, path);
-		add_pending_object(&rev, &right->object, path);
-		merge_bases = get_merge_bases(left, right, 1);
-		if (merge_bases) {
-			if (merge_bases->item == left)
-				fast_forward = 1;
-			else if (merge_bases->item == right)
-				fast_backward = 1;
-		}
-		for (list = merge_bases; list; list = list->next) {
-			list->item->object.flags |= UNINTERESTING;
-			add_pending_object(&rev, &list->item->object,
-				sha1_to_hex(list->item->object.sha1));
-		}
-		if (prepare_revision_walk(&rev))
-			message = "(revision walker failed)";
-	}
+	if (!message &&
+	    prepare_submodule_summary(&rev, path, left, right,
+					&fast_forward, &fast_backward))
+		message = "(revision walker failed)";
 
 	if (dirty_submodule & DIRTY_SUBMODULE_UNTRACKED)
 		fprintf(f, "Submodule %s contains untracked content\n", path);
@@ -221,25 +254,11 @@
 	fwrite(sb.buf, sb.len, 1, f);
 
 	if (!message) {
-		while ((commit = get_revision(&rev))) {
-			struct pretty_print_context ctx = {0};
-			ctx.date_mode = rev.date_mode;
-			strbuf_setlen(&sb, 0);
-			if (commit->object.flags & SYMMETRIC_LEFT) {
-				if (del)
-					strbuf_addstr(&sb, del);
-			}
-			else if (add)
-				strbuf_addstr(&sb, add);
-			format_commit_message(commit, format, &sb, &ctx);
-			if (reset)
-				strbuf_addstr(&sb, reset);
-			strbuf_addch(&sb, '\n');
-			fprintf(f, "%s", sb.buf);
-		}
+		print_submodule_summary(&rev, f, del, add, reset);
 		clear_commit_marks(left, ~0);
 		clear_commit_marks(right, ~0);
 	}
+
 	strbuf_release(&sb);
 }
 
diff --git a/symlinks.c b/symlinks.c
index 3cacebd..034943b 100644
--- a/symlinks.c
+++ b/symlinks.c
@@ -223,7 +223,7 @@
 	int flags;
 	int match_len = lstat_cache_matchlen(cache, name, len, &flags,
 			   FL_SYMLINK|FL_NOENT|FL_DIR, USE_ONLY_LSTAT);
-	if (flags & (FL_SYMLINK|FL_NOENT))
+	if (flags & FL_NOENT)
 		return 0;
 	else if (flags & FL_DIR)
 		return -1;
diff --git a/t/README b/t/README
index 25f7d2d..165e7cf 100644
--- a/t/README
+++ b/t/README
@@ -79,6 +79,10 @@
 --debug::
 	This may help the person who is developing a new test.
 	It causes the command defined with test_debug to run.
+	The "trash" directory (used to store all temporary data
+	during testing) is not deleted even if there are no
+	failed tests so that you can inspect its contents after
+	the test finished.
 
 --immediate::
 	This causes the test to immediately exit upon the first
@@ -328,7 +332,7 @@
 Skipping tests
 --------------
 
-If you need to skip tests you should do so be using the three-arg form
+If you need to skip tests you should do so by using the three-arg form
 of the test_* functions (see the "Test harness library" section
 below), e.g.:
 
diff --git a/t/lib-terminal.sh b/t/lib-terminal.sh
index c383b57..58d911d 100644
--- a/t/lib-terminal.sh
+++ b/t/lib-terminal.sh
@@ -1,8 +1,24 @@
 #!/bin/sh
 
-test_expect_success 'set up terminal for tests' '
-	if
-		test_have_prereq PERL &&
+test_expect_success PERL 'set up terminal for tests' '
+	# Reading from the pty master seems to get stuck _sometimes_
+	# on Mac OS X 10.5.0, using Perl 5.10.0 or 5.8.9.
+	#
+	# Reproduction recipe: run
+	#
+	#	i=0
+	#	while ./test-terminal.perl echo hi $i
+	#	do
+	#		: $((i = $i + 1))
+	#	done
+	#
+	# After 2000 iterations or so it hangs.
+	# https://rt.cpan.org/Ticket/Display.html?id=65692
+	#
+	if test "$(uname -s)" = Darwin
+	then
+		:
+	elif
 		"$PERL_PATH" "$TEST_DIRECTORY"/test-terminal.perl \
 			sh -c "test -t 1 && test -t 2"
 	then
diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh
index 8deec75..f4e8f43 100755
--- a/t/t0000-basic.sh
+++ b/t/t0000-basic.sh
@@ -435,7 +435,7 @@
 	test $numpath0 = 1
 '
 
-test_expect_success SYMLINKS 'absolute path works as expected' '
+test_expect_success SYMLINKS 'real path works as expected' '
 	mkdir first &&
 	ln -s ../.git first/.git &&
 	mkdir second &&
@@ -443,14 +443,14 @@
 	mkdir third &&
 	dir="$(cd .git; pwd -P)" &&
 	dir2=third/../second/other/.git &&
-	test "$dir" = "$(test-path-utils make_absolute_path $dir2)" &&
+	test "$dir" = "$(test-path-utils real_path $dir2)" &&
 	file="$dir"/index &&
-	test "$file" = "$(test-path-utils make_absolute_path $dir2/index)" &&
+	test "$file" = "$(test-path-utils real_path $dir2/index)" &&
 	basename=blub &&
-	test "$dir/$basename" = "$(cd .git && test-path-utils make_absolute_path "$basename")" &&
+	test "$dir/$basename" = "$(cd .git && test-path-utils real_path "$basename")" &&
 	ln -s ../first/file .git/syml &&
 	sym="$(cd first; pwd -P)"/file &&
-	test "$sym" = "$(test-path-utils make_absolute_path "$dir2/syml")"
+	test "$sym" = "$(test-path-utils real_path "$dir2/syml")"
 '
 
 test_expect_success 'very long name in the index handled sanely' '
diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh
index 2092450..ae26614 100755
--- a/t/t0040-parse-options.sh
+++ b/t/t0040-parse-options.sh
@@ -19,7 +19,7 @@
     --set23               set integer to 23
     -t <time>             get timestamp of <time>
     -L, --length <str>    get length of <str>
-    -F, --file <FILE>     set file to <FILE>
+    -F, --file <file>     set file to <file>
 
 String options
     -s, --string <string>
diff --git a/t/t0080-vcs-svn.sh b/t/t0080-vcs-svn.sh
index d3225ad..99a314b 100755
--- a/t/t0080-vcs-svn.sh
+++ b/t/t0080-vcs-svn.sh
@@ -76,60 +76,6 @@
 	test_cmp expected actual
 '
 
-test_expect_success 'line buffer' '
-	echo HELLO >expected1 &&
-	printf "%s\n" "" HELLO >expected2 &&
-	echo >expected3 &&
-	printf "%s\n" "" Q | q_to_nul >expected4 &&
-	printf "%s\n" foo "" >expected5 &&
-	printf "%s\n" "" foo >expected6 &&
-
-	test-line-buffer <<-\EOF >actual1 &&
-	5
-	HELLO
-	EOF
-
-	test-line-buffer <<-\EOF >actual2 &&
-	0
-
-	5
-	HELLO
-	EOF
-
-	q_to_nul <<-\EOF |
-	1
-	Q
-	EOF
-	test-line-buffer >actual3 &&
-
-	q_to_nul <<-\EOF |
-	0
-
-	1
-	Q
-	EOF
-	test-line-buffer >actual4 &&
-
-	test-line-buffer <<-\EOF >actual5 &&
-	5
-	foo
-	EOF
-
-	test-line-buffer <<-\EOF >actual6 &&
-	0
-
-	5
-	foo
-	EOF
-
-	test_cmp expected1 actual1 &&
-	test_cmp expected2 actual2 &&
-	test_cmp expected3 actual3 &&
-	test_cmp expected4 actual4 &&
-	test_cmp expected5 actual5 &&
-	test_cmp expected6 actual6
-'
-
 test_expect_success 'string pool' '
 	echo a does not equal b >expected.differ &&
 	echo a equals a >expected.match &&
diff --git a/t/t0081-line-buffer.sh b/t/t0081-line-buffer.sh
new file mode 100755
index 0000000..550fad0
--- /dev/null
+++ b/t/t0081-line-buffer.sh
@@ -0,0 +1,201 @@
+#!/bin/sh
+
+test_description="Test the svn importer's input handling routines.
+
+These tests exercise the line_buffer library, but their real purpose
+is to check the assumptions that library makes of the platform's input
+routines.  Processes engaged in bi-directional communication would
+hang if fread or fgets is too greedy.
+
+While at it, check that input of newlines and null bytes are handled
+correctly.
+"
+. ./test-lib.sh
+
+test -n "$GIT_REMOTE_SVN_TEST_BIG_FILES" && test_set_prereq EXPENSIVE
+
+generate_tens_of_lines () {
+	tens=$1 &&
+	line=$2 &&
+
+	i=0 &&
+	while test $i -lt "$tens"
+	do
+		for j in a b c d e f g h i j
+		do
+			echo "$line"
+		done &&
+		: $((i = $i + 1)) ||
+		return
+	done
+}
+
+long_read_test () {
+	: each line is 10 bytes, including newline &&
+	line=abcdefghi &&
+	echo "$line" >expect &&
+
+	if ! test_declared_prereq PIPE
+	then
+		echo >&4 "long_read_test: need to declare PIPE prerequisite"
+		return 127
+	fi &&
+	tens_of_lines=$(($1 / 100 + 1)) &&
+	lines=$(($tens_of_lines * 10)) &&
+	readsize=$((($lines - 1) * 10 + 3)) &&
+	copysize=7 &&
+	rm -f input &&
+	mkfifo input &&
+	{
+		{
+			generate_tens_of_lines $tens_of_lines "$line" &&
+			sleep 100
+		} >input &
+	} &&
+	test-line-buffer input <<-EOF >output &&
+	read $readsize
+	copy $copysize
+	EOF
+	kill $! &&
+	test_line_count = $lines output &&
+	tail -n 1 <output >actual &&
+	test_cmp expect actual
+}
+
+test_expect_success 'setup: have pipes?' '
+      rm -f frob &&
+      if mkfifo frob
+      then
+		test_set_prereq PIPE
+      fi
+'
+
+test_expect_success 'hello world' '
+	echo HELLO >expect &&
+	test-line-buffer <<-\EOF >actual &&
+	read 6
+	HELLO
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success PIPE '0-length read, no input available' '
+	>expect &&
+	rm -f input &&
+	mkfifo input &&
+	{
+		sleep 100 >input &
+	} &&
+	test-line-buffer input <<-\EOF >actual &&
+	read 0
+	copy 0
+	EOF
+	kill $! &&
+	test_cmp expect actual
+'
+
+test_expect_success '0-length read, send along greeting' '
+	echo HELLO >expect &&
+	test-line-buffer <<-\EOF >actual &&
+	read 0
+	copy 6
+	HELLO
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success PIPE '1-byte read, no input available' '
+	printf "%s" ab >expect &&
+	rm -f input &&
+	mkfifo input &&
+	{
+		{
+			printf "%s" a &&
+			printf "%s" b &&
+			sleep 100
+		} >input &
+	} &&
+	test-line-buffer input <<-\EOF >actual &&
+	read 1
+	copy 1
+	EOF
+	kill $! &&
+	test_cmp expect actual
+'
+
+test_expect_success PIPE 'long read (around 8192 bytes)' '
+	long_read_test 8192
+'
+
+test_expect_success PIPE,EXPENSIVE 'longer read (around 65536 bytes)' '
+	long_read_test 65536
+'
+
+test_expect_success 'read from file descriptor' '
+	rm -f input &&
+	echo hello >expect &&
+	echo hello >input &&
+	echo copy 6 |
+	test-line-buffer "&4" 4<input >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'buffer_read_string copes with null byte' '
+	>expect &&
+	q_to_nul <<-\EOF | test-line-buffer >actual &&
+	read 2
+	Q
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'skip, copy null byte' '
+	echo Q | q_to_nul >expect &&
+	q_to_nul <<-\EOF | test-line-buffer >actual &&
+	skip 2
+	Q
+	copy 2
+	Q
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'read null byte' '
+	echo ">QhelloQ" | q_to_nul >expect &&
+	q_to_nul <<-\EOF | test-line-buffer >actual &&
+	binary 8
+	QhelloQ
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'long reads are truncated' '
+	echo foo >expect &&
+	test-line-buffer <<-\EOF >actual &&
+	read 5
+	foo
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'long copies are truncated' '
+	printf "%s\n" "" foo >expect &&
+	test-line-buffer <<-\EOF >actual &&
+	read 1
+
+	copy 5
+	foo
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'long binary reads are truncated' '
+	echo ">foo" >expect &&
+	test-line-buffer <<-\EOF >actual &&
+	binary 5
+	foo
+	EOF
+	test_cmp expect actual
+'
+
+test_done
diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh
index dd32432..6d52b82 100755
--- a/t/t1007-hash-object.sh
+++ b/t/t1007-hash-object.sh
@@ -188,4 +188,17 @@
 	pop_repo
 done
 
+test_expect_success 'corrupt tree' '
+	echo abc >malformed-tree
+	test_must_fail git hash-object -t tree malformed-tree
+'
+
+test_expect_success 'corrupt commit' '
+	test_must_fail git hash-object -t commit --stdin </dev/null
+'
+
+test_expect_success 'corrupt tag' '
+	test_must_fail git hash-object -t tag --stdin </dev/null
+'
+
 test_done
diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index d0e5546..53fb822 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -876,11 +876,25 @@
 	"
 
 test_expect_success 'git -c "key=value" support' '
-	test "z$(git -c name=value config name)" = zvalue &&
 	test "z$(git -c core.name=value config core.name)" = zvalue &&
-	test "z$(git -c CamelCase=value config camelcase)" = zvalue &&
-	test "z$(git -c flag config --bool flag)" = ztrue &&
-	test_must_fail git -c core.name=value config name
+	test "z$(git -c foo.CamelCase=value config foo.camelcase)" = zvalue &&
+	test "z$(git -c foo.flag config --bool foo.flag)" = ztrue &&
+	test_must_fail git -c name=value config core.name
+'
+
+test_expect_success 'key sanity-checking' '
+	test_must_fail git config foo=bar &&
+	test_must_fail git config foo=.bar &&
+	test_must_fail git config foo.ba=r &&
+	test_must_fail git config foo.1bar &&
+	test_must_fail git config foo."ba
+				z".bar &&
+	test_must_fail git config . false &&
+	test_must_fail git config .foo false &&
+	test_must_fail git config foo. false &&
+	test_must_fail git config .foo. false &&
+	git config foo.bar true &&
+	git config foo."ba =z".bar false
 '
 
 test_done
diff --git a/t/t2019-checkout-ambiguous-ref.sh b/t/t2019-checkout-ambiguous-ref.sh
new file mode 100755
index 0000000..943541d
--- /dev/null
+++ b/t/t2019-checkout-ambiguous-ref.sh
@@ -0,0 +1,59 @@
+#!/bin/sh
+
+test_description='checkout handling of ambiguous (branch/tag) refs'
+. ./test-lib.sh
+
+test_expect_success 'setup ambiguous refs' '
+	test_commit branch file &&
+	git branch ambiguity &&
+	git branch vagueness &&
+	test_commit tag file &&
+	git tag ambiguity &&
+	git tag vagueness HEAD:file &&
+	test_commit other file
+'
+
+test_expect_success 'checkout ambiguous ref succeeds' '
+	git checkout ambiguity >stdout 2>stderr
+'
+
+test_expect_success 'checkout produces ambiguity warning' '
+	grep "warning.*ambiguous" stderr
+'
+
+test_expect_success 'checkout chooses branch over tag' '
+	echo refs/heads/ambiguity >expect &&
+	git symbolic-ref HEAD >actual &&
+	test_cmp expect actual &&
+	echo branch >expect &&
+	test_cmp expect file
+'
+
+test_expect_success 'checkout reports switch to branch' '
+	grep "Switched to branch" stderr &&
+	! grep "^HEAD is now at" stderr
+'
+
+test_expect_success 'checkout vague ref succeeds' '
+	git checkout vagueness >stdout 2>stderr &&
+	test_set_prereq VAGUENESS_SUCCESS
+'
+
+test_expect_success VAGUENESS_SUCCESS 'checkout produces ambiguity warning' '
+	grep "warning.*ambiguous" stderr
+'
+
+test_expect_success VAGUENESS_SUCCESS 'checkout chooses branch over tag' '
+	echo refs/heads/vagueness >expect &&
+	git symbolic-ref HEAD >actual &&
+	test_cmp expect actual &&
+	echo branch >expect &&
+	test_cmp expect file
+'
+
+test_expect_success VAGUENESS_SUCCESS 'checkout reports switch to branch' '
+	grep "Switched to branch" stderr &&
+	! grep "^HEAD is now at" stderr
+'
+
+test_done
diff --git a/t/t2020-checkout-detach.sh b/t/t2020-checkout-detach.sh
new file mode 100755
index 0000000..0042145
--- /dev/null
+++ b/t/t2020-checkout-detach.sh
@@ -0,0 +1,95 @@
+#!/bin/sh
+
+test_description='checkout into detached HEAD state'
+. ./test-lib.sh
+
+check_detached () {
+	test_must_fail git symbolic-ref -q HEAD >/dev/null
+}
+
+check_not_detached () {
+	git symbolic-ref -q HEAD >/dev/null
+}
+
+reset () {
+	git checkout master &&
+	check_not_detached
+}
+
+test_expect_success 'setup' '
+	test_commit one &&
+	test_commit two &&
+	git branch branch &&
+	git tag tag
+'
+
+test_expect_success 'checkout branch does not detach' '
+	reset &&
+	git checkout branch &&
+	check_not_detached
+'
+
+test_expect_success 'checkout tag detaches' '
+	reset &&
+	git checkout tag &&
+	check_detached
+'
+
+test_expect_success 'checkout branch by full name detaches' '
+	reset &&
+	git checkout refs/heads/branch &&
+	check_detached
+'
+
+test_expect_success 'checkout non-ref detaches' '
+	reset &&
+	git checkout branch^ &&
+	check_detached
+'
+
+test_expect_success 'checkout ref^0 detaches' '
+	reset &&
+	git checkout branch^0 &&
+	check_detached
+'
+
+test_expect_success 'checkout --detach detaches' '
+	reset &&
+	git checkout --detach branch &&
+	check_detached
+'
+
+test_expect_success 'checkout --detach without branch name' '
+	reset &&
+	git checkout --detach &&
+	check_detached
+'
+
+test_expect_success 'checkout --detach errors out for non-commit' '
+	reset &&
+	test_must_fail git checkout --detach one^{tree} &&
+	check_not_detached
+'
+
+test_expect_success 'checkout --detach errors out for extra argument' '
+	reset &&
+	git checkout master &&
+	test_must_fail git checkout --detach tag one.t &&
+	check_not_detached
+'
+
+test_expect_success 'checkout --detached and -b are incompatible' '
+	reset &&
+	test_must_fail git checkout --detach -b newbranch tag &&
+	check_not_detached
+'
+
+test_expect_success 'checkout --detach moves HEAD' '
+	reset &&
+	git checkout one &&
+	git checkout --detach two &&
+	git diff --exit-code HEAD &&
+	git diff --exit-code two
+'
+
+test_done
diff --git a/t/t2021-checkout-overwrite.sh b/t/t2021-checkout-overwrite.sh
new file mode 100755
index 0000000..27db2ad
--- /dev/null
+++ b/t/t2021-checkout-overwrite.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+test_description='checkout must not overwrite an untracked objects'
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+
+	mkdir -p a/b/c &&
+	>a/b/c/d &&
+	git add -A &&
+	git commit -m base &&
+	git tag start
+'
+
+test_expect_success 'create a commit where dir a/b changed to file' '
+
+	git checkout -b file &&
+	rm -rf a/b &&
+	>a/b &&
+	git add -A &&
+	git commit -m "dir to file"
+'
+
+test_expect_success 'checkout commit with dir must not remove untracked a/b' '
+
+	git rm --cached a/b &&
+	git commit -m "un-track the file" &&
+	test_must_fail git checkout start &&
+	test -f a/b
+'
+
+test_expect_success SYMLINKS 'create a commit where dir a/b changed to symlink' '
+
+	rm -rf a/b &&	# cleanup if previous test failed
+	git checkout -f -b symlink start &&
+	rm -rf a/b &&
+	ln -s foo a/b &&
+	git add -A &&
+	git commit -m "dir to symlink"
+'
+
+test_expect_failure SYMLINKS 'checkout commit with dir must not remove untracked a/b' '
+
+	git rm --cached a/b &&
+	git commit -m "un-track the symlink" &&
+	test_must_fail git checkout start &&
+	test -h a/b
+'
+
+test_done
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index f308235..78ce09f 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -223,6 +223,11 @@
     'branch from non-branch HEAD w/--track causes failure' \
     'test_must_fail git branch --track my10 HEAD^'
 
+test_expect_success \
+    'branch from tag w/--track causes failure' \
+    'git tag foobar &&
+     test_must_fail git branch --track my11 foobar'
+
 # Keep this test last, as it changes the current branch
 cat >expect <<EOF
 0000000000000000000000000000000000000000 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000	branch: Created from master
@@ -488,6 +493,15 @@
 	test "z$(git config branch.myr20.rebase)" = z
 '
 
+test_expect_success 'autosetuprebase always on detached HEAD' '
+	git config branch.autosetupmerge always &&
+	test_when_finished git checkout master &&
+	git checkout HEAD^0 &&
+	git branch my11 &&
+	test -z "$(git config branch.my11.remote)" &&
+	test -z "$(git config branch.my11.merge)"
+'
+
 test_expect_success 'detect misconfigured autosetuprebase (bad value)' '
 	git config branch.autosetuprebase garbage &&
 	test_must_fail git branch
diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh
index 607bf25..9574180 100755
--- a/t/t3507-cherry-pick-conflict.sh
+++ b/t/t3507-cherry-pick-conflict.sh
@@ -11,6 +11,18 @@
 
 . ./test-lib.sh
 
+test_cmp_rev () {
+	git rev-parse --verify "$1" >expect.rev &&
+	git rev-parse --verify "$2" >actual.rev &&
+	test_cmp expect.rev actual.rev
+}
+
+pristine_detach () {
+	git checkout -f "$1^0" &&
+	git read-tree -u --reset HEAD &&
+	git clean -d -f -f -q -x
+}
+
 test_expect_success setup '
 
 	echo unrelated >unrelated &&
@@ -23,13 +35,7 @@
 '
 
 test_expect_success 'failed cherry-pick does not advance HEAD' '
-
-	git checkout -f initial^0 &&
-	git read-tree -u --reset HEAD &&
-	git clean -d -f -f -q -x &&
-
-	git update-index --refresh &&
-	git diff-index --exit-code HEAD &&
+	pristine_detach initial &&
 
 	head=$(git rev-parse HEAD) &&
 	test_must_fail git cherry-pick picked &&
@@ -39,33 +45,96 @@
 '
 
 test_expect_success 'advice from failed cherry-pick' "
-	git checkout -f initial^0 &&
-	git read-tree -u --reset HEAD &&
-	git clean -d -f -f -q -x &&
-
-	git update-index --refresh &&
-	git diff-index --exit-code HEAD &&
+	pristine_detach initial &&
 
 	picked=\$(git rev-parse --short picked) &&
 	cat <<-EOF >expected &&
 	error: could not apply \$picked... picked
 	hint: after resolving the conflicts, mark the corrected paths
 	hint: with 'git add <paths>' or 'git rm <paths>'
-	hint: and commit the result with 'git commit -c \$picked'
+	hint: and commit the result with 'git commit'
 	EOF
 	test_must_fail git cherry-pick picked 2>actual &&
 
 	test_cmp expected actual
 "
 
+test_expect_success 'failed cherry-pick sets CHERRY_PICK_HEAD' '
+	pristine_detach initial &&
+	test_must_fail git cherry-pick picked &&
+	test_cmp_rev picked CHERRY_PICK_HEAD
+'
+
+test_expect_success 'successful cherry-pick does not set CHERRY_PICK_HEAD' '
+	pristine_detach initial &&
+	git cherry-pick base &&
+	test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
+'
+
+test_expect_success 'cherry-pick --no-commit does not set CHERRY_PICK_HEAD' '
+	pristine_detach initial &&
+	git cherry-pick --no-commit base &&
+	test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
+'
+
+test_expect_success 'GIT_CHERRY_PICK_HELP suppresses CHERRY_PICK_HEAD' '
+	pristine_detach initial &&
+	(
+		GIT_CHERRY_PICK_HELP="and then do something else" &&
+		export GIT_CHERRY_PICK_HELP &&
+		test_must_fail git cherry-pick picked
+	) &&
+	test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
+'
+
+test_expect_success 'git reset clears CHERRY_PICK_HEAD' '
+	pristine_detach initial &&
+
+	test_must_fail git cherry-pick picked &&
+	git reset &&
+
+	test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
+'
+
+test_expect_success 'failed commit does not clear CHERRY_PICK_HEAD' '
+	pristine_detach initial &&
+
+	test_must_fail git cherry-pick picked &&
+	test_must_fail git commit &&
+
+	test_cmp_rev picked CHERRY_PICK_HEAD
+'
+
+test_expect_success 'cancelled commit does not clear CHERRY_PICK_HEAD' '
+	pristine_detach initial &&
+
+	test_must_fail git cherry-pick picked &&
+	echo resolved >foo &&
+	git add foo &&
+	git update-index --refresh -q &&
+	test_must_fail git diff-index --exit-code HEAD &&
+	(
+		GIT_EDITOR=false &&
+		export GIT_EDITOR &&
+		test_must_fail git commit
+	) &&
+
+	test_cmp_rev picked CHERRY_PICK_HEAD
+'
+
+test_expect_success 'successful commit clears CHERRY_PICK_HEAD' '
+	pristine_detach initial &&
+
+	test_must_fail git cherry-pick picked &&
+	echo resolved >foo &&
+	git add foo &&
+	git commit &&
+
+	test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
+'
+
 test_expect_success 'failed cherry-pick produces dirty index' '
-
-	git checkout -f initial^0 &&
-	git read-tree -u --reset HEAD &&
-	git clean -d -f -f -q -x &&
-
-	git update-index --refresh &&
-	git diff-index --exit-code HEAD &&
+	pristine_detach initial &&
 
 	test_must_fail git cherry-pick picked &&
 
@@ -74,9 +143,7 @@
 '
 
 test_expect_success 'failed cherry-pick registers participants in index' '
-
-	git read-tree -u --reset HEAD &&
-	git clean -d -f -f -q -x &&
+	pristine_detach initial &&
 	{
 		git checkout base -- foo &&
 		git ls-files --stage foo &&
@@ -90,10 +157,7 @@
 		2 s/ 0	/ 2	/
 		3 s/ 0	/ 3	/
 	" < stages > expected &&
-	git checkout -f initial^0 &&
-
-	git update-index --refresh &&
-	git diff-index --exit-code HEAD &&
+	git read-tree -u --reset HEAD &&
 
 	test_must_fail git cherry-pick picked &&
 	git ls-files --stage --unmerged > actual &&
@@ -102,10 +166,7 @@
 '
 
 test_expect_success 'failed cherry-pick describes conflict in work tree' '
-
-	git checkout -f initial^0 &&
-	git read-tree -u --reset HEAD &&
-	git clean -d -f -f -q -x &&
+	pristine_detach initial &&
 	cat <<-EOF > expected &&
 	<<<<<<< HEAD
 	a
@@ -114,9 +175,6 @@
 	>>>>>>> objid picked
 	EOF
 
-	git update-index --refresh &&
-	git diff-index --exit-code HEAD &&
-
 	test_must_fail git cherry-pick picked &&
 
 	sed "s/[a-f0-9]*\.\.\./objid/" foo > actual &&
@@ -124,11 +182,8 @@
 '
 
 test_expect_success 'diff3 -m style' '
-
+	pristine_detach initial &&
 	git config merge.conflictstyle diff3 &&
-	git checkout -f initial^0 &&
-	git read-tree -u --reset HEAD &&
-	git clean -d -f -f -q -x &&
 	cat <<-EOF > expected &&
 	<<<<<<< HEAD
 	a
@@ -139,9 +194,6 @@
 	>>>>>>> objid picked
 	EOF
 
-	git update-index --refresh &&
-	git diff-index --exit-code HEAD &&
-
 	test_must_fail git cherry-pick picked &&
 
 	sed "s/[a-f0-9]*\.\.\./objid/" foo > actual &&
@@ -149,10 +201,8 @@
 '
 
 test_expect_success 'revert also handles conflicts sanely' '
-
 	git config --unset merge.conflictstyle &&
-	git read-tree -u --reset HEAD &&
-	git clean -d -f -f -q -x &&
+	pristine_detach initial &&
 	cat <<-EOF > expected &&
 	<<<<<<< HEAD
 	a
@@ -173,10 +223,7 @@
 		2 s/ 0	/ 2	/
 		3 s/ 0	/ 3	/
 	" < stages > expected-stages &&
-	git checkout -f initial^0 &&
-
-	git update-index --refresh &&
-	git diff-index --exit-code HEAD &&
+	git read-tree -u --reset HEAD &&
 
 	head=$(git rev-parse HEAD) &&
 	test_must_fail git revert picked &&
@@ -192,10 +239,8 @@
 '
 
 test_expect_success 'revert conflict, diff3 -m style' '
+	pristine_detach initial &&
 	git config merge.conflictstyle diff3 &&
-	git checkout -f initial^0 &&
-	git read-tree -u --reset HEAD &&
-	git clean -d -f -f -q -x &&
 	cat <<-EOF > expected &&
 	<<<<<<< HEAD
 	a
@@ -206,9 +251,6 @@
 	>>>>>>> parent of objid picked
 	EOF
 
-	git update-index --refresh &&
-	git diff-index --exit-code HEAD &&
-
 	test_must_fail git revert picked &&
 
 	sed "s/[a-f0-9]*\.\.\./objid/" foo > actual &&
diff --git a/t/t4003-diff-rename-1.sh b/t/t4003-diff-rename-1.sh
index c6130c4..bfa8835 100755
--- a/t/t4003-diff-rename-1.sh
+++ b/t/t4003-diff-rename-1.sh
@@ -29,7 +29,7 @@
 # copy-and-edit one, and rename-and-edit the other.  We do not say
 # anything about rezrov.
 
-GIT_DIFF_OPTS=--unified=0 git diff-index -M -p $tree >current
+GIT_DIFF_OPTS=--unified=0 git diff-index -C -p $tree >current
 cat >expected <<\EOF
 diff --git a/COPYING b/COPYING.1
 copy from COPYING
diff --git a/t/t4004-diff-rename-symlink.sh b/t/t4004-diff-rename-symlink.sh
index 92a65f4..6e562c8 100755
--- a/t/t4004-diff-rename-symlink.sh
+++ b/t/t4004-diff-rename-symlink.sh
@@ -35,7 +35,7 @@
 # a new creation.
 
 test_expect_success SYMLINKS 'setup diff output' "
-    GIT_DIFF_OPTS=--unified=0 git diff-index -M -p $tree >current &&
+    GIT_DIFF_OPTS=--unified=0 git diff-index -C -p $tree >current &&
     cat >expected <<\EOF
 diff --git a/bozbar b/bozbar
 new file mode 120000
diff --git a/t/t4005-diff-rename-2.sh b/t/t4005-diff-rename-2.sh
index 1ba359d..77d7f49 100755
--- a/t/t4005-diff-rename-2.sh
+++ b/t/t4005-diff-rename-2.sh
@@ -29,7 +29,7 @@
 # and COPYING.2 are based on COPYING, and do not say anything about
 # rezrov.
 
-git diff-index -M $tree >current
+git diff-index -C $tree >current
 
 cat >expected <<\EOF
 :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234	COPYING	COPYING.1
diff --git a/t/t4008-diff-break-rewrite.sh b/t/t4008-diff-break-rewrite.sh
index d79d9e1e..73b4a24 100755
--- a/t/t4008-diff-break-rewrite.sh
+++ b/t/t4008-diff-break-rewrite.sh
@@ -173,8 +173,8 @@
     'compare_diff_raw expected current'
 
 test_expect_success \
-    'run diff with -B -M' \
-    'git diff-index -B -M "$tree" >current'
+    'run diff with -B -C' \
+    'git diff-index -B -C "$tree" >current'
 
 cat >expected <<\EOF
 :100644 100644 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 08bb2fb671deff4c03a4d4a0a1315dff98d5732c C095	file0	file1
diff --git a/t/t4009-diff-rename-4.sh b/t/t4009-diff-rename-4.sh
index de3f174..f22c8e3 100755
--- a/t/t4009-diff-rename-4.sh
+++ b/t/t4009-diff-rename-4.sh
@@ -29,7 +29,7 @@
 # and COPYING.2 are based on COPYING, and do not say anything about
 # rezrov.
 
-git diff-index -z -M $tree >current
+git diff-index -z -C $tree >current
 
 cat >expected <<\EOF
 :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234
diff --git a/t/t4010-diff-pathspec.sh b/t/t4010-diff-pathspec.sh
index 94df7ae..fbc8cd8 100755
--- a/t/t4010-diff-pathspec.sh
+++ b/t/t4010-diff-pathspec.sh
@@ -70,4 +70,36 @@
 	test_cmp expected current
 '
 
+EMPTY_TREE=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+
+test_expect_success 'diff-tree with wildcard shows dir also matches' '
+	git diff-tree --name-only $EMPTY_TREE $tree -- "f*" >result &&
+	echo file0 >expected &&
+	test_cmp expected result
+'
+
+test_expect_success 'diff-tree -r with wildcard' '
+	git diff-tree -r --name-only $EMPTY_TREE $tree -- "*file1" >result &&
+	echo path1/file1 >expected &&
+	test_cmp expected result
+'
+
+test_expect_success 'diff-tree with wildcard shows dir also matches' '
+	git diff-tree --name-only $tree $tree2 -- "path1/f*" >result &&
+	echo path1 >expected &&
+	test_cmp expected result
+'
+
+test_expect_success 'diff-tree -r with wildcard from beginning' '
+	git diff-tree -r --name-only $tree $tree2 -- "path1/*file1" >result &&
+	echo path1/file1 >expected &&
+	test_cmp expected result
+'
+
+test_expect_success 'diff-tree -r with wildcard' '
+	git diff-tree -r --name-only $tree $tree2 -- "path1/f*" >result &&
+	echo path1/file1 >expected &&
+	test_cmp expected result
+'
+
 test_done
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index 027c13d..9c66367 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -709,4 +709,88 @@
 	test_path_is_missing .git/pager_used
 '
 
+test_expect_success 'format-patch handles multi-line subjects' '
+	rm -rf patches/ &&
+	echo content >>file &&
+	for i in one two three; do echo $i; done >msg &&
+	git add file &&
+	git commit -F msg &&
+	git format-patch -o patches -1 &&
+	grep ^Subject: patches/0001-one.patch >actual &&
+	echo "Subject: [PATCH] one two three" >expect &&
+	test_cmp expect actual
+'
+
+test_expect_success 'format-patch handles multi-line encoded subjects' '
+	rm -rf patches/ &&
+	echo content >>file &&
+	for i in en två tre; do echo $i; done >msg &&
+	git add file &&
+	git commit -F msg &&
+	git format-patch -o patches -1 &&
+	grep ^Subject: patches/0001-en.patch >actual &&
+	echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
+	test_cmp expect actual
+'
+
+M8="foo bar "
+M64=$M8$M8$M8$M8$M8$M8$M8$M8
+M512=$M64$M64$M64$M64$M64$M64$M64$M64
+cat >expect <<'EOF'
+Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
+ bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
+ foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
+ bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
+ foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
+ bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
+ foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
+ bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
+ foo bar foo bar foo bar foo bar
+EOF
+test_expect_success 'format-patch wraps extremely long headers (ascii)' '
+	echo content >>file &&
+	git add file &&
+	git commit -m "$M512" &&
+	git format-patch --stdout -1 >patch &&
+	sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
+	test_cmp expect subject
+'
+
+M8="föö bar "
+M64=$M8$M8$M8$M8$M8$M8$M8$M8
+M512=$M64$M64$M64$M64$M64$M64$M64$M64
+cat >expect <<'EOF'
+Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
+EOF
+test_expect_success 'format-patch wraps extremely long headers (rfc2047)' '
+	rm -rf patches/ &&
+	echo content >>file &&
+	git add file &&
+	git commit -m "$M512" &&
+	git format-patch --stdout -1 >patch &&
+	sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
+	test_cmp expect subject
+'
+
 test_done
diff --git a/t/t4031-diff-rewrite-binary.sh b/t/t4031-diff-rewrite-binary.sh
index 7e7b307..7d7470f 100755
--- a/t/t4031-diff-rewrite-binary.sh
+++ b/t/t4031-diff-rewrite-binary.sh
@@ -44,6 +44,13 @@
 	grep "GIT binary patch" diff
 '
 
+test_expect_success 'rewrite diff --stat shows binary changes' '
+	git diff -B --stat --summary >diff &&
+	grep "Bin" diff &&
+	grep "0 insertions.*0 deletions" diff &&
+	grep " rewrite file" diff
+'
+
 {
 	echo "#!$SHELL_PATH"
 	cat <<'EOF'
diff --git a/t/t4204-patch-id.sh b/t/t4204-patch-id.sh
index 68e2652..d2c930d 100755
--- a/t/t4204-patch-id.sh
+++ b/t/t4204-patch-id.sh
@@ -63,4 +63,40 @@
 	test_cmp patch-id_master patch-id_same
 '
 
+cat >nonl <<\EOF
+diff --git i/a w/a
+index e69de29..2e65efe 100644
+--- i/a
++++ w/a
+@@ -0,0 +1 @@
++a
+\ No newline at end of file
+diff --git i/b w/b
+index e69de29..6178079 100644
+--- i/b
++++ w/b
+@@ -0,0 +1 @@
++b
+EOF
+
+cat >withnl <<\EOF
+diff --git i/a w/a
+index e69de29..7898192 100644
+--- i/a
++++ w/a
+@@ -0,0 +1 @@
++a
+diff --git i/b w/b
+index e69de29..6178079 100644
+--- i/b
++++ w/b
+@@ -0,0 +1 @@
++b
+EOF
+
+test_expect_success 'patch-id handles no-nl-at-eof markers' '
+	cat nonl | calc_patch_id nonl &&
+	cat withnl | calc_patch_id withnl &&
+	test_cmp patch-id_nonl patch-id_withnl
+'
 test_done
diff --git a/t/t5701-clone-local.sh b/t/t5701-clone-local.sh
index 0f4d487..6972258 100755
--- a/t/t5701-clone-local.sh
+++ b/t/t5701-clone-local.sh
@@ -144,4 +144,17 @@
 	test_must_fail git push)
 '
 
+test_expect_success 'cloning non-existent directory fails' '
+	cd "$D" &&
+	rm -rf does-not-exist &&
+	test_must_fail git clone does-not-exist
+'
+
+test_expect_success 'cloning non-git directory fails' '
+	cd "$D" &&
+	rm -rf not-a-git-repo not-a-git-repo-clone &&
+	mkdir not-a-git-repo &&
+	test_must_fail git clone not-a-git-repo not-a-git-repo-clone
+'
+
 test_done
diff --git a/t/t6000-rev-list-misc.sh b/t/t6000-rev-list-misc.sh
new file mode 100755
index 0000000..b10685a
--- /dev/null
+++ b/t/t6000-rev-list-misc.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+
+test_description='miscellaneous rev-list tests'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+	echo content1 >wanted_file &&
+	echo content2 >unwanted_file &&
+	git add wanted_file unwanted_file &&
+	git commit -m one
+'
+
+test_expect_success 'rev-list --objects heeds pathspecs' '
+	git rev-list --objects HEAD -- wanted_file >output &&
+	grep wanted_file output &&
+	! grep unwanted_file output
+'
+
+test_expect_success 'rev-list --objects with pathspecs and deeper paths' '
+	mkdir foo &&
+	>foo/file &&
+	git add foo/file &&
+	git commit -m two &&
+
+	git rev-list --objects HEAD -- foo >output &&
+	grep foo/file output &&
+
+	git rev-list --objects HEAD -- foo/file >output &&
+	grep foo/file output &&
+	! grep unwanted_file output
+'
+
+test_expect_success 'rev-list --objects with pathspecs and copied files' '
+	git checkout --orphan junio-testcase &&
+	git rm -rf . &&
+
+	mkdir two &&
+	echo frotz >one &&
+	cp one two/three &&
+	git add one two/three &&
+	test_tick &&
+	git commit -m that &&
+
+	ONE=$(git rev-parse HEAD:one)
+	git rev-list --objects HEAD two >output &&
+	grep "$ONE two/three" output &&
+	! grep one output
+'
+
+test_done
diff --git a/t/t6004-rev-list-path-optim.sh b/t/t6004-rev-list-path-optim.sh
index 5dabf1c..3e8c42e 100755
--- a/t/t6004-rev-list-path-optim.sh
+++ b/t/t6004-rev-list-path-optim.sh
@@ -1,51 +1,96 @@
 #!/bin/sh
 
-test_description='git rev-list trivial path optimization test'
+test_description='git rev-list trivial path optimization test
+
+   d/z1
+   b0                             b1
+   o------------------------*----o master
+  /                        /
+ o---------o----o----o----o side
+ a0        c0   c1   a1   c2
+ d/f0      d/f1
+ d/z0
+
+'
 
 . ./test-lib.sh
 
 test_expect_success setup '
-echo Hello > a &&
-git add a &&
-git commit -m "Initial commit" a &&
-initial=$(git rev-parse --verify HEAD)
+	echo Hello >a &&
+	mkdir d &&
+	echo World >d/f &&
+	echo World >d/z &&
+	git add a d &&
+	test_tick &&
+	git commit -m "Initial commit" &&
+	git rev-parse --verify HEAD &&
+	git tag initial
 '
 
 test_expect_success path-optimization '
-    commit=$(echo "Unchanged tree" | git commit-tree "HEAD^{tree}" -p HEAD) &&
-    test $(git rev-list $commit | wc -l) = 2 &&
-    test $(git rev-list $commit -- . | wc -l) = 1
+	test_tick &&
+	commit=$(echo "Unchanged tree" | git commit-tree "HEAD^{tree}" -p HEAD) &&
+	test $(git rev-list $commit | wc -l) = 2 &&
+	test $(git rev-list $commit -- . | wc -l) = 1
 '
 
 test_expect_success 'further setup' '
 	git checkout -b side &&
 	echo Irrelevant >c &&
-	git add c &&
+	echo Irrelevant >d/f &&
+	git add c d/f &&
+	test_tick &&
 	git commit -m "Side makes an irrelevant commit" &&
+	git tag side_c0 &&
 	echo "More Irrelevancy" >c &&
 	git add c &&
+	test_tick &&
 	git commit -m "Side makes another irrelevant commit" &&
 	echo Bye >a &&
 	git add a &&
+	test_tick &&
 	git commit -m "Side touches a" &&
-	side=$(git rev-parse --verify HEAD) &&
+	git tag side_a1 &&
 	echo "Yet more Irrelevancy" >c &&
 	git add c &&
+	test_tick &&
 	git commit -m "Side makes yet another irrelevant commit" &&
 	git checkout master &&
 	echo Another >b &&
-	git add b &&
+	echo Munged >d/z &&
+	git add b d/z &&
+	test_tick &&
 	git commit -m "Master touches b" &&
+	git tag master_b0 &&
 	git merge side &&
 	echo Touched >b &&
 	git add b &&
+	test_tick &&
 	git commit -m "Master touches b again"
 '
 
 test_expect_success 'path optimization 2' '
-	( echo "$side"; echo "$initial" ) >expected &&
+	git rev-parse side_a1 initial >expected &&
 	git rev-list HEAD -- a >actual &&
 	test_cmp expected actual
 '
 
+test_expect_success 'pathspec with leading path' '
+	git rev-parse master^ master_b0 side_c0 initial >expected &&
+	git rev-list HEAD -- d >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'pathspec with glob (1)' '
+	git rev-parse master^ master_b0 side_c0 initial >expected &&
+	git rev-list HEAD -- "d/*" >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'pathspec with glob (2)' '
+	git rev-parse side_c0 initial >expected &&
+	git rev-list HEAD -- "d/[a-m]*" >actual &&
+	test_cmp expected actual
+'
+
 test_done
diff --git a/t/t6035-merge-dir-to-symlink.sh b/t/t6035-merge-dir-to-symlink.sh
index 92e02d5..2599ae5 100755
--- a/t/t6035-merge-dir-to-symlink.sh
+++ b/t/t6035-merge-dir-to-symlink.sh
@@ -17,13 +17,21 @@
 	git commit -m "dir to symlink"
 '
 
-test_expect_success SYMLINKS 'keep a/b-2/c/d across checkout' '
+test_expect_success SYMLINKS 'checkout does not clobber untracked symlink' '
 	git checkout HEAD^0 &&
 	git reset --hard master &&
 	git rm --cached a/b &&
 	git commit -m "untracked symlink remains" &&
-	 git checkout start^0 &&
-	 test -f a/b-2/c/d
+	test_must_fail git checkout start^0
+'
+
+test_expect_success SYMLINKS 'a/b-2/c/d is kept when clobbering symlink b' '
+	git checkout HEAD^0 &&
+	git reset --hard master &&
+	git rm --cached a/b &&
+	git commit -m "untracked symlink remains" &&
+	git checkout -f start^0 &&
+	test -f a/b-2/c/d
 '
 
 test_expect_success SYMLINKS 'checkout should not have deleted a/b-2/c/d' '
diff --git a/t/t6040-tracking-info.sh b/t/t6040-tracking-info.sh
index 1e0447f..cb85132 100755
--- a/t/t6040-tracking-info.sh
+++ b/t/t6040-tracking-info.sh
@@ -74,20 +74,20 @@
 	grep "have 1 and 1 different" actual
 '
 
-test_expect_success 'status when tracking lightweight tags' '
+test_expect_success 'fail to track lightweight tags' '
 	git checkout master &&
 	git tag light &&
-	git branch --track lighttrack light >actual &&
-	grep "set up to track" actual &&
-	git checkout lighttrack
+	test_must_fail git branch --track lighttrack light >actual &&
+	test_must_fail grep "set up to track" actual &&
+	test_must_fail git checkout lighttrack
 '
 
-test_expect_success 'status when tracking annotated tags' '
+test_expect_success 'fail to track annotated tags' '
 	git checkout master &&
 	git tag -m heavy heavy &&
-	git branch --track heavytrack heavy >actual &&
-	grep "set up to track" actual &&
-	git checkout heavytrack
+	test_must_fail git branch --track heavytrack heavy >actual &&
+	test_must_fail grep "set up to track" actual &&
+	test_must_fail git checkout heavytrack
 '
 
 test_expect_success 'setup tracking with branch --set-upstream on existing branch' '
diff --git a/t/t7201-co.sh b/t/t7201-co.sh
index 1337fa5..0c002ab 100755
--- a/t/t7201-co.sh
+++ b/t/t7201-co.sh
@@ -408,6 +408,15 @@
     test "z$(git rev-parse master^0)" = "z$(git rev-parse HEAD)"
 '
 
+test_expect_success 'checkout w/--track from tag fails' '
+    git checkout master^0 &&
+    test_must_fail git symbolic-ref HEAD &&
+    test_must_fail git checkout --track -b track frotz &&
+    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 &&
@@ -423,7 +432,6 @@
 test_expect_success \
     'checkout with --track fakes a sensible -b <name>' '
     git update-ref refs/remotes/origin/koala/bear renamer &&
-    git update-ref refs/new/koala/bear renamer &&
 
     git checkout --track origin/koala/bear &&
     test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
@@ -439,12 +447,6 @@
 
     git checkout --track remotes/origin/koala/bear &&
     test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
-    test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
-
-    git checkout master && git branch -D koala/bear &&
-
-    git checkout --track refs/new/koala/bear &&
-    test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
     test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)"
 '
 
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index bfb4975..fa9d23a 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -203,4 +203,56 @@
 	)
 '
 
+test_expect_success 'submodule update --merge  - ignores --merge  for new submodules' '
+	(cd super &&
+	 rm -rf submodule &&
+	 git submodule update submodule &&
+	 git status -s submodule >expect &&
+	 rm -rf submodule &&
+	 git submodule update --merge submodule &&
+	 git status -s submodule >actual &&
+	 test_cmp expect actual
+	)
+'
+
+test_expect_success 'submodule update --rebase - ignores --rebase for new submodules' '
+	(cd super &&
+	 rm -rf submodule &&
+	 git submodule update submodule &&
+	 git status -s submodule >expect &&
+	 rm -rf submodule &&
+	 git submodule update --rebase submodule &&
+	 git status -s submodule >actual &&
+	 test_cmp expect actual
+	)
+'
+
+test_expect_success 'submodule update ignores update=merge config for new submodules' '
+	(cd super &&
+	 rm -rf submodule &&
+	 git submodule update submodule &&
+	 git status -s submodule >expect &&
+	 rm -rf submodule &&
+	 git config submodule.submodule.update merge &&
+	 git submodule update submodule &&
+	 git status -s submodule >actual &&
+	 git config --unset submodule.submodule.update &&
+	 test_cmp expect actual
+	)
+'
+
+test_expect_success 'submodule update ignores update=rebase config for new submodules' '
+	(cd super &&
+	 rm -rf submodule &&
+	 git submodule update submodule &&
+	 git status -s submodule >expect &&
+	 rm -rf submodule &&
+	 git config submodule.submodule.update rebase &&
+	 git submodule update submodule &&
+	 git status -s submodule >actual &&
+	 git config --unset submodule.submodule.update &&
+	 test_cmp expect actual
+	)
+'
+
 test_done
diff --git a/t/t7500-commit.sh b/t/t7500-commit.sh
index d551b77..5976f59 100755
--- a/t/t7500-commit.sh
+++ b/t/t7500-commit.sh
@@ -28,13 +28,21 @@
 test_expect_success 'nonexistent template file should return error' '
 	echo changes >> foo &&
 	git add foo &&
-	test_must_fail git commit --template "$PWD"/notexist
+	(
+		GIT_EDITOR="echo hello >\"\$1\"" &&
+		export GIT_EDITOR &&
+		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 &&
-	test_must_fail git commit &&
-	git config --unset commit.template
+	test_when_finished "git config --unset commit.template" &&
+	(
+		GIT_EDITOR="echo hello >\"\$1\"" &&
+		export GIT_EDITOR &&
+		test_must_fail git commit
+	)
 '
 
 # From now on we'll use a template file that exists.
diff --git a/t/t7505-prepare-commit-msg-hook.sh b/t/t7505-prepare-commit-msg-hook.sh
index ff18962..5b4b694 100755
--- a/t/t7505-prepare-commit-msg-hook.sh
+++ b/t/t7505-prepare-commit-msg-hook.sh
@@ -132,6 +132,18 @@
 
 '
 
+test_expect_success 'with hook (merge)' '
+
+	head=`git rev-parse HEAD` &&
+	git checkout -b other HEAD@{1} &&
+	echo "more" >> file &&
+	git add file &&
+	git commit -m other &&
+	git checkout - &&
+	git merge other &&
+	test "`git log -1 --pretty=format:%s`" = merge
+'
+
 cat > "$HOOK" <<'EOF'
 #!/bin/sh
 exit 1
diff --git a/t/t7509-commit.sh b/t/t7509-commit.sh
index 77b6920..b61fd3c 100755
--- a/t/t7509-commit.sh
+++ b/t/t7509-commit.sh
@@ -157,4 +157,33 @@
 	test_must_fail git commit -a --reset-author -m done
 '
 
+test_expect_success 'commit respects CHERRY_PICK_HEAD and MERGE_MSG' '
+	echo "cherry-pick 1a" >>foo &&
+	test_tick &&
+	git commit -am "cherry-pick 1" --author="Cherry <cherry@pick.er>" &&
+	git tag cherry-pick-head &&
+	git rev-parse cherry-pick-head >.git/CHERRY_PICK_HEAD &&
+	echo "This is a MERGE_MSG" >.git/MERGE_MSG &&
+	echo "cherry-pick 1b" >>foo &&
+	test_tick &&
+	git commit -a &&
+	author_header cherry-pick-head >expect &&
+	author_header HEAD >actual &&
+	test_cmp expect actual &&
+
+	echo "This is a MERGE_MSG" >expect &&
+	message_body HEAD >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success '--reset-author with CHERRY_PICK_HEAD' '
+	git rev-parse cherry-pick-head >.git/CHERRY_PICK_HEAD &&
+	echo "cherry-pick 2" >>foo &&
+	test_tick &&
+	git commit -am "cherry-pick 2" --reset-author &&
+	echo "author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> $GIT_AUTHOR_DATE" >expect &&
+	author_header HEAD >actual &&
+	test_cmp expect actual
+'
+
 test_done
diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh
index d78bdec..dc838c9 100755
--- a/t/t7610-mergetool.sh
+++ b/t/t7610-mergetool.sh
@@ -16,23 +16,33 @@
 test_expect_success 'setup' '
     git config rerere.enabled true &&
     echo master >file1 &&
+    echo master file11 >file11 &&
+    echo master file12 >file12 &&
+    echo master file13 >file13 &&
+    echo master file14 >file14 &&
     mkdir subdir &&
     echo master sub >subdir/file3 &&
-    git add file1 subdir/file3 &&
-    git commit -m "added file1" &&
+    git add file1 file1[1-4] subdir/file3 &&
+    git commit -m "add initial versions" &&
 
     git checkout -b branch1 master &&
     echo branch1 change >file1 &&
     echo branch1 newfile >file2 &&
+    echo branch1 change file11 >file11 &&
+    echo branch1 change file13 >file13 &&
     echo branch1 sub >subdir/file3 &&
-    git add file1 file2 subdir/file3 &&
+    git add file1 file11 file13 file2 subdir/file3 &&
+    git rm file12 &&
     git commit -m "branch1 changes" &&
 
     git checkout master &&
     echo master updated >file1 &&
     echo master new >file2 &&
+    echo master updated file12 >file12 &&
+    echo master updated file14 >file14 &&
     echo master new sub >subdir/file3 &&
-    git add file1 file2 subdir/file3 &&
+    git add file1 file12 file14 file2 subdir/file3 &&
+    git rm file11 &&
     git commit -m "master updates" &&
 
     git config merge.tool mytool &&
@@ -46,6 +56,8 @@
     ( yes "" | git mergetool file1 >/dev/null 2>&1 ) &&
     ( yes "" | git mergetool file2 >/dev/null 2>&1 ) &&
     ( yes "" | git mergetool subdir/file3 >/dev/null 2>&1 ) &&
+    ( yes "d" | git mergetool file11 >/dev/null 2>&1 ) &&
+    ( yes "d" | git mergetool file12 >/dev/null 2>&1 ) &&
     test "$(cat file1)" = "master updated" &&
     test "$(cat file2)" = "master new" &&
     test "$(cat subdir/file3)" = "master new sub" &&
@@ -59,6 +71,8 @@
     ( yes "" | git mergetool file1 >/dev/null 2>&1 ) &&
     ( yes "" | git mergetool file2 >/dev/null 2>&1 ) &&
     ( yes "" | git mergetool subdir/file3 >/dev/null 2>&1 ) &&
+    ( yes "d" | git mergetool file11 >/dev/null 2>&1 ) &&
+    ( yes "d" | git mergetool file12 >/dev/null 2>&1 ) &&
     test "$(printf x | cat file1 -)" = "$(printf "master updated\r\nx")" &&
     test "$(printf x | cat file2 -)" = "$(printf "master new\r\nx")" &&
     test "$(printf x | cat subdir/file3 -)" = "$(printf "master new sub\r\nx")" &&
@@ -82,6 +96,8 @@
 	cd subdir &&
 	( yes "" | git mergetool ../file1 >/dev/null 2>&1 ) &&
 	( yes "" | git mergetool ../file2 >/dev/null 2>&1 ) &&
+	( yes "d" | git mergetool ../file11 >/dev/null 2>&1 ) &&
+	( yes "d" | git mergetool ../file12 >/dev/null 2>&1 ) &&
 	test "$(cat ../file1)" = "master updated" &&
 	test "$(cat ../file2)" = "master new" &&
 	git commit -m "branch1 resolved with mergetool - subdir"
@@ -92,6 +108,8 @@
     git checkout -b test4 branch1 &&
     test_must_fail git merge master &&
     test -n "$(git ls-files -u)" &&
+    ( yes "d" | git mergetool file11 >/dev/null 2>&1 ) &&
+    ( yes "d" | git mergetool file12 >/dev/null 2>&1 ) &&
     output="$(git mergetool --no-prompt)" &&
     test "$output" = "No files need merging" &&
     git reset --hard
@@ -102,13 +120,23 @@
 	cd subdir &&
 	git config rerere.enabled false &&
 	test_must_fail git merge master &&
-	git mergetool --no-prompt &&
+	( yes "d" "d" | git mergetool --no-prompt ) &&
 	test "$(cat ../file1)" = "master updated" &&
 	test "$(cat ../file2)" = "master new" &&
 	test "$(cat file3)" = "master new sub" &&
-	git add ../file1 ../file2 file3 &&
 	git commit -m "branch2 resolved by mergetool from subdir"
     )
 '
 
+test_expect_success 'mergetool skips resolved paths when rerere is active' '
+    git config rerere.enabled true &&
+    rm -rf .git/rr-cache &&
+    git checkout -b test5 branch1
+    test_must_fail git merge master >/dev/null 2>&1 &&
+    ( yes "d" "d" | git mergetool --no-prompt >/dev/null 2>&1 ) &&
+    output="$(yes "n" | git mergetool --no-prompt)" &&
+    test "$output" = "No files need merging" &&
+    git reset --hard
+'
+
 test_done
diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh
index c877758..dbc6cd8 100755
--- a/t/t7810-grep.sh
+++ b/t/t7810-grep.sh
@@ -182,6 +182,24 @@
 		test_cmp expected actual
 	'
 
+	test_expect_success "grep --max-depth 0 -- . t $L" '
+		{
+			echo ${HC}t/v:1:vvv
+			echo ${HC}v:1:vvv
+		} >expected &&
+		git grep --max-depth 0 -n -e vvv $H -- . t >actual &&
+		test_cmp expected actual
+	'
+
+	test_expect_success "grep --max-depth 0 -- t . $L" '
+		{
+			echo ${HC}t/v:1:vvv
+			echo ${HC}v:1:vvv
+		} >expected &&
+		git grep --max-depth 0 -n -e vvv $H -- t . >actual &&
+		test_cmp expected actual
+	'
+
 done
 
 cat >expected <<EOF
@@ -285,6 +303,11 @@
 	test_cmp expected actual
 '
 
+test_expect_success 'grep -f, ignore empty lines, read patterns from stdin' '
+	git grep -f - <patterns >actual &&
+	test_cmp expected actual
+'
+
 cat >expected <<EOF
 y:y yy
 --
diff --git a/t/t9010-svn-fe.sh b/t/t9010-svn-fe.sh
index 88a9751..5a6a4b9 100755
--- a/t/t9010-svn-fe.sh
+++ b/t/t9010-svn-fe.sh
@@ -9,6 +9,30 @@
 	git init
 }
 
+properties () {
+	while test "$#" -ne 0
+	do
+		property="$1" &&
+		value="$2" &&
+		printf "%s\n" "K ${#property}" &&
+		printf "%s\n" "$property" &&
+		printf "%s\n" "V ${#value}" &&
+		printf "%s\n" "$value" &&
+		shift 2 ||
+		return 1
+	done
+}
+
+text_no_props () {
+	text="$1
+" &&
+	printf "%s\n" "Prop-content-length: 10" &&
+	printf "%s\n" "Text-content-length: ${#text}" &&
+	printf "%s\n" "Content-length: $((${#text} + 10))" &&
+	printf "%s\n" "" "PROPS-END" &&
+	printf "%s\n" "$text"
+}
+
 >empty
 
 test_expect_success 'empty dump' '
@@ -18,13 +42,686 @@
 	git fast-import <stream
 '
 
-test_expect_success 'v3 dumps not supported' '
+test_expect_success 'v4 dumps not supported' '
 	reinit_git &&
-	echo "SVN-fs-dump-format-version: 3" >input &&
-	test_must_fail test-svn-fe input >stream &&
+	echo "SVN-fs-dump-format-version: 4" >v4.dump &&
+	test_must_fail test-svn-fe v4.dump >stream &&
 	test_cmp empty stream
 '
 
+test_expect_failure 'empty revision' '
+	reinit_git &&
+	printf "rev <nobody, nobody@local>: %s\n" "" "" >expect &&
+	cat >emptyrev.dump <<-\EOF &&
+	SVN-fs-dump-format-version: 3
+
+	Revision-number: 1
+	Prop-content-length: 0
+	Content-length: 0
+
+	Revision-number: 2
+	Prop-content-length: 0
+	Content-length: 0
+
+	EOF
+	test-svn-fe emptyrev.dump >stream &&
+	git fast-import <stream &&
+	git log -p --format="rev <%an, %ae>: %s" HEAD >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'empty properties' '
+	reinit_git &&
+	printf "rev <nobody, nobody@local>: %s\n" "" "" >expect &&
+	cat >emptyprop.dump <<-\EOF &&
+	SVN-fs-dump-format-version: 3
+
+	Revision-number: 1
+	Prop-content-length: 10
+	Content-length: 10
+
+	PROPS-END
+
+	Revision-number: 2
+	Prop-content-length: 10
+	Content-length: 10
+
+	PROPS-END
+	EOF
+	test-svn-fe emptyprop.dump >stream &&
+	git fast-import <stream &&
+	git log -p --format="rev <%an, %ae>: %s" HEAD >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'author name and commit message' '
+	reinit_git &&
+	echo "<author@example.com, author@example.com@local>" >expect.author &&
+	cat >message <<-\EOF &&
+	A concise summary of the change
+
+	A detailed description of the change, why it is needed, what
+	was broken and why applying this is the best course of action.
+
+	* file.c
+	    Details pertaining to an individual file.
+	EOF
+	{
+		properties \
+			svn:author author@example.com \
+			svn:log "$(cat message)" &&
+		echo PROPS-END
+	} >props &&
+	{
+		echo "SVN-fs-dump-format-version: 3" &&
+		echo &&
+		echo "Revision-number: 1" &&
+		echo Prop-content-length: $(wc -c <props) &&
+		echo Content-length: $(wc -c <props) &&
+		echo &&
+		cat props
+	} >log.dump &&
+	test-svn-fe log.dump >stream &&
+	git fast-import <stream &&
+	git log -p --format="%B" HEAD >actual.log &&
+	git log --format="<%an, %ae>" >actual.author &&
+	test_cmp message actual.log &&
+	test_cmp expect.author actual.author
+'
+
+test_expect_success 'unsupported properties are ignored' '
+	reinit_git &&
+	echo author >expect &&
+	cat >extraprop.dump <<-\EOF &&
+	SVN-fs-dump-format-version: 3
+
+	Revision-number: 1
+	Prop-content-length: 56
+	Content-length: 56
+
+	K 8
+	nonsense
+	V 1
+	y
+	K 10
+	svn:author
+	V 6
+	author
+	PROPS-END
+	EOF
+	test-svn-fe extraprop.dump >stream &&
+	git fast-import <stream &&
+	git log -p --format=%an HEAD >actual &&
+	test_cmp expect actual
+'
+
+test_expect_failure 'timestamp and empty file' '
+	echo author@example.com >expect.author &&
+	echo 1999-01-01 >expect.date &&
+	echo file >expect.files &&
+	reinit_git &&
+	{
+		properties \
+			svn:author author@example.com \
+			svn:date "1999-01-01T00:01:002.000000Z" \
+			svn:log "add empty file" &&
+		echo PROPS-END
+	} >props &&
+	{
+		cat <<-EOF &&
+		SVN-fs-dump-format-version: 3
+
+		Revision-number: 1
+		EOF
+		echo Prop-content-length: $(wc -c <props) &&
+		echo Content-length: $(wc -c <props) &&
+		echo &&
+		cat props &&
+		cat <<-\EOF
+
+		Node-path: empty-file
+		Node-kind: file
+		Node-action: add
+		Content-length: 0
+
+		EOF
+	} >emptyfile.dump &&
+	test-svn-fe emptyfile.dump >stream &&
+	git fast-import <stream &&
+	git log --format=%an HEAD >actual.author &&
+	git log --date=short --format=%ad HEAD >actual.date &&
+	git ls-tree -r --name-only HEAD >actual.files &&
+	test_cmp expect.author actual.author &&
+	test_cmp expect.date actual.date &&
+	test_cmp expect.files actual.files &&
+	git checkout HEAD empty-file &&
+	test_cmp empty file
+'
+
+test_expect_success 'directory with files' '
+	reinit_git &&
+	printf "%s\n" directory/file1 directory/file2 >expect.files &&
+	echo hi >hi &&
+	echo hello >hello &&
+	{
+		properties \
+			svn:author author@example.com \
+			svn:date "1999-02-01T00:01:002.000000Z" \
+			svn:log "add directory with some files in it" &&
+		echo PROPS-END
+	} >props &&
+	{
+		cat <<-EOF &&
+		SVN-fs-dump-format-version: 3
+
+		Revision-number: 1
+		EOF
+		echo Prop-content-length: $(wc -c <props) &&
+		echo Content-length: $(wc -c <props) &&
+		echo &&
+		cat props &&
+		cat <<-\EOF &&
+
+		Node-path: directory
+		Node-kind: dir
+		Node-action: add
+		Prop-content-length: 10
+		Content-length: 10
+
+		PROPS-END
+
+		Node-path: directory/file1
+		Node-kind: file
+		Node-action: add
+		EOF
+		text_no_props hello &&
+		cat <<-\EOF &&
+		Node-path: directory/file2
+		Node-kind: file
+		Node-action: add
+		EOF
+		text_no_props hi
+	} >directory.dump &&
+	test-svn-fe directory.dump >stream &&
+	git fast-import <stream &&
+
+	git ls-tree -r --name-only HEAD >actual.files &&
+	git checkout HEAD directory &&
+	test_cmp expect.files actual.files &&
+	test_cmp hello directory/file1 &&
+	test_cmp hi directory/file2
+'
+
+test_expect_success 'node without action' '
+	cat >inaction.dump <<-\EOF &&
+	SVN-fs-dump-format-version: 3
+
+	Revision-number: 1
+	Prop-content-length: 10
+	Content-length: 10
+
+	PROPS-END
+
+	Node-path: directory
+	Node-kind: dir
+	Prop-content-length: 10
+	Content-length: 10
+
+	PROPS-END
+	EOF
+	test_must_fail test-svn-fe inaction.dump
+'
+
+test_expect_success 'action: add node without text' '
+	cat >textless.dump <<-\EOF &&
+	SVN-fs-dump-format-version: 3
+
+	Revision-number: 1
+	Prop-content-length: 10
+	Content-length: 10
+
+	PROPS-END
+
+	Node-path: textless
+	Node-kind: file
+	Node-action: add
+	Prop-content-length: 10
+	Content-length: 10
+
+	PROPS-END
+	EOF
+	test_must_fail test-svn-fe textless.dump
+'
+
+test_expect_failure 'change file mode but keep old content' '
+	reinit_git &&
+	cat >expect <<-\EOF &&
+	OBJID
+	:120000 100644 OBJID OBJID T	greeting
+	OBJID
+	:100644 120000 OBJID OBJID T	greeting
+	OBJID
+	:000000 100644 OBJID OBJID A	greeting
+	EOF
+	echo "link hello" >expect.blob &&
+	echo hello >hello &&
+	cat >filemode.dump <<-\EOF &&
+	SVN-fs-dump-format-version: 3
+
+	Revision-number: 1
+	Prop-content-length: 10
+	Content-length: 10
+
+	PROPS-END
+
+	Node-path: greeting
+	Node-kind: file
+	Node-action: add
+	Prop-content-length: 10
+	Text-content-length: 11
+	Content-length: 21
+
+	PROPS-END
+	link hello
+
+	Revision-number: 2
+	Prop-content-length: 10
+	Content-length: 10
+
+	PROPS-END
+
+	Node-path: greeting
+	Node-kind: file
+	Node-action: change
+	Prop-content-length: 33
+	Content-length: 33
+
+	K 11
+	svn:special
+	V 1
+	*
+	PROPS-END
+
+	Revision-number: 3
+	Prop-content-length: 10
+	Content-length: 10
+
+	PROPS-END
+
+	Node-path: greeting
+	Node-kind: file
+	Node-action: change
+	Prop-content-length: 10
+	Content-length: 10
+
+	PROPS-END
+	EOF
+	test-svn-fe filemode.dump >stream &&
+	git fast-import <stream &&
+	{
+		git rev-list HEAD |
+		git diff-tree --root --stdin |
+		sed "s/$_x40/OBJID/g"
+	} >actual &&
+	git show HEAD:greeting >actual.blob &&
+	git show HEAD^:greeting >actual.target &&
+	test_cmp expect actual &&
+	test_cmp expect.blob actual.blob &&
+	test_cmp hello actual.target
+'
+
+test_expect_success 'change file mode and reiterate content' '
+	reinit_git &&
+	cat >expect <<-\EOF &&
+	OBJID
+	:120000 100644 OBJID OBJID T	greeting
+	OBJID
+	:100644 120000 OBJID OBJID T	greeting
+	OBJID
+	:000000 100644 OBJID OBJID A	greeting
+	EOF
+	echo "link hello" >expect.blob &&
+	echo hello >hello &&
+	cat >filemode.dump <<-\EOF &&
+	SVN-fs-dump-format-version: 3
+
+	Revision-number: 1
+	Prop-content-length: 10
+	Content-length: 10
+
+	PROPS-END
+
+	Node-path: greeting
+	Node-kind: file
+	Node-action: add
+	Prop-content-length: 10
+	Text-content-length: 11
+	Content-length: 21
+
+	PROPS-END
+	link hello
+
+	Revision-number: 2
+	Prop-content-length: 10
+	Content-length: 10
+
+	PROPS-END
+
+	Node-path: greeting
+	Node-kind: file
+	Node-action: change
+	Prop-content-length: 33
+	Text-content-length: 11
+	Content-length: 44
+
+	K 11
+	svn:special
+	V 1
+	*
+	PROPS-END
+	link hello
+
+	Revision-number: 3
+	Prop-content-length: 10
+	Content-length: 10
+
+	PROPS-END
+
+	Node-path: greeting
+	Node-kind: file
+	Node-action: change
+	Prop-content-length: 10
+	Text-content-length: 11
+	Content-length: 21
+
+	PROPS-END
+	link hello
+	EOF
+	test-svn-fe filemode.dump >stream &&
+	git fast-import <stream &&
+	{
+		git rev-list HEAD |
+		git diff-tree --root --stdin |
+		sed "s/$_x40/OBJID/g"
+	} >actual &&
+	git show HEAD:greeting >actual.blob &&
+	git show HEAD^:greeting >actual.target &&
+	test_cmp expect actual &&
+	test_cmp expect.blob actual.blob &&
+	test_cmp hello actual.target
+'
+
+test_expect_success 'deltas not supported' '
+	{
+		# (old) h + (inline) ello + (old) \n
+		printf "SVNQ%b%b%s" "Q\003\006\005\004" "\001Q\0204\001\002" "ello" |
+		q_to_nul
+	} >delta &&
+	{
+		properties \
+			svn:author author@example.com \
+			svn:date "1999-01-05T00:01:002.000000Z" \
+			svn:log "add greeting" &&
+		echo PROPS-END
+	} >props &&
+	{
+		properties \
+			svn:author author@example.com \
+			svn:date "1999-01-06T00:01:002.000000Z" \
+			svn:log "change it" &&
+		echo PROPS-END
+	} >props2 &&
+	{
+		echo SVN-fs-dump-format-version: 3 &&
+		echo &&
+		echo Revision-number: 1 &&
+		echo Prop-content-length: $(wc -c <props) &&
+		echo Content-length: $(wc -c <props) &&
+		echo &&
+		cat props &&
+		cat <<-\EOF &&
+
+		Node-path: hello
+		Node-kind: file
+		Node-action: add
+		Prop-content-length: 10
+		Text-content-length: 3
+		Content-length: 13
+
+		PROPS-END
+		hi
+
+		EOF
+		echo Revision-number: 2 &&
+		echo Prop-content-length: $(wc -c <props2) &&
+		echo Content-length: $(wc -c <props2) &&
+		echo &&
+		cat props2 &&
+		cat <<-\EOF &&
+
+		Node-path: hello
+		Node-kind: file
+		Node-action: change
+		Text-delta: true
+		Prop-content-length: 10
+		EOF
+		echo Text-content-length: $(wc -c <delta) &&
+		echo Content-length: $((10 + $(wc -c <delta))) &&
+		echo &&
+		echo PROPS-END &&
+		cat delta
+	} >delta.dump &&
+	test_must_fail test-svn-fe delta.dump
+'
+
+test_expect_success 'property deltas supported' '
+	reinit_git &&
+	cat >expect <<-\EOF &&
+	OBJID
+	:100755 100644 OBJID OBJID M	script.sh
+	EOF
+	{
+		properties \
+			svn:author author@example.com \
+			svn:date "1999-03-06T00:01:002.000000Z" \
+			svn:log "make an executable, or chmod -x it" &&
+		echo PROPS-END
+	} >revprops &&
+	{
+		echo SVN-fs-dump-format-version: 3 &&
+		echo &&
+		echo Revision-number: 1 &&
+		echo Prop-content-length: $(wc -c <revprops) &&
+		echo Content-length: $(wc -c <revprops) &&
+		echo &&
+		cat revprops &&
+		echo &&
+		cat <<-\EOF &&
+		Node-path: script.sh
+		Node-kind: file
+		Node-action: add
+		Text-content-length: 0
+		Prop-content-length: 39
+		Content-length: 39
+
+		K 14
+		svn:executable
+		V 4
+		true
+		PROPS-END
+
+		EOF
+		echo Revision-number: 2 &&
+		echo Prop-content-length: $(wc -c <revprops) &&
+		echo Content-length: $(wc -c <revprops) &&
+		echo &&
+		cat revprops &&
+		echo &&
+		cat <<-\EOF
+		Node-path: script.sh
+		Node-kind: file
+		Node-action: change
+		Prop-delta: true
+		Prop-content-length: 30
+		Content-length: 30
+
+		D 14
+		svn:executable
+		PROPS-END
+		EOF
+	} >propdelta.dump &&
+	test-svn-fe propdelta.dump >stream &&
+	git fast-import <stream &&
+	{
+		git rev-list HEAD |
+		git diff-tree --stdin |
+		sed "s/$_x40/OBJID/g"
+	} >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'properties on /' '
+	reinit_git &&
+	cat <<-\EOF >expect &&
+	OBJID
+	OBJID
+	:000000 100644 OBJID OBJID A	greeting
+	EOF
+	sed -e "s/X$//" <<-\EOF >changeroot.dump &&
+	SVN-fs-dump-format-version: 3
+
+	Revision-number: 1
+	Prop-content-length: 10
+	Content-length: 10
+
+	PROPS-END
+
+	Node-path: greeting
+	Node-kind: file
+	Node-action: add
+	Text-content-length: 0
+	Prop-content-length: 10
+	Content-length: 10
+
+	PROPS-END
+
+	Revision-number: 2
+	Prop-content-length: 10
+	Content-length: 10
+
+	PROPS-END
+
+	Node-path: X
+	Node-kind: dir
+	Node-action: change
+	Prop-delta: true
+	Prop-content-length: 43
+	Content-length: 43
+
+	K 10
+	svn:ignore
+	V 11
+	build-area
+
+	PROPS-END
+	EOF
+	test-svn-fe changeroot.dump >stream &&
+	git fast-import <stream &&
+	{
+		git rev-list HEAD |
+		git diff-tree --root --always --stdin |
+		sed "s/$_x40/OBJID/g"
+	} >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'deltas for typechange' '
+	reinit_git &&
+	cat >expect <<-\EOF &&
+	OBJID
+	:120000 100644 OBJID OBJID T	test-file
+	OBJID
+	:100755 120000 OBJID OBJID T	test-file
+	OBJID
+	:000000 100755 OBJID OBJID A	test-file
+	EOF
+	cat >deleteprop.dump <<-\EOF &&
+	SVN-fs-dump-format-version: 3
+
+	Revision-number: 1
+	Prop-content-length: 10
+	Content-length: 10
+
+	PROPS-END
+
+	Node-path: test-file
+	Node-kind: file
+	Node-action: add
+	Prop-delta: true
+	Prop-content-length: 35
+	Text-content-length: 17
+	Content-length: 52
+
+	K 14
+	svn:executable
+	V 0
+
+	PROPS-END
+	link testing 123
+
+	Revision-number: 2
+	Prop-content-length: 10
+	Content-length: 10
+
+	PROPS-END
+
+	Node-path: test-file
+	Node-kind: file
+	Node-action: change
+	Prop-delta: true
+	Prop-content-length: 53
+	Text-content-length: 17
+	Content-length: 70
+
+	K 11
+	svn:special
+	V 1
+	*
+	D 14
+	svn:executable
+	PROPS-END
+	link testing 231
+
+	Revision-number: 3
+	Prop-content-length: 10
+	Content-length: 10
+
+	PROPS-END
+
+	Node-path: test-file
+	Node-kind: file
+	Node-action: change
+	Prop-delta: true
+	Prop-content-length: 27
+	Text-content-length: 17
+	Content-length: 44
+
+	D 11
+	svn:special
+	PROPS-END
+	link testing 321
+	EOF
+	test-svn-fe deleteprop.dump >stream &&
+	git fast-import <stream &&
+	{
+		git rev-list HEAD |
+		git diff-tree --root --stdin |
+		sed "s/$_x40/OBJID/g"
+	} >actual &&
+	test_cmp expect actual
+'
+
+
 test_expect_success 'set up svn repo' '
 	svnconf=$PWD/svnconf &&
 	mkdir -p "$svnconf" &&
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index 52ac0e5..6b1ba6c 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -42,6 +42,14 @@
 
 >empty
 
+test_expect_success 'setup: have pipes?' '
+	rm -f frob &&
+	if mkfifo frob
+	then
+		test_set_prereq PIPE
+	fi
+'
+
 ###
 ### series A
 ###
@@ -898,6 +906,77 @@
 	 git diff-tree -C --find-copies-harder -r N4^ N4 >actual &&
 	 compare_diff_raw expect actual'
 
+test_expect_success PIPE 'N: read and copy directory' '
+	cat >expect <<-\EOF
+	:100755 100755 f1fb5da718392694d0076d677d6d0e364c79b0bc f1fb5da718392694d0076d677d6d0e364c79b0bc C100	file2/newf	file3/newf
+	:100644 100644 7123f7f44e39be127c5eb701e5968176ee9d78b1 7123f7f44e39be127c5eb701e5968176ee9d78b1 C100	file2/oldf	file3/oldf
+	EOF
+	git update-ref -d refs/heads/N4 &&
+	rm -f backflow &&
+	mkfifo backflow &&
+	(
+		exec <backflow &&
+		cat <<-EOF &&
+		commit refs/heads/N4
+		committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+		data <<COMMIT
+		copy by tree hash, part 2
+		COMMIT
+
+		from refs/heads/branch^0
+		ls "file2"
+		EOF
+		read mode type tree filename &&
+		echo "M 040000 $tree file3"
+	) |
+	git fast-import --cat-blob-fd=3 3>backflow &&
+	git diff-tree -C --find-copies-harder -r N4^ N4 >actual &&
+	compare_diff_raw expect actual
+'
+
+test_expect_success PIPE 'N: empty directory reads as missing' '
+	cat <<-\EOF >expect &&
+	OBJNAME
+	:000000 100644 OBJNAME OBJNAME A	unrelated
+	EOF
+	echo "missing src" >expect.response &&
+	git update-ref -d refs/heads/read-empty &&
+	rm -f backflow &&
+	mkfifo backflow &&
+	(
+		exec <backflow &&
+		cat <<-EOF &&
+		commit refs/heads/read-empty
+		committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+		data <<COMMIT
+		read "empty" (missing) directory
+		COMMIT
+
+		M 100644 inline src/greeting
+		data <<BLOB
+		hello
+		BLOB
+		C src/greeting dst1/non-greeting
+		C src/greeting unrelated
+		# leave behind "empty" src directory
+		D src/greeting
+		ls "src"
+		EOF
+		read -r line &&
+		printf "%s\n" "$line" >response &&
+		cat <<-\EOF
+		D dst1
+		D dst2
+		EOF
+	) |
+	git fast-import --cat-blob-fd=3 3>backflow &&
+	test_cmp expect.response response &&
+	git rev-list read-empty |
+	git diff-tree -r --root --stdin |
+	sed "s/$_x40/OBJNAME/g" >actual &&
+	test_cmp expect actual
+'
+
 test_expect_success \
 	'N: copy root directory by tree hash' \
 	'cat >expect <<-\EOF &&
@@ -1861,6 +1940,11 @@
     test_cmp marks.new non-relative.out
 '
 
+test_expect_success 'R: feature ls supported' '
+	echo "feature ls" |
+	git fast-import
+'
+
 test_expect_success 'R: feature cat-blob supported' '
 	echo "feature cat-blob" |
 	git fast-import
@@ -1986,14 +2070,6 @@
 	test_cmp expect actual
 '
 
-test_expect_success 'setup: have pipes?' '
-	rm -f frob &&
-	if mkfifo frob
-	then
-		test_set_prereq PIPE
-	fi
-'
-
 test_expect_success PIPE 'R: copy using cat-file' '
 	expect_id=$(git hash-object big) &&
 	expect_len=$(wc -c <big) &&
diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh
index 35c151d..afac5b5 100755
--- a/t/t9500-gitweb-standalone-no-errors.sh
+++ b/t/t9500-gitweb-standalone-no-errors.sh
@@ -446,6 +446,8 @@
 test_expect_success \
 	'encode(commit): utf8' \
 	'. "$TEST_DIRECTORY"/t3901-utf8.txt &&
+	 test_when_finished "GIT_AUTHOR_NAME=\"A U Thor\"" &&
+	 test_when_finished "GIT_COMMITTER_NAME=\"C O Mitter\"" &&
 	 echo "UTF-8" >> file &&
 	 git add file &&
 	 git commit -F "$TEST_DIRECTORY"/t3900/1-UTF-8.txt &&
@@ -454,11 +456,13 @@
 test_expect_success \
 	'encode(commit): iso-8859-1' \
 	'. "$TEST_DIRECTORY"/t3901-8859-1.txt &&
+	 test_when_finished "GIT_AUTHOR_NAME=\"A U Thor\"" &&
+	 test_when_finished "GIT_COMMITTER_NAME=\"C O Mitter\"" &&
 	 echo "ISO-8859-1" >> file &&
 	 git add file &&
 	 git config i18n.commitencoding ISO-8859-1 &&
+	 test_when_finished "git config --unset i18n.commitencoding" &&
 	 git commit -F "$TEST_DIRECTORY"/t3900/ISO8859-1.txt &&
-	 git config --unset i18n.commitencoding &&
 	 gitweb_run "p=.git;a=commit"'
 
 test_expect_success \
diff --git a/t/t9700/test.pl b/t/t9700/test.pl
index c15ca2d..13ba96e 100755
--- a/t/t9700/test.pl
+++ b/t/t9700/test.pl
@@ -113,6 +113,16 @@
 my $dir_commit = $r2->command_oneline('log', '-n1', '--pretty=format:%H', '.');
 isnt($last_commit, $dir_commit, 'log . does not show last commit');
 
+# commands outside working tree
+chdir($abs_repo_dir . '/..');
+my $r3 = Git->repository(Directory => $abs_repo_dir);
+my $tmpfile3 = "$abs_repo_dir/file3.tmp";
+open TEMPFILE3, "+>$tmpfile3" or die "Can't open $tmpfile3: $!";
+is($r3->cat_blob($file1hash, \*TEMPFILE3), 15, "cat_blob(outside): size");
+close TEMPFILE3;
+unlink $tmpfile3;
+chdir($abs_repo_dir);
+
 printf "1..%d\n", Test::More->builder->current_test;
 
 my $is_passing = eval { Test::More->is_passing };
diff --git a/t/t9800-git-p4.sh b/t/t9800-git-p4.sh
new file mode 100755
index 0000000..abe7c64
--- /dev/null
+++ b/t/t9800-git-p4.sh
@@ -0,0 +1,116 @@
+#!/bin/sh
+
+test_description='git-p4 tests'
+
+. ./test-lib.sh
+
+( p4 -h && p4d -h ) >/dev/null 2>&1 || {
+	skip_all='skipping git-p4 tests; no p4 or p4d'
+	test_done
+}
+
+GITP4=$GIT_BUILD_DIR/contrib/fast-import/git-p4
+P4DPORT=10669
+
+db="$TRASH_DIRECTORY/db"
+cli="$TRASH_DIRECTORY/cli"
+git="$TRASH_DIRECTORY/git"
+
+test_debug 'echo p4d -q -d -r "$db" -p $P4DPORT'
+test_expect_success setup '
+	mkdir -p "$db" &&
+	p4d -q -d -r "$db" -p $P4DPORT &&
+	mkdir -p "$cli" &&
+	mkdir -p "$git" &&
+	export P4PORT=localhost:$P4DPORT
+'
+
+test_expect_success 'add p4 files' '
+	cd "$cli" &&
+	p4 client -i <<-EOF &&
+	Client: client
+	Description: client
+	Root: $cli
+	View: //depot/... //client/...
+	EOF
+	export P4CLIENT=client &&
+	echo file1 >file1 &&
+	p4 add file1 &&
+	p4 submit -d "file1" &&
+	echo file2 >file2 &&
+	p4 add file2 &&
+	p4 submit -d "file2" &&
+	cd "$TRASH_DIRECTORY"
+'
+
+test_expect_success 'basic git-p4 clone' '
+	"$GITP4" clone --dest="$git" //depot &&
+	cd "$git" &&
+	git log --oneline >lines &&
+	test_line_count = 1 lines &&
+	cd .. &&
+	rm -rf "$git" && mkdir "$git"
+'
+
+test_expect_success 'git-p4 clone @all' '
+	"$GITP4" clone --dest="$git" //depot@all &&
+	cd "$git" &&
+	git log --oneline >lines &&
+	test_line_count = 2 lines &&
+	cd .. &&
+	rm -rf "$git" && mkdir "$git"
+'
+
+test_expect_success 'exit when p4 fails to produce marshaled output' '
+	badp4dir="$TRASH_DIRECTORY/badp4dir" &&
+	mkdir -p "$badp4dir" &&
+	cat >"$badp4dir"/p4 <<-EOF &&
+	#!$SHELL_PATH
+	exit 1
+	EOF
+	chmod 755 "$badp4dir"/p4 &&
+	PATH="$badp4dir:$PATH" "$GITP4" clone --dest="$git" //depot >errs 2>&1 ; retval=$? &&
+	test $retval -eq 1 &&
+	test_must_fail grep -q Traceback errs
+'
+
+test_expect_success 'add p4 files with wildcards in the names' '
+	cd "$cli" &&
+	echo file-wild-hash >file-wild#hash &&
+	echo file-wild-star >file-wild\*star &&
+	echo file-wild-at >file-wild@at &&
+	echo file-wild-percent >file-wild%percent &&
+	p4 add -f file-wild* &&
+	p4 submit -d "file wildcards" &&
+	cd "$TRASH_DIRECTORY"
+'
+
+test_expect_success 'wildcard files git-p4 clone' '
+	"$GITP4" clone --dest="$git" //depot &&
+	cd "$git" &&
+	test -f file-wild#hash &&
+	test -f file-wild\*star &&
+	test -f file-wild@at &&
+	test -f file-wild%percent &&
+	cd "$TRASH_DIRECTORY" &&
+	rm -rf "$git" && mkdir "$git"
+'
+
+test_expect_success 'clone bare' '
+	"$GITP4" clone --dest="$git" --bare //depot &&
+	cd "$git" &&
+	test ! -d .git &&
+	bare=`git config --get core.bare` &&
+	test "$bare" = true &&
+	cd "$TRASH_DIRECTORY" &&
+	rm -rf "$git" && mkdir "$git"
+'
+
+test_expect_success 'shutdown' '
+	pid=`pgrep -f p4d` &&
+	test -n "$pid" &&
+	test_debug "ps wl `echo $pid`" &&
+	kill $pid
+'
+
+test_done
diff --git a/t/valgrind/default.supp b/t/valgrind/default.supp
index 9e013fa..0a6724f 100644
--- a/t/valgrind/default.supp
+++ b/t/valgrind/default.supp
@@ -43,3 +43,9 @@
 	fun:write_buffer
 	fun:write_loose_object
 }
+
+{
+	ignore-sse-strlen-invalid-read-size
+	Memcheck:Addr4
+	fun:copy_ref
+}
diff --git a/test-line-buffer.c b/test-line-buffer.c
index c11bf7f..25b20b9 100644
--- a/test-line-buffer.c
+++ b/test-line-buffer.c
@@ -1,14 +1,9 @@
 /*
  * test-line-buffer.c: code to exercise the svn importer's input helper
- *
- * Input format:
- *	number NL
- *	(number bytes) NL
- *	number NL
- *	...
  */
 
 #include "git-compat-util.h"
+#include "strbuf.h"
 #include "vcs-svn/line_buffer.h"
 
 static uint32_t strtouint32(const char *s)
@@ -20,27 +15,84 @@
 	return (uint32_t) n;
 }
 
+static void handle_command(const char *command, const char *arg, struct line_buffer *buf)
+{
+	switch (*command) {
+	case 'b':
+		if (!prefixcmp(command, "binary ")) {
+			struct strbuf sb = STRBUF_INIT;
+			strbuf_addch(&sb, '>');
+			buffer_read_binary(buf, &sb, strtouint32(arg));
+			fwrite(sb.buf, 1, sb.len, stdout);
+			strbuf_release(&sb);
+			return;
+		}
+	case 'c':
+		if (!prefixcmp(command, "copy ")) {
+			buffer_copy_bytes(buf, strtouint32(arg));
+			return;
+		}
+	case 'r':
+		if (!prefixcmp(command, "read ")) {
+			const char *s = buffer_read_string(buf, strtouint32(arg));
+			fputs(s, stdout);
+			return;
+		}
+	case 's':
+		if (!prefixcmp(command, "skip ")) {
+			buffer_skip_bytes(buf, strtouint32(arg));
+			return;
+		}
+	default:
+		die("unrecognized command: %s", command);
+	}
+}
+
+static void handle_line(const char *line, struct line_buffer *stdin_buf)
+{
+	const char *arg = strchr(line, ' ');
+	if (!arg)
+		die("no argument in line: %s", line);
+	handle_command(line, arg + 1, stdin_buf);
+}
+
 int main(int argc, char *argv[])
 {
+	struct line_buffer stdin_buf = LINE_BUFFER_INIT;
+	struct line_buffer file_buf = LINE_BUFFER_INIT;
+	struct line_buffer *input = &stdin_buf;
+	const char *filename;
 	char *s;
 
-	if (argc != 1)
-		usage("test-line-buffer < input.txt");
-	if (buffer_init(NULL))
+	if (argc == 1)
+		filename = NULL;
+	else if (argc == 2)
+		filename = argv[1];
+	else
+		usage("test-line-buffer [file | &fd] < script");
+
+	if (buffer_init(&stdin_buf, NULL))
 		die_errno("open error");
-	while ((s = buffer_read_line())) {
-		s = buffer_read_string(strtouint32(s));
-		fputs(s, stdout);
-		fputc('\n', stdout);
-		buffer_skip_bytes(1);
-		if (!(s = buffer_read_line()))
-			break;
-		buffer_copy_bytes(strtouint32(s) + 1);
+	if (filename) {
+		if (*filename == '&') {
+			if (buffer_fdinit(&file_buf, strtouint32(filename + 1)))
+				die_errno("error opening fd %s", filename + 1);
+		} else {
+			if (buffer_init(&file_buf, filename))
+				die_errno("error opening %s", filename);
+		}
+		input = &file_buf;
 	}
-	if (buffer_deinit())
+
+	while ((s = buffer_read_line(&stdin_buf)))
+		handle_line(s, input);
+
+	if (filename && buffer_deinit(&file_buf))
+		die("error reading from %s", filename);
+	if (buffer_deinit(&stdin_buf))
 		die("input error");
 	if (ferror(stdout))
 		die("output error");
-	buffer_reset();
+	buffer_reset(&stdin_buf);
 	return 0;
 }
diff --git a/test-parse-options.c b/test-parse-options.c
index 0828592..4e3710b 100644
--- a/test-parse-options.c
+++ b/test-parse-options.c
@@ -46,7 +46,7 @@
 		OPT_DATE('t', NULL, &timestamp, "get timestamp of <time>"),
 		OPT_CALLBACK('L', "length", &integer, "str",
 			"get length of <str>", length_callback),
-		OPT_FILENAME('F', "file", &file, "set file to <FILE>"),
+		OPT_FILENAME('F', "file", &file, "set file to <file>"),
 		OPT_GROUP("String options"),
 		OPT_STRING('s', "string", &string, "string", "get a string"),
 		OPT_STRING(0, "string2", &string, "str", "get another string"),
diff --git a/test-path-utils.c b/test-path-utils.c
index d261398..e767159 100644
--- a/test-path-utils.c
+++ b/test-path-utils.c
@@ -11,9 +11,9 @@
 		return 0;
 	}
 
-	if (argc >= 2 && !strcmp(argv[1], "make_absolute_path")) {
+	if (argc >= 2 && !strcmp(argv[1], "real_path")) {
 		while (argc > 2) {
-			puts(make_absolute_path(argv[2]));
+			puts(real_path(argv[2]));
 			argc--;
 			argv++;
 		}
diff --git a/test-svn-fe.c b/test-svn-fe.c
index 77cf78a..b42ba78 100644
--- a/test-svn-fe.c
+++ b/test-svn-fe.c
@@ -9,7 +9,8 @@
 {
 	if (argc != 2)
 		usage("test-svn-fe <file>");
-	svndump_init(argv[1]);
+	if (svndump_init(argv[1]))
+		return 1;
 	svndump_read(NULL);
 	svndump_deinit();
 	svndump_reset();
diff --git a/transport-helper.c b/transport-helper.c
index 4e4754c..0c5b1bd 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -12,8 +12,7 @@
 
 static int debug;
 
-struct helper_data
-{
+struct helper_data {
 	const char *name;
 	struct child_process *helper;
 	FILE *out;
@@ -973,7 +972,7 @@
  */
 static int udt_do_write(struct unidirectional_transfer *t)
 {
-	size_t bytes;
+	ssize_t bytes;
 
 	if (t->bufuse == 0)
 		return 0;	/* Nothing to write. */
diff --git a/tree-diff.c b/tree-diff.c
index 12c9a88..3954281 100644
--- a/tree-diff.c
+++ b/tree-diff.c
@@ -6,34 +6,18 @@
 #include "diffcore.h"
 #include "tree.h"
 
-static char *malloc_base(const char *base, int baselen, const char *path, int pathlen)
-{
-	char *newbase = xmalloc(baselen + pathlen + 2);
-	memcpy(newbase, base, baselen);
-	memcpy(newbase + baselen, path, pathlen);
-	memcpy(newbase + baselen + pathlen, "/", 2);
-	return newbase;
-}
+static void show_entry(struct diff_options *opt, const char *prefix,
+		       struct tree_desc *desc, struct strbuf *base);
 
-static char *malloc_fullname(const char *base, int baselen, const char *path, int pathlen)
-{
-	char *fullname = xmalloc(baselen + pathlen + 1);
-	memcpy(fullname, base, baselen);
-	memcpy(fullname + baselen, path, pathlen);
-	fullname[baselen + pathlen] = 0;
-	return fullname;
-}
-
-static void show_entry(struct diff_options *opt, const char *prefix, struct tree_desc *desc,
-		       const char *base, int baselen);
-
-static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const char *base, int baselen, struct diff_options *opt)
+static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2,
+			      struct strbuf *base, struct diff_options *opt)
 {
 	unsigned mode1, mode2;
 	const char *path1, *path2;
 	const unsigned char *sha1, *sha2;
 	int cmp, pathlen1, pathlen2;
-	char *fullname;
+	int old_baselen = base->len;
+	int retval = 0;
 
 	sha1 = tree_entry_extract(t1, &path1, &mode1);
 	sha2 = tree_entry_extract(t2, &path2, &mode2);
@@ -42,11 +26,11 @@
 	pathlen2 = tree_entry_len(path2, sha2);
 	cmp = base_name_compare(path1, pathlen1, mode1, path2, pathlen2, mode2);
 	if (cmp < 0) {
-		show_entry(opt, "-", t1, base, baselen);
+		show_entry(opt, "-", t1, base);
 		return -1;
 	}
 	if (cmp > 0) {
-		show_entry(opt, "+", t2, base, baselen);
+		show_entry(opt, "+", t2, base);
 		return 1;
 	}
 	if (!DIFF_OPT_TST(opt, FIND_COPIES_HARDER) && !hashcmp(sha1, sha2) && mode1 == mode2)
@@ -57,149 +41,29 @@
 	 * file, we need to consider it a remove and an add.
 	 */
 	if (S_ISDIR(mode1) != S_ISDIR(mode2)) {
-		show_entry(opt, "-", t1, base, baselen);
-		show_entry(opt, "+", t2, base, baselen);
+		show_entry(opt, "-", t1, base);
+		show_entry(opt, "+", t2, base);
 		return 0;
 	}
 
+	strbuf_add(base, path1, pathlen1);
 	if (DIFF_OPT_TST(opt, RECURSIVE) && S_ISDIR(mode1)) {
-		int retval;
-		char *newbase = malloc_base(base, baselen, path1, pathlen1);
 		if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE)) {
-			newbase[baselen + pathlen1] = 0;
 			opt->change(opt, mode1, mode2,
-				    sha1, sha2, newbase, 0, 0);
-			newbase[baselen + pathlen1] = '/';
+				    sha1, sha2, base->buf, 0, 0);
 		}
-		retval = diff_tree_sha1(sha1, sha2, newbase, opt);
-		free(newbase);
-		return retval;
+		strbuf_addch(base, '/');
+		retval = diff_tree_sha1(sha1, sha2, base->buf, opt);
+	} else {
+		opt->change(opt, mode1, mode2, sha1, sha2, base->buf, 0, 0);
 	}
-
-	fullname = malloc_fullname(base, baselen, path1, pathlen1);
-	opt->change(opt, mode1, mode2, sha1, sha2, fullname, 0, 0);
-	free(fullname);
+	strbuf_setlen(base, old_baselen);
 	return 0;
 }
 
-/*
- * Is a tree entry interesting given the pathspec we have?
- *
- * Pre-condition: baselen == 0 || base[baselen-1] == '/'
- *
- * Return:
- *  - 2 for "yes, and all subsequent entries will be"
- *  - 1 for yes
- *  - zero for no
- *  - negative for "no, and no subsequent entries will be either"
- */
-static int tree_entry_interesting(struct tree_desc *desc, const char *base, int baselen, struct diff_options *opt)
-{
-	const char *path;
-	const unsigned char *sha1;
-	unsigned mode;
-	int i;
-	int pathlen;
-	int never_interesting = -1;
-
-	if (!opt->nr_paths)
-		return 2;
-
-	sha1 = tree_entry_extract(desc, &path, &mode);
-
-	pathlen = tree_entry_len(path, sha1);
-
-	for (i = 0; i < opt->nr_paths; i++) {
-		const char *match = opt->paths[i];
-		int matchlen = opt->pathlens[i];
-		int m = -1; /* signals that we haven't called strncmp() */
-
-		if (baselen >= matchlen) {
-			/* If it doesn't match, move along... */
-			if (strncmp(base, match, matchlen))
-				continue;
-
-			/*
-			 * If the base is a subdirectory of a path which
-			 * was specified, all of them are interesting.
-			 */
-			if (!matchlen ||
-			    base[matchlen] == '/' ||
-			    match[matchlen - 1] == '/')
-				return 2;
-
-			/* Just a random prefix match */
-			continue;
-		}
-
-		/* Does the base match? */
-		if (strncmp(base, match, baselen))
-			continue;
-
-		match += baselen;
-		matchlen -= baselen;
-
-		if (never_interesting) {
-			/*
-			 * We have not seen any match that sorts later
-			 * than the current path.
-			 */
-
-			/*
-			 * Does match sort strictly earlier than path
-			 * with their common parts?
-			 */
-			m = strncmp(match, path,
-				    (matchlen < pathlen) ? matchlen : pathlen);
-			if (m < 0)
-				continue;
-
-			/*
-			 * If we come here even once, that means there is at
-			 * least one pathspec that would sort equal to or
-			 * later than the path we are currently looking at.
-			 * In other words, if we have never reached this point
-			 * after iterating all pathspecs, it means all
-			 * pathspecs are either outside of base, or inside the
-			 * base but sorts strictly earlier than the current
-			 * one.  In either case, they will never match the
-			 * subsequent entries.  In such a case, we initialized
-			 * the variable to -1 and that is what will be
-			 * returned, allowing the caller to terminate early.
-			 */
-			never_interesting = 0;
-		}
-
-		if (pathlen > matchlen)
-			continue;
-
-		if (matchlen > pathlen) {
-			if (match[pathlen] != '/')
-				continue;
-			if (!S_ISDIR(mode))
-				continue;
-		}
-
-		if (m == -1)
-			/*
-			 * we cheated and did not do strncmp(), so we do
-			 * that here.
-			 */
-			m = strncmp(match, path, pathlen);
-
-		/*
-		 * If common part matched earlier then it is a hit,
-		 * because we rejected the case where path is not a
-		 * leading directory and is shorter than match.
-		 */
-		if (!m)
-			return 1;
-	}
-	return never_interesting; /* No matches */
-}
-
 /* A whole sub-tree went away or appeared */
-static void show_tree(struct diff_options *opt, const char *prefix, struct tree_desc *desc, const char *base, int baselen)
+static void show_tree(struct diff_options *opt, const char *prefix,
+		      struct tree_desc *desc, struct strbuf *base)
 {
 	int all_interesting = 0;
 	while (desc->size) {
@@ -208,31 +72,32 @@
 		if (all_interesting)
 			show = 1;
 		else {
-			show = tree_entry_interesting(desc, base, baselen,
-						      opt);
+			show = tree_entry_interesting(&desc->entry, base, 0,
+						      &opt->pathspec);
 			if (show == 2)
 				all_interesting = 1;
 		}
 		if (show < 0)
 			break;
 		if (show)
-			show_entry(opt, prefix, desc, base, baselen);
+			show_entry(opt, prefix, desc, base);
 		update_tree_entry(desc);
 	}
 }
 
 /* A file entry went away or appeared */
-static void show_entry(struct diff_options *opt, const char *prefix, struct tree_desc *desc,
-		       const char *base, int baselen)
+static void show_entry(struct diff_options *opt, const char *prefix,
+		       struct tree_desc *desc, struct strbuf *base)
 {
 	unsigned mode;
 	const char *path;
 	const unsigned char *sha1 = tree_entry_extract(desc, &path, &mode);
 	int pathlen = tree_entry_len(path, sha1);
+	int old_baselen = base->len;
 
+	strbuf_add(base, path, pathlen);
 	if (DIFF_OPT_TST(opt, RECURSIVE) && S_ISDIR(mode)) {
 		enum object_type type;
-		char *newbase = malloc_base(base, baselen, path, pathlen);
 		struct tree_desc inner;
 		void *tree;
 		unsigned long size;
@@ -241,28 +106,25 @@
 		if (!tree || type != OBJ_TREE)
 			die("corrupt tree sha %s", sha1_to_hex(sha1));
 
-		if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE)) {
-			newbase[baselen + pathlen] = 0;
-			opt->add_remove(opt, *prefix, mode, sha1, newbase, 0);
-			newbase[baselen + pathlen] = '/';
-		}
+		if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE))
+			opt->add_remove(opt, *prefix, mode, sha1, base->buf, 0);
+
+		strbuf_addch(base, '/');
 
 		init_tree_desc(&inner, tree, size);
-		show_tree(opt, prefix, &inner, newbase, baselen + 1 + pathlen);
-
+		show_tree(opt, prefix, &inner, base);
 		free(tree);
-		free(newbase);
-	} else {
-		char *fullname = malloc_fullname(base, baselen, path, pathlen);
-		opt->add_remove(opt, prefix[0], mode, sha1, fullname, 0);
-		free(fullname);
-	}
+	} else
+		opt->add_remove(opt, prefix[0], mode, sha1, base->buf, 0);
+
+	strbuf_setlen(base, old_baselen);
 }
 
-static void skip_uninteresting(struct tree_desc *t, const char *base, int baselen, struct diff_options *opt, int *all_interesting)
+static void skip_uninteresting(struct tree_desc *t, struct strbuf *base,
+			       struct diff_options *opt, int *all_interesting)
 {
 	while (t->size) {
-		int show = tree_entry_interesting(t, base, baselen, opt);
+		int show = tree_entry_interesting(&t->entry, base, 0, &opt->pathspec);
 		if (show == 2)
 			*all_interesting = 1;
 		if (!show) {
@@ -276,37 +138,44 @@
 	}
 }
 
-int diff_tree(struct tree_desc *t1, struct tree_desc *t2, const char *base, struct diff_options *opt)
+int diff_tree(struct tree_desc *t1, struct tree_desc *t2,
+	      const char *base_str, struct diff_options *opt)
 {
-	int baselen = strlen(base);
+	struct strbuf base;
+	int baselen = strlen(base_str);
 	int all_t1_interesting = 0;
 	int all_t2_interesting = 0;
 
+	/* Enable recursion indefinitely */
+	opt->pathspec.recursive = DIFF_OPT_TST(opt, RECURSIVE);
+	opt->pathspec.max_depth = -1;
+
+	strbuf_init(&base, PATH_MAX);
+	strbuf_add(&base, base_str, baselen);
+
 	for (;;) {
 		if (DIFF_OPT_TST(opt, QUICK) &&
 		    DIFF_OPT_TST(opt, HAS_CHANGES))
 			break;
-		if (opt->nr_paths) {
+		if (opt->pathspec.nr) {
 			if (!all_t1_interesting)
-				skip_uninteresting(t1, base, baselen, opt,
-						   &all_t1_interesting);
+				skip_uninteresting(t1, &base, opt, &all_t1_interesting);
 			if (!all_t2_interesting)
-				skip_uninteresting(t2, base, baselen, opt,
-						   &all_t2_interesting);
+				skip_uninteresting(t2, &base, opt, &all_t2_interesting);
 		}
 		if (!t1->size) {
 			if (!t2->size)
 				break;
-			show_entry(opt, "+", t2, base, baselen);
+			show_entry(opt, "+", t2, &base);
 			update_tree_entry(t2);
 			continue;
 		}
 		if (!t2->size) {
-			show_entry(opt, "-", t1, base, baselen);
+			show_entry(opt, "-", t1, &base);
 			update_tree_entry(t1);
 			continue;
 		}
-		switch (compare_tree_entry(t1, t2, base, baselen, opt)) {
+		switch (compare_tree_entry(t1, t2, &base, opt)) {
 		case -1:
 			update_tree_entry(t1);
 			continue;
@@ -319,6 +188,8 @@
 		}
 		die("git diff-tree: internal error");
 	}
+
+	strbuf_release(&base);
 	return 0;
 }
 
@@ -349,7 +220,7 @@
 	DIFF_OPT_SET(&diff_opts, RECURSIVE);
 	DIFF_OPT_SET(&diff_opts, FIND_COPIES_HARDER);
 	diff_opts.output_format = DIFF_FORMAT_NO_OUTPUT;
-	diff_opts.single_follow = opt->paths[0];
+	diff_opts.single_follow = opt->pathspec.raw[0];
 	diff_opts.break_opt = opt->break_opt;
 	paths[0] = NULL;
 	diff_tree_setup_paths(paths, &diff_opts);
@@ -369,15 +240,16 @@
 		 * diff_queued_diff, we will also use that as the path in
 		 * the future!
 		 */
-		if ((p->status == 'R' || p->status == 'C') && !strcmp(p->two->path, opt->paths[0])) {
+		if ((p->status == 'R' || p->status == 'C') &&
+		    !strcmp(p->two->path, opt->pathspec.raw[0])) {
 			/* Switch the file-pairs around */
 			q->queue[i] = choice;
 			choice = p;
 
 			/* Update the path we use from now on.. */
 			diff_tree_release_paths(opt);
-			opt->paths[0] = xstrdup(p->one->path);
-			diff_tree_setup_paths(opt->paths, opt);
+			opt->pathspec.raw[0] = xstrdup(p->one->path);
+			diff_tree_setup_paths(opt->pathspec.raw, opt);
 
 			/*
 			 * The caller expects us to return a set of vanilla
@@ -452,36 +324,12 @@
 	return retval;
 }
 
-static int count_paths(const char **paths)
-{
-	int i = 0;
-	while (*paths++)
-		i++;
-	return i;
-}
-
 void diff_tree_release_paths(struct diff_options *opt)
 {
-	free(opt->pathlens);
+	free_pathspec(&opt->pathspec);
 }
 
 void diff_tree_setup_paths(const char **p, struct diff_options *opt)
 {
-	opt->nr_paths = 0;
-	opt->pathlens = NULL;
-	opt->paths = NULL;
-
-	if (p) {
-		int i;
-
-		opt->paths = p;
-		opt->nr_paths = count_paths(p);
-		if (opt->nr_paths == 0) {
-			opt->pathlens = NULL;
-			return;
-		}
-		opt->pathlens = xmalloc(opt->nr_paths * sizeof(int));
-		for (i=0; i < opt->nr_paths; i++)
-			opt->pathlens[i] = strlen(p[i]);
-	}
+	init_pathspec(&opt->pathspec, p);
 }
diff --git a/tree-walk.c b/tree-walk.c
index a9bbf4e..322becc 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -1,6 +1,7 @@
 #include "cache.h"
 #include "tree-walk.h"
 #include "unpack-trees.h"
+#include "dir.h"
 #include "tree.h"
 
 static const char *get_mode(const char *str, unsigned int *modep)
@@ -455,3 +456,186 @@
 	free(tree);
 	return retval;
 }
+
+static int match_entry(const struct name_entry *entry, int pathlen,
+		       const char *match, int matchlen,
+		       int *never_interesting)
+{
+	int m = -1; /* signals that we haven't called strncmp() */
+
+	if (*never_interesting) {
+		/*
+		 * We have not seen any match that sorts later
+		 * than the current path.
+		 */
+
+		/*
+		 * Does match sort strictly earlier than path
+		 * with their common parts?
+		 */
+		m = strncmp(match, entry->path,
+			    (matchlen < pathlen) ? matchlen : pathlen);
+		if (m < 0)
+			return 0;
+
+		/*
+		 * If we come here even once, that means there is at
+		 * least one pathspec that would sort equal to or
+		 * later than the path we are currently looking at.
+		 * In other words, if we have never reached this point
+		 * after iterating all pathspecs, it means all
+		 * pathspecs are either outside of base, or inside the
+		 * base but sorts strictly earlier than the current
+		 * one.  In either case, they will never match the
+		 * subsequent entries.  In such a case, we initialized
+		 * the variable to -1 and that is what will be
+		 * returned, allowing the caller to terminate early.
+		 */
+		*never_interesting = 0;
+	}
+
+	if (pathlen > matchlen)
+		return 0;
+
+	if (matchlen > pathlen) {
+		if (match[pathlen] != '/')
+			return 0;
+		if (!S_ISDIR(entry->mode))
+			return 0;
+	}
+
+	if (m == -1)
+		/*
+		 * we cheated and did not do strncmp(), so we do
+		 * that here.
+		 */
+		m = strncmp(match, entry->path, pathlen);
+
+	/*
+	 * If common part matched earlier then it is a hit,
+	 * because we rejected the case where path is not a
+	 * leading directory and is shorter than match.
+	 */
+	if (!m)
+		return 1;
+
+	return 0;
+}
+
+static int match_dir_prefix(const char *base, int baselen,
+			    const char *match, int matchlen)
+{
+	if (strncmp(base, match, matchlen))
+		return 0;
+
+	/*
+	 * If the base is a subdirectory of a path which
+	 * was specified, all of them are interesting.
+	 */
+	if (!matchlen ||
+	    base[matchlen] == '/' ||
+	    match[matchlen - 1] == '/')
+		return 1;
+
+	/* Just a random prefix match */
+	return 0;
+}
+
+/*
+ * Is a tree entry interesting given the pathspec we have?
+ *
+ * Pre-condition: either baselen == base_offset (i.e. empty path)
+ * or base[baselen-1] == '/' (i.e. with trailing slash).
+ *
+ * Return:
+ *  - 2 for "yes, and all subsequent entries will be"
+ *  - 1 for yes
+ *  - zero for no
+ *  - negative for "no, and no subsequent entries will be either"
+ */
+int tree_entry_interesting(const struct name_entry *entry,
+			   struct strbuf *base, int base_offset,
+			   const struct pathspec *ps)
+{
+	int i;
+	int pathlen, baselen = base->len - base_offset;
+	int never_interesting = ps->has_wildcard ? 0 : -1;
+
+	if (!ps->nr) {
+		if (!ps->recursive || ps->max_depth == -1)
+			return 2;
+		return !!within_depth(base->buf + base_offset, baselen,
+				      !!S_ISDIR(entry->mode),
+				      ps->max_depth);
+	}
+
+	pathlen = tree_entry_len(entry->path, entry->sha1);
+
+	for (i = ps->nr - 1; i >= 0; i--) {
+		const struct pathspec_item *item = ps->items+i;
+		const char *match = item->match;
+		const char *base_str = base->buf + base_offset;
+		int matchlen = item->len;
+
+		if (baselen >= matchlen) {
+			/* If it doesn't match, move along... */
+			if (!match_dir_prefix(base_str, baselen, match, matchlen))
+				goto match_wildcards;
+
+			if (!ps->recursive || ps->max_depth == -1)
+				return 2;
+
+			return !!within_depth(base_str + matchlen + 1,
+					      baselen - matchlen - 1,
+					      !!S_ISDIR(entry->mode),
+					      ps->max_depth);
+		}
+
+		/* Does the base match? */
+		if (!strncmp(base_str, match, baselen)) {
+			if (match_entry(entry, pathlen,
+					match + baselen, matchlen - baselen,
+					&never_interesting))
+				return 1;
+
+			if (ps->items[i].has_wildcard) {
+				if (!fnmatch(match + baselen, entry->path, 0))
+					return 1;
+
+				/*
+				 * Match all directories. We'll try to
+				 * match files later on.
+				 */
+				if (ps->recursive && S_ISDIR(entry->mode))
+					return 1;
+			}
+
+			continue;
+		}
+
+match_wildcards:
+		if (!ps->items[i].has_wildcard)
+			continue;
+
+		/*
+		 * Concatenate base and entry->path into one and do
+		 * fnmatch() on it.
+		 */
+
+		strbuf_add(base, entry->path, pathlen);
+
+		if (!fnmatch(match, base->buf + base_offset, 0)) {
+			strbuf_setlen(base, base_offset + baselen);
+			return 1;
+		}
+		strbuf_setlen(base, base_offset + baselen);
+
+		/*
+		 * Match all directories. We'll try to match files
+		 * later on.
+		 */
+		if (ps->recursive && S_ISDIR(entry->mode))
+			return 1;
+	}
+	return never_interesting; /* No matches */
+}
diff --git a/tree-walk.h b/tree-walk.h
index 7e3e0b5..39524b7 100644
--- a/tree-walk.h
+++ b/tree-walk.h
@@ -60,4 +60,6 @@
 	return info->pathlen + tree_entry_len(n->path, n->sha1);
 }
 
+extern int tree_entry_interesting(const struct name_entry *, struct strbuf *, int, const struct pathspec *ps);
+
 #endif
diff --git a/utf8.c b/utf8.c
index 84cfc72..8acbc66 100644
--- a/utf8.c
+++ b/utf8.c
@@ -405,6 +405,15 @@
 	}
 }
 
+int strbuf_add_wrapped_bytes(struct strbuf *buf, const char *data, int len,
+			     int indent, int indent2, int width)
+{
+	char *tmp = xstrndup(data, len);
+	int r = strbuf_add_wrapped_text(buf, tmp, indent, indent2, width);
+	free(tmp);
+	return r;
+}
+
 int is_encoding_utf8(const char *name)
 {
 	if (!name)
diff --git a/utf8.h b/utf8.h
index ebc4d2f..81f2c82 100644
--- a/utf8.h
+++ b/utf8.h
@@ -10,6 +10,8 @@
 
 int strbuf_add_wrapped_text(struct strbuf *buf,
 		const char *text, int indent, int indent2, int width);
+int strbuf_add_wrapped_bytes(struct strbuf *buf, const char *data, int len,
+			     int indent, int indent2, int width);
 
 #ifndef NO_ICONV
 char *reencode_string(const char *in, const char *out_encoding, const char *in_encoding);
diff --git a/vcs-svn/fast_export.c b/vcs-svn/fast_export.c
index 6cfa256..260cf50 100644
--- a/vcs-svn/fast_export.c
+++ b/vcs-svn/fast_export.c
@@ -63,14 +63,14 @@
 	printf("progress Imported commit %"PRIu32".\n\n", revision);
 }
 
-void fast_export_blob(uint32_t mode, uint32_t mark, uint32_t len)
+void fast_export_blob(uint32_t mode, uint32_t mark, uint32_t len, struct line_buffer *input)
 {
 	if (mode == REPO_MODE_LNK) {
 		/* svn symlink blobs start with "link " */
-		buffer_skip_bytes(5);
+		buffer_skip_bytes(input, 5);
 		len -= 5;
 	}
 	printf("blob\nmark :%"PRIu32"\ndata %"PRIu32"\n", mark, len);
-	buffer_copy_bytes(len);
+	buffer_copy_bytes(input, len);
 	fputc('\n', stdout);
 }
diff --git a/vcs-svn/fast_export.h b/vcs-svn/fast_export.h
index 2aaaea5..054e7d5 100644
--- a/vcs-svn/fast_export.h
+++ b/vcs-svn/fast_export.h
@@ -1,11 +1,14 @@
 #ifndef FAST_EXPORT_H_
 #define FAST_EXPORT_H_
 
+#include "line_buffer.h"
+
 void fast_export_delete(uint32_t depth, uint32_t *path);
 void fast_export_modify(uint32_t depth, uint32_t *path, uint32_t mode,
 			uint32_t mark);
 void fast_export_commit(uint32_t revision, uint32_t author, char *log,
 			uint32_t uuid, uint32_t url, unsigned long timestamp);
-void fast_export_blob(uint32_t mode, uint32_t mark, uint32_t len);
+void fast_export_blob(uint32_t mode, uint32_t mark, uint32_t len,
+		      struct line_buffer *input);
 
 #endif
diff --git a/vcs-svn/line_buffer.c b/vcs-svn/line_buffer.c
index 1543567..aedf105 100644
--- a/vcs-svn/line_buffer.c
+++ b/vcs-svn/line_buffer.c
@@ -5,47 +5,76 @@
 
 #include "git-compat-util.h"
 #include "line_buffer.h"
-#include "obj_pool.h"
+#include "strbuf.h"
 
-#define LINE_BUFFER_LEN 10000
 #define COPY_BUFFER_LEN 4096
 
-/* Create memory pool for char sequence of known length */
-obj_pool_gen(blob, char, 4096)
-
-static char line_buffer[LINE_BUFFER_LEN];
-static char byte_buffer[COPY_BUFFER_LEN];
-static FILE *infile;
-
-int buffer_init(const char *filename)
+int buffer_init(struct line_buffer *buf, const char *filename)
 {
-	infile = filename ? fopen(filename, "r") : stdin;
-	if (!infile)
+	buf->infile = filename ? fopen(filename, "r") : stdin;
+	if (!buf->infile)
 		return -1;
 	return 0;
 }
 
-int buffer_deinit(void)
+int buffer_fdinit(struct line_buffer *buf, int fd)
+{
+	buf->infile = fdopen(fd, "r");
+	if (!buf->infile)
+		return -1;
+	return 0;
+}
+
+int buffer_tmpfile_init(struct line_buffer *buf)
+{
+	buf->infile = tmpfile();
+	if (!buf->infile)
+		return -1;
+	return 0;
+}
+
+int buffer_deinit(struct line_buffer *buf)
 {
 	int err;
-	if (infile == stdin)
-		return ferror(infile);
-	err = ferror(infile);
-	err |= fclose(infile);
+	if (buf->infile == stdin)
+		return ferror(buf->infile);
+	err = ferror(buf->infile);
+	err |= fclose(buf->infile);
 	return err;
 }
 
+FILE *buffer_tmpfile_rewind(struct line_buffer *buf)
+{
+	rewind(buf->infile);
+	return buf->infile;
+}
+
+long buffer_tmpfile_prepare_to_read(struct line_buffer *buf)
+{
+	long pos = ftell(buf->infile);
+	if (pos < 0)
+		return error("ftell error: %s", strerror(errno));
+	if (fseek(buf->infile, 0, SEEK_SET))
+		return error("seek error: %s", strerror(errno));
+	return pos;
+}
+
+int buffer_read_char(struct line_buffer *buf)
+{
+	return fgetc(buf->infile);
+}
+
 /* Read a line without trailing newline. */
-char *buffer_read_line(void)
+char *buffer_read_line(struct line_buffer *buf)
 {
 	char *end;
-	if (!fgets(line_buffer, sizeof(line_buffer), infile))
+	if (!fgets(buf->line_buffer, sizeof(buf->line_buffer), buf->infile))
 		/* Error or data exhausted. */
 		return NULL;
-	end = line_buffer + strlen(line_buffer);
+	end = buf->line_buffer + strlen(buf->line_buffer);
 	if (end[-1] == '\n')
 		end[-1] = '\0';
-	else if (feof(infile))
+	else if (feof(buf->infile))
 		; /* No newline at end of file.  That's fine. */
 	else
 		/*
@@ -54,44 +83,50 @@
 		 * but for now let's return an error.
 		 */
 		return NULL;
-	return line_buffer;
+	return buf->line_buffer;
 }
 
-char *buffer_read_string(uint32_t len)
+char *buffer_read_string(struct line_buffer *buf, uint32_t len)
 {
-	char *s;
-	blob_free(blob_pool.size);
-	s = blob_pointer(blob_alloc(len + 1));
-	s[fread(s, 1, len, infile)] = '\0';
-	return ferror(infile) ? NULL : s;
+	strbuf_reset(&buf->blob_buffer);
+	strbuf_fread(&buf->blob_buffer, len, buf->infile);
+	return ferror(buf->infile) ? NULL : buf->blob_buffer.buf;
 }
 
-void buffer_copy_bytes(uint32_t len)
+void buffer_read_binary(struct line_buffer *buf,
+				struct strbuf *sb, uint32_t size)
 {
+	strbuf_fread(sb, size, buf->infile);
+}
+
+void buffer_copy_bytes(struct line_buffer *buf, uint32_t len)
+{
+	char byte_buffer[COPY_BUFFER_LEN];
 	uint32_t in;
-	while (len > 0 && !feof(infile) && !ferror(infile)) {
+	while (len > 0 && !feof(buf->infile) && !ferror(buf->infile)) {
 		in = len < COPY_BUFFER_LEN ? len : COPY_BUFFER_LEN;
-		in = fread(byte_buffer, 1, in, infile);
+		in = fread(byte_buffer, 1, in, buf->infile);
 		len -= in;
 		fwrite(byte_buffer, 1, in, stdout);
 		if (ferror(stdout)) {
-			buffer_skip_bytes(len);
+			buffer_skip_bytes(buf, len);
 			return;
 		}
 	}
 }
 
-void buffer_skip_bytes(uint32_t len)
+void buffer_skip_bytes(struct line_buffer *buf, uint32_t len)
 {
+	char byte_buffer[COPY_BUFFER_LEN];
 	uint32_t in;
-	while (len > 0 && !feof(infile) && !ferror(infile)) {
+	while (len > 0 && !feof(buf->infile) && !ferror(buf->infile)) {
 		in = len < COPY_BUFFER_LEN ? len : COPY_BUFFER_LEN;
-		in = fread(byte_buffer, 1, in, infile);
+		in = fread(byte_buffer, 1, in, buf->infile);
 		len -= in;
 	}
 }
 
-void buffer_reset(void)
+void buffer_reset(struct line_buffer *buf)
 {
-	blob_reset();
+	strbuf_release(&buf->blob_buffer);
 }
diff --git a/vcs-svn/line_buffer.h b/vcs-svn/line_buffer.h
index 9c78ae1..96ce966 100644
--- a/vcs-svn/line_buffer.h
+++ b/vcs-svn/line_buffer.h
@@ -1,12 +1,31 @@
 #ifndef LINE_BUFFER_H_
 #define LINE_BUFFER_H_
 
-int buffer_init(const char *filename);
-int buffer_deinit(void);
-char *buffer_read_line(void);
-char *buffer_read_string(uint32_t len);
-void buffer_copy_bytes(uint32_t len);
-void buffer_skip_bytes(uint32_t len);
-void buffer_reset(void);
+#include "strbuf.h"
+
+#define LINE_BUFFER_LEN 10000
+
+struct line_buffer {
+	char line_buffer[LINE_BUFFER_LEN];
+	struct strbuf blob_buffer;
+	FILE *infile;
+};
+#define LINE_BUFFER_INIT {"", STRBUF_INIT, NULL}
+
+int buffer_init(struct line_buffer *buf, const char *filename);
+int buffer_fdinit(struct line_buffer *buf, int fd);
+int buffer_deinit(struct line_buffer *buf);
+void buffer_reset(struct line_buffer *buf);
+
+int buffer_tmpfile_init(struct line_buffer *buf);
+FILE *buffer_tmpfile_rewind(struct line_buffer *buf);	/* prepare to write. */
+long buffer_tmpfile_prepare_to_read(struct line_buffer *buf);
+
+char *buffer_read_line(struct line_buffer *buf);
+char *buffer_read_string(struct line_buffer *buf, uint32_t len);
+int buffer_read_char(struct line_buffer *buf);
+void buffer_read_binary(struct line_buffer *buf, struct strbuf *sb, uint32_t len);
+void buffer_copy_bytes(struct line_buffer *buf, uint32_t len);
+void buffer_skip_bytes(struct line_buffer *buf, uint32_t len);
 
 #endif
diff --git a/vcs-svn/line_buffer.txt b/vcs-svn/line_buffer.txt
index 8906fb1..e89cc41 100644
--- a/vcs-svn/line_buffer.txt
+++ b/vcs-svn/line_buffer.txt
@@ -14,22 +14,46 @@
 
 The calling program:
 
+ - initializes a `struct line_buffer` to LINE_BUFFER_INIT
  - specifies a file to read with `buffer_init`
  - processes input with `buffer_read_line`, `buffer_read_string`,
    `buffer_skip_bytes`, and `buffer_copy_bytes`
  - closes the file with `buffer_deinit`, perhaps to start over and
    read another file.
 
-Before exiting, the caller can use `buffer_reset` to deallocate
-resources for the benefit of profiling tools.
+When finished, the caller can use `buffer_reset` to deallocate
+resources.
+
+Using temporary files
+---------------------
+
+Temporary files provide a place to store data that should not outlive
+the calling program.  A program
+
+ - initializes a `struct line_buffer` to LINE_BUFFER_INIT
+ - requests a temporary file with `buffer_tmpfile_init`
+ - acquires an output handle by calling `buffer_tmpfile_rewind`
+ - uses standard I/O functions like `fprintf` and `fwrite` to fill
+   the temporary file
+ - declares writing is over with `buffer_tmpfile_prepare_to_read`
+ - can re-read what was written with `buffer_read_line`,
+   `buffer_read_string`, and so on
+ - can reuse the temporary file by calling `buffer_tmpfile_rewind`
+   again
+ - removes the temporary file with `buffer_deinit`, perhaps to
+   reuse the line_buffer for some other file.
+
+When finished, the calling program can use `buffer_reset` to deallocate
+resources.
 
 Functions
 ---------
 
-`buffer_init`::
-	Open the named file for input.  If filename is NULL,
-	start reading from stdin.  On failure, returns -1 (with
-	errno indicating the nature of the failure).
+`buffer_init`, `buffer_fdinit`::
+	Open the named file or file descriptor for input.
+	buffer_init(buf, NULL) prepares to read from stdin.
+	On failure, returns -1 (with errno indicating the nature
+	of the failure).
 
 `buffer_deinit`::
 	Stop reading from the current file (closing it unless
diff --git a/vcs-svn/repo_tree.c b/vcs-svn/repo_tree.c
index e3d1fa3..207ffc3 100644
--- a/vcs-svn/repo_tree.c
+++ b/vcs-svn/repo_tree.c
@@ -38,7 +38,7 @@
 static int repo_dirent_name_cmp(const void *a, const void *b);
 
 /* Treap for directory entries */
-trp_gen(static, dent_, struct repo_dirent, children, dent, repo_dirent_name_cmp);
+trp_gen(static, dent_, struct repo_dirent, children, dent, repo_dirent_name_cmp)
 
 uint32_t next_blob_mark(void)
 {
@@ -175,25 +175,18 @@
 	repo_write_dirent(path, mode, blob_mark, 0);
 }
 
-uint32_t repo_replace(uint32_t *path, uint32_t blob_mark)
-{
-	uint32_t mode = 0;
-	struct repo_dirent *src_dent;
-	src_dent = repo_read_dirent(active_commit, path);
-	if (src_dent != NULL) {
-		mode = src_dent->mode;
-		repo_write_dirent(path, mode, blob_mark, 0);
-	}
-	return mode;
-}
-
-void repo_modify(uint32_t *path, uint32_t mode, uint32_t blob_mark)
+uint32_t repo_modify_path(uint32_t *path, uint32_t mode, uint32_t blob_mark)
 {
 	struct repo_dirent *src_dent;
 	src_dent = repo_read_dirent(active_commit, path);
-	if (src_dent != NULL && blob_mark == 0)
+	if (!src_dent)
+		return 0;
+	if (!blob_mark)
 		blob_mark = src_dent->content_offset;
+	if (!mode)
+		mode = src_dent->mode;
 	repo_write_dirent(path, mode, blob_mark, 0);
+	return mode;
 }
 
 void repo_delete(uint32_t *path)
diff --git a/vcs-svn/repo_tree.h b/vcs-svn/repo_tree.h
index 5476175..68baeb5 100644
--- a/vcs-svn/repo_tree.h
+++ b/vcs-svn/repo_tree.h
@@ -14,8 +14,7 @@
 uint32_t next_blob_mark(void);
 uint32_t repo_copy(uint32_t revision, uint32_t *src, uint32_t *dst);
 void repo_add(uint32_t *path, uint32_t mode, uint32_t blob_mark);
-uint32_t repo_replace(uint32_t *path, uint32_t blob_mark);
-void repo_modify(uint32_t *path, uint32_t mode, uint32_t blob_mark);
+uint32_t repo_modify_path(uint32_t *path, uint32_t mode, uint32_t blob_mark);
 void repo_delete(uint32_t *path);
 void repo_commit(uint32_t revision, uint32_t author, char *log, uint32_t uuid,
 		 uint32_t url, long unsigned timestamp);
diff --git a/vcs-svn/string_pool.c b/vcs-svn/string_pool.c
index f5b1da8..8af8d54 100644
--- a/vcs-svn/string_pool.c
+++ b/vcs-svn/string_pool.c
@@ -30,7 +30,7 @@
 }
 
 /* Build a Treap from the node structure (a trp_node w/ offset) */
-trp_gen(static, tree_, struct node, children, node, node_cmp);
+trp_gen(static, tree_, struct node, children, node, node_cmp)
 
 const char *pool_fetch(uint32_t entry)
 {
diff --git a/vcs-svn/svndump.c b/vcs-svn/svndump.c
index 2ad2c30..ee7c0bb 100644
--- a/vcs-svn/svndump.c
+++ b/vcs-svn/svndump.c
@@ -30,7 +30,9 @@
 /* Create memory pool for log messages */
 obj_pool_gen(log, char, 4096)
 
-static char* log_copy(uint32_t length, char *log)
+static struct line_buffer input = LINE_BUFFER_INIT;
+
+static char *log_copy(uint32_t length, const char *log)
 {
 	char *buffer;
 	log_free(log_pool.size);
@@ -40,8 +42,9 @@
 }
 
 static struct {
-	uint32_t action, propLength, textLength, srcRev, srcMode, mark, type;
+	uint32_t action, propLength, textLength, srcRev, type;
 	uint32_t src[REPO_MAX_PATH_DEPTH], dst[REPO_MAX_PATH_DEPTH];
+	uint32_t text_delta, prop_delta;
 } node_ctx;
 
 static struct {
@@ -58,7 +61,9 @@
 	uint32_t svn_log, svn_author, svn_date, svn_executable, svn_special, uuid,
 		revision_number, node_path, node_kind, node_action,
 		node_copyfrom_path, node_copyfrom_rev, text_content_length,
-		prop_content_length, content_length, svn_fs_dump_format_version;
+		prop_content_length, content_length, svn_fs_dump_format_version,
+		/* version 3 format */
+		text_delta, prop_delta;
 } keys;
 
 static void reset_node_ctx(char *fname)
@@ -69,9 +74,9 @@
 	node_ctx.textLength = LENGTH_UNKNOWN;
 	node_ctx.src[0] = ~0;
 	node_ctx.srcRev = 0;
-	node_ctx.srcMode = 0;
 	pool_tok_seq(REPO_MAX_PATH_DEPTH, node_ctx.dst, "/", fname);
-	node_ctx.mark = 0;
+	node_ctx.text_delta = 0;
+	node_ctx.prop_delta = 0;
 }
 
 static void reset_rev_ctx(uint32_t revision)
@@ -107,81 +112,148 @@
 	keys.prop_content_length = pool_intern("Prop-content-length");
 	keys.content_length = pool_intern("Content-length");
 	keys.svn_fs_dump_format_version = pool_intern("SVN-fs-dump-format-version");
+	/* version 3 format (Subversion 1.1.0) */
+	keys.text_delta = pool_intern("Text-delta");
+	keys.prop_delta = pool_intern("Prop-delta");
+}
+
+static void handle_property(uint32_t key, const char *val, uint32_t len,
+				uint32_t *type_set)
+{
+	if (key == keys.svn_log) {
+		if (!val)
+			die("invalid dump: unsets svn:log");
+		/* Value length excludes terminating nul. */
+		rev_ctx.log = log_copy(len + 1, val);
+	} else if (key == keys.svn_author) {
+		rev_ctx.author = pool_intern(val);
+	} else if (key == keys.svn_date) {
+		if (!val)
+			die("invalid dump: unsets svn:date");
+		if (parse_date_basic(val, &rev_ctx.timestamp, NULL))
+			warning("invalid timestamp: %s", val);
+	} else if (key == keys.svn_executable || key == keys.svn_special) {
+		if (*type_set) {
+			if (!val)
+				return;
+			die("invalid dump: sets type twice");
+		}
+		if (!val) {
+			node_ctx.type = REPO_MODE_BLB;
+			return;
+		}
+		*type_set = 1;
+		node_ctx.type = key == keys.svn_executable ?
+				REPO_MODE_EXE :
+				REPO_MODE_LNK;
+	}
 }
 
 static void read_props(void)
 {
-	uint32_t len;
 	uint32_t key = ~0;
-	char *val = NULL;
-	char *t;
-	while ((t = buffer_read_line()) && strcmp(t, "PROPS-END")) {
-		if (!strncmp(t, "K ", 2)) {
-			len = atoi(&t[2]);
-			key = pool_intern(buffer_read_string(len));
-			buffer_read_line();
-		} else if (!strncmp(t, "V ", 2)) {
-			len = atoi(&t[2]);
-			val = buffer_read_string(len);
-			if (key == keys.svn_log) {
-				/* Value length excludes terminating nul. */
-				rev_ctx.log = log_copy(len + 1, val);
-			} else if (key == keys.svn_author) {
-				rev_ctx.author = pool_intern(val);
-			} else if (key == keys.svn_date) {
-				if (parse_date_basic(val, &rev_ctx.timestamp, NULL))
-					fprintf(stderr, "Invalid timestamp: %s\n", val);
-			} else if (key == keys.svn_executable) {
-				node_ctx.type = REPO_MODE_EXE;
-			} else if (key == keys.svn_special) {
-				node_ctx.type = REPO_MODE_LNK;
-			}
+	const char *t;
+	/*
+	 * NEEDSWORK: to support simple mode changes like
+	 *	K 11
+	 *	svn:special
+	 *	V 1
+	 *	*
+	 *	D 14
+	 *	svn:executable
+	 * we keep track of whether a mode has been set and reset to
+	 * plain file only if not.  We should be keeping track of the
+	 * symlink and executable bits separately instead.
+	 */
+	uint32_t type_set = 0;
+	while ((t = buffer_read_line(&input)) && strcmp(t, "PROPS-END")) {
+		uint32_t len;
+		const char *val;
+		const char type = t[0];
+
+		if (!type || t[1] != ' ')
+			die("invalid property line: %s\n", t);
+		len = atoi(&t[2]);
+		val = buffer_read_string(&input, len);
+		buffer_skip_bytes(&input, 1);	/* Discard trailing newline. */
+
+		switch (type) {
+		case 'K':
+			key = pool_intern(val);
+			continue;
+		case 'D':
+			key = pool_intern(val);
+			val = NULL;
+			len = 0;
+			/* fall through */
+		case 'V':
+			handle_property(key, val, len, &type_set);
 			key = ~0;
-			buffer_read_line();
+			continue;
+		default:
+			die("invalid property line: %s\n", t);
 		}
 	}
 }
 
 static void handle_node(void)
 {
-	if (node_ctx.propLength != LENGTH_UNKNOWN && node_ctx.propLength)
-		read_props();
+	uint32_t mark = 0;
+	const uint32_t type = node_ctx.type;
+	const int have_props = node_ctx.propLength != LENGTH_UNKNOWN;
 
-	if (node_ctx.srcRev)
-		node_ctx.srcMode = repo_copy(node_ctx.srcRev, node_ctx.src, node_ctx.dst);
-
-	if (node_ctx.textLength != LENGTH_UNKNOWN &&
-	    node_ctx.type != REPO_MODE_DIR)
-		node_ctx.mark = next_blob_mark();
-
+	if (node_ctx.text_delta)
+		die("text deltas not supported");
+	if (node_ctx.textLength != LENGTH_UNKNOWN)
+		mark = next_blob_mark();
 	if (node_ctx.action == NODEACT_DELETE) {
-		repo_delete(node_ctx.dst);
-	} else if (node_ctx.action == NODEACT_CHANGE ||
-			   node_ctx.action == NODEACT_REPLACE) {
-		if (node_ctx.action == NODEACT_REPLACE &&
-		    node_ctx.type == REPO_MODE_DIR)
-			repo_replace(node_ctx.dst, node_ctx.mark);
-		else if (node_ctx.propLength != LENGTH_UNKNOWN)
-			repo_modify(node_ctx.dst, node_ctx.type, node_ctx.mark);
-		else if (node_ctx.textLength != LENGTH_UNKNOWN)
-			node_ctx.srcMode = repo_replace(node_ctx.dst, node_ctx.mark);
-	} else if (node_ctx.action == NODEACT_ADD) {
-		if (node_ctx.srcRev && node_ctx.propLength != LENGTH_UNKNOWN)
-			repo_modify(node_ctx.dst, node_ctx.type, node_ctx.mark);
-		else if (node_ctx.srcRev && node_ctx.textLength != LENGTH_UNKNOWN)
-			node_ctx.srcMode = repo_replace(node_ctx.dst, node_ctx.mark);
-		else if ((node_ctx.type == REPO_MODE_DIR && !node_ctx.srcRev) ||
-			 node_ctx.textLength != LENGTH_UNKNOWN)
-			repo_add(node_ctx.dst, node_ctx.type, node_ctx.mark);
+		if (mark || have_props || node_ctx.srcRev)
+			die("invalid dump: deletion node has "
+				"copyfrom info, text, or properties");
+		return repo_delete(node_ctx.dst);
 	}
-
-	if (node_ctx.propLength == LENGTH_UNKNOWN && node_ctx.srcMode)
-		node_ctx.type = node_ctx.srcMode;
-
-	if (node_ctx.mark)
-		fast_export_blob(node_ctx.type, node_ctx.mark, node_ctx.textLength);
-	else if (node_ctx.textLength != LENGTH_UNKNOWN)
-		buffer_skip_bytes(node_ctx.textLength);
+	if (node_ctx.action == NODEACT_REPLACE) {
+		repo_delete(node_ctx.dst);
+		node_ctx.action = NODEACT_ADD;
+	}
+	if (node_ctx.srcRev) {
+		repo_copy(node_ctx.srcRev, node_ctx.src, node_ctx.dst);
+		if (node_ctx.action == NODEACT_ADD)
+			node_ctx.action = NODEACT_CHANGE;
+	}
+	if (mark && type == REPO_MODE_DIR)
+		die("invalid dump: directories cannot have text attached");
+	if (node_ctx.action == NODEACT_CHANGE && !~*node_ctx.dst) {
+		if (type != REPO_MODE_DIR)
+			die("invalid dump: root of tree is not a regular file");
+	} else if (node_ctx.action == NODEACT_CHANGE) {
+		uint32_t mode = repo_modify_path(node_ctx.dst, 0, mark);
+		if (!mode)
+			die("invalid dump: path to be modified is missing");
+		if (mode == REPO_MODE_DIR && type != REPO_MODE_DIR)
+			die("invalid dump: cannot modify a directory into a file");
+		if (mode != REPO_MODE_DIR && type == REPO_MODE_DIR)
+			die("invalid dump: cannot modify a file into a directory");
+		node_ctx.type = mode;
+	} else if (node_ctx.action == NODEACT_ADD) {
+		if (!mark && type != REPO_MODE_DIR)
+			die("invalid dump: adds node without text");
+		repo_add(node_ctx.dst, type, mark);
+	} else {
+		die("invalid dump: Node-path block lacks Node-action");
+	}
+	if (have_props) {
+		const uint32_t old_mode = node_ctx.type;
+		if (!node_ctx.prop_delta)
+			node_ctx.type = type;
+		if (node_ctx.propLength)
+			read_props();
+		if (node_ctx.type != old_mode)
+			repo_modify_path(node_ctx.dst, node_ctx.type, mark);
+	}
+	if (mark)
+		fast_export_blob(node_ctx.type, mark,
+				 node_ctx.textLength, &input);
 }
 
 static void handle_revision(void)
@@ -200,7 +272,7 @@
 	uint32_t key;
 
 	reset_dump_ctx(pool_intern(url));
-	while ((t = buffer_read_line())) {
+	while ((t = buffer_read_line(&input))) {
 		val = strstr(t, ": ");
 		if (!val)
 			continue;
@@ -210,8 +282,8 @@
 
 		if (key == keys.svn_fs_dump_format_version) {
 			dump_ctx.version = atoi(val);
-			if (dump_ctx.version > 2)
-				die("expected svn dump format version <= 2, found %"PRIu32,
+			if (dump_ctx.version > 3)
+				die("expected svn dump format version <= 3, found %"PRIu32,
 				    dump_ctx.version);
 		} else if (key == keys.uuid) {
 			dump_ctx.uuid = pool_intern(val);
@@ -255,9 +327,13 @@
 			node_ctx.textLength = atoi(val);
 		} else if (key == keys.prop_content_length) {
 			node_ctx.propLength = atoi(val);
+		} else if (key == keys.text_delta) {
+			node_ctx.text_delta = !strcmp(val, "true");
+		} else if (key == keys.prop_delta) {
+			node_ctx.prop_delta = !strcmp(val, "true");
 		} else if (key == keys.content_length) {
 			len = atoi(val);
-			buffer_read_line();
+			buffer_read_line(&input);
 			if (active_ctx == REV_CTX) {
 				read_props();
 			} else if (active_ctx == NODE_CTX) {
@@ -265,7 +341,7 @@
 				active_ctx = REV_CTX;
 			} else {
 				fprintf(stderr, "Unexpected content length header: %"PRIu32"\n", len);
-				buffer_skip_bytes(len);
+				buffer_skip_bytes(&input, len);
 			}
 		}
 	}
@@ -275,14 +351,16 @@
 		handle_revision();
 }
 
-void svndump_init(const char *filename)
+int svndump_init(const char *filename)
 {
-	buffer_init(filename);
+	if (buffer_init(&input, filename))
+		return error("cannot open %s: %s", filename, strerror(errno));
 	repo_init();
 	reset_dump_ctx(~0);
 	reset_rev_ctx(0);
 	reset_node_ctx(NULL);
 	init_keys();
+	return 0;
 }
 
 void svndump_deinit(void)
@@ -292,7 +370,7 @@
 	reset_dump_ctx(~0);
 	reset_rev_ctx(0);
 	reset_node_ctx(NULL);
-	if (buffer_deinit())
+	if (buffer_deinit(&input))
 		fprintf(stderr, "Input error\n");
 	if (ferror(stdout))
 		fprintf(stderr, "Output error\n");
@@ -301,7 +379,7 @@
 void svndump_reset(void)
 {
 	log_reset();
-	buffer_reset();
+	buffer_reset(&input);
 	repo_reset();
 	reset_dump_ctx(~0);
 	reset_rev_ctx(0);
diff --git a/vcs-svn/svndump.h b/vcs-svn/svndump.h
index 93c412f..df9ceb0 100644
--- a/vcs-svn/svndump.h
+++ b/vcs-svn/svndump.h
@@ -1,7 +1,7 @@
 #ifndef SVNDUMP_H_
 #define SVNDUMP_H_
 
-void svndump_init(const char *filename);
+int svndump_init(const char *filename);
 void svndump_read(const char *url);
 void svndump_deinit(void);
 void svndump_reset(void);
diff --git a/wrapper.c b/wrapper.c
index 4c147d6..2829000 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -209,7 +209,7 @@
 		if (!template[0])
 			template = origtemplate;
 
-		nonrelative_template = make_nonrelative_path(template);
+		nonrelative_template = absolute_path(template);
 		errno = saved_errno;
 		die_errno("Unable to create temporary file '%s'",
 			nonrelative_template);
@@ -344,7 +344,7 @@
 		if (!template[0])
 			template = origtemplate;
 
-		nonrelative_template = make_nonrelative_path(template);
+		nonrelative_template = absolute_path(template);
 		errno = saved_errno;
 		die_errno("Unable to create temporary file '%s'",
 			nonrelative_template);
diff --git a/wt-status.c b/wt-status.c
index 123582b..4daa8bb 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -60,7 +60,7 @@
 	color_fprintf_ln(s->fp, c, "# Unmerged paths:");
 	if (!advice_status_hints)
 		return;
-	if (s->in_merge)
+	if (s->whence != FROM_COMMIT)
 		;
 	else if (!s->is_initial)
 		color_fprintf_ln(s->fp, c, "#   (use \"git reset %s <file>...\" to unstage)", s->reference);
@@ -77,7 +77,7 @@
 	color_fprintf_ln(s->fp, c, "# Changes to be committed:");
 	if (!advice_status_hints)
 		return;
-	if (s->in_merge)
+	if (s->whence != FROM_COMMIT)
 		; /* NEEDSWORK: use "git reset --unresolve"??? */
 	else if (!s->is_initial)
 		color_fprintf_ln(s->fp, c, "#   (use \"git reset %s <file>...\" to unstage)", s->reference);
@@ -323,7 +323,7 @@
     }
 	rev.diffopt.format_callback = wt_status_collect_changed_cb;
 	rev.diffopt.format_callback_data = s;
-	rev.prune_data = s->pathspec;
+	init_pathspec(&rev.prune_data, s->pathspec);
 	run_diff_files(&rev, 0);
 }
 
@@ -348,20 +348,22 @@
 	rev.diffopt.detect_rename = 1;
 	rev.diffopt.rename_limit = 200;
 	rev.diffopt.break_opt = 0;
-	rev.prune_data = s->pathspec;
+	init_pathspec(&rev.prune_data, s->pathspec);
 	run_diff_index(&rev, 1);
 }
 
 static void wt_status_collect_changes_initial(struct wt_status *s)
 {
+	struct pathspec pathspec;
 	int i;
 
+	init_pathspec(&pathspec, s->pathspec);
 	for (i = 0; i < active_nr; i++) {
 		struct string_list_item *it;
 		struct wt_status_change_data *d;
 		struct cache_entry *ce = active_cache[i];
 
-		if (!ce_path_match(ce, s->pathspec))
+		if (!ce_path_match(ce, &pathspec))
 			continue;
 		it = string_list_insert(&s->change, ce->name);
 		d = it->util;
@@ -376,6 +378,7 @@
 		else
 			d->index_status = DIFF_STATUS_ADDED;
 	}
+	free_pathspec(&pathspec);
 }
 
 static void wt_status_collect_untracked(struct wt_status *s)
diff --git a/wt-status.h b/wt-status.h
index 20b17cf..cec482a 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -24,6 +24,13 @@
 	SHOW_ALL_UNTRACKED_FILES
 };
 
+/* from where does this commit originate */
+enum commit_whence {
+	FROM_COMMIT,     /* normal */
+	FROM_MERGE,      /* commit came from merge */
+	FROM_CHERRY_PICK /* commit came from cherry-pick */
+};
+
 struct wt_status_change_data {
 	int worktree_status;
 	int index_status;
@@ -40,7 +47,7 @@
 	const char **pathspec;
 	int verbose;
 	int amend;
-	int in_merge;
+	enum commit_whence whence;
 	int nowarn;
 	int use_color;
 	int relative_paths;