Merge branch 'ld/push-porcelain-output-format'

* ld/push-porcelain-output-format:
  add --porcelain option to git-push
diff --git a/Documentation/asciidoc.conf b/Documentation/asciidoc.conf
index dc76e7f..87a90f2 100644
--- a/Documentation/asciidoc.conf
+++ b/Documentation/asciidoc.conf
@@ -17,6 +17,7 @@
 startsb=[
 endsb=]
 tilde=~
+backtick=`
 
 ifdef::backend-docbook[]
 [linkgit-inlinemacro]
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 2fecbe3..cb6832b 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -456,7 +456,9 @@
 it will be treated as a shell command.  For example, defining
 "alias.new = !gitk --all --not ORIG_HEAD", the invocation
 "git new" is equivalent to running the shell command
-"gitk --all --not ORIG_HEAD".
+"gitk --all --not ORIG_HEAD".  Note that shell commands will be
+executed from the top-level directory of a repository, which may
+not necessarily be the current directory.
 
 apply.whitespace::
 	Tells 'git-apply' how to handle whitespaces, in the same way
@@ -1043,6 +1045,12 @@
 	over HTTPS. Can be overridden by the 'GIT_SSL_KEY' environment
 	variable.
 
+http.sslCertPasswordProtected::
+	Enable git's password prompt for the SSL certificate.  Otherwise
+	OpenSSL will prompt the user, possibly many times, if the
+	certificate or private key is encrypted.  Can be overridden by the
+	'GIT_SSL_CERT_PASSWORD_PROTECTED' environment variable.
+
 http.sslCAInfo::
 	File containing the certificates to verify the peer with when
 	fetching or pushing over HTTPS. Can be overridden by the
diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt
index 6d92cbe..32e689b 100644
--- a/Documentation/git-am.txt
+++ b/Documentation/git-am.txt
@@ -13,7 +13,7 @@
 	 [--3way] [--interactive] [--committer-date-is-author-date]
 	 [--ignore-date]
 	 [--whitespace=<option>] [-C<n>] [-p<n>] [--directory=<dir>]
-	 [--reject]
+	 [--reject] [-q | --quiet]
 	 [<mbox> | <Maildir>...]
 'git am' (--skip | --resolved | --abort)
 
@@ -39,6 +39,10 @@
 --keep::
 	Pass `-k` flag to 'git-mailinfo' (see linkgit:git-mailinfo[1]).
 
+-q::
+--quiet::
+	Be quiet. Only print error messages.
+
 -u::
 --utf8::
 	Pass `-u` flag to 'git-mailinfo' (see linkgit:git-mailinfo[1]).
diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt
index ffc02c7..63e7a42 100644
--- a/Documentation/git-bisect.txt
+++ b/Documentation/git-bisect.txt
@@ -164,9 +164,8 @@
 $ git bisect skip                 # Current version cannot be tested
 ------------
 
-But computing the commit to test may be slower afterwards and git may
-eventually not be able to tell the first bad commit among a bad commit
-and one or more skipped commits.
+But git may eventually be unable to tell the first bad commit among
+a bad commit and one or more skipped commits.
 
 You can even skip a range of commits, instead of just one commit,
 using the "'<commit1>'..'<commit2>'" notation. For example:
diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt
index fccb82d..b753c9d 100644
--- a/Documentation/git-grep.txt
+++ b/Documentation/git-grep.txt
@@ -122,6 +122,14 @@
 -<num>::
 	A shortcut for specifying -C<num>.
 
+-p::
+--show-function::
+	Show the preceding line that contains the function name of
+	the match, unless the matching line is a function name itself.
+	The name is determined in the same way as 'git diff' works out
+	patch hunk headers (see 'Defining a custom hunk-header' in
+	linkgit:gitattributes[5]).
+
 -f <file>::
 	Read patterns from <file>, one per line.
 
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 26f3b7b..db1b71d 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -236,6 +236,10 @@
 	is used instead ('git-merge-recursive' when merging a single
 	head, 'git-merge-octopus' otherwise).  This implies --merge.
 
+-q::
+--quiet::
+	Be quiet. Implies --no-stat.
+
 -v::
 --verbose::
 	Be verbose. Implies --stat.
diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt
index 4bbdd05..82045a2 100644
--- a/Documentation/git-rev-parse.txt
+++ b/Documentation/git-rev-parse.txt
@@ -30,6 +30,11 @@
 	Only meaningful in `--parseopt` mode. Tells the option parser to echo
 	out the first `--` met instead of skipping it.
 
+--stop-at-non-option::
+	Only meaningful in `--parseopt` mode.  Lets the option parser stop at
+	the first non-option argument.  This can be used to parse sub-commands
+	that take options themself.
+
 --sq-quote::
 	Use 'git-rev-parse' in shell quoting mode (see SQ-QUOTE
 	section below). In contrast to the `--sq` option below, this
diff --git a/Documentation/git-show-ref.txt b/Documentation/git-show-ref.txt
index 98e294a..f4429bd 100644
--- a/Documentation/git-show-ref.txt
+++ b/Documentation/git-show-ref.txt
@@ -9,8 +9,9 @@
 --------
 [verse]
 'git show-ref' [-q|--quiet] [--verify] [-h|--head] [-d|--dereference]
-	     [-s|--hash] [--abbrev] [--tags] [--heads] [--] <pattern>...
-'git show-ref' --exclude-existing[=pattern]
+	     [-s|--hash[=<n>]] [--abbrev[=<n>]] [--tags]
+	     [--heads] [--] <pattern>...
+'git show-ref' --exclude-existing[=<pattern>] < ref-list
 
 DESCRIPTION
 -----------
@@ -48,7 +49,7 @@
 	appended.
 
 -s::
---hash::
+--hash[=<n>]::
 
 	Only show the SHA1 hash, not the reference name. When combined with
 	--dereference the dereferenced tag will still be shown after the SHA1.
@@ -59,11 +60,10 @@
 	Aside from returning an error code of 1, it will also print an error
 	message if '--quiet' was not specified.
 
---abbrev::
---abbrev=len::
+--abbrev[=<n>]::
 
 	Abbreviate the object name.  When using `--hash`, you do
-	not have to say `--hash --abbrev`; `--hash=len` would do.
+	not have to say `--hash --abbrev`; `--hash=n` would do.
 
 -q::
 --quiet::
@@ -71,8 +71,7 @@
 	Do not print any results to stdout. When combined with '--verify' this
 	can be used to silently check if a reference exists.
 
---exclude-existing::
---exclude-existing=pattern::
+--exclude-existing[=<pattern>]::
 
 	Make 'git-show-ref' act as a filter that reads refs from stdin of the
 	form "^(?:<anything>\s)?<refname>(?:\^\{\})?$" and performs the
diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt
index a42d4c8..1c64a02 100644
--- a/Documentation/git-stash.txt
+++ b/Documentation/git-stash.txt
@@ -9,10 +9,11 @@
 --------
 [verse]
 'git stash' list [<options>]
-'git stash' ( show | drop ) [<stash>]
-'git stash' ( pop | apply ) [--index] [<stash>]
+'git stash' show [<stash>]
+'git stash' drop [-q|--quiet] [<stash>]
+'git stash' ( pop | apply ) [--index] [-q|--quiet] [<stash>]
 'git stash' branch <branchname> [<stash>]
-'git stash' [save [--keep-index] [<message>]]
+'git stash' [save [--keep-index] [-q|--quiet] [<message>]]
 'git stash' clear
 'git stash' create
 
@@ -41,7 +42,7 @@
 OPTIONS
 -------
 
-save [--keep-index] [<message>]::
+save [--keep-index] [-q|--quiet] [<message>]::
 
 	Save your local modifications to a new 'stash', and run `git reset
 	--hard` to revert them.  This is the default action when no
@@ -75,7 +76,7 @@
 	it will accept any format known to 'git-diff' (e.g., `git stash show
 	-p stash@\{1}` to view the second most recent stash in patch form).
 
-pop [<stash>]::
+pop [--index] [-q|--quiet] [<stash>]::
 
 	Remove a single stashed state from the stash list and apply it
 	on top of the current working tree state, i.e., do the inverse
@@ -93,7 +94,7 @@
 +
 When no `<stash>` is given, `stash@\{0}` is assumed.
 
-apply [--index] [<stash>]::
+apply [--index] [-q|--quiet] [<stash>]::
 
 	Like `pop`, but do not remove the state from the stash list.
 
@@ -115,7 +116,7 @@
 	Remove all the stashed states. Note that those states will then
 	be subject to pruning, and may be difficult or impossible to recover.
 
-drop [<stash>]::
+drop [-q|--quiet] [<stash>]::
 
 	Remove a single stashed state from the stash list. When no `<stash>`
 	is given, it removes the latest one. i.e. `stash@\{0}`
diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index 470bd75..683ba1a 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -141,8 +141,9 @@
 	the processing to terminate. This can be overridden by adding '|| :'
 	to the end of the command.
 +
-As an example, "git submodule foreach 'echo $path `git rev-parse HEAD`' will
-show the path and currently checked out commit for each submodule.
+As an example, +git submodule foreach \'echo $path {backtick}git
+rev-parse HEAD{backtick}'+ will show the path and currently checked out
+commit for each submodule.
 
 sync::
 	Synchronizes submodules' remote URL configuration setting
diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index 7e9b9a0..10af599 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -11,11 +11,11 @@
 
 DESCRIPTION
 -----------
-'git-svn' is a simple conduit for changesets between Subversion and git.
+'git svn' is a simple conduit for changesets between Subversion and git.
 It provides a bidirectional flow of changes between a Subversion and a git
 repository.
 
-'git-svn' can track a standard Subversion repository,
+'git svn' can track a standard Subversion repository,
 following the common "trunk/branches/tags" layout, with the --stdlayout option.
 It can also follow branches and tags in any layout with the -T/-t/-b options
 (see options to 'init' below, and also the 'clone' command).
@@ -26,11 +26,10 @@
 
 COMMANDS
 --------
---
 
 'init'::
 	Initializes an empty git repository with additional
-	metadata directories for 'git-svn'.  The Subversion URL
+	metadata directories for 'git svn'.  The Subversion URL
 	may be specified as a command-line argument, or as full
 	URL arguments to -T/-t/-b.  Optionally, the target
 	directory to operate on can be specified as a second
@@ -63,16 +62,6 @@
 	Set the 'useSvnsyncProps' option in the [svn-remote] config.
 --rewrite-root=<URL>;;
 	Set the 'rewriteRoot' option in the [svn-remote] config.
---use-log-author;;
-	When retrieving svn commits into git (as part of fetch, rebase, or
-	dcommit operations), look for the first From: or Signed-off-by: line
-	in the log message and use that as the author string.
---add-author-from;;
-	When committing to svn from git (as part of commit or dcommit
-	operations), if the existing log message doesn't already have a
-	From: or Signed-off-by: line, append a From: line based on the
-	git commit's author string.  If you use this, then --use-log-author
-	will retrieve a valid author string for all commits.
 --username=<USER>;;
 	For transports that SVN handles authentication for (http,
 	https, and plain svn), specify the username.  For other
@@ -100,12 +89,12 @@
 
 --localtime;;
 	Store Git commit times in the local timezone instead of UTC.  This
-	makes 'git-log' (even without --date=local) show the same times
+	makes 'git log' (even without --date=local) show the same times
 	that `svn log` would in the local timezone.
 
 --parent;;
 	Fetch only from the SVN parent of the current HEAD.
-
++
 This doesn't interfere with interoperating with the Subversion
 repository you cloned from, but if you wish for your local Git
 repository to be able to interoperate with someone else's local Git
@@ -118,20 +107,39 @@
 	The '--ignore-paths' option should match for every 'fetch'
 	(including automatic fetches due to 'clone', 'dcommit',
 	'rebase', etc) on a given repository.
-
++
+[verse]
 config key: svn-remote.<name>.ignore-paths
-
-	If the ignore-paths config key is set and the command
-	line option is also given, both regular expressions
-	will be used.
-
++
+If the ignore-paths config key is set and the command line option is
+also given, both regular expressions will be used.
++
 Examples:
++
+--
+Skip "doc*" directory for every fetch;;
++
+------------------------------------------------------------------------
+--ignore-paths="^doc"
+------------------------------------------------------------------------
 
-	--ignore-paths="^doc" - skip "doc*" directory for every
-	    fetch.
+Skip "branches" and "tags" of first level directories;;
++
+------------------------------------------------------------------------
+--ignore-paths="^[^/]+/(?:branches|tags)"
+------------------------------------------------------------------------
+--
 
-	--ignore-paths="^[^/]+/(?:branches|tags)" - skip
-	    "branches" and "tags" of first level directories.
+--use-log-author;;
+	When retrieving svn commits into git (as part of fetch, rebase, or
+	dcommit operations), look for the first From: or Signed-off-by: line
+	in the log message and use that as the author string.
+--add-author-from;;
+	When committing to svn from git (as part of commit or dcommit
+	operations), if the existing log message doesn't already have a
+	From: or Signed-off-by: line, append a From: line based on the
+	git commit's author string.  If you use this, then --use-log-author
+	will retrieve a valid author string for all commits.
 
 'clone'::
 	Runs 'init' and 'fetch'.  It will automatically create a
@@ -139,29 +147,29 @@
 	or if a second argument is passed; it will create a directory
 	and work within that.  It accepts all arguments that the
 	'init' and 'fetch' commands accept; with the exception of
-	'--fetch-all'.   After a repository is cloned, the 'fetch'
-	command will be able to update revisions without affecting
-	the working tree; and the 'rebase' command will be able
-	to update the working tree with the latest changes.
+	'--fetch-all' and '--parent'.  After a repository is cloned,
+	the 'fetch' command will be able to update revisions without
+	affecting the working tree; and the 'rebase' command will be
+	able to update the working tree with the latest changes.
 
 'rebase'::
 	This fetches revisions from the SVN parent of the current HEAD
 	and rebases the current (uncommitted to SVN) work against it.
-
-This works similarly to `svn update` or 'git-pull' except that
-it preserves linear history with 'git-rebase' instead of
-'git-merge' for ease of dcommitting with 'git-svn'.
-
-This accepts all options that 'git-svn fetch' and 'git-rebase'
++
+This works similarly to `svn update` or 'git pull' except that
+it preserves linear history with 'git rebase' instead of
+'git merge' for ease of dcommitting with 'git svn'.
++
+This accepts all options that 'git svn fetch' and 'git rebase'
 accept.  However, '--fetch-all' only fetches from the current
 [svn-remote], and not all [svn-remote] definitions.
-
-Like 'git-rebase'; this requires that the working tree be clean
++
+Like 'git rebase'; this requires that the working tree be clean
 and have no uncommitted changes.
 
 -l;;
 --local;;
-	Do not fetch remotely; only run 'git-rebase' against the
+	Do not fetch remotely; only run 'git rebase' against the
 	last fetched commit from the upstream SVN.
 
 'dcommit'::
@@ -169,11 +177,11 @@
 	repository, and then rebase or reset (depending on whether or
 	not there is a diff between SVN and head).  This will create
 	a revision in SVN for each commit in git.
-	It is recommended that you run 'git-svn' fetch and rebase (not
+	It is recommended that you run 'git svn' fetch and rebase (not
 	pull or merge) your commits against the latest changes in the
 	SVN repository.
 	An optional revision or branch argument may be specified, and
-	causes 'git-svn' to do all work on that revision/branch
+	causes 'git svn' to do all work on that revision/branch
 	instead of HEAD.
 	This is advantageous over 'set-tree' (below) because it produces
 	cleaner, more linear history.
@@ -182,18 +190,17 @@
 	After committing, do not rebase or reset.
 --commit-url <URL>;;
 	Commit to this SVN URL (the full path).  This is intended to
-	allow existing git-svn repositories created with one transport
+	allow existing 'git svn' repositories created with one transport
 	method (e.g. `svn://` or `http://` for anonymous read) to be
 	reused if a user is later given access to an alternate transport
 	method (e.g. `svn+ssh://` or `https://`) for commit.
-
++
+[verse]
 config key: svn-remote.<name>.commiturl
-
 config key: svn.commiturl (overwrites all svn-remote.<name>.commiturl options)
