Merge branch 'cn/pull-rebase-message'

By Carlos Martín Nieto
* cn/pull-rebase-message:
  Make git-{pull,rebase} message without tracking information friendlier
diff --git a/Documentation/RelNotes/1.7.10.txt b/Documentation/RelNotes/1.7.10.txt
index 7813ea1..b966a8e 100644
--- a/Documentation/RelNotes/1.7.10.txt
+++ b/Documentation/RelNotes/1.7.10.txt
@@ -52,6 +52,9 @@
 
  * "git push" learned the "--prune" option, similar to "git fetch".
 
+ * "git symbolic-ref" learned the "--short" option to abbreviate the
+   refname it shows unambiguously.
+
  * "git tag --list" can be given "--points-at <object>" to limit its
    output to those that point at the given object.
 
@@ -64,6 +67,9 @@
    needed (including the ones that are not necessary for a specific
    task).
 
+ * Project search in "gitweb" shows the substring that matched in the
+   project name and description highlighted.
+
 Foreign Interface
 
  * Improved handling of views, labels and branches in git-p4 (in contrib).
@@ -112,39 +118,10 @@
 releases are contained in this release (see release notes to them for
 details).
 
- * "git branch --with $that" assumed incorrectly that the user will never
-   ask the question with nonsense value in $that.
-   (merge 6c41e97 cn/maint-branch-with-bad later to maint).
-
- * An invalid regular expression pattern given by an end user made
-   "gitweb" to return garbled response.
-   (merge 36612e4 jn/maint-gitweb-invalid-regexp later to maint).
-
- * "git rev-list --verify-objects -q" omitted the extra verification
-   it needs to do over "git rev-list --objects -q" by mistake.
-   (merge 9899372 nd/maint-verify-objects later to maint).
-
- * The bulk check-in codepath streamed contents that needs
-   smudge/clean filters without running them, instead of punting and
-   delegating to the codepath to run filters after slurping everything
-   to core.
-   (merge 4f22b10 jk/maint-avoid-streaming-filtered-contents later to maint).
-
- * When the filter driver exits before reading the content before the
-   main git process writes the contents to be filtered to the pipe to
-   it, the latter could be killed with SIGPIPE instead of ignoring
-   such an event as an error.
-   (merge 6424c2a jb/filter-ignore-sigpipe later to maint).
-
- * When a remote helper exits before reading the blank line from the
-   main git process to signal the end of commands, the latter could be
-   killed with SIGPIPE. Instead we should ignore such event as a
-   non-error.
-   (merge c34fe63 sp/smart-http-failure-to-push later to maint).
-
- * "git bundle create" produced a corrupt bundle file upon seeing
-   commits with excessively long subject line.
-   (merge 8a557bb tr/maint-bundle-long-subject later to maint).
+ * The code to synthesize the fake ancestor tree used by 3-way merge
+   fallback in "git am" was not prepared to read a patch created with
+   a non-standard -p<num> value.
+   (merge a61ba26 jc/am-3-nonstandard-popt later to maint).
 
  * "gitweb" used to drop warnings in the log file when "heads" view is
    accessed in a repository whose HEAD does not point at a valid
@@ -152,7 +129,7 @@
 
 ---
 exec >/var/tmp/1
-O=v1.7.9.2-358-g64d1544
+O=v1.7.9.2-383-gb8b5290
 echo O=$(git describe)
 git log --first-parent --oneline ^maint $O..
 echo
diff --git a/Documentation/RelNotes/1.7.9.3.txt b/Documentation/RelNotes/1.7.9.3.txt
index d7be177..91c6501 100644
--- a/Documentation/RelNotes/1.7.9.3.txt
+++ b/Documentation/RelNotes/1.7.9.3.txt
@@ -11,14 +11,41 @@
    to link the binary with -lintl even when libintl.h is missing from
    the system.
 
+ * When the filter driver exits before reading the content before the
+   main git process writes the contents to be filtered to the pipe to
+   it, the latter could be killed with SIGPIPE instead of ignoring
+   such an event as an error.
+
  * "git add --refresh <pathspec>" used to warn about unmerged paths
    outside the given pathspec.
 
+ * The bulk check-in codepath in "git add" streamed contents that
+   needs smudge/clean filters without running them, instead of punting
+   and delegating to the codepath to run filters after slurping
+   everything to core.
+
+ * "git branch --with $that" assumed incorrectly that the user will never
+   ask the question with nonsense value in $that.
+
+ * "git bundle create" produced a corrupt bundle file upon seeing
+   commits with excessively long subject line.
+
+ * When a remote helper exits before reading the blank line from the
+   main git process to signal the end of commands, the latter could be
+   killed with SIGPIPE. Instead we should ignore such event as a
+   non-error.
+
  * The commit log template given with "git merge --edit" did not have
    a short instructive text like what "git commit" gives.
 
+ * "git rev-list --verify-objects -q" omitted the extra verification
+   it needs to do over "git rev-list --objects -q" by mistake.
+
  * "gitweb" used to drop warnings in the log file when "heads" view is
    accessed in a repository whose HEAD does not point at a valid
    branch.
 
+ * An invalid regular expression pattern given by an end user made
+   "gitweb" to return garbled response.
+
 Also contains minor fixes and documentation updates.
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 5367ba9..c081657 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -1275,9 +1275,10 @@
 	This is the default.
 
 http.proxy::
-	Override the HTTP proxy, normally configured using the 'http_proxy'
-	environment variable (see linkgit:curl[1]).  This can be overridden
-	on a per-remote basis; see remote.<name>.proxy
+	Override the HTTP proxy, normally configured using the 'http_proxy',
+	'https_proxy', and 'all_proxy' environment variables (see
+	`curl(1)`).  This can be overridden on a per-remote basis; see
+	remote.<name>.proxy
 
 http.cookiefile::
 	File containing previously stored cookie lines which should be used
diff --git a/Documentation/diff-config.txt b/Documentation/diff-config.txt
index 1aed79e..6aa1be0 100644
--- a/Documentation/diff-config.txt
+++ b/Documentation/diff-config.txt
@@ -52,6 +52,10 @@
 and accumulating child directory counts in the parent directories:
 `files,10,cumulative`.
 
+diff.statGraphWidth::
+	Limit the width of the graph part in --stat output. If set, applies
+	to all commands generating --stat outuput except format-patch.
+
 diff.external::
 	If this config variable is set, diff generation is not
 	performed using the internal diff machinery, but using the
diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
index 9f7cba2..7d4566f 100644
--- a/Documentation/diff-options.txt
+++ b/Documentation/diff-options.txt
@@ -52,14 +52,23 @@
 --patience::
 	Generate a diff using the "patience diff" algorithm.
 
+--histogram::
+	Generate a diff using the "histogram diff" algorithm.
+
 --stat[=<width>[,<name-width>[,<count>]]]::
-	Generate a diffstat.  You can override the default
-	output width for 80-column terminal by `--stat=<width>`.
-	The width of the filename part can be controlled by
-	giving another width to it separated by a comma.
+	Generate a diffstat. By default, as much space as necessary
+	will be used for the filename part, and the rest for the graph
+	part. Maximum width defaults to terminal width, or 80 columns
+	if not connected to a terminal, and can be overriden by
+	`<width>`. The width of the filename part can be limited by
+	giving another width `<name-width>` after a comma. The width
+	of the graph part can be limited by using
+	`--stat-graph-width=<width>` (affects all commands generating
+	a stat graph) or by setting `diff.statGraphWidth=<width>`
+	(does not affect `git format-patch`).
 	By giving a third parameter `<count>`, you can limit the
-	output to the first `<count>` lines, followed by
-	`...` if there are more.
+	output to the first `<count>` lines, followed by `...` if
+	there are more.
 +
 These parameters can also be set individually with `--stat-width=<width>`,
 `--stat-name-width=<name-width>` and `--stat-count=<count>`.
diff --git a/Documentation/git-fsck.txt b/Documentation/git-fsck.txt
index 47e2f19..bbb25da 100644
--- a/Documentation/git-fsck.txt
+++ b/Documentation/git-fsck.txt
@@ -33,7 +33,7 @@
 --dangling::
 --no-dangling::
 	Print objects that exist but that are never 'directly' used (default).
-	`--no-dangling` can be used to squech this information from the output.
+	`--no-dangling` can be used to omit this information from the output.
 
 --root::
 	Report root nodes.
diff --git a/Documentation/git-symbolic-ref.txt b/Documentation/git-symbolic-ref.txt
index a45d4c4..981d3a8 100644
--- a/Documentation/git-symbolic-ref.txt
+++ b/Documentation/git-symbolic-ref.txt
@@ -8,7 +8,8 @@
 SYNOPSIS
 --------
 [verse]
-'git symbolic-ref' [-q] [-m <reason>] <name> [<ref>]
+'git symbolic-ref' [-m <reason>] <name> <ref>
+'git symbolic-ref' [-q] [--short] <name>
 
 DESCRIPTION
 -----------
@@ -33,6 +34,10 @@
 	symbolic ref but a detached HEAD; instead exit with
 	non-zero status silently.
 
