Merge branch 'dt/untracked-subdir' into maint

The experimental untracked-cache feature were buggy when paths with
a few levels of subdirectories are involved.

* dt/untracked-subdir:
  untracked cache: fix entry invalidation
  untracked-cache: fix subdirectory handling
  t7063: use --force-untracked-cache to speed up a bit
  untracked-cache: support sparse checkout
diff --git a/Documentation/RelNotes/2.2.3.txt b/Documentation/RelNotes/2.2.3.txt
new file mode 100644
index 0000000..5bfffa4
--- /dev/null
+++ b/Documentation/RelNotes/2.2.3.txt
@@ -0,0 +1,9 @@
+Git v2.2.3 Release Notes
+========================
+
+Fixes since v2.2.2
+------------------
+
+ * A handful of codepaths that used to use fixed-sized arrays to hold
+   pathnames have been corrected to use strbuf and other mechanisms to
+   allow longer pathnames without fearing overflows.
diff --git a/Documentation/RelNotes/2.3.9.txt b/Documentation/RelNotes/2.3.9.txt
new file mode 100644
index 0000000..1a2ad32
--- /dev/null
+++ b/Documentation/RelNotes/2.3.9.txt
@@ -0,0 +1,9 @@
+Git v2.3.9 Release Notes
+========================
+
+Fixes since v2.3.8
+------------------
+
+ * A handful of codepaths that used to use fixed-sized arrays to hold
+   pathnames have been corrected to use strbuf and other mechanisms to
+   allow longer pathnames without fearing overflows.
diff --git a/Documentation/RelNotes/2.4.8.txt b/Documentation/RelNotes/2.4.8.txt
new file mode 100644
index 0000000..ad946b2
--- /dev/null
+++ b/Documentation/RelNotes/2.4.8.txt
@@ -0,0 +1,21 @@
+Git v2.4.8 Release Notes
+========================
+
+Fixes since v2.4.7
+------------------
+
+ * Abandoning an already applied change in "git rebase -i" with
+   "--continue" left CHERRY_PICK_HEAD and confused later steps.
+
+ * Various fixes around "git am" that applies a patch to a history
+   that is not there yet.
+
+ * "git for-each-ref" reported "missing object" for 0{40} when it
+   encounters a broken ref.  The lack of object whose name is 0{40} is
+   not the problem; the ref being broken is.
+
+ * "git commit --cleanup=scissors" was not careful enough to protect
+   against getting fooled by a line that looked like scissors.
+
+Also contains typofixes, documentation updates and trivial code
+clean-ups.
diff --git a/Documentation/RelNotes/2.4.9.txt b/Documentation/RelNotes/2.4.9.txt
new file mode 100644
index 0000000..09af9dd
--- /dev/null
+++ b/Documentation/RelNotes/2.4.9.txt
@@ -0,0 +1,9 @@
+Git v2.4.9 Release Notes
+========================
+
+Fixes since v2.4.9
+------------------
+
+ * A handful of codepaths that used to use fixed-sized arrays to hold
+   pathnames have been corrected to use strbuf and other mechanisms to
+   allow longer pathnames without fearing overflows.
diff --git a/Documentation/RelNotes/2.5.1.txt b/Documentation/RelNotes/2.5.1.txt
new file mode 100644
index 0000000..b705533
--- /dev/null
+++ b/Documentation/RelNotes/2.5.1.txt
@@ -0,0 +1,65 @@
+Git v2.5.1 Release Notes
+========================
+
+Fixes since v2.5
+----------------
+
+ * Running an aliased command from a subdirectory when the .git thing
+   in the working tree is a gitfile pointing elsewhere did not work.
+
+ * Often a fast-import stream builds a new commit on top of the
+   previous commit it built, and it often unconditionally emits a
+   "from" command to specify the first parent, which can be omitted in
+   such a case.  This caused fast-import to forget the tree of the
+   previous commit and then re-read it from scratch, which was
+   inefficient.  Optimize for this common case.
+
+ * The "rev-parse --parseopt" mode parsed the option specification
+   and the argument hint in a strange way to allow '=' and other
+   special characters in the option name while forbidding them from
+   the argument hint.  This made it impossible to define an option
+   like "--pair <key>=<value>" with "pair=key=value" specification,
+   which instead would have defined a "--pair=key <value>" option.
+
+ * A "rebase" replays changes of the local branch on top of something
+   else, as such they are placed in stage #3 and referred to as
+   "theirs", while the changes in the new base, typically a foreign
+   work, are placed in stage #2 and referred to as "ours".  Clarify
+   the "checkout --ours/--theirs".
+
+ * An experimental "untracked cache" feature used uname(2) in a
+   slightly unportable way.
+
+ * "sparse checkout" misbehaved for a path that is excluded from the
+   checkout when switching between branches that differ at the path.
+
+ * The low-level "git send-pack" did not honor 'user.signingkey'
+   configuration variable when sending a signed-push.
+
+ * An attempt to delete a ref by pushing into a repository whose HEAD
+   symbolic reference points at an unborn branch that cannot be
+   created due to ref D/F conflict (e.g. refs/heads/a/b exists, HEAD
+   points at refs/heads/a) failed.
+
+ * "git subtree" (in contrib/) depended on "git log" output to be
+   stable, which was a no-no.  Apply a workaround to force a
+   particular date format.
+
+ * "git clone $URL" in recent releases of Git contains a regression in
+   the code that invents a new repository name incorrectly based on
+   the $URL.  This has been corrected.
+   (merge db2e220 jk/guess-repo-name-regression-fix later to maint).
+
+ * Running tests with the "-x" option to make them verbose had some
+   unpleasant interactions with other features of the test suite.
+   (merge 9b5fe78 jk/test-with-x later to maint).
+
+ * "git pull" in recent releases of Git has a regression in the code
+   that allows custom path to the --upload-pack=<program>.  This has
+   been corrected.
+
+ * pipe() emulation used in Git for Windows looked at a wrong variable
+   when checking for an error from an _open_osfhandle() call.
+
+Also contains typofixes, documentation updates and trivial code
+clean-ups.
diff --git a/Documentation/RelNotes/2.5.2.txt b/Documentation/RelNotes/2.5.2.txt
new file mode 100644
index 0000000..3f74939
--- /dev/null
+++ b/Documentation/RelNotes/2.5.2.txt
@@ -0,0 +1,63 @@
+Git v2.5.2 Release Notes
+========================
+
+Fixes since v2.5.1
+------------------
+
+ * "git init empty && git -C empty log" said "bad default revision 'HEAD'",
+   which was found to be a bit confusing to new users.
+
+ * The "interpret-trailers" helper mistook a multi-paragraph title of
+   a commit log message with a colon in it as the end of the trailer
+   block.
+
+ * When re-priming the cache-tree opportunistically while committing
+   the in-core index as-is, we mistakenly invalidated the in-core
+   index too aggressively, causing the experimental split-index code
+   to unnecessarily rewrite the on-disk index file(s).
+
+ * "git archive" did not use zip64 extension when creating an archive
+   with more than 64k entries, which nobody should need, right ;-)?
+
+ * The code in "multiple-worktree" support that attempted to recover
+   from an inconsistent state updated an incorrect file.
+
+ * "git rev-list" does not take "--notes" option, but did not complain
+   when one is given.
+
+ * Because the configuration system does not allow "alias.0foo" and
+   "pager.0foo" as the configuration key, the user cannot use '0foo'
+   as a custom command name anyway, but "git 0foo" tried to look these
+   keys up and emitted useless warnings before saying '0foo is not a
+   git command'.  These warning messages have been squelched.
+
+ * We recently rewrote one of the build scripts in Perl, which made it
+   necessary to have Perl to build Git.  Reduced Perl dependency by
+   rewriting it again using sed.
+
+ * t1509 test that requires a dedicated VM environment had some
+   bitrot, which has been corrected.
+
+ * strbuf_read() used to have one extra iteration (and an unnecessary
+   strbuf_grow() of 8kB), which was eliminated.
+
+ * The codepath to produce error messages had a hard-coded limit to
+   the size of the message, primarily to avoid memory allocation while
+   calling die().
+
+ * When trying to see that an object does not exist, a state errno
+   leaked from our "first try to open a packfile with O_NOATIME and
+   then if it fails retry without it" logic on a system that refuses
+   O_NOATIME.  This confused us and caused us to die, saying that the
+   packfile is unreadable, when we should have just reported that the
+   object does not exist in that packfile to the caller.
+
+ * An off-by-one error made "git remote" to mishandle a remote with a
+   single letter nickname.
+
+ * A handful of codepaths that used to use fixed-sized arrays to hold
+   pathnames have been corrected to use strbuf and other mechanisms to
+   allow longer pathnames without fearing overflows.
+
+Also contains typofixes, documentation updates and trivial code
+clean-ups.
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 43bb53c..a65cdd4 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -1298,7 +1298,7 @@
 	the refs that match the <pattern>.
 
 gc.reflogExpireUnreachable::
-gc.<ref>.reflogExpireUnreachable::
+gc.<pattern>.reflogExpireUnreachable::
 	'git reflog expire' removes reflog entries older than
 	this time and are not reachable from the current tip;
 	defaults to 30 days.  With "<pattern>" (e.g. "refs/stash")
diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index 63b739c..e269fb1 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -120,6 +120,21 @@
 --theirs::
 	When checking out paths from the index, check out stage #2
 	('ours') or #3 ('theirs') for unmerged paths.
