diff --git a/combine-diff.c b/combine-diff.c
index 216a77e0880..210ffcbce38 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -528,7 +528,7 @@ static void show_parent_lno(struct sline *sline, unsigned long l0, unsigned long
 {
 	l0 = sline[l0].p_lno[n];
 	l1 = sline[l1].p_lno[n];
-	printf("-%lu,%lu ", l0, l1-l0);
+	printf(" -%lu,%lu", l0, l1-l0);
 }
 
 static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent)
@@ -548,9 +548,9 @@ static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent)
 			if (!(sline[hunk_end].flag & mark))
 				break;
 		for (i = 0; i <= num_parent; i++) putchar(combine_marker);
-		printf(" +%lu,%lu ", lno+1, hunk_end-lno);
 		for (i = 0; i < num_parent; i++)
 			show_parent_lno(sline, lno, hunk_end, cnt, i);
+		printf(" +%lu,%lu ", lno+1, hunk_end-lno);
 		for (i = 0; i <= num_parent; i++) putchar(combine_marker);
 		putchar('\n');
 		while (lno < hunk_end) {
@@ -714,11 +714,11 @@ int show_combined_diff(struct combine_diff_path *elem, int num_parent,
 		printf("index ");
 		for (i = 0; i < num_parent; i++) {
 			printf("%s%s",
-			       i ? ".." : "",
+			       i ? "," : "",
 			       find_unique_abbrev(elem->parent_sha1[i],
 						  DEFAULT_ABBREV));
 		}
-		printf("->%s\n",
+		printf("..%s\n",
 		       find_unique_abbrev(elem->sha1, DEFAULT_ABBREV));
 		dump_sline(sline, cnt, num_parent);
 	}
diff --git a/http-fetch.c b/http-fetch.c
index 97ce13c44c3..72edf28b001 100644
--- a/http-fetch.c
+++ b/http-fetch.c
@@ -220,7 +220,6 @@ static void start_object_request(struct object_request *obj_req)
 		free(obj_req->url);
 		return;
 	}
-	
 }
 
 static void finish_object_request(struct object_request *obj_req)
@@ -326,7 +325,7 @@ void fill_active_slots(void)
 			slot->curl = NULL;
 		}
 		slot = slot->next;
-	}				
+	}
 }
 #endif
 
@@ -382,10 +381,10 @@ static int fetch_index(struct alt_base *repo, unsigned char *sha1)
 
 	if (get_verbosely)
 		fprintf(stderr, "Getting index for pack %s\n", hex);
-	
+
 	url = xmalloc(strlen(repo->base) + 64);
 	sprintf(url, "%s/objects/pack/pack-%s.idx", repo->base, hex);
-	
+
 	filename = sha1_pack_index_name(sha1);
 	snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
 	indexfile = fopen(tmpfile, "a");
@@ -504,7 +503,7 @@ static void process_alternates_response(void *callback_data)
 			} else if (!memcmp(data + i, "../", 3)) {
 				i += 3;
 				serverlen = strlen(base);
-				while (i + 2 < posn && 
+				while (i + 2 < posn &&
 				       !memcmp(data + i, "../", 3)) {
 					do {
 						serverlen--;
@@ -513,7 +512,7 @@ static void process_alternates_response(void *callback_data)
 					i += 3;
 				}
 				// If the server got removed, give up.
-				okay = strchr(base, ':') - base + 3 < 
+				okay = strchr(base, ':') - base + 3 <
 					serverlen;
 			} else if (alt_req->http_specific) {
 				char *colon = strchr(data + i, ':');
@@ -531,7 +530,7 @@ static void process_alternates_response(void *callback_data)
 					posn - i - 7);
 				target[serverlen + posn - i - 7] = '\0';
 				if (get_verbosely)
-					fprintf(stderr, 
+					fprintf(stderr,
 						"Also look at %s\n", target);
 				newalt = xmalloc(sizeof(*newalt));
 				newalt->next = NULL;
@@ -580,7 +579,7 @@ static void fetch_alternates(char *base)
 
 	if (get_verbosely)
 		fprintf(stderr, "Getting alternates list for %s\n", base);
-	
+
 	url = xmalloc(strlen(base) + 31);
 	sprintf(url, "%s/objects/info/http-alternates", base);
 
@@ -630,7 +629,7 @@ static int fetch_indices(struct alt_base *repo)
 
 	if (get_verbosely)
 		fprintf(stderr, "Getting pack list for %s\n", repo->base);
-	
+
 	url = xmalloc(strlen(repo->base) + 21);
 	sprintf(url, "%s/objects/info/packs", repo->base);
 
@@ -844,7 +843,7 @@ int fetch(unsigned char *sha1)
 		fetch_alternates(alt->base);
 		altbase = altbase->next;
 	}
-	return error("Unable to find %s under %s\n", sha1_to_hex(sha1), 
+	return error("Unable to find %s under %s\n", sha1_to_hex(sha1),
 		     alt->base);
 }
 
@@ -905,7 +904,7 @@ int fetch_ref(char *ref, unsigned char *sha1)
         buffer.posn = 0;
         buffer.buffer = hex;
         hex[41] = '\0';
-        
+
 	url = quote_ref_url(base, ref);
 	slot = get_active_slot();
 	slot->results = &results;
diff --git a/sha1_name.c b/sha1_name.c
index ba0747c84dd..fa85d8a88d3 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -388,43 +388,36 @@ static int peel_onion(const char *name, int len, unsigned char *sha1)
 
 static int get_sha1_1(const char *name, int len, unsigned char *sha1)
 {
-	int parent, ret;
+	int ret, has_suffix;
 	const char *cp;
 
-	/* foo^[0-9] or foo^ (== foo^1); we do not do more than 9 parents. */
-	if (len > 2 && name[len-2] == '^' &&
-	    name[len-1] >= '0' && name[len-1] <= '9') {
-		parent = name[len-1] - '0';
-		len -= 2;
-	}
-	else if (len > 1 && name[len-1] == '^') {
-		parent = 1;
-		len--;
-	} else
-		parent = -1;
-
-	if (parent >= 0)
-		return get_parent(name, len, sha1, parent);
-
 	/* "name~3" is "name^^^",
-	 * "name~12" is "name^^^^^^^^^^^^", and
 	 * "name~" and "name~0" are name -- not "name^0"!
+	 * "name^" is not "name^0"; it is "name^1".
 	 */
-	parent = 0;
+	has_suffix = 0;
 	for (cp = name + len - 1; name <= cp; cp--) {
 		int ch = *cp;
 		if ('0' <= ch && ch <= '9')
 			continue;
-		if (ch != '~')
-			parent = -1;
+		if (ch == '~' || ch == '^')
+			has_suffix = ch;
 		break;
 	}
-	if (!parent && *cp == '~') {
+
+	if (has_suffix) {
+		int num = 0;
 		int len1 = cp - name;
 		cp++;
 		while (cp < name + len)
-			parent = parent * 10 + *cp++ - '0';
-		return get_nth_ancestor(name, len1, sha1, parent);
+			num = num * 10 + *cp++ - '0';
+		if (has_suffix == '^') {
+			if (!num && len1 == len - 1)
+				num = 1;
+			return get_parent(name, len1, sha1, num);
+		}
+		/* else if (has_suffix == '~') -- goes without saying */
+		return get_nth_ancestor(name, len1, sha1, num);
 	}
 
 	ret = peel_onion(name, len, sha1);