+--short::
+	When showing the value of <name> as a symbolic ref, try to shorten the
+	value, e.g. from `refs/heads/master` to `master`.
+
 -m::
 	Update the reflog for <name> with <reason>.  This is valid only
 	when creating or updating a symbolic ref.
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 22fadeb..b257d80 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -44,9 +44,10 @@
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
-* link:v1.7.9.2/git.html[documentation for release 1.7.9.2]
+* link:v1.7.9.3/git.html[documentation for release 1.7.9.3]
 
 * release notes for
+  link:RelNotes/1.7.9.3.txt[1.7.9.3],
   link:RelNotes/1.7.9.2.txt[1.7.9.2],
   link:RelNotes/1.7.9.1.txt[1.7.9.1],
   link:RelNotes/1.7.9.txt[1.7.9].
diff --git a/builtin/diff.c b/builtin/diff.c
index 387afa7..424c815 100644
--- a/builtin/diff.c
+++ b/builtin/diff.c
@@ -285,6 +285,10 @@
 	/* Otherwise, we are doing the usual "git" diff */
 	rev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index;
 
+	/* Scale to real terminal size and respect statGraphWidth config */
+	rev.diffopt.stat_width = -1;
+	rev.diffopt.stat_graph_width = -1;
+
 	/* Default to let external and textconv be used */
 	DIFF_OPT_SET(&rev.diffopt, ALLOW_EXTERNAL);
 	DIFF_OPT_SET(&rev.diffopt, ALLOW_TEXTCONV);
diff --git a/builtin/log.c b/builtin/log.c
index 7d1f6f8..8a47012 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -77,6 +77,8 @@
 		get_commit_format(fmt_pretty, rev);
 	rev->verbose_header = 1;
 	DIFF_OPT_SET(&rev->diffopt, RECURSIVE);
+	rev->diffopt.stat_width = -1; /* use full terminal width */
+	rev->diffopt.stat_graph_width = -1; /* respect statGraphWidth config */
 	rev->abbrev_commit = default_abbrev_commit;
 	rev->show_root_diff = default_show_root;
 	rev->subject_prefix = fmt_patch_subject_prefix;
@@ -447,6 +449,8 @@
 	rev.diff = 1;
 	rev.always_show_header = 1;
 	rev.no_walk = 1;
+	rev.diffopt.stat_width = -1; 	/* Scale to real terminal size */
+
 	memset(&opt, 0, sizeof(opt));
 	opt.def = "HEAD";
 	opt.tweak = show_rev_tweak_rev;
diff --git a/builtin/merge.c b/builtin/merge.c
index d3e1e8d..cb8f149 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -399,6 +399,8 @@
 	if (new_head && show_diffstat) {
 		struct diff_options opts;
 		diff_setup(&opts);
+		opts.stat_width = -1; /* use full terminal width */
+		opts.stat_graph_width = -1; /* respect statGraphWidth config */
 		opts.output_format |=
 			DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
 		opts.detect_rename = DIFF_DETECT_RENAME;
diff --git a/builtin/symbolic-ref.c b/builtin/symbolic-ref.c
index 2ef5962..801d62e 100644
--- a/builtin/symbolic-ref.c
+++ b/builtin/symbolic-ref.c
@@ -8,13 +8,15 @@
 	NULL
 };
 
+static int shorten;
+
 static void check_symref(const char *HEAD, int quiet)
 {
 	unsigned char sha1[20];
 	int flag;
-	const char *refs_heads_master = resolve_ref_unsafe(HEAD, sha1, 0, &flag);
+	const char *refname = resolve_ref_unsafe(HEAD, sha1, 0, &flag);
 
-	if (!refs_heads_master)
+	if (!refname)
 		die("No such ref: %s", HEAD);
 	else if (!(flag & REF_ISSYMREF)) {
 		if (!quiet)
@@ -22,7 +24,9 @@
 		else
 			exit(1);
 	}
-	puts(refs_heads_master);
+	if (shorten)
+		refname = shorten_unambiguous_ref(refname, 0);
+	puts(refname);
 }
 
 int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
@@ -32,6 +36,7 @@
 	struct option options[] = {
 		OPT__QUIET(&quiet,
 			"suppress error message for non-symbolic (detached) refs"),
+		OPT_BOOL(0, "short", &shorten, "shorten ref output"),
 		OPT_STRING('m', NULL, &msg, "reason", "reason of the update"),
 		OPT_END(),
 	};
diff --git a/bundle.c b/bundle.c
index 7a760db..d9cfd90 100644
--- a/bundle.c
+++ b/bundle.c
@@ -273,7 +273,7 @@
 			if (!get_sha1_hex(buf.buf + 1, sha1)) {
 				struct object *object = parse_object(sha1);
 				object->flags |= UNINTERESTING;
-				add_pending_object(&revs, object, buf.buf);
+				add_pending_object(&revs, object, xstrdup(buf.buf));
 			}
 		} else if (!get_sha1_hex(buf.buf, sha1)) {
 			struct object *object = parse_object(sha1);
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 33f0e4d..fba076d 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -2092,6 +2092,7 @@
 		core.whitespace
 		core.worktree
 		diff.autorefreshindex
+		diff.statGraphWidth
 		diff.external
 		diff.ignoreSubmodules
 		diff.mnemonicprefix
diff --git a/diff.c b/diff.c
index a1c06b5..f47bffa 100644
--- a/diff.c
+++ b/diff.c
@@ -31,6 +31,7 @@
 int diff_auto_refresh_index = 1;
 static int diff_mnemonic_prefix;
 static int diff_no_prefix;
+static int diff_stat_graph_width;
 static int diff_dirstat_permille_default = 30;
 static struct diff_options default_diff_options;
 
@@ -156,6 +157,10 @@
 		diff_no_prefix = git_config_bool(var, value);
 		return 0;
 	}
+	if (!strcmp(var, "diff.statgraphwidth")) {
+		diff_stat_graph_width = git_config_int(var, value);
+		return 0;
+	}
 	if (!strcmp(var, "diff.external"))
 		return git_config_string(&external_diff_cmd_cfg, var, value);
 	if (!strcmp(var, "diff.wordregex"))
@@ -1375,7 +1380,7 @@
 	int i, len, add, del, adds = 0, dels = 0;
 	uintmax_t max_change = 0, max_len = 0;
 	int total_files = data->nr;
-	int width, name_width, count;
+	int width, name_width, graph_width, number_width = 4, count;
 	const char *reset, *add_c, *del_c;
 	const char *line_prefix = "";
 	int extra_shown = 0;
@@ -1389,25 +1394,15 @@
 		line_prefix = msg->buf;
 	}
 
-	width = options->stat_width ? options->stat_width : 80;
-	name_width = options->stat_name_width ? options->stat_name_width : 50;
 	count = options->stat_count ? options->stat_count : data->nr;
 
-	/* Sanity: give at least 5 columns to the graph,
-	 * but leave at least 10 columns for the name.
-	 */
-	if (width < 25)
-		width = 25;
-	if (name_width < 10)
-		name_width = 10;
-	else if (width < name_width + 15)
-		name_width = width - 15;
-
-	/* Find the longest filename and max number of changes */
 	reset = diff_get_color_opt(options, DIFF_RESET);
 	add_c = diff_get_color_opt(options, DIFF_FILE_NEW);
 	del_c = diff_get_color_opt(options, DIFF_FILE_OLD);
 
+	/*
+	 * Find the longest filename and max number of changes
+	 */
 	for (i = 0; (i < count) && (i < data->nr); i++) {
 		struct diffstat_file *file = data->files[i];
 		uintmax_t change = file->added + file->deleted;
@@ -1428,19 +1423,72 @@
 	}
 	count = i; /* min(count, data->nr) */
 
-	/* Compute the width of the graph part;
-	 * 10 is for one blank at the beginning of the line plus
-	 * " | count " between the name and the graph.
+	/*
+	 * We have width = stat_width or term_columns() columns total.
+	 * We want a maximum of min(max_len, stat_name_width) for the name part.
+	 * We want a maximum of min(max_change, stat_graph_width) for the +- part.
+	 * We also need 1 for " " and 4 + decimal_width(max_change)
+	 * for " | NNNN " and one the empty column at the end, altogether
+	 * 6 + decimal_width(max_change).
 	 *
-	 * From here on, name_width is the width of the name area,
-	 * and width is the width of the graph area.
+	 * If there's not enough space, we will use the smaller of
+	 * stat_name_width (if set) and 5/8*width for the filename,
+	 * and the rest for constant elements + graph part, but no more
+	 * than stat_graph_width for the graph part.
+	 * (5/8 gives 50 for filename and 30 for the constant parts + graph
+	 * for the standard terminal size).
+	 *
+	 * In other words: stat_width limits the maximum width, and
+	 * stat_name_width fixes the maximum width of the filename,
+	 * and is also used to divide available columns if there
+	 * aren't enough.
 	 */
-	name_width = (name_width < max_len) ? name_width : max_len;
-	if (width < (name_width + 10) + max_change)
-		width = width - (name_width + 10);
-	else
-		width = max_change;
 