++
+Note that during `git rebase` and `git pull --rebase`, 'ours' and
+'theirs' may appear swapped; `--ours` gives the version from the
+branch the changes are rebased onto, while `--theirs` gives the
+version from the branch that holds your work that is being rebased.
++
+This is because `rebase` is used in a workflow that treats the
+history at the remote as the shared canonical one, and treats the
+work done on the branch you are rebasing as the third-party work to
+be integrated, and you are temporarily assuming the role of the
+keeper of the canonical history during the rebase.  As the keeper of
+the canonical history, you need to view the history from the remote
+as `ours` (i.e. "our shared canonical history"), while what you did
+on your side branch as `theirs` (i.e. "one contributor's work on top
+of it").
 
 -b <new_branch>::
 	Create a new branch named <new_branch> and start it at
diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt
index c483100..b6c6326 100644
--- a/Documentation/git-rev-parse.txt
+++ b/Documentation/git-rev-parse.txt
@@ -311,8 +311,8 @@
 `<opt-spec>`::
 	its format is the short option character, then the long option name
 	separated by a comma. Both parts are not required, though at least one
-	is necessary. `h,help`, `dry-run` and `f` are all three correct
-	`<opt-spec>`.
+	is necessary. May not contain any of the `<flags>` characters.
+	`h,help`, `dry-run` and `f` are examples of correct `<opt-spec>`.
 
 `<flags>`::
 	`<flags>` are of `*`, `=`, `?` or `!`.
diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index 11d1e2f..0c0f60b 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -174,6 +174,9 @@
 	(including automatic fetches due to 'clone', 'dcommit',
 	'rebase', etc) on a given repository. '--ignore-paths' takes
 	precedence over '--include-paths'.
++
+[verse]
+config key: svn-remote.<name>.include-paths
 
 --log-window-size=<n>;;
 	Fetch <n> log entries per request when scanning Subversion history.
diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt
index 034d10d..4b04c2b 100644
--- a/Documentation/git-tag.txt
+++ b/Documentation/git-tag.txt
@@ -14,7 +14,6 @@
 'git tag' -d <tagname>...
 'git tag' [-n[<num>]] -l [--contains <commit>] [--points-at <object>]
 	[--column[=<options>] | --no-column] [<pattern>...]
-	[<pattern>...]
 'git tag' -v <tagname>...
 
 DESCRIPTION
diff --git a/Documentation/git-tools.txt b/Documentation/git-tools.txt
index 78a0d95..2f4ff50 100644
--- a/Documentation/git-tools.txt
+++ b/Documentation/git-tools.txt
@@ -1,118 +1,10 @@
-A short Git tools survey
-========================
+Git Tools
+=========
 
+When Git was young, people looking for third-party Git-related tools came
+to the Git project itself to find them, thus a list of such tools was
+maintained here. These days, however, search engines fill that role much
+more efficiently, so this manually-maintained list has been retired.
 
-Introduction
-------------
-
-Apart from Git contrib/ area there are some others third-party tools
-you may want to look.
-
-This document presents a brief summary of each tool and the corresponding
-link.
-
-
-Alternative/Augmentative Porcelains
------------------------------------
-
-   - *Cogito* (http://www.kernel.org/pub/software/scm/cogito/)
-
-   Cogito is a version control system layered on top of the Git tree history
-   storage system. It aims at seamless user interface and ease of use,
-   providing generally smoother user experience than the "raw" Core Git
-   itself and indeed many other version control systems.
-
-   Cogito is no longer maintained as most of its functionality
-   is now in core Git.
-
-
-   - *pg* (http://www.spearce.org/category/projects/scm/pg/)
-
-   pg is a shell script wrapper around Git to help the user manage a set of
-   patches to files. pg is somewhat like quilt or StGit, but it does have a
-   slightly different feature set.
-
-
-   - *StGit* (http://www.procode.org/stgit/)
-
-   Stacked Git provides a quilt-like patch management functionality in the
-   Git environment. You can easily manage your patches in the scope of Git
-   until they get merged upstream.
-
-
-History Viewers
----------------
-
-   - *gitk* (shipped with git-core)
-
-   gitk is a simple Tk GUI for browsing history of Git repositories easily.
-
-
-   - *gitview*  (contrib/)
-
-   gitview is a GTK based repository browser for Git
-
-
-   - *gitweb* (shipped with git-core)
-
-   Gitweb provides full-fledged web interface for Git repositories.
-
-
-   - *qgit* (http://digilander.libero.it/mcostalba/)
-
-   QGit is a git/StGit GUI viewer built on Qt/C++. QGit could be used
-   to browse history and directory tree, view annotated files, commit
-   changes cherry picking single files or applying patches.
-   Currently it is the fastest and most feature rich among the Git
-   viewers and commit tools.
-
-   - *tig* (http://jonas.nitro.dk/tig/)
-
-   tig by Jonas Fonseca is a simple Git repository browser
-   written using ncurses. Basically, it just acts as a front-end
-   for git-log and git-show/git-diff. Additionally, you can also
-   use it as a pager for Git commands.
-
-
-Foreign SCM interface
----------------------
-
-   - *git-svn* (shipped with git-core)
-
-   git-svn is a simple conduit for changesets between a single Subversion
-   branch and Git.
-
-
-   - *quilt2git / git2quilt* (http://home-tj.org/wiki/index.php/Misc)
-
-   These utilities convert patch series in a quilt repository and commit
-   series in Git back and forth.
-
-
-   - *hg-to-git* (contrib/)
-
-   hg-to-git converts a Mercurial repository into a Git one, and
-   preserves the full branch history in the process. hg-to-git can
-   also be used in an incremental way to keep the Git repository
-   in sync with the master Mercurial repository.
-
-
-Others
-------
-
-   - *(h)gct* (http://www.cyd.liu.se/users/~freku045/gct/)
-
-   Commit Tool or (h)gct is a GUI enabled commit tool for Git and
-   Mercurial (hg). It allows the user to view diffs, select which files
-   to committed (or ignored / reverted) write commit messages and
-   perform the commit itself.
-
-   - *git.el* (contrib/)
-
-   This is an Emacs interface for Git. The user interface is modelled on
-   pcl-cvs. It has been developed on Emacs 21 and will probably need some
-   tweaking to work on XEmacs.
-
-
-http://git.or.cz/gitwiki/InterfacesFrontendsAndTools has more
-comprehensive list.
+See also the `contrib/` area, and the Git wiki:
+http://git.or.cz/gitwiki/InterfacesFrontendsAndTools
diff --git a/Documentation/git.txt b/Documentation/git.txt
index f4cb5cb..629e62c 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -43,14 +43,18 @@
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
-* link:v2.5.0/git.html[documentation for release 2.5]
+* link:v2.5.2/git.html[documentation for release 2.5.2]
 
 * release notes for
-  link:RelNotes/2.5.0.txt[2.5],
+  link:RelNotes/2.5.2.txt[2.5.2],
+  link:RelNotes/2.5.1.txt[2.5.1],
+  link:RelNotes/2.5.0.txt[2.5].
 
-* link:v2.4.7/git.html[documentation for release 2.4.7]
+* link:v2.4.9/git.html[documentation for release 2.4.9]
 
 * release notes for
+  link:RelNotes/2.4.9.txt[2.4.9],
+  link:RelNotes/2.4.8.txt[2.4.8],
   link:RelNotes/2.4.7.txt[2.4.7],
   link:RelNotes/2.4.6.txt[2.4.6],
   link:RelNotes/2.4.5.txt[2.4.5],
@@ -60,9 +64,10 @@
   link:RelNotes/2.4.1.txt[2.4.1],
   link:RelNotes/2.4.0.txt[2.4].
 
-* link:v2.3.8/git.html[documentation for release 2.3.8]
+* link:v2.3.9/git.html[documentation for release 2.3.9]
 
 * release notes for
+  link:RelNotes/2.3.9.txt[2.3.9],
   link:RelNotes/2.3.8.txt[2.3.8],
   link:RelNotes/2.3.7.txt[2.3.7],
   link:RelNotes/2.3.6.txt[2.3.6],
@@ -73,9 +78,10 @@
   link:RelNotes/2.3.1.txt[2.3.1],
   link:RelNotes/2.3.0.txt[2.3].
 
-* link:v2.2.2/git.html[documentation for release 2.2.2]
+* link:v2.2.3/git.html[documentation for release 2.2.3]
 
 * release notes for
+  link:RelNotes/2.2.3.txt[2.2.3],
   link:RelNotes/2.2.2.txt[2.2.2],
   link:RelNotes/2.2.1.txt[2.2.1],
   link:RelNotes/2.2.0.txt[2.2].
@@ -780,7 +786,7 @@
 ~~~~~~~~~~~~~~~~~~
 These environment variables apply to 'all' core Git commands. Nb: it
 is worth noting that they may be used/overridden by SCMS sitting above
-Git so take care if using Cogito etc.
+Git so take care if using a foreign front-end.
 
 'GIT_INDEX_FILE'::
 	This environment allows the specification of an alternate
diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index dc865cb..671cebd 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -139,7 +139,9 @@
 - '%f': sanitized subject line, suitable for a filename
 - '%b': body
 - '%B': raw body (unwrapped subject and body)
+ifndef::git-rev-list[]
 - '%N': commit notes
+endif::git-rev-list[]
 - '%GG': raw verification message from GPG for a signed commit
 - '%G?': show "G" for a Good signature, "B" for a Bad signature, "U" for a good,
   untrusted signature and "N" for no signature
diff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt
index 642af6e..8d6c5ce 100644
--- a/Documentation/pretty-options.txt
+++ b/Documentation/pretty-options.txt
@@ -42,6 +42,7 @@
 	verbatim; this means that invalid sequences in the original
 	commit may be copied to the output.
 
+ifndef::git-rev-list[]
 --notes[=<ref>]::
 	Show the notes (see linkgit:git-notes[1]) that annotate the
 	commit, when showing the commit log message.  This is the default
@@ -73,6 +74,7 @@
 --[no-]standard-notes::
 	These options are deprecated. Use the above --notes/--no-notes
 	options instead.
+endif::git-rev-list[]
 
 --show-signature::
 	Check the validity of a signed commit object by passing the signature
diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt
index 77ac439..31bee06 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -58,9 +58,11 @@
 	more than one `--grep=<pattern>`, commits whose message
 	matches any of the given patterns are chosen (but see
 	`--all-match`).
+ifndef::git-rev-list[]
 +
 When `--show-notes` is in effect, the message from the notes is
 matched as if it were part of the log message.
+endif::git-rev-list[]
 
 --all-match::
 	Limit the commits output to ones that match all given `--grep`,
diff --git a/Documentation/technical/index-format.txt b/Documentation/technical/index-format.txt
index b7093af..7392ff6 100644
--- a/Documentation/technical/index-format.txt
+++ b/Documentation/technical/index-format.txt
@@ -275,7 +275,7 @@
 
     - The directory name terminated by NUL.
 
-    - A number of untrached file/dir names terminated by NUL.
+    - A number of untracked file/dir names terminated by NUL.
 
 The remaining data of each directory block is grouped by type:
 
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index cd96820..9e3723e 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.5.0
+DEF_VER=v2.5.2
 
 LF='
 '
@@ -38,5 +38,3 @@
 	echo >&2 "GIT_VERSION = $VN"
 	echo "GIT_VERSION = $VN" >$GVF
 }
-
-
diff --git a/Makefile b/Makefile
index 8c3c724..ce0cfe2 100644
--- a/Makefile
+++ b/Makefile
@@ -1696,10 +1696,10 @@
 	ln -s $< $@ 2>/dev/null || \
 	cp $< $@
 
-common-cmds.h: generate-cmdlist.perl command-list.txt
+common-cmds.h: generate-cmdlist.sh command-list.txt
 
 common-cmds.h: $(wildcard Documentation/git-*.txt)
-	$(QUIET_GEN)$(PERL_PATH) generate-cmdlist.perl command-list.txt > $@+ && mv $@+ $@
+	$(QUIET_GEN)./generate-cmdlist.sh command-list.txt >$@+ && mv $@+ $@
 
 SCRIPT_DEFINES = $(SHELL_PATH_SQ):$(DIFF_SQ):$(GIT_VERSION):\
 	$(localedir_SQ):$(NO_CURL):$(USE_GETTEXT_SCHEME):$(SANE_TOOL_PATH_SQ):\
diff --git a/RelNotes b/RelNotes
index 3295d66..24f83fe 120000
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.5.0.txt
\ No newline at end of file
+Documentation/RelNotes/2.5.2.txt
\ No newline at end of file
diff --git a/alias.c b/alias.c
index 6aa164a..a11229d 100644
--- a/alias.c
+++ b/alias.c
@@ -5,7 +5,8 @@
 	char *v = NULL;
 	struct strbuf key = STRBUF_INIT;
 	strbuf_addf(&key, "alias.%s", alias);
-	git_config_get_string(key.buf, &v);
+	if (git_config_key_is_valid(key.buf))
+		git_config_get_string(key.buf, &v);
 	strbuf_release(&key);
 	return v;
 }
diff --git a/archive-zip.c b/archive-zip.c
index ae3d67f..9db4735 100644
--- a/archive-zip.c
+++ b/archive-zip.c
@@ -16,7 +16,9 @@
 
 static unsigned int zip_offset;
 static unsigned int zip_dir_offset;
-static unsigned int zip_dir_entries;
+static uint64_t zip_dir_entries;
+
+static unsigned int max_creator_version;
 
 #define ZIP_DIRECTORY_MIN_SIZE	(1024 * 1024)
 #define ZIP_STREAM	(1 <<  3)
@@ -86,6 +88,28 @@
 	unsigned char _end[1];
 };
 
+struct zip64_dir_trailer {
+	unsigned char magic[4];
+	unsigned char record_size[8];
+	unsigned char creator_version[2];
+	unsigned char version[2];
+	unsigned char disk[4];
+	unsigned char directory_start_disk[4];
+	unsigned char entries_on_this_disk[8];
+	unsigned char entries[8];
+	unsigned char size[8];
+	unsigned char offset[8];
+	unsigned char _end[1];
+};
+
+struct zip64_dir_trailer_locator {
+	unsigned char magic[4];
+	unsigned char disk[4];
+	unsigned char offset[8];
+	unsigned char number_of_disks[4];
+	unsigned char _end[1];
+};
+
 /*
  * On ARM, padding is added at the end of the struct, so a simple
  * sizeof(struct ...) reports two bytes more than the payload size
@@ -98,6 +122,12 @@
 #define ZIP_EXTRA_MTIME_SIZE	offsetof(struct zip_extra_mtime, _end)
 #define ZIP_EXTRA_MTIME_PAYLOAD_SIZE \
 	(ZIP_EXTRA_MTIME_SIZE - offsetof(struct zip_extra_mtime, flags))
+#define ZIP64_DIR_TRAILER_SIZE	offsetof(struct zip64_dir_trailer, _end)
+#define ZIP64_DIR_TRAILER_RECORD_SIZE \
+	(ZIP64_DIR_TRAILER_SIZE - \
+	 offsetof(struct zip64_dir_trailer, creator_version))
+#define ZIP64_DIR_TRAILER_LOCATOR_SIZE \
+	offsetof(struct zip64_dir_trailer_locator, _end)
 
 static void copy_le16(unsigned char *dest, unsigned int n)
 {
@@ -113,6 +143,31 @@
 	dest[3] = 0xff & (n >> 030);
 }
 
+static void copy_le64(unsigned char *dest, uint64_t n)
+{
+	dest[0] = 0xff & n;
+	dest[1] = 0xff & (n >> 010);
+	dest[2] = 0xff & (n >> 020);
+	dest[3] = 0xff & (n >> 030);
+	dest[4] = 0xff & (n >> 040);
+	dest[5] = 0xff & (n >> 050);
+	dest[6] = 0xff & (n >> 060);
+	dest[7] = 0xff & (n >> 070);
+}
+
+static uint64_t clamp_max(uint64_t n, uint64_t max, int *clamped)
+{
+	if (n <= max)
+		return n;
+	*clamped = 1;
+	return max;
+}
+
+static void copy_le16_clamp(unsigned char *dest, uint64_t n, int *clamped)
+{
+	copy_le16(dest, clamp_max(n, 0xffff, clamped));
+}
+
 static void *zlib_deflate_raw(void *data, unsigned long size,
 			      int compression_level,
 			      unsigned long *compressed_size)
@@ -223,6 +278,7 @@
 	unsigned long size;
 	int is_binary = -1;
 	const char *path_without_prefix = path + args->baselen;
+	unsigned int creator_version = 0;
 
 	crc = crc32(0, NULL, 0);
 
@@ -251,6 +307,8 @@
 		method = 0;
 		attr2 = S_ISLNK(mode) ? ((mode | 0777) << 16) :
 			(mode & 0111) ? ((mode) << 16) : 0;
+		if (S_ISLNK(mode) || (mode & 0111))
+			creator_version = 0x0317;
 		if (S_ISREG(mode) && args->compression_level != 0 && size > 0)
 			method = 8;
 
@@ -279,6 +337,9 @@
 				sha1_to_hex(sha1));
 	}
 
+	if (creator_version > max_creator_version)
+		max_creator_version = creator_version;
+
 	if (buffer && method == 8) {
 		out = deflated = zlib_deflate_raw(buffer, size,
 						  args->compression_level,
@@ -303,8 +364,7 @@
 	}
 
 	copy_le32(dirent.magic, 0x02014b50);
-	copy_le16(dirent.creator_version,
-		S_ISLNK(mode) || (S_ISREG(mode) && (mode & 0111)) ? 0x0317 : 0);
+	copy_le16(dirent.creator_version, creator_version);
 	copy_le16(dirent.version, 10);
 	copy_le16(dirent.flags, flags);
 	copy_le16(dirent.compression_method, method);
@@ -437,20 +497,49 @@
 	return 0;
 }
 
+static void write_zip64_trailer(void)
+{
+	struct zip64_dir_trailer trailer64;
+	struct zip64_dir_trailer_locator locator64;
+
+	copy_le32(trailer64.magic, 0x06064b50);
+	copy_le64(trailer64.record_size, ZIP64_DIR_TRAILER_RECORD_SIZE);
+	copy_le16(trailer64.creator_version, max_creator_version);
+	copy_le16(trailer64.version, 45);
+	copy_le32(trailer64.disk, 0);
+	copy_le32(trailer64.directory_start_disk, 0);
+	copy_le64(trailer64.entries_on_this_disk, zip_dir_entries);
+	copy_le64(trailer64.entries, zip_dir_entries);
+	copy_le64(trailer64.size, zip_dir_offset);
+	copy_le64(trailer64.offset, zip_offset);
+
+	copy_le32(locator64.magic, 0x07064b50);
+	copy_le32(locator64.disk, 0);
+	copy_le64(locator64.offset, zip_offset + zip_dir_offset);
+	copy_le32(locator64.number_of_disks, 1);
+
+	write_or_die(1, &trailer64, ZIP64_DIR_TRAILER_SIZE);
+	write_or_die(1, &locator64, ZIP64_DIR_TRAILER_LOCATOR_SIZE);
+}
+
 static void write_zip_trailer(const unsigned char *sha1)
 {
 	struct zip_dir_trailer trailer;
+	int clamped = 0;
 
 	copy_le32(trailer.magic, 0x06054b50);
 	copy_le16(trailer.disk, 0);
 	copy_le16(trailer.directory_start_disk, 0);
-	copy_le16(trailer.entries_on_this_disk, zip_dir_entries);
-	copy_le16(trailer.entries, zip_dir_entries);
+	copy_le16_clamp(trailer.entries_on_this_disk, zip_dir_entries,
+			&clamped);
+	copy_le16_clamp(trailer.entries, zip_dir_entries, &clamped);
 	copy_le32(trailer.size, zip_dir_offset);
 	copy_le32(trailer.offset, zip_offset);
 	copy_le16(trailer.comment_length, sha1 ? GIT_SHA1_HEXSZ : 0);
 
 	write_or_die(1, zip_dir, zip_dir_offset);
+	if (clamped)
+		write_zip64_trailer();
 	write_or_die(1, &trailer, ZIP_DIR_TRAILER_SIZE);
 	if (sha1)
 		write_or_die(1, sha1_to_hex(sha1), GIT_SHA1_HEXSZ);
diff --git a/builtin/add.c b/builtin/add.c
index 4bd98b7..b2a5c57 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -375,7 +375,6 @@
 
 	if (add_new_files) {
 		int baselen;
-		struct pathspec empty_pathspec;
 
 		/* Set up the default git porcelain excludes */
 		memset(&dir, 0, sizeof(dir));
@@ -384,7 +383,6 @@
 			setup_standard_excludes(&dir);
 		}
 
-		memset(&empty_pathspec, 0, sizeof(empty_pathspec));
 		/* This picks up the paths that are not tracked */
 		baselen = fill_directory(&dir, &pathspec);
 		if (pathspec.nr)
diff --git a/builtin/checkout.c b/builtin/checkout.c
index f71844a..3b6e499 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -282,7 +282,7 @@
 	if (opts->source_tree)
 		read_tree_some(opts->source_tree, &opts->pathspec);
 
-	ps_matched = xcalloc(1, opts->pathspec.nr);
+	ps_matched = xcalloc(opts->pathspec.nr, 1);
 
 	/*
 	 * Make sure all pathspecs participated in locating the paths
diff --git a/builtin/clone.c b/builtin/clone.c
index a72ff7e..53cf545 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -174,7 +174,8 @@
 	/*
 	 * Strip .{bundle,git}.
 	 */
-	strip_suffix(start, is_bundle ? ".bundle" : ".git" , &len);
+	len = end - start;
+	strip_suffix_mem(start, &len, is_bundle ? ".bundle" : ".git");
 
 	if (is_bare)
 		dir = xstrfmt("%.*s.git", (int)len, start);
diff --git a/builtin/commit.c b/builtin/commit.c
index 254477f..1692620 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -404,10 +404,8 @@
 		hold_locked_index(&index_lock, 1);
 		refresh_cache_or_die(refresh_flags);
 		if (active_cache_changed
-		    || !cache_tree_fully_valid(active_cache_tree)) {
+		    || !cache_tree_fully_valid(active_cache_tree))
 			update_main_cache_tree(WRITE_TREE_SILENT);
-			active_cache_changed = 1;
-		}
 		if (active_cache_changed) {
 			if (write_locked_index(&the_index, &index_lock,
 					       COMMIT_LOCK))
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 8d5b2db..635bbdf 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -979,17 +979,15 @@
 {
 	struct remote_group_data *g = priv;
 
-	if (starts_with(key, "remotes.") &&
-			!strcmp(key + 8, g->name)) {
+	if (skip_prefix(key, "remotes.", &key) && !strcmp(key, g->name)) {
 		/* split list by white space */
-		int space = strcspn(value, " \t\n");
 		while (*value) {
-			if (space > 1) {
+			size_t wordlen = strcspn(value, " \t\n");
+
+			if (wordlen >= 1)
 				string_list_append(g->list,
-						   xstrndup(value, space));
-			}
-			value += space + (value[space] != '\0');
-			space = strcspn(value, " \t\n");
+						   xstrndup(value, wordlen));
+			value += wordlen + (value[wordlen] != '\0');
 		}
 	}
 
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 6fa2205..b6a7cb0 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -516,7 +516,7 @@
 
 	/* Treat unmatching pathspec elements as errors */
 	if (pathspec.nr && error_unmatch)
-		ps_matched = xcalloc(1, pathspec.nr);
+		ps_matched = xcalloc(pathspec.nr, 1);
 
 	if ((dir.flags & DIR_SHOW_IGNORED) && !exc_given)
 		die("ls-files --ignored needs some exclude pattern");
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 94d0571..04cb5a1 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -911,7 +911,7 @@
 			return "deletion prohibited";
 		}
 
-		if (!strcmp(namespaced_name, head_name)) {
+		if (head_name && !strcmp(namespaced_name, head_name)) {
 			switch (deny_delete_current) {
 			case DENY_IGNORE:
 				break;
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index c0b4b53..d80d1ed 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -350,6 +350,9 @@
 	    revs.diff)
 		usage(rev_list_usage);
 
+	if (revs.show_notes)
+		die(_("rev-list does not support display of notes"));
+
 	save_commit_buffer = (revs.verbose_header ||
 			      revs.grep_filter.pattern_list ||
 			      revs.grep_filter.header_list);
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index b623239..02d747d 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -371,6 +371,7 @@
 					N_("output in stuck long form")),
 		OPT_END(),
 	};
+	static const char * const flag_chars = "*=?!";
 
 	struct strbuf sb = STRBUF_INIT, parsed = STRBUF_INIT;
 	const char **usage = NULL;
@@ -400,7 +401,7 @@
 	/* parse: (<short>|<short>,<long>|<long>)[*=?!]*<arghint>? SP+ <help> */
 	while (strbuf_getline(&sb, stdin, '\n') != EOF) {
 		const char *s;
-		const char *end;
+		const char *help;
 		struct option *o;
 
 		if (!sb.len)
@@ -410,45 +411,23 @@
 		memset(opts + onb, 0, sizeof(opts[onb]));
 
 		o = &opts[onb++];
-		s = strchr(sb.buf, ' ');
-		if (!s || *sb.buf == ' ') {
+		help = strchr(sb.buf, ' ');
+		if (!help || *sb.buf == ' ') {
 			o->type = OPTION_GROUP;
 			o->help = xstrdup(skipspaces(sb.buf));
 			continue;
 		}
 
 		o->type = OPTION_CALLBACK;
-		o->help = xstrdup(skipspaces(s));
+		o->help = xstrdup(skipspaces(help));
 		o->value = &parsed;
 		o->flags = PARSE_OPT_NOARG;
 		o->callback = &parseopt_dump;
 
-		/* Possible argument name hint */
-		end = s;
-		while (s > sb.buf && strchr("*=?!", s[-1]) == NULL)
-			--s;
-		if (s != sb.buf && s != end)
-			o->argh = xmemdupz(s, end - s);
-		if (s == sb.buf)
-			s = end;
-
-		while (s > sb.buf && strchr("*=?!", s[-1])) {
-			switch (*--s) {
-			case '=':
-				o->flags &= ~PARSE_OPT_NOARG;
-				break;
-			case '?':
-				o->flags &= ~PARSE_OPT_NOARG;
-				o->flags |= PARSE_OPT_OPTARG;
-				break;
-			case '!':
-				o->flags |= PARSE_OPT_NONEG;
-				break;
-			case '*':
-				o->flags |= PARSE_OPT_HIDDEN;
-				break;
-			}
-		}
+		/* name(s) */
+		s = strpbrk(sb.buf, flag_chars);
+		if (s == NULL)
+			s = help;
 
 		if (s - sb.buf == 1) /* short option only */
 			o->short_name = *sb.buf;
@@ -458,6 +437,30 @@
 			o->short_name = *sb.buf;
 			o->long_name = xmemdupz(sb.buf + 2, s - sb.buf - 2);
 		}
+
+		/* flags */
+		while (s < help) {
+			switch (*s++) {
+			case '=':
+				o->flags &= ~PARSE_OPT_NOARG;
+				continue;
+			case '?':
+				o->flags &= ~PARSE_OPT_NOARG;
+				o->flags |= PARSE_OPT_OPTARG;
+				continue;
+			case '!':
+				o->flags |= PARSE_OPT_NONEG;
+				continue;
+			case '*':
+				o->flags |= PARSE_OPT_HIDDEN;
+				continue;
+			}
+			s--;
+			break;
+		}
+
+		if (s < help)
+			o->argh = xmemdupz(s, help - s);
 	}
 	strbuf_release(&sb);
 
diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index b961e5a..23b2962 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -11,6 +11,7 @@
 #include "transport.h"
 #include "version.h"
 #include "sha1-array.h"
+#include "gpg-interface.h"
 
 static const char send_pack_usage[] =
 "git send-pack [--all | --mirror] [--dry-run] [--force] [--receive-pack=<git-receive-pack>] [--verbose] [--thin] [--atomic] [<host>:]<directory> [<ref>...]\n"
@@ -113,6 +114,8 @@
 	int from_stdin = 0;
 	struct push_cas_option cas = {0};
 
+	git_config(git_gpg_config, NULL);
+
 	argv++;
 	for (i = 1; i < argc; i++, argv++) {
 		const char *arg = *argv;
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index 323f857..344ae4c 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -730,7 +730,6 @@
 
 	if (reflog) {
 		struct object_id oid;
-		char nth_desc[256];
 		char *ref;
 		int base = 0;
 		unsigned int flags = 0;
@@ -769,6 +768,7 @@
 
 		for (i = 0; i < reflog; i++) {
 			char *logmsg;
+			char *nth_desc;
 			const char *msg;
 			unsigned long timestamp;
 			int tz;
@@ -787,8 +787,10 @@
 						show_date(timestamp, tz, 1),
 						msg);
 			free(logmsg);
-			sprintf(nth_desc, "%s@{%d}", *av, base+i);
+
+			nth_desc = xstrfmt("%s@{%d}", *av, base+i);
 			append_ref(nth_desc, &oid, 1);
+			free(nth_desc);
 		}
 		free(ref);
 	}
diff --git a/cache.h b/cache.h
index 4f55466..c9e2f74 100644
--- a/cache.h
+++ b/cache.h
@@ -1446,6 +1446,7 @@
 extern int git_config_set_in_file(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_key_is_valid(const char *key);
 extern int git_config_set_multivar(const char *, const char *, const char *, int);
 extern int git_config_set_multivar_in_file(const char *, const char *, const char *, const char *, int);
 extern int git_config_rename_section(const char *, const char *);
diff --git a/compat/mingw.c b/compat/mingw.c
index 496e6f8..f74da23 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -681,7 +681,7 @@
 		return -1;
 	}
 	filedes[1] = _open_osfhandle((int)h[1], O_NOINHERIT);
-	if (filedes[0] < 0) {
+	if (filedes[1] < 0) {
 		close(filedes[0]);
 		CloseHandle(h[1]);
 		return -1;
diff --git a/config.c b/config.c
index 9fd275f..0e532b8 100644
--- a/config.c
+++ b/config.c
@@ -1848,7 +1848,7 @@
  * 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_)
+static int git_config_parse_key_1(const char *key, char **store_key, int *baselen_, int quiet)
 {
 	int i, dot, baselen;
 	const char *last_dot = strrchr(key, '.');
@@ -1859,12 +1859,14 @@
 	 */
 
 	if (last_dot == NULL || last_dot == key) {
-		error("key does not contain a section: %s", key);
+		if (!quiet)
+			error("key does not contain a section: %s", key);
 		return -CONFIG_NO_SECTION_OR_NAME;
 	}
 
 	if (!last_dot[1]) {
-		error("key does not contain variable name: %s", key);
+		if (!quiet)
+			error("key does not contain variable name: %s", key);
 		return -CONFIG_NO_SECTION_OR_NAME;
 	}
 
@@ -1875,7 +1877,8 @@
 	/*
 	 * Validate the key and while at it, lower case it for matching.
 	 */
-	*store_key = xmalloc(strlen(key) + 1);
+	if (store_key)
+		*store_key = xmalloc(strlen(key) + 1);
 
 	dot = 0;
 	for (i = 0; key[i]; i++) {
@@ -1886,26 +1889,42 @@
 		if (!dot || i > baselen) {
 			if (!iskeychar(c) ||
 			    (i == baselen + 1 && !isalpha(c))) {
-				error("invalid key: %s", key);
+				if (!quiet)
+					error("invalid key: %s", key);
 				goto out_free_ret_1;
 			}
 			c = tolower(c);
 		} else if (c == '\n') {
-			error("invalid key (newline): %s", key);
+			if (!quiet)
+				error("invalid key (newline): %s", key);
 			goto out_free_ret_1;
 		}
-		(*store_key)[i] = c;
+		if (store_key)
+			(*store_key)[i] = c;
 	}
-	(*store_key)[i] = 0;
+	if (store_key)
+		(*store_key)[i] = 0;
 
 	return 0;
 
 out_free_ret_1:
-	free(*store_key);
-	*store_key = NULL;
+	if (store_key) {
+		free(*store_key);
+		*store_key = NULL;
+	}
 	return -CONFIG_INVALID_KEY;
 }
 
+int git_config_parse_key(const char *key, char **store_key, int *baselen)
+{
+	return git_config_parse_key_1(key, store_key, baselen, 0);
+}
+
+int git_config_key_is_valid(const char *key)
+{
+	return !git_config_parse_key_1(key, NULL, NULL, 1);
+}
+
 /*
  * If value==NULL, unset in (remove from) config,
  * if value_regex!=NULL, disregard key/value pairs where value does not match.
@@ -1935,7 +1954,7 @@
 				const char *key, const char *value,
 				const char *value_regex, int multi_replace)
 {
-	int fd = -1, in_fd;
+	int fd = -1, in_fd = -1;
 	int ret;
 	struct lock_file *lock = NULL;
 	char *filename_buf = NULL;
@@ -2065,6 +2084,7 @@
 			goto out_free;
 		}
 		close(in_fd);
+		in_fd = -1;
 
 		if (chmod(lock->filename.buf, st.st_mode & 07777) < 0) {
 			error("chmod on %s failed: %s",
@@ -2148,6 +2168,8 @@
 	free(filename_buf);
 	if (contents)
 		munmap(contents, contents_sz);
+	if (in_fd >= 0)
+		close(in_fd);
 	return ret;
 
 write_err_out:
diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh
index 07bd77c..9f06571 100755
--- a/contrib/subtree/git-subtree.sh
+++ b/contrib/subtree/git-subtree.sh
@@ -305,7 +305,7 @@
 	# We're going to set some environment vars here, so
 	# do it in a subshell to get rid of them safely later
 	debug copy_commit "{$1}" "{$2}" "{$3}"
-	git log -1 --pretty=format:'%an%n%ae%n%ad%n%cn%n%ce%n%cd%n%B' "$1" |
+	git log -1 --pretty=format:'%an%n%ae%n%aD%n%cn%n%ce%n%cD%n%B' "$1" |
 	(
 		read GIT_AUTHOR_NAME
 		read GIT_AUTHOR_EMAIL
diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh
index bd3df97..9051982 100755
--- a/contrib/subtree/t/t7900-subtree.sh
+++ b/contrib/subtree/t/t7900-subtree.sh
@@ -94,6 +94,10 @@
 # Back to mainline
 cd ..
 
+test_expect_success 'enable log.date=relative to catch errors' '
+	git config log.date relative
+'
+
 test_expect_success 'add main4' '
 	create main4 &&
 	git commit -m "main4" &&
diff --git a/dir.c b/dir.c
index c1edabf..a71331a 100644
--- a/dir.c
+++ b/dir.c
@@ -1849,7 +1849,7 @@
 
 	if (sb.len)
 		return sb.buf;
-	if (uname(&uts))
+	if (uname(&uts) < 0)
 		die_errno(_("failed to get kernel name and information"));
 	strbuf_addf(&sb, "Location %s, system %s %s %s", get_git_work_tree(),
 		    uts.sysname, uts.release, uts.version);
diff --git a/environment.c b/environment.c
index 61c685b..03cf5f6 100644
--- a/environment.c
+++ b/environment.c
@@ -231,6 +231,8 @@
 	}
 	git_work_tree_initialized = 1;
 	work_tree = xstrdup(real_path(new_work_tree));
+	if (setenv(GIT_WORK_TREE_ENVIRONMENT, work_tree, 1))
+		die("could not set GIT_WORK_TREE to '%s'", work_tree);
 }
 
 const char *get_git_work_tree(void)
diff --git a/fast-import.c b/fast-import.c
index 6378726..ece0096 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -2588,14 +2588,12 @@
 {
 	const char *from;
 	struct branch *s;
+	unsigned char sha1[20];
 
 	if (!skip_prefix(command_buf.buf, "from ", &from))
 		return 0;
 
-	if (b->branch_tree.tree) {
-		release_tree_content_recursive(b->branch_tree.tree);
-		b->branch_tree.tree = NULL;
-	}
+	hashcpy(sha1, b->branch_tree.versions[1].sha1);
 
 	s = lookup_branch(from);
 	if (b == s)
@@ -2610,14 +2608,16 @@
 		struct object_entry *oe = find_mark(idnum);
 		if (oe->type != OBJ_COMMIT)
 			die("Mark :%" PRIuMAX " not a commit", idnum);
-		hashcpy(b->sha1, oe->idx.sha1);
-		if (oe->pack_id != MAX_PACK_ID) {
-			unsigned long size;
-			char *buf = gfi_unpack_entry(oe, &size);
-			parse_from_commit(b, buf, size);
-			free(buf);
-		} else
-			parse_from_existing(b);
+		if (hashcmp(b->sha1, oe->idx.sha1)) {
+			hashcpy(b->sha1, oe->idx.sha1);
+			if (oe->pack_id != MAX_PACK_ID) {
+				unsigned long size;
+				char *buf = gfi_unpack_entry(oe, &size);
+				parse_from_commit(b, buf, size);
+				free(buf);
+			} else
+				parse_from_existing(b);
+		}
 	} else if (!get_sha1(from, b->sha1)) {
 		parse_from_existing(b);
 		if (is_null_sha1(b->sha1))
@@ -2626,6 +2626,11 @@
 	else
 		die("Invalid ref name or SHA1 expression: %s", from);
 
+	if (b->branch_tree.tree && hashcmp(sha1, b->branch_tree.versions[1].sha1)) {
+		release_tree_content_recursive(b->branch_tree.tree);
+		b->branch_tree.tree = NULL;
+	}
+
 	read_next_command();
 	return 1;
 }
diff --git a/generate-cmdlist.perl b/generate-cmdlist.perl
deleted file mode 100755
index 31516e3..0000000
--- a/generate-cmdlist.perl
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use warnings;
-
-print <<"EOT";
-/* Automatically generated by $0 */
-
-struct cmdname_help {
-	char name[16];
-	char help[80];
-	unsigned char group;
-};
-
-static char *common_cmd_groups[] = {
-EOT
-
-my $n = 0;
-my %grp;
-while (<>) {
-	last if /^### command list/;
-	next if (1../^### common groups/) || /^#/ || /^\s*$/;
-	chop;
-	my ($k, $v) = split ' ', $_, 2;
-	$grp{$k} = $n++;
-	print "\tN_(\"$v\"),\n";
-}
-
-print "};\n\nstatic struct cmdname_help common_cmds[] = {\n";
-
-while (<>) {
-	next if /^#/ || /^\s*$/;
-	my @tags = split;
-	my $cmd = shift @tags;
-	for my $t (@tags) {
-		if (exists $grp{$t}) {
-			my $s;
-			open my $f, '<', "Documentation/$cmd.txt" or die;
-			while (<$f>) {
-				($s) = /^$cmd - (.+)$/;
-				last if $s;
-			}
-			close $f;
-			$cmd =~ s/^git-//;
-			print "\t{\"$cmd\", N_(\"$s\"), $grp{$t}},\n";
-			last;
-		}
-	}
-}
-
-print "};\n";
diff --git a/generate-cmdlist.sh b/generate-cmdlist.sh
new file mode 100755
index 0000000..ab0d1b0
--- /dev/null
+++ b/generate-cmdlist.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+echo "/* Automatically generated by $0 */
+struct cmdname_help {
+	char name[16];
+	char help[80];
+	unsigned char group;
+};
+
+static const char *common_cmd_groups[] = {"
+
+grps=grps$$.tmp
+match=match$$.tmp
+trap "rm -f '$grps' '$match'" 0 1 2 3 15
+
+sed -n '
+	1,/^### common groups/b
+	/^### command list/q
+	/^#/b
+	/^[ 	]*$/b
+	h;s/^[^ 	][^ 	]*[ 	][ 	]*\(.*\)/	N_("\1"),/p
+	g;s/^\([^ 	][^ 	]*\)[ 	].*/\1/w '$grps'
+	' "$1"
+printf '};\n\n'
+
+n=0
+substnum=
+while read grp
+do
+	echo "^git-..*[ 	]$grp"
+	substnum="$substnum${substnum:+;}s/[ 	]$grp/$n/"
+	n=$(($n+1))
+done <"$grps" >"$match"
+
+printf 'static struct cmdname_help common_cmds[] = {\n'
+grep -f "$match" "$1" |
+sed 's/^git-//' |
+sort |
+while read cmd tags
+do
+	tag=$(echo "$tags" | sed "$substnum; s/[^0-9]//g")
+	sed -n '
+		/^NAME/,/git-'"$cmd"'/H
+		${
+			x
+			s/.*git-'"$cmd"' - \(.*\)/	{"'"$cmd"'", N_("\1"), '$tag'},/
+			p
+		}' "Documentation/git-$cmd.txt"
+done
+echo "};"
diff --git a/git-am.sh b/git-am.sh
index 3af351f..455ce4f 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -510,7 +510,7 @@
 		git read-tree --reset -u $head_tree $head_tree &&
 		index_tree=$(git write-tree) &&
 		git read-tree -m -u $index_tree $head_tree
-		git read-tree $head_tree
+		git read-tree -m $head_tree
 		;;
 	,t)
 		if test -f "$dotest/rebasing"
diff --git a/git-compat-util.h b/git-compat-util.h
index c6d391f..076461e 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -389,7 +389,6 @@
 
 /* General helper functions */
 extern void vreportf(const char *prefix, const char *err, va_list params);
-extern void vwritef(int fd, const char *prefix, const char *err, va_list params);
 extern NORETURN void usage(const char *err);
 extern NORETURN void usagef(const char *err, ...) __attribute__((format (printf, 1, 2)));
 extern NORETURN void die(const char *err, ...) __attribute__((format (printf, 1, 2)));
@@ -425,6 +424,7 @@
 extern void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list params));
 extern void set_error_routine(void (*routine)(const char *err, va_list params));
 extern void set_die_is_recursing_routine(int (*routine)(void));
+extern void set_error_handle(FILE *);
 
 extern int starts_with(const char *str, const char *prefix);
 
diff --git a/git-pull.sh b/git-pull.sh
index a814bf6..e8dc2e0 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -295,7 +295,7 @@
 }
 orig_head=$(git rev-parse -q --verify HEAD)
 git fetch $verbosity $progress $dry_run $recurse_submodules $all $append \
-$upload_pack $force $tags $prune $keep $depth $unshallow $update_shallow \
+${upload_pack:+"$upload_pack"} $force $tags $prune $keep $depth $unshallow $update_shallow \
 $refmap --update-head-ok "$@" || exit 1
 test -z "$dry_run" || exit 0
 
diff --git a/git-submodule.sh b/git-submodule.sh
index 36797c3..25b1ddf 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -904,7 +904,7 @@
 				;;
 			!*)
 				command="${update_module#!}"
-				die_msg="$(eval_gettext "Execution of '\$command \$sha1' failed in submodule  path '\$prefix\$sm_path'")"
+				die_msg="$(eval_gettext "Execution of '\$command \$sha1' failed in submodule path '\$prefix\$sm_path'")"
 				say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': '\$command \$sha1'")"
 				must_die_on_failure=yes
 				;;
diff --git a/notes.c b/notes.c
index df08209..eacd2a6 100644
--- a/notes.c
+++ b/notes.c
@@ -362,13 +362,14 @@
 	return strcmp(a->path, b->path);
 }
 
-static void add_non_note(struct notes_tree *t, const char *path,
+/* note: takes ownership of path string */
+static void add_non_note(struct notes_tree *t, char *path,
 		unsigned int mode, const unsigned char *sha1)
 {
 	struct non_note *p = t->prev_non_note, *n;
 	n = (struct non_note *) xmalloc(sizeof(struct non_note));
 	n->next = NULL;
-	n->path = xstrdup(path);
+	n->path = path;
 	n->mode = mode;
 	hashcpy(n->sha1, sha1);
 	t->prev_non_note = n;
@@ -482,17 +483,17 @@
 		 * component.
 		 */
 		{
-			char non_note_path[PATH_MAX];
-			char *p = non_note_path;
+			struct strbuf non_note_path = STRBUF_INIT;
 			const char *q = sha1_to_hex(subtree->key_sha1);
 			int i;
 			for (i = 0; i < prefix_len; i++) {
-				*p++ = *q++;
-				*p++ = *q++;
-				*p++ = '/';
+				strbuf_addch(&non_note_path, *q++);
+				strbuf_addch(&non_note_path, *q++);
+				strbuf_addch(&non_note_path, '/');
 			}
-			strcpy(p, entry.path);
-			add_non_note(t, non_note_path, entry.mode, entry.sha1);
+			strbuf_addstr(&non_note_path, entry.path);
+			add_non_note(t, strbuf_detach(&non_note_path, NULL),
+				     entry.mode, entry.sha1);
 		}
 	}
 	free(buf);
diff --git a/pager.c b/pager.c
index 070dc11..27d4c8a 100644
--- a/pager.c
+++ b/pager.c
@@ -150,7 +150,8 @@
 	struct strbuf key = STRBUF_INIT;
 	const char *value = NULL;
 	strbuf_addf(&key, "pager.%s", cmd);
-	if (!git_config_get_value(key.buf, &value)) {
+	if (git_config_key_is_valid(key.buf) &&
+	    !git_config_get_value(key.buf, &value)) {
 		int b = git_config_maybe_bool(key.buf, value);
 		if (b >= 0)
 			want = b;
diff --git a/parse-options.h b/parse-options.h
index c71e9da..08d7818 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -126,7 +126,7 @@
 #define OPT_BOOL(s, l, v, h)        OPT_SET_INT(s, l, v, h, 1)
 #define OPT_HIDDEN_BOOL(s, l, v, h) { OPTION_SET_INT, (s), (l), (v), NULL, \
 				      (h), PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, 1}
-#define OPT_CMDMODE(s, l, v, h, i) { OPTION_CMDMODE, (s), (l), (v), NULL, \
+#define OPT_CMDMODE(s, l, v, h, i)  { OPTION_CMDMODE, (s), (l), (v), NULL, \
 				      (h), PARSE_OPT_NOARG|PARSE_OPT_NONEG, NULL, (i) }
 #define OPT_INTEGER(s, l, v, h)     { OPTION_INTEGER, (s), (l), (v), N_("n"), (h) }
 #define OPT_STRING(s, l, v, a, h)   { OPTION_STRING,  (s), (l), (v), (a), (h) }
diff --git a/po/README b/po/README
index d8c9111..fef4c0f 100644
--- a/po/README
+++ b/po/README
@@ -10,10 +10,26 @@
 
         https://github.com/git-l10n/git-po/
 
+The two character language translation codes are defined by ISO_639-1, as
+stated in the gettext(1) full manual, appendix A.1, Usual Language Codes.
+
+
+Contributing to an existing translation
+---------------------------------------
 As a contributor for a language XX, you should first check TEAMS file in
 this directory to see whether a dedicated repository for your language XX
 exists. Fork the dedicated repository and start to work if it exists.
 
+Sometime, contributors may find that the translations of their Git
+distributions are quite different with the translations of the
+corresponding version from Git official. This is because some Git
+distributions (such as from Ubuntu, etc.) have their own l10n workflow.
+For this case, wrong translations should be reported and fixed through
+their workflows.
+
+
+Creating a new language translation
+-----------------------------------
 If you are the first contributor for the language XX, please fork this
 repository, prepare and/or update the translated message file po/XX.po
 (described later), and ask the l10n coordinator to pull your work.
@@ -23,6 +39,9 @@
 language, so that the l10n coordinator only needs to interact with one
 person per language.
 
+
+Translation Process Flow
+------------------------
 The overall data-flow looks like this:
 
     +-------------------+            +------------------+
diff --git a/revision.c b/revision.c
index ab97ffd..9b9d77d 100644
--- a/revision.c
+++ b/revision.c
@@ -2173,6 +2173,21 @@
 	return 1;
 }
 
+static void NORETURN diagnose_missing_default(const char *def)
+{
+	unsigned char sha1[20];
+	int flags;
+	const char *refname;
+
+	refname = resolve_ref_unsafe(def, 0, sha1, &flags);
+	if (!refname || !(flags & REF_ISSYMREF) || (flags & REF_ISBROKEN))
+		die(_("your current branch appears to be broken"));
+
+	skip_prefix(refname, "refs/heads/", &refname);
+	die(_("your current branch '%s' does not have any commits yet"),
+	    refname);
+}
+
 /*
  * Parse revision information, filling in the "rev_info" structure,
  * and removing the used arguments from the argument list.
@@ -2302,7 +2317,7 @@
 		struct object *object;
 		struct object_context oc;
 		if (get_sha1_with_context(revs->def, 0, sha1, &oc))
-			die("bad default revision '%s'", revs->def);
+			diagnose_missing_default(revs->def);
 		object = get_reference(revs, revs->def, sha1, 0);
 		add_pending_object_with_mode(revs, object, revs->def, oc.mode);
 	}
diff --git a/run-command.c b/run-command.c
index 4d73e90..0d01671 100644
--- a/run-command.c
+++ b/run-command.c
@@ -200,7 +200,6 @@
 #endif
 
 #ifndef GIT_WINDOWS_NATIVE
-static int child_err = 2;
 static int child_notifier = -1;
 
 static void notify_parent(void)
@@ -212,17 +211,6 @@
 	 */
 	xwrite(child_notifier, "", 1);
 }
-
-static NORETURN void die_child(const char *err, va_list params)
-{
-	vwritef(child_err, "fatal: ", err, params);
-	exit(128);
-}
-
-static void error_child(const char *err, va_list params)
-{
-	vwritef(child_err, "error: ", err, params);
-}
 #endif
 
 static inline void set_cloexec(int fd)
@@ -362,11 +350,10 @@
 		 * in subsequent call paths use the parent's stderr.
 		 */
 		if (cmd->no_stderr || need_err) {
-			child_err = dup(2);
+			int child_err = dup(2);
 			set_cloexec(child_err);
+			set_error_handle(fdopen(child_err, "w"));
 		}
-		set_die_routine(die_child);
-		set_error_routine(error_child);
 
 		close(notify_pipe[0]);
 		set_cloexec(notify_pipe[1]);
diff --git a/setup.c b/setup.c
index 82c0cc2..465b42a 100644
--- a/setup.c
+++ b/setup.c
@@ -402,9 +402,9 @@
 	struct strbuf path = STRBUF_INIT;
 	struct stat st;
 
-	strbuf_addf(&path, "%s/gitfile", gitdir);
+	strbuf_addf(&path, "%s/gitdir", gitdir);
 	if (stat(path.buf, &st) || st.st_mtime + 24 * 3600 < time(NULL))
-		write_file(path.buf, 0, "%s\n", gitfile);
+		write_file(path.buf, 1, "%s\n", gitfile);
 	strbuf_release(&path);
 }
 
