Merge branch 'nm/maint-conflicted-submodule-entries' into maint

* nm/maint-conflicted-submodule-entries:
  submodule: process conflicting submodules only once
diff --git a/Documentation/RelNotes/1.7.4.3.txt b/Documentation/RelNotes/1.7.4.3.txt
new file mode 100644
index 0000000..02a3d5b
--- /dev/null
+++ b/Documentation/RelNotes/1.7.4.3.txt
@@ -0,0 +1,32 @@
+Git v1.7.4.3 Release Notes
+==========================
+
+Fixes since v1.7.4.2
+--------------------
+
+ * "git apply" used to confuse lines updated by previous hunks as lines
+   that existed before when applying a hunk, contributing misapplication
+   of patches with offsets.
+
+ * "git branch --track" (and "git checkout --track --branch") used to
+   allow setting up a random non-branch that does not make sense to follow
+   as the "upstream".  The command correctly diagnoses it as an error.
+
+ * "git checkout $other_branch" silently removed untracked symbolic links
+   in the working tree that are in the way in order to check out paths
+   under it from the named branch.
+
+ * "git cvsimport" did not bail out immediately when the cvs server cannot
+   be reached, spewing unnecessary error messages that complain about the
+   server response that it never got.
+
+ * "git diff --quiet" did not work very well with the "--diff-filter"
+   option.
+
+ * "git grep -n" lacked a long-hand synonym --line-number.
+
+ * "git stash apply" reported the result of its operation by running
+   "git status" from the top-level of the working tree; it should (and
+   now does) run it from the user's working directory.
+
+And other minor fixes and documentation updates.
diff --git a/Documentation/RelNotes/1.7.4.4.txt b/Documentation/RelNotes/1.7.4.4.txt
new file mode 100644
index 0000000..e914904
--- /dev/null
+++ b/Documentation/RelNotes/1.7.4.4.txt
@@ -0,0 +1,37 @@
+Git v1.7.4.4 Release Notes
+==========================
+
+Fixes since v1.7.4.3
+--------------------
+
+ * Compilation of sha1_file.c on BSD platforms were broken due to our
+   recent use of getrlimit() without including <sys/resource.h>.
+
+ * "git config" did not diagnose incorrect configuration variable names.
+
+ * "git format-patch" did not wrap a long subject line that resulted from
+   rfc2047 encoding.
+
+ * "git instaweb" should work better again with plackup.
+
+ * "git log --max-count=4 -Sfoobar" now shows 4 commits that changes the
+   number of occurrences of string "foobar"; it used to scan only for 4
+   commits and then emitted only matching ones.
+
+ * "git log --first-parent --boundary $c^..$c" segfaulted on a merge.
+
+ * "git pull" into an empty branch should have behaved as if
+   fast-forwarding from emptiness to the version being pulled, with
+   the usual protection against overwriting untracked files.
+
+ * "git status" spent all the effort to notice racily-clean index entries
+   but didn't update the index file to help later operations go faster in
+   some cases.
+
+And other minor fixes and documentation updates.
+
+---
+exec >/var/tmp/1
+O=v1.7.4.3-22-g8c8674f
+echo O=$(git describe maint)
+git shortlog --no-merges $O..maint
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 1a571f4..6babbc7 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -320,7 +320,7 @@
 	Set the path to the root of the working tree.
 	This can be overridden by the GIT_WORK_TREE environment
 	variable and the '--work-tree' command line option.
-	The value can an absolute path or relative to the path to
+	The value can be an absolute path or relative to the path to
 	the .git directory, which is either specified by --git-dir
 	or GIT_DIR, or automatically discovered.
 	If --git-dir or GIT_DIR is specified but none of
@@ -558,6 +558,12 @@
 	Enable "sparse checkout" feature. See section "Sparse checkout" in
 	linkgit:git-read-tree[1] for more information.
 
+core.abbrev::
+	Set the length object names are abbreviated to.  If unspecified,
+	many commands abbreviate to 7 hexdigits, which may not be enough
+	for abbreviated object names to stay unique for sufficiently long
+	time.
+
 add.ignore-errors::
 add.ignoreErrors::
 	Tells 'git add' to continue adding files when some files cannot be
diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt
index 1701e42..c443e0f 100644
--- a/Documentation/git-bisect.txt
+++ b/Documentation/git-bisect.txt
@@ -279,53 +279,68 @@
 $ git bisect run make test           # "make test" builds and tests
 ------------
 
-* Automatically bisect a broken test suite:
-+
-------------
-$ cat ~/test.sh
-#!/bin/sh
-make || exit 125                   # this skips broken builds
-make test                          # "make test" runs the test suite
-$ git bisect start v1.3 v1.1 --    # v1.3 is bad, v1.1 is good
-$ git bisect run ~/test.sh
-------------
-+
-Here we use a "test.sh" custom script. In this script, if "make"
-fails, we skip the current commit.
-+
-It is safer to use a custom script outside the repository to prevent
-interactions between the bisect, make and test processes and the
-script.
-+
-"make test" should "exit 0", if the test suite passes, and
-"exit 1" otherwise.
-
 * Automatically bisect a broken test case:
 +
 ------------
 $ cat ~/test.sh
 #!/bin/sh
 make || exit 125                     # this skips broken builds
-~/check_test_case.sh                 # does the test case passes ?
+~/check_test_case.sh                 # does the test case pass?
 $ git bisect start HEAD HEAD~10 --   # culprit is among the last 10
 $ git bisect run ~/test.sh
 ------------
 +
-Here "check_test_case.sh" should "exit 0" if the test case passes,
+Here we use a "test.sh" custom script. In this script, if "make"
+fails, we skip the current commit.
+"check_test_case.sh" should "exit 0" if the test case passes,
 and "exit 1" otherwise.
 +
-It is safer if both "test.sh" and "check_test_case.sh" scripts are
+It is safer if both "test.sh" and "check_test_case.sh" are
 outside the repository to prevent interactions between the bisect,
 make and test processes and the scripts.
 
-* Automatically bisect a broken test suite:
+* Automatically bisect with temporary modifications (hot-fix):
++
+------------
+$ cat ~/test.sh
+#!/bin/sh
+
+# tweak the working tree by merging the hot-fix branch
+# and then attempt a build
+if	git merge --no-commit hot-fix &&
+	make
+then
+	# run project specific test and report its status
+	~/check_test_case.sh
+	status=$?
+else
+	# tell the caller this is untestable
+	status=125
+fi
+
+# undo the tweak to allow clean flipping to the next commit
+git reset --hard
+
+# return control
+exit $status
+------------
++
+This applies modifications from a hot-fix branch before each test run,
+e.g. in case your build or test environment changed so that older
+revisions may need a fix which newer ones have already. (Make sure the
+hot-fix branch is based off a commit which is contained in all revisions
+which you are bisecting, so that the merge does not pull in too much, or
+use `git cherry-pick` instead of `git merge`.)
+
+* Automatically bisect a broken test case:
 +
 ------------
 $ git bisect start HEAD HEAD~10 --   # culprit is among the last 10
 $ git bisect run sh -c "make || exit 125; ~/check_test_case.sh"
 ------------
 +
-Does the same as the previous example, but on a single line.
+This shows that you can do without a run script if you write the test
+on a single line.
 
 Author
 ------
diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt
index 796e748..aa69b8e 100644
--- a/Documentation/git-filter-branch.txt
+++ b/Documentation/git-filter-branch.txt
@@ -361,7 +361,7 @@
 	'git ls-files -s | sed "s-\t\"*-&newsubdir/-" |
 		GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
 			git update-index --index-info &&
-	 mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE' HEAD
+	 mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD
 ---------------------------------------------------------------
 
 
diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt
index ff41784..c43aa43 100644
--- a/Documentation/git-log.txt
+++ b/Documentation/git-log.txt
@@ -25,6 +25,7 @@
 
 -<n>::
 	Limits the number of commits to show.
+	Note that this is a commit limiting option, see below.
 
 <since>..<until>::
 	Show only commits between the named two commits.  When
@@ -72,16 +73,16 @@
 	to be prefixed with "\-- " to separate them from options or
 	refnames.
 
-Common diff options
-~~~~~~~~~~~~~~~~~~~
-
-:git-log: 1
-include::diff-options.txt[]
-
 include::rev-list-options.txt[]
 
 include::pretty-formats.txt[]
 
+Common diff options
+-------------------
+
+:git-log: 1
+include::diff-options.txt[]
+
 include::diff-generate-patch.txt[]
 
 Examples
diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt
index a9c373c..96684bc 100644
--- a/Documentation/git-pack-objects.txt
+++ b/Documentation/git-pack-objects.txt
@@ -192,13 +192,18 @@
 --delta-base-offset::
 	A packed archive can express the base object of a delta as
 	either a 20-byte object name or as an offset in the
-	stream, but older versions of git don't understand the
+	stream, but ancient versions of git don't understand the
 	latter.  By default, 'git pack-objects' only uses the
 	former format for better compatibility.  This option
 	allows the command to use the latter format for
 	compactness.  Depending on the average delta chain
 	length, this option typically shrinks the resulting
 	packfile by 3-5 per-cent.