+	if (options->stat_width == -1)
+		width = term_columns();
+	else
+		width = options->stat_width ? options->stat_width : 80;
+
+	if (options->stat_graph_width == -1)
+		options->stat_graph_width = diff_stat_graph_width;
+
+	/*
+	 * Guarantee 3/8*16==6 for the graph part
+	 * and 5/8*16==10 for the filename part
+	 */
+	if (width < 16 + 6 + number_width)
+		width = 16 + 6 + number_width;
+
+	/*
+	 * First assign sizes that are wanted, ignoring available width.
+	 */
+	graph_width = (options->stat_graph_width &&
+		       options->stat_graph_width < max_change) ?
+		options->stat_graph_width : max_change;
+	name_width = (options->stat_name_width > 0 &&
+		      options->stat_name_width < max_len) ?
+		options->stat_name_width : max_len;
+
+	/*
+	 * Adjust adjustable widths not to exceed maximum width
+	 */
+	if (name_width + number_width + 6 + graph_width > width) {
+		if (graph_width > width * 3/8 - number_width - 6)
+			graph_width = width * 3/8 - number_width - 6;
+		if (options->stat_graph_width &&
+		    graph_width > options->stat_graph_width)
+			graph_width = options->stat_graph_width;
+		if (name_width > width - number_width - 6 - graph_width)
+			name_width = width - number_width - 6 - graph_width;
+		else
+			graph_width = width - number_width - 6 - name_width;
+	}
+
+	/*
+	 * From here name_width is the width of the name area,
+	 * and graph_width is the width of the graph area.
+	 * max_change is used to scale graph properly.
+	 */
 	for (i = 0; i < count; i++) {
 		const char *prefix = "";
 		char *name = data->files[i]->print_name;
@@ -1496,18 +1544,18 @@
 		adds += add;
 		dels += del;
 
-		if (width <= max_change) {
+		if (graph_width <= max_change) {
 			int total = add + del;
 
-			total = scale_linear(add + del, width, max_change);
+			total = scale_linear(add + del, graph_width, max_change);
 			if (total < 2 && add && del)
 				/* width >= 2 due to the sanity check */
 				total = 2;
 			if (add < del) {
-				add = scale_linear(add, width, max_change);
+				add = scale_linear(add, graph_width, max_change);
 				del = total - add;
 			} else {
-				del = scale_linear(del, width, max_change);
+				del = scale_linear(del, graph_width, max_change);
 				add = total - del;
 			}
 		}
@@ -3299,6 +3347,7 @@
 	char *end;
 	int width = options->stat_width;
 	int name_width = options->stat_name_width;
+	int graph_width = options->stat_graph_width;
 	int count = options->stat_count;
 	int argcount = 1;
 
@@ -3327,6 +3376,16 @@
 				name_width = strtoul(av[1], &end, 10);
 				argcount = 2;
 			}
+		} else if (!prefixcmp(arg, "-graph-width")) {
+			arg += strlen("-graph-width");
+			if (*arg == '=')
+				graph_width = strtoul(arg + 1, &end, 10);
+			else if (!*arg && !av[1])
+				die("Option '--stat-graph-width' requires a value");
+			else if (!*arg) {
+				graph_width = strtoul(av[1], &end, 10);
+				argcount = 2;
+			}
 		} else if (!prefixcmp(arg, "-count")) {
 			arg += strlen("-count");
 			if (*arg == '=')
@@ -3352,6 +3411,7 @@
 		return 0;
 	options->output_format |= DIFF_FORMAT_DIFFSTAT;
 	options->stat_name_width = name_width;
+	options->stat_graph_width = graph_width;
 	options->stat_width = width;
 	options->stat_count = count;
 	return argcount;
diff --git a/diff.h b/diff.h
index 7af5f1e..e6a782c 100644
--- a/diff.h
+++ b/diff.h
@@ -129,6 +129,7 @@
 
 	int stat_width;
 	int stat_name_width;
+	int stat_graph_width;
 	int stat_count;
 	const char *word_regex;
 	enum diff_words_type word_diff;
diff --git a/fast-import.c b/fast-import.c
index 6cd19e5..c1486ca 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -2712,7 +2712,7 @@
 	/* Obtain the new tag name from the rest of our command */
 	sp = strchr(command_buf.buf, ' ') + 1;
 	t = pool_alloc(sizeof(struct tag));
-	t->next_tag = NULL;
+	memset(t, 0, sizeof(struct tag));
 	t->name = pool_strdup(sp);
 	if (last_tag)
 		last_tag->next_tag = t;
diff --git a/git-am.sh b/git-am.sh
index 906f91f..0bd290b 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -128,15 +128,18 @@
     mkdir "$dotest/patch-merge-tmp-dir"
 
     # First see if the patch records the index info that we can use.
-    git apply --build-fake-ancestor "$dotest/patch-merge-tmp-index" \
-	"$dotest/patch" &&
+    cmd="git apply $git_apply_opt --build-fake-ancestor" &&
+    cmd="$cmd "'"$dotest/patch-merge-tmp-index" "$dotest/patch"' &&
+    eval "$cmd" &&
     GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \
     git write-tree >"$dotest/patch-merge-base+" ||
     cannot_fallback "$(gettext "Repository lacks necessary blobs to fall back on 3-way merge.")"
 
     say Using index info to reconstruct a base tree...
-    if GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \
-	git apply --cached <"$dotest/patch"
+
+    cmd='GIT_INDEX_FILE="$dotest/patch-merge-tmp-index"'
+    cmd="$cmd git apply --cached $git_apply_opt"' <"$dotest/patch"'
+    if eval "$cmd"
     then
 	mv "$dotest/patch-merge-base+" "$dotest/patch-merge-base"
 	mv "$dotest/patch-merge-tmp-index" "$dotest/patch-merge-index"
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 7729ed2..cd98888 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -1724,6 +1724,88 @@
 	}
 }
 
+# Highlight selected fragments of string, using given CSS class,
+# and escape HTML.  It is assumed that fragments do not overlap.
+# Regions are passed as list of pairs (array references).
+#
+# Example: esc_html_hl_regions("foobar", "mark", [ 0, 3 ]) returns
+# '<span class="mark">foo</span>bar'
+sub esc_html_hl_regions {
+	my ($str, $css_class, @sel) = @_;
+	return esc_html($str) unless @sel;
+
+	my $out = '';
+	my $pos = 0;
+
+	for my $s (@sel) {
+		$out .= esc_html(substr($str, $pos, $s->[0] - $pos))
+			if ($s->[0] - $pos > 0);
+		$out .= $cgi->span({-class => $css_class},
+		                   esc_html(substr($str, $s->[0], $s->[1] - $s->[0])));
+
+		$pos = $s->[1];
+	}
+	$out .= esc_html(substr($str, $pos))
+		if ($pos < length($str));
+
+	return $out;
+}
+
+# return positions of beginning and end of each match
+sub matchpos_list {
+	my ($str, $regexp) = @_;
+	return unless (defined $str && defined $regexp);
+
+	my @matches;
+	while ($str =~ /$regexp/g) {
+		push @matches, [$-[0], $+[0]];
+	}
+	return @matches;
+}
+
+# highlight match (if any), and escape HTML
+sub esc_html_match_hl {
+	my ($str, $regexp) = @_;
+	return esc_html($str) unless defined $regexp;
+
+	my @matches = matchpos_list($str, $regexp);
+	return esc_html($str) unless @matches;
+
+	return esc_html_hl_regions($str, 'match', @matches);
+}
+
+
+# highlight match (if any) of shortened string, and escape HTML
+sub esc_html_match_hl_chopped {
+	my ($str, $chopped, $regexp) = @_;
+	return esc_html_match_hl($str, $regexp) unless defined $chopped;
+
+	my @matches = matchpos_list($str, $regexp);
+	return esc_html($chopped) unless @matches;
+
+	# filter matches so that we mark chopped string
+	my $tail = "... "; # see chop_str
+	unless ($chopped =~ s/\Q$tail\E$//) {
+		$tail = '';
+	}
+	my $chop_len = length($chopped);
+	my $tail_len = length($tail);
+	my @filtered;
+
+	for my $m (@matches) {
+		if ($m->[0] > $chop_len) {
+			push @filtered, [ $chop_len, $chop_len + $tail_len ] if ($tail_len > 0);
+			last;
+		} elsif ($m->[1] > $chop_len) {
+			push @filtered, [ $m->[0], $chop_len + $tail_len ];
+			last;
+		}
+		push @filtered, $m;
+	}
+
+	return esc_html_hl_regions($chopped . $tail, 'match', @filtered);
+}
+
 ## ----------------------------------------------------------------------
 ## functions returning short strings
 
@@ -5174,7 +5256,7 @@
 # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
 
 sub git_project_search_form {
-	my ($searchtext, $search_use_regexp);
+	my ($searchtext, $search_use_regexp) = @_;
 
 	my $limit = '';
 	if ($project_filter) {
@@ -5368,10 +5450,17 @@
 			print "</td>\n";
 		}
 		print "<td>" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"),
-		                        -class => "list"}, esc_html($pr->{'path'})) . "</td>\n" .
+		                        -class => "list"},
+		                       esc_html_match_hl($pr->{'path'}, $search_regexp)) .
+		      "</td>\n" .
 		      "<td>" . $cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary"),