-
-	Using this option for any other purpose (don't ask)
-	is very strongly discouraged.
---
++
+Using this option for any other purpose (don't ask) is very strongly
+discouraged.
 
 'branch'::
 	Create a branch in the SVN repository.
@@ -232,10 +239,12 @@
 The following features from `svn log' are supported:
 +
 --
--r/--revision=<n>[:<n>];;
+-r <n>[:<n>];;
+--revision=<n>[:<n>];;
 	is supported, non-numeric args are not:
 	HEAD, NEXT, BASE, PREV, etc ...
--v/--verbose;;
+-v;;
+--verbose;;
 	it's not completely compatible with the --verbose
 	output in svn log, but reasonably close.
 --limit=<n>;;
@@ -258,7 +267,7 @@
 client converts the UTC time to the local time (or based on the TZ=
 environment). This command has the same behaviour.
 +
-Any other arguments are passed directly to 'git-log'
+Any other arguments are passed directly to 'git log'
 
 'blame'::
        Show what revision and author last modified each line of a file. The
@@ -266,15 +275,14 @@
        `svn blame' by default. Like the SVN blame command,
        local uncommitted changes in the working copy are ignored;
        the version of the file in the HEAD revision is annotated. Unknown
-       arguments are passed directly to 'git-blame'.
+       arguments are passed directly to 'git blame'.
 +
 --git-format;;
-	Produce output in the same format as 'git-blame', but with
+	Produce output in the same format as 'git blame', but with
 	SVN revision numbers instead of git commit hashes. In this mode,
 	changes that haven't been committed to SVN (including local
 	working-copy edits) are shown as revision 0.
 
---
 'find-rev'::
 	When given an SVN revision number of the form 'rN', returns the
 	corresponding git commit hash (this can optionally be followed by a
@@ -288,7 +296,7 @@
 	absolutely no attempts to do patching when committing to SVN, it
 	simply overwrites files with those specified in the tree or
 	commit.  All merging is assumed to have taken place
-	independently of 'git-svn' functions.
+	independently of 'git svn' functions.
 
 'create-ignore'::
 	Recursively finds the svn:ignore property on directories and
@@ -303,12 +311,12 @@
 
 'commit-diff'::
 	Commits the diff of two tree-ish arguments from the
-	command-line.  This command does not rely on being inside an `git-svn
+	command-line.  This command does not rely on being inside an `git svn
 	init`-ed repository.  This command takes three arguments, (a) the
 	original tree to diff against, (b) the new tree result, (c) the
 	URL of the target Subversion repository.  The final argument
-	(URL) may be omitted if you are working from a 'git-svn'-aware
-	repository (that has been `init`-ed with 'git-svn').
+	(URL) may be omitted if you are working from a 'git svn'-aware
+	repository (that has been `init`-ed with 'git svn').
 	The -r<revision> option is required for this.
 
 'info'::
@@ -340,163 +348,156 @@
 	"checksum mismatch" (missed a modification).  If the problem
 	file cannot be ignored forever (with --ignore-paths) the only
 	way to repair the repo is to use 'reset'.
-
++
 Only the rev_map and refs/remotes/git-svn are changed.  Follow 'reset'
-with a 'fetch' and then 'git-reset' or 'git-rebase' to move local
+with a 'fetch' and then 'git reset' or 'git rebase' to move local
 branches onto the new tree.
 
--r/--revision=<n>;;
+-r <n>;;
+--revision=<n>;;
 	Specify the most recent revision to keep.  All later revisions
 	are discarded.
--p/--parent;;
+-p;;
+--parent;;
 	Discard the specified revision as well, keeping the nearest
 	parent instead.
 Example:;;
 Assume you have local changes in "master", but you need to refetch "r2".
-
++
 ------------
     r1---r2---r3 remotes/git-svn
                 \
                  A---B master
 ------------
-
++
 Fix the ignore-paths or SVN permissions problem that caused "r2" to
 be incomplete in the first place.  Then:
-
++
 [verse]
 git svn reset -r2 -p
 git svn fetch
-
++
 ------------
     r1---r2'--r3' remotes/git-svn
       \
        r2---r3---A---B master
 ------------
-
-Then fixup "master" with 'git-rebase'.
-Do NOT use 'git-merge' or your history will not be compatible with a
++
+Then fixup "master" with 'git rebase'.
+Do NOT use 'git merge' or your history will not be compatible with a
 future 'dcommit'!
-
++
 [verse]
 git rebase --onto remotes/git-svn A^ master
-
++
 ------------
     r1---r2'--r3' remotes/git-svn
                 \
                  A'--B' master
 ------------
 
-
---
-
 OPTIONS
 -------
---
 
 --shared[={false|true|umask|group|all|world|everybody}]::
 --template=<template_directory>::
 	Only used with the 'init' command.
-	These are passed directly to 'git-init'.
+	These are passed directly to 'git init'.
 
 -r <ARG>::
 --revision <ARG>::
-
-Used with the 'fetch' command.
-
+	   Used with the 'fetch' command.
++
 This allows revision ranges for partial/cauterized history
 to be supported.  $NUMBER, $NUMBER1:$NUMBER2 (numeric ranges),
 $NUMBER:HEAD, and BASE:$NUMBER are all supported.
-
++
 This can allow you to make partial mirrors when running fetch;
 but is generally not recommended because history will be skipped
 and lost.
 
 -::
 --stdin::
-
-Only used with the 'set-tree' command.
-
+	Only used with the 'set-tree' command.
++
 Read a list of commits from stdin and commit them in reverse
 order.  Only the leading sha1 is read from each line, so
-'git-rev-list --pretty=oneline' output can be used.
+'git rev-list --pretty=oneline' output can be used.
 
 --rmdir::
-
-Only used with the 'dcommit', 'set-tree' and 'commit-diff' commands.
-
+	Only used with the 'dcommit', 'set-tree' and 'commit-diff' commands.
++
 Remove directories from the SVN tree if there are no files left
 behind.  SVN can version empty directories, and they are not
 removed by default if there are no files left in them.  git
 cannot version empty directories.  Enabling this flag will make
 the commit to SVN act like git.
-
++
+[verse]
 config key: svn.rmdir
 
 -e::
 --edit::
-
-Only used with the 'dcommit', 'set-tree' and 'commit-diff' commands.
-
+	Only used with the 'dcommit', 'set-tree' and 'commit-diff' commands.
++
 Edit the commit message before committing to SVN.  This is off by
 default for objects that are commits, and forced on when committing
 tree objects.
-
++
+[verse]
 config key: svn.edit
 
 -l<num>::
 --find-copies-harder::
-
-Only used with the 'dcommit', 'set-tree' and 'commit-diff' commands.
-
-They are both passed directly to 'git-diff-tree'; see
+	Only used with the 'dcommit', 'set-tree' and 'commit-diff' commands.
++
+They are both passed directly to 'git diff-tree'; see
 linkgit:git-diff-tree[1] for more information.
-
++
 [verse]
 config key: svn.l
 config key: svn.findcopiesharder
 
 -A<filename>::
 --authors-file=<filename>::
-
-Syntax is compatible with the file used by 'git-cvsimport':
-
+	Syntax is compatible with the file used by 'git cvsimport':
++
 ------------------------------------------------------------------------
 	loginname = Joe User <user@example.com>
 ------------------------------------------------------------------------
-
-If this option is specified and 'git-svn' encounters an SVN
-committer name that does not exist in the authors-file, 'git-svn'
++
+If this option is specified and 'git svn' encounters an SVN
+committer name that does not exist in the authors-file, 'git svn'
 will abort operation. The user will then have to add the
-appropriate entry.  Re-running the previous 'git-svn' command
+appropriate entry.  Re-running the previous 'git svn' command
 after the authors-file is modified should continue operation.
-
++
+[verse]
 config key: svn.authorsfile
 
 --authors-prog=<filename>::
-
-If this option is specified, for each SVN committer name that does not
-exist in the authors file, the given file is executed with the committer
-name as the first argument.  The program is expected to return a single
-line of the form "Name <email>", which will be treated as if included in
-the authors file.
+	If this option is specified, for each SVN committer name that
+	does not exist in the authors file, the given file is executed
+	with the committer name as the first argument.  The program is
+	expected to return a single line of the form "Name <email>",
+	which will be treated as if included in the authors file.
 
 -q::
 --quiet::
-	Make 'git-svn' less verbose. Specify a second time to make it
+	Make 'git svn' less verbose. Specify a second time to make it
 	even less verbose.
 
 --repack[=<n>]::
 --repack-flags=<flags>::
-
-These should help keep disk usage sane for large fetches
-with many revisions.
-
+	These should help keep disk usage sane for large fetches with
+	many revisions.
++
 --repack takes an optional argument for the number of revisions
 to fetch before repacking.  This defaults to repacking every
 1000 commits fetched if no argument is specified.
-
---repack-flags are passed directly to 'git-repack'.
-
++
+--repack-flags are passed directly to 'git repack'.
++
 [verse]
 config key: svn.repack
 config key: svn.repackflags
@@ -505,41 +506,36 @@
 --merge::
 -s<strategy>::
 --strategy=<strategy>::
-
-These are only used with the 'dcommit' and 'rebase' commands.
-
-Passed directly to 'git-rebase' when using 'dcommit' if a
-'git-reset' cannot be used (see 'dcommit').
+	These are only used with the 'dcommit' and 'rebase' commands.
++
+Passed directly to 'git rebase' when using 'dcommit' if a
+'git reset' cannot be used (see 'dcommit').
 
 -n::
 --dry-run::
-
-This can be used with the 'dcommit', 'rebase', 'branch' and 'tag'
-commands.
-
+	This can be used with the 'dcommit', 'rebase', 'branch' and
+	'tag' commands.
++
 For 'dcommit', print out the series of git arguments that would show
 which diffs would be committed to SVN.
-
++
 For 'rebase', display the local branch associated with the upstream svn
 repository associated with the current branch and the URL of svn
 repository that will be fetched from.
-
++
 For 'branch' and 'tag', display the urls that will be used for copying when
 creating the branch or tag.
 
---
 
 ADVANCED OPTIONS
 ----------------
---
 
 -i<GIT_SVN_ID>::
 --id <GIT_SVN_ID>::
-
-This sets GIT_SVN_ID (instead of using the environment).  This
-allows the user to override the default refname to fetch from
-when tracking a single URL.  The 'log' and 'dcommit' commands
-no longer require this switch as an argument.
+	This sets GIT_SVN_ID (instead of using the environment).  This
+	allows the user to override the default refname to fetch from
+	when tracking a single URL.  The 'log' and 'dcommit' commands
+	no longer require this switch as an argument.
 
 -R<remote name>::
 --svn-remote <remote name>::
@@ -553,33 +549,30 @@
 	started tracking a branch and never tracked the trunk it was
 	descended from. This feature is enabled by default, use
 	--no-follow-parent to disable it.
-
++
+[verse]
 config key: svn.followparent
 
---
 CONFIG FILE-ONLY OPTIONS
 ------------------------
---
 
 svn.noMetadata::
 svn-remote.<name>.noMetadata::
-
-This gets rid of the 'git-svn-id:' lines at the end of every commit.
-
-If you lose your .git/svn/git-svn/.rev_db file, 'git-svn' will not
+	This gets rid of the 'git-svn-id:' lines at the end of every commit.
++
+If you lose your .git/svn/git-svn/.rev_db file, 'git svn' will not
 be able to rebuild it and you won't be able to fetch again,
 either.  This is fine for one-shot imports.
-
-The 'git-svn log' command will not work on repositories using
++
+The 'git svn log' command will not work on repositories using
 this, either.  Using this conflicts with the 'useSvmProps'
 option for (hopefully) obvious reasons.
 
 svn.useSvmProps::
 svn-remote.<name>.useSvmProps::
-
-This allows 'git-svn' to re-map repository URLs and UUIDs from
-mirrors created using SVN::Mirror (or svk) for metadata.
-
+	This allows 'git svn' to re-map repository URLs and UUIDs from
+	mirrors created using SVN::Mirror (or svk) for metadata.
++
 If an SVN revision has a property, "svm:headrev", it is likely
 that the revision was created by SVN::Mirror (also used by SVK).
 The property contains a repository UUID and a revision.  We want
@@ -596,23 +589,22 @@
 
 svn-remote.<name>.rewriteRoot::
 	This allows users to create repositories from alternate
-	URLs.  For example, an administrator could run 'git-svn' on the
+	URLs.  For example, an administrator could run 'git svn' on the
 	server locally (accessing via file://) but wish to distribute
 	the repository with a public http:// or svn:// URL in the
 	metadata so users of it will see the public URL.
 
 svn.brokenSymlinkWorkaround::
-This disables potentially expensive checks to workaround broken symlinks
-checked into SVN by broken clients.  Set this option to "false" if you
-track a SVN repository with many empty blobs that are not symlinks.
-This option may be changed while "git-svn" is running and take effect on
-the next revision fetched.  If unset, git-svn assumes this option to be
-"true".
-
---
+	This disables potentially expensive checks to workaround
+	broken symlinks checked into SVN by broken clients.  Set this
+	option to "false" if you track a SVN repository with many
+	empty blobs that are not symlinks.  This option may be changed
+	while 'git svn' is running and take effect on the next
+	revision fetched.  If unset, 'git svn' assumes this option to
+	be "true".
 
 Since the noMetadata, rewriteRoot, useSvnsyncProps and useSvmProps
-options all affect the metadata generated and used by 'git-svn'; they
+options all affect the metadata generated and used by 'git svn'; they
 *must* be set in the configuration file before any history is imported
 and these settings should never be changed once they are set.
 
@@ -630,7 +622,7 @@
 	git svn clone http://svn.example.com/project/trunk
 # Enter the newly cloned directory:
 	cd trunk
-# You should be on master branch, double-check with git-branch
+# You should be on master branch, double-check with 'git branch'
 	git branch
 # Do some work and commit locally to git:
 	git commit ...
@@ -661,12 +653,12 @@
 # of dcommit/rebase/show-ignore should be the same as above.
 ------------------------------------------------------------------------
 
-The initial 'git-svn clone' can be quite time-consuming
+The initial 'git svn clone' can be quite time-consuming
 (especially for large Subversion repositories). If multiple
 people (or one person with multiple machines) want to use
-'git-svn' to interact with the same Subversion repository, you can
-do the initial 'git-svn clone' to a repository on a server and
-have each person clone that repository with 'git-clone':
+'git svn' to interact with the same Subversion repository, you can
+do the initial 'git svn clone' to a repository on a server and
+have each person clone that repository with 'git clone':
 
 ------------------------------------------------------------------------
 # Do the initial import on a server
@@ -680,7 +672,7 @@
 	git fetch
 # Create a local branch from one of the branches just fetched
 	git checkout -b master FETCH_HEAD
-# Initialize git-svn locally (be sure to use the same URL and -T/-b/-t options as were used on server)
+# Initialize 'git svn' locally (be sure to use the same URL and -T/-b/-t options as were used on server)
 	git svn init http://svn.example.com/project
 # Pull the latest changes from Subversion
 	git svn rebase
@@ -689,7 +681,7 @@
 REBASE VS. PULL/MERGE
 ---------------------
 
-Originally, 'git-svn' recommended that the 'remotes/git-svn' branch be
+Originally, 'git svn' recommended that the 'remotes/git-svn' branch be
 pulled or merged from.  This is because the author favored
 `git svn set-tree B` to commit a single head rather than the
 `git svn set-tree A..B` notation to commit multiple commits.
@@ -704,7 +696,7 @@
 DESIGN PHILOSOPHY
 -----------------
 Merge tracking in Subversion is lacking and doing branched development
-with Subversion can be cumbersome as a result.  While 'git-svn' can track
+with Subversion can be cumbersome as a result.  While 'git svn' can track
 copy history (including branches and tags) for repositories adopting a
 standard layout, it cannot yet represent merge history that happened
 inside git back upstream to SVN users.  Therefore it is advised that
@@ -715,25 +707,25 @@
 -------
 
 For the sake of simplicity and interoperating with a less-capable system
-(SVN), it is recommended that all 'git-svn' users clone, fetch and dcommit
-directly from the SVN server, and avoid all 'git-clone'/'pull'/'merge'/'push'
+(SVN), it is recommended that all 'git svn' users clone, fetch and dcommit
+directly from the SVN server, and avoid all 'git clone'/'pull'/'merge'/'push'
 operations between git repositories and branches.  The recommended
 method of exchanging code between git branches and users is
-'git-format-patch' and 'git-am', or just 'dcommit'ing to the SVN repository.
+'git format-patch' and 'git am', or just 'dcommit'ing to the SVN repository.
 
-Running 'git-merge' or 'git-pull' is NOT recommended on a branch you
+Running 'git merge' or 'git pull' is NOT recommended on a branch you
 plan to 'dcommit' from.  Subversion does not represent merges in any
 reasonable or useful fashion; so users using Subversion cannot see any
 merges you've made.  Furthermore, if you merge or pull from a git branch
 that is a mirror of an SVN branch, 'dcommit' may commit to the wrong
 branch.
 
-'git-clone' does not clone branches under the refs/remotes/ hierarchy or
-any 'git-svn' metadata, or config.  So repositories created and managed with
-using 'git-svn' should use 'rsync' for cloning, if cloning is to be done
+'git clone' does not clone branches under the refs/remotes/ hierarchy or
+any 'git svn' metadata, or config.  So repositories created and managed with
+using 'git svn' should use 'rsync' for cloning, if cloning is to be done
 at all.
 
-Since 'dcommit' uses rebase internally, any git branches you 'git-push' to
+Since 'dcommit' uses rebase internally, any git branches you 'git push' to
 before 'dcommit' on will require forcing an overwrite of the existing ref
 on the remote repository.  This is generally considered bad practice,
 see the linkgit:git-push[1] documentation for details.
@@ -743,7 +735,7 @@
 you've already pushed to a remote repository for other users, and
 dcommit with SVN is analogous to that.
 
-When using multiple --branches or --tags, 'git-svn' does not automatically
+When using multiple --branches or --tags, 'git svn' does not automatically
 handle name collisions (for example, if two branches from different paths have
 the same name, or if a branch and a tag have the same name).  In these cases,
 use 'init' to set up your git repository then, before your first 'fetch', edit
@@ -769,7 +761,7 @@
 CONFIGURATION
 -------------
 
-'git-svn' stores [svn-remote] configuration information in the
+'git svn' stores [svn-remote] configuration information in the
 repository .git/config file.  It is similar the core git
 [remote] sections except 'fetch' keys do not accept glob
 arguments; but they are instead handled by the 'branches'
@@ -790,7 +782,7 @@
 however the remote wildcard may be anywhere as long as it's an
 independent path component (surrounded by '/' or EOL).   This
 type of configuration is not automatically created by 'init' and
-should be manually entered with a text-editor or using 'git-config'.
+should be manually entered with a text-editor or using 'git config'.
 
 SEE ALSO
 --------
diff --git a/Documentation/gittutorial.txt b/Documentation/gittutorial.txt
index c7fa949..cf0689c 100644
--- a/Documentation/gittutorial.txt
+++ b/Documentation/gittutorial.txt
@@ -332,11 +332,11 @@
 ------------------------------------------------
 
 This operation is safe even if Alice has uncommitted local changes.
-The range notation HEAD..FETCH_HEAD" means "show everything that is reachable
-from the FETCH_HEAD but exclude anything that is reachable from HEAD.
+The range notation "HEAD..FETCH_HEAD" means "show everything that is reachable
+from the FETCH_HEAD but exclude anything that is reachable from HEAD".
 Alice already knows everything that leads to her current state (HEAD),
-and reviewing what Bob has in his state (FETCH_HEAD) that she has not
-seen with this command
+and reviews what Bob has in his state (FETCH_HEAD) that she has not
+seen with this command.
 
 If Alice wants to visualize what Bob did since their histories forked
 she can issue the following command:
@@ -375,9 +375,9 @@
 alice$ git remote add bob /home/bob/myrepo
 ------------------------------------------------
 
-With this, Alice can perform the first part of the "pull" operation alone using the
-'git-fetch' command without merging them with her own branch,
-using:
+With this, Alice can perform the first part of the "pull" operation
+alone using the 'git-fetch' command without merging them with her own
+branch, using:
 
 -------------------------------------
 alice$ git fetch bob
@@ -566,22 +566,22 @@
 
 You can also give 'git-log' a "range" of commits where the first is not
 necessarily an ancestor of the second; for example, if the tips of
-the branches "stable-release" and "master" diverged from a common
+the branches "stable" and "master" diverged from a common
 commit some time ago, then
 
 -------------------------------------
-$ git log stable..experimental
+$ git log stable..master
 -------------------------------------
 
-will list commits made in the experimental branch but not in the
+will list commits made in the master branch but not in the
 stable branch, while
 
 -------------------------------------
-$ git log experimental..stable
+$ git log master..stable
 -------------------------------------
 
 will show the list of commits made on the stable branch but not
-the experimental branch.
+the master branch.
 
 The 'git-log' command has a weakness: it must present commits in a
 list.  When the history has lines of development that diverged and
diff --git a/Makefile b/Makefile
index 41ab8e9..78cc113 100644
--- a/Makefile
+++ b/Makefile
@@ -194,6 +194,8 @@
 #
 # Define USE_NED_ALLOCATOR if you want to replace the platforms default
 # memory allocators with the nedmalloc allocator written by Niall Douglas.
+#
+# Define NO_REGEX if you have no or inferior regex support in your C library.
 
 GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
 	@$(SHELL_PATH) ./GIT-VERSION-GEN
@@ -723,6 +725,7 @@
 	NO_MEMMEM = YesPlease
 	NO_MKDTEMP = YesPlease
 	NO_MKSTEMPS = YesPlease
+	NO_REGEX = YesPlease
 	ifeq ($(uname_R),5.7)
 		NEEDS_RESOLV = YesPlease
 		NO_IPV6 = YesPlease
@@ -750,7 +753,7 @@
 	endif
 	INSTALL = /usr/ucb/install
 	TAR = gtar
-	BASIC_CFLAGS += -D__EXTENSIONS__ -D__sun__
+	BASIC_CFLAGS += -D__EXTENSIONS__ -D__sun__ -DHAVE_ALLOCA_H
 endif
 ifeq ($(uname_O),Cygwin)
 	NO_D_TYPE_IN_DIRENT = YesPlease
@@ -884,9 +887,10 @@
 	USE_NED_ALLOCATOR = YesPlease
 	UNRELIABLE_FSTAT = UnfortunatelyYes
 	OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo
-	COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/regex -Icompat/fnmatch
+	NO_REGEX = YesPlease
+	COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/fnmatch
 	COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
-	COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/regex/regex.o compat/winansi.o
+	COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o
 	EXTLIBS += -lws2_32
 	X = .exe
 ifneq (,$(wildcard ../THIS_IS_MSYSGIT))
@@ -1200,6 +1204,10 @@
 ifdef UNRELIABLE_FSTAT
 	BASIC_CFLAGS += -DUNRELIABLE_FSTAT
 endif
+ifdef NO_REGEX
+	COMPAT_CFLAGS += -Icompat/regex
+	COMPAT_OBJS += compat/regex/regex.o
+endif
 
 ifdef USE_NED_ALLOCATOR
        COMPAT_CFLAGS += -DUSE_NED_ALLOCATOR -DOVERRIDE_STRDUP -DNDEBUG -DREPLACE_SYSTEM_ALLOCATOR -Icompat/nedmalloc
@@ -1464,7 +1472,7 @@
 		$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
 
 $(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
-$(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
+$(patsubst git-%$X,%.o,$(PROGRAMS)) git.o: $(LIB_H) $(wildcard */*.h)
 builtin-revert.o wt-status.o: wt-status.h
 
 $(LIB_FILE): $(LIB_OBJS)
diff --git a/abspath.c b/abspath.c
index 649f34f..4bee0ba 100644
--- a/abspath.c
+++ b/abspath.c
@@ -41,13 +41,13 @@
 
 		if (*buf) {
 			if (!*cwd && !getcwd(cwd, sizeof(cwd)))
-				die ("Could not get current working directory");
+				die_errno ("Could not get current working directory");
 
 			if (chdir(buf))
-				die ("Could not switch to '%s'", buf);
+				die_errno ("Could not switch to '%s'", buf);
 		}
 		if (!getcwd(buf, PATH_MAX))
-			die ("Could not get current working directory");
+			die_errno ("Could not get current working directory");
 
 		if (last_elem) {
 			int len = strlen(buf);
@@ -63,7 +63,7 @@
 		if (!lstat(buf, &st) && S_ISLNK(st.st_mode)) {
 			len = readlink(buf, next_buf, PATH_MAX);
 			if (len < 0)
-				die ("Invalid symlink: %s", buf);
+				die_errno ("Invalid symlink '%s'", buf);
 			if (PATH_MAX <= len)
 				die("symbolic link too long: %s", buf);
 			next_buf[len] = '\0';
@@ -75,7 +75,7 @@
 	}
 
 	if (*cwd && chdir(cwd))
-		die ("Could not change back to '%s'", cwd);
+		die_errno ("Could not change back to '%s'", cwd);
 
 	return buf;
 }
@@ -109,7 +109,7 @@
 	} else {
 		const char *cwd = get_pwd_cwd();
 		if (!cwd)
-			die("Cannot determine the current working directory");
+			die_errno("Cannot determine the current working directory");
 		if (snprintf(buf, PATH_MAX, "%s/%s", cwd, path) >= PATH_MAX)
 			die("Too long path: %.*s", 60, path);
 	}
diff --git a/attr.c b/attr.c
index f8f6faa..55bdb7c 100644
--- a/attr.c
+++ b/attr.c
@@ -555,6 +555,8 @@
 		}
 	}
 
+	strbuf_release(&pathbuf);
+
 	/*
 	 * Finally push the "info" one at the top of the stack.
 	 */
diff --git a/bisect.c b/bisect.c
index dbeb287..7f20acb 100644
--- a/bisect.c
+++ b/bisect.c
@@ -461,7 +461,7 @@
 	FILE *fp = fopen(filename, "r");
 
 	if (!fp)
-		die("Could not open file '%s': %s", filename, strerror(errno));
+		die_errno("Could not open file '%s'", filename);
 
 	while (strbuf_getline(&str, fp, '\n') != EOF) {
 		char *quoted;
@@ -585,16 +585,49 @@
 	return filtered;
 }
 
-static struct commit_list *apply_skip_ratio(struct commit_list *list,
-					    int count,
-					    int skip_num, int skip_denom)
+#define PRN_MODULO 32768
+
+/*
+ * This is a pseudo random number generator based on "man 3 rand".
+ * It is not used properly because the seed is the argument and it
+ * is increased by one between each call, but that should not matter
+ * for this application.
+ */
+int get_prn(int count) {
+	count = count * 1103515245 + 12345;
+	return ((unsigned)(count/65536) % PRN_MODULO);
+}
+
+/*
+ * Custom integer square root from
+ * http://en.wikipedia.org/wiki/Integer_square_root
+ */
+static int sqrti(int val)
 {
-	int index, i;
+	float d, x = val;
+
+	if (val == 0)
+		return 0;
+
+	do {
+		float y = (x + (float)val / x) / 2;
+		d = (y > x) ? y - x : x - y;
+		x = y;
+	} while (d >= 0.5);
+
+	return (int)x;
+}
+
+static struct commit_list *skip_away(struct commit_list *list, int count)
+{
 	struct commit_list *cur, *previous;
+	int prn, index, i;
+
+	prn = get_prn(count);
+	index = (count * prn / PRN_MODULO) * sqrti(prn) / sqrti(PRN_MODULO);
 
 	cur = list;
 	previous = NULL;
-	index = count * skip_num / skip_denom;
 
 	for (i = 0; cur; cur = cur->next, i++) {
 		if (i == index) {
@@ -614,7 +647,6 @@
 					   struct commit_list **tried)
 {
 	int count, skipped_first;
-	int skip_num, skip_denom;
 
 	*tried = NULL;
 
@@ -626,11 +658,7 @@
 	if (!skipped_first)
 		return list;
 
-	/* Use alternatively 1/5, 2/5 and 3/5 as skip ratio. */
-	skip_num = count % 3 + 1;
-	skip_denom = 5;
-
-	return apply_skip_ratio(list, count, skip_num, skip_denom);
+	return skip_away(list, count);
 }
 
 static void bisect_rev_setup(struct rev_info *revs, const char *prefix,
@@ -712,8 +740,7 @@
 	int fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0600);
 
 	if (fd < 0)
-		die("could not create file '%s': %s",
-		    filename, strerror(errno));
+		die_errno("could not create file '%s'", filename);
 
 	bisect_rev_hex[len] = '\n';
 	write_or_die(fd, bisect_rev_hex, len + 1);
diff --git a/branch.c b/branch.c
index 62030af..05ef3f5 100644
--- a/branch.c
+++ b/branch.c
@@ -172,7 +172,7 @@
 
 	lock = lock_any_ref_for_update(ref.buf, NULL, 0);
 	if (!lock)
-		die("Failed to lock ref for update: %s.", strerror(errno));
+		die_errno("Failed to lock ref for update");
 
 	if (reflog)
 		log_all_ref_updates = 1;
@@ -188,7 +188,7 @@
 		setup_tracking(name, real_ref, track);
 
 	if (write_ref_sha1(lock, sha1, msg) < 0)
-		die("Failed to write ref: %s.", strerror(errno));
+		die_errno("Failed to write ref");
 
 	strbuf_release(&ref);
 	free(real_ref);
diff --git a/builtin-add.c b/builtin-add.c
index 4e44148..78989da 100644
--- a/builtin-add.c
+++ b/builtin-add.c
@@ -220,7 +220,7 @@
 	launch_editor(file, NULL, NULL);
 
 	if (stat(file, &st))
-		die("Could not stat '%s'", file);
+		die_errno("Could not stat '%s'", file);
 	if (!st.st_size)
 		die("Empty patch. Aborted.");
 
diff --git a/builtin-apply.c b/builtin-apply.c
index 4cf819c..dc0ff5e 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -280,7 +280,7 @@
 static void read_patch_file(struct strbuf *sb, int fd)
 {
 	if (strbuf_read(sb, fd, 0) < 0)
-		die("git apply: read returned %s", strerror(errno));
+		die_errno("git apply: failed to read");
 
 	/*
 	 * Make sure that we have some slop in the buffer
@@ -2823,8 +2823,8 @@
 	} else {
 		if (!cached) {
 			if (lstat(path, &st) < 0)
-				die("unable to stat newly created file %s",
-				    path);
+				die_errno("unable to stat newly created file '%s'",
+					  path);
 			fill_stat_cache_info(ce, &st);
 		}
 		if (write_sha1_file(buf, size, blob_type, ce->sha1) < 0)
@@ -2864,7 +2864,7 @@
 	strbuf_release(&nbuf);
 
 	if (close(fd) < 0)
-		die("closing file %s: %s", path, strerror(errno));
+		die_errno("closing file '%s'", path);
 	return 0;
 }
 
@@ -2913,7 +2913,7 @@
 			++nr;
 		}
 	}
-	die("unable to write file %s mode %o", path, mode);
+	die_errno("unable to write file '%s' mode %o", path, mode);
 }
 
 static void create_file(struct patch *patch)
@@ -3356,7 +3356,7 @@
 
 		fd = open(arg, O_RDONLY);
 		if (fd < 0)
-			die("can't open patch '%s': %s", arg, strerror(errno));
+			die_errno("can't open patch '%s'", arg);
 		read_stdin = 0;
 		set_default_whitespace_mode(whitespace_option);
 		errs |= apply_patch(fd, arg, options);
diff --git a/builtin-archive.c b/builtin-archive.c
index 3c5a5a7..f9a4bea 100644
--- a/builtin-archive.c
+++ b/builtin-archive.c
@@ -13,10 +13,10 @@
 {
 	int output_fd = open(output_file, O_CREAT | O_WRONLY | O_TRUNC, 0666);
 	if (output_fd < 0)
-		die("could not create archive file: %s ", output_file);
+		die_errno("could not create archive file '%s'", output_file);
 	if (output_fd != 1) {
 		if (dup2(output_fd, 1) < 0)
-			die("could not redirect output");
+			die_errno("could not redirect output");
 		else
 			close(output_fd);
 	}
diff --git a/builtin-blame.c b/builtin-blame.c
index 0c2d29a..fd6ca51 100644
--- a/builtin-blame.c
+++ b/builtin-blame.c
@@ -2008,23 +2008,23 @@
 
 		if (contents_from) {
 			if (stat(contents_from, &st) < 0)
-				die("Cannot stat %s", contents_from);
+				die_errno("Cannot stat '%s'", contents_from);
 			read_from = contents_from;
 		}
 		else {
 			if (lstat(path, &st) < 0)
-				die("Cannot lstat %s", path);
+				die_errno("Cannot lstat '%s'", path);
 			read_from = path;
 		}
 		mode = canon_mode(st.st_mode);
 		switch (st.st_mode & S_IFMT) {
 		case S_IFREG:
 			if (strbuf_read_file(&buf, read_from, st.st_size) != st.st_size)
-				die("cannot open or read %s", read_from);
+				die_errno("cannot open or read '%s'", read_from);
 			break;
 		case S_IFLNK:
 			if (strbuf_readlink(&buf, read_from, st.st_size) < 0)
-				die("cannot readlink %s", read_from);
+				die_errno("cannot readlink '%s'", read_from);
 			break;
 		default:
 			die("unsupported file type %s", read_from);
@@ -2035,7 +2035,7 @@
 		contents_from = "standard input";
 		mode = 0;
 		if (strbuf_read(&buf, 0, 0) < 0)
-			die("read error %s from stdin", strerror(errno));
+			die_errno("failed to read from stdin");
 	}
 	convert_to_git(path, buf.buf, buf.len, &buf, 0);
 	origin->file.ptr = buf.buf;
@@ -2261,8 +2261,7 @@
 	argc = parse_options_end(&ctx);
 
 	if (revs_file && read_ancestry(revs_file))
-		die("reading graft file %s failed: %s",
-		    revs_file, strerror(errno));
+		die_errno("reading graft file '%s' failed", revs_file);
 
 	if (cmd_is_annotate) {
 		output_option |= OUTPUT_ANNOTATE_COMPAT;
@@ -2350,7 +2349,7 @@
 
 		setup_work_tree();
 		if (!has_string_in_work_tree(path))
-			die("cannot stat path %s: %s", path, strerror(errno));
+			die_errno("cannot stat path '%s'", path);
 	}
 
 	setup_revisions(argc, argv, &revs, NULL);
diff --git a/builtin-clone.c b/builtin-clone.c
index 2ceacb7..32dea74 100644
--- a/builtin-clone.c
+++ b/builtin-clone.c
@@ -220,13 +220,13 @@
 
 	dir = opendir(src->buf);
 	if (!dir)
-		die("failed to open %s", src->buf);
+		die_errno("failed to open '%s'", src->buf);
 
 	if (mkdir(dest->buf, 0777)) {
 		if (errno != EEXIST)
-			die("failed to create directory %s", dest->buf);
+			die_errno("failed to create directory '%s'", dest->buf);
 		else if (stat(dest->buf, &buf))
-			die("failed to stat %s", dest->buf);
+			die_errno("failed to stat '%s'", dest->buf);
 		else if (!S_ISDIR(buf.st_mode))
 			die("%s exists and is not a directory", dest->buf);
 	}
@@ -252,17 +252,16 @@
 		}
 
 		if (unlink(dest->buf) && errno != ENOENT)
-			die("failed to unlink %s: %s",
-			    dest->buf, strerror(errno));
+			die_errno("failed to unlink '%s'", dest->buf);
 		if (!option_no_hardlinks) {
 			if (!link(src->buf, dest->buf))
 				continue;
 			if (option_local)
-				die("failed to create link %s", dest->buf);
+				die_errno("failed to create link '%s'", dest->buf);
 			option_no_hardlinks = 1;
 		}
 		if (copy_file(dest->buf, src->buf, 0666))
-			die("failed to copy file to %s", dest->buf);
+			die_errno("failed to copy file to '%s'", dest->buf);
 	}
 	closedir(dir);
 }
@@ -420,11 +419,11 @@
 	if (!option_bare) {
 		junk_work_tree = work_tree;
 		if (safe_create_leading_directories_const(work_tree) < 0)
-			die("could not create leading directories of '%s': %s",
-					work_tree, strerror(errno));
+			die_errno("could not create leading directories of '%s'",
+				  work_tree);
 		if (!dest_exists && mkdir(work_tree, 0755))
-			die("could not create work tree dir '%s': %s.",
-					work_tree, strerror(errno));
+			die_errno("could not create work tree dir '%s'.",
+				  work_tree);
 		set_git_work_tree(work_tree);
 	}
 	junk_git_dir = git_dir;
diff --git a/builtin-commit-tree.c b/builtin-commit-tree.c
index 0453425..6467077 100644
--- a/builtin-commit-tree.c
+++ b/builtin-commit-tree.c
@@ -124,7 +124,7 @@
 	}
 
 	if (strbuf_read(&buffer, 0, 0) < 0)
-		die("git commit-tree: read returned %s", strerror(errno));
+		die_errno("git commit-tree: failed to read");
 
 	if (!commit_tree(buffer.buf, tree_sha1, parents, commit_sha1, NULL)) {
 		printf("%s\n", sha1_to_hex(commit_sha1));
diff --git a/builtin-commit.c b/builtin-commit.c
index 41e222d..4bcce06 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -434,12 +434,12 @@
 		if (isatty(0))
 			fprintf(stderr, "(reading log message from standard input)\n");
 		if (strbuf_read(&sb, 0, 0) < 0)
-			die("could not read log from standard input");
+			die_errno("could not read log from standard input");
 		hook_arg1 = "message";
 	} else if (logfile) {
 		if (strbuf_read_file(&sb, logfile, 0) < 0)
-			die("could not read log file '%s': %s",
-			    logfile, strerror(errno));
+			die_errno("could not read log file '%s'",
+				  logfile);
 		hook_arg1 = "message";
 	} else if (use_message) {
 		buffer = strstr(use_message_buffer, "\n\n");
@@ -450,16 +450,15 @@
 		hook_arg2 = use_message;
 	} else if (!stat(git_path("MERGE_MSG"), &statbuf)) {
 		if (strbuf_read_file(&sb, git_path("MERGE_MSG"), 0) < 0)
-			die("could not read MERGE_MSG: %s", strerror(errno));
+			die_errno("could not read MERGE_MSG");
 		hook_arg1 = "merge";
 	} else if (!stat(git_path("SQUASH_MSG"), &statbuf)) {
 		if (strbuf_read_file(&sb, git_path("SQUASH_MSG"), 0) < 0)
-			die("could not read SQUASH_MSG: %s", strerror(errno));
+			die_errno("could not read SQUASH_MSG");
 		hook_arg1 = "squash";
 	} else if (template_file && !stat(template_file, &statbuf)) {
 		if (strbuf_read_file(&sb, template_file, 0) < 0)
-			die("could not read %s: %s",
-			    template_file, strerror(errno));
+			die_errno("could not read '%s'", template_file);
 		hook_arg1 = "template";
 	}
 
@@ -472,8 +471,7 @@
 
 	fp = fopen(git_path(commit_editmsg), "w");
 	if (fp == NULL)
-		die("could not open %s: %s",
-		    git_path(commit_editmsg), strerror(errno));
+		die_errno("could not open '%s'", git_path(commit_editmsg));
 
 	if (cleanup_mode != CLEANUP_NONE)
 		stripspace(&sb, 0);
@@ -497,7 +495,7 @@
 	}
 
 	if (fwrite(sb.buf, 1, sb.len, fp) < sb.len)
-		die("could not write commit template: %s", strerror(errno));
+		die_errno("could not write commit template");
 
 	strbuf_release(&sb);
 
@@ -940,8 +938,8 @@
 		pptr = &commit_list_insert(lookup_commit(head_sha1), pptr)->next;
 		fp = fopen(git_path("MERGE_HEAD"), "r");
 		if (fp == NULL)
-			die("could not open %s for reading: %s",
-			    git_path("MERGE_HEAD"), strerror(errno));
+			die_errno("could not open '%s' for reading",
+				  git_path("MERGE_HEAD"));
 		while (strbuf_getline(&m, fp, '\n') != EOF) {
 			unsigned char sha1[20];
 			if (get_sha1_hex(m.buf, sha1) < 0)
@@ -952,8 +950,7 @@
 		strbuf_release(&m);
 		if (!stat(git_path("MERGE_MODE"), &statbuf)) {
 			if (strbuf_read_file(&sb, git_path("MERGE_MODE"), 0) < 0)
-				die("could not read MERGE_MODE: %s",
-						strerror(errno));
+				die_errno("could not read MERGE_MODE");
 			if (!strcmp(sb.buf, "no-ff"))
 				allow_fast_forward = 0;
 		}
@@ -967,8 +964,9 @@
 	/* Finally, get the commit message */
 	strbuf_reset(&sb);
 	if (strbuf_read_file(&sb, git_path(commit_editmsg), 0) < 0) {
+		int saved_errno = errno;
 		rollback_index_files();
-		die("could not read commit message");
+		die("could not read commit message: %s", strerror(saved_errno));
 	}
 
 	/* Truncate the message just before the diff, if any. */
diff --git a/builtin-config.c b/builtin-config.c
index 60915f9..a2d656e 100644
--- a/builtin-config.c
+++ b/builtin-config.c
@@ -383,8 +383,8 @@
 		check_argc(argc, 0, 0);
 		if (git_config(show_all_config, NULL) < 0) {
 			if (config_exclusive_filename)
-				die("unable to read config file %s: %s",
-				    config_exclusive_filename, strerror(errno));
+				die_errno("unable to read config file '%s'",
+					  config_exclusive_filename);
 			else
 				die("error processing config file(s)");
 		}
diff --git a/builtin-diff.c b/builtin-diff.c
index d75d69b..2e51f40 100644
--- a/builtin-diff.c
+++ b/builtin-diff.c
@@ -70,7 +70,7 @@
 		usage(builtin_diff_usage);
 
 	if (lstat(path, &st))
-		die("'%s': %s", path, strerror(errno));
+		die_errno("failed to stat '%s'", path);
 	if (!(S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)))
 		die("'%s': not a regular file or symlink", path);
 
diff --git a/builtin-fast-export.c b/builtin-fast-export.c
index 6cef810..9a8a6fc 100644
--- a/builtin-fast-export.c
+++ b/builtin-fast-export.c
@@ -119,7 +119,7 @@
 
 	printf("blob\nmark :%"PRIu32"\ndata %lu\n", last_idnum, size);
 	if (size && fwrite(buf, size, 1, stdout) != 1)
-		die ("Could not write blob %s", sha1_to_hex(sha1));
+		die_errno ("Could not write blob '%s'", sha1_to_hex(sha1));
 	printf("\n");
 
 	show_progress();
@@ -451,7 +451,7 @@
 	char line[512];
 	FILE *f = fopen(input_file, "r");
 	if (!f)
-		die("cannot read %s: %s", input_file, strerror(errno));
+		die_errno("cannot read '%s'", input_file);
 
 	while (fgets(line, sizeof(line), f)) {
 		uint32_t mark;
diff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c
index 29356d2..3dbdf7a 100644
--- a/builtin-fetch--tool.c
+++ b/builtin-fetch--tool.c
@@ -8,7 +8,7 @@
 {
 	struct strbuf buf = STRBUF_INIT;
 	if (strbuf_read(&buf, 0, 1024) < 0) {
-		die("error reading standard input: %s", strerror(errno));
+		die_errno("error reading standard input");
 	}
 	return strbuf_detach(&buf, NULL);
 }
diff --git a/builtin-fmt-merge-msg.c b/builtin-fmt-merge-msg.c
index fbf9582..9d52400 100644
--- a/builtin-fmt-merge-msg.c
+++ b/builtin-fmt-merge-msg.c
@@ -368,12 +368,11 @@
 	if (inpath && strcmp(inpath, "-")) {
 		in = fopen(inpath, "r");
 		if (!in)
-			die("cannot open %s", inpath);
+			die_errno("cannot open '%s'", inpath);
 	}
 
 	if (strbuf_read(&input, fileno(in), 0) < 0)
-		die("could not read input file %s", strerror(errno));
-
+		die_errno("could not read input file");
 	ret = fmt_merge_msg(merge_summary, &input, &output);
 	if (ret)
 		return ret;
diff --git a/builtin-fsck.c b/builtin-fsck.c
index e077e72..b3d38fa 100644
--- a/builtin-fsck.c
+++ b/builtin-fsck.c
@@ -217,7 +217,7 @@
 				return;
 			}
 			if (!(f = fopen(filename, "w")))
-				die("Could not open %s", filename);
+				die_errno("Could not open '%s'", filename);
 			if (obj->type == OBJ_BLOB) {
 				enum object_type type;
 				unsigned long size;
@@ -225,15 +225,15 @@
 						&type, &size);
 				if (buf) {
 					if (fwrite(buf, size, 1, f) != 1)
-						die("Could not write %s: %s",
-						    filename, strerror(errno));
+						die_errno("Could not write '%s'",
+							  filename);
 					free(buf);
 				}
 			} else
 				fprintf(f, "%s\n", sha1_to_hex(obj->sha1));
 			if (fclose(f))
-				die("Could not finish %s: %s",
-				    filename, strerror(errno));
+				die_errno("Could not finish '%s'",
+					  filename);
 		}
 		return;
 	}
diff --git a/builtin-grep.c b/builtin-grep.c
index 73fc922..f477659 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -11,6 +11,7 @@
 #include "tree-walk.h"
 #include "builtin.h"
 #include "parse-options.h"
+#include "userdiff.h"
 #include "grep.h"
 
 #ifndef NO_EXTERNAL_GREP
@@ -30,6 +31,12 @@
 {
 	struct grep_opt *opt = cb;
 
+	switch (userdiff_config(var, value)) {
+	case 0: break;
+	case -1: return -1;
+	default: return 0;
+	}
+
 	if (!strcmp(var, "color.grep")) {
 		opt->color = git_config_colorbool(var, value, -1);
 		return 0;
@@ -278,6 +285,17 @@
 		argc -= 2;
 	}
 
+	if (opt->pre_context || opt->post_context) {
+		/*
+		 * grep handles hunk marks between files, but we need to
+		 * do that ourselves between multiple calls.
+		 */
+		if (opt->show_hunk_mark)
+			write_or_die(1, "--\n", 3);
+		else
+			opt->show_hunk_mark = 1;
+	}
+
 	status = exec_grep(argc, argv);
 
 	if (kept_0) {
@@ -594,7 +612,7 @@
 
 	patterns = fopen(arg, "r");
 	if (!patterns)
-		die("'%s': %s", arg, strerror(errno));
+		die_errno("cannot open '%s'", arg);
 	while (strbuf_getline(&sb, patterns, '\n') == 0) {
 		/* ignore empty line like grep does */
 		if (sb.len == 0)
@@ -710,6 +728,8 @@
 			"show <n> context lines after matches"),
 		OPT_NUMBER_CALLBACK(&opt, "shortcut for -C NUM",
 			context_callback),
+		OPT_BOOLEAN('p', "show-function", &opt.funcname,
+			"show a line with the function name before matches"),
 		OPT_GROUP(""),
 		OPT_CALLBACK('f', NULL, &opt, "file",
 			"read patterns from file", file_callback),
@@ -778,7 +798,7 @@
 		argc--;
 	}
 
-	if (opt.color && !opt.color_external)
+	if ((opt.color && !opt.color_external) || opt.funcname)
 		external_grep_allowed = 0;
 	if (!opt.pattern_list)
 		die("no pattern given.");
diff --git a/builtin-init-db.c b/builtin-init-db.c
index d1fa12a..4a56006 100644
--- a/builtin-init-db.c
+++ b/builtin-init-db.c
@@ -61,20 +61,20 @@
 		memcpy(template + template_baselen, de->d_name, namelen+1);
 		if (lstat(path, &st_git)) {
 			if (errno != ENOENT)
-				die("cannot stat %s", path);
+				die_errno("cannot stat '%s'", path);
 		}
 		else
 			exists = 1;
 
 		if (lstat(template, &st_template))
-			die("cannot stat template %s", template);
+			die_errno("cannot stat template '%s'", template);
 
 		if (S_ISDIR(st_template.st_mode)) {
 			DIR *subdir = opendir(template);
 			int baselen_sub = baselen + namelen;
 			int template_baselen_sub = template_baselen + namelen;
 			if (!subdir)
-				die("cannot opendir %s", template);
+				die_errno("cannot opendir '%s'", template);
 			path[baselen_sub++] =
 				template[template_baselen_sub++] = '/';
 			path[baselen_sub] =
@@ -91,16 +91,17 @@
 			int len;
 			len = readlink(template, lnk, sizeof(lnk));
 			if (len < 0)
-				die("cannot readlink %s", template);
+				die_errno("cannot readlink '%s'", template);
 			if (sizeof(lnk) <= len)
 				die("insanely long symlink %s", template);
 			lnk[len] = 0;
 			if (symlink(lnk, path))
-				die("cannot symlink %s %s", lnk, path);
+				die_errno("cannot symlink '%s' '%s'", lnk, path);
 		}
 		else if (S_ISREG(st_template.st_mode)) {
 			if (copy_file(path, template, st_template.st_mode))
-				die("cannot copy %s to %s", template, path);
+				die_errno("cannot copy '%s' to '%s'", template,
+					  path);
 		}
 		else
 			error("ignoring template %s", template);
@@ -350,7 +351,7 @@
 	if (!strcmp(".", git_dir))
 		return 1;
 	if (!getcwd(cwd, sizeof(cwd)))
-		die("cannot tell cwd");
+		die_errno("cannot tell cwd");
 	if (!strcmp(git_dir, cwd))
 		return 1;
 	/*
@@ -440,11 +441,11 @@
 		if (!git_work_tree_cfg) {
 			git_work_tree_cfg = xcalloc(PATH_MAX, 1);
 			if (!getcwd(git_work_tree_cfg, PATH_MAX))
-				die ("Cannot access current working directory.");
+				die_errno ("Cannot access current working directory");
 		}
 		if (access(get_git_work_tree(), X_OK))
-			die ("Cannot access work tree '%s'",
-			     get_git_work_tree());
+			die_errno ("Cannot access work tree '%s'",
+				   get_git_work_tree());
 	}
 
 	set_git_dir(make_absolute_path(git_dir));
diff --git a/builtin-log.c b/builtin-log.c
index 44f9a27..0c2fa0a 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -1013,8 +1013,8 @@
 		if (use_stdout)
 			die("standard output, or directory, which one?");
 		if (mkdir(output_directory, 0777) < 0 && errno != EEXIST)
-			die("Could not create directory %s",
-			    output_directory);
+			die_errno("Could not create directory '%s'",
+				  output_directory);
 	}
 
 	if (rev.pending.nr == 1) {
diff --git a/builtin-mailsplit.c b/builtin-mailsplit.c
index 71f3b3b..ad5f6b5 100644
--- a/builtin-mailsplit.c
+++ b/builtin-mailsplit.c
@@ -81,7 +81,7 @@
 
 	fd = open(name, O_WRONLY | O_CREAT | O_EXCL, 0666);
 	if (fd < 0)
-		die("cannot open output file %s", name);
+		die_errno("cannot open output file '%s'", name);
 	output = fdopen(fd, "w");
 
 	/* Copy it out, while searching for a line that begins with
@@ -91,7 +91,7 @@
 		int is_partial = len && buf[len-1] != '\n';
 
 		if (fwrite(buf, 1, len, output) != len)
-			die("cannot write output");
+			die_errno("cannot write output");
 
 		len = read_line_with_nul(buf, sizeof(buf), mbox);
 		if (len == 0) {
@@ -99,7 +99,7 @@
 				status = 1;
 				break;
 			}
-			die("cannot read mbox");
+			die_errno("cannot read mbox");
 		}
 		if (!is_partial && !is_bare && is_from_line(buf, len))
 			break; /* done with one message */
diff --git a/builtin-merge.c b/builtin-merge.c
index af9adab..82b5466 100644
--- a/builtin-merge.c
+++ b/builtin-merge.c
@@ -268,7 +268,7 @@
 	printf("Squash commit -- not updating HEAD\n");
 	fd = open(git_path("SQUASH_MSG"), O_WRONLY | O_CREAT, 0666);
 	if (fd < 0)
-		die("Could not write to %s", git_path("SQUASH_MSG"));
+		die_errno("Could not write to '%s'", git_path("SQUASH_MSG"));
 
 	init_revisions(&rev, NULL);
 	rev.ignore_merges = 1;
@@ -294,9 +294,9 @@
 			NULL, NULL, rev.date_mode, 0);
 	}
 	if (write(fd, out.buf, out.len) < 0)
-		die("Writing SQUASH_MSG: %s", strerror(errno));
+		die_errno("Writing SQUASH_MSG");
 	if (close(fd))
-		die("Finishing SQUASH_MSG: %s", strerror(errno));
+		die_errno("Finishing SQUASH_MSG");
 	strbuf_release(&out);
 }
 
@@ -428,8 +428,8 @@
 
 		fp = fopen(git_path("FETCH_HEAD"), "r");
 		if (!fp)
-			die("could not open %s for reading: %s",
-				git_path("FETCH_HEAD"), strerror(errno));
+			die_errno("could not open '%s' for reading",
+				  git_path("FETCH_HEAD"));
 		strbuf_getline(&line, fp, '\n');
 		fclose(fp);
 		ptr = strstr(line.buf, "\tnot-for-merge\t");
@@ -764,7 +764,8 @@
 
 	fp = fopen(git_path("MERGE_MSG"), "a");
 	if (!fp)
-		die("Could not open %s for writing", git_path("MERGE_MSG"));
+		die_errno("Could not open '%s' for writing",
+			  git_path("MERGE_MSG"));
 	fprintf(fp, "\nConflicts:\n");
 	for (pos = 0; pos < active_nr; pos++) {
 		struct cache_entry *ce = active_cache[pos];
@@ -1189,27 +1190,29 @@
 				sha1_to_hex(j->item->object.sha1));
 		fd = open(git_path("MERGE_HEAD"), O_WRONLY | O_CREAT, 0666);
 		if (fd < 0)
-			die("Could open %s for writing",
-				git_path("MERGE_HEAD"));
+			die_errno("Could not open '%s' for writing",
+				  git_path("MERGE_HEAD"));
 		if (write_in_full(fd, buf.buf, buf.len) != buf.len)
-			die("Could not write to %s", git_path("MERGE_HEAD"));
+			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("Could open %s for writing", git_path("MERGE_MSG"));
+			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("Could not write to %s", git_path("MERGE_MSG"));
+			die_errno("Could not write to '%s'", git_path("MERGE_MSG"));
 		close(fd);
 		fd = open(git_path("MERGE_MODE"), O_WRONLY | O_CREAT | O_TRUNC, 0666);
 		if (fd < 0)
-			die("Could open %s for writing", git_path("MERGE_MODE"));
+			die_errno("Could not open '%s' for writing",
+				  git_path("MERGE_MODE"));
 		strbuf_reset(&buf);
 		if (!allow_fast_forward)
 			strbuf_addf(&buf, "no-ff");
 		if (write_in_full(fd, buf.buf, buf.len) != buf.len)
-			die("Could not write to %s", git_path("MERGE_MODE"));
+			die_errno("Could not write to '%s'", git_path("MERGE_MODE"));
 		close(fd);
 	}
 
diff --git a/builtin-mv.c b/builtin-mv.c
index 8b81d4b..b592c36 100644
--- a/builtin-mv.c
+++ b/builtin-mv.c
@@ -24,14 +24,10 @@
 	result[count] = NULL;
 	for (i = 0; i < count; i++) {
 		int length = strlen(result[i]);
-		if (length > 0 && result[i][length - 1] == '/') {
+		if (length > 0 && is_dir_sep(result[i][length - 1]))
 			result[i] = xmemdupz(result[i], length - 1);
-		}
-		if (base_name) {
-			const char *last_slash = strrchr(result[i], '/');
-			if (last_slash)
-				result[i] = last_slash + 1;
-		}
+		if (base_name)
+			result[i] = basename((char *)result[i]);
 	}
 	return get_pathspec(prefix, result);
 }
@@ -209,7 +205,7 @@
 			printf("Renaming %s to %s\n", src, dst);
 		if (!show_only && mode != INDEX &&
 				rename(src, dst) < 0 && !ignore_errors)
-			die ("renaming %s failed: %s", src, strerror(errno));
+			die_errno ("renaming '%s' failed", src);
 
 		if (mode == WORKING_DIRECTORY)
 			continue;
diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
index 941cc2d..a27c2f6 100644
--- a/builtin-pack-objects.c
+++ b/builtin-pack-objects.c
@@ -536,11 +536,9 @@
 				 base_name, sha1_to_hex(sha1));
 			free_pack_by_name(tmpname);
 			if (adjust_perm(pack_tmp_name, mode))
-				die("unable to make temporary pack file readable: %s",
-				    strerror(errno));
+				die_errno("unable to make temporary pack file readable");
 			if (rename(pack_tmp_name, tmpname))
-				die("unable to rename temporary pack file: %s",
-				    strerror(errno));
+				die_errno("unable to rename temporary pack file");
 
 			/*
 			 * Packs are runtime accessed in their mtime
@@ -566,11 +564,9 @@
 			snprintf(tmpname, sizeof(tmpname), "%s-%s.idx",
 				 base_name, sha1_to_hex(sha1));
 			if (adjust_perm(idx_tmp_name, mode))
-				die("unable to make temporary index file readable: %s",
-				    strerror(errno));
+				die_errno("unable to make temporary index file readable");
 			if (rename(idx_tmp_name, tmpname))
-				die("unable to rename temporary index file: %s",
-				    strerror(errno));
+				die_errno("unable to rename temporary index file");
 
 			free(idx_tmp_name);
 			free(pack_tmp_name);
@@ -1879,7 +1875,7 @@
 			if (!ferror(stdin))
 				die("fgets returned NULL, not EOF, not error!");
 			if (errno != EINTR)
-				die("fgets: %s", strerror(errno));
+				die_errno("fgets");
 			clearerr(stdin);
 			continue;
 		}
diff --git a/builtin-receive-pack.c b/builtin-receive-pack.c
index 33d345d..6ec1d05 100644
--- a/builtin-receive-pack.c
+++ b/builtin-receive-pack.c
@@ -123,27 +123,27 @@
 static const char pre_receive_hook[] = "hooks/pre-receive";
 static const char post_receive_hook[] = "hooks/post-receive";
 
-static int hook_status(int code, const char *hook_name)
+static int run_status(int code, const char *cmd_name)
 {
 	switch (code) {
 	case 0:
 		return 0;
 	case -ERR_RUN_COMMAND_FORK:
-		return error("hook fork failed");
+		return error("fork of %s failed", cmd_name);
 	case -ERR_RUN_COMMAND_EXEC:
-		return error("hook execute failed");
+		return error("execute of %s failed", cmd_name);
 	case -ERR_RUN_COMMAND_PIPE:
-		return error("hook pipe failed");
+		return error("pipe failed");
 	case -ERR_RUN_COMMAND_WAITPID:
 		return error("waitpid failed");
 	case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
 		return error("waitpid is confused");
 	case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
-		return error("%s died of signal", hook_name);
+		return error("%s died of signal", cmd_name);
 	case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
-		return error("%s died strangely", hook_name);
+		return error("%s died strangely", cmd_name);
 	default:
-		error("%s exited with error code %d", hook_name, -code);
+		error("%s exited with error code %d", cmd_name, -code);
 		return -code;
 	}
 }
@@ -174,7 +174,7 @@
 
 	code = start_command(&proc);
 	if (code)
-		return hook_status(code, hook_name);
+		return run_status(code, hook_name);
 	for (cmd = commands; cmd; cmd = cmd->next) {
 		if (!cmd->error_string) {
 			size_t n = snprintf(buf, sizeof(buf), "%s %s %s\n",
@@ -186,7 +186,7 @@
 		}
 	}
 	close(proc.in);
-	return hook_status(finish_command(&proc), hook_name);
+	return run_status(finish_command(&proc), hook_name);
 }
 
 static int run_update_hook(struct command *cmd)
@@ -203,7 +203,7 @@
 	argv[3] = sha1_to_hex(cmd->new_sha1);
 	argv[4] = NULL;
 
-	return hook_status(run_command_v_opt(argv, RUN_COMMAND_NO_STDIN |
+	return run_status(run_command_v_opt(argv, RUN_COMMAND_NO_STDIN |
 					RUN_COMMAND_STDOUT_TO_STDERR),
 			update_hook);
 }
@@ -394,7 +394,7 @@
 static void run_update_post_hook(struct command *cmd)
 {
 	struct command *cmd_p;
-	int argc;
+	int argc, status;
 	const char **argv;
 
 	for (argc = 0, cmd_p = cmd; cmd_p; cmd_p = cmd_p->next) {
@@ -417,8 +417,9 @@
 		argc++;
 	}
 	argv[argc] = NULL;
-	run_command_v_opt(argv, RUN_COMMAND_NO_STDIN
-		| RUN_COMMAND_STDOUT_TO_STDERR);
+	status = run_command_v_opt(argv, RUN_COMMAND_NO_STDIN
+			| RUN_COMMAND_STDOUT_TO_STDERR);
+	run_status(status, update_post_hook);
 }
 
 static void execute_commands(const char *unpacker_error)
@@ -534,24 +535,10 @@
 		unpacker[i++] = hdr_arg;
 		unpacker[i++] = NULL;
 		code = run_command_v_opt(unpacker, RUN_GIT_CMD);
-		switch (code) {
-		case 0:
+		if (!code)
 			return NULL;
-		case -ERR_RUN_COMMAND_FORK:
-			return "unpack fork failed";
-		case -ERR_RUN_COMMAND_EXEC:
-			return "unpack execute failed";
-		case -ERR_RUN_COMMAND_WAITPID:
-			return "waitpid failed";
-		case -ERR_RUN_COMMAND_WAITPID_WRONG_PID:
-			return "waitpid is confused";
-		case -ERR_RUN_COMMAND_WAITPID_SIGNAL:
-			return "unpacker died of signal";
-		case -ERR_RUN_COMMAND_WAITPID_NOEXIT:
-			return "unpacker died strangely";
-		default:
-			return "unpacker exited with error code";
-		}
+		run_status(code, unpacker[0]);
+		return "unpack-objects abnormal exit";
 	} else {
 		const char *keeper[7];
 		int s, status, i = 0;
@@ -574,8 +561,11 @@
 		ip.argv = keeper;
 		ip.out = -1;
 		ip.git_cmd = 1;
-		if (start_command(&ip))
+		status = start_command(&ip);
+		if (status) {
+			run_status(status, keeper[0]);
 			return "index-pack fork failed";
+		}
 		pack_lockfile = index_pack_lockfile(ip.out);
 		close(ip.out);
 		status = finish_command(&ip);
@@ -583,6 +573,7 @@
 			reprepare_packed_git();
 			return NULL;
 		}
+		run_status(status, keeper[0]);
 		return "index-pack abnormal exit";
 	}
 }
diff --git a/builtin-remote.c b/builtin-remote.c
index 2fb76d3..008abfe 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -787,7 +787,7 @@
 	read_branches();
 
 	if (query) {
-		transport = transport_get(NULL, states->remote->url_nr > 0 ?
+		transport = transport_get(states->remote, states->remote->url_nr > 0 ?
 			states->remote->url[0] : NULL);
 		remote_refs = transport_get_remote_refs(transport);
 		transport_disconnect(transport);
diff --git a/builtin-rev-parse.c b/builtin-rev-parse.c
index 112d622..45bead6 100644
--- a/builtin-rev-parse.c
+++ b/builtin-rev-parse.c
@@ -301,7 +301,7 @@
 
 static int cmd_parseopt(int argc, const char **argv, const char *prefix)
 {
-	static int keep_dashdash = 0;
+	static int keep_dashdash = 0, stop_at_non_option = 0;
 	static char const * const parseopt_usage[] = {
 		"git rev-parse --parseopt [options] -- [<args>...]",
 		NULL
@@ -309,6 +309,9 @@
 	static struct option parseopt_opts[] = {
 		OPT_BOOLEAN(0, "keep-dashdash", &keep_dashdash,
 					"keep the `--` passed as an arg"),
+		OPT_BOOLEAN(0, "stop-at-non-option", &stop_at_non_option,
+					"stop parsing after the "
+					"first non-option argument"),
 		OPT_END(),
 	};
 
@@ -394,7 +397,8 @@
 	ALLOC_GROW(opts, onb + 1, osz);
 	memset(opts + onb, 0, sizeof(opts[onb]));
 	argc = parse_options(argc, argv, prefix, opts, usage,
-	                     keep_dashdash ? PARSE_OPT_KEEP_DASHDASH : 0);
+			keep_dashdash ? PARSE_OPT_KEEP_DASHDASH : 0 |
+			stop_at_non_option ? PARSE_OPT_STOP_AT_NON_OPTION : 0);
 
 	strbuf_addf(&parsed, " --");
 	sq_quote_argv(&parsed, argv, 0);
@@ -592,7 +596,7 @@
 					continue;
 				}
 				if (!getcwd(cwd, PATH_MAX))
-					die("unable to get current working directory");
+					die_errno("unable to get current working directory");
 				printf("%s/.git\n", cwd);
 				continue;
 			}
diff --git a/builtin-revert.c b/builtin-revert.c
index c87115a..151aa6a 100644
--- a/builtin-revert.c
+++ b/builtin-revert.c
@@ -135,7 +135,7 @@
 {
 	int len = strlen(string);
 	if (write_in_full(msg_fd, string, len) < 0)
-		die ("Could not write to MERGE_MSG");
+		die_errno ("Could not write to MERGE_MSG");
 }
 
 static void add_message_to_msg(const char *message)
diff --git a/builtin-rm.c b/builtin-rm.c
index 0cc4912..57975db 100644
--- a/builtin-rm.c
+++ b/builtin-rm.c
@@ -257,7 +257,7 @@
 				continue;
 			}
 			if (!removed)
-				die("git rm: %s: %s", path, strerror(errno));
+				die_errno("git rm: '%s'", path);
 		}
 	}
 
diff --git a/builtin-send-pack.c b/builtin-send-pack.c
index c375a3d..47fb9f7 100644
--- a/builtin-send-pack.c
+++ b/builtin-send-pack.c
@@ -59,7 +59,7 @@
 	po.out = fd;
 	po.git_cmd = 1;
 	if (start_command(&po))
-		die("git pack-objects failed (%s)", strerror(errno));
+		die_errno("git pack-objects failed");
 
 	/*
 	 * We feed the pack-objects we just spawned with revision
diff --git a/builtin-show-ref.c b/builtin-show-ref.c
index dc76c50..c46550c 100644
--- a/builtin-show-ref.c
+++ b/builtin-show-ref.c
@@ -4,12 +4,18 @@
 #include "object.h"
 #include "tag.h"
 #include "string-list.h"
+#include "parse-options.h"
 
-static const char show_ref_usage[] = "git show-ref [-q|--quiet] [--verify] [-h|--head] [-d|--dereference] [-s|--hash[=<length>]] [--abbrev[=<length>]] [--tags] [--heads] [--] [pattern*] < ref-list";
+static const char * const show_ref_usage[] = {
+	"git show-ref [-q|--quiet] [--verify] [-h|--head] [-d|--dereference] [-s|--hash[=<n>]] [--abbrev[=<n>]] [--tags] [--heads] [--] [pattern*] ",
+	"git show-ref --exclude-existing[=pattern] < ref-list",
+	NULL
+};
 
-static int deref_tags = 0, show_head = 0, tags_only = 0, heads_only = 0,
-	found_match = 0, verify = 0, quiet = 0, hash_only = 0, abbrev = 0;
+static int deref_tags, show_head, tags_only, heads_only, found_match, verify,
+	   quiet, hash_only, abbrev, exclude_arg;
 static const char **pattern;
+static const char *exclude_existing_arg;
 
 static void show_one(const char *refname, const unsigned char *sha1)
 {
@@ -150,79 +156,60 @@
 	return 0;
 }
 
+static int hash_callback(const struct option *opt, const char *arg, int unset)
+{
+	hash_only = 1;
+	/* Use full length SHA1 if no argument */
+	if (!arg)
+		return 0;
+	return parse_opt_abbrev_cb(opt, arg, unset);
+}
+
+static int exclude_existing_callback(const struct option *opt, const char *arg,
+				     int unset)
+{
+	exclude_arg = 1;
+	*(const char **)opt->value = arg;
+	return 0;
+}
+
+static int help_callback(const struct option *opt, const char *arg, int unset)
+{
+	return -1;
+}
+
+static const struct option show_ref_options[] = {
+	OPT_BOOLEAN(0, "tags", &tags_only, "only show tags (can be combined with heads)"),
+	OPT_BOOLEAN(0, "heads", &heads_only, "only show heads (can be combined with tags)"),
+	OPT_BOOLEAN(0, "verify", &verify, "stricter reference checking, "
+		    "requires exact ref path"),
+	OPT_BOOLEAN('h', "head", &show_head, "show the HEAD reference"),
+	OPT_BOOLEAN('d', "dereference", &deref_tags,
+		    "dereference tags into object IDs"),
+	{ OPTION_CALLBACK, 's', "hash", &abbrev, "n",
+	  "only show SHA1 hash using <n> digits",
+	  PARSE_OPT_OPTARG, &hash_callback },
+	OPT__ABBREV(&abbrev),
+	OPT__QUIET(&quiet),
+	{ OPTION_CALLBACK, 0, "exclude-existing", &exclude_existing_arg,
+	  "pattern", "show refs from stdin that aren't in local repository",
+	  PARSE_OPT_OPTARG | PARSE_OPT_NONEG, exclude_existing_callback },
+	{ OPTION_CALLBACK, 0, "help-all", NULL, NULL, "show usage",
+	  PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, help_callback },
+	OPT_END()
+};
+
 int cmd_show_ref(int argc, const char **argv, const char *prefix)
 {
-	int i;
+	argc = parse_options(argc, argv, prefix, show_ref_options,
+			     show_ref_usage, PARSE_OPT_NO_INTERNAL_HELP);
 
-	for (i = 1; i < argc; i++) {
-		const char *arg = argv[i];
-		if (*arg != '-') {
-			pattern = argv + i;
-			break;
-		}
-		if (!strcmp(arg, "--")) {
-			pattern = argv + i + 1;
-			if (!*pattern)
-				pattern = NULL;
-			break;
-		}
-		if (!strcmp(arg, "-q") || !strcmp(arg, "--quiet")) {
-			quiet = 1;
-			continue;
-		}
-		if (!strcmp(arg, "-h") || !strcmp(arg, "--head")) {
-			show_head = 1;
-			continue;
-		}
-		if (!strcmp(arg, "-d") || !strcmp(arg, "--dereference")) {
-			deref_tags = 1;
-			continue;
-		}
-		if (!strcmp(arg, "-s") || !strcmp(arg, "--hash")) {
-			hash_only = 1;
-			continue;
-		}
-		if (!prefixcmp(arg, "--hash=") ||
-		    (!prefixcmp(arg, "--abbrev") &&
-		     (arg[8] == '=' || arg[8] == '\0'))) {
-			if (arg[2] != 'h' && !arg[8])
-				/* --abbrev only */
-				abbrev = DEFAULT_ABBREV;
-			else {
-				/* --hash= or --abbrev= */
-				char *end;
-				if (arg[2] == 'h') {
-					hash_only = 1;
-					arg += 7;
-				}
-				else
-					arg += 9;
-				abbrev = strtoul(arg, &end, 10);
-				if (*end || abbrev > 40)
-					usage(show_ref_usage);
-				if (abbrev < MINIMUM_ABBREV)
-					abbrev = MINIMUM_ABBREV;
-			}
-			continue;
-		}
-		if (!strcmp(arg, "--verify")) {
-			verify = 1;
-			continue;
-		}
-		if (!strcmp(arg, "--tags")) {
-			tags_only = 1;
-			continue;
-		}
-		if (!strcmp(arg, "--heads")) {
-			heads_only = 1;
-			continue;
-		}
-		if (!strcmp(arg, "--exclude-existing"))
-			return exclude_existing(NULL);
-		if (!prefixcmp(arg, "--exclude-existing="))
-			return exclude_existing(arg + 19);
-		usage(show_ref_usage);
-	}
+	if (exclude_arg)
+		return exclude_existing(exclude_existing_arg);
+
+	pattern = argv;
+	if (!*pattern)
+		pattern = NULL;
 
 	if (verify) {
 		if (!pattern)
diff --git a/builtin-stripspace.c b/builtin-stripspace.c
index d6e3896..1fd2205 100644
--- a/builtin-stripspace.c
+++ b/builtin-stripspace.c
@@ -78,7 +78,7 @@
 		strip_comments = 1;
 
 	if (strbuf_read(&buf, 0, 1024) < 0)
-		die("could not read the input");
+		die_errno("could not read the input");
 
 	stripspace(&buf, strip_comments);
 
diff --git a/builtin-tag.c b/builtin-tag.c
index 080e04a..a51a6d1 100644
--- a/builtin-tag.c
+++ b/builtin-tag.c
@@ -308,8 +308,7 @@
 		path = git_pathdup("TAG_EDITMSG");
 		fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
 		if (fd < 0)
-			die("could not create file '%s': %s",
-						path, strerror(errno));
+			die_errno("could not create file '%s'", path);
 
 		if (!is_null_sha1(prev))
 			write_tag_body(fd, prev);
@@ -443,11 +442,11 @@
 		else {
 			if (!strcmp(msgfile, "-")) {
 				if (strbuf_read(&buf, 0, 1024) < 0)
-					die("cannot read %s", msgfile);
+					die_errno("cannot read '%s'", msgfile);
 			} else {
 				if (strbuf_read_file(&buf, msgfile, 1024) < 0)
-					die("could not open or read '%s': %s",
-						msgfile, strerror(errno));
+					die_errno("could not open or read '%s'",
+						msgfile);
 			}
 		}
 	}
diff --git a/builtin-tar-tree.c b/builtin-tar-tree.c
index f88e721..8b3a35e 100644
--- a/builtin-tar-tree.c
+++ b/builtin-tar-tree.c
@@ -91,7 +91,7 @@
 
 	n = write_in_full(1, content + 11, 41);
 	if (n < 41)
-		die("git get-tar-commit-id: write error");
+		die_errno("git get-tar-commit-id: write error");
 
 	return 0;
 }
diff --git a/builtin-unpack-objects.c b/builtin-unpack-objects.c
index 7e3ea73..557148a 100644
--- a/builtin-unpack-objects.c
+++ b/builtin-unpack-objects.c
@@ -68,7 +68,7 @@
 		if (ret <= 0) {
 			if (!ret)
 				die("early EOF");
-			die("read error on input: %s", strerror(errno));
+			die_errno("read error on input");
 		}
 		len += ret;
 	} while (len < min);
diff --git a/combine-diff.c b/combine-diff.c
index 60d0367..bbf74fc 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -746,7 +746,7 @@
 
 			done = read_in_full(fd, result, len);
 			if (done < 0)
-				die("read error '%s'", elem->path);
+				die_errno("read error '%s'", elem->path);
 			else if (done < len)
 				die("early EOF '%s'", elem->path);
 
diff --git a/commit.c b/commit.c
index aa3b35b..a47fb4d 100644
--- a/commit.c
+++ b/commit.c
@@ -50,7 +50,6 @@
 
 static unsigned long parse_commit_date(const char *buf, const char *tail)
 {
-	unsigned long date;
 	const char *dateptr;
 
 	if (buf + 6 >= tail)
@@ -73,10 +72,7 @@
 	if (buf >= tail)
 		return 0;
 	/* dateptr < buf && buf[-1] == '\n', so strtoul will stop at buf-1 */
-	date = strtoul(dateptr, NULL, 10);
-	if (date == ULONG_MAX)
-		date = 0;
-	return date;
+	return strtoul(dateptr, NULL, 10);
 }
 
 static struct commit_graft **commit_graft;
diff --git a/compat/mingw.h b/compat/mingw.h
index 4f7ba4c..c1859c5 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -92,6 +92,8 @@
 	errno = EINVAL;
 	return -1;
 }
+/* bash cannot reliably detect negative return codes as failure */
+#define exit(code) exit((code) & 0xff)
 
 /*
  * simple adaptors
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index b60cb68..9c48864 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1165,7 +1165,7 @@
 			$__git_log_shortlog_options
 			$__git_log_gitk_options
 			--root --topo-order --date-order --reverse
-			--follow
+			--follow --full-diff
 			--abbrev-commit --abbrev=
 			--relative-date --date=
 			--pretty= --format= --oneline
@@ -1357,11 +1357,12 @@
 		c=$((--c))
 	done
 
-	for i in $(git --git-dir="$(__gitdir)" config $config_file --list \
-			2>/dev/null); do
-		case "$i" in
-		*.*)
-			echo "${i/=*/}"
+	git --git-dir="$(__gitdir)" config $config_file --list 2>/dev/null |
+	while read line
+	do
+		case "$line" in
+		*.*=*)
+			echo "${line/=*/}"
 			;;
 		esac
 	done
@@ -1457,7 +1458,7 @@
 	branch.*.*)
 		local pfx="${cur%.*}."
 		cur="${cur##*.}"
-		__gitcomp "remote merge mergeoptions" "$pfx" "$cur"
+		__gitcomp "remote merge mergeoptions rebase" "$pfx" "$cur"
 		return
 		;;
 	branch.*)
@@ -1504,7 +1505,7 @@
 		cur="${cur##*.}"
 		__gitcomp "
 			url proxy fetch push mirror skipDefaultUpdate
-			receivepack uploadpack tagopt
+			receivepack uploadpack tagopt pushurl
 			" "$pfx" "$cur"
 		return
 		;;
@@ -1522,6 +1523,7 @@
 		;;
 	esac
 	__gitcomp "
+		add.ignore-errors
 		alias.
 		apply.whitespace
 		branch.autosetupmerge
diff --git a/csum-file.c b/csum-file.c
index 2ddb12a..4d50cc5 100644
--- a/csum-file.c
+++ b/csum-file.c
@@ -26,7 +26,7 @@
 		}
 		if (!ret)
 			die("sha1 file '%s' write error. Out of diskspace", f->name);
-		die("sha1 file '%s' write error (%s)", f->name, strerror(errno));
+		die_errno("sha1 file '%s' write error", f->name);
 	}
 }
 
@@ -55,8 +55,7 @@
 		if (flags & CSUM_FSYNC)
 			fsync_or_die(f->fd, f->name);
 		if (close(f->fd))
-			die("%s: sha1 file error on close (%s)",
-			    f->name, strerror(errno));
+			die_errno("%s: sha1 file error on close", f->name);
 		fd = 0;
 	} else
 		fd = f->fd;
diff --git a/daemon.c b/daemon.c
index 366db37..1b5ada6 100644
--- a/daemon.c
+++ b/daemon.c
@@ -1,6 +1,8 @@
 #include "cache.h"
 #include "pkt-line.h"
 #include "exec_cmd.h"
+#include "run-command.h"
+#include "strbuf.h"
 
 #include <syslog.h>
 
@@ -343,28 +345,66 @@
 	return service->fn();
 }
 
+static void copy_to_log(int fd)
+{
+	struct strbuf line = STRBUF_INIT;
+	FILE *fp;
+
+	fp = fdopen(fd, "r");
+	if (fp == NULL) {
+		logerror("fdopen of error channel failed");
+		close(fd);
+		return;
+	}
+
+	while (strbuf_getline(&line, fp, '\n') != EOF) {
+		logerror("%s", line.buf);
+		strbuf_setlen(&line, 0);
+	}
+
+	strbuf_release(&line);
+	fclose(fp);
+}
+
+static int run_service_command(const char **argv)
+{
+	struct child_process cld;
+
+	memset(&cld, 0, sizeof(cld));
+	cld.argv = argv;
+	cld.git_cmd = 1;
+	cld.err = -1;
+	if (start_command(&cld))
+		return -1;
+
+	close(0);
+	close(1);
+
+	copy_to_log(cld.err);
+
+	return finish_command(&cld);
+}
+
 static int upload_pack(void)
 {
 	/* Timeout as string */
 	char timeout_buf[64];
+	const char *argv[] = { "upload-pack", "--strict", timeout_buf, ".", NULL };
 
 	snprintf(timeout_buf, sizeof timeout_buf, "--timeout=%u", timeout);
-
-	/* git-upload-pack only ever reads stuff, so this is safe */
-	execl_git_cmd("upload-pack", "--strict", timeout_buf, ".", NULL);
-	return -1;
+	return run_service_command(argv);
 }
 
 static int upload_archive(void)
 {
-	execl_git_cmd("upload-archive", ".", NULL);
-	return -1;
+	static const char *argv[] = { "upload-archive", ".", NULL };
+	return run_service_command(argv);
 }
 
 static int receive_pack(void)
 {
-	execl_git_cmd("receive-pack", ".", NULL);
-	return -1;
+	static const char *argv[] = { "receive-pack", ".", NULL };
+	return run_service_command(argv);
 }
 
 static struct daemon_service daemon_service[] = {
@@ -862,7 +902,7 @@
 					case ECONNABORTED:
 						continue;
 					default:
-						die("accept returned %s", strerror(errno));
+						die_errno("accept returned");
 					}
 				}
 				handle(incoming, (struct sockaddr *)&ss, sslen);
@@ -878,7 +918,7 @@
 	while (fd != -1 && fd < 2)
 		fd = dup(fd);
 	if (fd == -1)
-		die("open /dev/null or dup failed: %s", strerror(errno));
+		die_errno("open /dev/null or dup failed");
 	if (fd > 2)
 		close(fd);
 }
@@ -889,12 +929,12 @@
 		case 0:
 			break;
 		case -1:
-			die("fork failed: %s", strerror(errno));
+			die_errno("fork failed");
 		default:
 			exit(0);
 	}
 	if (setsid() == -1)
-		die("setsid failed: %s", strerror(errno));
+		die_errno("setsid failed");
 	close(0);
 	close(1);
 	close(2);
@@ -905,9 +945,9 @@
 {
 	FILE *f = fopen(path, "w");
 	if (!f)
-		die("cannot open pid file %s: %s", path, strerror(errno));
+		die_errno("cannot open pid file '%s'", path);
 	if (fprintf(f, "%"PRIuMAX"\n", (uintmax_t) getpid()) < 0 || fclose(f) != 0)
-		die("failed to write pid file %s: %s", path, strerror(errno));
+		die_errno("failed to write pid file '%s'", path);
 }
 
 static int serve(char *listen_addr, int listen_port, struct passwd *pass, gid_t gid)
@@ -1107,8 +1147,7 @@
 		socklen_t slen = sizeof(ss);
 
 		if (!freopen("/dev/null", "w", stderr))
-			die("failed to redirect stderr to /dev/null: %s",
-			    strerror(errno));
+			die_errno("failed to redirect stderr to /dev/null");
 
 		if (getpeername(0, peer, &slen))
 			peer = NULL;
diff --git a/diff.c b/diff.c
index 43835d7..cd35e0c 100644
--- a/diff.c
+++ b/diff.c
@@ -1603,6 +1603,7 @@
 			free(mf1.ptr);
 		if (textconv_two)
 			free(mf2.ptr);
+		xdiff_clear_find_func(&xecfg);
 	}
 
  free_ab_and_return:
@@ -1975,14 +1976,14 @@
 	fd = git_mkstemps(temp->tmp_path, PATH_MAX, template.buf,
 			strlen(base) + 1);
 	if (fd < 0)
-		die("unable to create temp-file: %s", strerror(errno));
+		die_errno("unable to create temp-file");
 	if (convert_to_working_tree(path,
 			(const char *)blob, (size_t)size, &buf)) {
 		blob = buf.buf;
 		size = buf.len;
 	}
 	if (write_in_full(fd, blob, size) != size)
-		die("unable to write temp-file");
+		die_errno("unable to write temp-file");
 	close(fd);
 	temp->name = temp->tmp_path;
 	strcpy(temp->hex, sha1_to_hex(sha1));
@@ -2021,12 +2022,12 @@
 		if (lstat(name, &st) < 0) {
 			if (errno == ENOENT)
 				goto not_a_valid_file;
-			die("stat(%s): %s", name, strerror(errno));
+			die_errno("stat(%s)", name);
 		}
 		if (S_ISLNK(st.st_mode)) {
 			struct strbuf sb = STRBUF_INIT;
 			if (strbuf_readlink(&sb, name, st.st_size) < 0)
-				die("readlink(%s)", name);
+				die_errno("readlink(%s)", name);
 			prep_temp_blob(name, temp, sb.buf, sb.len,
 				       (one->sha1_valid ?
 					one->sha1 : null_sha1),
@@ -2219,7 +2220,7 @@
 				return;
 			}
 			if (lstat(one->path, &st) < 0)
-				die("stat %s", one->path);
+				die_errno("stat '%s'", one->path);
 			if (index_path(one->sha1, one->path, &st, 0))
 				die("cannot hash %s", one->path);
 		}
diff --git a/dir.c b/dir.c
index bbfcb56..74b3bbf 100644
--- a/dir.c
+++ b/dir.c
@@ -759,7 +759,7 @@
 	if (!dir)
 		return NULL;
 	if (!getcwd(buffer, size))
-		die("can't find the current directory: %s", strerror(errno));
+		die_errno("can't find the current directory");
 
 	if (!is_absolute_path(dir))
 		dir = make_absolute_path(dir);
diff --git a/entry.c b/entry.c
index cc841ed..d3e86c7 100644
--- a/entry.c
+++ b/entry.c
@@ -37,7 +37,7 @@
 			if (errno == EEXIST && state->force &&
 			    !unlink_or_warn(buf) && !mkdir(buf, 0777))
 				continue;
-			die("cannot create directory at %s", buf);
+			die_errno("cannot create directory at '%s'", buf);
 		}
 	}
 	free(buf);
@@ -51,7 +51,7 @@
 	char *name;
 
 	if (!dir)
-		die("cannot opendir %s (%s)", path, strerror(errno));
+		die_errno("cannot opendir '%s'", path);
 	strcpy(pathbuf, path);
 	name = pathbuf + strlen(path);
 	*name++ = '/';
@@ -61,15 +61,15 @@
 			continue;
 		strcpy(name, de->d_name);
 		if (lstat(pathbuf, &st))
-			die("cannot lstat %s (%s)", pathbuf, strerror(errno));
+			die_errno("cannot lstat '%s'", pathbuf);
 		if (S_ISDIR(st.st_mode))
 			remove_subtree(pathbuf);
 		else if (unlink(pathbuf))
-			die("cannot unlink %s (%s)", pathbuf, strerror(errno));
+			die_errno("cannot unlink '%s'", pathbuf);
 	}
 	closedir(dir);
 	if (rmdir(path))
-		die("cannot rmdir %s (%s)", path, strerror(errno));
+		die_errno("cannot rmdir '%s'", path);
 }
 
 static int create_file(const char *path, unsigned int mode)
diff --git a/fast-import.c b/fast-import.c
index a2a2458..7ef9865 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -905,10 +905,10 @@
 
 	keep_fd = odb_pack_keep(name, sizeof(name), pack_data->sha1);
 	if (keep_fd < 0)
-		die("cannot create keep file");
+		die_errno("cannot create keep file");
 	write_or_die(keep_fd, keep_msg, strlen(keep_msg));
 	if (close(keep_fd))
-		die("failed to write keep file");
+		die_errno("failed to write keep file");
 
 	snprintf(name, sizeof(name), "%s/pack/pack-%s.pack",
 		 get_object_directory(), sha1_to_hex(pack_data->sha1));
@@ -2342,7 +2342,7 @@
 	char line[512];
 	FILE *f = fopen(input_file, "r");
 	if (!f)
-		die("cannot read %s: %s", input_file, strerror(errno));
+		die_errno("cannot read '%s'", input_file);
 	while (fgets(line, sizeof(line), f)) {
 		uintmax_t mark;
 		char *end;
@@ -2448,7 +2448,7 @@
 				fclose(pack_edges);
 			pack_edges = fopen(a + 20, "a");
 			if (!pack_edges)
-				die("Cannot open %s: %s", a + 20, strerror(errno));
+				die_errno("Cannot open '%s'", a + 20);
 		} else if (!strcmp(a, "--force"))
 			force_update = 1;
 		else if (!strcmp(a, "--quiet"))
diff --git a/fsck.c b/fsck.c
index 511b82c..89278c1 100644
--- a/fsck.c
+++ b/fsck.c
@@ -229,7 +229,7 @@
 	struct commit_graft *graft;
 	int parents = 0;
 
-	if (!commit->date)
+	if (commit->date == ULONG_MAX)
 		return error_func(&commit->object, FSCK_ERROR, "invalid author/committer line");
 
 	if (memcmp(buffer, "tree ", 5))
diff --git a/git-am.sh b/git-am.sh
index 578780b..d64d997 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -11,6 +11,7 @@
 i,interactive   run interactively
 b,binary*       (historical option -- no-op)
 3,3way          allow fall back on 3way merging if needed
+q,quiet         be quiet
 s,signoff       add a Signed-off-by line to the commit message
 u,utf8          recode into utf8 (default)
 k,keep          pass -k flag to git-mailinfo
@@ -18,6 +19,7 @@
 directory=      pass it through git-apply
 C=              pass it through git-apply
 p=              pass it through git-apply
+patch-format=   format the patch(es) are in
 reject          pass it through git-apply
 resolvemsg=     override error message when patch failure occurs
 r,resolved      to be used after a patch failure
@@ -99,7 +101,7 @@
     git write-tree >"$dotest/patch-merge-base+" ||
     cannot_fallback "Repository lacks necessary blobs to fall back on 3-way merge."
 
-    echo Using index info to reconstruct a base tree...
+    say Using index info to reconstruct a base tree...
     if GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \
 	git apply --cached <"$dotest/patch"
     then
@@ -115,7 +117,7 @@
     orig_tree=$(cat "$dotest/patch-merge-base") &&
     rm -fr "$dotest"/patch-merge-* || exit 1
 
-    echo Falling back to patching base and 3-way merge...
+    say Falling back to patching base and 3-way merge...
 
     # This is not so wrong.  Depending on which base we picked,
     # orig_tree may be wildly different from ours, but his_tree
@@ -125,6 +127,10 @@
 
     eval GITHEAD_$his_tree='"$FIRSTLINE"'
     export GITHEAD_$his_tree
+    if test -n "$GIT_QUIET"
+    then
+	    export GIT_MERGE_VERBOSITY=0
+    fi
     git-merge-recursive $orig_tree -- HEAD $his_tree || {
 	    git rerere
 	    echo Failed to merge in the changes.
@@ -133,6 +139,126 @@
     unset GITHEAD_$his_tree
 }
 
+clean_abort () {
+	test $# = 0 || echo >&2 "$@"
+	rm -fr "$dotest"
+	exit 1
+}
+
+patch_format=
+
+check_patch_format () {
+	# early return if patch_format was set from the command line
+	if test -n "$patch_format"
+	then
+		return 0
+	fi
+
+	# we default to mbox format if input is from stdin and for
+	# directories
+	if test $# = 0 || test "x$1" = "x-" || test -d "$1"
+	then
+		patch_format=mbox
+		return 0
+	fi
+
+	# otherwise, check the first few lines of the first patch to try
+	# to detect its format
+	{
+		read l1
+		read l2
+		read l3
+		case "$l1" in
+		"From "* | "From: "*)
+			patch_format=mbox
+			;;
+		'# This series applies on GIT commit'*)
+			patch_format=stgit-series
+			;;
+		"# HG changeset patch")
+			patch_format=hg
+			;;
+		*)
+			# if the second line is empty and the third is
+			# a From, Author or Date entry, this is very
+			# likely an StGIT patch
+			case "$l2,$l3" in
+			,"From: "* | ,"Author: "* | ,"Date: "*)
+				patch_format=stgit
+				;;
+			*)
+				;;
+			esac
+			;;
+		esac
+	} < "$1" || clean_abort
+}
+
+split_patches () {
+	case "$patch_format" in
+	mbox)
+		git mailsplit -d"$prec" -o"$dotest" -b -- "$@" > "$dotest/last" ||
+		clean_abort
+		;;
+	stgit-series)
+		if test $# -ne 1
+		then
+			clean_abort "Only one StGIT patch series can be applied at once"
+		fi
+		series_dir=`dirname "$1"`
+		series_file="$1"
+		shift
+		{
+			set x
+			while read filename
+			do
+				set "$@" "$series_dir/$filename"
+			done
+			# remove the safety x
+			shift
+			# remove the arg coming from the first-line comment
+			shift
+		} < "$series_file" || clean_abort
+		# set the patch format appropriately
+		patch_format=stgit
+		# now handle the actual StGIT patches
+		split_patches "$@"
+		;;
+	stgit)
+		this=0
+		for stgit in "$@"
+		do
+			this=`expr "$this" + 1`
+			msgnum=`printf "%0${prec}d" $this`
+			# Perl version of StGIT parse_patch. The first nonemptyline
+			# not starting with Author, From or Date is the
+			# subject, and the body starts with the next nonempty
+			# line not starting with Author, From or Date
+			perl -ne 'BEGIN { $subject = 0 }
+				if ($subject > 1) { print ; }
+				elsif (/^\s+$/) { next ; }
+				elsif (/^Author:/) { print s/Author/From/ ; }
+				elsif (/^(From|Date)/) { print ; }
+				elsif ($subject) {
+					$subject = 2 ;
+					print "\n" ;
+					print ;
+				} else {
+					print "Subject: ", $_ ;
+					$subject = 1;
+				}
+			' < "$stgit" > "$dotest/$msgnum" || clean_abort
+		done
+		echo "$this" > "$dotest/last"
+		this=
+		msgnum=
+		;;
+	*)
+		clean_abort "Patch format $patch_format is not supported."
+		;;
+	esac
+}
+
 prec=4
 dotest="$GIT_DIR/rebase-apply"
 sign= utf8=t keep= skip= interactive= resolved= rebasing= abort=
@@ -175,12 +301,16 @@
 		git_apply_opt="$git_apply_opt $(sq "$1=$2")"; shift ;;
 	-C|-p)
 		git_apply_opt="$git_apply_opt $(sq "$1$2")"; shift ;;
+	--patch-format)
+		shift ; patch_format="$1" ;;
 	--reject)
 		git_apply_opt="$git_apply_opt $1" ;;
 	--committer-date-is-author-date)
 		committer_date_is_author_date=t ;;
 	--ignore-date)
 		ignore_date=t ;;
+	-q|--quiet)
+		GIT_QUIET=t ;;
 	--)
 		shift; break ;;
 	*)
@@ -274,12 +404,12 @@
 		done
 		shift
 	fi
-	git mailsplit -d"$prec" -o"$dotest" -b -- "$@" > "$dotest/last" ||  {
-		rm -fr "$dotest"
-		exit 1
-	}
 
-	# -s, -u, -k, --whitespace, -3, -C and -p flags are kept
+	check_patch_format "$@"
+
+	split_patches "$@"
+
+	# -s, -u, -k, --whitespace, -3, -C, -q and -p flags are kept
 	# for the resuming session after a patch failure.
 	# -i can and must be given when resuming.
 	echo " $git_apply_opt" >"$dotest/apply-opt"
@@ -287,6 +417,7 @@
 	echo "$sign" >"$dotest/sign"
 	echo "$utf8" >"$dotest/utf8"
 	echo "$keep" >"$dotest/keep"
+	echo "$GIT_QUIET" >"$dotest/quiet"
 	echo 1 >"$dotest/next"
 	if test -n "$rebasing"
 	then
@@ -327,6 +458,10 @@
 then
 	keep=-k
 fi
+if test "$(cat "$dotest/quiet")" = t
+then
+	GIT_QUIET=t
+fi
 if test "$(cat "$dotest/threeway")" = t
 then
 	threeway=t
@@ -352,7 +487,7 @@
 
 if test "$this" -gt "$last"
 then
-	echo Nothing to do.
+	say Nothing to do.
 	rm -fr "$dotest"
 	exit
 fi
@@ -498,11 +633,18 @@
 		stop_here $this
 	fi
 
-	printf 'Applying: %s\n' "$FIRSTLINE"
+	say "Applying: $FIRSTLINE"
 
 	case "$resolved" in
 	'')
-		eval 'git apply '"$git_apply_opt"' --index "$dotest/patch"'
+		# When we are allowed to fall back to 3-way later, don't give
+		# false errors during the initial attempt.
+		squelch=
+		if test "$threeway" = t
+		then
+			squelch='>/dev/null 2>&1 '
+		fi
+		eval "git apply $squelch$git_apply_opt"' --index "$dotest/patch"'
 		apply_status=$?
 		;;
 	t)
@@ -534,7 +676,7 @@
 		    # Applying the patch to an earlier tree and merging the
 		    # result may have produced the same tree as ours.
 		    git diff-index --quiet --cached HEAD -- && {
-			echo No changes -- Patch already applied.
+			say No changes -- Patch already applied.
 			go_next
 			continue
 		    }
@@ -560,7 +702,7 @@
 			GIT_AUTHOR_DATE=
 		fi
 		parent=$(git rev-parse --verify -q HEAD) ||
-		echo >&2 "applying to an empty history"
+		say >&2 "applying to an empty history"
 
 		if test -n "$committer_date_is_author_date"
 		then
diff --git a/git-compat-util.h b/git-compat-util.h
index 919b7f1..9609eaa 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -175,6 +175,7 @@
 /* General helper functions */
 extern void usage(const char *err) NORETURN;
 extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
+extern void die_errno(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
 extern int error(const char *err, ...) __attribute__((format (printf, 1, 2)));
 extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2)));
 
diff --git a/git-cvsexportcommit.perl b/git-cvsexportcommit.perl
index a36df33..59b6722 100755
--- a/git-cvsexportcommit.perl
+++ b/git-cvsexportcommit.perl
@@ -259,7 +259,8 @@
 	    if $file =~ /^no file /
 		&& $status eq 'Up-to-date';
 
-	$cvsstat{$fullname{$file}} = $status;
+	$cvsstat{$fullname{$file}} = $status
+	    if defined $fullname{$file};
       }
     }
 }
@@ -299,7 +300,7 @@
 	while (<FILTER_IN>)
 	{
 	    my $line = $_;
-	    $line =~ s/\$([A-Z][a-z]+):[^\$]+\$/\$\1\$/g;
+	    $line =~ s/\$([A-Z][a-z]+):[^\$]+\$/\$$1\$/g;
 	    print FILTER_OUT $line;
 	}
 	close FILTER_IN;
diff --git a/git-rebase.sh b/git-rebase.sh
index 334629f..18bc694 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -3,7 +3,7 @@
 # Copyright (c) 2005 Junio C Hamano.
 #
 
-USAGE='[--interactive | -i] [-v] [--force-rebase | -f] [--onto <newbase>] [<upstream>|--root] [<branch>]'
+USAGE='[--interactive | -i] [-v] [--force-rebase | -f] [--onto <newbase>] [<upstream>|--root] [<branch>] [--quiet | -q]'
 LONG_USAGE='git-rebase replaces <branch> with a new branch of the
 same name.  When the --onto option is provided the new branch starts
 out with a HEAD equal to <newbase>, otherwise it is equal to <upstream>
@@ -72,11 +72,20 @@
 			echo "directly, but instead do one of the following: "
 			die "$RESOLVEMSG"
 		fi
-		printf "Committed: %0${prec}d " $msgnum
+		if test -z "$GIT_QUIET"
+		then
+			printf "Committed: %0${prec}d " $msgnum
+		fi
 	else
-		printf "Already applied: %0${prec}d " $msgnum
+		if test -z "$GIT_QUIET"
+		then
+			printf "Already applied: %0${prec}d " $msgnum
+		fi
 	fi
-	git rev-list --pretty=oneline -1 "$cmt" | sed -e 's/^[^ ]* //'
+	if test -z "$GIT_QUIET"
+	then
+		git rev-list --pretty=oneline -1 "$cmt" | sed -e 's/^[^ ]* //'
+	fi
 
 	prev_head=`git rev-parse HEAD^0`
 	# save the resulting commit so we can read-tree on it later
@@ -97,6 +106,10 @@
 	eval GITHEAD_$cmt='"${cmt_name##refs/heads/}~$(($end - $msgnum))"'
 	eval GITHEAD_$hd='$(cat "$dotest/onto_name")'
 	export GITHEAD_$cmt GITHEAD_$hd
+	if test -n "$GIT_QUIET"
+	then
+		export GIT_MERGE_VERBOSITY=1
+	fi
 	git-merge-$strategy "$cmt^" -- "$hd" "$cmt"
 	rv=$?
 	case "$rv" in
@@ -138,7 +151,7 @@
 finish_rb_merge () {
 	move_to_original_branch
 	rm -r "$dotest"
-	echo "All done."
+	say All done.
 }
 
 is_interactive () {
@@ -207,6 +220,7 @@
 			end=$(cat "$dotest/end")
 			msgnum=$(cat "$dotest/msgnum")
 			onto=$(cat "$dotest/onto")
+			GIT_QUIET=$(cat "$dotest/quiet")
 			continue_merge
 			while test "$msgnum" -le "$end"
 			do
@@ -219,6 +233,7 @@
 		head_name=$(cat "$GIT_DIR"/rebase-apply/head-name) &&
 		onto=$(cat "$GIT_DIR"/rebase-apply/onto) &&
 		orig_head=$(cat "$GIT_DIR"/rebase-apply/orig-head) &&
+		GIT_QUIET=$(cat "$GIT_DIR"/rebase-apply/quiet)
 		git am --resolved --3way --resolvemsg="$RESOLVEMSG" &&
 		move_to_original_branch
 		exit
@@ -236,6 +251,7 @@
 			msgnum=$(cat "$dotest/msgnum")
 			msgnum=$(($msgnum + 1))
 			onto=$(cat "$dotest/onto")
+			GIT_QUIET=$(cat "$dotest/quiet")
 			while test "$msgnum" -le "$end"
 			do
 				call_merge "$msgnum"
@@ -247,6 +263,7 @@
 		head_name=$(cat "$GIT_DIR"/rebase-apply/head-name) &&
 		onto=$(cat "$GIT_DIR"/rebase-apply/onto) &&
 		orig_head=$(cat "$GIT_DIR"/rebase-apply/orig-head) &&
+		GIT_QUIET=$(cat "$GIT_DIR"/rebase-apply/quiet)
 		git am -3 --skip --resolvemsg="$RESOLVEMSG" &&
 		move_to_original_branch
 		exit
@@ -258,9 +275,11 @@
 		git rerere clear
 		if test -d "$dotest"
 		then
+			GIT_QUIET=$(cat "$dotest/quiet")
 			move_to_original_branch
 		else
 			dotest="$GIT_DIR"/rebase-apply
+			GIT_QUIET=$(cat "$dotest/quiet")
 			move_to_original_branch
 		fi
 		git reset --hard $(cat "$dotest/orig-head")
@@ -298,6 +317,13 @@
 	-v|--verbose)
 		verbose=t
 		diffstat=t
+		GIT_QUIET=
+		;;
+	-q|--quiet)
+		GIT_QUIET=t
+		git_am_opt="$git_am_opt -q"
+		verbose=
+		diffstat=
 		;;
 	--whitespace=*)
 		git_am_opt="$git_am_opt $1"
@@ -442,15 +468,15 @@
 	then
 		# Lazily switch to the target branch if needed...
 		test -z "$switch_to" || git checkout "$switch_to"
-		echo >&2 "Current branch $branch_name is up to date."
+		say "Current branch $branch_name is up to date."
 		exit 0
 	else
-		echo "Current branch $branch_name is up to date, rebase forced."
+		say "Current branch $branch_name is up to date, rebase forced."
 	fi
 fi
 
 # Detach HEAD and reset the tree
-echo "First, rewinding head to replay your work on top of it..."
+say "First, rewinding head to replay your work on top of it..."
 git checkout -q "$onto^0" || die "could not detach HEAD"
 git update-ref ORIG_HEAD $branch
 
@@ -468,7 +494,7 @@
 # we just fast forwarded.
 if test "$mb" = "$branch"
 then
-	echo >&2 "Fast-forwarded $branch_name to $onto_name."
+	say "Fast-forwarded $branch_name to $onto_name."
 	move_to_original_branch
 	exit 0
 fi
@@ -490,7 +516,8 @@
 	test 0 != $ret -a -d "$GIT_DIR"/rebase-apply &&
 		echo $head_name > "$GIT_DIR"/rebase-apply/head-name &&
 		echo $onto > "$GIT_DIR"/rebase-apply/onto &&
-		echo $orig_head > "$GIT_DIR"/rebase-apply/orig-head
+		echo $orig_head > "$GIT_DIR"/rebase-apply/orig-head &&
+		echo "$GIT_QUIET" > "$GIT_DIR"/rebase-apply/quiet
 	exit $ret
 fi
 
@@ -504,6 +531,7 @@
 echo "$prev_head" > "$dotest/prev_head"
 echo "$orig_head" > "$dotest/orig-head"
 echo "$head_name" > "$dotest/head-name"
+echo "$GIT_QUIET" > "$dotest/quiet"
 
 msgnum=0
 for cmt in `git rev-list --reverse --no-merges "$revisions"`
diff --git a/git-repack.sh b/git-repack.sh
index 0868734..1bf2394 100755
--- a/git-repack.sh
+++ b/git-repack.sh
@@ -24,7 +24,7 @@
 . git-sh-setup
 
 no_update_info= all_into_one= remove_redundant= unpack_unreachable=
-local= quiet= no_reuse= extra=
+local= no_reuse= extra=
 while test $# != 0
 do
 	case "$1" in
@@ -33,7 +33,7 @@
 	-A)	all_into_one=t
 		unpack_unreachable=--unpack-unreachable ;;
 	-d)	remove_redundant=t ;;
-	-q)	quiet=-q ;;
+	-q)	GIT_QUIET=t ;;
 	-f)	no_reuse=--no-reuse-object ;;
 	-l)	local=--local ;;
 	--max-pack-size|--window|--window-memory|--depth)
@@ -80,13 +80,11 @@
 	;;
 esac
 
-args="$args $local $quiet $no_reuse$extra"
+args="$args $local ${GIT_QUIET:+-q} $no_reuse$extra"
 names=$(git pack-objects --honor-pack-keep --non-empty --all --reflog $args </dev/null "$PACKTMP") ||
 	exit 1
 if [ -z "$names" ]; then
-	if test -z "$quiet"; then
-		echo Nothing new to pack.
-	fi
+	say Nothing new to pack.
 fi
 
 # Ok we have prepared all new packfiles.
@@ -176,7 +174,7 @@
 		  done
 		)
 	fi
-	git prune-packed $quiet
+	git prune-packed ${GIT_QUIET:+-q}
 fi
 
 case "$no_update_info" in
diff --git a/git-request-pull.sh b/git-request-pull.sh
index a2cf5b8..5917773 100755
--- a/git-request-pull.sh
+++ b/git-request-pull.sh
@@ -12,6 +12,9 @@
 . git-sh-setup
 . git-parse-remote
 
+GIT_PAGER=
+export GIT_PAGER
+
 base=$1
 url=$2
 head=${3-HEAD}
@@ -34,7 +37,7 @@
 	}")
 if [ -z "$branch" ]; then
 	echo "warn: No branch of $url is at:" >&2
-	git log --max-count=1 --pretty='format:warn:   %h: %s' $headrev >&2
+	git log --max-count=1 --pretty='tformat:warn:   %h: %s' $headrev >&2
 	echo "warn: Are you sure you pushed $head there?" >&2
 	echo >&2
 	echo >&2
@@ -42,8 +45,6 @@
 	status=1
 fi
 
-PAGER=
-export PAGER
 echo "The following changes since commit $baserev:"
 git shortlog --max-count=1 $baserev | sed -e 's/^\(.\)/  \1/'
 
diff --git a/git-sh-setup.sh b/git-sh-setup.sh
index 80acb7d..c41c2f7 100755
--- a/git-sh-setup.sh
+++ b/git-sh-setup.sh
@@ -44,6 +44,15 @@
 	exit 1
 }
 
+GIT_QUIET=
+
+say () {
+	if test -z "$GIT_QUIET"
+	then
+		printf '%s\n' "$*"
+	fi
+}
+
 if test -n "$OPTIONS_SPEC"; then
 	usage() {
 		"$0" -h
diff --git a/git-stash.sh b/git-stash.sh
index e6a5867..531c7c3 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -3,10 +3,11 @@
 
 dashless=$(basename "$0" | sed -e 's/-/ /')
 USAGE="list [<options>]
-   or: $dashless ( show | drop ) [<stash>]
-   or: $dashless ( pop | apply ) [--index] [<stash>]
+   or: $dashless show [<stash>]
+   or: $dashless drop [-q|--quiet] [<stash>]
+   or: $dashless ( pop | apply ) [--index] [-q|--quiet] [<stash>]
    or: $dashless branch <branchname> [<stash>]
-   or: $dashless [save [--keep-index] [<message>]]
+   or: $dashless [save [--keep-index] [-q|--quiet] [<message>]]
    or: $dashless clear"
 
 SUBDIRECTORY_OK=Yes
@@ -94,18 +95,28 @@
 
 save_stash () {
 	keep_index=
-	case "$1" in
-	--keep-index)
-		keep_index=t
+	while test $# != 0
+	do
+		case "$1" in
+		--keep-index)
+			keep_index=t
+			;;
+		-q|--quiet)
+			GIT_QUIET=t
+			;;
+		*)
+			break
+			;;
+		esac
 		shift
-	esac
+	done
 
 	stash_msg="$*"
 
 	git update-index -q --refresh
 	if no_changes
 	then
-		echo 'No local changes to save'
+		say 'No local changes to save'
 		exit 0
 	fi
 	test -f "$GIT_DIR/logs/$ref_stash" ||
@@ -118,9 +129,9 @@
 
 	git update-ref -m "$stash_msg" $ref_stash $w_commit ||
 		die "Cannot save the current status"
-	printf 'Saved working directory and index state "%s"\n' "$stash_msg"
+	say Saved working directory and index state "$stash_msg"
 
-	git reset --hard
+	git reset --hard ${GIT_QUIET:+-q}
 
 	if test -n "$keep_index" && test -n $i_tree
 	then
@@ -156,11 +167,22 @@
 		die 'Cannot apply to a dirty working tree, please stage your changes'
 
 	unstash_index=
-	case "$1" in
-	--index)
-		unstash_index=t
+
+	while test $# != 0
+	do
+		case "$1" in
+		--index)
+			unstash_index=t
+			;;
+		-q|--quiet)
+			GIT_QUIET=t
+			;;
+		*)
+			break
+			;;
+		esac
 		shift
-	esac
+	done
 
 	# current index state
 	c_tree=$(git write-tree) ||
@@ -193,6 +215,10 @@
 		export GITHEAD_$w_tree GITHEAD_$c_tree GITHEAD_$b_tree
 	"
 
+	if test -n "$GIT_QUIET"
+	then
+		export GIT_MERGE_VERBOSITY=0
+	fi
 	if git-merge-recursive $b_tree -- $c_tree $w_tree
 	then
 		# No conflict
@@ -207,7 +233,12 @@
 				die "Cannot unstage modified files"
 			rm -f "$a"
 		fi
-		git status || :
+		squelch=
+		if test -n "$GIT_QUIET"
+		then
+			squelch='>/dev/null 2>&1'
+		fi
+		eval "git status $squelch" || :
 	else
 		# Merge conflict; keep the exit status from merge-recursive
 		status=$?
@@ -222,6 +253,19 @@
 drop_stash () {
 	have_stash || die 'No stash entries to drop'
 
+	while test $# != 0
+	do
+		case "$1" in
+		-q|--quiet)
+			GIT_QUIET=t
+			;;
+		*)
+			break
+			;;
+		esac
+		shift
+	done
+
 	if test $# = 0
 	then
 		set x "$ref_stash@{0}"
@@ -235,7 +279,7 @@
 		die "$*: not a valid stashed state"
 
 	git reflog delete --updateref --rewrite "$@" &&
-		echo "Dropped $* ($s)" || die "$*: Could not drop stash entry"
+		say "Dropped $* ($s)" || die "$*: Could not drop stash entry"
 
 	# clear_stash if we just dropped the last stash entry
 	git rev-parse --verify "$ref_stash@{0}" > /dev/null 2>&1 || clear_stash
@@ -312,7 +356,7 @@
 	if test $# -eq 0
 	then
 		save_stash &&
-		echo '(To restore them type "git stash apply")'
+		say '(To restore them type "git stash apply")'
 	else
 		usage
 	fi
diff --git a/git-submodule.sh b/git-submodule.sh
index f4f3562..ebed711 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -14,23 +14,11 @@
 
 command=
 branch=
-quiet=
 reference=
 cached=
 nofetch=
 update=
 
-#
-# print stuff on stdout unless -q was specified
-#
-say()
-{
-	if test -z "$quiet"
-	then
-		echo "$@"
-	fi
-}
-
 # Resolve relative url by appending to parent's url
 resolve_relative_url ()
 {
@@ -137,7 +125,7 @@
 			shift
 			;;
 		-q|--quiet)
-			quiet=1
+			GIT_QUIET=1
 			;;
 		--reference)
 			case "$2" in '') usage ;; esac
@@ -273,7 +261,7 @@
 	do
 		case "$1" in
 		-q|--quiet)
-			quiet=1
+			GIT_QUIET=1
 			;;
 		--)
 			shift
@@ -333,7 +321,7 @@
 		case "$1" in
 		-q|--quiet)
 			shift
-			quiet=1
+			GIT_QUIET=1
 			;;
 		-i|--init)
 			init=1
@@ -659,7 +647,7 @@
 	do
 		case "$1" in
 		-q|--quiet)
-			quiet=1
+			GIT_QUIET=1
 			;;
 		--cached)
 			cached=1
@@ -713,7 +701,7 @@
 	do
 		case "$1" in
 		-q|--quiet)
-			quiet=1
+			GIT_QUIET=1
 			shift
 			;;
 		--)
@@ -768,7 +756,7 @@
 		command=$1
 		;;
 	-q|--quiet)
-		quiet=1
+		GIT_QUIET=1
 		;;
 	-b|--branch)
 		case "$2" in
diff --git a/git.c b/git.c
index 7d7f949..807d875 100644
--- a/git.c
+++ b/git.c
@@ -188,10 +188,9 @@
 				  alias_command);
 
 		new_argv = xrealloc(new_argv, sizeof(char *) *
-				    (count + *argcp + 1));
+				    (count + *argcp));
 		/* insert after command name */
 		memcpy(new_argv + count, *argv + 1, sizeof(char *) * *argcp);
-		new_argv[count+*argcp] = NULL;
 
 		*argv = new_argv;
 		*argcp += count - 1;
@@ -200,7 +199,7 @@
 	}
 
 	if (subdir && chdir(subdir))
-		die("Cannot change to %s: %s", subdir, strerror(errno));
+		die_errno("Cannot change to '%s'", subdir);
 
 	errno = saved_errno;
 
@@ -246,7 +245,7 @@
 
 	status = p->fn(argc, argv, prefix);
 	if (status)
-		return status & 0xff;
+		return status;
 
 	/* Somebody closed stdout? */
 	if (fstat(fileno(stdout), &st))
@@ -257,11 +256,11 @@
 
 	/* Check for ENOSPC and EIO errors.. */
 	if (fflush(stdout))
-		die("write failure on standard output: %s", strerror(errno));
+		die_errno("write failure on standard output");
 	if (ferror(stdout))
 		die("unknown write failure on standard output");
 	if (fclose(stdout))
-		die("close failed on standard output: %s", strerror(errno));
+		die_errno("close failed on standard output");
 	return 0;
 }
 
diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css
index a01eac8..d05bc37 100644
--- a/gitweb/gitweb.css
+++ b/gitweb/gitweb.css
@@ -28,6 +28,10 @@
 	border-width: 0px;
 }
 
+img.avatar {
+	vertical-align: middle;
+}
+
 div.page_header {
 	height: 25px;
 	padding: 8px;
@@ -132,11 +136,14 @@
 	font-style: italic;
 }
 
+.author_date, .author {
+	font-style: italic;
+}
+
 div.author_date {
 	padding: 8px;
 	border: solid #d9d8d1;
 	border-width: 0px 0px 1px 0px;
-	font-style: italic;
 }
 
 a.list {
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 1e7e2d8..6a1b5b5 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -195,6 +195,14 @@
 	'x-zip' => undef, '' => undef,
 );
 
+# Pixel sizes for icons and avatars. If the default font sizes or lineheights
+# are changed, it may be appropriate to change these values too via
+# $GITWEB_CONFIG.
+our %avatar_size = (
+	'default' => 16,
+	'double'  => 32
+);
+
 # You define site-wide feature defaults here; override them with
 # $GITWEB_CONFIG as necessary.
 our %feature = (
@@ -365,6 +373,27 @@
 		'sub' => \&feature_patches,
 		'override' => 0,
 		'default' => [16]},
+
+	# Avatar support. When this feature is enabled, views such as
+	# shortlog or commit will display an avatar associated with
+	# the email of the committer(s) and/or author(s).
+
+	# Currently available providers are gravatar and picon.
+	# If an unknown provider is specified, the feature is disabled.
+
+	# Gravatar depends on Digest::MD5.
+	# Picon currently relies on the indiana.edu database.
+
+	# To enable system wide have in $GITWEB_CONFIG
+	# $feature{'avatar'}{'default'} = ['<provider>'];
+	# where <provider> is either gravatar or picon.
+	# To have project specific config enable override in $GITWEB_CONFIG
+	# $feature{'avatar'}{'override'} = 1;
+	# and in project config gitweb.avatar = <provider>;
+	'avatar' => {
+		'sub' => \&feature_avatar,
+		'override' => 0,
+		'default' => ['']},
 );
 
 sub gitweb_get_feature {
@@ -433,6 +462,12 @@
 	return ($_[0]);
 }
 
+sub feature_avatar {
+	my @val = (git_get_project_config('avatar'));
+
+	return @val ? @val : @_;
+}
+
 # checking HEAD file with -e is fragile if the repository was
 # initialized long time ago (i.e. symlink HEAD) and was pack-ref'ed
 # and then pruned.
@@ -814,6 +849,19 @@
 our @snapshot_fmts = gitweb_get_feature('snapshot');
 @snapshot_fmts = filter_snapshot_fmts(@snapshot_fmts);
 
+# check that the avatar feature is set to a known provider name,
+# and for each provider check if the dependencies are satisfied.
+# if the provider name is invalid or the dependencies are not met,
+# reset $git_avatar to the empty string.
+our ($git_avatar) = gitweb_get_feature('avatar');
+if ($git_avatar eq 'gravatar') {
+	$git_avatar = '' unless (eval { require Digest::MD5; 1; });
+} elsif ($git_avatar eq 'picon') {
+	# no dependencies
+} else {
+	$git_avatar = '';
+}
+
 # dispatch
 if (!defined $action) {
 	if (defined $hash) {
@@ -1469,6 +1517,82 @@
 	}
 }
 
+# Rather than recomputing the url for an email multiple times, we cache it
+# after the first hit. This gives a visible benefit in views where the avatar
+# for the same email is used repeatedly (e.g. shortlog).
+# The cache is shared by all avatar engines (currently gravatar only), which
+# are free to use it as preferred. Since only one avatar engine is used for any
+# given page, there's no risk for cache conflicts.
+our %avatar_cache = ();
+
+# Compute the picon url for a given email, by using the picon search service over at
+# http://www.cs.indiana.edu/picons/search.html
+sub picon_url {
+	my $email = lc shift;
+	if (!$avatar_cache{$email}) {
+		my ($user, $domain) = split('@', $email);
+		$avatar_cache{$email} =
+			"http://www.cs.indiana.edu/cgi-pub/kinzler/piconsearch.cgi/" .
+			"$domain/$user/" .
+			"users+domains+unknown/up/single";
+	}
+	return $avatar_cache{$email};
+}
+
+# Compute the gravatar url for a given email, if it's not in the cache already.
+# Gravatar stores only the part of the URL before the size, since that's the
+# one computationally more expensive. This also allows reuse of the cache for
+# different sizes (for this particular engine).
+sub gravatar_url {
+	my $email = lc shift;
+	my $size = shift;
+	$avatar_cache{$email} ||=
+		"http://www.gravatar.com/avatar/" .
+			Digest::MD5::md5_hex($email) . "?s=";
+	return $avatar_cache{$email} . $size;
+}
+
+# Insert an avatar for the given $email at the given $size if the feature
+# is enabled.
+sub git_get_avatar {
+	my ($email, %opts) = @_;
+	my $pre_white  = ($opts{-pad_before} ? "&nbsp;" : "");
+	my $post_white = ($opts{-pad_after}  ? "&nbsp;" : "");
+	$opts{-size} ||= 'default';
+	my $size = $avatar_size{$opts{-size}} || $avatar_size{'default'};
+	my $url = "";
+	if ($git_avatar eq 'gravatar') {
+		$url = gravatar_url($email, $size);
+	} elsif ($git_avatar eq 'picon') {
+		$url = picon_url($email);
+	}
+	# Other providers can be added by extending the if chain, defining $url
+	# as needed. If no variant puts something in $url, we assume avatars
+	# are completely disabled/unavailable.
+	if ($url) {
+		return $pre_white .
+		       "<img width=\"$size\" " .
+		            "class=\"avatar\" " .
+		            "src=\"$url\" " .
+			    "alt=\"\" " .
+		       "/>" . $post_white;
+	} else {
+		return "";
+	}
+}
+
+# format the author name of the given commit with the given tag
+# the author name is chopped and escaped according to the other
+# optional parameters (see chop_str).
+sub format_author_html {
+	my $tag = shift;
+	my $co = shift;
+	my $author = chop_and_escape_str($co->{'author_name'}, @_);
+	return "<$tag class=\"author\">" .
+	       git_get_avatar($co->{'author_email'}, -pad_after => 1) .
+	       $author . "</$tag>";
+}
+
 # format git diff header line, i.e. "diff --(git|combined|cc) ..."
 sub format_git_diff_header_line {
 	my $line = shift;
@@ -2399,8 +2523,14 @@
 			$tag{'name'} = $1;
 		} elsif ($line =~ m/^tagger (.*) ([0-9]+) (.*)$/) {
 			$tag{'author'} = $1;
-			$tag{'epoch'} = $2;
-			$tag{'tz'} = $3;
+			$tag{'author_epoch'} = $2;
+			$tag{'author_tz'} = $3;
+			if ($tag{'author'} =~ m/^([^<]+) <([^>]*)>/) {
+				$tag{'author_name'}  = $1;
+				$tag{'author_email'} = $2;
+			} else {
+				$tag{'author_name'} = $tag{'author'};
+			}
 		} elsif ($line =~ m/--BEGIN/) {
 			push @comment, $line;
 			last;
@@ -3214,21 +3344,54 @@
 	      "\n</div>\n";
 }
 
-sub git_print_authorship {
-	my $co = shift;
-
-	my %ad = parse_date($co->{'author_epoch'}, $co->{'author_tz'});
-	print "<div class=\"author_date\">" .
-	      esc_html($co->{'author_name'}) .
-	      " [$ad{'rfc2822'}";
-	if ($ad{'hour_local'} < 6) {
+sub print_local_time {
+	my %date = @_;
+	if ($date{'hour_local'} < 6) {
 		printf(" (<span class=\"atnight\">%02d:%02d</span> %s)",
-		       $ad{'hour_local'}, $ad{'minute_local'}, $ad{'tz_local'});
+			$date{'hour_local'}, $date{'minute_local'}, $date{'tz_local'});
 	} else {
 		printf(" (%02d:%02d %s)",
-		       $ad{'hour_local'}, $ad{'minute_local'}, $ad{'tz_local'});
+			$date{'hour_local'}, $date{'minute_local'}, $date{'tz_local'});
 	}
-	print "]</div>\n";
+}
+
+# Outputs the author name and date in long form
+sub git_print_authorship {
+	my $co = shift;
+	my %opts = @_;
+	my $tag = $opts{-tag} || 'div';
+
+	my %ad = parse_date($co->{'author_epoch'}, $co->{'author_tz'});
+	print "<$tag class=\"author_date\">" .
+	      esc_html($co->{'author_name'}) .
+	      " [$ad{'rfc2822'}";
+	print_local_time(%ad) if ($opts{-localtime});
+	print "]" . git_get_avatar($co->{'author_email'}, -pad_before => 1)
+		  . "</$tag>\n";
+}
+
+# Outputs table rows containing the full author or committer information,
+# in the format expected for 'commit' view (& similia).
+# Parameters are a commit hash reference, followed by the list of people
+# to output information for. If the list is empty it defalts to both
+# author and committer.
+sub git_print_authorship_rows {
+	my $co = shift;
+	# too bad we can't use @people = @_ || ('author', 'committer')
+	my @people = @_;
+	@people = ('author', 'committer') unless @people;
+	foreach my $who (@people) {
+		my %wd = parse_date($co->{"${who}_epoch"}, $co->{"${who}_tz"});
+		print "<tr><td>$who</td><td>" . esc_html($co->{$who}) . "</td>" .
+		      "<td rowspan=\"2\">" .
+		      git_get_avatar($co->{"${who}_email"}, -size => 'double') .
+		      "</td></tr>\n" .
+		      "<tr>" .
+		      "<td></td><td> $wd{'rfc2822'}";
+		print_local_time(%wd);
+		print "</td>" .
+		      "</tr>\n";
+	}
 }
 
 sub git_print_page_path {
@@ -4142,11 +4305,9 @@
 			print "<tr class=\"light\">\n";
 		}
 		$alternate ^= 1;
-		my $author = chop_and_escape_str($co{'author_name'}, 10);
 		# git_summary() used print "<td><i>$co{'age_string'}</i></td>\n" .
 		print "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
-		      "<td><i>" . $author . "</i></td>\n" .
-		      "<td>";
+		      format_author_html('td', \%co, 10) . "<td>";
 		print format_subject_html($co{'title'}, $co{'title_short'},
 		                          href(action=>"commit", hash=>$commit), $ref);
 		print "</td>\n" .
@@ -4193,11 +4354,9 @@
 			print "<tr class=\"light\">\n";
 		}
 		$alternate ^= 1;
-	# shortlog uses      chop_str($co{'author_name'}, 10)
-		my $author = chop_and_escape_str($co{'author_name'}, 15, 3);
 		print "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
-		      "<td><i>" . $author . "</i></td>\n" .
-		      "<td>";
+	# shortlog:   format_author_html('td', \%co, 10)
+		      format_author_html('td', \%co, 15, 3) . "<td>";
 		# originally git_history used chop_str($co{'title'}, 50)
 		print format_subject_html($co{'title'}, $co{'title_short'},
 		                          href(action=>"commit", hash=>$commit), $ref);
@@ -4350,9 +4509,8 @@
 			print "<tr class=\"light\">\n";
 		}
 		$alternate ^= 1;
-		my $author = chop_and_escape_str($co{'author_name'}, 15, 5);
 		print "<td title=\"$co{'age_string_age'}\"><i>$co{'age_string_date'}</i></td>\n" .
-		      "<td><i>" . $author . "</i></td>\n" .
+		      format_author_html('td', \%co, 15, 5) .
 		      "<td>" .
 		      $cgi->a({-href => href(action=>"commit", hash=>$co{'id'}),
 		               -class => "list subject"},
@@ -4586,11 +4744,7 @@
 	                                      $tag{'type'}) . "</td>\n" .
 	      "</tr>\n";
 	if (defined($tag{'author'})) {
-		my %ad = parse_date($tag{'epoch'}, $tag{'tz'});
-		print "<tr><td>author</td><td>" . esc_html($tag{'author'}) . "</td></tr>\n";
-		print "<tr><td></td><td>" . $ad{'rfc2822'} .
-			sprintf(" (%02d:%02d %s)", $ad{'hour_local'}, $ad{'minute_local'}, $ad{'tz_local'}) .
-			"</td></tr>\n";
+		git_print_authorship_rows(\%tag, 'author');
 	}
 	print "</table>\n\n" .
 	      "</div>\n";
@@ -5094,9 +5248,9 @@
 		      " | " .
 		      $cgi->a({-href => href(action=>"tree", hash=>$commit, hash_base=>$commit)}, "tree") .
 		      "<br/>\n" .
-		      "</div>\n" .
-		      "<i>" . esc_html($co{'author_name'}) .  " [$ad{'rfc2822'}]</i><br/>\n" .
 		      "</div>\n";
+		      git_print_authorship(\%co, -tag => 'span');
+		      print "<br/>\n</div>\n";
 
 		print "<div class=\"log_body\">\n";
 		git_print_log($co{'comment'}, -final_empty_line=> 1);
@@ -5115,8 +5269,6 @@
 	$hash ||= $hash_base || "HEAD";
 	my %co = parse_commit($hash)
 	    or die_error(404, "Unknown commit object");
-	my %ad = parse_date($co{'author_epoch'}, $co{'author_tz'});
-	my %cd = parse_date($co{'committer_epoch'}, $co{'committer_tz'});
 
 	my $parent  = $co{'parent'};
 	my $parents = $co{'parents'}; # listref
@@ -5183,22 +5335,7 @@
 	}
 	print "<div class=\"title_text\">\n" .
 	      "<table class=\"object_header\">\n";
-	print "<tr><td>author</td><td>" . esc_html($co{'author'}) . "</td></tr>\n".
-	      "<tr>" .
-	      "<td></td><td> $ad{'rfc2822'}";
-	if ($ad{'hour_local'} < 6) {
-		printf(" (<span class=\"atnight\">%02d:%02d</span> %s)",
-		       $ad{'hour_local'}, $ad{'minute_local'}, $ad{'tz_local'});
-	} else {
-		printf(" (%02d:%02d %s)",
-		       $ad{'hour_local'}, $ad{'minute_local'}, $ad{'tz_local'});
-	}
-	print "</td>" .
-	      "</tr>\n";
-	print "<tr><td>committer</td><td>" . esc_html($co{'committer'}) . "</td></tr>\n";
-	print "<tr><td></td><td> $cd{'rfc2822'}" .
-	      sprintf(" (%02d:%02d %s)", $cd{'hour_local'}, $cd{'minute_local'}, $cd{'tz_local'}) .
-	      "</td></tr>\n";
+	git_print_authorship_rows(\%co);
 	print "<tr><td>commit</td><td class=\"sha1\">$co{'id'}</td></tr>\n";
 	print "<tr>" .
 	      "<td>tree</td>" .
@@ -5579,7 +5716,11 @@
 		git_header_html(undef, $expires);
 		git_print_page_nav('commitdiff','', $hash,$co{'tree'},$hash, $formats_nav);
 		git_print_header_div('commit', esc_html($co{'title'}) . $ref, $hash);
-		git_print_authorship(\%co);
+		print "<div class=\"title_text\">\n" .
+		      "<table class=\"object_header\">\n";
+		git_print_authorship_rows(\%co);
+		print "</table>".
+		      "</div>\n";
 		print "<div class=\"page_body\">\n";
 		if (@{$co{'comment'}} > 1) {
 			print "<div class=\"log\">\n";
diff --git a/grep.c b/grep.c
index 92a47c7..5d162da 100644
--- a/grep.c
+++ b/grep.c
@@ -1,5 +1,6 @@
 #include "cache.h"
 #include "grep.h"
+#include "userdiff.h"
 #include "xdiff-interface.h"
 
 void append_header_grep_pattern(struct grep_opt *opt, enum grep_header_field field, const char *pat)
@@ -490,6 +491,17 @@
 {
 	int rest = eol - bol;
 
+	if (opt->pre_context || opt->post_context) {
+		if (opt->last_shown == 0) {
+			if (opt->show_hunk_mark)
+				fputs("--\n", stdout);
+			else
+				opt->show_hunk_mark = 1;
+		} else if (lno > opt->last_shown + 1)
+			fputs("--\n", stdout);
+	}
+	opt->last_shown = lno;
+
 	if (opt->null_following_name)
 		sign = '\0';
 	if (opt->pathname)
@@ -520,22 +532,95 @@
 	printf("%.*s\n", rest, bol);
 }
 
+static int match_funcname(struct grep_opt *opt, char *bol, char *eol)
+{
+	xdemitconf_t *xecfg = opt->priv;
+	if (xecfg && xecfg->find_func) {
+		char buf[1];
+		return xecfg->find_func(bol, eol - bol, buf, 1,
+					xecfg->find_func_priv) >= 0;
+	}
+
+	if (bol == eol)
+		return 0;
+	if (isalpha(*bol) || *bol == '_' || *bol == '$')
+		return 1;
+	return 0;
+}
+
+static void show_funcname_line(struct grep_opt *opt, const char *name,
+			       char *buf, char *bol, unsigned lno)
+{
+	while (bol > buf) {
+		char *eol = --bol;
+
+		while (bol > buf && bol[-1] != '\n')
+			bol--;
+		lno--;
+
+		if (lno <= opt->last_shown)
+			break;
+
+		if (match_funcname(opt, bol, eol)) {
+			show_line(opt, bol, eol, name, lno, '=');
+			break;
+		}
+	}
+}
+
+static void show_pre_context(struct grep_opt *opt, const char *name, char *buf,
+			     char *bol, unsigned lno)
+{
+	unsigned cur = lno, from = 1, funcname_lno = 0;
+	int funcname_needed = opt->funcname;
+
+	if (opt->pre_context < lno)
+		from = lno - opt->pre_context;
+	if (from <= opt->last_shown)
+		from = opt->last_shown + 1;
+
+	/* Rewind. */
+	while (bol > buf && cur > from) {
+		char *eol = --bol;
+
+		while (bol > buf && bol[-1] != '\n')
+			bol--;
+		cur--;
+		if (funcname_needed && match_funcname(opt, bol, eol)) {
+			funcname_lno = cur;
+			funcname_needed = 0;
+		}
+	}
+
+	/* We need to look even further back to find a function signature. */
+	if (opt->funcname && funcname_needed)
+		show_funcname_line(opt, name, buf, bol, cur);
+
+	/* Back forward. */
+	while (cur < lno) {
+		char *eol = bol, sign = (cur == funcname_lno) ? '=' : '-';
+
+		while (*eol != '\n')
+			eol++;
+		show_line(opt, bol, eol, name, cur, sign);
+		bol = eol + 1;
+		cur++;
+	}
+}
+
 static int grep_buffer_1(struct grep_opt *opt, const char *name,
 			 char *buf, unsigned long size, int collect_hits)
 {
 	char *bol = buf;
 	unsigned long left = size;
 	unsigned lno = 1;
-	struct pre_context_line {
-		char *bol;
-		char *eol;
-	} *prev = NULL, *pcl;
 	unsigned last_hit = 0;
-	unsigned last_shown = 0;
 	int binary_match_only = 0;
-	const char *hunk_mark = "";
 	unsigned count = 0;
 	enum grep_context ctx = GREP_CONTEXT_HEAD;
+	xdemitconf_t xecfg;
+
+	opt->last_shown = 0;
 
 	if (buffer_is_binary(buf, size)) {
 		switch (opt->binary) {
@@ -550,10 +635,16 @@
 		}
 	}
 
-	if (opt->pre_context)
-		prev = xcalloc(opt->pre_context, sizeof(*prev));
-	if (opt->pre_context || opt->post_context)
-		hunk_mark = "--\n";
+	memset(&xecfg, 0, sizeof(xecfg));
+	if (opt->funcname && !opt->unmatch_name_only && !opt->status_only &&
+	    !opt->name_only && !binary_match_only && !collect_hits) {
+		struct userdiff_driver *drv = userdiff_find_by_path(name);
+		if (drv && drv->funcname.pattern) {
+			const struct userdiff_funcname *pe = &drv->funcname;
+			xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags);
+			opt->priv = &xecfg;
+		}
+	}
 
 	while (left) {
 		char *eol, ch;
@@ -601,45 +692,20 @@
 			 * the context which is nonsense, but the user
 			 * deserves to get that ;-).
 			 */
-			if (opt->pre_context) {
-				unsigned from;
-				if (opt->pre_context < lno)
-					from = lno - opt->pre_context;
-				else
-					from = 1;
-				if (from <= last_shown)
-					from = last_shown + 1;
-				if (last_shown && from != last_shown + 1)
-					fputs(hunk_mark, stdout);
-				while (from < lno) {
-					pcl = &prev[lno-from-1];
-					show_line(opt, pcl->bol, pcl->eol,
-						  name, from, '-');
-					from++;
-				}
-				last_shown = lno-1;
-			}
-			if (last_shown && lno != last_shown + 1)
-				fputs(hunk_mark, stdout);
+			if (opt->pre_context)
+				show_pre_context(opt, name, buf, bol, lno);
+			else if (opt->funcname)
+				show_funcname_line(opt, name, buf, bol, lno);
 			if (!opt->count)
 				show_line(opt, bol, eol, name, lno, ':');
-			last_shown = last_hit = lno;
+			last_hit = lno;
 		}
 		else if (last_hit &&
 			 lno <= last_hit + opt->post_context) {
 			/* If the last hit is within the post context,
 			 * we need to show this line.
 			 */
-			if (last_shown && lno != last_shown + 1)
-				fputs(hunk_mark, stdout);
 			show_line(opt, bol, eol, name, lno, '-');
-			last_shown = lno;
-		}
-		if (opt->pre_context) {
-			memmove(prev+1, prev,
-				(opt->pre_context-1) * sizeof(*prev));
-			prev->bol = bol;
-			prev->eol = eol;
 		}
 
 	next_line:
@@ -650,7 +716,6 @@
 		lno++;
 	}
 
-	free(prev);
 	if (collect_hits)
 		return 0;
 
@@ -662,6 +727,9 @@
 		return 1;
 	}
 
+	xdiff_clear_find_func(&xecfg);
+	opt->priv = NULL;
+
 	/* NEEDSWORK:
 	 * The real "grep -c foo *.c" gives many "bar.c:0" lines,
 	 * which feels mostly useless but sometimes useful.  Maybe
diff --git a/grep.h b/grep.h
index 464e272..f00db0e 100644
--- a/grep.h
+++ b/grep.h
@@ -79,11 +79,15 @@
 	int pathname;
 	int null_following_name;
 	int color;
+	int funcname;
 	char color_match[COLOR_MAXLEN];
 	const char *color_external;
 	int regflags;
 	unsigned pre_context;
 	unsigned post_context;
+	unsigned last_shown;
+	int show_hunk_mark;
+	void *priv;
 };
 
 extern void append_grep_pattern(struct grep_opt *opt, const char *pat, const char *origin, int no, enum grep_pat_token t);
diff --git a/hash-object.c b/hash-object.c
index 47cf43c..9455dd0 100644
--- a/hash-object.c
+++ b/hash-object.c
@@ -29,7 +29,7 @@
 	int fd;
 	fd = open(path, O_RDONLY);
 	if (fd < 0)
-		die("Cannot open %s", path);
+		die_errno("Cannot open '%s'", path);
 	hash_fd(fd, type, write_object, vpath);
 }
 
diff --git a/http-push.c b/http-push.c
index 8cc8ee0..00e83dc 100644
--- a/http-push.c
+++ b/http-push.c
@@ -193,6 +193,8 @@
 		case '&':
 			strbuf_addstr(&buf, "&amp;");
 			break;
+		case 0:
+			return strbuf_detach(&buf, NULL);
 		}
 		s++;
 	}
diff --git a/http.c b/http.c
index b049948..a2720d5 100644
--- a/http.c
+++ b/http.c
@@ -33,6 +33,17 @@
 static const char *curl_http_proxy;
 static char *user_name, *user_pass;
 
+#if LIBCURL_VERSION_NUM >= 0x071700
+/* Use CURLOPT_KEYPASSWD as is */
+#elif LIBCURL_VERSION_NUM >= 0x070903
+#define CURLOPT_KEYPASSWD CURLOPT_SSLKEYPASSWD
+#else
+#define CURLOPT_KEYPASSWD CURLOPT_SSLCERTPASSWD
+#endif
+
+static char *ssl_cert_password;
+static int ssl_cert_password_required;
+
 static struct curl_slist *pragma_header;
 static struct curl_slist *no_pragma_header;
 
@@ -136,6 +147,11 @@
 #endif
 	if (!strcmp("http.sslcainfo", var))
 		return git_config_string(&ssl_cainfo, var, value);
+	if (!strcmp("http.sslcertpasswordprotected", var)) {
+		if (git_config_bool(var, value))
+			ssl_cert_password_required = 1;
+		return 0;
+	}
 #ifdef USE_CURL_MULTI
 	if (!strcmp("http.maxrequests", var)) {
 		max_requests = git_config_int(var, value);
@@ -174,6 +190,22 @@
 	}
 }
 
+static int has_cert_password(void)
+{
+	if (ssl_cert_password != NULL)
+		return 1;
+	if (ssl_cert == NULL || ssl_cert_password_required != 1)
+		return 0;
+	/* Only prompt the user once. */
+	ssl_cert_password_required = -1;
+	ssl_cert_password = getpass("Certificate Password: ");
+	if (ssl_cert_password != NULL) {
+		ssl_cert_password = xstrdup(ssl_cert_password);
+		return 1;
+	} else
+		return 0;
+}
+
 static CURL *get_curl_handle(void)
 {
 	CURL *result = curl_easy_init();
@@ -196,6 +228,8 @@
 
 	if (ssl_cert != NULL)
 		curl_easy_setopt(result, CURLOPT_SSLCERT, ssl_cert);
+	if (has_cert_password())
+		curl_easy_setopt(result, CURLOPT_KEYPASSWD, ssl_cert_password);
 #if LIBCURL_VERSION_NUM >= 0x070903
 	if (ssl_key != NULL)
 		curl_easy_setopt(result, CURLOPT_SSLKEY, ssl_key);
@@ -339,8 +373,13 @@
 	if (getenv("GIT_CURL_FTP_NO_EPSV"))
 		curl_ftp_no_epsv = 1;
 
-	if (remote && remote->url && remote->url[0])
+	if (remote && remote->url && remote->url[0]) {
 		http_auth_init(remote->url[0]);
+		if (!ssl_cert_password_required &&
+		    getenv("GIT_SSL_CERT_PASSWORD_PROTECTED") &&
+		    !prefixcmp(remote->url[0], "https://"))
+			ssl_cert_password_required = 1;
+	}
 
 #ifndef NO_CURL_EASY_DUPHANDLE
 	curl_default = get_curl_handle();
@@ -383,6 +422,13 @@
 		free((void *)curl_http_proxy);
 		curl_http_proxy = NULL;
 	}
+
+	if (ssl_cert_password != NULL) {
+		memset(ssl_cert_password, 0, strlen(ssl_cert_password));
+		free(ssl_cert_password);
+		ssl_cert_password = NULL;
+	}
+	ssl_cert_password_required = 0;
 }
 
 struct active_request_slot *get_active_slot(void)
diff --git a/index-pack.c b/index-pack.c
index c72cbd4..340074f 100644
--- a/index-pack.c
+++ b/index-pack.c
@@ -143,7 +143,7 @@
 		if (ret <= 0) {
 			if (!ret)
 				die("early EOF");
-			die("read error on input: %s", strerror(errno));
+			die_errno("read error on input");
 		}
 		input_len += ret;
 		if (from_stdin)
@@ -178,13 +178,12 @@
 		} else
 			output_fd = open(pack_name, O_CREAT|O_EXCL|O_RDWR, 0600);
 		if (output_fd < 0)
-			die("unable to create %s: %s", pack_name, strerror(errno));
+			die_errno("unable to create '%s'", pack_name);
 		pack_fd = output_fd;
 	} else {
 		input_fd = open(pack_name, O_RDONLY);
 		if (input_fd < 0)
-			die("cannot open packfile '%s': %s",
-			    pack_name, strerror(errno));
+			die_errno("cannot open packfile '%s'", pack_name);
 		output_fd = -1;
 		pack_fd = input_fd;
 	}
@@ -370,7 +369,7 @@
 	do {
 		ssize_t n = pread(pack_fd, data + rdy, len - rdy, from + rdy);
 		if (n < 0)
-			die("cannot pread pack file: %s", strerror(errno));
+			die_errno("cannot pread pack file");
 		if (!n)
 			die("premature end of pack file, %lu bytes missing",
 			    len - rdy);
@@ -631,7 +630,7 @@
 
 	/* If input_fd is a file, we should have reached its end now. */
 	if (fstat(input_fd, &st))
-		die("cannot fstat packfile: %s", strerror(errno));
+		die_errno("cannot fstat packfile");
 	if (S_ISREG(st.st_mode) &&
 			lseek(input_fd, 0, SEEK_CUR) - input_len != st.st_size)
 		die("pack has junk at the end");
@@ -788,7 +787,7 @@
 		fsync_or_die(output_fd, curr_pack_name);
 		err = close(output_fd);
 		if (err)
-			die("error while closing pack file: %s", strerror(errno));
+			die_errno("error while closing pack file");
 	}
 
 	if (keep_msg) {
@@ -801,16 +800,16 @@
 
 		if (keep_fd < 0) {
 			if (errno != EEXIST)
-				die("cannot write keep file '%s' (%s)",
-				    keep_name, strerror(errno));
+				die_errno("cannot write keep file '%s'",
+					  keep_name);
 		} else {
 			if (keep_msg_len > 0) {
 				write_or_die(keep_fd, keep_msg, keep_msg_len);
 				write_or_die(keep_fd, "\n", 1);
 			}
 			if (close(keep_fd) != 0)
-				die("cannot close written keep file '%s' (%s)",
-				    keep_name, strerror(errno));
+				die_errno("cannot close written keep file '%s'",
+				    keep_name);
 			report = "keep";
 		}
 	}
diff --git a/ll-merge.c b/ll-merge.c
index 9168958..0571564 100644
--- a/ll-merge.c
+++ b/ll-merge.c
@@ -55,7 +55,7 @@
 
 static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
 			mmbuffer_t *result,
-			const char *path_unused,
+			const char *path,
 			mmfile_t *orig,
 			mmfile_t *src1, const char *name1,
 			mmfile_t *src2, const char *name2,
@@ -67,10 +67,10 @@
 	if (buffer_is_binary(orig->ptr, orig->size) ||
 	    buffer_is_binary(src1->ptr, src1->size) ||
 	    buffer_is_binary(src2->ptr, src2->size)) {
-		warning("Cannot merge binary files: %s vs. %s\n",
-			name1, name2);
+		warning("Cannot merge binary files: %s (%s vs. %s)\n",
+			path, name1, name2);
 		return ll_binary_merge(drv_unused, result,
-				       path_unused,
+				       path,
 				       orig, src1, name1,
 				       src2, name2,
 				       virtual_ancestor);
@@ -152,7 +152,7 @@
 	strcpy(path, ".merge_file_XXXXXX");
 	fd = xmkstemp(path);
 	if (write_in_full(fd, src->ptr, src->size) != src->size)
-		die("unable to write temp-file");
+		die_errno("unable to write temp-file");
 	close(fd);
 }
 
diff --git a/log-tree.c b/log-tree.c
index 59d63eb..6f73c17 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -321,7 +321,8 @@
 	}
 
 	/*
-	 * If use_terminator is set, add a newline at the end of the entry.
+	 * If use_terminator is set, we already handled any record termination
+	 * at the end of the last record.
 	 * Otherwise, add a diffopt.line_termination character before all
 	 * entries but the first.  (IOW, as a separator between entries)
 	 */
diff --git a/merge-recursive.c b/merge-recursive.c
index c703445..d415c41 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -438,7 +438,7 @@
 			/* Ignore epipe */
 			if (errno == EPIPE)
 				break;
-			die("merge-recursive: %s", strerror(errno));
+			die_errno("merge-recursive");
 		} else if (!ret) {
 			die("merge-recursive: disk full?");
 		}
@@ -554,7 +554,7 @@
 				mode = 0666;
 			fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, mode);
 			if (fd < 0)
-				die("failed to open %s: %s", path, strerror(errno));
+				die_errno("failed to open '%s'", path);
 			flush_buffer(fd, buf, size);
 			close(fd);
 		} else if (S_ISLNK(mode)) {
@@ -562,7 +562,7 @@
 			safe_create_leading_directories_const(path);
 			unlink(path);
 			if (symlink(lnk, path))
-				die("failed to symlink %s: %s", path, strerror(errno));
+				die_errno("failed to symlink '%s'", path);
 			free(lnk);
 		} else
 			die("do not know what to do with %06o %s '%s'",
@@ -622,8 +622,13 @@
 	char *name1, *name2;
 	int merge_status;
 
-	name1 = xstrdup(mkpath("%s:%s", branch1, a->path));
-	name2 = xstrdup(mkpath("%s:%s", branch2, b->path));
+	if (strcmp(a->path, b->path)) {
+		name1 = xstrdup(mkpath("%s:%s", branch1, a->path));
+		name2 = xstrdup(mkpath("%s:%s", branch2, b->path));
+	} else {
+		name1 = xstrdup(mkpath("%s", branch1));
+		name2 = xstrdup(mkpath("%s", branch2));
+	}
 
 	fill_mm(one->sha1, &orig);
 	fill_mm(a->sha1, &src1);
diff --git a/mktag.c b/mktag.c
index 99a356e..a609e3e 100644
--- a/mktag.c
+++ b/mktag.c
@@ -165,7 +165,7 @@
 	setup_git_directory();
 
 	if (strbuf_read(&buf, 0, 4096) < 0) {
-		die("could not read from stdin");
+		die_errno("could not read from stdin");
 	}
 
 	/* Verify it for some basic sanity: it needs to start with
diff --git a/pack-refs.c b/pack-refs.c
index 301fc60..7f43f8a 100644
--- a/pack-refs.c
+++ b/pack-refs.c
@@ -93,8 +93,7 @@
 				       LOCK_DIE_ON_ERROR);
 	cbdata.refs_file = fdopen(fd, "w");
 	if (!cbdata.refs_file)
-		die("unable to create ref-pack file structure (%s)",
-		    strerror(errno));
+		die_errno("unable to create ref-pack file structure");
 
 	/* perhaps other traits later as well */
 	fprintf(cbdata.refs_file, "# pack-refs with: peeled \n");
@@ -103,7 +102,7 @@
 	if (ferror(cbdata.refs_file))
 		die("failed to write ref-pack file");
 	if (fflush(cbdata.refs_file) || fsync(fd) || fclose(cbdata.refs_file))
-		die("failed to write ref-pack file (%s)", strerror(errno));
+		die_errno("failed to write ref-pack file");
 	/*
 	 * Since the lock file was fdopen()'ed and then fclose()'ed above,
 	 * assign -1 to the lock file descriptor so that commit_lock_file()
@@ -111,7 +110,7 @@
 	 */
 	packed.fd = -1;
 	if (commit_lock_file(&packed) < 0)
-		die("unable to overwrite old ref-pack file (%s)", strerror(errno));
+		die_errno("unable to overwrite old ref-pack file");
 	if (cbdata.flags & PACK_REFS_PRUNE)
 		prune_refs(cbdata.ref_to_prune);
 	return 0;
diff --git a/pack-write.c b/pack-write.c
index 7053538..741efcd 100644
--- a/pack-write.c
+++ b/pack-write.c
@@ -51,7 +51,7 @@
 		fd = open(index_name, O_CREAT|O_EXCL|O_WRONLY, 0600);
 	}
 	if (fd < 0)
-		die("unable to create %s: %s", index_name, strerror(errno));
+		die_errno("unable to create '%s'", index_name);
 	f = sha1fd(fd, index_name);
 
 	/* if last object's offset is >= 2^31 we should use index V2 */
@@ -174,11 +174,11 @@
 	git_SHA1_Init(&new_sha1_ctx);
 
 	if (lseek(pack_fd, 0, SEEK_SET) != 0)
-		die("Failed seeking to start of %s: %s", pack_name, strerror(errno));
+		die_errno("Failed seeking to start of '%s'", pack_name);
 	if (read_in_full(pack_fd, &hdr, sizeof(hdr)) != sizeof(hdr))
-		die("Unable to reread header of %s: %s", pack_name, strerror(errno));
+		die_errno("Unable to reread header of '%s'", pack_name);
 	if (lseek(pack_fd, 0, SEEK_SET) != 0)
-		die("Failed seeking to start of %s: %s", pack_name, strerror(errno));
+		die_errno("Failed seeking to start of '%s'", pack_name);
 	git_SHA1_Update(&old_sha1_ctx, &hdr, sizeof(hdr));
 	hdr.hdr_entries = htonl(object_count);
 	git_SHA1_Update(&new_sha1_ctx, &hdr, sizeof(hdr));
@@ -195,7 +195,7 @@
 		if (!n)
 			break;
 		if (n < 0)
-			die("Failed to checksum %s: %s", pack_name, strerror(errno));
+			die_errno("Failed to checksum '%s'", pack_name);
 		git_SHA1_Update(&new_sha1_ctx, buf, n);
 
 		aligned_sz -= n;
diff --git a/pkt-line.c b/pkt-line.c
index f5d0086..b691abe 100644
--- a/pkt-line.c
+++ b/pkt-line.c
@@ -28,7 +28,7 @@
 		}
 		if (!ret)
 			die("write error (disk full?)");
-		die("write error (%s)", strerror(errno));
+		die_errno("write error");
 	}
 	return nn;
 }
@@ -67,7 +67,7 @@
 {
 	ssize_t ret = read_in_full(fd, buffer, size);
 	if (ret < 0)
-		die("read error (%s)", strerror(errno));
+		die_errno("read error");
 	else if (ret < size)
 		die("The remote end hung up unexpectedly");
 }
diff --git a/read-cache.c b/read-cache.c
index 3f58711..4e3e272 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -638,7 +638,7 @@
 {
 	struct stat st;
 	if (lstat(path, &st))
-		die("%s: unable to stat (%s)", path, strerror(errno));
+		die_errno("unable to stat '%s'", path);
 	return add_to_index(istate, path, &st, flags);
 }
 
@@ -1251,11 +1251,11 @@
 	if (fd < 0) {
 		if (errno == ENOENT)
 			return 0;
-		die("index file open failed (%s)", strerror(errno));
+		die_errno("index file open failed");
 	}
 
 	if (fstat(fd, &st))
-		die("cannot stat the open index (%s)", strerror(errno));
+		die_errno("cannot stat the open index");
 
 	errno = EINVAL;
 	mmap_size = xsize_t(st.st_size);
@@ -1265,7 +1265,7 @@
 	mmap = xmmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
 	close(fd);
 	if (mmap == MAP_FAILED)
-		die("unable to map index file");
+		die_errno("unable to map index file");
 
 	hdr = mmap;
 	if (verify_hdr(hdr, mmap_size) < 0)
diff --git a/refs.c b/refs.c
index 24438c6..dffe395 100644
--- a/refs.c
+++ b/refs.c
@@ -1418,7 +1418,7 @@
 	logfile = git_path("logs/%s", ref);
 	logfd = open(logfile, O_RDONLY, 0);
 	if (logfd < 0)
-		die("Unable to read log %s: %s", logfile, strerror(errno));
+		die_errno("Unable to read log '%s'", logfile);
 	fstat(logfd, &st);
 	if (!st.st_size)
 		die("Log %s is empty.", logfile);
diff --git a/remote.c b/remote.c
index 733ba57..c3ada2d 100644
--- a/remote.c
+++ b/remote.c
@@ -1277,7 +1277,7 @@
 
 static struct ref *get_local_ref(const char *name)
 {
-	if (!name)
+	if (!name || name[0] == '\0')
 		return NULL;
 
 	if (!prefixcmp(name, "refs/"))
diff --git a/revision.c b/revision.c
index bf58448..a31434b 100644
--- a/revision.c
+++ b/revision.c
@@ -1077,6 +1077,8 @@
 		revs->show_all = 1;
 	} else if (!strcmp(arg, "--remove-empty")) {
 		revs->remove_empty_trees = 1;
+	} else if (!strcmp(arg, "--merges")) {
+		revs->merges_only = 1;
 	} else if (!strcmp(arg, "--no-merges")) {
 		revs->no_merges = 1;
 	} else if (!strcmp(arg, "--boundary")) {
@@ -1676,6 +1678,8 @@
 		return commit_ignore;
 	if (revs->no_merges && commit->parents && commit->parents->next)
 		return commit_ignore;
+	if (revs->merges_only && !(commit->parents && commit->parents->next))
+		return commit_ignore;
 	if (!commit_match(commit, revs))
 		return commit_ignore;
 	if (revs->prune && revs->dense) {
diff --git a/revision.h b/revision.h
index 227164c..fb74492 100644
--- a/revision.h
+++ b/revision.h
@@ -36,6 +36,7 @@
 	unsigned int	dense:1,
 			prune:1,
 			no_merges:1,
+			merges_only:1,
 			no_walk:1,
 			show_all:1,
 			remove_empty_trees:1,
diff --git a/run-command.c b/run-command.c
index eb2efc3..ff3d8e2 100644
--- a/run-command.c
+++ b/run-command.c
@@ -101,8 +101,8 @@
 		}
 
 		if (cmd->dir && chdir(cmd->dir))
-			die("exec %s: cd to %s failed (%s)", cmd->argv[0],
-			    cmd->dir, strerror(errno));
+			die_errno("exec '%s': cd to '%s' failed", cmd->argv[0],
+			    cmd->dir);
 		if (cmd->env) {
 			for (; *cmd->env; cmd->env++) {
 				if (strchr(*cmd->env, '='))
diff --git a/setup.c b/setup.c
index ebd60de..e3781b6 100644
--- a/setup.c
+++ b/setup.c
@@ -81,7 +81,7 @@
 	if (errno == ENOENT)
 		die("ambiguous argument '%s': unknown revision or path not in the working tree.\n"
 		    "Use '--' to separate paths from revisions", arg);
-	die("'%s': %s", arg, strerror(errno));
+	die_errno("failed to stat '%s'", arg);
 }
 
 /*
@@ -103,7 +103,7 @@
 		die("ambiguous argument '%s': both revision and filename\n"
 		    "Use '--' to separate filenames from revisions", arg);
 	if (errno != ENOENT && errno != ENOTDIR)
-		die("'%s': %s", arg, strerror(errno));
+		die_errno("failed to stat '%s'", arg);
 }
 
 const char **get_pathspec(const char *prefix, const char **pathspec)
@@ -257,7 +257,7 @@
 		return NULL;
 	fd = open(path, O_RDONLY);
 	if (fd < 0)
-		die("Error opening %s: %s", path, strerror(errno));
+		die_errno("Error opening '%s'", path);
 	buf = xmalloc(st.st_size + 1);
 	len = read_in_full(fd, buf, st.st_size);
 	close(fd);
@@ -327,7 +327,7 @@
 				return NULL;
 			set_git_dir(make_absolute_path(gitdirenv));
 			if (chdir(work_tree_env) < 0)
-				die ("Could not chdir to %s", work_tree_env);
+				die_errno ("Could not chdir to '%s'", work_tree_env);
 			strcat(buffer, "/");
 			return retval;
 		}
@@ -339,7 +339,7 @@
 	}
 
 	if (!getcwd(cwd, sizeof(cwd)-1))
-		die("Unable to read current working directory");
+		die_errno("Unable to read current working directory");
 
 	ceil_offset = longest_ancestor_length(cwd, env_ceiling_dirs);
 	if (ceil_offset < 0 && has_dos_drive_prefix(cwd))
@@ -382,14 +382,14 @@
 		if (offset <= ceil_offset) {
 			if (nongit_ok) {
 				if (chdir(cwd))
-					die("Cannot come back to cwd");
+					die_errno("Cannot come back to cwd");
 				*nongit_ok = 1;
 				return NULL;
 			}
 			die("Not a git repository (or any of the parent directories): %s", DEFAULT_GIT_DIR_ENVIRONMENT);
 		}
 		if (chdir(".."))
-			die("Cannot change to %s/..: %s", cwd, strerror(errno));
+			die_errno("Cannot change to '%s/..'", cwd);
 	}
 
 	inside_git_dir = 0;
@@ -493,10 +493,10 @@
 		static char buffer[PATH_MAX + 1];
 		char *rel;
 		if (retval && chdir(retval))
-			die ("Could not jump back into original cwd");
+			die_errno ("Could not jump back into original cwd");
 		rel = get_relative_cwd(buffer, PATH_MAX, get_git_work_tree());
 		if (rel && *rel && chdir(get_git_work_tree()))
-			die ("Could not jump to working directory");
+			die_errno ("Could not jump to working directory");
 		return rel && *rel ? strcat(rel, "/") : NULL;
 	}
 
diff --git a/sha1_file.c b/sha1_file.c
index 8f5fe62..4576ff7 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -2286,7 +2286,7 @@
 	if (fsync_object_files)
 		fsync_or_die(fd, "sha1 file");
 	if (close(fd) != 0)
-		die("error when closing sha1 file (%s)", strerror(errno));
+		die_errno("error when closing sha1 file");
 }
 
 /* Size of directory component, including the ending '/' */
diff --git a/shell.c b/shell.c
index b968be7..e4864e0 100644
--- a/shell.c
+++ b/shell.c
@@ -60,7 +60,7 @@
 	while (devnull_fd >= 0 && devnull_fd <= 2)
 		devnull_fd = dup(devnull_fd);
 	if (devnull_fd == -1)
-		die("opening /dev/null failed (%s)", strerror(errno));
+		die_errno("opening /dev/null failed");
 	close (devnull_fd);
 
 	/*
diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh
index 997002d..e504058 100755
--- a/t/t1502-rev-parse-parseopt.sh
+++ b/t/t1502-rev-parse-parseopt.sh
@@ -20,8 +20,7 @@
 
 EOF
 
-test_expect_success 'test --parseopt help output' '
-	git rev-parse --parseopt -- -h 2> output.err <<EOF
+cat > optionspec << EOF
 some-command [options] <args>...
 
 some-command does foo and bar!
@@ -37,7 +36,47 @@
 Extras
 extra1    line above used to cause a segfault but no longer does
 EOF
+
+test_expect_success 'test --parseopt help output' '
+	git rev-parse --parseopt -- -h 2> output.err < optionspec
 	test_cmp expect.err output.err
 '
 
+cat > expect <<EOF
+set -- --foo --bar 'ham' -- 'arg'
+EOF
+
+test_expect_success 'test --parseopt' '
+	git rev-parse --parseopt -- --foo --bar=ham arg < optionspec > output &&
+	test_cmp expect output
+'
+
+test_expect_success 'test --parseopt with mixed options and arguments' '
+	git rev-parse --parseopt -- --foo arg --bar=ham < optionspec > output &&
+	test_cmp expect output
+'
+
+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 &&
+	test_cmp expect output
+'
+
+test_expect_success 'test --parseopt --stop-at-non-option' '
+	git rev-parse --parseopt --stop-at-non-option -- --foo arg --bar=ham < optionspec > output &&
+	test_cmp expect output
+'
+
+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
+'
+
 test_done
diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh
index 7f62bfb..c5c29cc 100755
--- a/t/t3400-rebase.sh
+++ b/t/t3400-rebase.sh
@@ -54,8 +54,8 @@
      git rebase master'
 
 test_expect_success 'rebase against master twice' '
-     git rebase master 2>err &&
-     grep "Current branch my-topic-branch is up to date" err
+     git rebase master >out &&
+     grep "Current branch my-topic-branch is up to date" out
 '
 
 test_expect_success 'rebase against master twice with --force' '
@@ -65,14 +65,14 @@
 
 test_expect_success 'rebase against master twice from another branch' '
      git checkout my-topic-branch^ &&
-     git rebase master my-topic-branch 2>err &&
-     grep "Current branch my-topic-branch is up to date" err
+     git rebase master my-topic-branch >out &&
+     grep "Current branch my-topic-branch is up to date" out
 '
 
 test_expect_success 'rebase fast-forward to master' '
      git checkout my-topic-branch^ &&
-     git rebase my-topic-branch 2>err &&
-     grep "Fast-forwarded HEAD to my-topic-branch" err
+     git rebase my-topic-branch >out &&
+     grep "Fast-forwarded HEAD to my-topic-branch" out
 '
 
 test_expect_success \
@@ -126,4 +126,11 @@
      grep "Untracked working tree file .B. would be overwritten" output.err
 '
 
+test_expect_success 'rebase -q is quiet' '
+     rm B &&
+     git checkout -b quiet topic &&
+     git rebase -q master > output.out 2>&1 &&
+     test ! -s output.out
+'
+
 test_done
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index c32ff66..a973628 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -119,11 +119,11 @@
 EOF
 
 cat > expect2 << EOF
-<<<<<<< HEAD:file1
+<<<<<<< HEAD
 2
 =======
 3
->>>>>>> b7ca976... G:file1
+>>>>>>> b7ca976... G
 EOF
 
 test_expect_success 'stop on conflicting pick' '
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index 7484cbe..7a3fb67 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -177,4 +177,27 @@
 	test 0 = $(git stash list | wc -l)
 '
 
+test_expect_success 'apply -q is quiet' '
+	echo foo > file &&
+	git stash &&
+	git stash apply -q > output.out 2>&1 &&
+	test ! -s output.out
+'
+
+test_expect_success 'save -q is quiet' '
+	git stash save --quiet > output.out 2>&1 &&
+	test ! -s output.out
+'
+
+test_expect_success 'pop -q is quiet' '
+	git stash pop -q > output.out 2>&1 &&
+	test ! -s output.out
+'
+
+test_expect_success 'drop -q is quiet' '
+	git stash &&
+	git stash drop -q > output.out 2>&1 &&
+	test ! -s output.out
+'
+
 test_done
diff --git a/t/t4037-diff-r-t-dirs.sh b/t/t4037-diff-r-t-dirs.sh
new file mode 100755
index 0000000..f5ce3b2
--- /dev/null
+++ b/t/t4037-diff-r-t-dirs.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+test_description='diff -r -t shows directory additions and deletions'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+	mkdir dc dr dt &&
+	>dc/1 &&
+	>dr/2 &&
+	>dt/3 &&
+	>fc &&
+	>fr &&
+	>ft &&
+	git add . &&
+	test_tick &&
+	git commit -m initial &&
+
+	rm -fr dt dr ft fr &&
+	mkdir da ft &&
+	for p in dc/1 da/4 dt ft/5 fc
+	do
+		echo hello >$p || exit
+	done &&
+	git add -u &&
+	git add . &&
+	test_tick &&
+	git commit -m second
+'
+
+cat >expect <<\EOF
+A	da
+A	da/4
+M	dc
+M	dc/1
+D	dr
+D	dr/2
+A	dt
+D	dt
+D	dt/3
+M	fc
+D	fr
+D	ft
+A	ft
+A	ft/5
+EOF
+
+test_expect_success verify '
+	git diff-tree -r -t --name-status HEAD^ HEAD >actual &&
+	test_cmp expect actual
+'
+
+test_done
diff --git a/t/t4150-am.sh b/t/t4150-am.sh
index d6ebbae..a12bf84 100755
--- a/t/t4150-am.sh
+++ b/t/t4150-am.sh
@@ -180,6 +180,17 @@
 	test -z "$(git diff lorem)"
 '
 
+test_expect_success 'am -3 -q is quiet' '
+	git reset master2 --hard &&
+	sed -n -e "3,\$p" msg >file &&
+	head -n 9 msg >>file &&
+	git add file &&
+	test_tick &&
+	git commit -m "copied stuff" &&
+	git am -3 -q lorem-move.patch > output.out 2>&1 &&
+	! test -s output.out
+'
+
 test_expect_success 'am pauses on conflict' '
 	git checkout lorem2^^ &&
 	test_must_fail git am lorem-move.patch &&
@@ -305,4 +316,19 @@
 	test "z$result" = "z$(git rev-parse first^{tree})"
 '
 
+test_expect_success 'am newline in subject' '
+	git checkout first &&
+	test_tick &&
+	sed -e "s/second/second \\\n foo/" patch1 > patchnl &&
+	git am < patchnl > output.out 2>&1 &&
+	grep "^Applying: second \\\n foo$" output.out
+'
+
+test_expect_success 'am -q is quiet' '
+	git checkout first &&
+	test_tick &&
+	git am -q < patch1 > output.out 2>&1 &&
+	! test -s output.out
+'
+
 test_done
diff --git a/t/t6024-recursive-merge.sh b/t/t6024-recursive-merge.sh
index 129fa30..b3fbf65 100755
--- a/t/t6024-recursive-merge.sh
+++ b/t/t6024-recursive-merge.sh
@@ -65,18 +65,18 @@
 "
 
 cat > expect << EOF
-<<<<<<< HEAD:a1
+<<<<<<< HEAD
 F
 =======
 G
->>>>>>> G:a1
+>>>>>>> G
 EOF
 
 test_expect_success "result contains a conflict" "test_cmp expect a1"
 
 git ls-files --stage > out
 cat > expect << EOF
-100644 da056ce14a2241509897fa68bb2b3b6e6194ef9e 1	a1
+100644 439cc46de773d8a83c77799b7cc9191c128bfcff 1	a1
 100644 cf84443e49e1b366fac938711ddf4be2d4d1d9e9 2	a1
 100644 fd7923529855d0b274795ae3349c5e0438333979 3	a1
 EOF
@@ -93,8 +93,7 @@
 	git add binary-file &&
 	git commit -m binary2 &&
 	test_must_fail git merge F > merge.out 2> merge.err &&
-	grep "Cannot merge binary files: HEAD:binary-file vs. F:binary-file" \
-		merge.err
+	grep "Cannot merge binary files: binary-file (HEAD vs. F)" merge.err
 '
 
 test_expect_success 'mark rename/delete as unmerged' '
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index 4556cdd..1315bab 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh
@@ -563,8 +563,8 @@
 	hash7=$(git rev-parse --verify HEAD) &&
 	test "$hash7" = "$HASH7" &&
         git bisect skip &&
-	hash3=$(git rev-parse --verify HEAD) &&
-	test "$hash3" = "$HASH3"
+	para3=$(git rev-parse --verify HEAD) &&
+	test "$para3" = "$PARA_HASH3"
 '
 
 #
diff --git a/t/t7002-grep.sh b/t/t7002-grep.sh
index 7868af8..b13aa7e 100755
--- a/t/t7002-grep.sh
+++ b/t/t7002-grep.sh
@@ -8,6 +8,15 @@
 
 . ./test-lib.sh
 
+cat >hello.c <<EOF
+#include <stdio.h>
+int main(int argc, const char **argv)
+{
+	printf("Hello world.\n");
+	return 0;
+}
+EOF
+
 test_expect_success setup '
 	{
 		echo foo mmap bar
@@ -22,7 +31,7 @@
 	echo zzz > z &&
 	mkdir t &&
 	echo test >t/t &&
-	git add file w x y z t/t &&
+	git add file w x y z t/t hello.c &&
 	test_tick &&
 	git commit -m initial
 '
@@ -155,6 +164,28 @@
 	test_cmp expected actual
 '
 
+cat >expected <<EOF
+y:y yy
+--
+z:zzz
+EOF
+
+# Create 1024 file names that sort between "y" and "z" to make sure
+# the two files are handled by different calls to an external grep.
+# This depends on MAXARGS in builtin-grep.c being 1024 or less.
+c32="0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v"
+test_expect_success 'grep -C1, hunk mark between files' '
+	for a in $c32; do for b in $c32; do : >y-$a$b; done; done &&
+	git add y-?? &&
+	git grep -C1 "^[yz]" >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'grep -C1 --no-ext-grep, hunk mark between files' '
+	git grep -C1 --no-ext-grep "^[yz]" >actual &&
+	test_cmp expected actual
+'
+
 test_expect_success 'log grep setup' '
 	echo a >>file &&
 	test_tick &&
@@ -207,9 +238,45 @@
 test_expect_success 'grep with CE_VALID file' '
 	git update-index --assume-unchanged t/t &&
 	rm t/t &&
-	test "$(git grep --no-ext-grep t)" = "t/t:test" &&
+	test "$(git grep --no-ext-grep test)" = "t/t:test" &&
 	git update-index --no-assume-unchanged t/t &&
 	git checkout t/t
 '
 
+cat >expected <<EOF
+hello.c=#include <stdio.h>
+hello.c:	return 0;
+EOF
+
+test_expect_success 'grep -p with userdiff' '
+	git config diff.custom.funcname "^#" &&
+	echo "hello.c diff=custom" >.gitattributes &&
+	git grep -p return >actual &&
+	test_cmp expected actual
+'
+
+cat >expected <<EOF
+hello.c=int main(int argc, const char **argv)
+hello.c:	return 0;
+EOF
+
+test_expect_success 'grep -p' '
+	rm -f .gitattributes &&
+	git grep -p return >actual &&
+	test_cmp expected actual
+'
+
+cat >expected <<EOF
+hello.c-#include <stdio.h>
+hello.c=int main(int argc, const char **argv)
+hello.c-{
+hello.c-	printf("Hello world.\n");
+hello.c:	return 0;
+EOF
+
+test_expect_success 'grep -p -B5' '
+	git grep -p -B5 return >actual &&
+	test_cmp expected actual
+'
+
 test_done
diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh
index d539619..6275181 100755
--- a/t/t9500-gitweb-standalone-no-errors.sh
+++ b/t/t9500-gitweb-standalone-no-errors.sh
@@ -660,6 +660,7 @@
 
 \$feature{'blame'}{'override'} = 1;
 \$feature{'snapshot'}{'override'} = 1;
+\$feature{'avatar'}{'override'} = 1;
 EOF
 
 test_expect_success \
@@ -671,6 +672,7 @@
 	'config override: tree view, features disabled in repo config' \
 	'git config gitweb.blame no &&
 	 git config gitweb.snapshot none &&
+	 git config gitweb.avatar gravatar &&
 	 gitweb_run "p=.git;a=tree"'
 test_debug 'cat gitweb.log'
 
diff --git a/test-sha1.c b/test-sha1.c
index 9b98d07..80daba9 100644
--- a/test-sha1.c
+++ b/test-sha1.c
@@ -32,7 +32,7 @@
 			if (sz == 0)
 				break;
 			if (sz < 0)
-				die("test-sha1: %s", strerror(errno));
+				die_errno("test-sha1");
 			this_sz += sz;
 			cp += sz;
 			room -= sz;
diff --git a/transport.c b/transport.c
index b074067..de0d587 100644
--- a/transport.c
+++ b/transport.c
@@ -158,7 +158,7 @@
 
 	strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX"));
 	if (!mkdtemp(temp_dir.buf))
-		die ("Could not make temporary directory");
+		die_errno ("Could not make temporary directory");
 	temp_dir_len = temp_dir.len;
 
 	strbuf_addstr(&buf, rsync_url(transport->url));
@@ -321,7 +321,7 @@
 
 	strbuf_addstr(&temp_dir, git_path("rsync-refs-XXXXXX"));
 	if (!mkdtemp(temp_dir.buf))
-		die ("Could not make temporary directory");
+		die_errno ("Could not make temporary directory");
 	strbuf_addch(&temp_dir, '/');
 
 	if (flags & TRANSPORT_PUSH_ALL) {
diff --git a/tree-diff.c b/tree-diff.c
index edd8394..0459e54 100644
--- a/tree-diff.c
+++ b/tree-diff.c
@@ -239,6 +239,12 @@
 		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);
+			newbase[baselen + pathlen] = '/';
+		}
+
 		init_tree_desc(&inner, tree, size);
 		show_tree(opt, prefix, &inner, newbase, baselen + 1 + pathlen);
 
diff --git a/unpack-file.c b/unpack-file.c
index 75cd2f1..ac9cbf7 100644
--- a/unpack-file.c
+++ b/unpack-file.c
@@ -17,7 +17,7 @@
 	strcpy(path, ".merge_file_XXXXXX");
 	fd = xmkstemp(path);
 	if (write_in_full(fd, buf, size) != size)
-		die("unable to write temp-file");
+		die_errno("unable to write temp-file");
 	close(fd);
 	return path;
 }
diff --git a/upload-pack.c b/upload-pack.c
index edc7861..841ebb5 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -28,7 +28,7 @@
 
 static int multi_ack, nr_our_refs;
 static int use_thin_pack, use_ofs_delta, use_include_tag;
-static int no_progress;
+static int no_progress, daemon_mode;
 static struct object_array have_obj;
 static struct object_array want_obj;
 static unsigned int timeout;
@@ -521,6 +521,10 @@
 	}
 	if (debug_fd)
 		write_in_full(debug_fd, "#E\n", 3);
+
+	if (!use_sideband && daemon_mode)
+		no_progress = 1;
+
 	if (depth == 0 && shallows.nr == 0)
 		return;
 	if (depth > 0) {
@@ -630,6 +634,7 @@
 		}
 		if (!prefixcmp(arg, "--timeout=")) {
 			timeout = atoi(arg+10);
+			daemon_mode = 1;
 			continue;
 		}
 		if (!strcmp(arg, "--")) {
diff --git a/usage.c b/usage.c
index 820d09f..b6aea45 100644
--- a/usage.c
+++ b/usage.c
@@ -60,6 +60,34 @@
 	va_end(params);
 }
 
+void die_errno(const char *fmt, ...)
+{
+	va_list params;
+	char fmt_with_err[1024];
+	char str_error[256], *err;
+	int i, j;
+
+	err = strerror(errno);
+	for (i = j = 0; err[i] && j < sizeof(str_error) - 1; ) {
+		if ((str_error[j++] = err[i++]) != '%')
+			continue;
+		if (j < sizeof(str_error) - 1) {
+			str_error[j++] = '%';
+		} else {
+			/* No room to double the '%', so we overwrite it with
+			 * '\0' below */
+			j--;
+			break;
+		}
+	}
+	str_error[j] = 0;
+	snprintf(fmt_with_err, sizeof(fmt_with_err), "%s: %s", fmt, str_error);
+
+	va_start(params, fmt);
+	die_routine(fmt_with_err, params);
+	va_end(params);
+}
+
 int error(const char *err, ...)
 {
 	va_list params;
diff --git a/wrapper.c b/wrapper.c
index 7eb3218..c9be140 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -96,7 +96,7 @@
 		release_pack_memory(length, fd);
 		ret = mmap(start, length, prot, flags, fd, offset);
 		if (ret == MAP_FAILED)
-			die("Out of memory? mmap failed: %s", strerror(errno));
+			die_errno("Out of memory? mmap failed");
 	}
 	return ret;
 }
@@ -175,7 +175,7 @@
 {
 	int ret = dup(fd);
 	if (ret < 0)
-		die("dup failed: %s", strerror(errno));
+		die_errno("dup failed");
 	return ret;
 }
 
@@ -183,7 +183,7 @@
 {
 	FILE *stream = fdopen(fd, mode);
 	if (stream == NULL)
-		die("Out of memory? fdopen failed: %s", strerror(errno));
+		die_errno("Out of memory? fdopen failed");
 	return stream;
 }
 
@@ -193,7 +193,7 @@
 
 	fd = mkstemp(template);
 	if (fd < 0)
-		die("Unable to create temporary file: %s", strerror(errno));
+		die_errno("Unable to create temporary file");
 	return fd;
 }
 
diff --git a/write_or_die.c b/write_or_die.c
index 4c29255..d45b536 100644
--- a/write_or_die.c
+++ b/write_or_die.c
@@ -41,14 +41,14 @@
 		 */
 		if (errno == EPIPE || errno == EINVAL)
 			exit(0);
-		die("write failure on %s: %s", desc, strerror(errno));
+		die_errno("write failure on '%s'", desc);
 	}
 }
 
 void fsync_or_die(int fd, const char *msg)
 {
 	if (fsync(fd) < 0) {
-		die("%s: fsync error (%s)", msg, strerror(errno));
+		die_errno("fsync error on '%s'", msg);
 	}
 }
 
@@ -57,7 +57,7 @@
 	if (write_in_full(fd, buf, count) < 0) {
 		if (errno == EPIPE)
 			exit(0);
-		die("write error (%s)", strerror(errno));
+		die_errno("write error");
 	}
 }
 
diff --git a/xdiff-interface.c b/xdiff-interface.c
index b9b0db8..01f14fb 100644
--- a/xdiff-interface.c
+++ b/xdiff-interface.c
@@ -309,6 +309,21 @@
 	}
 }
 
+void xdiff_clear_find_func(xdemitconf_t *xecfg)
+{
+	if (xecfg->find_func) {
+		int i;
+		struct ff_regs *regs = xecfg->find_func_priv;
+
+		for (i = 0; i < regs->nr; i++)
+			regfree(&regs->array[i].re);
+		free(regs->array);
+		free(regs);
+		xecfg->find_func = NULL;
+		xecfg->find_func_priv = NULL;
+	}
+}
+
 int git_xmerge_style = -1;
 
 int git_xmerge_config(const char *var, const char *value, void *cb)
diff --git a/xdiff-interface.h b/xdiff-interface.h
index 7352b9a..55572c3 100644
--- a/xdiff-interface.h
+++ b/xdiff-interface.h
@@ -21,6 +21,7 @@
 int buffer_is_binary(const char *ptr, unsigned long size);
 
 extern void xdiff_set_find_func(xdemitconf_t *xecfg, const char *line, int cflags);
+extern void xdiff_clear_find_func(xdemitconf_t *xecfg);
 extern int git_xmerge_config(const char *var, const char *value, void *cb);
 extern int git_xmerge_style;