++
+Note: Porcelain commands such as `git gc` (see linkgit:git-gc[1]),
+`git repack` (see linkgit:git-repack[1]) pass this option by default
+in modern git when they put objects in your repository into pack files.
+So does `git bundle` (see linkgit:git-bundle[1]) when it creates a bundle.
 
 --threads=<n>::
 	Specifies the number of threads to spawn when searching for best
diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt
index 9c47ad8..09860de 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -1,164 +1,10 @@
-Commit Formatting
-~~~~~~~~~~~~~~~~~
-
-ifdef::git-rev-list[]
-Using these options, linkgit:git-rev-list[1] will act similar to the
-more specialized family of commit log tools: linkgit:git-log[1],
-linkgit:git-show[1], and linkgit:git-whatchanged[1]
-endif::git-rev-list[]
-
-include::pretty-options.txt[]
-
---relative-date::
-
-	Synonym for `--date=relative`.
-
---date=(relative|local|default|iso|rfc|short|raw)::
-
-	Only takes effect for dates shown in human-readable format, such
-	as when using "--pretty". `log.date` config variable sets a default
-	value for log command's --date option.
-+
-`--date=relative` shows dates relative to the current time,
-e.g. "2 hours ago".
-+
-`--date=local` shows timestamps in user's local timezone.
-+
-`--date=iso` (or `--date=iso8601`) shows timestamps in ISO 8601 format.
-+
-`--date=rfc` (or `--date=rfc2822`) shows timestamps in RFC 2822
-format, often found in E-mail messages.
-+
-`--date=short` shows only date but not time, in `YYYY-MM-DD` format.
-+
-`--date=raw` shows the date in the internal raw git format `%s %z` format.
-+
-`--date=default` shows timestamps in the original timezone
-(either committer's or author's).
-
-ifdef::git-rev-list[]
---header::
-
-	Print the contents of the commit in raw-format; each record is
-	separated with a NUL character.
-endif::git-rev-list[]
-
---parents::
-
-	Print also the parents of the commit (in the form "commit parent...").
-	Also enables parent rewriting, see 'History Simplification' below.
-
---children::
-
-	Print also the children of the commit (in the form "commit child...").
-	Also enables parent rewriting, see 'History Simplification' below.
-
-ifdef::git-rev-list[]
---timestamp::
-	Print the raw commit timestamp.
-endif::git-rev-list[]
-
---left-right::
-
-	Mark which side of a symmetric diff a commit is reachable from.
-	Commits from the left side are prefixed with `<` and those from
-	the right with `>`.  If combined with `--boundary`, those
-	commits are prefixed with `-`.
-+
-For example, if you have this topology:
-+
------------------------------------------------------------------------
-             y---b---b  branch B
-            / \ /
-           /   .
-          /   / \
-         o---x---a---a  branch A
------------------------------------------------------------------------
-+
-you would get an output like this:
-+
------------------------------------------------------------------------
-	$ git rev-list --left-right --boundary --pretty=oneline A...B
-
-	>bbbbbbb... 3rd on b
-	>bbbbbbb... 2nd on b
-	<aaaaaaa... 3rd on a
-	<aaaaaaa... 2nd on a
-	-yyyyyyy... 1st on b
-	-xxxxxxx... 1st on a
------------------------------------------------------------------------
-
---graph::
-
-	Draw a text-based graphical representation of the commit history
-	on the left hand side of the output.  This may cause extra lines
-	to be printed in between commits, in order for the graph history
-	to be drawn properly.
-+
-This enables parent rewriting, see 'History Simplification' below.
-+
-This implies the '--topo-order' option by default, but the
-'--date-order' option may also be specified.
-
-ifdef::git-rev-list[]
---count::
-	Print a number stating how many commits would have been
-	listed, and suppress all other output.  When used together
-	with '--left-right', instead print the counts for left and
-	right commits, separated by a tab.
-endif::git-rev-list[]
-
-
-ifndef::git-rev-list[]
-Diff Formatting
-~~~~~~~~~~~~~~~
-
-Below are listed options that control the formatting of diff output.
-Some of them are specific to linkgit:git-rev-list[1], however other diff
-options may be given. See linkgit:git-diff-files[1] for more options.
-
--c::
-
-	With this option, diff output for a merge commit
-	shows the differences from each of the parents to the merge result
-	simultaneously instead of showing pairwise diff between a parent
-	and the result one at a time. Furthermore, it lists only files
-	which were modified from all parents.
-
---cc::
-
-	This flag implies the '-c' options and further compresses the
-	patch output by omitting uninteresting hunks whose contents in
-	the parents have only two variants and the merge result picks
-	one of them without modification.
-
--m::
-
-	This flag makes the merge commits show the full diff like
-	regular commits; for each merge parent, a separate log entry
-	and diff is generated. An exception is that only diff against
-	the first parent is shown when '--first-parent' option is given;
-	in that case, the output represents the changes the merge
-	brought _into_ the then-current branch.
-
--r::
-
-	Show recursive diffs.
-
--t::
-
-	Show the tree objects in the diff output. This implies '-r'.
-
--s::
-	Suppress diff output.
-endif::git-rev-list[]
-
 Commit Limiting
 ~~~~~~~~~~~~~~~
 
 Besides specifying a range of commits that should be listed using the
 special notations explained in the description, additional commit
-limiting may be applied.
+limiting may be applied. Note that they are applied before commit
+ordering and formatting options, such as '--reverse'.
 
 --
 
@@ -735,3 +581,158 @@
 --do-walk::
 
 	Overrides a previous --no-walk.