-		                        -class => "list", -title => $pr->{'descr_long'}},
-		                        esc_html($pr->{'descr'})) . "</td>\n" .
+		                        -class => "list",
+		                        -title => $pr->{'descr_long'}},
+		                        $search_regexp
+		                        ? esc_html_match_hl_chopped($pr->{'descr_long'},
+		                                                    $pr->{'descr'}, $search_regexp)
+		                        : esc_html($pr->{'descr'})) .
+		      "</td>\n" .
 		      "<td><i>" . chop_and_escape_str($pr->{'owner'}, 15) . "</i></td>\n";
 		print "<td class=\"". age_class($pr->{'age'}) . "\">" .
 		      (defined $pr->{'age_string'} ? $pr->{'age_string'} : "No commits") . "</td>\n" .
diff --git a/http.c b/http.c
index 0ffd79c..8ac8eb6 100644
--- a/http.c
+++ b/http.c
@@ -295,8 +295,10 @@
 	if (curl_ftp_no_epsv)
 		curl_easy_setopt(result, CURLOPT_FTP_USE_EPSV, 0);
 
-	if (curl_http_proxy)
+	if (curl_http_proxy) {
 		curl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);
+		curl_easy_setopt(result, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
+	}
 
 	return result;
 }
diff --git a/parse-options.c b/parse-options.c
index 1908996..850cfa7 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -393,6 +393,8 @@
 			case -1:
 				return parse_options_usage(ctx, usagestr, options, 1);
 			case -2:
+				if (ctx->opt)
+					check_typos(arg + 1, options);
 				goto unknown;
 			}
 			if (ctx->opt)
diff --git a/t/perf/p4000-diff-algorithms.sh b/t/perf/p4000-diff-algorithms.sh
new file mode 100755
index 0000000..d6e505c
--- /dev/null
+++ b/t/perf/p4000-diff-algorithms.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+test_description="Tests diff generation performance"
+
+. ./perf-lib.sh
+
+test_perf_default_repo
+
+test_perf 'log -3000 (baseline)' '
+	git log -1000 >/dev/null
+'
+
+test_perf 'log --raw -3000 (tree-only)' '
+	git log --raw -3000 >/dev/null
+'
+
+test_perf 'log -p -3000 (Myers)' '
+	git log -p -3000 >/dev/null
+'
+
+test_perf 'log -p -3000 --histogram' '
+	git log -p -3000 --histogram >/dev/null
+'
+
+test_perf 'log -p -3000 --patience' '
+	git log -p -3000 --patience >/dev/null
+'
+
+test_done
diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh
index f4e8f43..ccb5435 100755
--- a/t/t0000-basic.sh
+++ b/t/t0000-basic.sh
@@ -34,69 +34,69 @@
 # git init has been done in an empty repository.
 # make sure it is empty.
 
-find .git/objects -type f -print >should-be-empty
-test_expect_success \
-    '.git/objects should be empty after git init in an empty repo.' \
-    'cmp -s /dev/null should-be-empty'
+test_expect_success '.git/objects should be empty after git init in an empty repo' '
+	find .git/objects -type f -print >should-be-empty &&
+	test_line_count = 0 should-be-empty
+'
 
 # also it should have 2 subdirectories; no fan-out anymore, pack, and info.
 # 3 is counting "objects" itself
-find .git/objects -type d -print >full-of-directories
-test_expect_success \
-    '.git/objects should have 3 subdirectories.' \
-    'test $(wc -l < full-of-directories) = 3'
+test_expect_success '.git/objects should have 3 subdirectories' '
+	find .git/objects -type d -print >full-of-directories &&
+	test_line_count = 3 full-of-directories
+'
 
 ################################################################
 # Test harness
 test_expect_success 'success is reported like this' '
-    :
+	:
 '
 test_expect_failure 'pretend we have a known breakage' '
-    false
+	false
 '
 
 test_expect_success 'pretend we have fixed a known breakage (run in sub test-lib)' "
-    mkdir passing-todo &&
-    (cd passing-todo &&
-    cat >passing-todo.sh <<EOF &&
-#!$SHELL_PATH
+	mkdir passing-todo &&
+	(cd passing-todo &&
+	cat >passing-todo.sh <<-EOF &&
+	#!$SHELL_PATH
 
-test_description='A passing TODO test
+	test_description='A passing TODO test
 
-This is run in a sub test-lib so that we do not get incorrect passing
-metrics
-'
+	This is run in a sub test-lib so that we do not get incorrect
+	passing metrics
+	'
 
-# Point to the t/test-lib.sh, which isn't in ../ as usual
-TEST_DIRECTORY=\"$TEST_DIRECTORY\"
-. \"\$TEST_DIRECTORY\"/test-lib.sh
+	# Point to the t/test-lib.sh, which isn't in ../ as usual
+	TEST_DIRECTORY=\"$TEST_DIRECTORY\"
+	. \"\$TEST_DIRECTORY\"/test-lib.sh
 
-test_expect_failure 'pretend we have fixed a known breakage' '
-    :
-'
+	test_expect_failure 'pretend we have fixed a known breakage' '
+		:
+	'
 
-test_done
-EOF
-    chmod +x passing-todo.sh &&
-    ./passing-todo.sh >out 2>err &&
-    ! test -s err &&
-sed -e 's/^> //' >expect <<EOF &&
-> ok 1 - pretend we have fixed a known breakage # TODO known breakage
-> # fixed 1 known breakage(s)
-> # passed all 1 test(s)
-> 1..1
-EOF
-    test_cmp expect out)
+	test_done
+	EOF
+	chmod +x passing-todo.sh &&
+	./passing-todo.sh >out 2>err &&
+	! test -s err &&
+	sed -e 's/^> //' >expect <<-\\EOF &&
+	> ok 1 - pretend we have fixed a known breakage # TODO known breakage
+	> # fixed 1 known breakage(s)
+	> # passed all 1 test(s)
+	> 1..1
+	EOF
+	test_cmp expect out)
 "
 test_set_prereq HAVEIT
 haveit=no
 test_expect_success HAVEIT 'test runs if prerequisite is satisfied' '
-    test_have_prereq HAVEIT &&
-    haveit=yes
+	test_have_prereq HAVEIT &&
+	haveit=yes
 '
 donthaveit=yes
 test_expect_success DONTHAVEIT 'unmet prerequisite causes test to be skipped' '
-    donthaveit=no
+	donthaveit=no
 '
 if test $haveit$donthaveit != yesyes
 then
@@ -107,17 +107,17 @@
 test_set_prereq HAVETHIS
 haveit=no
 test_expect_success HAVETHIS,HAVEIT 'test runs if prerequisites are satisfied' '
-    test_have_prereq HAVEIT &&
-    test_have_prereq HAVETHIS &&
-    haveit=yes
+	test_have_prereq HAVEIT &&
+	test_have_prereq HAVETHIS &&
+	haveit=yes
 '
 donthaveit=yes
 test_expect_success HAVEIT,DONTHAVEIT 'unmet prerequisites causes test to be skipped' '
-    donthaveit=no
+	donthaveit=no
 '
 donthaveiteither=yes
 test_expect_success DONTHAVEIT,HAVEIT 'unmet prerequisites causes test to be skipped' '
-    donthaveiteither=no
+	donthaveiteither=no
 '
 if test $haveit$donthaveit$donthaveiteither != yesyesyes
 then
@@ -127,7 +127,7 @@
 
 clean=no
 test_expect_success 'tests clean up after themselves' '
-    test_when_finished clean=yes
+	test_when_finished clean=yes
 '
 
 if test $clean != yes
@@ -137,106 +137,100 @@
 fi
 
 test_expect_success 'tests clean up even on failures' "