diff --git a/sha1_file.c b/sha1_file.c
index 1cee438..17262e1 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -377,15 +377,12 @@
 	char *map;
 	size_t mapsz;
 	struct stat st;
-	const char alt_file_name[] = "info/alternates";
-	/* Given that relative_base is no longer than PATH_MAX,
-	   ensure that "path" has enough space to append "/", the
-	   file name, "info/alternates", and a trailing NUL.  */
-	char path[PATH_MAX + 1 + sizeof alt_file_name];
+	char *path;
 	int fd;
 
-	sprintf(path, "%s/%s", relative_base, alt_file_name);
+	path = xstrfmt("%s/info/alternates", relative_base);
 	fd = git_open_noatime(path);
+	free(path);
 	if (fd < 0)
 		return;
 	if (fstat(fd, &st) || (st.st_size == 0)) {
@@ -1461,7 +1458,10 @@
 	static int sha1_file_open_flag = O_NOATIME;
 
 	for (;;) {
-		int fd = open(name, O_RDONLY | sha1_file_open_flag);
+		int fd;
+
+		errno = 0;
+		fd = open(name, O_RDONLY | sha1_file_open_flag);
 		if (fd >= 0)
 			return fd;
 
diff --git a/strbuf.c b/strbuf.c
index bbaf32e..c606f33 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -364,19 +364,19 @@
 
 	strbuf_grow(sb, hint ? hint : 8192);
 	for (;;) {
-		ssize_t cnt;
+		ssize_t want = sb->alloc - sb->len - 1;
+		ssize_t got = read_in_full(fd, sb->buf + sb->len, want);
 
-		cnt = xread(fd, sb->buf + sb->len, sb->alloc - sb->len - 1);
-		if (cnt < 0) {
+		if (got < 0) {
 			if (oldalloc == 0)
 				strbuf_release(sb);
 			else
 				strbuf_setlen(sb, oldlen);
 			return -1;
 		}
-		if (!cnt)
+		sb->len += got;
+		if (got < want)
 			break;
-		sb->len += cnt;
 		strbuf_grow(sb, 8192);
 	}
 
diff --git a/t/t0002-gitfile.sh b/t/t0002-gitfile.sh
index 37e9396..9393322 100755
--- a/t/t0002-gitfile.sh
+++ b/t/t0002-gitfile.sh
@@ -99,4 +99,21 @@
 	test "$SHA" = "$(git rev-list HEAD)"
 '
 
+test_expect_success 'setup_git_dir twice in subdir' '
+	git init sgd &&
+	(
+		cd sgd &&
+		git config alias.lsfi ls-files &&
+		mv .git .realgit &&
+		echo "gitdir: .realgit" >.git &&
+		mkdir subdir &&
+		cd subdir &&
+		>foo &&
+		git add foo &&
+		git lsfi >actual &&
+		echo foo >expected &&
+		test_cmp expected actual
+	)
+'
+
 test_done
diff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh
index 601d02d..f92dd1f 100755
--- a/t/t0090-cache-tree.sh
+++ b/t/t0090-cache-tree.sh
@@ -218,4 +218,14 @@
 	! test -s errors
 '
 
+test_expect_success 'switching trees does not invalidate shared index' '
+	git update-index --split-index &&
+	>split &&
+	git add split &&
+	test-dump-split-index .git/index | grep -v ^own >before &&
+	git commit -m "as-is" &&
+	test-dump-split-index .git/index | grep -v ^own >after &&
+	test_cmp before after
+'
+
 test_done
diff --git a/t/t1090-sparse-checkout-scope.sh b/t/t1090-sparse-checkout-scope.sh
new file mode 100755
index 0000000..1f61eb3
--- /dev/null
+++ b/t/t1090-sparse-checkout-scope.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+
+test_description='sparse checkout scope tests'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+	echo "initial" >a &&
+	echo "initial" >b &&
+	echo "initial" >c &&
+	git add a b c &&
+	git commit -m "initial commit"
+'
+
+test_expect_success 'create feature branch' '
+	git checkout -b feature &&
+	echo "modified" >b &&
+	echo "modified" >c &&
+	git add b c &&
+	git commit -m "modification"
+'
+
+test_expect_success 'perform sparse checkout of master' '
+	git config --local --bool core.sparsecheckout true &&
+	echo "!/*" >.git/info/sparse-checkout &&
+	echo "/a" >>.git/info/sparse-checkout &&
+	echo "/c" >>.git/info/sparse-checkout &&
+	git checkout master &&
+	test_path_is_file a &&
+	test_path_is_missing b &&
+	test_path_is_file c
+'
+
+test_expect_success 'merge feature branch into sparse checkout of master' '
+	git merge feature &&
+	test_path_is_file a &&
+	test_path_is_missing b &&
+	test_path_is_file c &&
+	test "$(cat c)" = "modified"
+'
+
+test_expect_success 'return to full checkout of master' '
+	git checkout feature &&
+	echo "/*" >.git/info/sparse-checkout &&
+	git checkout master &&
+	test_path_is_file a &&
+	test_path_is_file b &&
+	test_path_is_file c &&
+	test "$(cat b)" = "modified"
+'
+
+test_done
diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh
index ebe7c3b..310f93f 100755
--- a/t/t1502-rev-parse-parseopt.sh
+++ b/t/t1502-rev-parse-parseopt.sh
@@ -3,7 +3,40 @@
 test_description='test git rev-parse --parseopt'
 . ./test-lib.sh
 
-sed -e 's/^|//' >expect <<\END_EXPECT
+test_expect_success 'setup optionspec' '
+	sed -e "s/^|//" >optionspec <<\EOF
+|some-command [options] <args>...
+|
+|some-command does foo and bar!
+|--
+|h,help    show the help
+|
+|foo       some nifty option --foo
+|bar=      some cool option --bar with an argument
+|b,baz     a short and long option
+|
+| An option group Header
+|C?        option C with an optional argument
+|d,data?   short and long option with an optional argument
+|
+| Argument hints
+|B=arg     short option required argument
+|bar2=arg  long option required argument
+|e,fuz=with-space  short and long option required argument
+|s?some    short option optional argument
+|long?data long option optional argument
+|g,fluf?path     short and long option optional argument
+|longest=very-long-argument-hint  a very long argument hint
+|pair=key=value  with an equals sign in the hint
+|short-hint=a    with a one symbol hint
+|
+|Extras
+|extra1    line above used to cause a segfault but no longer does
+EOF
+'
+
+test_expect_success 'test --parseopt help output' '
+	sed -e "s/^|//" >expect <<\END_EXPECT &&
 |cat <<\EOF
 |usage: some-command [options] <args>...
 |
@@ -28,49 +61,23 @@
 |    -g, --fluf[=<path>]   short and long option optional argument
 |    --longest <very-long-argument-hint>
 |                          a very long argument hint
+|    --pair <key=value>    with an equals sign in the hint
+|    --short-hint <a>      with a one symbol hint
 |
 |Extras
 |    --extra1              line above used to cause a segfault but no longer does
 |
 |EOF
 END_EXPECT
-
-sed -e 's/^|//' >optionspec <<\EOF
-|some-command [options] <args>...
-|
-|some-command does foo and bar!
-|--
-|h,help    show the help
-|
-|foo       some nifty option --foo
-|bar=      some cool option --bar with an argument
-|b,baz     a short and long option
-|
-| An option group Header
-|C?        option C with an optional argument
-|d,data?   short and long option with an optional argument
-|
-| Argument hints
-|B=arg     short option required argument
-|bar2=arg  long option required argument
-|e,fuz=with-space  short and long option required argument
-|s?some    short option optional argument
-|long?data long option optional argument
-|g,fluf?path     short and long option optional argument
-|longest=very-long-argument-hint  a very long argument hint
-|
-|Extras
-|extra1    line above used to cause a segfault but no longer does
-EOF
-
-test_expect_success 'test --parseopt help output' '
 	test_expect_code 129 git rev-parse --parseopt -- -h > output < optionspec &&
 	test_i18ncmp expect output
 '
 
-cat > expect <<EOF
+test_expect_success 'setup expect.1' "
+	cat > expect <<EOF
 set -- --foo --bar 'ham' -b -- 'arg'
 EOF
+"
 
 test_expect_success 'test --parseopt' '
 	git rev-parse --parseopt -- --foo --bar=ham --baz arg < optionspec > output &&
@@ -82,9 +89,11 @@
 	test_cmp expect output
 '
 
-cat > expect <<EOF
+test_expect_success 'setup expect.2' "
+	cat > expect <<EOF
 set -- --foo -- 'arg' '--bar=ham'
 EOF
+"
 
 test_expect_success 'test --parseopt with --' '
 	git rev-parse --parseopt -- --foo -- arg --bar=ham < optionspec > output &&
@@ -96,54 +105,66 @@
 	test_cmp expect output
 '
 
-cat > expect <<EOF
+test_expect_success 'setup expect.3' "
+	cat > expect <<EOF
 set -- --foo -- '--' 'arg' '--bar=ham'
 EOF
+"
 
 test_expect_success 'test --parseopt --keep-dashdash' '
 	git rev-parse --parseopt --keep-dashdash -- --foo -- arg --bar=ham < optionspec > output &&
 	test_cmp expect output
 '
 
-cat >expect <<EOF
+test_expect_success 'setup expect.4' "
+	cat >expect <<EOF
 set -- --foo -- '--' 'arg' '--spam=ham'
 EOF
+"
 
 test_expect_success 'test --parseopt --keep-dashdash --stop-at-non-option with --' '
 	git rev-parse --parseopt --keep-dashdash --stop-at-non-option -- --foo -- arg --spam=ham <optionspec >output &&
 	test_cmp expect output
 '
 
-cat > expect <<EOF
+test_expect_success 'setup expect.5' "
+	cat > expect <<EOF
 set -- --foo -- 'arg' '--spam=ham'
 EOF
+"
 
 test_expect_success 'test --parseopt --keep-dashdash --stop-at-non-option without --' '
 	git rev-parse --parseopt --keep-dashdash --stop-at-non-option -- --foo arg --spam=ham <optionspec >output &&
 	test_cmp expect output
 '
 
-cat > expect <<EOF
+test_expect_success 'setup expect.6' "
+	cat > expect <<EOF
 set -- --foo --bar='z' --baz -C'Z' --data='A' -- 'arg'
 EOF
+"
 
 test_expect_success 'test --parseopt --stuck-long' '
 	git rev-parse --parseopt --stuck-long -- --foo --bar=z -b arg -CZ -dA <optionspec >output &&
 	test_cmp expect output
 '
 
-cat > expect <<EOF
+test_expect_success 'setup expect.7' "
+	cat > expect <<EOF
 set -- --data='' -C --baz -- 'arg'
 EOF
+"
 
 test_expect_success 'test --parseopt --stuck-long and empty optional argument' '
 	git rev-parse --parseopt --stuck-long -- --data= arg -C -b <optionspec >output &&
 	test_cmp expect output
 '
 
-cat > expect <<EOF
+test_expect_success 'setup expect.8' "
+	cat > expect <<EOF
 set -- --data --baz -- 'arg'
 EOF
+"
 
 test_expect_success 'test --parseopt --stuck-long and long option with unset optional argument' '
 	git rev-parse --parseopt --stuck-long -- --data arg -b <optionspec >output &&
diff --git a/t/t1509-root-worktree.sh b/t/t1509-root-worktree.sh
index b6977d4..553a3f6 100755
--- a/t/t1509-root-worktree.sh
+++ b/t/t1509-root-worktree.sh
@@ -125,7 +125,7 @@
 ONE_SHA1=d00491fd7e5bb6fa28c517a0bb32b8b506539d4d
 
 test_expect_success 'setup' '
-	rm -rf /foo
+	rm -rf /foo &&
 	mkdir /foo &&
 	mkdir /foo/bar &&
 	echo 1 > /foo/foome &&
@@ -218,7 +218,7 @@
 
 test_expect_success 'go to /' 'cd /'
 test_expect_success 'setup' '
-	rm -rf /.git
+	rm -rf /.git &&
 	echo "Initialized empty Git repository in /.git/" > expected &&
 	git init > result &&
 	test_cmp expected result
@@ -241,8 +241,8 @@
 
 # DESTROYYYYY!!!!!
 test_expect_success 'setup' '
-	rm -rf /refs /objects /info /hooks
-	rm /*
+	rm -rf /refs /objects /info /hooks &&
+	rm -f /expected /ls.expected /me /result &&
 	cd / &&
 	echo "Initialized empty Git repository in /" > expected &&
 	git init --bare > result &&
diff --git a/t/t2019-checkout-ambiguous-ref.sh b/t/t2019-checkout-ambiguous-ref.sh
index 8396320..199b22d 100755
--- a/t/t2019-checkout-ambiguous-ref.sh
+++ b/t/t2019-checkout-ambiguous-ref.sh
@@ -69,7 +69,7 @@
 	)
 '
 
-test_expect_success 'wildcard ambiguation, refs lose' '
+test_expect_success !MINGW 'wildcard ambiguation, refs lose' '
 	git init ambi2 &&
 	(
 		cd ambi2 &&
diff --git a/t/t3020-ls-files-error-unmatch.sh b/t/t3020-ls-files-error-unmatch.sh
index ca01053..124e73b 100755
--- a/t/t3020-ls-files-error-unmatch.sh
+++ b/t/t3020-ls-files-error-unmatch.sh
@@ -22,7 +22,7 @@
     'test_must_fail git ls-files --error-unmatch foo bar-does-not-match'
 
 test_expect_success \
-    'git ls-files --error-unmatch should succeed eith matched paths.' \
+    'git ls-files --error-unmatch should succeed with matched paths.' \
     'git ls-files --error-unmatch foo bar'
 
 test_done
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index 1b2e981..19277dd 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -871,4 +871,18 @@
 	test_must_fail git log --graph --no-walk
 '
 
+test_expect_success 'log diagnoses bogus HEAD' '
+	git init empty &&
+	test_must_fail git -C empty log 2>stderr &&
+	test_i18ngrep does.not.have.any.commits stderr &&
+	echo 1234abcd >empty/.git/refs/heads/master &&
+	test_must_fail git -C empty log 2>stderr &&
+	test_i18ngrep broken stderr &&
+	echo "ref: refs/heads/invalid.lock" >empty/.git/HEAD &&
+	test_must_fail git -C empty log 2>stderr &&
+	test_i18ngrep broken stderr &&
+	test_must_fail git -C empty log --default totally-bogus 2>stderr &&
+	test_i18ngrep broken stderr
+'
+
 test_done
diff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh
index 654adda..cca2338 100755
--- a/t/t5004-archive-corner-cases.sh
+++ b/t/t5004-archive-corner-cases.sh
@@ -115,4 +115,44 @@
 	check_dir extract sub
 '
 
+ZIPINFO=zipinfo
+
+test_lazy_prereq ZIPINFO '
+	n=$("$ZIPINFO" "$TEST_DIRECTORY"/t5004/empty.zip | sed -n "2s/.* //p")
+	test "x$n" = "x0"
+'
+
+test_expect_success ZIPINFO 'zip archive with many entries' '
+	# add a directory with 256 files
+	mkdir 00 &&
+	for a in 0 1 2 3 4 5 6 7 8 9 a b c d e f
+	do
+		for b in 0 1 2 3 4 5 6 7 8 9 a b c d e f
+		do
+			: >00/$a$b
+		done
+	done &&
+	git add 00 &&
+	git commit -m "256 files in 1 directory" &&
+
+	# duplicate it to get 65536 files in 256 directories
+	subtree=$(git write-tree --prefix=00/) &&
+	for c in 0 1 2 3 4 5 6 7 8 9 a b c d e f
+	do
+		for d in 0 1 2 3 4 5 6 7 8 9 a b c d e f
+		do
+			echo "040000 tree $subtree	$c$d"
+		done
+	done >tree &&
+	tree=$(git mktree <tree) &&
+
+	# zip them
+	git archive -o many.zip $tree &&
+
+	# check the number of entries in the ZIP file directory
+	expr 65536 + 256 >expect &&
+	"$ZIPINFO" many.zip | head -2 | sed -n "2s/.* //p" >actual &&
+	test_cmp expect actual
+'
+
 test_done
diff --git a/t/t5603-clone-dirname.sh b/t/t5603-clone-dirname.sh
new file mode 100755
index 0000000..765cc43
--- /dev/null
+++ b/t/t5603-clone-dirname.sh
@@ -0,0 +1,106 @@
+#!/bin/sh
+
+test_description='check output directory names used by git-clone'
+. ./test-lib.sh
+
+# we use a fake ssh wrapper that ignores the arguments
+# entirely; we really only care that we get _some_ repo,
+# as the real test is what clone does on the local side
+test_expect_success 'setup ssh wrapper' '
+	write_script "$TRASH_DIRECTORY/ssh-wrapper" <<-\EOF &&
+	git upload-pack "$TRASH_DIRECTORY"
+	EOF
+	GIT_SSH="$TRASH_DIRECTORY/ssh-wrapper" &&
+	export GIT_SSH &&
+	export TRASH_DIRECTORY
+'
+
+# make sure that cloning $1 results in local directory $2
+test_clone_dir () {
+	url=$1; shift
+	dir=$1; shift
+	expect=success
+	bare=non-bare
+	clone_opts=
+	for i in "$@"
+	do
+		case "$i" in
+		fail)
+			expect=failure
+			;;
+		bare)
+			bare=bare
+			clone_opts=--bare
+			;;
+		esac
+	done
+	test_expect_$expect "clone of $url goes to $dir ($bare)" "
+		rm -rf $dir &&
+		git clone $clone_opts $url &&
+		test_path_is_dir $dir
+	"
+}
+
+# basic syntax with bare and non-bare variants
+test_clone_dir host:foo foo
+test_clone_dir host:foo foo.git bare
+test_clone_dir host:foo.git foo
+test_clone_dir host:foo.git foo.git bare
+test_clone_dir host:foo/.git foo
+test_clone_dir host:foo/.git foo.git bare
+
+# similar, but using ssh URL rather than host:path syntax
+test_clone_dir ssh://host/foo foo
+test_clone_dir ssh://host/foo foo.git bare
+test_clone_dir ssh://host/foo.git foo
+test_clone_dir ssh://host/foo.git foo.git bare
+test_clone_dir ssh://host/foo/.git foo
+test_clone_dir ssh://host/foo/.git foo.git bare
+
+# we should remove trailing slashes and .git suffixes
+test_clone_dir ssh://host/foo/ foo
+test_clone_dir ssh://host/foo/// foo
+test_clone_dir ssh://host/foo/.git/ foo
+test_clone_dir ssh://host/foo.git/ foo
+test_clone_dir ssh://host/foo.git/// foo
+test_clone_dir ssh://host/foo///.git/ foo
+test_clone_dir ssh://host/foo/.git/// foo
+
+test_clone_dir host:foo/ foo
+test_clone_dir host:foo/// foo
+test_clone_dir host:foo.git/ foo
+test_clone_dir host:foo/.git/ foo
+test_clone_dir host:foo.git/// foo
+test_clone_dir host:foo///.git/ foo
+test_clone_dir host:foo/.git/// foo
+
+# omitting the path should default to the hostname
+test_clone_dir ssh://host/ host
+test_clone_dir ssh://host:1234/ host fail
+test_clone_dir ssh://user@host/ host fail
+test_clone_dir host:/ host fail
+
+# auth materials should be redacted
+test_clone_dir ssh://user:password@host/ host fail
+test_clone_dir ssh://user:password@host:1234/ host fail
+test_clone_dir ssh://user:passw@rd@host:1234/ host fail
+test_clone_dir user@host:/ host fail
+test_clone_dir user:password@host:/ host fail
+test_clone_dir user:passw@rd@host:/ host fail
+
+# auth-like material should not be dropped
+test_clone_dir ssh://host/foo@bar foo@bar
+test_clone_dir ssh://host/foo@bar.git foo@bar
+test_clone_dir ssh://user:password@host/foo@bar foo@bar
+test_clone_dir ssh://user:passw@rd@host/foo@bar.git foo@bar
+
+test_clone_dir host:/foo@bar foo@bar
+test_clone_dir host:/foo@bar.git foo@bar
+test_clone_dir user:password@host:/foo@bar foo@bar
+test_clone_dir user:passw@rd@host:/foo@bar.git foo@bar
+
+# trailing port-like numbers should not be stripped for paths
+test_clone_dir ssh://user:password@host/test:1234 1234
+test_clone_dir ssh://user:password@host/test:1234.git 1234
+
+test_done
diff --git a/t/t7006-pager.sh b/t/t7006-pager.sh
index 947b690..6ea7ac4 100755
--- a/t/t7006-pager.sh
+++ b/t/t7006-pager.sh
@@ -447,4 +447,13 @@
 	test_cmp expect actual
 '
 
+test_expect_success 'command with underscores does not complain' '
+	write_script git-under_score <<-\EOF &&
+	echo ok
+	EOF
+	git --exec-path=. under_score >actual 2>&1 &&
+	echo ok >expect &&
+	test_cmp expect actual
+'
+
 test_done
diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh
index 99be5d9..634808a 100755
--- a/t/t7300-clean.sh
+++ b/t/t7300-clean.sh
@@ -432,9 +432,7 @@
 	(
 		cd foo &&
 		git init &&
-		>hello.world
-		git add . &&
-		git commit -a -m nested
+		test_commit nested hello.world
 	) &&
 	(
 		cd bar &&
@@ -443,9 +441,7 @@
 	(
 		cd baz/boo &&
 		git init &&
-		>deeper.world
-		git add . &&
-		git commit -a -m deeply.nested
+		test_commit deeply.nested deeper.world
 	) &&
 	git clean -f -d &&
 	test -f foo/.git/index &&
@@ -461,9 +457,7 @@
 	(
 		cd foo &&
 		git init &&
-		>hello.world
-		git add . &&
-		git commit -a -m nested
+		test_commit nested hello.world
 	) &&
 	(
 		cd bar &&
@@ -472,9 +466,7 @@
 	(
 		cd baz/boo &&
 		git init &&
-		>deeper.world
-		git add . &&
-		git commit -a -m deeply.nested
+		test_commit deeply.nested deeper.world
 	) &&
 	git clean -f -f -d &&
 	! test -d foo &&
diff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh
index bd0ab46..322c436 100755
--- a/t/t7513-interpret-trailers.sh
+++ b/t/t7513-interpret-trailers.sh
@@ -93,12 +93,39 @@
 		Acked-by: Johan
 		Reviewed-by: Peff
 	EOF
-	echo "Acked-by: Johan" |
+	{ echo; echo "Acked-by: Johan"; } |
 	git -c "trailer.Acked-by.ifexists=addifdifferent" interpret-trailers \
 		--trailer "Reviewed-by: Peff" --trailer "Acked-by: Johan" >actual &&
 	test_cmp expected actual
 '
 
+test_expect_success 'with only a title in the message' '
+	cat >expected <<-\EOF &&
+		area: change
+
+		Reviewed-by: Peff
+		Acked-by: Johan
+	EOF
+	echo "area: change" |
+	git interpret-trailers --trailer "Reviewed-by: Peff" \
+		--trailer "Acked-by: Johan" >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'with multiline title in the message' '
+	cat >expected <<-\EOF &&
+		place of
+		code: change
+
+		Reviewed-by: Peff
+		Acked-by: Johan
+	EOF
+	printf "%s\n" "place of" "code: change" |
+	git interpret-trailers --trailer "Reviewed-by: Peff" \
+		--trailer "Acked-by: Johan" >actual &&
+	test_cmp expected actual
+'
+
 test_expect_success 'with config setup' '
 	git config trailer.ack.key "Acked-by: " &&
 	cat >expected <<-\EOF &&
diff --git a/t/test-lib.sh b/t/test-lib.sh
index cea6cda..16c4d7b 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -531,6 +531,10 @@
 	fi
 }
 
+want_trace () {
+	test "$trace" = t && test "$verbose" = t
+}
+
 # This is a separate function because some tests use
 # "return" to end a test_expect_success block early
 # (and we want to make sure we run any cleanup like
@@ -538,7 +542,7 @@
 test_eval_inner_ () {
 	# Do not add anything extra (including LF) after '$*'
 	eval "
-		test \"$trace\" = t && set -x
+		want_trace && set -x
 		$*"
 }
 
@@ -554,7 +558,7 @@
 	{
 		test_eval_inner_ "$@" </dev/null >&3 2>&4
 		test_eval_ret_=$?
-		if test "$trace" = t
+		if want_trace
 		then
 			set +x
 			if test "$test_eval_ret_" != 0
@@ -571,12 +575,17 @@
 	expecting_failure=$2
 
 	if test "${GIT_TEST_CHAIN_LINT:-1}" != 0; then
+		# turn off tracing for this test-eval, as it simply creates
+		# confusing noise in the "-x" output
+		trace_tmp=$trace
+		trace=
 		# 117 is magic because it is unlikely to match the exit
 		# code of other programs
 		test_eval_ "(exit 117) && $1"
 		if test "$?" != 117; then
 			error "bug in the test script: broken &&-chain: $1"
 		fi
+		trace=$trace_tmp
 	fi
 
 	setup_malloc_check
diff --git a/test-dump-split-index.c b/test-dump-split-index.c
index 9cf3112..861d28c 100644
--- a/test-dump-split-index.c
+++ b/test-dump-split-index.c
@@ -26,9 +26,11 @@
 		       sha1_to_hex(ce->sha1), ce_stage(ce), ce->name);
 	}
 	printf("replacements:");
-	ewah_each_bit(si->replace_bitmap, show_bit, NULL);
+	if (si->replace_bitmap)
+		ewah_each_bit(si->replace_bitmap, show_bit, NULL);
 	printf("\ndeletions:");
-	ewah_each_bit(si->delete_bitmap, show_bit, NULL);
+	if (si->delete_bitmap)
+		ewah_each_bit(si->delete_bitmap, show_bit, NULL);
 	printf("\n");
 	return 0;
 }
diff --git a/trailer.c b/trailer.c
index 4b14a56..6f3416f 100644
--- a/trailer.c
+++ b/trailer.c
@@ -735,13 +735,22 @@
  */
 static int find_trailer_start(struct strbuf **lines, int count)
 {
-	int start, only_spaces = 1;
+	int start, end_of_title, only_spaces = 1;
+
+	/* The first paragraph is the title and cannot be trailers */
+	for (start = 0; start < count; start++) {
+		if (lines[start]->buf[0] == comment_line_char)
+			continue;
+		if (contains_only_spaces(lines[start]->buf))
+			break;
+	}
+	end_of_title = start;
 
 	/*
 	 * Get the start of the trailers by looking starting from the end
 	 * for a line with only spaces before lines with one separator.
 	 */
-	for (start = count - 1; start >= 0; start--) {
+	for (start = count - 1; start >= end_of_title; start--) {
 		if (lines[start]->buf[0] == comment_line_char)
 			continue;
 		if (contains_only_spaces(lines[start]->buf)) {
diff --git a/transport-helper.c b/transport-helper.c
index 5d99a6b..68e498e 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -490,7 +490,8 @@
 		else
 			private = xstrdup(name);
 		if (private) {
-			read_ref(private, posn->old_sha1);
+			if (read_ref(private, posn->old_sha1) < 0)
+				die("Could not read ref %s", private);
 			free(private);
 		}
 	}
@@ -1019,7 +1020,10 @@
 		if (eon) {
 			if (has_attribute(eon + 1, "unchanged")) {
 				(*tail)->status |= REF_STATUS_UPTODATE;
-				read_ref((*tail)->name, (*tail)->old_sha1);
+				if (read_ref((*tail)->name,
+					     (*tail)->old_sha1) < 0)
+					die(N_("Could not read ref %s"),
+					    (*tail)->name);
 			}
 		}
 		tail = &((*tail)->next);
diff --git a/unpack-trees.c b/unpack-trees.c
index 2927660..6e9f755 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -224,6 +224,9 @@
 		struct cache_entry *ce = index->cache[i];
 
 		if (ce->ce_flags & CE_UPDATE) {
+			if (ce->ce_flags & CE_WT_REMOVE)
+				die("BUG: both update and delete flags are set on %s",
+				    ce->name);
 			display_progress(progress, ++cnt);
 			ce->ce_flags &= ~CE_UPDATE;
 			if (o->update && !o->dry_run) {
@@ -293,6 +296,7 @@
 		if (!(ce->ce_flags & CE_UPDATE) && verify_uptodate_sparse(ce, o))
 			return -1;
 		ce->ce_flags |= CE_WT_REMOVE;
+		ce->ce_flags &= ~CE_UPDATE;
 	}
 	if (was_skip_worktree && !ce_skip_worktree(ce)) {
 		if (verify_absent_sparse(ce, ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN, o))
@@ -1437,15 +1441,18 @@
 	if (!len)
 		return 0;
 	else if (len > 0) {
-		char path[PATH_MAX + 1];
-		memcpy(path, ce->name, len);
-		path[len] = 0;
-		if (lstat(path, &st))
-			return error("cannot stat '%s': %s", path,
-					strerror(errno));
+		char *path;
+		int ret;
 
-		return check_ok_to_remove(path, len, DT_UNKNOWN, NULL, &st,
-				error_type, o);
+		path = xmemdupz(ce->name, len);
+		if (lstat(path, &st))
+			ret = error("cannot stat '%s': %s", path,
+					strerror(errno));
+		else
+			ret = check_ok_to_remove(path, len, DT_UNKNOWN, NULL,
+						 &st, error_type, o);
+		free(path);
+		return ret;
 	} else if (lstat(ce->name, &st)) {
 		if (errno != ENOENT)
 			return error("cannot stat '%s': %s", ce->name,
diff --git a/usage.c b/usage.c
index ed14645..82ff131 100644
--- a/usage.c
+++ b/usage.c
@@ -6,23 +6,22 @@
 #include "git-compat-util.h"
 #include "cache.h"
 
+static FILE *error_handle;
+static int tweaked_error_buffering;
+
 void vreportf(const char *prefix, const char *err, va_list params)
 {
-	char msg[4096];
-	vsnprintf(msg, sizeof(msg), err, params);
-	fprintf(stderr, "%s%s\n", prefix, msg);
-}
+	FILE *fh = error_handle ? error_handle : stderr;
 
-void vwritef(int fd, const char *prefix, const char *err, va_list params)
-{
-	char msg[4096];
-	int len = vsnprintf(msg, sizeof(msg), err, params);
-	if (len > sizeof(msg))
-		len = sizeof(msg);
+	fflush(fh);
+	if (!tweaked_error_buffering) {
+		setvbuf(fh, NULL, _IOLBF, 0);
+		tweaked_error_buffering = 1;
+	}
 
-	write_in_full(fd, prefix, strlen(prefix));
-	write_in_full(fd, msg, len);
-	write_in_full(fd, "\n", 1);
+	fputs(prefix, fh);
+	vfprintf(fh, err, params);
+	fputc('\n', fh);
 }
 
 static NORETURN void usage_builtin(const char *err, va_list params)
@@ -76,6 +75,12 @@
 	die_is_recursing = routine;
 }
 
+void set_error_handle(FILE *fh)
+{
+	error_handle = fh;
+	tweaked_error_buffering = 0;
+}
+
 void NORETURN usagef(const char *err, ...)
 {
 	va_list params;
diff --git a/wt-status.c b/wt-status.c
index eaed4fe..e8c39ef 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -1,5 +1,4 @@
 #include "cache.h"
-#include "pathspec.h"
 #include "wt-status.h"
 #include "object.h"
 #include "dir.h"
diff --git a/wt-status.h b/wt-status.h
index e0a99f7..c9b3b74 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -4,6 +4,7 @@
 #include <stdio.h>
 #include "string-list.h"
 #include "color.h"
+#include "pathspec.h"
 
 enum color_wt_status {
 	WT_STATUS_HEADER = 0,