+
+Commit Formatting
+~~~~~~~~~~~~~~~~~
+
+ifdef::git-rev-list[]
+Using these options, linkgit:git-rev-list[1] will act similar to the
+more specialized family of commit log tools: linkgit:git-log[1],
+linkgit:git-show[1], and linkgit:git-whatchanged[1]
+endif::git-rev-list[]
+
+include::pretty-options.txt[]
+
+--relative-date::
+
+	Synonym for `--date=relative`.
+
+--date=(relative|local|default|iso|rfc|short|raw)::
+
+	Only takes effect for dates shown in human-readable format, such
+	as when using "--pretty". `log.date` config variable sets a default
+	value for log command's --date option.
++
+`--date=relative` shows dates relative to the current time,
+e.g. "2 hours ago".
++
+`--date=local` shows timestamps in user's local timezone.
++
+`--date=iso` (or `--date=iso8601`) shows timestamps in ISO 8601 format.
++
+`--date=rfc` (or `--date=rfc2822`) shows timestamps in RFC 2822
+format, often found in E-mail messages.
++
+`--date=short` shows only date but not time, in `YYYY-MM-DD` format.
++
+`--date=raw` shows the date in the internal raw git format `%s %z` format.
++
+`--date=default` shows timestamps in the original timezone
+(either committer's or author's).
+
+ifdef::git-rev-list[]
+--header::
+
+	Print the contents of the commit in raw-format; each record is
+	separated with a NUL character.
+endif::git-rev-list[]
+
+--parents::
+
+	Print also the parents of the commit (in the form "commit parent...").
+	Also enables parent rewriting, see 'History Simplification' below.
+
+--children::
+
+	Print also the children of the commit (in the form "commit child...").
+	Also enables parent rewriting, see 'History Simplification' below.
+
+ifdef::git-rev-list[]
+--timestamp::
+	Print the raw commit timestamp.
+endif::git-rev-list[]
+
+--left-right::
+
+	Mark which side of a symmetric diff a commit is reachable from.
+	Commits from the left side are prefixed with `<` and those from
+	the right with `>`.  If combined with `--boundary`, those
+	commits are prefixed with `-`.
++
+For example, if you have this topology:
++
+-----------------------------------------------------------------------
+	     y---b---b  branch B
+	    / \ /
+	   /   .
+	  /   / \
+	 o---x---a---a  branch A
+-----------------------------------------------------------------------
++
+you would get an output like this:
++
+-----------------------------------------------------------------------
+	$ git rev-list --left-right --boundary --pretty=oneline A...B
+
+	>bbbbbbb... 3rd on b
+	>bbbbbbb... 2nd on b
+	<aaaaaaa... 3rd on a
+	<aaaaaaa... 2nd on a
+	-yyyyyyy... 1st on b
+	-xxxxxxx... 1st on a
+-----------------------------------------------------------------------
+
+--graph::
+
+	Draw a text-based graphical representation of the commit history
+	on the left hand side of the output.  This may cause extra lines
+	to be printed in between commits, in order for the graph history
+	to be drawn properly.
++
+This enables parent rewriting, see 'History Simplification' below.
++
+This implies the '--topo-order' option by default, but the
+'--date-order' option may also be specified.
+
+ifdef::git-rev-list[]
+--count::
+	Print a number stating how many commits would have been
+	listed, and suppress all other output.  When used together
+	with '--left-right', instead print the counts for left and
+	right commits, separated by a tab.
+endif::git-rev-list[]
+
+
+ifndef::git-rev-list[]
+Diff Formatting
+~~~~~~~~~~~~~~~
+
+Below are listed options that control the formatting of diff output.
+Some of them are specific to linkgit:git-rev-list[1], however other diff
+options may be given. See linkgit:git-diff-files[1] for more options.
+
+-c::
+
+	With this option, diff output for a merge commit
+	shows the differences from each of the parents to the merge result
+	simultaneously instead of showing pairwise diff between a parent
+	and the result one at a time. Furthermore, it lists only files
+	which were modified from all parents.
+
+--cc::
+
+	This flag implies the '-c' options and further compresses the
+	patch output by omitting uninteresting hunks whose contents in
+	the parents have only two variants and the merge result picks
+	one of them without modification.
+
+-m::
+
+	This flag makes the merge commits show the full diff like
+	regular commits; for each merge parent, a separate log entry
+	and diff is generated. An exception is that only diff against
+	the first parent is shown when '--first-parent' option is given;
+	in that case, the output represents the changes the merge
+	brought _into_ the then-current branch.
+
+-r::
+
+	Show recursive diffs.
+
+-t::
+
+	Show the tree objects in the diff output. This implies '-r'.
+
+-s::
+	Suppress diff output.
+endif::git-rev-list[]
diff --git a/Documentation/technical/index-format.txt b/Documentation/technical/index-format.txt
new file mode 100644
index 0000000..7b233ca
--- /dev/null
+++ b/Documentation/technical/index-format.txt
@@ -0,0 +1,185 @@
+GIT index format
+================
+
+= The git index file has the following format
+
+  All binary numbers are in network byte order. Version 2 is described
+  here unless stated otherwise.
+
+   - A 12-byte header consisting of
+
+     4-byte signature:
+       The signature is { 'D', 'I', 'R', 'C' } (stands for "dircache")
+
+     4-byte version number:
+       The current supported versions are 2 and 3.
+
+     32-bit number of index entries.
+
+   - A number of sorted index entries (see below).
+
+   - Extensions
+
+     Extensions are identified by signature. Optional extensions can
+     be ignored if GIT does not understand them.
+
+     GIT currently supports cached tree and resolve undo extensions.
+
+     4-byte extension signature. If the first byte is 'A'..'Z' the
+     extension is optional and can be ignored.
+
+     32-bit size of the extension
+
+     Extension data
+
+   - 160-bit SHA-1 over the content of the index file before this
+     checksum.
+
+== Index entry
+
+  Index entries are sorted in ascending order on the name field,
+  interpreted as a string of unsigned bytes (i.e. memcmp() order, no
+  localization, no special casing of directory separator '/'). Entries
+  with the same name are sorted by their stage field.
+
+  32-bit ctime seconds, the last time a file's metadata changed
+    this is stat(2) data
+
+  32-bit ctime nanosecond fractions
+    this is stat(2) data
+
+  32-bit mtime seconds, the last time a file's data changed
+    this is stat(2) data
+
+  32-bit mtime nanosecond fractions
+    this is stat(2) data
+
+  32-bit dev
+    this is stat(2) data
+
+  32-bit ino
+    this is stat(2) data
+
+  32-bit mode, split into (high to low bits)
+
+    4-bit object type
+      valid values in binary are 1000 (regular file), 1010 (symbolic link)
+      and 1110 (gitlink)
+
+    3-bit unused
+
+    9-bit unix permission. Only 0755 and 0644 are valid for regular files.
+    Symbolic links and gitlinks have value 0 in this field.
+
+  32-bit uid
+    this is stat(2) data
+
+  32-bit gid
+    this is stat(2) data
+
+  32-bit file size
+    This is the on-disk size from stat(2), truncated to 32-bit.
+
+  160-bit SHA-1 for the represented object
+
+  A 16-bit 'flags' field split into (high to low bits)
+
+    1-bit assume-valid flag
+
+    1-bit extended flag (must be zero in version 2)
+
+    2-bit stage (during merge)
+
+    12-bit name length if the length is less than 0xFFF; otherwise 0xFFF
+    is stored in this field.
+
+  (Version 3) A 16-bit field, only applicable if the "extended flag"
+  above is 1, split into (high to low bits).
+
+    1-bit reserved for future
+
+    1-bit skip-worktree flag (used by sparse checkout)
+
+    1-bit intent-to-add flag (used by "git add -N")
+
+    13-bit unused, must be zero
+
+  Entry path name (variable length) relative to top level directory
+    (without leading slash). '/' is used as path separator. The special
+    path components ".", ".." and ".git" (without quotes) are disallowed.
+    Trailing slash is also disallowed.
+
+    The exact encoding is undefined, but the '.' and '/' characters
+    are encoded in 7-bit ASCII and the encoding cannot contain a NUL
+    byte (iow, this is a UNIX pathname).
+
+  1-8 nul bytes as necessary to pad the entry to a multiple of eight bytes
+  while keeping the name NUL-terminated.
+
+== Extensions
+
+=== Cached tree
+
+  Cached tree extension contains pre-computed hashes for trees that can
+  be derived from the index. It helps speed up tree object generation
+  from index for a new commit.
+
+  When a path is updated in index, the path must be invalidated and
+  removed from tree cache.
+
+  The signature for this extension is { 'T', 'R', 'E', 'E' }.
+
+  A series of entries fill the entire extension; each of which
+  consists of:
+
+  - NUL-terminated path component (relative to its parent directory);
+
+  - ASCII decimal number of entries in the index that is covered by the
+    tree this entry represents (entry_count);
+
+  - A space (ASCII 32);
+
+  - ASCII decimal number that represents the number of subtrees this
+    tree has;
+
+  - A newline (ASCII 10); and
+
+  - 160-bit object name for the object that would result from writing
+    this span of index as a tree.
+
+  An entry can be in an invalidated state and is represented by having -1
+  in the entry_count field.
+
+  The entries are written out in the top-down, depth-first order.  The
+  first entry represents the root level of the repository, followed by the
+  first subtree---let's call this A---of the root level (with its name
+  relative to the root level), followed by the first subtree of A (with
+  its name relative to A), ...
+
+=== Resolve undo
+
+  A conflict is represented in the index as a set of higher stage entries.
+  When a conflict is resolved (e.g. with "git add path"), these higher
+  stage entries will be removed and a stage-0 entry with proper resoluton
+  is added.
+
+  When these higher stage entries are removed, they are saved in the
+  resolve undo extension, so that conflicts can be recreated (e.g. with
+  "git checkout -m"), in case users want to redo a conflict resolution
+  from scratch.
+
+  The signature for this extension is { 'R', 'E', 'U', 'C' }.
+
+  A series of entries fill the entire extension; each of which
+  consists of:
+
+  - NUL-terminated pathname the entry describes (relative to the root of
+    the repository, i.e. full pathname);
+
+  - Three NUL-terminated ASCII octal numbers, entry mode of entries in
+    stage 1 to 3 (a missing stage is represented by "0" in this field);
+    and
+
+  - At most three 160-bit object names of the entry in stages from 1 to 3
+    (nothing is written for a missing stage).
+
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index 0b4e960..cbd6e34 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v1.7.4.2
+DEF_VER=v1.7.4.3
 
 LF='
 '
diff --git a/RelNotes b/RelNotes
index 9a74955..d5ad5e1 120000
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/1.7.4.2.txt
\ No newline at end of file
+Documentation/RelNotes/1.7.4.4
\ No newline at end of file
diff --git a/branch.c b/branch.c
index 93dc866..da5c03e 100644
--- a/branch.c
+++ b/branch.c
@@ -175,9 +175,14 @@
 			die("Cannot setup tracking information; starting point is not a branch.");
 		break;
 	case 1:
-		/* Unique completion -- good, only if it is a real ref */
-		if (explicit_tracking && !strcmp(real_ref, "HEAD"))
-			die("Cannot setup tracking information; starting point is not a branch.");
+		/* Unique completion -- good, only if it is a real branch */
+		if (prefixcmp(real_ref, "refs/heads/") &&
+		    prefixcmp(real_ref, "refs/remotes/")) {
+			if (explicit_tracking)
+				die("Cannot setup tracking information; starting point is not a branch.");
+			else
+				real_ref = NULL;
+		}
 		break;
 	default:
 		die("Ambiguous object name: '%s'.", start_name);
diff --git a/builtin/apply.c b/builtin/apply.c
index 14951da..36e1507 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -204,6 +204,7 @@
 	unsigned hash : 24;
 	unsigned flag : 8;
 #define LINE_COMMON     1
+#define LINE_PATCHED	2
 };
 
 /*
@@ -2085,7 +2086,8 @@
 
 	/* Quick hash check */
 	for (i = 0; i < preimage_limit; i++)