-    mkdir failing-cleanup &&
-    (cd failing-cleanup &&
-    cat >failing-cleanup.sh <<EOF &&
-#!$SHELL_PATH
+	mkdir failing-cleanup &&
+	(
+	cd failing-cleanup &&
 
-test_description='Failing tests with cleanup commands'
+	cat >failing-cleanup.sh <<-EOF &&
+	#!$SHELL_PATH
 
-# Point to the t/test-lib.sh, which isn't in ../ as usual
-TEST_DIRECTORY=\"$TEST_DIRECTORY\"
-. \"\$TEST_DIRECTORY\"/test-lib.sh
+	test_description='Failing tests with cleanup commands'
 
-test_expect_success 'tests clean up even after a failure' '
-    touch clean-after-failure &&
-    test_when_finished rm clean-after-failure &&
-    (exit 1)
-'
+	# Point to the t/test-lib.sh, which isn't in ../ as usual
+	TEST_DIRECTORY=\"$TEST_DIRECTORY\"
+	. \"\$TEST_DIRECTORY\"/test-lib.sh
 
-test_expect_success 'failure to clean up causes the test to fail' '
-    test_when_finished \"(exit 2)\"
-'
+	test_expect_success 'tests clean up even after a failure' '
+		touch clean-after-failure &&
+		test_when_finished rm clean-after-failure &&
+		(exit 1)
+	'
+	test_expect_success 'failure to clean up causes the test to fail' '
+		test_when_finished \"(exit 2)\"
+	'
+	test_done
 
-test_done
-EOF
-    chmod +x failing-cleanup.sh &&
-    test_must_fail ./failing-cleanup.sh >out 2>err &&
-    ! test -s err &&
-    ! test -f \"trash directory.failing-cleanup/clean-after-failure\" &&
-sed -e 's/Z$//' -e 's/^> //' >expect <<\EOF &&
-> not ok - 1 tests clean up even after a failure
-> #	Z
-> #	    touch clean-after-failure &&
-> #	    test_when_finished rm clean-after-failure &&
-> #	    (exit 1)
-> #	Z
-> not ok - 2 failure to clean up causes the test to fail
-> #	Z
-> #	    test_when_finished \"(exit 2)\"
-> #	Z
-> # failed 2 among 2 test(s)
-> 1..2
-EOF
-    test_cmp expect out)
+	EOF
+
+	chmod +x failing-cleanup.sh &&
+	test_must_fail ./failing-cleanup.sh >out 2>err &&
+	! test -s err &&
+	! test -f \"trash directory.failing-cleanup/clean-after-failure\" &&
+	sed -e 's/Z$//' -e 's/^> //' >expect <<-\\EOF &&
+	> not ok - 1 tests clean up even after a failure
+	> #	Z
+	> #	touch clean-after-failure &&
+	> #	test_when_finished rm clean-after-failure &&
+	> #	(exit 1)
+	> #	Z
+	> not ok - 2 failure to clean up causes the test to fail
+	> #	Z
+	> #	test_when_finished \"(exit 2)\"
+	> #	Z
+	> # failed 2 among 2 test(s)
+	> 1..2
+	EOF
+	test_cmp expect out
+	)
 "
 
 ################################################################
 # Basics of the basics
 
 # updating a new file without --add should fail.
-test_expect_success 'git update-index without --add should fail adding.' '
-    test_must_fail git update-index should-be-empty
+test_expect_success 'git update-index without --add should fail adding' '
+	test_must_fail git update-index should-be-empty
 '
 
 # and with --add it should succeed, even if it is empty (it used to fail).
-test_expect_success \
-    'git update-index with --add should succeed.' \
-    'git update-index --add should-be-empty'
-
-test_expect_success \
-    'writing tree out with git write-tree' \
-    'tree=$(git write-tree)'
-
-# we know the shape and contents of the tree and know the object ID for it.
-test_expect_success \
-    'validate object ID of a known tree.' \
-    'test "$tree" = 7bb943559a305bdd6bdee2cef6e5df2413c3d30a'
-
-# Removing paths.
-rm -f should-be-empty full-of-directories
-test_expect_success 'git update-index without --remove should fail removing.' '
-    test_must_fail git update-index should-be-empty
+test_expect_success 'git update-index with --add should succeed' '
+	git update-index --add should-be-empty
 '
 
-test_expect_success \
-    'git update-index with --remove should be able to remove.' \
-    'git update-index --remove should-be-empty'
+test_expect_success 'writing tree out with git write-tree' '
+	tree=$(git write-tree)
+'
+
+# we know the shape and contents of the tree and know the object ID for it.
+test_expect_success 'validate object ID of a known tree' '
+	test "$tree" = 7bb943559a305bdd6bdee2cef6e5df2413c3d30a
+    '
+
+# Removing paths.
+test_expect_success 'git update-index without --remove should fail removing' '
+	rm -f should-be-empty full-of-directories &&
+	test_must_fail git update-index should-be-empty
+'
+
+test_expect_success 'git update-index with --remove should be able to remove' '
+	git update-index --remove should-be-empty
+'
 
 # Empty tree can be written with recent write-tree.
-test_expect_success \
-    'git write-tree should be able to write an empty tree.' \
-    'tree=$(git write-tree)'
+test_expect_success 'git write-tree should be able to write an empty tree' '
+	tree=$(git write-tree)
+'
 
-test_expect_success \
-    'validate object ID of a known tree.' \
-    'test "$tree" = 4b825dc642cb6eb9a060e54bf8d69288fbee4904'
+test_expect_success 'validate object ID of a known tree' '
+	test "$tree" = 4b825dc642cb6eb9a060e54bf8d69288fbee4904
+'
 
 # Various types of objects
+
 # Some filesystems do not support symblic links; on such systems
 # some expected values are different
-mkdir path2 path3 path3/subp3
-paths='path0 path2/file2 path3/file3 path3/subp3/file3'
-for p in $paths
-do
-    echo "hello $p" >$p
-done
 if test_have_prereq SYMLINKS
 then
-	for p in $paths
-	do
-		ln -s "hello $p" ${p}sym
-	done
 	expectfilter=cat
 	expectedtree=087704a96baf1c2d1c869a8b084481e121c88b5b
 	expectedptree1=21ae8269cacbe57ae09138dcc3a2887f904d02b3
@@ -248,135 +242,154 @@
 	expectedptree2=ce580448f0148b985a513b693fdf7d802cacb44f
 fi
 
-test_expect_success \
-    'adding various types of objects with git update-index --add.' \
-    'find path* ! -type d -print | xargs git update-index --add'
+
+test_expect_success 'adding various types of objects with git update-index --add' '
+	mkdir path2 path3 path3/subp3 &&
+	paths="path0 path2/file2 path3/file3 path3/subp3/file3" &&
+	(
+		for p in $paths
+		do
+			echo "hello $p" >$p || exit 1
+			if test_have_prereq SYMLINKS
+			then
+				ln -s "hello $p" ${p}sym || exit 1
+			fi
+		done
+	) &&
+	find path* ! -type d -print | xargs git update-index --add
+'
 
 # Show them and see that matches what we expect.
-test_expect_success \
-    'showing stage with git ls-files --stage' \
-    'git ls-files --stage >current'
+test_expect_success 'showing stage with git ls-files --stage' '
+	git ls-files --stage >current
+'
 
-$expectfilter >expected <<\EOF
-100644 f87290f8eb2cbbea7857214459a0739927eab154 0	path0
-120000 15a98433ae33114b085f3eb3bb03b832b3180a01 0	path0sym
-100644 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 0	path2/file2
-120000 d8ce161addc5173867a3c3c730924388daedbc38 0	path2/file2sym
-100644 0aa34cae68d0878578ad119c86ca2b5ed5b28376 0	path3/file3
-120000 8599103969b43aff7e430efea79ca4636466794f 0	path3/file3sym
-100644 00fb5908cb97c2564a9783c0c64087333b3b464f 0	path3/subp3/file3
-120000 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c 0	path3/subp3/file3sym
-EOF
-test_expect_success \
-    'validate git ls-files output for a known tree.' \
-    'test_cmp expected current'
+test_expect_success 'validate git ls-files output for a known tree' '
+	$expectfilter >expected <<-\EOF &&
+	100644 f87290f8eb2cbbea7857214459a0739927eab154 0	path0
+	120000 15a98433ae33114b085f3eb3bb03b832b3180a01 0	path0sym
+	100644 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 0	path2/file2
+	120000 d8ce161addc5173867a3c3c730924388daedbc38 0	path2/file2sym
+	100644 0aa34cae68d0878578ad119c86ca2b5ed5b28376 0	path3/file3
+	120000 8599103969b43aff7e430efea79ca4636466794f 0	path3/file3sym
+	100644 00fb5908cb97c2564a9783c0c64087333b3b464f 0	path3/subp3/file3
+	120000 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c 0	path3/subp3/file3sym
+	EOF
+	test_cmp expected current
+'
 
-test_expect_success \
-    'writing tree out with git write-tree.' \
-    'tree=$(git write-tree)'
-test_expect_success \
-    'validate object ID for a known tree.' \
-    'test "$tree" = "$expectedtree"'
+test_expect_success 'writing tree out with git write-tree' '
+	tree=$(git write-tree)
+'
 
-test_expect_success \
-    'showing tree with git ls-tree' \
-    'git ls-tree $tree >current'
-cat >expected <<\EOF
-100644 blob f87290f8eb2cbbea7857214459a0739927eab154	path0
-120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01	path0sym
-040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe	path2
-040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3	path3
-EOF
-test_expect_success SYMLINKS \
-    'git ls-tree output for a known tree.' \
-    'test_cmp expected current'
+test_expect_success 'validate object ID for a known tree' '
+	test "$tree" = "$expectedtree"
+'
+
+test_expect_success 'showing tree with git ls-tree' '
+    git ls-tree $tree >current
+'
+
+test_expect_success SYMLINKS 'git ls-tree output for a known tree' '
+	cat >expected <<-\EOF &&
+	100644 blob f87290f8eb2cbbea7857214459a0739927eab154	path0
+	120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01	path0sym
+	040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe	path2
+	040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3	path3
+	EOF
+	test_cmp expected current
+'
 
 # This changed in ls-tree pathspec change -- recursive does
 # not show tree nodes anymore.
