Sync with 2.2.3
diff --git a/Documentation/RelNotes/2.2.3.txt b/Documentation/RelNotes/2.2.3.txt
new file mode 100644
index 0000000..5bfffa4
--- /dev/null
+++ b/Documentation/RelNotes/2.2.3.txt
@@ -0,0 +1,9 @@
+Git v2.2.3 Release Notes
+========================
+
+Fixes since v2.2.2
+------------------
+
+ * A handful of codepaths that used to use fixed-sized arrays to hold
+   pathnames have been corrected to use strbuf and other mechanisms to
+   allow longer pathnames without fearing overflows.
diff --git a/Documentation/git.txt b/Documentation/git.txt
index adff610..9c46cab 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -56,9 +56,10 @@
   link:RelNotes/2.3.1.txt[2.3.1],
   link:RelNotes/2.3.0.txt[2.3].
 
-* link:v2.2.2/git.html[documentation for release 2.2.2]
+* link:v2.2.3/git.html[documentation for release 2.2.3]
 
 * release notes for
+  link:RelNotes/2.2.3.txt[2.2.3],
   link:RelNotes/2.2.2.txt[2.2.2],
   link:RelNotes/2.2.1.txt[2.2.1],
   link:RelNotes/2.2.0.txt[2.2].
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index 365228a..808225c 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -723,7 +723,6 @@
 
 	if (reflog) {
 		unsigned char sha1[20];
-		char nth_desc[256];
 		char *ref;
 		int base = 0;
 		unsigned int flags = 0;
@@ -762,6 +761,7 @@
 
 		for (i = 0; i < reflog; i++) {
 			char *logmsg;
+			char *nth_desc;
 			const char *msg;
 			unsigned long timestamp;
 			int tz;
@@ -780,8 +780,10 @@
 						show_date(timestamp, tz, 1),
 						msg);
 			free(logmsg);
-			sprintf(nth_desc, "%s@{%d}", *av, base+i);
+
+			nth_desc = xstrfmt("%s@{%d}", *av, base+i);
 			append_ref(nth_desc, sha1, 1);
+			free(nth_desc);
 		}
 		free(ref);
 	}
diff --git a/notes.c b/notes.c
index 2be4d7f..d465200 100644
--- a/notes.c
+++ b/notes.c
@@ -362,13 +362,14 @@
 	return strcmp(a->path, b->path);
 }
 
-static void add_non_note(struct notes_tree *t, const char *path,
+/* note: takes ownership of path string */
+static void add_non_note(struct notes_tree *t, char *path,
 		unsigned int mode, const unsigned char *sha1)
 {
 	struct non_note *p = t->prev_non_note, *n;
 	n = (struct non_note *) xmalloc(sizeof(struct non_note));
 	n->next = NULL;
-	n->path = xstrdup(path);
+	n->path = path;
 	n->mode = mode;
 	hashcpy(n->sha1, sha1);
 	t->prev_non_note = n;
@@ -482,17 +483,17 @@
 		 * component.
 		 */
 		{
-			char non_note_path[PATH_MAX];
-			char *p = non_note_path;
+			struct strbuf non_note_path = STRBUF_INIT;
 			const char *q = sha1_to_hex(subtree->key_sha1);
 			int i;
 			for (i = 0; i < prefix_len; i++) {
-				*p++ = *q++;
-				*p++ = *q++;
-				*p++ = '/';
+				strbuf_addch(&non_note_path, *q++);
+				strbuf_addch(&non_note_path, *q++);
+				strbuf_addch(&non_note_path, '/');
 			}
-			strcpy(p, entry.path);
-			add_non_note(t, non_note_path, entry.mode, entry.sha1);
+			strbuf_addstr(&non_note_path, entry.path);
+			add_non_note(t, strbuf_detach(&non_note_path, NULL),
+				     entry.mode, entry.sha1);
 		}
 	}
 	free(buf);
diff --git a/sha1_file.c b/sha1_file.c
index 88f06ba..ec3adca 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -377,15 +377,12 @@
 	char *map;
 	size_t mapsz;
 	struct stat st;
-	const char alt_file_name[] = "info/alternates";
-	/* Given that relative_base is no longer than PATH_MAX,
-	   ensure that "path" has enough space to append "/", the
-	   file name, "info/alternates", and a trailing NUL.  */
-	char path[PATH_MAX + 1 + sizeof alt_file_name];
+	char *path;
 	int fd;
 
-	sprintf(path, "%s/%s", relative_base, alt_file_name);
+	path = xstrfmt("%s/info/alternates", relative_base);
 	fd = git_open_noatime(path);
+	free(path);
 	if (fd < 0)
 		return;
 	if (fstat(fd, &st) || (st.st_size == 0)) {
diff --git a/unpack-trees.c b/unpack-trees.c
index be84ba2..17a5eeb 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -1434,15 +1434,18 @@
 	if (!len)
 		return 0;
 	else if (len > 0) {
-		char path[PATH_MAX + 1];
-		memcpy(path, ce->name, len);
-		path[len] = 0;
-		if (lstat(path, &st))
-			return error("cannot stat '%s': %s", path,
-					strerror(errno));
+		char *path;
+		int ret;
 
-		return check_ok_to_remove(path, len, DT_UNKNOWN, NULL, &st,
-				error_type, o);
+		path = xmemdupz(ce->name, len);
+		if (lstat(path, &st))
+			ret = error("cannot stat '%s': %s", path,
+					strerror(errno));
+		else
+			ret = check_ok_to_remove(path, len, DT_UNKNOWN, NULL,
+						 &st, error_type, o);
+		free(path);
+		return ret;
 	} else if (lstat(ce->name, &st)) {
 		if (errno != ENOENT)
 			return error("cannot stat '%s': %s", ce->name,