-		if (preimage->line[i].hash != img->line[try_lno + i].hash)
+		if ((img->line[try_lno + i].flag & LINE_PATCHED) ||
+		    (preimage->line[i].hash != img->line[try_lno + i].hash))
 			return 0;
 
 	if (preimage_limit == preimage->nr) {
@@ -2428,11 +2430,15 @@
 	memcpy(img->line + applied_pos,
 	       postimage->line,
 	       postimage->nr * sizeof(*img->line));
+	for (i = 0; i < postimage->nr; i++)
+		img->line[applied_pos + i].flag |= LINE_PATCHED;
+
 	img->nr = nr;
 }
 
 static int apply_one_fragment(struct image *img, struct fragment *frag,
-			      int inaccurate_eof, unsigned ws_rule)
+			      int inaccurate_eof, unsigned ws_rule,
+			      int nth_fragment)
 {
 	int match_beginning, match_end;
 	const char *patch = frag->patch;
@@ -2638,6 +2644,15 @@
 				apply = 0;
 		}
 
+		if (apply_verbosely && applied_pos != pos) {
+			int offset = applied_pos - pos;
+			if (apply_in_reverse)
+				offset = 0 - offset;
+			fprintf(stderr,
+				"Hunk #%d succeeded at %d (offset %d lines).\n",
+				nth_fragment, applied_pos + 1, offset);
+		}
+
 		/*
 		 * Warn if it was necessary to reduce the number
 		 * of context lines.
@@ -2785,12 +2800,14 @@
 	const char *name = patch->old_name ? patch->old_name : patch->new_name;
 	unsigned ws_rule = patch->ws_rule;
 	unsigned inaccurate_eof = patch->inaccurate_eof;
+	int nth = 0;
 
 	if (patch->is_binary)
 		return apply_binary(img, patch);
 
 	while (frag) {
-		if (apply_one_fragment(img, frag, inaccurate_eof, ws_rule)) {
+		nth++;
+		if (apply_one_fragment(img, frag, inaccurate_eof, ws_rule, nth)) {
 			error("patch failed: %s:%ld", name, frag->oldpos);
 			if (!apply_with_reject)
 				return -1;
diff --git a/builtin/checkout.c b/builtin/checkout.c
index cd7f56e..e98576f 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -678,7 +678,7 @@
 int cmd_checkout(int argc, const char **argv, const char *prefix)
 {
 	struct checkout_opts opts;
-	unsigned char rev[20];
+	unsigned char rev[20], branch_rev[20];
 	const char *arg;
 	struct branch_info new;
 	struct tree *source_tree = NULL;
@@ -832,18 +832,21 @@
 		argc--;
 
 		new.name = arg;
-		if ((new.commit = lookup_commit_reference_gently(rev, 1))) {
-			setup_branch_path(&new);
+		setup_branch_path(&new);
 
-			if ((check_ref_format(new.path) == CHECK_REF_FORMAT_OK) &&
-			    resolve_ref(new.path, rev, 1, NULL))
-				;
-			else
-				new.path = NULL;
+		if (check_ref_format(new.path) == CHECK_REF_FORMAT_OK &&
+		    resolve_ref(new.path, branch_rev, 1, NULL))
+			hashcpy(rev, branch_rev);
+		else
+			new.path = NULL; /* not an existing branch */
+
+		if (!(new.commit = lookup_commit_reference_gently(rev, 1))) {
+			/* not a commit */
+			source_tree = parse_tree_indirect(rev);
+		} else {
 			parse_commit(new.commit);
 			source_tree = new.commit->tree;
-		} else
-			source_tree = parse_tree_indirect(rev);
+		}
 
 		if (!source_tree)                   /* case (1): want a tree */
 			die("reference is not a tree: %s", arg);
diff --git a/builtin/commit.c b/builtin/commit.c
index d71e1e0..6e32166 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1131,13 +1131,8 @@
 	refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, s.pathspec, NULL, NULL);
 
 	fd = hold_locked_index(&index_lock, 0);
-	if (0 <= fd) {
-		if (active_cache_changed &&
-		    !write_cache(fd, active_cache, active_nr))
-			commit_locked_index(&index_lock);
-		else
-			rollback_lock_file(&index_lock);
-	}
+	if (0 <= fd)
+		update_index_if_able(&the_index, &index_lock);
 
 	s.is_initial = get_sha1(s.reference, sha1) ? 1 : 0;
 	s.in_merge = in_merge;
diff --git a/builtin/config.c b/builtin/config.c
index b8b18e3..f874436 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -153,7 +153,6 @@
 static int get_value(const char *key_, const char *regex_)
 {
 	int ret = -1;
-	char *tl;
 	char *global = NULL, *repo_config = NULL;
 	const char *system_wide = NULL, *local;
 
@@ -167,18 +166,32 @@
 			system_wide = git_etc_gitconfig();
 	}
 
-	key = xstrdup(key_);
-	for (tl=key+strlen(key)-1; tl >= key && *tl != '.'; --tl)
-		*tl = tolower(*tl);
-	for (tl=key; *tl && *tl != '.'; ++tl)
-		*tl = tolower(*tl);
-
 	if (use_key_regexp) {
+		char *tl;
+
+		/*
+		 * NEEDSWORK: this naive pattern lowercasing obviously does not
+		 * work for more complex patterns like "^[^.]*Foo.*bar".
+		 * Perhaps we should deprecate this altogether someday.
+		 */
+
+		key = xstrdup(key_);
+		for (tl = key + strlen(key) - 1;
+		     tl >= key && *tl != '.';
+		     tl--)
+			*tl = tolower(*tl);
+		for (tl = key; *tl && *tl != '.'; tl++)
+			*tl = tolower(*tl);
+
 		key_regexp = (regex_t*)xmalloc(sizeof(regex_t));
 		if (regcomp(key_regexp, key, REG_EXTENDED)) {
 			fprintf(stderr, "Invalid key pattern: %s\n", key_);
+			free(key);
 			goto free_strings;
 		}
+	} else {
+		if (git_config_parse_key(key_, &key, NULL))
+			goto free_strings;
 	}
 
 	if (regex_) {
diff --git a/builtin/describe.c b/builtin/describe.c
index 3ba26dc..4afd150 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -21,7 +21,7 @@
 static int all;	/* Any valid ref can be used */
 static int tags;	/* Allow lightweight tags */
 static int longformat;
-static int abbrev = DEFAULT_ABBREV;
+static int abbrev = -1; /* unspecified */
 static int max_candidates = 10;
 static struct hash_table names;
 static int have_util;
@@ -420,7 +420,11 @@
 		OPT_END(),
 	};
 
+	git_config(git_default_config, NULL);
 	argc = parse_options(argc, argv, prefix, options, describe_usage, 0);
+	if (abbrev < 0)
+		abbrev = DEFAULT_ABBREV;
+
 	if (max_candidates < 0)
 		max_candidates = 0;
 	else if (max_candidates > MAX_TAGS)
diff --git a/builtin/diff.c b/builtin/diff.c
index 42822cd..d4d80c9 100644
--- a/builtin/diff.c
+++ b/builtin/diff.c
@@ -197,12 +197,7 @@
 	discard_cache();
 	read_cache();
 	refresh_cache(REFRESH_QUIET|REFRESH_UNMERGED);
-
-	if (active_cache_changed &&
-	    !write_cache(fd, active_cache, active_nr))
-		commit_locked_index(lock_file);
-
-	rollback_lock_file(lock_file);
+	update_index_if_able(&the_index, lock_file);
 }
 
 static int builtin_diff_files(struct rev_info *revs, int argc, const char **argv)