-test_expect_success \
-    'showing tree with git ls-tree -r' \
-    'git ls-tree -r $tree >current'
-$expectfilter >expected <<\EOF
-100644 blob f87290f8eb2cbbea7857214459a0739927eab154	path0
-120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01	path0sym
-100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7	path2/file2
-120000 blob d8ce161addc5173867a3c3c730924388daedbc38	path2/file2sym
-100644 blob 0aa34cae68d0878578ad119c86ca2b5ed5b28376	path3/file3
-120000 blob 8599103969b43aff7e430efea79ca4636466794f	path3/file3sym
-100644 blob 00fb5908cb97c2564a9783c0c64087333b3b464f	path3/subp3/file3
-120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c	path3/subp3/file3sym
-EOF
-test_expect_success \
-    'git ls-tree -r output for a known tree.' \
-    'test_cmp expected current'
-
-# But with -r -t we can have both.
-test_expect_success \
-    'showing tree with git ls-tree -r -t' \
-    'git ls-tree -r -t $tree >current'
-cat >expected <<\EOF
-100644 blob f87290f8eb2cbbea7857214459a0739927eab154	path0
-120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01	path0sym
-040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe	path2
-100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7	path2/file2
-120000 blob d8ce161addc5173867a3c3c730924388daedbc38	path2/file2sym
-040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3	path3
-100644 blob 0aa34cae68d0878578ad119c86ca2b5ed5b28376	path3/file3
-120000 blob 8599103969b43aff7e430efea79ca4636466794f	path3/file3sym
-040000 tree 3c5e5399f3a333eddecce7a9b9465b63f65f51e2	path3/subp3
-100644 blob 00fb5908cb97c2564a9783c0c64087333b3b464f	path3/subp3/file3
-120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c	path3/subp3/file3sym
-EOF
-test_expect_success SYMLINKS \
-    'git ls-tree -r output for a known tree.' \
-    'test_cmp expected current'
-
-test_expect_success \
-    'writing partial tree out with git write-tree --prefix.' \
-    'ptree=$(git write-tree --prefix=path3)'
-test_expect_success \
-    'validate object ID for a known tree.' \
-    'test "$ptree" = "$expectedptree1"'
-
-test_expect_success \
-    'writing partial tree out with git write-tree --prefix.' \
-    'ptree=$(git write-tree --prefix=path3/subp3)'
-test_expect_success \
-    'validate object ID for a known tree.' \
-    'test "$ptree" = "$expectedptree2"'
-
-cat >badobjects <<EOF
-100644 blob 1000000000000000000000000000000000000000	dir/file1
-100644 blob 2000000000000000000000000000000000000000	dir/file2
-100644 blob 3000000000000000000000000000000000000000	dir/file3
-100644 blob 4000000000000000000000000000000000000000	dir/file4
-100644 blob 5000000000000000000000000000000000000000	dir/file5
-EOF
-
-rm .git/index
-test_expect_success \
-    'put invalid objects into the index.' \
-    'git update-index --index-info < badobjects'
-
-test_expect_success 'writing this tree without --missing-ok.' '
-    test_must_fail git write-tree
+test_expect_success 'showing tree with git ls-tree -r' '
+	git ls-tree -r $tree >current
 '
 
-test_expect_success \
-    'writing this tree with --missing-ok.' \
-    'git write-tree --missing-ok'
+test_expect_success 'git ls-tree -r output for a known tree' '
+	$expectfilter >expected <<-\EOF &&
+	100644 blob f87290f8eb2cbbea7857214459a0739927eab154	path0
+	120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01	path0sym
+	100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7	path2/file2
+	120000 blob d8ce161addc5173867a3c3c730924388daedbc38	path2/file2sym
+	100644 blob 0aa34cae68d0878578ad119c86ca2b5ed5b28376	path3/file3
+	120000 blob 8599103969b43aff7e430efea79ca4636466794f	path3/file3sym
+	100644 blob 00fb5908cb97c2564a9783c0c64087333b3b464f	path3/subp3/file3
+	120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c	path3/subp3/file3sym
+	EOF
+	test_cmp expected current
+'
+
+# But with -r -t we can have both.
+test_expect_success 'showing tree with git ls-tree -r -t' '
+	git ls-tree -r -t $tree >current
+'
+
+test_expect_success SYMLINKS 'git ls-tree -r output for a known tree' '
+	cat >expected <<-\EOF &&
+	100644 blob f87290f8eb2cbbea7857214459a0739927eab154	path0
+	120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01	path0sym
+	040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe	path2
+	100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7	path2/file2
+	120000 blob d8ce161addc5173867a3c3c730924388daedbc38	path2/file2sym
+	040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3	path3
+	100644 blob 0aa34cae68d0878578ad119c86ca2b5ed5b28376	path3/file3
+	120000 blob 8599103969b43aff7e430efea79ca4636466794f	path3/file3sym
+	040000 tree 3c5e5399f3a333eddecce7a9b9465b63f65f51e2	path3/subp3
+	100644 blob 00fb5908cb97c2564a9783c0c64087333b3b464f	path3/subp3/file3
+	120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c	path3/subp3/file3sym
+	EOF
+	test_cmp expected current
+'
+
+test_expect_success 'writing partial tree out with git write-tree --prefix' '
+	ptree=$(git write-tree --prefix=path3)
+'
+
+test_expect_success 'validate object ID for a known tree' '
+	test "$ptree" = "$expectedptree1"
+'
+
+test_expect_success 'writing partial tree out with git write-tree --prefix' '
+	ptree=$(git write-tree --prefix=path3/subp3)
+'
+
+test_expect_success 'validate object ID for a known tree' '
+	test "$ptree" = "$expectedptree2"
+'
+
+test_expect_success 'put invalid objects into the index' '
+	rm -f .git/index &&
+	cat >badobjects <<-\EOF &&
+	100644 blob 1000000000000000000000000000000000000000	dir/file1
+	100644 blob 2000000000000000000000000000000000000000	dir/file2
+	100644 blob 3000000000000000000000000000000000000000	dir/file3
+	100644 blob 4000000000000000000000000000000000000000	dir/file4
+	100644 blob 5000000000000000000000000000000000000000	dir/file5
+	EOF
+	git update-index --index-info <badobjects
+'
+
+test_expect_success 'writing this tree without --missing-ok' '
+	test_must_fail git write-tree
+'
+
+test_expect_success 'writing this tree with --missing-ok' '
+	git write-tree --missing-ok
+'
 
 
 ################################################################
-rm .git/index
-test_expect_success \
-    'git read-tree followed by write-tree should be idempotent.' \
-    'git read-tree $tree &&
-     test -f .git/index &&
-     newtree=$(git write-tree) &&
-     test "$newtree" = "$tree"'
+test_expect_success 'git read-tree followed by write-tree should be idempotent' '
+	rm -f .git/index
+	git read-tree $tree &&
+	test -f .git/index &&
+	newtree=$(git write-tree) &&
+	test "$newtree" = "$tree"
+'
 
-$expectfilter >expected <<\EOF
+test_expect_success 'validate git diff-files output for a know cache/work tree state' '
+	$expectfilter >expected <<\EOF &&
 :100644 100644 f87290f8eb2cbbea7857214459a0739927eab154 0000000000000000000000000000000000000000 M	path0
 :120000 120000 15a98433ae33114b085f3eb3bb03b832b3180a01 0000000000000000000000000000000000000000 M	path0sym
 :100644 100644 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 0000000000000000000000000000000000000000 M	path2/file2
@@ -386,45 +399,47 @@
 :100644 100644 00fb5908cb97c2564a9783c0c64087333b3b464f 0000000000000000000000000000000000000000 M	path3/subp3/file3
 :120000 120000 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c 0000000000000000000000000000000000000000 M	path3/subp3/file3sym
 EOF
-test_expect_success \
-    'validate git diff-files output for a know cache/work tree state.' \
-    'git diff-files >current && test_cmp current expected >/dev/null'
+	git diff-files >current &&
+	test_cmp current expected
+'
 
-test_expect_success \
-    'git update-index --refresh should succeed.' \
-    'git update-index --refresh'
+test_expect_success 'git update-index --refresh should succeed' '
+	git update-index --refresh
+'
 
-test_expect_success \
-    'no diff after checkout and git update-index --refresh.' \
-    'git diff-files >current && cmp -s current /dev/null'
+test_expect_success 'no diff after checkout and git update-index --refresh' '
+	git diff-files >current &&
+	cmp -s current /dev/null
+'
 
 ################################################################
 P=$expectedtree
-test_expect_success \
-    'git commit-tree records the correct tree in a commit.' \
-    'commit0=$(echo NO | git commit-tree $P) &&
-     tree=$(git show --pretty=raw $commit0 |
-	 sed -n -e "s/^tree //p" -e "/^author /q") &&
-     test "z$tree" = "z$P"'
 