diff --git a/builtin/log.c b/builtin/log.c
index 0f43d2e..9a15d69 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -263,7 +263,13 @@
 	 * retain that state information if replacing rev->diffopt in this loop
 	 */
 	while ((commit = get_revision(rev)) != NULL) {
-		log_tree_commit(rev, commit);
+		if (!log_tree_commit(rev, commit) &&
+		    rev->max_count >= 0)
+			/*
+			 * We decremented max_count in get_revision,
+			 * but we didn't actually show the commit.
+			 */
+			rev->max_count++;
 		if (!rev->reflog_info) {
 			/* we allow cycles in reflog ancestry */
 			free(commit->buffer);
diff --git a/cache.h b/cache.h
index f2dabef..342b410 100644
--- a/cache.h
+++ b/cache.h
@@ -527,6 +527,7 @@
 extern int hold_lock_file_for_update(struct lock_file *, const char *path, int);
 extern int hold_lock_file_for_append(struct lock_file *, const char *path, int);
 extern int commit_lock_file(struct lock_file *);
+extern void update_index_if_able(struct index_state *, struct lock_file *);
 
 extern int hold_locked_index(struct lock_file *, int);
 extern int commit_locked_index(struct lock_file *);
@@ -540,6 +541,7 @@
 extern int trust_ctime;
 extern int quote_path_fully;
 extern int has_symlinks;
+extern int minimum_abbrev, default_abbrev;
 extern int ignore_case;
 extern int assume_unchanged;
 extern int prefer_symlink_refs;
@@ -759,8 +761,8 @@
 }
 
 /* Convert to/from hex/sha1 representation */
-#define MINIMUM_ABBREV 4
-#define DEFAULT_ABBREV 7
+#define MINIMUM_ABBREV minimum_abbrev
+#define DEFAULT_ABBREV default_abbrev
 
 struct object_context {
 	unsigned char tree[20];
@@ -999,6 +1001,7 @@
 extern int git_config_string(const char **, const char *, const char *);
 extern int git_config_pathname(const char **, const char *, const char *);
 extern int git_config_set(const char *, const char *);
+extern int git_config_parse_key(const char *, char **, int *);
 extern int git_config_set_multivar(const char *, const char *, const char *, int);
 extern int git_config_rename_section(const char *, const char *);
 extern const char *git_etc_gitconfig(void);
diff --git a/config.c b/config.c
index 822ef83..749e5af 100644
--- a/config.c
+++ b/config.c
@@ -523,6 +523,14 @@
 		return 0;
 	}
 
+	if (!strcmp(var, "core.abbrev")) {
+		int abbrev = git_config_int(var, value);
+		if (abbrev < minimum_abbrev || abbrev > 40)
+			return -1;
+		default_abbrev = abbrev;
+		return 0;
+	}
+
 	if (!strcmp(var, "core.loosecompression")) {
 		int level = git_config_int(var, value);
 		if (level == -1)
@@ -1093,6 +1101,75 @@
 }
 
 /*
+ * Auxiliary function to sanity-check and split the key into the section
+ * identifier and variable name.
+ *
+ * Returns 0 on success, -1 when there is an invalid character in the key and
+ * -2 if there is no section name in the key.
+ *
+ * store_key - pointer to char* which will hold a copy of the key with
+ *             lowercase section and variable name
+ * baselen - pointer to int which will hold the length of the
+ *           section + subsection part, can be NULL
+ */
+int git_config_parse_key(const char *key, char **store_key, int *baselen_)
+{
+	int i, dot, baselen;
+	const char *last_dot = strrchr(key, '.');
+
+	/*
+	 * Since "key" actually contains the section name and the real
+	 * key name separated by a dot, we have to know where the dot is.
+	 */
+
+	if (last_dot == NULL || last_dot == key) {
+		error("key does not contain a section: %s", key);
+		return -2;
+	}
+
+	if (!last_dot[1]) {
+		error("key does not contain variable name: %s", key);
+		return -2;
+	}
+
+	baselen = last_dot - key;
+	if (baselen_)
+		*baselen_ = baselen;
+
+	/*
+	 * Validate the key and while at it, lower case it for matching.
+	 */
+	*store_key = xmalloc(strlen(key) + 1);
+
+	dot = 0;
+	for (i = 0; key[i]; i++) {
+		unsigned char c = key[i];
+		if (c == '.')
+			dot = 1;
+		/* Leave the extended basename untouched.. */
+		if (!dot || i > baselen) {
+			if (!iskeychar(c) ||
+			    (i == baselen + 1 && !isalpha(c))) {
+				error("invalid key: %s", key);
+				goto out_free_ret_1;
+			}
+			c = tolower(c);
+		} else if (c == '\n') {
+			error("invalid key (newline): %s", key);
+			goto out_free_ret_1;
+		}
+		(*store_key)[i] = c;
+	}
+	(*store_key)[i] = 0;
+
+	return 0;
+
+out_free_ret_1:
+	free(*store_key);
+	return -1;
+}
+
+/*
  * If value==NULL, unset in (remove from) config,
  * if value_regex!=NULL, disregard key/value pairs where value does not match.
  * if multi_replace==0, nothing, or only one matching key/value is replaced,
@@ -1118,59 +1195,23 @@
 int git_config_set_multivar(const char *key, const char *value,
 	const char *value_regex, int multi_replace)
 {
-	int i, dot;
 	int fd = -1, in_fd;
 	int ret;
 	char *config_filename;
 	struct lock_file *lock = NULL;
-	const char *last_dot = strrchr(key, '.');
 
 	if (config_exclusive_filename)
 		config_filename = xstrdup(config_exclusive_filename);
 	else
 		config_filename = git_pathdup("config");
 
-	/*
-	 * Since "key" actually contains the section name and the real
-	 * key name separated by a dot, we have to know where the dot is.
-	 */
-
-	if (last_dot == NULL) {
-		error("key does not contain a section: %s", key);
-		ret = 2;
+	/* parse-key returns negative; flip the sign to feed exit(3) */
+	ret = 0 - git_config_parse_key(key, &store.key, &store.baselen);
+	if (ret)
 		goto out_free;
-	}
-	store.baselen = last_dot - key;
 
 	store.multi_replace = multi_replace;
 
-	/*
-	 * Validate the key and while at it, lower case it for matching.
-	 */
-	store.key = xmalloc(strlen(key) + 1);
-	dot = 0;
-	for (i = 0; key[i]; i++) {
-		unsigned char c = key[i];
-		if (c == '.')
-			dot = 1;
-		/* Leave the extended basename untouched.. */
-		if (!dot || i > store.baselen) {
-			if (!iskeychar(c) || (i == store.baselen+1 && !isalpha(c))) {
-				error("invalid key: %s", key);
-				free(store.key);
-				ret = 1;
-				goto out_free;
-			}
-			c = tolower(c);
-		} else if (c == '\n') {
-			error("invalid key (newline): %s", key);
-			free(store.key);
-			ret = 1;
-			goto out_free;
-		}
-		store.key[i] = c;
-	}
-	store.key[i] = 0;
 
 	/*
 	 * The lock serves a purpose in addition to locking: the new
diff --git a/diff-lib.c b/diff-lib.c
index 392ce2b..f8e3325 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -103,7 +103,8 @@
 		unsigned dirty_submodule = 0;
 
 		if (DIFF_OPT_TST(&revs->diffopt, QUICK) &&
-			DIFF_OPT_TST(&revs->diffopt, HAS_CHANGES))
+		    !revs->diffopt.filter &&
+		    DIFF_OPT_TST(&revs->diffopt, HAS_CHANGES))
 			break;
 
 		if (!ce_path_match(ce, revs->prune_data))
diff --git a/environment.c b/environment.c
index c3efbb9..33c8064 100644
--- a/environment.c
+++ b/environment.c
@@ -15,6 +15,7 @@
 int trust_executable_bit = 1;
 int trust_ctime = 1;
 int has_symlinks = 1;
+int minimum_abbrev = 4, default_abbrev = 7;
 int ignore_case;
 int assume_unchanged;
 int prefer_symlink_refs;
diff --git a/git-compat-util.h b/git-compat-util.h
index bf947b1..79b5122 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -118,6 +118,7 @@
 #endif
 #ifndef __MINGW32__
 #include <sys/wait.h>
+#include <sys/resource.h>
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #include <termios.h>
diff --git a/git-cvsimport.perl b/git-cvsimport.perl
index 8e683e5..bbf327f 100755
--- a/git-cvsimport.perl
+++ b/git-cvsimport.perl
@@ -366,7 +366,9 @@
 	$self->{'socketo'}->write("valid-requests\n");
 	$self->{'socketo'}->flush();
 
-	chomp(my $rep=$self->readline());
+	my $rep=$self->readline();
+	die "Failed to read from server" unless defined $rep;
+	chomp($rep);
 	if ($rep !~ s/^Valid-requests\s*//) {
 		$rep="<unknown>" unless $rep;
 		die "Expected Valid-requests from server, but got: $rep\n";
diff --git a/git-instaweb.sh b/git-instaweb.sh
index 10fcebb..8bfa8a0 100755
--- a/git-instaweb.sh
+++ b/git-instaweb.sh
@@ -558,12 +558,14 @@
 
 # make it runnable as standalone app,
 # like it would be run via 'plackup' utility
-if (__FILE__ eq \$0) {
+if (caller) {
+	return \$app;
+} else {
 	require Plack::Runner;
 
 	my \$runner = Plack::Runner->new();
 	\$runner->parse_options(qw(--env deployment --port $port),
-			       "$local" ? qw(--host 127.0.0.1) : ());
+				"$local" ? qw(--host 127.0.0.1) : ());
 	\$runner->run(\$app);
 }
 __END__
diff --git a/git-parse-remote.sh b/git-parse-remote.sh
index d3782d9..9b950be 100644
--- a/git-parse-remote.sh
+++ b/git-parse-remote.sh
@@ -56,7 +56,7 @@
 
 get_default_remote () {
 	curr_branch=$(git symbolic-ref -q HEAD)
-	curr_branch="${cur_branch#refs/heads/}"
+	curr_branch="${curr_branch#refs/heads/}"
 	origin=$(git config --get "branch.$curr_branch.remote")
 	echo ${origin:-origin}
 }
diff --git a/git-pull.sh b/git-pull.sh
index f6b7b84..c98c0fc 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -272,7 +272,7 @@
 if test -z "$orig_head"
 then
 	git update-ref -m "initial pull" HEAD $merge_head "$curr_head" &&
-	git read-tree --reset -u HEAD || exit 1
+	git read-tree -m -u HEAD || exit 1
 	exit
 fi
 
diff --git a/git-stash.sh b/git-stash.sh
index 7561b37..a305fb1 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -12,12 +12,14 @@
 
 SUBDIRECTORY_OK=Yes
 OPTIONS_SPEC=
+START_DIR=`pwd`
 . git-sh-setup
 require_work_tree
 cd_to_toplevel
 
 TMP="$GIT_DIR/.git-stash.$$"
-trap 'rm -f "$TMP-*"' 0
+TMPindex=${GIT_INDEX_FILE-"$GIT_DIR/index"}.stash.$$
+trap 'rm -f "$TMP-"* "$TMPindex"' 0
 
 ref_stash=refs/stash
 
@@ -81,14 +83,12 @@
 
 		# state of the working tree
 		w_tree=$( (
-			rm -f "$TMP-index" &&
-			cp -p ${GIT_INDEX_FILE-"$GIT_DIR/index"} "$TMP-index" &&
-			GIT_INDEX_FILE="$TMP-index" &&
+			git read-tree --index-output="$TMPindex" -m $i_tree &&
+			GIT_INDEX_FILE="$TMPindex" &&
 			export GIT_INDEX_FILE &&
-			git read-tree -m $i_tree &&
 			git diff --name-only -z HEAD | git update-index -z --add --remove --stdin &&
 			git write-tree &&
-			rm -f "$TMP-index"
+			rm -f "$TMPindex"
 		) ) ||
 			die "Cannot save the current worktree state"
 
@@ -394,7 +394,7 @@
 		then
 			squelch='>/dev/null 2>&1'
 		fi
-		eval "git status $squelch" || :
+		(cd "$START_DIR" && eval "git status $squelch") || :
 	else
 		# Merge conflict; keep the exit status from merge-recursive
 		status=$?
diff --git a/gitweb/static/gitweb.js b/gitweb/static/gitweb.js
index 9c66928..40ec084 100644
--- a/gitweb/static/gitweb.js
+++ b/gitweb/static/gitweb.js
@@ -399,7 +399,24 @@
  * used to extract hours and minutes from timezone info, e.g '-0900'
  * @constant
  */
-var tzRe = /^([+-][0-9][0-9])([0-9][0-9])$/;
+var tzRe = /^([+-])([0-9][0-9])([0-9][0-9])$/;
+
+/**
+ * convert numeric timezone +/-ZZZZ to offset from UTC in seconds
+ *
+ * @param {String} timezoneInfo: numeric timezone '(+|-)HHMM'
+ * @returns {Number} offset from UTC in seconds for timezone
+ *
+ * @globals tzRe
+ */
+function timezoneOffset(timezoneInfo) {
+	var match = tzRe.exec(timezoneInfo);
+	var tz_sign = (match[1] === '-' ? -1 : +1);
+	var tz_hour = parseInt(match[2],10);
+	var tz_min  = parseInt(match[3],10);
+
+	return tz_sign*(((tz_hour*60) + tz_min)*60);
+}
 
 /**
  * return date in local time formatted in iso-8601 like format
@@ -408,14 +425,11 @@
  * @param {Number} epoch: seconds since '00:00:00 1970-01-01 UTC'
  * @param {String} timezoneInfo: numeric timezone '(+|-)HHMM'
  * @returns {String} date in local time in iso-8601 like format
- *
- * @globals tzRe
  */
 function formatDateISOLocal(epoch, timezoneInfo) {
-	var match = tzRe.exec(timezoneInfo);
 	// date corrected by timezone
 	var localDate = new Date(1000 * (epoch +
-		(parseInt(match[1],10)*3600 + parseInt(match[2],10)*60)));
+		timezoneOffset(timezoneInfo)));
 	var localDateStr = // e.g. '2005-08-07'
 		localDate.getUTCFullYear()                 + '-' +
 		padLeft(localDate.getUTCMonth()+1, 2, '0') + '-' +