-test_expect_success \
-    'git commit-tree records the correct parent in a commit.' \
-    'commit1=$(echo NO | git commit-tree $P -p $commit0) &&
-     parent=$(git show --pretty=raw $commit1 |
-	 sed -n -e "s/^parent //p" -e "/^author /q") &&
-     test "z$commit0" = "z$parent"'
+test_expect_success 'git commit-tree records the correct tree in a commit' '
+	commit0=$(echo NO | git commit-tree $P) &&
+	tree=$(git show --pretty=raw $commit0 |
+		 sed -n -e "s/^tree //p" -e "/^author /q") &&
+	test "z$tree" = "z$P"
+'
 
-test_expect_success \
-    'git commit-tree omits duplicated parent in a commit.' \
-    'commit2=$(echo NO | git commit-tree $P -p $commit0 -p $commit0) &&
-     parent=$(git show --pretty=raw $commit2 |
-	 sed -n -e "s/^parent //p" -e "/^author /q" |
-	 sort -u) &&
-     test "z$commit0" = "z$parent" &&
-     numparent=$(git show --pretty=raw $commit2 |
-	 sed -n -e "s/^parent //p" -e "/^author /q" |
-	 wc -l) &&
-     test $numparent = 1'
+test_expect_success 'git commit-tree records the correct parent in a commit' '
+	commit1=$(echo NO | git commit-tree $P -p $commit0) &&
+	parent=$(git show --pretty=raw $commit1 |
+		sed -n -e "s/^parent //p" -e "/^author /q") &&
+	test "z$commit0" = "z$parent"
+'
+
+test_expect_success 'git commit-tree omits duplicated parent in a commit' '
+	commit2=$(echo NO | git commit-tree $P -p $commit0 -p $commit0) &&
+	     parent=$(git show --pretty=raw $commit2 |
+		sed -n -e "s/^parent //p" -e "/^author /q" |
+		sort -u) &&
+	test "z$commit0" = "z$parent" &&
+	numparent=$(git show --pretty=raw $commit2 |
+		sed -n -e "s/^parent //p" -e "/^author /q" |
+		wc -l) &&
+	test $numparent = 1
+'
 
 test_expect_success 'update-index D/F conflict' '
 	mv path0 tmp &&
diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh
index a44bcb9..e3f354a 100755
--- a/t/t0040-parse-options.sh
+++ b/t/t0040-parse-options.sh
@@ -236,6 +236,16 @@
 	test_cmp typo.err output.err
 '
 
+cat > typo.err << EOF
+error: did you mean \`--ambiguous\` (with two dashes ?)
+EOF
+
+test_expect_success 'detect possible typos' '
+	test_must_fail test-parse-options -ambiguous > output 2> output.err &&
+	test ! -s output &&
+	test_cmp typo.err output.err
+'
+
 cat > expect <<EOF
 boolean: 0
 integer: 0
diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
index 8621ab0..20e28e3 100755
--- a/t/t0300-credentials.sh
+++ b/t/t0300-credentials.sh
@@ -8,10 +8,13 @@
 	cat >dump <<-\EOF &&
 	whoami=`echo $0 | sed s/.*git-credential-//`
 	echo >&2 "$whoami: $*"
-	while IFS== read key value; do
+	OIFS=$IFS
+	IFS==
+	while read key value; do
 		echo >&2 "$whoami: $key=$value"
 		eval "$key=$value"
 	done
+	IFS=$OIFS
 	EOF
 
 	write_script git-credential-useless <<-\EOF &&
diff --git a/t/t4052-stat-output.sh b/t/t4052-stat-output.sh
new file mode 100755
index 0000000..328aa8f
--- /dev/null
+++ b/t/t4052-stat-output.sh
@@ -0,0 +1,220 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 Zbigniew Jędrzejewski-Szmek
+#
+
+test_description='test --stat output of various commands'
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-terminal.sh
+
+# 120 character name
+name=aaaaaaaaaa
+name=$name$name$name$name$name$name$name$name$name$name$name$name
+test_expect_success 'preparation' '
+	>"$name" &&
+	git add "$name" &&
+	git commit -m message &&
+	echo a >"$name" &&
+	git commit -m message "$name"
+'
+
+while read cmd args
+do
+	cat >expect <<-'EOF'
+	 ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |    1 +
+	EOF
+	test_expect_success "$cmd: small change with long name gives more space to the name" '
+		git $cmd $args >output &&
+		grep " | " output >actual &&
+		test_cmp expect actual
+	'
+
+	cat >expect <<-'EOF'
+	 ...aaaaaaaaaaaaaaaaaaaaaaaaaa |    1 +
+	EOF
+	test_expect_success "$cmd --stat=width: a long name is given more room when the bar is short" '
+		git $cmd $args --stat=40 >output &&
+		grep " | " output >actual &&
+		test_cmp expect actual
+	'
+
+	test_expect_success "$cmd --stat-width=width with long name" '
+		git $cmd $args --stat-width=40 >output &&
+		grep " | " output >actual &&
+		test_cmp expect actual
+	'
+
+	cat >expect <<-'EOF'
+	 ...aaaaaaaaaaaaaaaaaaaaaaaaaaa |    1 +
+	EOF
+	test_expect_success "$cmd --stat=...,name-width with long name" '
+		git $cmd $args --stat=60,30 >output &&
+		grep " | " output >actual &&
+		test_cmp expect actual
+	'
+
+	test_expect_success "$cmd --stat-name-width with long name" '
+		git $cmd $args --stat-name-width=30 >output &&
+		grep " | " output >actual &&
+		test_cmp expect actual
+	'
+done <<\EOF
+format-patch -1 --stdout
+diff HEAD^ HEAD --stat
+show --stat
+log -1 --stat
+EOF
+
+
+test_expect_success 'preparation for big change tests' '
+	>abcd &&
+	git add abcd &&
+	git commit -m message &&
+	i=0 &&
+	while test $i -lt 1000
+	do
+		echo $i && i=$(($i + 1))
+	done >abcd &&
+	git commit -m message abcd
+'
+
+cat >expect80 <<'EOF'
+ abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+EOF
+
+cat >expect200 <<'EOF'
+ abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+EOF
+
+while read verb expect cmd args
+do
+	test_expect_success "$cmd $verb COLUMNS (big change)" '
+		COLUMNS=200 git $cmd $args >output
+		grep " | " output >actual &&
+		test_cmp "$expect" actual
+	'
+done <<\EOF
+ignores expect80 format-patch -1 --stdout
+respects expect200 diff HEAD^ HEAD --stat
+respects expect200 show --stat
+respects expect200 log -1 --stat
+EOF
+
+cat >expect40 <<'EOF'
+ abcd | 1000 ++++++++++++++++++++++++++
+EOF
+
+while read verb expect cmd args
+do
+	test_expect_success "$cmd $verb not enough COLUMNS (big change)" '
+		COLUMNS=40 git $cmd $args >output
+		grep " | " output >actual &&
+		test_cmp "$expect" actual
+	'
+
+	test_expect_success "$cmd $verb statGraphWidth config" '
+		git -c diff.statGraphWidth=26 $cmd $args >output
+		grep " | " output >actual &&
+		test_cmp "$expect" actual
+	'
+done <<\EOF
+ignores expect80 format-patch -1 --stdout
+respects expect40 diff HEAD^ HEAD --stat
+respects expect40 show --stat
+respects expect40 log -1 --stat
+EOF
+
+
+cat >expect <<'EOF'
+ abcd | 1000 ++++++++++++++++++++++++++
+EOF
+while read cmd args
+do
+	test_expect_success "$cmd --stat=width with big change" '
+		git $cmd $args --stat=40 >output
+		grep " | " output >actual &&
+		test_cmp expect actual
+	'
+
+	test_expect_success "$cmd --stat-width=width with big change" '
+		git $cmd $args --stat-width=40 >output
+		grep " | " output >actual &&
+		test_cmp expect actual
+	'
+
+	test_expect_success "$cmd --stat-graph--width with big change" '
+		git $cmd $args --stat-graph-width=26 >output
+		grep " | " output >actual &&
+		test_cmp expect actual
+	'
+done <<\EOF
+format-patch -1 --stdout
+diff HEAD^ HEAD --stat
+show --stat
+log -1 --stat
+EOF
+
+test_expect_success 'preparation for long filename tests' '
+	cp abcd aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&
+	git add aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&
+	git commit -m message
+'
+
+cat >expect <<'EOF'
+ ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++
+EOF
+while read cmd args
+do
+	test_expect_success "$cmd --stat=width with big change is more balanced" '
+		git $cmd $args --stat-width=60 >output &&
+		grep " | " output >actual &&
+		test_cmp expect actual
+	'
+done <<\EOF
+format-patch -1 --stdout
+diff HEAD^ HEAD --stat
+show --stat
+log -1 --stat
+EOF
+
+cat >expect80 <<'EOF'
+ ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++++++++++
+EOF
+cat >expect200 <<'EOF'
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+EOF
+while read verb expect cmd args
+do
+	test_expect_success "$cmd $verb COLUMNS (long filename)" '
+		COLUMNS=200 git $cmd $args >output
+		grep " | " output >actual &&
+		test_cmp "$expect" actual
+	'
+done <<\EOF
+ignores expect80 format-patch -1 --stdout
+respects expect200 diff HEAD^ HEAD --stat
+respects expect200 show --stat
+respects expect200 log -1 --stat
+EOF
+
+cat >expect <<'EOF'
+ abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+EOF
+test_expect_success 'merge --stat respects COLUMNS (big change)' '
+	git checkout -b branch HEAD^^ &&
+	COLUMNS=100 git merge --stat --no-ff master^ >output &&
+	grep " | " output >actual
+	test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 +++++++++++++++++++++++++++++++++++++++
+EOF
+test_expect_success 'merge --stat respects COLUMNS (long filename)' '
+	COLUMNS=100 git merge --stat --no-ff master >output &&
+	grep " | " output >actual
+	test_cmp expect actual
+'
+
+test_done
diff --git a/t/t4150-am.sh b/t/t4150-am.sh
index 6f77fff..ccc0280 100755
--- a/t/t4150-am.sh
+++ b/t/t4150-am.sh
@@ -123,6 +123,7 @@
 	git commit -m "added another file" &&
 
 	git format-patch --stdout master >lorem-move.patch &&
+	git format-patch --no-prefix --stdout master >lorem-zero.patch &&
 
 	git checkout -b rename &&
 	git mv file renamed &&
@@ -286,6 +287,20 @@
 	git diff --exit-code lorem
 '
 
+test_expect_success 'am -3 -p0 can read --no-prefix patch' '
+	rm -fr .git/rebase-apply &&
+	git reset --hard &&
+	git checkout -b lorem3 master2 &&
+	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 -p0 lorem-zero.patch &&
+	! test -d .git/rebase-apply &&
+	git diff --exit-code lorem
+'
+
 test_expect_success 'am can rename a file' '
 	grep "^rename from" rename.patch &&
 	rm -fr .git/rebase-apply &&
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index 79ee913..308c02e 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -14,6 +14,14 @@
 	test "$2" = $(grep '^[0-9a-f]\{40\} ' verify.out | wc -l)
 }
 
+convert_bundle_to_pack () {
+	while read x && test -n "$x"
+	do
+		:;
+	done
+	cat
+}
+
 test_expect_success setup '
 	echo >file original &&
 	git add file &&
@@ -206,13 +214,7 @@
 
 test_expect_success 'bundle 1 has only 3 files ' '
 	cd "$D" &&
-	(
-		while read x && test -n "$x"
-		do
-			:;
-		done
-		cat
-	) <bundle1 >bundle.pack &&
+	convert_bundle_to_pack <bundle1 >bundle.pack &&
 	git index-pack bundle.pack &&
 	test_bundle_object_count bundle.pack 3
 '
@@ -229,13 +231,7 @@
 	git add file2 &&
 	git commit -m add.file2 file2 &&
 	git bundle create bundle3 -1 HEAD &&
-	(
-		while read x && test -n "$x"
-		do
-			:;
-		done
-		cat
-	) <bundle3 >bundle.pack &&
+	convert_bundle_to_pack <bundle3 >bundle.pack &&
 	git index-pack bundle.pack &&
 	test_bundle_object_count bundle.pack 3
 '
@@ -433,14 +429,31 @@
 '
 
 test_expect_success "should be able to fetch with duplicate refspecs" '
-        mkdir dups &&
-        cd dups &&
-        git init &&
-        git config branch.master.remote three &&
-        git config remote.three.url ../three/.git &&
-        git config remote.three.fetch +refs/heads/*:refs/remotes/origin/* &&
-        git config --add remote.three.fetch +refs/heads/*:refs/remotes/origin/* &&
-        git fetch three
+	mkdir dups &&
+	(
+		cd dups &&
+		git init &&
+		git config branch.master.remote three &&
+		git config remote.three.url ../three/.git &&
+		git config remote.three.fetch +refs/heads/*:refs/remotes/origin/* &&
+		git config --add remote.three.fetch +refs/heads/*:refs/remotes/origin/* &&
+		git fetch three
+	)
+'
+
+test_expect_success 'all boundary commits are excluded' '
+	test_commit base &&
+	test_commit oneside &&
+	git checkout HEAD^ &&
+	test_commit otherside &&
+	git checkout master &&
+	test_tick &&
+	git merge otherside &&
+	ad=$(git log --no-walk --format=%ad HEAD) &&
+	git bundle create twoside-boundary.bdl master --since="$ad" &&
+	convert_bundle_to_pack <twoside-boundary.bdl >twoside-boundary.pack &&
+	pack=$(git index-pack --fix-thin --stdin <twoside-boundary.pack) &&
+	test_bundle_object_count .git/objects/pack/pack-${pack##pack	}.pack 3
 '
 
 test_done
diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh
index 5c546c9..6764d51 100755
--- a/t/t5512-ls-remote.sh
+++ b/t/t5512-ls-remote.sh
@@ -5,7 +5,6 @@
 . ./test-lib.sh
 
 test_expect_success setup '
-
 	>file &&
 	git add file &&
 	test_tick &&
@@ -18,45 +17,33 @@
 	) >expected.all &&
 
 	git remote add self "$(pwd)/.git"
-
 '
 
 test_expect_success 'ls-remote --tags .git' '
-
 	git ls-remote --tags .git >actual &&
 	test_cmp expected.tag actual
-
 '
 
 test_expect_success 'ls-remote .git' '
-
 	git ls-remote .git >actual &&
 	test_cmp expected.all actual
-
 '
 
 test_expect_success 'ls-remote --tags self' '
-
 	git ls-remote --tags self >actual &&
 	test_cmp expected.tag actual
-
 '
 
 test_expect_success 'ls-remote self' '
-
 	git ls-remote self >actual &&
 	test_cmp expected.all actual
-
 '
 
 test_expect_success 'dies when no remote specified and no default remotes found' '
-
 	test_must_fail git ls-remote
-
 '
 
 test_expect_success 'use "origin" when no remote specified' '
-
 	URL="$(pwd)/.git" &&
 	echo "From $URL" >exp_err &&
 
@@ -65,18 +52,14 @@
 
 	test_cmp exp_err actual_err &&
 	test_cmp expected.all actual
-
 '
 
 test_expect_success 'suppress "From <url>" with -q' '
-
 	git ls-remote -q 2>actual_err &&
 	test_must_fail test_cmp exp_err actual_err
-
 '
 
 test_expect_success 'use branch.<name>.remote if possible' '
-
 	#
 	# Test that we are indeed using branch.<name>.remote, not "origin", even
 	# though the "origin" remote has been set.
@@ -99,14 +82,13 @@
 	git ls-remote 2>actual_err >actual &&
 	test_cmp exp_err actual_err &&
 	test_cmp exp actual
-
 '
 
-cat >exp <<EOF
-fatal: 'refs*master' does not appear to be a git repository
-fatal: The remote end hung up unexpectedly
-EOF
 test_expect_success 'confuses pattern as remote when no remote specified' '
+	cat >exp <<-\EOF &&
+	fatal: '\''refs*master'\'' does not appear to be a git repository
+	fatal: The remote end hung up unexpectedly
+	EOF
 	#
 	# Do not expect "git ls-remote <pattern>" to work; ls-remote, correctly,
 	# confuses <pattern> for <remote>. Although ugly, this behaviour is akin
@@ -120,7 +102,6 @@
 	# role as a pattern.
 	test_must_fail git ls-remote refs*master >actual 2>&1 &&
 	test_cmp exp actual
-
 '
 
 test_expect_success 'die with non-2 for wrong repository even with --exit-code' '
diff --git a/t/t5704-bundle.sh b/t/t5704-bundle.sh
index a51c8b0..9e43731 100755
--- a/t/t5704-bundle.sh
+++ b/t/t5704-bundle.sh
@@ -54,8 +54,8 @@
 	git bundle list-heads long-subject-bundle.bdl >heads &&
 	test -s heads &&
 	git fetch long-subject-bundle.bdl &&
-	sed -n "/^-/{p;q}" long-subject-bundle.bdl >boundary &&
-	grep "^-$_x40 " boundary
+	sed -n "/^-/{p;q;}" long-subject-bundle.bdl >boundary &&
+	grep "^-[0-9a-f]\\{40\\} " boundary
 '
 
 test_done
diff --git a/t/test-lib.sh b/t/test-lib.sh
index d75766a..30ed4d7 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -42,10 +42,11 @@
 TERM=dumb
 export LANG LC_ALL PAGER TERM TZ
 EDITOR=:
-unset VISUAL
-unset EMAIL
-unset LANGUAGE
-unset $(perl -e '
+# A call to "unset" with no arguments causes at least Solaris 10
+# /usr/xpg4/bin/sh and /bin/ksh to bail out.  So keep the unsets
+# deriving from the command substitution clustered with the other
+# ones.
+unset VISUAL EMAIL LANGUAGE $(perl -e '
 	my @env = keys %ENV;
 	my $ok = join("|", qw(
 		TRACE