diff --git a/list-objects.c b/list-objects.c
index 8953548..44fa5a9 100644
--- a/list-objects.c
+++ b/list-objects.c
@@ -148,7 +148,12 @@
 	struct commit *commit;
 
 	while ((commit = get_revision(revs)) != NULL) {
-		add_pending_tree(revs, commit->tree);
+		/*
+		 * an uninteresting boundary commit may not have its tree
+		 * parsed yet, but we are not going to show them anyway
+		 */
+		if (commit->tree)
+			add_pending_tree(revs, commit->tree);
 		show_commit(commit, data);
 	}
 	for (i = 0; i < revs->pending.nr; i++) {
diff --git a/pretty.c b/pretty.c
index 8549934..65d20a7 100644
--- a/pretty.c
+++ b/pretty.c
@@ -216,36 +216,53 @@
 static void add_rfc2047(struct strbuf *sb, const char *line, int len,
 		       const char *encoding)
 {
-	int i, last;
+	static const int max_length = 78; /* per rfc2822 */
+	int i;
+	int line_len;
+
+	/* How many bytes are already used on the current line? */
+	for (i = sb->len - 1; i >= 0; i--)
+		if (sb->buf[i] == '\n')
+			break;
+	line_len = sb->len - (i+1);
 
 	for (i = 0; i < len; i++) {
 		int ch = line[i];
-		if (non_ascii(ch))
+		if (non_ascii(ch) || ch == '\n')
 			goto needquote;
 		if ((i + 1 < len) && (ch == '=' && line[i+1] == '?'))
 			goto needquote;
 	}
-	strbuf_add(sb, line, len);
+	strbuf_add_wrapped_bytes(sb, line, len, 0, 1, max_length - line_len);
 	return;
 
 needquote:
 	strbuf_grow(sb, len * 3 + strlen(encoding) + 100);
 	strbuf_addf(sb, "=?%s?q?", encoding);
-	for (i = last = 0; i < len; i++) {
+	line_len += strlen(encoding) + 5; /* 5 for =??q? */
+	for (i = 0; i < len; i++) {
 		unsigned ch = line[i] & 0xFF;
+
+		if (line_len >= max_length - 2) {
+			strbuf_addf(sb, "?=\n =?%s?q?", encoding);
+			line_len = strlen(encoding) + 5 + 1; /* =??q? plus SP */
+		}
+
 		/*
 		 * We encode ' ' using '=20' even though rfc2047
 		 * allows using '_' for readability.  Unfortunately,
 		 * many programs do not understand this and just
 		 * leave the underscore in place.
 		 */
-		if (is_rfc2047_special(ch) || ch == ' ') {
-			strbuf_add(sb, line + last, i - last);
+		if (is_rfc2047_special(ch) || ch == ' ' || ch == '\n') {
 			strbuf_addf(sb, "=%02X", ch);
-			last = i + 1;
+			line_len += 3;
+		}
+		else {
+			strbuf_addch(sb, ch);
+			line_len++;
 		}
 	}
-	strbuf_add(sb, line + last, len - last);
 	strbuf_addstr(sb, "?=");
 }
 
@@ -1106,11 +1123,10 @@
 		   const char *encoding,
 		   int need_8bit_cte)
 {
-	const char *line_separator = (fmt == CMIT_FMT_EMAIL) ? "\n " : " ";
 	struct strbuf title;
 
 	strbuf_init(&title, 80);
-	*msg_p = format_subject(&title, *msg_p, line_separator);
+	*msg_p = format_subject(&title, *msg_p, " ");
 
 	strbuf_grow(sb, title.len + 1024);
 	if (subject) {
diff --git a/read-cache.c b/read-cache.c
index 4f2e890..0480d94 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -1568,6 +1568,31 @@
 	return result;
 }
 
+static int has_racy_timestamp(struct index_state *istate)
+{
+	int entries = istate->cache_nr;
+	int i;
+
+	for (i = 0; i < entries; i++) {
+		struct cache_entry *ce = istate->cache[i];
+		if (is_racy_timestamp(istate, ce))
+			return 1;
+	}
+	return 0;
+}
+
+/*
+ * Opportunisticly update the index but do not complain if we can't
+ */
+void update_index_if_able(struct index_state *istate, struct lock_file *lockfile)
+{
+	if ((istate->cache_changed || has_racy_timestamp(istate)) &&
+	    !write_index(istate, lockfile->fd))
+		commit_locked_index(lockfile);
+	else
+		rollback_lock_file(lockfile);
+}
+
 int write_index(struct index_state *istate, int newfd)
 {
 	git_SHA_CTX c;
diff --git a/symlinks.c b/symlinks.c
index 3cacebd..034943b 100644
--- a/symlinks.c
+++ b/symlinks.c
@@ -223,7 +223,7 @@
 	int flags;
 	int match_len = lstat_cache_matchlen(cache, name, len, &flags,
 			   FL_SYMLINK|FL_NOENT|FL_DIR, USE_ONLY_LSTAT);
-	if (flags & (FL_SYMLINK|FL_NOENT))
+	if (flags & FL_NOENT)
 		return 0;
 	else if (flags & FL_DIR)
 		return -1;
diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index d0e5546..53fb822 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -876,11 +876,25 @@
 	"
 
 test_expect_success 'git -c "key=value" support' '
-	test "z$(git -c name=value config name)" = zvalue &&
 	test "z$(git -c core.name=value config core.name)" = zvalue &&
-	test "z$(git -c CamelCase=value config camelcase)" = zvalue &&
-	test "z$(git -c flag config --bool flag)" = ztrue &&
-	test_must_fail git -c core.name=value config name
+	test "z$(git -c foo.CamelCase=value config foo.camelcase)" = zvalue &&
+	test "z$(git -c foo.flag config --bool foo.flag)" = ztrue &&
+	test_must_fail git -c name=value config core.name
+'
+
+test_expect_success 'key sanity-checking' '
+	test_must_fail git config foo=bar &&
+	test_must_fail git config foo=.bar &&
+	test_must_fail git config foo.ba=r &&
+	test_must_fail git config foo.1bar &&
+	test_must_fail git config foo."ba
+				z".bar &&
+	test_must_fail git config . false &&
+	test_must_fail git config .foo false &&
+	test_must_fail git config foo. false &&
+	test_must_fail git config .foo. false &&
+	git config foo.bar true &&
+	git config foo."ba =z".bar false
 '
 
 test_done
diff --git a/t/t2019-checkout-ambiguous-ref.sh b/t/t2019-checkout-ambiguous-ref.sh
new file mode 100755
index 0000000..943541d
--- /dev/null
+++ b/t/t2019-checkout-ambiguous-ref.sh
@@ -0,0 +1,59 @@
+#!/bin/sh
+
+test_description='checkout handling of ambiguous (branch/tag) refs'
+. ./test-lib.sh
+
+test_expect_success 'setup ambiguous refs' '
+	test_commit branch file &&
+	git branch ambiguity &&
+	git branch vagueness &&
+	test_commit tag file &&
+	git tag ambiguity &&
+	git tag vagueness HEAD:file &&
+	test_commit other file
+'
+
+test_expect_success 'checkout ambiguous ref succeeds' '
+	git checkout ambiguity >stdout 2>stderr
+'
+
+test_expect_success 'checkout produces ambiguity warning' '
+	grep "warning.*ambiguous" stderr
+'
+
+test_expect_success 'checkout chooses branch over tag' '
+	echo refs/heads/ambiguity >expect &&
+	git symbolic-ref HEAD >actual &&
+	test_cmp expect actual &&
+	echo branch >expect &&
+	test_cmp expect file
+'
+
+test_expect_success 'checkout reports switch to branch' '
+	grep "Switched to branch" stderr &&
+	! grep "^HEAD is now at" stderr
+'
+
+test_expect_success 'checkout vague ref succeeds' '
+	git checkout vagueness >stdout 2>stderr &&
+	test_set_prereq VAGUENESS_SUCCESS
+'
+
+test_expect_success VAGUENESS_SUCCESS 'checkout produces ambiguity warning' '
+	grep "warning.*ambiguous" stderr
+'
+
+test_expect_success VAGUENESS_SUCCESS 'checkout chooses branch over tag' '
+	echo refs/heads/vagueness >expect &&
+	git symbolic-ref HEAD >actual &&
+	test_cmp expect actual &&
+	echo branch >expect &&
+	test_cmp expect file
+'
+
+test_expect_success VAGUENESS_SUCCESS 'checkout reports switch to branch' '
+	grep "Switched to branch" stderr &&
+	! grep "^HEAD is now at" stderr
+'
+
+test_done
diff --git a/t/t2021-checkout-overwrite.sh b/t/t2021-checkout-overwrite.sh
new file mode 100755
index 0000000..27db2ad
--- /dev/null
+++ b/t/t2021-checkout-overwrite.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+test_description='checkout must not overwrite an untracked objects'
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+
+	mkdir -p a/b/c &&
+	>a/b/c/d &&
+	git add -A &&
+	git commit -m base &&
+	git tag start
+'
+
+test_expect_success 'create a commit where dir a/b changed to file' '
+
+	git checkout -b file &&
+	rm -rf a/b &&
+	>a/b &&
+	git add -A &&
+	git commit -m "dir to file"
+'
+
+test_expect_success 'checkout commit with dir must not remove untracked a/b' '
+
+	git rm --cached a/b &&
+	git commit -m "un-track the file" &&
+	test_must_fail git checkout start &&
+	test -f a/b
+'
+
+test_expect_success SYMLINKS 'create a commit where dir a/b changed to symlink' '
+
+	rm -rf a/b &&	# cleanup if previous test failed
+	git checkout -f -b symlink start &&
+	rm -rf a/b &&
+	ln -s foo a/b &&
+	git add -A &&
+	git commit -m "dir to symlink"
+'
+
+test_expect_failure SYMLINKS 'checkout commit with dir must not remove untracked a/b' '
+
+	git rm --cached a/b &&
+	git commit -m "un-track the symlink" &&
+	test_must_fail git checkout start &&
+	test -h a/b
+'
+
+test_done
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index f308235..78ce09f 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -223,6 +223,11 @@
     'branch from non-branch HEAD w/--track causes failure' \
     'test_must_fail git branch --track my10 HEAD^'
 
+test_expect_success \
+    'branch from tag w/--track causes failure' \
+    'git tag foobar &&
+     test_must_fail git branch --track my11 foobar'
+
 # Keep this test last, as it changes the current branch
 cat >expect <<EOF
 0000000000000000000000000000000000000000 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000	branch: Created from master
@@ -488,6 +493,15 @@
 	test "z$(git config branch.myr20.rebase)" = z
 '
 
+test_expect_success 'autosetuprebase always on detached HEAD' '
+	git config branch.autosetupmerge always &&
+	test_when_finished git checkout master &&
+	git checkout HEAD^0 &&
+	git branch my11 &&
+	test -z "$(git config branch.my11.remote)" &&
+	test -z "$(git config branch.my11.merge)"
+'
+
 test_expect_success 'detect misconfigured autosetuprebase (bad value)' '
 	git config branch.autosetuprebase garbage &&
 	test_must_fail git branch
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index 6fd560c..f62aaf5 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -556,4 +556,23 @@
 	git rev-parse stash@{0} --
 '
 
+test_expect_success 'stash apply shows status same as git status (relative to current directory)' '
+	git stash clear &&
+	echo 1 >subdir/subfile1 &&
+	echo 2 >subdir/subfile2 &&
+	git add subdir/subfile1 &&
+	git commit -m subdir &&
+	(
+		cd subdir &&
+		echo x >subfile1 &&
+		echo x >../file &&
+		git status >../expect &&
+		git stash &&
+		sane_unset GIT_MERGE_VERBOSITY &&
+		git stash apply
+	) |
+	sed -e 1,2d >actual && # drop "Saved..." and "HEAD is now..."
+	test_cmp expect actual
+'
+
 test_done
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index b8f81d0..5daa0f2 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -210,6 +210,9 @@
 log -SF master
 log -S F master
 log -SF -p master
+log -SF master --max-count=0
+log -SF master --max-count=1
+log -SF master --max-count=2
 log -GF master
 log -GF -p master
 log -GF -p --pickaxe-all master
diff --git a/t/t4013/diff.log_-SF_master_--max-count=0 b/t/t4013/diff.log_-SF_master_--max-count=0
new file mode 100644
index 0000000..c1fc6c8
--- /dev/null
+++ b/t/t4013/diff.log_-SF_master_--max-count=0
@@ -0,0 +1,2 @@
+$ git log -SF master --max-count=0
+$
diff --git a/t/t4013/diff.log_-SF_master_--max-count=1 b/t/t4013/diff.log_-SF_master_--max-count=1
new file mode 100644
index 0000000..c981a03
--- /dev/null
+++ b/t/t4013/diff.log_-SF_master_--max-count=1
@@ -0,0 +1,7 @@
+$ git log -SF master --max-count=1
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
+Author: A U Thor <author@example.com>
+Date:   Mon Jun 26 00:02:00 2006 +0000
+
+    Third
+$
diff --git a/t/t4013/diff.log_-SF_master_--max-count=2 b/t/t4013/diff.log_-SF_master_--max-count=2
new file mode 100644
index 0000000..a6c55fd
--- /dev/null
+++ b/t/t4013/diff.log_-SF_master_--max-count=2
@@ -0,0 +1,7 @@
+$ git log -SF master --max-count=2
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
+Author: A U Thor <author@example.com>
+Date:   Mon Jun 26 00:02:00 2006 +0000
+
+    Third
+$
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index 027c13d..9c66367 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -709,4 +709,88 @@
 	test_path_is_missing .git/pager_used
 '
 
+test_expect_success 'format-patch handles multi-line subjects' '
+	rm -rf patches/ &&
+	echo content >>file &&
+	for i in one two three; do echo $i; done >msg &&
+	git add file &&
+	git commit -F msg &&
+	git format-patch -o patches -1 &&
+	grep ^Subject: patches/0001-one.patch >actual &&
+	echo "Subject: [PATCH] one two three" >expect &&
+	test_cmp expect actual
+'
+
+test_expect_success 'format-patch handles multi-line encoded subjects' '
+	rm -rf patches/ &&
+	echo content >>file &&
+	for i in en två tre; do echo $i; done >msg &&
+	git add file &&
+	git commit -F msg &&
+	git format-patch -o patches -1 &&
+	grep ^Subject: patches/0001-en.patch >actual &&
+	echo "Subject: [PATCH] =?UTF-8?q?en=20tv=C3=A5=20tre?=" >expect &&
+	test_cmp expect actual
+'
+
+M8="foo bar "
+M64=$M8$M8$M8$M8$M8$M8$M8$M8
+M512=$M64$M64$M64$M64$M64$M64$M64$M64
+cat >expect <<'EOF'
+Subject: [PATCH] foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
+ bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
+ foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
+ bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
+ foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
+ bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
+ foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo
+ bar foo bar foo bar foo bar foo bar foo bar foo bar foo bar
+ foo bar foo bar foo bar foo bar
+EOF
+test_expect_success 'format-patch wraps extremely long headers (ascii)' '
+	echo content >>file &&
+	git add file &&
+	git commit -m "$M512" &&
+	git format-patch --stdout -1 >patch &&
+	sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
+	test_cmp expect subject
+'
+
+M8="föö bar "
+M64=$M8$M8$M8$M8$M8$M8$M8$M8
+M512=$M64$M64$M64$M64$M64$M64$M64$M64
+cat >expect <<'EOF'
+Subject: [PATCH] =?UTF-8?q?f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6=C3=B6=20bar=20f=C3=B6?=
+ =?UTF-8?q?=C3=B6=20bar=20f=C3=B6=C3=B6=20bar?=
+EOF
+test_expect_success 'format-patch wraps extremely long headers (rfc2047)' '
+	rm -rf patches/ &&
+	echo content >>file &&
+	git add file &&
+	git commit -m "$M512" &&
+	git format-patch --stdout -1 >patch &&
+	sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject &&
+	test_cmp expect subject
+'
+
 test_done
diff --git a/t/t4040-whitespace-status.sh b/t/t4040-whitespace-status.sh
index a30b03b..abc4934 100755
--- a/t/t4040-whitespace-status.sh
+++ b/t/t4040-whitespace-status.sh
@@ -60,4 +60,11 @@
 	git diff-files -b -p --exit-code
 '
 
+test_expect_success 'diff-files --diff-filter --quiet' '
+	git reset --hard &&
+	rm a/d &&
+	echo x >>b/e &&
+	test_must_fail git diff-files --diff-filter=M --quiet
+'
+
 test_done
diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh
index 0470a81..0e5eb67 100755
--- a/t/t5520-pull.sh
+++ b/t/t5520-pull.sh
@@ -46,6 +46,17 @@
 	test_cmp file cloned-uho/file
 '
 
+test_expect_success 'pulling into void does not overwrite untracked files' '
+	git init cloned-untracked &&
+	(
+		cd cloned-untracked &&
+		echo untracked >file &&
+		test_must_fail git pull .. master &&
+		echo untracked >expect &&
+		test_cmp expect file
+	)
+'
+
 test_expect_success 'test . as a remote' '
 
 	git branch copy master &&
diff --git a/t/t6035-merge-dir-to-symlink.sh b/t/t6035-merge-dir-to-symlink.sh
index 92e02d5..2599ae5 100755
--- a/t/t6035-merge-dir-to-symlink.sh
+++ b/t/t6035-merge-dir-to-symlink.sh
@@ -17,13 +17,21 @@
 	git commit -m "dir to symlink"
 '
 
-test_expect_success SYMLINKS 'keep a/b-2/c/d across checkout' '
+test_expect_success SYMLINKS 'checkout does not clobber untracked symlink' '
 	git checkout HEAD^0 &&
 	git reset --hard master &&
 	git rm --cached a/b &&
 	git commit -m "untracked symlink remains" &&
-	 git checkout start^0 &&
-	 test -f a/b-2/c/d
+	test_must_fail git checkout start^0
+'
+
+test_expect_success SYMLINKS 'a/b-2/c/d is kept when clobbering symlink b' '
+	git checkout HEAD^0 &&
+	git reset --hard master &&
+	git rm --cached a/b &&
+	git commit -m "untracked symlink remains" &&
+	git checkout -f start^0 &&
+	test -f a/b-2/c/d
 '
 
 test_expect_success SYMLINKS 'checkout should not have deleted a/b-2/c/d' '
diff --git a/t/t6040-tracking-info.sh b/t/t6040-tracking-info.sh
index 1e0447f..cb85132 100755
--- a/t/t6040-tracking-info.sh
+++ b/t/t6040-tracking-info.sh
@@ -74,20 +74,20 @@
 	grep "have 1 and 1 different" actual
 '
 
-test_expect_success 'status when tracking lightweight tags' '
+test_expect_success 'fail to track lightweight tags' '
 	git checkout master &&
 	git tag light &&
-	git branch --track lighttrack light >actual &&
-	grep "set up to track" actual &&
-	git checkout lighttrack
+	test_must_fail git branch --track lighttrack light >actual &&
+	test_must_fail grep "set up to track" actual &&
+	test_must_fail git checkout lighttrack
 '
 
-test_expect_success 'status when tracking annotated tags' '
+test_expect_success 'fail to track annotated tags' '
 	git checkout master &&
 	git tag -m heavy heavy &&
-	git branch --track heavytrack heavy >actual &&
-	grep "set up to track" actual &&
-	git checkout heavytrack
+	test_must_fail git branch --track heavytrack heavy >actual &&
+	test_must_fail grep "set up to track" actual &&
+	test_must_fail git checkout heavytrack
 '
 
 test_expect_success 'setup tracking with branch --set-upstream on existing branch' '
diff --git a/t/t6110-rev-list-sparse.sh b/t/t6110-rev-list-sparse.sh
new file mode 100755
index 0000000..2a267e8
--- /dev/null
+++ b/t/t6110-rev-list-sparse.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+test_description='operations that cull histories in unusual ways'
+. ./test-lib.sh
+
+test_commit () {
+	echo "$1" >"$1.file" &&
+	git add "$1.file" &&
+	test_tick &&
+	git commit -m "$1"
+}
+
+test_expect_success setup '
+	test_commit A &&
+	test_commit B &&
+	test_commit C &&
+	git checkout -b side HEAD^ &&
+	test_commit D &&
+	test_commit E &&
+	git merge master
+'
+
+test_expect_success 'rev-list --first-parent --boundary' '
+	git rev-list --first-parent --boundary HEAD^..
+'
+
+test_done
diff --git a/t/t7201-co.sh b/t/t7201-co.sh
index 1337fa5..0c002ab 100755
--- a/t/t7201-co.sh
+++ b/t/t7201-co.sh
@@ -408,6 +408,15 @@
     test "z$(git rev-parse master^0)" = "z$(git rev-parse HEAD)"
 '
 
+test_expect_success 'checkout w/--track from tag fails' '
+    git checkout master^0 &&
+    test_must_fail git symbolic-ref HEAD &&
+    test_must_fail git checkout --track -b track frotz &&
+    test_must_fail git rev-parse --verify track &&
+    test_must_fail git symbolic-ref HEAD &&
+    test "z$(git rev-parse master^0)" = "z$(git rev-parse HEAD)"
+'
+
 test_expect_success 'detach a symbolic link HEAD' '
     git checkout master &&
     git config --bool core.prefersymlinkrefs yes &&
@@ -423,7 +432,6 @@
 test_expect_success \
     'checkout with --track fakes a sensible -b <name>' '
     git update-ref refs/remotes/origin/koala/bear renamer &&
-    git update-ref refs/new/koala/bear renamer &&
 
     git checkout --track origin/koala/bear &&
     test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
@@ -439,12 +447,6 @@
 
     git checkout --track remotes/origin/koala/bear &&
     test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
-    test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" &&
-
-    git checkout master && git branch -D koala/bear &&
-
-    git checkout --track refs/new/koala/bear &&
-    test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" &&
     test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)"
 '
 
diff --git a/utf8.c b/utf8.c
index 84cfc72..8acbc66 100644
--- a/utf8.c
+++ b/utf8.c
@@ -405,6 +405,15 @@
 	}
 }
 
+int strbuf_add_wrapped_bytes(struct strbuf *buf, const char *data, int len,
+			     int indent, int indent2, int width)
+{
+	char *tmp = xstrndup(data, len);
+	int r = strbuf_add_wrapped_text(buf, tmp, indent, indent2, width);
+	free(tmp);
+	return r;
+}
+
 int is_encoding_utf8(const char *name)
 {
 	if (!name)
diff --git a/utf8.h b/utf8.h
index ebc4d2f..81f2c82 100644
--- a/utf8.h
+++ b/utf8.h
@@ -10,6 +10,8 @@
 
 int strbuf_add_wrapped_text(struct strbuf *buf,
 		const char *text, int indent, int indent2, int width);
+int strbuf_add_wrapped_bytes(struct strbuf *buf, const char *data, int len,
+			     int indent, int indent2, int width);
 
 #ifndef NO_ICONV
 char *reencode_string(const char *in, const char *out_encoding, const char *in_encoding);