replace {pre,suf}fixcmp() with {starts,ends}_with()

Leaving only the function definitions and declarations so that any
new topic in flight can still make use of the old functions, replace
existing uses of the prefixcmp() and suffixcmp() with new API
functions.

The change can be recreated by mechanically applying this:

    $ git grep -l -e prefixcmp -e suffixcmp -- \*.c |
      grep -v strbuf\\.c |
      xargs perl -pi -e '
        s|!prefixcmp\(|starts_with\(|g;
        s|prefixcmp\(|!starts_with\(|g;
        s|!suffixcmp\(|ends_with\(|g;
        s|suffixcmp\(|!ends_with\(|g;
      '

on the result of preparatory changes in this series.

Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
diff --git a/alias.c b/alias.c
index 9938f03..5efc3d6 100644
--- a/alias.c
+++ b/alias.c
@@ -5,7 +5,7 @@
 
 static int alias_lookup_cb(const char *k, const char *v, void *cb)
 {
-	if (!prefixcmp(k, "alias.") && !strcmp(k + 6, alias_key)) {
+	if (starts_with(k, "alias.") && !strcmp(k + 6, alias_key)) {
 		if (!v)
 			return config_error_nonbool(k);
 		alias_val = xstrdup(v);
diff --git a/attr.c b/attr.c
index 0e774c6..8d13d70 100644
--- a/attr.c
+++ b/attr.c
@@ -211,7 +211,7 @@
 	name = cp;
 	namelen = strcspn(name, blank);
 	if (strlen(ATTRIBUTE_MACRO_PREFIX) < namelen &&
-	    !prefixcmp(name, ATTRIBUTE_MACRO_PREFIX)) {
+	    starts_with(name, ATTRIBUTE_MACRO_PREFIX)) {
 		if (!macro_ok) {
 			fprintf(stderr, "%s not allowed: %s:%d\n",
 				name, src, lineno);
diff --git a/bisect.c b/bisect.c
index 1e46a4f..37200b4 100644
--- a/bisect.c
+++ b/bisect.c
@@ -406,9 +406,9 @@
 	if (!strcmp(refname, "bad")) {
 		current_bad_sha1 = xmalloc(20);
 		hashcpy(current_bad_sha1, sha1);
-	} else if (!prefixcmp(refname, "good-")) {
+	} else if (starts_with(refname, "good-")) {
 		sha1_array_append(&good_revs, sha1);
-	} else if (!prefixcmp(refname, "skip-")) {
+	} else if (starts_with(refname, "skip-")) {
 		sha1_array_append(&skipped_revs, sha1);
 	}
 
diff --git a/branch.c b/branch.c
index 9e6c68e..723a36b 100644
--- a/branch.c
+++ b/branch.c
@@ -50,7 +50,7 @@
 void install_branch_config(int flag, const char *local, const char *origin, const char *remote)
 {
 	const char *shortname = remote + 11;
-	int remote_is_branch = !prefixcmp(remote, "refs/heads/");
+	int remote_is_branch = starts_with(remote, "refs/heads/");
 	struct strbuf key = STRBUF_INIT;
 	int rebasing = should_setup_rebase(origin);
 
@@ -272,7 +272,7 @@
 		break;
 	case 1:
 		/* Unique completion -- good, only if it is a real branch */
-		if (prefixcmp(real_ref, "refs/heads/") &&
+		if (!starts_with(real_ref, "refs/heads/") &&
 		    validate_remote_tracking_branch(real_ref)) {
 			if (explicit_tracking)
 				die(_(upstream_not_branch), start_name);
diff --git a/builtin/apply.c b/builtin/apply.c
index ef32e4f..b0d0986 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -1409,10 +1409,10 @@
 		case '\\':
 			continue;
 		case '@':
-			ret = size < 3 || prefixcmp(line, "@@ ");
+			ret = size < 3 || !starts_with(line, "@@ ");
 			break;
 		case 'd':
-			ret = size < 5 || prefixcmp(line, "diff ");
+			ret = size < 5 || !starts_with(line, "diff ");
 			break;
 		default:
 			ret = -1;
@@ -1798,11 +1798,11 @@
 
 	*status_p = 0;
 
-	if (!prefixcmp(buffer, "delta ")) {
+	if (starts_with(buffer, "delta ")) {
 		patch_method = BINARY_DELTA_DEFLATED;
 		origlen = strtoul(buffer + 6, NULL, 10);
 	}
-	else if (!prefixcmp(buffer, "literal ")) {
+	else if (starts_with(buffer, "literal ")) {
 		patch_method = BINARY_LITERAL_DEFLATED;
 		origlen = strtoul(buffer + 8, NULL, 10);
 	}
@@ -3627,12 +3627,12 @@
 	    hunk->oldpos == 1 && hunk->oldlines == 1 &&
 	    /* does preimage begin with the heading? */
 	    (preimage = memchr(hunk->patch, '\n', hunk->size)) != NULL &&
-	    !prefixcmp(++preimage, heading) &&
+	    starts_with(++preimage, heading) &&
 	    /* does it record full SHA-1? */
 	    !get_sha1_hex(preimage + sizeof(heading) - 1, sha1) &&
 	    preimage[sizeof(heading) + 40 - 1] == '\n' &&
 	    /* does the abbreviated name on the index line agree with it? */
-	    !prefixcmp(preimage + sizeof(heading) - 1, p->old_sha1_prefix))
+	    starts_with(preimage + sizeof(heading) - 1, p->old_sha1_prefix))
 		return 0; /* it all looks fine */
 
 	/* we may have full object name on the index line */
diff --git a/builtin/archive.c b/builtin/archive.c
index 49178f1..a1e3b94 100644
--- a/builtin/archive.c
+++ b/builtin/archive.c
@@ -57,9 +57,9 @@
 	if (!buf)
 		die(_("git archive: expected ACK/NAK, got EOF"));
 	if (strcmp(buf, "ACK")) {
-		if (!prefixcmp(buf, "NACK "))
+		if (starts_with(buf, "NACK "))
 			die(_("git archive: NACK %s"), buf + 5);
-		if (!prefixcmp(buf, "ERR "))
+		if (starts_with(buf, "ERR "))
 			die(_("remote error: %s"), buf + 4);
 		die(_("git archive: protocol error"));
 	}
diff --git a/builtin/branch.c b/builtin/branch.c
index f157f92..c5953e5 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -81,13 +81,13 @@
 
 static int git_branch_config(const char *var, const char *value, void *cb)
 {
-	if (!prefixcmp(var, "column."))
+	if (starts_with(var, "column."))
 		return git_column_config(var, value, "branch", &colopts);
 	if (!strcmp(var, "color.branch")) {
 		branch_use_color = git_config_colorbool(var, value);
 		return 0;
 	}
-	if (!prefixcmp(var, "color.branch.")) {
+	if (starts_with(var, "color.branch.")) {
 		int slot = parse_branch_color_slot(var, 13);
 		if (slot < 0)
 			return 0;
@@ -868,7 +868,7 @@
 	if (!strcmp(head, "HEAD")) {
 		detached = 1;
 	} else {
-		if (prefixcmp(head, "refs/heads/"))
+		if (!starts_with(head, "refs/heads/"))
 			die(_("HEAD not found below refs/heads!"));
 		head += 11;
 	}
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 54f80bd..7e939b0 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -781,7 +781,7 @@
 	if (!(flag & REF_ISSYMREF))
 		old.path = NULL;
 
-	if (old.path && !prefixcmp(old.path, "refs/heads/"))
+	if (old.path && starts_with(old.path, "refs/heads/"))
 		old.name = old.path + strlen("refs/heads/");
 
 	if (!new->name) {
@@ -816,7 +816,7 @@
 		return 0;
 	}
 
-	if (!prefixcmp(var, "submodule."))
+	if (starts_with(var, "submodule."))
 		return parse_submodule_config_option(var, value);
 
 	return git_xmerge_config(var, value, NULL);
@@ -1151,9 +1151,9 @@
 		const char *argv0 = argv[0];
 		if (!argc || !strcmp(argv0, "--"))
 			die (_("--track needs a branch name"));
-		if (!prefixcmp(argv0, "refs/"))
+		if (starts_with(argv0, "refs/"))
 			argv0 += 5;
-		if (!prefixcmp(argv0, "remotes/"))
+		if (starts_with(argv0, "remotes/"))
 			argv0 += 8;
 		argv0 = strchr(argv0, '/');
 		if (!argv0 || !argv0[1])
diff --git a/builtin/clean.c b/builtin/clean.c
index 615cd57..2f26297 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -100,7 +100,7 @@
 
 static int git_clean_config(const char *var, const char *value, void *cb)
 {
-	if (!prefixcmp(var, "column."))
+	if (starts_with(var, "column."))
 		return git_column_config(var, value, "clean", &colopts);
 
 	/* honors the color.interactive* config variables which also
@@ -109,7 +109,7 @@
 		clean_use_color = git_config_colorbool(var, value);
 		return 0;
 	}
-	if (!prefixcmp(var, "color.interactive.")) {
+	if (starts_with(var, "color.interactive.")) {
 		int slot = parse_clean_color_slot(var +
 						  strlen("color.interactive."));
 		if (slot < 0)
diff --git a/builtin/clone.c b/builtin/clone.c
index 874e0fd..ec4d1cd 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -508,9 +508,9 @@
 {
 	const struct ref *ref;
 	for (ref = refs; ref; ref = ref->next) {
-		if (prefixcmp(ref->name, "refs/tags/"))
+		if (!starts_with(ref->name, "refs/tags/"))
 			continue;
-		if (!suffixcmp(ref->name, "^{}"))
+		if (ends_with(ref->name, "^{}"))
 			continue;
 		if (!has_sha1_file(ref->old_sha1))
 			continue;
@@ -578,7 +578,7 @@
 static void update_head(const struct ref *our, const struct ref *remote,
 			const char *msg)
 {
-	if (our && !prefixcmp(our->name, "refs/heads/")) {
+	if (our && starts_with(our->name, "refs/heads/")) {
 		/* Local default branch link */
 		create_symref("HEAD", our->name, NULL);
 		if (!option_bare) {
@@ -625,7 +625,7 @@
 		if (advice_detached_head)
 			detach_advice(sha1_to_hex(sha1));
 	} else {
-		if (prefixcmp(head, "refs/heads/"))
+		if (!starts_with(head, "refs/heads/"))
 			die(_("HEAD not found below refs/heads!"));
 	}
 	free(head);
diff --git a/builtin/column.c b/builtin/column.c
index e125a55..7581852 100644
--- a/builtin/column.c
+++ b/builtin/column.c
@@ -34,7 +34,7 @@
 	};
 
 	/* This one is special and must be the first one */
-	if (argc > 1 && !prefixcmp(argv[1], "--command=")) {
+	if (argc > 1 && starts_with(argv[1], "--command=")) {
 		command = argv[1] + 10;
 		git_config(column_config, (void *)command);
 	} else
diff --git a/builtin/commit.c b/builtin/commit.c
index 6ab4605..4f765a2 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -733,7 +733,7 @@
 				eol = nl - sb.buf;
 			else
 				eol = sb.len;
-			if (!prefixcmp(sb.buf + previous, "\nConflicts:\n")) {
+			if (starts_with(sb.buf + previous, "\nConflicts:\n")) {
 				ignore_footer = sb.len - previous;
 				break;
 			}
@@ -904,7 +904,7 @@
 			eol = sb->len;
 
 		if (strlen(sign_off_header) <= eol - i &&
-		    !prefixcmp(sb->buf + i, sign_off_header)) {
+		    starts_with(sb->buf + i, sign_off_header)) {
 			i = eol;
 			continue;
 		}
@@ -1183,7 +1183,7 @@
 {
 	struct wt_status *s = cb;
 
-	if (!prefixcmp(k, "column."))
+	if (starts_with(k, "column."))
 		return git_column_config(k, v, "status", &s->colopts);
 	if (!strcmp(k, "status.submodulesummary")) {
 		int is_bool;
@@ -1211,7 +1211,7 @@
 		s->display_comment_prefix = git_config_bool(k, v);
 		return 0;
 	}
-	if (!prefixcmp(k, "status.color.") || !prefixcmp(k, "color.status.")) {
+	if (starts_with(k, "status.color.") || starts_with(k, "color.status.")) {
 		int slot = parse_status_slot(k, 13);
 		if (slot < 0)
 			return 0;
@@ -1377,7 +1377,7 @@
 
 	head = resolve_ref_unsafe("HEAD", junk_sha1, 0, NULL);
 	printf("[%s%s ",
-		!prefixcmp(head, "refs/heads/") ?
+		starts_with(head, "refs/heads/") ?
 			head + 11 :
 			!strcmp(head, "HEAD") ?
 				_("detached HEAD") :
diff --git a/builtin/describe.c b/builtin/describe.c
index 6f62109..7db43da 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -141,7 +141,7 @@
 
 static int get_name(const char *path, const unsigned char *sha1, int flag, void *cb_data)
 {
-	int is_tag = !prefixcmp(path, "refs/tags/");
+	int is_tag = starts_with(path, "refs/tags/");
 	unsigned char peeled[20];
 	int is_annotated, prio;
 
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index 78250ea..ea55a24 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -476,7 +476,7 @@
 		}
 	}
 
-	if (!prefixcmp(name, "refs/tags/"))
+	if (starts_with(name, "refs/tags/"))
 		name += 10;
 	printf("tag %s\nfrom :%d\n%.*s%sdata %d\n%.*s\n",
 	       name, tagged_mark,
diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c
index c8e8582..10fcdc2 100644
--- a/builtin/fetch-pack.c
+++ b/builtin/fetch-pack.c
@@ -48,11 +48,11 @@
 	for (i = 1; i < argc && *argv[i] == '-'; i++) {
 		const char *arg = argv[i];
 
-		if (!prefixcmp(arg, "--upload-pack=")) {
+		if (starts_with(arg, "--upload-pack=")) {
 			args.uploadpack = arg + 14;
 			continue;
 		}
-		if (!prefixcmp(arg, "--exec=")) {
+		if (starts_with(arg, "--exec=")) {
 			args.uploadpack = arg + 7;
 			continue;
 		}
@@ -85,7 +85,7 @@
 			args.verbose = 1;
 			continue;
 		}
-		if (!prefixcmp(arg, "--depth=")) {
+		if (starts_with(arg, "--depth=")) {
 			args.depth = strtol(arg + 8, NULL, 0);
 			continue;
 		}
diff --git a/builtin/fetch.c b/builtin/fetch.c
index bd7a101..4dd8250 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -313,7 +313,7 @@
 	}
 
 	if (!is_null_sha1(ref->old_sha1) &&
-	    !prefixcmp(ref->name, "refs/tags/")) {
+	    starts_with(ref->name, "refs/tags/")) {
 		int r;
 		r = s_update_ref("updating tag", ref, 0);
 		strbuf_addf(display, "%c %-*s %-*s -> %s%s",
@@ -336,10 +336,10 @@
 		 * more likely to follow a standard layout.
 		 */
 		const char *name = remote_ref ? remote_ref->name : "";
-		if (!prefixcmp(name, "refs/tags/")) {
+		if (starts_with(name, "refs/tags/")) {
 			msg = "storing tag";
 			what = _("[new tag]");
-		} else if (!prefixcmp(name, "refs/heads/")) {
+		} else if (starts_with(name, "refs/heads/")) {
 			msg = "storing head";
 			what = _("[new branch]");
 		} else {
@@ -471,15 +471,15 @@
 				kind = "";
 				what = "";
 			}
-			else if (!prefixcmp(rm->name, "refs/heads/")) {
+			else if (starts_with(rm->name, "refs/heads/")) {
 				kind = "branch";
 				what = rm->name + 11;
 			}
-			else if (!prefixcmp(rm->name, "refs/tags/")) {
+			else if (starts_with(rm->name, "refs/tags/")) {
 				kind = "tag";
 				what = rm->name + 10;
 			}
-			else if (!prefixcmp(rm->name, "refs/remotes/")) {
+			else if (starts_with(rm->name, "refs/remotes/")) {
 				kind = "remote-tracking branch";
 				what = rm->name + 13;
 			}
@@ -644,7 +644,7 @@
 
 	for_each_ref(add_existing, &existing_refs);
 	for (ref = transport_get_remote_refs(transport); ref; ref = ref->next) {
-		if (prefixcmp(ref->name, "refs/tags/"))
+		if (!starts_with(ref->name, "refs/tags/"))
 			continue;
 
 		/*
@@ -653,7 +653,7 @@
 		 * to fetch then we can mark the ref entry in the list
 		 * as one to ignore by setting util to NULL.
 		 */
-		if (!suffixcmp(ref->name, "^{}")) {
+		if (ends_with(ref->name, "^{}")) {
 			if (item && !has_sha1_file(ref->old_sha1) &&
 			    !will_fetch(head, ref->old_sha1) &&
 			    !has_sha1_file(item->util) &&
@@ -892,7 +892,7 @@
 {
 	struct remote_group_data *g = priv;
 
-	if (!prefixcmp(key, "remotes.") &&
+	if (starts_with(key, "remotes.") &&
 			!strcmp(key + 8, g->name)) {
 		/* split list by white space */
 		int space = strcspn(value, " \t\n");
diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
index 1c04070..3906eda 100644
--- a/builtin/fmt-merge-msg.c
+++ b/builtin/fmt-merge-msg.c
@@ -109,7 +109,7 @@
 	if (len < 43 || line[40] != '\t')
 		return 1;
 
-	if (!prefixcmp(line + 41, "not-for-merge"))
+	if (starts_with(line + 41, "not-for-merge"))
 		return 0;
 
 	if (line[41] != '\t')
@@ -155,16 +155,16 @@
 	if (pulling_head) {
 		origin = src;
 		src_data->head_status |= 1;
-	} else if (!prefixcmp(line, "branch ")) {
+	} else if (starts_with(line, "branch ")) {
 		origin_data->is_local_branch = 1;
 		origin = line + 7;
 		string_list_append(&src_data->branch, origin);
 		src_data->head_status |= 2;
-	} else if (!prefixcmp(line, "tag ")) {
+	} else if (starts_with(line, "tag ")) {
 		origin = line;
 		string_list_append(&src_data->tag, origin + 4);
 		src_data->head_status |= 2;
-	} else if (!prefixcmp(line, "remote-tracking branch ")) {
+	} else if (starts_with(line, "remote-tracking branch ")) {
 		origin = line + strlen("remote-tracking branch ");
 		string_list_append(&src_data->r_branch, origin);
 		src_data->head_status |= 2;
@@ -605,7 +605,7 @@
 		resolve_refdup("HEAD", head_sha1, 1, NULL);
 	if (!current_branch)
 		die("No current branch");
-	if (!prefixcmp(current_branch, "refs/heads/"))
+	if (starts_with(current_branch, "refs/heads/"))
 		current_branch += 11;
 
 	find_merge_parents(&merge_parents, in, head_sha1);
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index d096051..883d383 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -441,7 +441,7 @@
 		if (name[wholen] != 0 &&
 		    strcmp(name + wholen, "name") &&
 		    strcmp(name + wholen, "email") &&
-		    prefixcmp(name + wholen, "date"))
+		    !starts_with(name + wholen, "date"))
 			continue;
 		if (!wholine)
 			wholine = find_wholine(who, wholen, buf, sz);
@@ -453,7 +453,7 @@
 			v->s = copy_name(wholine);
 		else if (!strcmp(name + wholen, "email"))
 			v->s = copy_email(wholine);
-		else if (!prefixcmp(name + wholen, "date"))
+		else if (starts_with(name + wholen, "date"))
 			grab_date(wholine, v, name);
 	}
 
@@ -475,7 +475,7 @@
 		if (deref)
 			name++;
 
-		if (!prefixcmp(name, "creatordate"))
+		if (starts_with(name, "creatordate"))
 			grab_date(wholine, v, name);
 		else if (!strcmp(name, "creator"))
 			v->s = copy_line(wholine);
@@ -655,14 +655,14 @@
 			name++;
 		}
 
-		if (!prefixcmp(name, "refname"))
+		if (starts_with(name, "refname"))
 			refname = ref->refname;
-		else if (!prefixcmp(name, "symref"))
+		else if (starts_with(name, "symref"))
 			refname = ref->symref ? ref->symref : "";
-		else if (!prefixcmp(name, "upstream")) {
+		else if (starts_with(name, "upstream")) {
 			struct branch *branch;
 			/* only local branches may have an upstream */
-			if (prefixcmp(ref->refname, "refs/heads/"))
+			if (!starts_with(ref->refname, "refs/heads/"))
 				continue;
 			branch = branch_get(ref->refname + 11);
 
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 97ce678..1affdd5 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -442,7 +442,7 @@
 			add_sha1_list(sha1, DIRENT_SORT_HINT(de));
 			continue;
 		}
-		if (!prefixcmp(de->d_name, "tmp_obj_"))
+		if (starts_with(de->d_name, "tmp_obj_"))
 			continue;
 		fprintf(stderr, "bad sha1 file: %s/%s\n", path, de->d_name);
 	}
@@ -484,7 +484,7 @@
 
 static int is_branch(const char *refname)
 {
-	return !strcmp(refname, "HEAD") || !prefixcmp(refname, "refs/heads/");
+	return !strcmp(refname, "HEAD") || starts_with(refname, "refs/heads/");
 }
 
 static int fsck_handle_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
@@ -566,7 +566,7 @@
 	if (!strcmp(head_points_at, "HEAD"))
 		/* detached HEAD */
 		null_is_error = 1;
-	else if (prefixcmp(head_points_at, "refs/heads/"))
+	else if (!starts_with(head_points_at, "refs/heads/"))
 		return error("HEAD points to something strange (%s)",
 			     head_points_at);
 	if (is_null_sha1(head_sha1)) {
diff --git a/builtin/help.c b/builtin/help.c
index f1e236b..cc17e67 100644
--- a/builtin/help.c
+++ b/builtin/help.c
@@ -100,7 +100,7 @@
 	 */
 	finish_command(&ec_process);
 
-	if (prefixcmp(buffer.buf, "emacsclient")) {
+	if (!starts_with(buffer.buf, "emacsclient")) {
 		strbuf_release(&buffer);
 		return error(_("Failed to parse emacsclient version."));
 	}
@@ -258,7 +258,7 @@
 
 static int git_help_config(const char *var, const char *value, void *cb)
 {
-	if (!prefixcmp(var, "column."))
+	if (starts_with(var, "column."))
 		return git_column_config(var, value, "help", &colopts);
 	if (!strcmp(var, "help.format")) {
 		if (!value)
@@ -278,7 +278,7 @@
 		add_man_viewer(value);
 		return 0;
 	}
-	if (!prefixcmp(var, "man."))
+	if (starts_with(var, "man."))
 		return add_man_viewer_info(var, value);
 
 	return git_default_config(var, value, cb);
@@ -306,7 +306,7 @@
 {
 	if (!git_cmd)
 		return "git";
-	else if (!prefixcmp(git_cmd, "git"))
+	else if (starts_with(git_cmd, "git"))
 		return git_cmd;
 	else if (is_git_command(git_cmd))
 		return prepend("git-", git_cmd);
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 9e9eb4b..2f37a38 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -1534,9 +1534,9 @@
 				stat_only = 1;
 			} else if (!strcmp(arg, "--keep")) {
 				keep_msg = "";
-			} else if (!prefixcmp(arg, "--keep=")) {
+			} else if (starts_with(arg, "--keep=")) {
 				keep_msg = arg + 7;
-			} else if (!prefixcmp(arg, "--threads=")) {
+			} else if (starts_with(arg, "--threads=")) {
 				char *end;
 				nr_threads = strtoul(arg+10, &end, 0);
 				if (!arg[10] || *end || nr_threads < 0)
@@ -1547,7 +1547,7 @@
 						  "ignoring %s"), arg);
 				nr_threads = 1;
 #endif
-			} else if (!prefixcmp(arg, "--pack_header=")) {
+			} else if (starts_with(arg, "--pack_header=")) {
 				struct pack_header *hdr;
 				char *c;
 
@@ -1566,7 +1566,7 @@
 				if (index_name || (i+1) >= argc)
 					usage(index_pack_usage);
 				index_name = argv[++i];
-			} else if (!prefixcmp(arg, "--index-version=")) {
+			} else if (starts_with(arg, "--index-version=")) {
 				char *c;
 				opts.version = strtoul(arg + 16, &c, 10);
 				if (opts.version > 2)
diff --git a/builtin/init-db.c b/builtin/init-db.c
index 78aa387..b3f03cf 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -266,7 +266,7 @@
 		/* allow template config file to override the default */
 		if (log_all_ref_updates == -1)
 		    git_config_set("core.logallrefupdates", "true");
-		if (prefixcmp(git_dir, work_tree) ||
+		if (!starts_with(git_dir, work_tree) ||
 		    strcmp(git_dir + strlen(work_tree), "/.git")) {
 			git_config_set("core.worktree", work_tree);
 		}
diff --git a/builtin/log.c b/builtin/log.c
index b708517..b97373d 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -391,7 +391,7 @@
 		default_show_root = git_config_bool(var, value);
 		return 0;
 	}
-	if (!prefixcmp(var, "color.decorate."))
+	if (starts_with(var, "color.decorate."))
 		return parse_decorate_color_config(var, 15, value);
 	if (!strcmp(var, "log.mailmap")) {
 		use_mailmap_config = git_config_bool(var, value);
@@ -477,7 +477,7 @@
 		int new_offset = offset + 1;
 		while (new_offset < size && buf[new_offset++] != '\n')
 			; /* do nothing */
-		if (!prefixcmp(buf + offset, "tagger "))
+		if (starts_with(buf + offset, "tagger "))
 			show_tagger(buf + offset + 7,
 				    new_offset - offset - 7, rev);
 		offset = new_offset;
@@ -882,7 +882,7 @@
 	ref = rev->cmdline.rev[positive].name;
 	tip_sha1 = rev->cmdline.rev[positive].item->sha1;
 	if (dwim_ref(ref, strlen(ref), branch_sha1, &full_ref) &&
-	    !prefixcmp(full_ref, "refs/heads/") &&
+	    starts_with(full_ref, "refs/heads/") &&
 	    !hashcmp(tip_sha1, branch_sha1))
 		branch = xstrdup(full_ref + strlen("refs/heads/"));
 	free(full_ref);
@@ -1388,7 +1388,7 @@
 			unsigned char sha1[20];
 			const char *ref;
 			ref = resolve_ref_unsafe("HEAD", sha1, 1, NULL);
-			if (ref && !prefixcmp(ref, "refs/heads/"))
+			if (ref && starts_with(ref, "refs/heads/"))
 				branch_name = xstrdup(ref + strlen("refs/heads/"));
 			else
 				branch_name = xstrdup(""); /* no branch */
diff --git a/builtin/ls-remote.c b/builtin/ls-remote.c
index 25e83cf..39e5144 100644
--- a/builtin/ls-remote.c
+++ b/builtin/ls-remote.c
@@ -50,11 +50,11 @@
 		const char *arg = argv[i];
 
 		if (*arg == '-') {
-			if (!prefixcmp(arg, "--upload-pack=")) {
+			if (starts_with(arg, "--upload-pack=")) {
 				uploadpack = arg + 14;
 				continue;
 			}
-			if (!prefixcmp(arg, "--exec=")) {
+			if (starts_with(arg, "--exec=")) {
 				uploadpack = arg + 7;
 				continue;
 			}
diff --git a/builtin/mailinfo.c b/builtin/mailinfo.c
index 24a772d..2c3cd8e 100644
--- a/builtin/mailinfo.c
+++ b/builtin/mailinfo.c
@@ -328,11 +328,11 @@
 	}
 
 	/* for inbody stuff */
-	if (!prefixcmp(line->buf, ">From") && isspace(line->buf[5])) {
+	if (starts_with(line->buf, ">From") && isspace(line->buf[5])) {
 		ret = 1; /* Should this return 0? */
 		goto check_header_out;
 	}
-	if (!prefixcmp(line->buf, "[PATCH]") && isspace(line->buf[7])) {
+	if (starts_with(line->buf, "[PATCH]") && isspace(line->buf[7])) {
 		for (i = 0; header[i]; i++) {
 			if (!memcmp("Subject", header[i], 7)) {
 				handle_header(&hdr_data[i], line);
@@ -361,7 +361,7 @@
 	char *cp = line->buf;
 
 	/* Count mbox From headers as headers */
-	if (!prefixcmp(cp, "From ") || !prefixcmp(cp, ">From "))
+	if (starts_with(cp, "From ") || starts_with(cp, ">From "))
 		return 1;
 
 	while ((ch = *cp++)) {
@@ -671,11 +671,11 @@
 	size_t i;
 
 	/* Beginning of a "diff -" header? */
-	if (!prefixcmp(line->buf, "diff -"))
+	if (starts_with(line->buf, "diff -"))
 		return 1;
 
 	/* CVS "Index: " line? */
-	if (!prefixcmp(line->buf, "Index: "))
+	if (starts_with(line->buf, "Index: "))
 		return 1;
 
 	/*
@@ -685,7 +685,7 @@
 	if (line->len < 4)
 		return 0;
 
-	if (!prefixcmp(line->buf, "---")) {
+	if (starts_with(line->buf, "---")) {
 		/* space followed by a filename? */
 		if (line->buf[3] == ' ' && !isspace(line->buf[4]))
 			return 1;
@@ -986,7 +986,7 @@
 
 static int git_mailinfo_config(const char *var, const char *value, void *unused)
 {
-	if (prefixcmp(var, "mailinfo."))
+	if (!starts_with(var, "mailinfo."))
 		return git_default_config(var, value, unused);
 	if (!strcmp(var, "mailinfo.scissors")) {
 		use_scissors = git_config_bool(var, value);
@@ -1020,7 +1020,7 @@
 			metainfo_charset = def_charset;
 		else if (!strcmp(argv[1], "-n"))
 			metainfo_charset = NULL;
-		else if (!prefixcmp(argv[1], "--encoding="))
+		else if (starts_with(argv[1], "--encoding="))
 			metainfo_charset = argv[1] + 11;
 		else if (!strcmp(argv[1], "--scissors"))
 			use_scissors = 1;
diff --git a/builtin/merge-recursive.c b/builtin/merge-recursive.c
index 3a64f5d..a90f28f 100644
--- a/builtin/merge-recursive.c
+++ b/builtin/merge-recursive.c
@@ -29,7 +29,7 @@
 	struct commit *result;
 
 	init_merge_options(&o);
-	if (argv[0] && !suffixcmp(argv[0], "-subtree"))
+	if (argv[0] && ends_with(argv[0], "-subtree"))
 		o.subtree_shift = "";
 
 	if (argc < 4)
@@ -38,7 +38,7 @@
 	for (i = 1; i < argc; ++i) {
 		const char *arg = argv[i];
 
-		if (!prefixcmp(arg, "--")) {
+		if (starts_with(arg, "--")) {
 			if (!arg[2])
 				break;
 			if (parse_merge_opt(&o, arg + 2))
diff --git a/builtin/merge.c b/builtin/merge.c
index 41fb66d..4941a6c 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -446,17 +446,17 @@
 		die(_("'%s' does not point to a commit"), remote);
 
 	if (dwim_ref(remote, strlen(remote), branch_head, &found_ref) > 0) {
-		if (!prefixcmp(found_ref, "refs/heads/")) {
+		if (starts_with(found_ref, "refs/heads/")) {
 			strbuf_addf(msg, "%s\t\tbranch '%s' of .\n",
 				    sha1_to_hex(branch_head), remote);
 			goto cleanup;
 		}
-		if (!prefixcmp(found_ref, "refs/tags/")) {
+		if (starts_with(found_ref, "refs/tags/")) {
 			strbuf_addf(msg, "%s\t\ttag '%s' of .\n",
 				    sha1_to_hex(branch_head), remote);
 			goto cleanup;
 		}
-		if (!prefixcmp(found_ref, "refs/remotes/")) {
+		if (starts_with(found_ref, "refs/remotes/")) {
 			strbuf_addf(msg, "%s\t\tremote-tracking branch '%s' of .\n",
 				    sha1_to_hex(branch_head), remote);
 			goto cleanup;
@@ -570,8 +570,8 @@
 {
 	int status;
 
-	if (branch && !prefixcmp(k, "branch.") &&
-		!prefixcmp(k + 7, branch) &&
+	if (branch && starts_with(k, "branch.") &&
+		starts_with(k + 7, branch) &&
 		!strcmp(k + 7 + strlen(branch), ".mergeoptions")) {
 		free(branch_mergeoptions);
 		branch_mergeoptions = xstrdup(v);
@@ -1106,7 +1106,7 @@
 	 * current branch.
 	 */
 	branch = branch_to_free = resolve_refdup("HEAD", head_sha1, 0, &flag);
-	if (branch && !prefixcmp(branch, "refs/heads/"))
+	if (branch && starts_with(branch, "refs/heads/"))
 		branch += 11;
 	if (!branch || is_null_sha1(head_sha1))
 		head_commit = NULL;
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 20fcf8c..9903901 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -101,9 +101,9 @@
 {
 	if (shorten_unambiguous)
 		refname = shorten_unambiguous_ref(refname, 0);
-	else if (!prefixcmp(refname, "refs/heads/"))
+	else if (starts_with(refname, "refs/heads/"))
 		refname = refname + 11;
-	else if (!prefixcmp(refname, "refs/"))
+	else if (starts_with(refname, "refs/"))
 		refname = refname + 5;
 	return refname;
 }
@@ -149,7 +149,7 @@
 	int can_abbreviate_output = data->tags_only && data->name_only;
 	int deref = 0;
 
-	if (data->tags_only && prefixcmp(path, "refs/tags/"))
+	if (data->tags_only && !starts_with(path, "refs/tags/"))
 		return 0;
 
 	if (data->ref_filter) {
diff --git a/builtin/notes.c b/builtin/notes.c
index d459e23..2b24d05 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -347,7 +347,7 @@
 	init_notes(NULL, NULL, NULL, 0);
 	t = &default_notes_tree;
 
-	if (prefixcmp(t->ref, "refs/notes/"))
+	if (!starts_with(t->ref, "refs/notes/"))
 		die("Refusing to %s notes in %s (outside of refs/notes/)",
 		    subcommand, t->ref);
 	return t;
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 36273dd..dfb4d84 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -2032,7 +2032,7 @@
 {
 	unsigned char peeled[20];
 
-	if (!prefixcmp(path, "refs/tags/") && /* is a tag? */
+	if (starts_with(path, "refs/tags/") && /* is a tag? */
 	    !peel_ref(path, peeled)        && /* peelable? */
 	    locate_object_entry(peeled))      /* object packed? */
 		add_object_entry(sha1, OBJ_TAG, NULL, 0);
diff --git a/builtin/prune.c b/builtin/prune.c
index 6366917..a85ef54 100644
--- a/builtin/prune.c
+++ b/builtin/prune.c
@@ -80,7 +80,7 @@
 			prune_object(path, de->d_name, sha1);
 			continue;
 		}
-		if (!prefixcmp(de->d_name, "tmp_obj_")) {
+		if (starts_with(de->d_name, "tmp_obj_")) {
 			prune_tmp_object(path, de->d_name);
 			continue;
 		}
@@ -119,7 +119,7 @@
 		return;
 	}
 	while ((de = readdir(dir)) != NULL)
-		if (!prefixcmp(de->d_name, "tmp_"))
+		if (starts_with(de->d_name, "tmp_"))
 			prune_tmp_object(path, de->d_name);
 	closedir(dir);
 }
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 67ce1ef..e09994f 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -428,7 +428,7 @@
 	struct ref_lock *lock;
 
 	/* only refs/... are allowed */
-	if (prefixcmp(name, "refs/") || check_refname_format(name + 5, 0)) {
+	if (!starts_with(name, "refs/") || check_refname_format(name + 5, 0)) {
 		rp_error("refusing to create funny ref '%s' remotely", name);
 		return "funny refname";
 	}
@@ -459,7 +459,7 @@
 	}
 
 	if (!is_null_sha1(old_sha1) && is_null_sha1(new_sha1)) {
-		if (deny_deletes && !prefixcmp(name, "refs/heads/")) {
+		if (deny_deletes && starts_with(name, "refs/heads/")) {
 			rp_error("denying ref deletion for %s", name);
 			return "deletion prohibited";
 		}
@@ -483,7 +483,7 @@
 
 	if (deny_non_fast_forwards && !is_null_sha1(new_sha1) &&
 	    !is_null_sha1(old_sha1) &&
-	    !prefixcmp(name, "refs/heads/")) {
+	    starts_with(name, "refs/heads/")) {
 		struct object *old_object, *new_object;
 		struct commit *old_commit, *new_commit;
 
diff --git a/builtin/reflog.c b/builtin/reflog.c
index 6eb24c8..852cff6 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -610,12 +610,12 @@
 		const char *arg = argv[i];
 		if (!strcmp(arg, "--dry-run") || !strcmp(arg, "-n"))
 			cb.dry_run = 1;
-		else if (!prefixcmp(arg, "--expire=")) {
+		else if (starts_with(arg, "--expire=")) {
 			if (parse_expiry_date(arg + 9, &cb.expire_total))
 				die(_("'%s' is not a valid timestamp"), arg);
 			explicit_expiry |= EXPIRE_TOTAL;
 		}
-		else if (!prefixcmp(arg, "--expire-unreachable=")) {
+		else if (starts_with(arg, "--expire-unreachable=")) {
 			if (parse_expiry_date(arg + 21, &cb.expire_unreachable))
 				die(_("'%s' is not a valid timestamp"), arg);
 			explicit_expiry |= EXPIRE_UNREACH;
diff --git a/builtin/remote.c b/builtin/remote.c
index 9b3a98e..b3fd92f 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -261,7 +261,7 @@
 
 static int config_read_branches(const char *key, const char *value, void *cb)
 {
-	if (!prefixcmp(key, "branch.")) {
+	if (starts_with(key, "branch.")) {
 		const char *orig_key = key;
 		char *name;
 		struct string_list_item *item;
@@ -269,13 +269,13 @@
 		enum { REMOTE, MERGE, REBASE } type;
 
 		key += 7;
-		if (!suffixcmp(key, ".remote")) {
+		if (ends_with(key, ".remote")) {
 			name = xstrndup(key, strlen(key) - 7);
 			type = REMOTE;
-		} else if (!suffixcmp(key, ".merge")) {
+		} else if (ends_with(key, ".merge")) {
 			name = xstrndup(key, strlen(key) - 6);
 			type = MERGE;
-		} else if (!suffixcmp(key, ".rebase")) {
+		} else if (ends_with(key, ".rebase")) {
 			name = xstrndup(key, strlen(key) - 7);
 			type = REBASE;
 		} else
@@ -526,9 +526,9 @@
 	}
 
 	/* don't delete non-remote-tracking refs */
-	if (prefixcmp(refname, "refs/remotes/")) {
+	if (!starts_with(refname, "refs/remotes/")) {
 		/* advise user how to delete local branches */
-		if (!prefixcmp(refname, "refs/heads/"))
+		if (starts_with(refname, "refs/heads/"))
 			string_list_append(branches->skipped,
 					   abbrev_branch(refname));
 		/* silently skip over other non-remote refs */
@@ -563,7 +563,7 @@
 	const char *symref;
 
 	strbuf_addf(&buf, "refs/remotes/%s/", rename->old);
-	if (!prefixcmp(refname, buf.buf)) {
+	if (starts_with(refname, buf.buf)) {
 		item = string_list_append(rename->remote_branches, xstrdup(refname));
 		symref = resolve_ref_unsafe(refname, orig_sha1, 1, &flag);
 		if (flag & REF_ISSYMREF)
diff --git a/builtin/repack.c b/builtin/repack.c
index a0ff5c7..938bc75 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -78,7 +78,7 @@
 		return;
 
 	while ((e = readdir(dir)) != NULL) {
-		if (suffixcmp(e->d_name, ".pack"))
+		if (!ends_with(e->d_name, ".pack"))
 			continue;
 
 		len = strlen(e->d_name) - strlen(".pack");
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index c76b89d..6b89402 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -508,7 +508,7 @@
 			}
 			continue;
 		}
-		if (!prefixcmp(arg, "-n")) {
+		if (starts_with(arg, "-n")) {
 			if ((filter & DO_FLAGS) && (filter & DO_REVS))
 				show(arg);
 			continue;
@@ -560,7 +560,7 @@
 				continue;
 			}
 			if (!strcmp(arg, "--short") ||
-			    !prefixcmp(arg, "--short=")) {
+			    starts_with(arg, "--short=")) {
 				filter &= ~(DO_FLAGS|DO_NOREV);
 				verify = 1;
 				abbrev = DEFAULT_ABBREV;
@@ -588,7 +588,7 @@
 				symbolic = SHOW_SYMBOLIC_FULL;
 				continue;
 			}
-			if (!prefixcmp(arg, "--abbrev-ref") &&
+			if (starts_with(arg, "--abbrev-ref") &&
 			    (!arg[12] || arg[12] == '=')) {
 				abbrev_ref = 1;
 				abbrev_ref_strict = warn_ambiguous_refs;
@@ -606,7 +606,7 @@
 				for_each_ref(show_reference, NULL);
 				continue;
 			}
-			if (!prefixcmp(arg, "--disambiguate=")) {
+			if (starts_with(arg, "--disambiguate=")) {
 				for_each_abbrev(arg + 15, show_abbrev, NULL);
 				continue;
 			}
@@ -615,7 +615,7 @@
 				for_each_ref_in("refs/bisect/good", anti_reference, NULL);
 				continue;
 			}
-			if (!prefixcmp(arg, "--branches=")) {
+			if (starts_with(arg, "--branches=")) {
 				for_each_glob_ref_in(show_reference, arg + 11,
 					"refs/heads/", NULL);
 				continue;
@@ -624,7 +624,7 @@
 				for_each_branch_ref(show_reference, NULL);
 				continue;
 			}
-			if (!prefixcmp(arg, "--tags=")) {
+			if (starts_with(arg, "--tags=")) {
 				for_each_glob_ref_in(show_reference, arg + 7,
 					"refs/tags/", NULL);
 				continue;
@@ -633,11 +633,11 @@
 				for_each_tag_ref(show_reference, NULL);
 				continue;
 			}
-			if (!prefixcmp(arg, "--glob=")) {
+			if (starts_with(arg, "--glob=")) {
 				for_each_glob_ref(show_reference, arg + 7, NULL);
 				continue;
 			}
-			if (!prefixcmp(arg, "--remotes=")) {
+			if (starts_with(arg, "--remotes=")) {
 				for_each_glob_ref_in(show_reference, arg + 10,
 					"refs/remotes/", NULL);
 				continue;
@@ -724,19 +724,19 @@
 						: "false");
 				continue;
 			}
-			if (!prefixcmp(arg, "--since=")) {
+			if (starts_with(arg, "--since=")) {
 				show_datestring("--max-age=", arg+8);
 				continue;
 			}
-			if (!prefixcmp(arg, "--after=")) {
+			if (starts_with(arg, "--after=")) {
 				show_datestring("--max-age=", arg+8);
 				continue;
 			}
-			if (!prefixcmp(arg, "--before=")) {
+			if (starts_with(arg, "--before=")) {
 				show_datestring("--min-age=", arg+9);
 				continue;
 			}
-			if (!prefixcmp(arg, "--until=")) {
+			if (starts_with(arg, "--until=")) {
 				show_datestring("--min-age=", arg+8);
 				continue;
 			}
diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index 4482f16..e7f0b97 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -115,15 +115,15 @@
 		const char *arg = *argv;
 
 		if (*arg == '-') {
-			if (!prefixcmp(arg, "--receive-pack=")) {
+			if (starts_with(arg, "--receive-pack=")) {
 				receivepack = arg + 15;
 				continue;
 			}
-			if (!prefixcmp(arg, "--exec=")) {
+			if (starts_with(arg, "--exec=")) {
 				receivepack = arg + 7;
 				continue;
 			}
-			if (!prefixcmp(arg, "--remote=")) {
+			if (starts_with(arg, "--remote=")) {
 				remote_name = arg + 9;
 				continue;
 			}
@@ -181,7 +181,7 @@
 					exit(1);
 				continue;
 			}
-			if (!prefixcmp(arg, "--" CAS_OPT_NAME "=")) {
+			if (starts_with(arg, "--" CAS_OPT_NAME "=")) {
 				if (parse_push_cas_option(&cas,
 							  strchr(arg, '=') + 1, 0) < 0)
 					exit(1);
diff --git a/builtin/shortlog.c b/builtin/shortlog.c
index c226f76..4b7e536 100644
--- a/builtin/shortlog.c
+++ b/builtin/shortlog.c
@@ -65,7 +65,7 @@
 	eol = strchr(oneline, '\n');
 	if (!eol)
 		eol = oneline + strlen(oneline);
-	if (!prefixcmp(oneline, "[PATCH")) {
+	if (starts_with(oneline, "[PATCH")) {
 		char *eob = strchr(oneline, ']');
 		if (eob && (!eol || eob < eol))
 			oneline = eob + 1;
@@ -95,7 +95,7 @@
 
 	while (fgets(author, sizeof(author), stdin) != NULL) {
 		if (!(author[0] == 'A' || author[0] == 'a') ||
-		    prefixcmp(author + 1, "uthor: "))
+		    !starts_with(author + 1, "uthor: "))
 			continue;
 		while (fgets(oneline, sizeof(oneline), stdin) &&
 		       oneline[0] != '\n')
@@ -123,7 +123,7 @@
 		else
 			eol++;
 
-		if (!prefixcmp(buffer, "author "))
+		if (starts_with(buffer, "author "))
 			author = buffer + 7;
 		buffer = eol;
 	}
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index 001f29c..f20c274 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -285,7 +285,7 @@
 		pp_commit_easy(CMIT_FMT_ONELINE, commit, &pretty);
 		pretty_str = pretty.buf;
 	}
-	if (!prefixcmp(pretty_str, "[PATCH] "))
+	if (starts_with(pretty_str, "[PATCH] "))
 		pretty_str += 8;
 
 	if (!no_name) {
@@ -396,7 +396,7 @@
 {
 	unsigned char tmp[20];
 	int ofs = 11;
-	if (prefixcmp(refname, "refs/heads/"))
+	if (!starts_with(refname, "refs/heads/"))
 		return 0;
 	/* If both heads/foo and tags/foo exists, get_sha1 would
 	 * get confused.
@@ -410,7 +410,7 @@
 {
 	unsigned char tmp[20];
 	int ofs = 13;
-	if (prefixcmp(refname, "refs/remotes/"))
+	if (!starts_with(refname, "refs/remotes/"))
 		return 0;
 	/* If both heads/foo and tags/foo exists, get_sha1 would
 	 * get confused.
@@ -422,7 +422,7 @@
 
 static int append_tag_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
 {
-	if (prefixcmp(refname, "refs/tags/"))
+	if (!starts_with(refname, "refs/tags/"))
 		return 0;
 	return append_ref(refname + 5, sha1, 0);
 }
@@ -453,9 +453,9 @@
 		return 0;
 	if (fnmatch(match_ref_pattern, tail, 0))
 		return 0;
-	if (!prefixcmp(refname, "refs/heads/"))
+	if (starts_with(refname, "refs/heads/"))
 		return append_head_ref(refname, sha1, flag, cb_data);
-	if (!prefixcmp(refname, "refs/tags/"))
+	if (starts_with(refname, "refs/tags/"))
 		return append_tag_ref(refname, sha1, flag, cb_data);
 	return append_ref(refname, sha1, 0);
 }
@@ -480,11 +480,11 @@
 	if ((!head[0]) ||
 	    (head_sha1 && sha1 && hashcmp(head_sha1, sha1)))
 		return 0;
-	if (!prefixcmp(head, "refs/heads/"))
+	if (starts_with(head, "refs/heads/"))
 		head += 11;
-	if (!prefixcmp(name, "refs/heads/"))
+	if (starts_with(name, "refs/heads/"))
 		name += 11;
-	else if (!prefixcmp(name, "heads/"))
+	else if (starts_with(name, "heads/"))
 		name += 6;
 	return !strcmp(head, name);
 }
@@ -813,7 +813,7 @@
 				has_head++;
 		}
 		if (!has_head) {
-			int offset = !prefixcmp(head, "refs/heads/") ? 11 : 0;
+			int offset = starts_with(head, "refs/heads/") ? 11 : 0;
 			append_one_rev(head + offset);
 		}
 	}
diff --git a/builtin/show-ref.c b/builtin/show-ref.c
index 9f3f5e3..5ba1f30 100644
--- a/builtin/show-ref.c
+++ b/builtin/show-ref.c
@@ -37,8 +37,8 @@
 	if (tags_only || heads_only) {
 		int match;
 
-		match = heads_only && !prefixcmp(refname, "refs/heads/");
-		match |= tags_only && !prefixcmp(refname, "refs/tags/");
+		match = heads_only && starts_with(refname, "refs/heads/");
+		match |= tags_only && starts_with(refname, "refs/tags/");
 		if (!match)
 			return 0;
 	}
@@ -210,7 +210,7 @@
 		while (*pattern) {
 			unsigned char sha1[20];
 
-			if (!prefixcmp(*pattern, "refs/") &&
+			if (starts_with(*pattern, "refs/") &&
 			    !read_ref(*pattern, sha1)) {
 				if (!quiet)
 					show_one(*pattern, sha1);
diff --git a/builtin/symbolic-ref.c b/builtin/symbolic-ref.c
index 71286b4..b6a711d 100644
--- a/builtin/symbolic-ref.c
+++ b/builtin/symbolic-ref.c
@@ -65,7 +65,7 @@
 		break;
 	case 2:
 		if (!strcmp(argv[0], "HEAD") &&
-		    prefixcmp(argv[1], "refs/"))
+		    !starts_with(argv[1], "refs/"))
 			die("Refusing to point HEAD outside of refs/");
 		create_symref(argv[0], argv[1], msg);
 		break;
diff --git a/builtin/tag.c b/builtin/tag.c
index ea55f1d..74d3780 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -259,7 +259,7 @@
 	int status = git_gpg_config(var, value, cb);
 	if (status)
 		return status;
-	if (!prefixcmp(var, "column."))
+	if (starts_with(var, "column."))
 		return git_column_config(var, value, "tag", &colopts);
 	return git_default_config(var, value, cb);
 }
diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c
index 2217d7b..62ff673 100644
--- a/builtin/unpack-objects.c
+++ b/builtin/unpack-objects.c
@@ -523,7 +523,7 @@
 				strict = 1;
 				continue;
 			}
-			if (!prefixcmp(arg, "--pack_header=")) {
+			if (starts_with(arg, "--pack_header=")) {
 				struct pack_header *hdr;
 				char *c;
 
diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index 702e90d..1292cfe 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -229,15 +229,15 @@
 			die("empty command in input");
 		else if (isspace(*cmd.buf))
 			die("whitespace before command: %s", cmd.buf);
-		else if (!prefixcmp(cmd.buf, "update "))
+		else if (starts_with(cmd.buf, "update "))
 			parse_cmd_update(cmd.buf + 7);
-		else if (!prefixcmp(cmd.buf, "create "))
+		else if (starts_with(cmd.buf, "create "))
 			parse_cmd_create(cmd.buf + 7);
-		else if (!prefixcmp(cmd.buf, "delete "))
+		else if (starts_with(cmd.buf, "delete "))
 			parse_cmd_delete(cmd.buf + 7);
-		else if (!prefixcmp(cmd.buf, "verify "))
+		else if (starts_with(cmd.buf, "verify "))
 			parse_cmd_verify(cmd.buf + 7);
-		else if (!prefixcmp(cmd.buf, "option "))
+		else if (starts_with(cmd.buf, "option "))
 			parse_cmd_option(cmd.buf + 7);
 		else
 			die("unknown command: %s", cmd.buf);
diff --git a/builtin/upload-archive.c b/builtin/upload-archive.c
index af2da35..32ab94c 100644
--- a/builtin/upload-archive.c
+++ b/builtin/upload-archive.c
@@ -37,7 +37,7 @@
 		if (sent_argv.argc > MAX_ARGS)
 			die("Too many options (>%d)", MAX_ARGS - 1);
 
-		if (prefixcmp(buf, arg_cmd))
+		if (!starts_with(buf, arg_cmd))
 			die("'argument' token or flush expected");
 		argv_array_push(&sent_argv, buf + strlen(arg_cmd));
 	}
diff --git a/commit.c b/commit.c
index de16a3c..2a9bf59 100644
--- a/commit.c
+++ b/commit.c
@@ -559,7 +559,7 @@
 	     buf;
 	     buf = line_end + 1) {
 		line_end = strchrnul(buf, '\n');
-		if (prefixcmp(buf, "author ")) {
+		if (!starts_with(buf, "author ")) {
 			if (!line_end[0] || line_end[1] == '\n')
 				return; /* end of header */
 			continue;
@@ -1106,7 +1106,7 @@
 		next = next ? next + 1 : tail;
 		if (in_signature && line[0] == ' ')
 			sig = line + 1;
-		else if (!prefixcmp(line, gpg_sig_header) &&
+		else if (starts_with(line, gpg_sig_header) &&
 			 line[gpg_sig_header_len] == ' ')
 			sig = line + gpg_sig_header_len + 1;
 		if (sig) {
@@ -1186,7 +1186,7 @@
 	for (i = 0; i < ARRAY_SIZE(sigcheck_gpg_status); i++) {
 		const char *found, *next;
 
-		if (!prefixcmp(buf, sigcheck_gpg_status[i].check + 1)) {
+		if (starts_with(buf, sigcheck_gpg_status[i].check + 1)) {
 			/* At the very beginning of the buffer */
 			found = buf + strlen(sigcheck_gpg_status[i].check + 1);
 		} else {
diff --git a/config.c b/config.c
index e1d66a1..7b62f33 100644
--- a/config.c
+++ b/config.c
@@ -969,25 +969,25 @@
 
 int git_default_config(const char *var, const char *value, void *dummy)
 {
-	if (!prefixcmp(var, "core."))
+	if (starts_with(var, "core."))
 		return git_default_core_config(var, value);
 
-	if (!prefixcmp(var, "user."))
+	if (starts_with(var, "user."))
 		return git_ident_config(var, value, dummy);
 
-	if (!prefixcmp(var, "i18n."))
+	if (starts_with(var, "i18n."))
 		return git_default_i18n_config(var, value);
 
-	if (!prefixcmp(var, "branch."))
+	if (starts_with(var, "branch."))
 		return git_default_branch_config(var, value);
 
-	if (!prefixcmp(var, "push."))
+	if (starts_with(var, "push."))
 		return git_default_push_config(var, value);
 
-	if (!prefixcmp(var, "mailmap."))
+	if (starts_with(var, "mailmap."))
 		return git_default_mailmap_config(var, value);
 
-	if (!prefixcmp(var, "advice."))
+	if (starts_with(var, "advice."))
 		return git_default_advice_config(var, value);
 
 	if (!strcmp(var, "pager.color") || !strcmp(var, "color.pager")) {
@@ -1872,7 +1872,7 @@
 	const char *dot;
 
 	/* Does it start with "section." ? */
-	if (prefixcmp(var, section) || var[section_len] != '.')
+	if (!starts_with(var, section) || var[section_len] != '.')
 		return -1;
 
 	/*
diff --git a/connect.c b/connect.c
index 06e88b0..d51d106 100644
--- a/connect.c
+++ b/connect.c
@@ -145,7 +145,7 @@
 		if (!len)
 			break;
 
-		if (len > 4 && !prefixcmp(buffer, "ERR "))
+		if (len > 4 && starts_with(buffer, "ERR "))
 			die("remote error: %s", buffer + 4);
 
 		if (len < 42 || get_sha1_hex(buffer, old_sha1) || buffer[40] != ' ')
diff --git a/connected.c b/connected.c
index fae8d64..51d8ba4 100644
--- a/connected.c
+++ b/connected.c
@@ -38,7 +38,7 @@
 	if (transport && transport->smart_options &&
 	    transport->smart_options->self_contained_and_connected &&
 	    transport->pack_lockfile &&
-	    !suffixcmp(transport->pack_lockfile, ".keep")) {
+	    ends_with(transport->pack_lockfile, ".keep")) {
 		struct strbuf idx_file = STRBUF_INIT;
 		strbuf_addstr(&idx_file, transport->pack_lockfile);
 		strbuf_setlen(&idx_file, idx_file.len - 5); /* ".keep" */
diff --git a/convert.c b/convert.c
index 11a95fc..ab80b72 100644
--- a/convert.c
+++ b/convert.c
@@ -1121,7 +1121,7 @@
 {
 	int i;
 
-	if (prefixcmp(str, "$Id: "))
+	if (!starts_with(str, "$Id: "))
 		return 0;
 	for (i = 5; str[i]; i++) {
 		if (isspace(str[i]) && str[i+1] != '$')
diff --git a/daemon.c b/daemon.c
index 34916c5..7bee953 100644
--- a/daemon.c
+++ b/daemon.c
@@ -235,7 +235,7 @@
 
 static int git_daemon_config(const char *var, const char *value, void *cb)
 {
-	if (!prefixcmp(var, "daemon.") &&
+	if (starts_with(var, "daemon.") &&
 	    !strcmp(var + 7, service_looking_at->config_name)) {
 		service_enabled = git_config_bool(var, value);
 		return 0;
@@ -633,7 +633,7 @@
 	for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
 		struct daemon_service *s = &(daemon_service[i]);
 		int namelen = strlen(s->name);
-		if (!prefixcmp(line, "git-") &&
+		if (starts_with(line, "git-") &&
 		    !strncmp(s->name, line + 4, namelen) &&
 		    line[namelen + 4] == ' ') {
 			/*
@@ -1165,11 +1165,11 @@
 	for (i = 1; i < argc; i++) {
 		char *arg = argv[i];
 
-		if (!prefixcmp(arg, "--listen=")) {
+		if (starts_with(arg, "--listen=")) {
 			string_list_append(&listen_addr, xstrdup_tolower(arg + 9));
 			continue;
 		}
-		if (!prefixcmp(arg, "--port=")) {
+		if (starts_with(arg, "--port=")) {
 			char *end;
 			unsigned long n;
 			n = strtoul(arg+7, &end, 0);
@@ -1199,19 +1199,19 @@
 			export_all_trees = 1;
 			continue;
 		}
-		if (!prefixcmp(arg, "--access-hook=")) {
+		if (starts_with(arg, "--access-hook=")) {
 			access_hook = arg + 14;
 			continue;
 		}
-		if (!prefixcmp(arg, "--timeout=")) {
+		if (starts_with(arg, "--timeout=")) {
 			timeout = atoi(arg+10);
 			continue;
 		}
-		if (!prefixcmp(arg, "--init-timeout=")) {
+		if (starts_with(arg, "--init-timeout=")) {
 			init_timeout = atoi(arg+15);
 			continue;
 		}
-		if (!prefixcmp(arg, "--max-connections=")) {
+		if (starts_with(arg, "--max-connections=")) {
 			max_connections = atoi(arg+18);
 			if (max_connections < 0)
 				max_connections = 0;	        /* unlimited */
@@ -1221,7 +1221,7 @@
 			strict_paths = 1;
 			continue;
 		}
-		if (!prefixcmp(arg, "--base-path=")) {
+		if (starts_with(arg, "--base-path=")) {
 			base_path = arg+12;
 			continue;
 		}
@@ -1229,7 +1229,7 @@
 			base_path_relaxed = 1;
 			continue;
 		}
-		if (!prefixcmp(arg, "--interpolated-path=")) {
+		if (starts_with(arg, "--interpolated-path=")) {
 			interpolated_path = arg+20;
 			continue;
 		}
@@ -1241,11 +1241,11 @@
 			user_path = "";
 			continue;
 		}
-		if (!prefixcmp(arg, "--user-path=")) {
+		if (starts_with(arg, "--user-path=")) {
 			user_path = arg + 12;
 			continue;
 		}
-		if (!prefixcmp(arg, "--pid-file=")) {
+		if (starts_with(arg, "--pid-file=")) {
 			pid_file = arg + 11;
 			continue;
 		}
@@ -1254,35 +1254,35 @@
 			log_syslog = 1;
 			continue;
 		}
-		if (!prefixcmp(arg, "--user=")) {
+		if (starts_with(arg, "--user=")) {
 			user_name = arg + 7;
 			continue;
 		}
-		if (!prefixcmp(arg, "--group=")) {
+		if (starts_with(arg, "--group=")) {
 			group_name = arg + 8;
 			continue;
 		}
-		if (!prefixcmp(arg, "--enable=")) {
+		if (starts_with(arg, "--enable=")) {
 			enable_service(arg + 9, 1);
 			continue;
 		}
-		if (!prefixcmp(arg, "--disable=")) {
+		if (starts_with(arg, "--disable=")) {
 			enable_service(arg + 10, 0);
 			continue;
 		}
-		if (!prefixcmp(arg, "--allow-override=")) {
+		if (starts_with(arg, "--allow-override=")) {
 			make_service_overridable(arg + 17, 1);
 			continue;
 		}
-		if (!prefixcmp(arg, "--forbid-override=")) {
+		if (starts_with(arg, "--forbid-override=")) {
 			make_service_overridable(arg + 18, 0);
 			continue;
 		}
-		if (!prefixcmp(arg, "--informative-errors")) {
+		if (starts_with(arg, "--informative-errors")) {
 			informative_errors = 1;
 			continue;
 		}
-		if (!prefixcmp(arg, "--no-informative-errors")) {
+		if (starts_with(arg, "--no-informative-errors")) {
 			informative_errors = 0;
 			continue;
 		}
diff --git a/diff.c b/diff.c
index e34bf97..d53029b 100644
--- a/diff.c
+++ b/diff.c
@@ -235,7 +235,7 @@
 	if (userdiff_config(var, value) < 0)
 		return -1;
 
-	if (!prefixcmp(var, "diff.color.") || !prefixcmp(var, "color.diff.")) {
+	if (starts_with(var, "diff.color.") || starts_with(var, "color.diff.")) {
 		int slot = parse_diff_color_slot(var, 11);
 		if (slot < 0)
 			return 0;
@@ -264,7 +264,7 @@
 		return 0;
 	}
 
-	if (!prefixcmp(var, "submodule."))
+	if (starts_with(var, "submodule."))
 		return parse_submodule_config_option(var, value);
 
 	return git_default_config(var, value, cb);
@@ -1215,7 +1215,7 @@
 			diff_words_append(line, len,
 					  &ecbdata->diff_words->plus);
 			return;
-		} else if (!prefixcmp(line, "\\ ")) {
+		} else if (starts_with(line, "\\ ")) {
 			/*
 			 * Eat the "no newline at eof" marker as if we
 			 * saw a "+" or "-" line with nothing on it,
@@ -2387,9 +2387,9 @@
 			xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags);
 		if (!diffopts)
 			;
-		else if (!prefixcmp(diffopts, "--unified="))
+		else if (starts_with(diffopts, "--unified="))
 			xecfg.ctxlen = strtoul(diffopts + 10, NULL, 10);
-		else if (!prefixcmp(diffopts, "-u"))
+		else if (starts_with(diffopts, "-u"))
 			xecfg.ctxlen = strtoul(diffopts + 2, NULL, 10);
 		if (o->word_diff)
 			init_diff_words_data(&ecbdata, o, one, two);
@@ -3391,7 +3391,7 @@
 	if (arg[0] != '-' || arg[1] != '-')
 		return 0;
 	arg += strlen("--");
-	if (prefixcmp(arg, opt))
+	if (!starts_with(arg, opt))
 		return 0;
 	arg += strlen(opt);
 	if (*arg == '=') { /* sticked form: --option=value */
@@ -3422,7 +3422,7 @@
 
 	switch (*arg) {
 	case '-':
-		if (!prefixcmp(arg, "-width")) {
+		if (starts_with(arg, "-width")) {
 			arg += strlen("-width");
 			if (*arg == '=')
 				width = strtoul(arg + 1, &end, 10);
@@ -3432,7 +3432,7 @@
 				width = strtoul(av[1], &end, 10);
 				argcount = 2;
 			}
-		} else if (!prefixcmp(arg, "-name-width")) {
+		} else if (starts_with(arg, "-name-width")) {
 			arg += strlen("-name-width");
 			if (*arg == '=')
 				name_width = strtoul(arg + 1, &end, 10);
@@ -3442,7 +3442,7 @@
 				name_width = strtoul(av[1], &end, 10);
 				argcount = 2;
 			}
-		} else if (!prefixcmp(arg, "-graph-width")) {
+		} else if (starts_with(arg, "-graph-width")) {
 			arg += strlen("-graph-width");
 			if (*arg == '=')
 				graph_width = strtoul(arg + 1, &end, 10);
@@ -3452,7 +3452,7 @@
 				graph_width = strtoul(av[1], &end, 10);
 				argcount = 2;
 			}
-		} else if (!prefixcmp(arg, "-count")) {
+		} else if (starts_with(arg, "-count")) {
 			arg += strlen("-count");
 			if (*arg == '=')
 				count = strtoul(arg + 1, &end, 10);
@@ -3614,15 +3614,15 @@
 		options->output_format |= DIFF_FORMAT_SHORTSTAT;
 	else if (!strcmp(arg, "-X") || !strcmp(arg, "--dirstat"))
 		return parse_dirstat_opt(options, "");
-	else if (!prefixcmp(arg, "-X"))
+	else if (starts_with(arg, "-X"))
 		return parse_dirstat_opt(options, arg + 2);
-	else if (!prefixcmp(arg, "--dirstat="))
+	else if (starts_with(arg, "--dirstat="))
 		return parse_dirstat_opt(options, arg + 10);
 	else if (!strcmp(arg, "--cumulative"))
 		return parse_dirstat_opt(options, "cumulative");
 	else if (!strcmp(arg, "--dirstat-by-file"))
 		return parse_dirstat_opt(options, "files");
-	else if (!prefixcmp(arg, "--dirstat-by-file=")) {
+	else if (starts_with(arg, "--dirstat-by-file=")) {
 		parse_dirstat_opt(options, "files");
 		return parse_dirstat_opt(options, arg + 18);
 	}
@@ -3639,17 +3639,17 @@
 		options->output_format |= DIFF_FORMAT_NAME_STATUS;
 	else if (!strcmp(arg, "-s") || !strcmp(arg, "--no-patch"))
 		options->output_format |= DIFF_FORMAT_NO_OUTPUT;
-	else if (!prefixcmp(arg, "--stat"))
+	else if (starts_with(arg, "--stat"))
 		/* --stat, --stat-width, --stat-name-width, or --stat-count */
 		return stat_opt(options, av);
 
 	/* renames options */
-	else if (!prefixcmp(arg, "-B") || !prefixcmp(arg, "--break-rewrites=") ||
+	else if (starts_with(arg, "-B") || starts_with(arg, "--break-rewrites=") ||
 		 !strcmp(arg, "--break-rewrites")) {
 		if ((options->break_opt = diff_scoreopt_parse(arg)) == -1)
 			return error("invalid argument to -B: %s", arg+2);
 	}
-	else if (!prefixcmp(arg, "-M") || !prefixcmp(arg, "--find-renames=") ||
+	else if (starts_with(arg, "-M") || starts_with(arg, "--find-renames=") ||
 		 !strcmp(arg, "--find-renames")) {
 		if ((options->rename_score = diff_scoreopt_parse(arg)) == -1)
 			return error("invalid argument to -M: %s", arg+2);
@@ -3658,7 +3658,7 @@
 	else if (!strcmp(arg, "-D") || !strcmp(arg, "--irreversible-delete")) {
 		options->irreversible_delete = 1;
 	}
-	else if (!prefixcmp(arg, "-C") || !prefixcmp(arg, "--find-copies=") ||
+	else if (starts_with(arg, "-C") || starts_with(arg, "--find-copies=") ||
 		 !strcmp(arg, "--find-copies")) {
 		if (options->detect_rename == DIFF_DETECT_COPY)
 			DIFF_OPT_SET(options, FIND_COPIES_HARDER);
@@ -3674,7 +3674,7 @@
 		DIFF_OPT_CLR(options, RENAME_EMPTY);
 	else if (!strcmp(arg, "--relative"))
 		DIFF_OPT_SET(options, RELATIVE_NAME);
-	else if (!prefixcmp(arg, "--relative=")) {
+	else if (starts_with(arg, "--relative=")) {
 		DIFF_OPT_SET(options, RELATIVE_NAME);
 		options->prefix = arg + 11;
 	}
@@ -3727,7 +3727,7 @@
 		DIFF_OPT_CLR(options, FOLLOW_RENAMES);
 	else if (!strcmp(arg, "--color"))
 		options->use_color = 1;
-	else if (!prefixcmp(arg, "--color=")) {
+	else if (starts_with(arg, "--color=")) {
 		int value = git_config_colorbool(NULL, arg+8);
 		if (value < 0)
 			return error("option `color' expects \"always\", \"auto\", or \"never\"");
@@ -3739,7 +3739,7 @@
 		options->use_color = 1;
 		options->word_diff = DIFF_WORDS_COLOR;
 	}
-	else if (!prefixcmp(arg, "--color-words=")) {
+	else if (starts_with(arg, "--color-words=")) {
 		options->use_color = 1;
 		options->word_diff = DIFF_WORDS_COLOR;
 		options->word_regex = arg + 14;
@@ -3748,7 +3748,7 @@
 		if (options->word_diff == DIFF_WORDS_NONE)
 			options->word_diff = DIFF_WORDS_PLAIN;
 	}
-	else if (!prefixcmp(arg, "--word-diff=")) {
+	else if (starts_with(arg, "--word-diff=")) {
 		const char *type = arg + 12;
 		if (!strcmp(type, "plain"))
 			options->word_diff = DIFF_WORDS_PLAIN;
@@ -3784,12 +3784,12 @@
 	else if (!strcmp(arg, "--ignore-submodules")) {
 		DIFF_OPT_SET(options, OVERRIDE_SUBMODULE_CONFIG);
 		handle_ignore_submodules_arg(options, "all");
-	} else if (!prefixcmp(arg, "--ignore-submodules=")) {
+	} else if (starts_with(arg, "--ignore-submodules=")) {
 		DIFF_OPT_SET(options, OVERRIDE_SUBMODULE_CONFIG);
 		handle_ignore_submodules_arg(options, arg + 20);
 	} else if (!strcmp(arg, "--submodule"))
 		DIFF_OPT_SET(options, SUBMODULE_LOG);
-	else if (!prefixcmp(arg, "--submodule="))
+	else if (starts_with(arg, "--submodule="))
 		return parse_submodule_opt(options, arg + 12);
 
 	/* misc options */
@@ -3825,7 +3825,7 @@
 	}
 	else if (!strcmp(arg, "--abbrev"))
 		options->abbrev = DEFAULT_ABBREV;
-	else if (!prefixcmp(arg, "--abbrev=")) {
+	else if (starts_with(arg, "--abbrev=")) {
 		options->abbrev = strtoul(arg + 9, NULL, 10);
 		if (options->abbrev < MINIMUM_ABBREV)
 			options->abbrev = MINIMUM_ABBREV;
@@ -3907,15 +3907,15 @@
 	cmd = *opt++;
 	if (cmd == '-') {
 		/* convert the long-form arguments into short-form versions */
-		if (!prefixcmp(opt, "break-rewrites")) {
+		if (starts_with(opt, "break-rewrites")) {
 			opt += strlen("break-rewrites");
 			if (*opt == 0 || *opt++ == '=')
 				cmd = 'B';
-		} else if (!prefixcmp(opt, "find-copies")) {
+		} else if (starts_with(opt, "find-copies")) {
 			opt += strlen("find-copies");
 			if (*opt == 0 || *opt++ == '=')
 				cmd = 'C';
-		} else if (!prefixcmp(opt, "find-renames")) {
+		} else if (starts_with(opt, "find-renames")) {
 			opt += strlen("find-renames");
 			if (*opt == 0 || *opt++ == '=')
 				cmd = 'M';
@@ -4325,7 +4325,7 @@
 	int new_len;
 
 	/* Ignore line numbers when computing the SHA1 of the patch */
-	if (!prefixcmp(line, "@@ -"))
+	if (starts_with(line, "@@ -"))
 		return;
 
 	new_len = remove_space(line, len);
diff --git a/environment.c b/environment.c
index cd2b068..3c76905 100644
--- a/environment.c
+++ b/environment.c
@@ -171,7 +171,7 @@
 
 const char *strip_namespace(const char *namespaced_ref)
 {
-	if (prefixcmp(namespaced_ref, get_git_namespace()))
+	if (!starts_with(namespaced_ref, get_git_namespace()))
 		return NULL;
 	return namespaced_ref + namespace_len;
 }
diff --git a/fast-import.c b/fast-import.c
index f4d9969..4fd18a3 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -1877,8 +1877,8 @@
 				return EOF;
 
 			if (!seen_data_command
-				&& prefixcmp(command_buf.buf, "feature ")
-				&& prefixcmp(command_buf.buf, "option ")) {
+				&& !starts_with(command_buf.buf, "feature ")
+				&& !starts_with(command_buf.buf, "option ")) {
 				parse_argv();
 			}
 
@@ -1898,7 +1898,7 @@
 			rc->prev->next = rc;
 			cmd_tail = rc;
 		}
-		if (!prefixcmp(command_buf.buf, "cat-blob ")) {
+		if (starts_with(command_buf.buf, "cat-blob ")) {
 			parse_cat_blob();
 			continue;
 		}
@@ -1917,7 +1917,7 @@
 
 static void parse_mark(void)
 {
-	if (!prefixcmp(command_buf.buf, "mark :")) {
+	if (starts_with(command_buf.buf, "mark :")) {
 		next_mark = strtoumax(command_buf.buf + 6, NULL, 10);
 		read_next_command();
 	}
@@ -1929,10 +1929,10 @@
 {
 	strbuf_reset(sb);
 
-	if (prefixcmp(command_buf.buf, "data "))
+	if (!starts_with(command_buf.buf, "data "))
 		die("Expected 'data n' command, found: %s", command_buf.buf);
 
-	if (!prefixcmp(command_buf.buf + 5, "<<")) {
+	if (starts_with(command_buf.buf + 5, "<<")) {
 		char *term = xstrdup(command_buf.buf + 5 + 2);
 		size_t term_len = command_buf.len - 5 - 2;
 
@@ -2306,7 +2306,7 @@
 	if (*p == ':') {
 		oe = find_mark(parse_mark_ref_space(&p));
 		hashcpy(sha1, oe->idx.sha1);
-	} else if (!prefixcmp(p, "inline ")) {
+	} else if (starts_with(p, "inline ")) {
 		inline_data = 1;
 		oe = NULL; /* not used with inline_data, but makes gcc happy */
 		p += strlen("inline");  /* advance to space */
@@ -2479,7 +2479,7 @@
 	if (*p == ':') {
 		oe = find_mark(parse_mark_ref_space(&p));
 		hashcpy(sha1, oe->idx.sha1);
-	} else if (!prefixcmp(p, "inline ")) {
+	} else if (starts_with(p, "inline ")) {
 		inline_data = 1;
 		oe = NULL; /* not used with inline_data, but makes gcc happy */
 		p += strlen("inline");  /* advance to space */
@@ -2590,7 +2590,7 @@
 	const char *from;
 	struct branch *s;
 
-	if (prefixcmp(command_buf.buf, "from "))
+	if (!starts_with(command_buf.buf, "from "))
 		return 0;
 
 	if (b->branch_tree.tree) {
@@ -2636,7 +2636,7 @@
 	struct branch *s;
 
 	*count = 0;
-	while (!prefixcmp(command_buf.buf, "merge ")) {
+	while (starts_with(command_buf.buf, "merge ")) {
 		from = strchr(command_buf.buf, ' ') + 1;
 		n = xmalloc(sizeof(*n));
 		s = lookup_branch(from);
@@ -2687,11 +2687,11 @@
 
 	read_next_command();
 	parse_mark();
-	if (!prefixcmp(command_buf.buf, "author ")) {
+	if (starts_with(command_buf.buf, "author ")) {
 		author = parse_ident(command_buf.buf + 7);
 		read_next_command();
 	}
-	if (!prefixcmp(command_buf.buf, "committer ")) {
+	if (starts_with(command_buf.buf, "committer ")) {
 		committer = parse_ident(command_buf.buf + 10);
 		read_next_command();
 	}
@@ -2712,19 +2712,19 @@
 
 	/* file_change* */
 	while (command_buf.len > 0) {
-		if (!prefixcmp(command_buf.buf, "M "))
+		if (starts_with(command_buf.buf, "M "))
 			file_change_m(b);
-		else if (!prefixcmp(command_buf.buf, "D "))
+		else if (starts_with(command_buf.buf, "D "))
 			file_change_d(b);
-		else if (!prefixcmp(command_buf.buf, "R "))
+		else if (starts_with(command_buf.buf, "R "))
 			file_change_cr(b, 1);
-		else if (!prefixcmp(command_buf.buf, "C "))
+		else if (starts_with(command_buf.buf, "C "))
 			file_change_cr(b, 0);
-		else if (!prefixcmp(command_buf.buf, "N "))
+		else if (starts_with(command_buf.buf, "N "))
 			note_change_n(b, &prev_fanout);
 		else if (!strcmp("deleteall", command_buf.buf))
 			file_change_deleteall(b);
-		else if (!prefixcmp(command_buf.buf, "ls "))
+		else if (starts_with(command_buf.buf, "ls "))
 			parse_ls(b);
 		else {
 			unread_command_buf = 1;
@@ -2793,7 +2793,7 @@
 	read_next_command();
 
 	/* from ... */
-	if (prefixcmp(command_buf.buf, "from "))
+	if (!starts_with(command_buf.buf, "from "))
 		die("Expected from command, got %s", command_buf.buf);
 	from = strchr(command_buf.buf, ' ') + 1;
 	s = lookup_branch(from);
@@ -2821,7 +2821,7 @@
 	read_next_command();
 
 	/* tagger ... */
-	if (!prefixcmp(command_buf.buf, "tagger ")) {
+	if (starts_with(command_buf.buf, "tagger ")) {
 		tagger = parse_ident(command_buf.buf + 7);
 		read_next_command();
 	} else
@@ -3209,7 +3209,7 @@
 
 static int parse_one_option(const char *option)
 {
-	if (!prefixcmp(option, "max-pack-size=")) {
+	if (starts_with(option, "max-pack-size=")) {
 		unsigned long v;
 		if (!git_parse_ulong(option + 14, &v))
 			return 0;
@@ -3221,20 +3221,20 @@
 			v = 1024 * 1024;
 		}
 		max_packsize = v;
-	} else if (!prefixcmp(option, "big-file-threshold=")) {
+	} else if (starts_with(option, "big-file-threshold=")) {
 		unsigned long v;
 		if (!git_parse_ulong(option + 19, &v))
 			return 0;
 		big_file_threshold = v;
-	} else if (!prefixcmp(option, "depth=")) {
+	} else if (starts_with(option, "depth=")) {
 		option_depth(option + 6);
-	} else if (!prefixcmp(option, "active-branches=")) {
+	} else if (starts_with(option, "active-branches=")) {
 		option_active_branches(option + 16);
-	} else if (!prefixcmp(option, "export-pack-edges=")) {
+	} else if (starts_with(option, "export-pack-edges=")) {
 		option_export_pack_edges(option + 18);
-	} else if (!prefixcmp(option, "quiet")) {
+	} else if (starts_with(option, "quiet")) {
 		show_stats = 0;
-	} else if (!prefixcmp(option, "stats")) {
+	} else if (starts_with(option, "stats")) {
 		show_stats = 1;
 	} else {
 		return 0;
@@ -3245,14 +3245,14 @@
 
 static int parse_one_feature(const char *feature, int from_stream)
 {
-	if (!prefixcmp(feature, "date-format=")) {
+	if (starts_with(feature, "date-format=")) {
 		option_date_format(feature + 12);
-	} else if (!prefixcmp(feature, "import-marks=")) {
+	} else if (starts_with(feature, "import-marks=")) {
 		option_import_marks(feature + 13, from_stream, 0);
-	} else if (!prefixcmp(feature, "import-marks-if-exists=")) {
+	} else if (starts_with(feature, "import-marks-if-exists=")) {
 		option_import_marks(feature + strlen("import-marks-if-exists="),
 					from_stream, 1);
-	} else if (!prefixcmp(feature, "export-marks=")) {
+	} else if (starts_with(feature, "export-marks=")) {
 		option_export_marks(feature + 13);
 	} else if (!strcmp(feature, "cat-blob")) {
 		; /* Don't die - this feature is supported */
@@ -3350,7 +3350,7 @@
 		if (parse_one_feature(a + 2, 0))
 			continue;
 
-		if (!prefixcmp(a + 2, "cat-blob-fd=")) {
+		if (starts_with(a + 2, "cat-blob-fd=")) {
 			option_cat_blob_fd(a + 2 + strlen("cat-blob-fd="));
 			continue;
 		}
@@ -3404,25 +3404,25 @@
 	while (read_next_command() != EOF) {
 		if (!strcmp("blob", command_buf.buf))
 			parse_new_blob();
-		else if (!prefixcmp(command_buf.buf, "ls "))
+		else if (starts_with(command_buf.buf, "ls "))
 			parse_ls(NULL);
-		else if (!prefixcmp(command_buf.buf, "commit "))
+		else if (starts_with(command_buf.buf, "commit "))
 			parse_new_commit();
-		else if (!prefixcmp(command_buf.buf, "tag "))
+		else if (starts_with(command_buf.buf, "tag "))
 			parse_new_tag();
-		else if (!prefixcmp(command_buf.buf, "reset "))
+		else if (starts_with(command_buf.buf, "reset "))
 			parse_reset_branch();
 		else if (!strcmp("checkpoint", command_buf.buf))
 			parse_checkpoint();
 		else if (!strcmp("done", command_buf.buf))
 			break;
-		else if (!prefixcmp(command_buf.buf, "progress "))
+		else if (starts_with(command_buf.buf, "progress "))
 			parse_progress();
-		else if (!prefixcmp(command_buf.buf, "feature "))
+		else if (starts_with(command_buf.buf, "feature "))
 			parse_feature();
-		else if (!prefixcmp(command_buf.buf, "option git "))
+		else if (starts_with(command_buf.buf, "option git "))
 			parse_option();
-		else if (!prefixcmp(command_buf.buf, "option "))
+		else if (starts_with(command_buf.buf, "option "))
 			/* ignore non-git options*/;
 		else
 			die("Unsupported command: %s", command_buf.buf);
diff --git a/fetch-pack.c b/fetch-pack.c
index 1042448..36be5b2 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -176,9 +176,9 @@
 		 */
 		char *line;
 		while ((line = packet_read_line(fd, NULL))) {
-			if (!prefixcmp(line, "shallow "))
+			if (starts_with(line, "shallow "))
 				continue;
-			if (!prefixcmp(line, "unshallow "))
+			if (starts_with(line, "unshallow "))
 				continue;
 			die("git fetch-pack: expected shallow list");
 		}
@@ -194,7 +194,7 @@
 		die("git fetch-pack: expected ACK/NAK, got EOF");
 	if (!strcmp(line, "NAK"))
 		return NAK;
-	if (!prefixcmp(line, "ACK ")) {
+	if (starts_with(line, "ACK ")) {
 		if (!get_sha1_hex(line+4, result_sha1)) {
 			if (len < 45)
 				return ACK;
@@ -323,13 +323,13 @@
 
 		send_request(args, fd[1], &req_buf);
 		while ((line = packet_read_line(fd[0], NULL))) {
-			if (!prefixcmp(line, "shallow ")) {
+			if (starts_with(line, "shallow ")) {
 				if (get_sha1_hex(line + 8, sha1))
 					die("invalid shallow line: %s", line);
 				register_shallow(sha1);
 				continue;
 			}
-			if (!prefixcmp(line, "unshallow ")) {
+			if (starts_with(line, "unshallow ")) {
 				if (get_sha1_hex(line + 10, sha1))
 					die("invalid unshallow line: %s", line);
 				if (!lookup_object(sha1))
@@ -523,7 +523,7 @@
 		}
 
 		if (!keep && args->fetch_all &&
-		    (!args->depth || prefixcmp(ref->name, "refs/tags/")))
+		    (!args->depth || !starts_with(ref->name, "refs/tags/")))
 			keep = 1;
 
 		if (keep) {
diff --git a/git.c b/git.c
index 727e380..3799514 100644
--- a/git.c
+++ b/git.c
@@ -54,7 +54,7 @@
 		/*
 		 * Check remaining flags.
 		 */
-		if (!prefixcmp(cmd, "--exec-path")) {
+		if (starts_with(cmd, "--exec-path")) {
 			cmd += 11;
 			if (*cmd == '=')
 				git_set_argv_exec_path(cmd + 1);
@@ -92,7 +92,7 @@
 				*envchanged = 1;
 			(*argv)++;
 			(*argc)--;
-		} else if (!prefixcmp(cmd, "--git-dir=")) {
+		} else if (starts_with(cmd, "--git-dir=")) {
 			setenv(GIT_DIR_ENVIRONMENT, cmd + 10, 1);
 			if (envchanged)
 				*envchanged = 1;
@@ -106,7 +106,7 @@
 				*envchanged = 1;
 			(*argv)++;
 			(*argc)--;
-		} else if (!prefixcmp(cmd, "--namespace=")) {
+		} else if (starts_with(cmd, "--namespace=")) {
 			setenv(GIT_NAMESPACE_ENVIRONMENT, cmd + 12, 1);
 			if (envchanged)
 				*envchanged = 1;
@@ -120,7 +120,7 @@
 				*envchanged = 1;
 			(*argv)++;
 			(*argc)--;
-		} else if (!prefixcmp(cmd, "--work-tree=")) {
+		} else if (starts_with(cmd, "--work-tree=")) {
 			setenv(GIT_WORK_TREE_ENVIRONMENT, cmd + 12, 1);
 			if (envchanged)
 				*envchanged = 1;
@@ -566,7 +566,7 @@
 	 * So we just directly call the internal command handler, and
 	 * die if that one cannot handle it.
 	 */
-	if (!prefixcmp(cmd, "git-")) {
+	if (starts_with(cmd, "git-")) {
 		cmd += 4;
 		argv[0] = cmd;
 		handle_internal_command(argc, argv);
@@ -578,7 +578,7 @@
 	argc--;
 	handle_options(&argv, &argc, NULL);
 	if (argc > 0) {
-		if (!prefixcmp(argv[0], "--"))
+		if (starts_with(argv[0], "--"))
 			argv[0] += 2;
 	} else {
 		/* The user didn't specify a command; give them help */
diff --git a/help.c b/help.c
index f068925..df7d16d 100644
--- a/help.c
+++ b/help.c
@@ -148,7 +148,7 @@
 	while ((de = readdir(dir)) != NULL) {
 		int entlen;
 
-		if (prefixcmp(de->d_name, prefix))
+		if (!starts_with(de->d_name, prefix))
 			continue;
 
 		strbuf_setlen(&buf, len);
@@ -255,7 +255,7 @@
 	if (!strcmp(var, "help.autocorrect"))
 		autocorrect = git_config_int(var,value);
 	/* Also use aliases for command lookup */
-	if (!prefixcmp(var, "alias."))
+	if (starts_with(var, "alias."))
 		add_cmdname(&aliases, var + 6, strlen(var + 6));
 
 	return git_default_config(var, value, cb);
@@ -329,7 +329,7 @@
 		if ((n < ARRAY_SIZE(common_cmds)) && !cmp) {
 			/* Yes, this is one of the common commands */
 			n++; /* use the entry from common_cmds[] */
-			if (!prefixcmp(candidate, cmd)) {
+			if (starts_with(candidate, cmd)) {
 				/* Give prefix match a very good score */
 				main_cmds.names[i]->len = 0;
 				continue;
@@ -414,7 +414,7 @@
 	struct similar_ref_cb *cb = (struct similar_ref_cb *)(cb_data);
 	char *branch = strrchr(refname, '/') + 1;
 	/* A remote branch of the same name is deemed similar */
-	if (!prefixcmp(refname, "refs/remotes/") &&
+	if (starts_with(refname, "refs/remotes/") &&
 	    !strcmp(branch, cb->base_ref))
 		string_list_append(cb->similar_refs,
 				   refname + strlen("refs/remotes/"));
diff --git a/http-backend.c b/http-backend.c
index 8c464bd..d2c0a62 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -226,7 +226,7 @@
 		return 0;
 	}
 
-	if (!prefixcmp(var, "http.")) {
+	if (starts_with(var, "http.")) {
 		int i;
 
 		for (i = 0; i < ARRAY_SIZE(rpc_service); i++) {
@@ -247,7 +247,7 @@
 	struct rpc_service *svc = NULL;
 	int i;
 
-	if (prefixcmp(name, "git-"))
+	if (!starts_with(name, "git-"))
 		forbidden("Unsupported service: '%s'", name);
 
 	for (i = 0; i < ARRAY_SIZE(rpc_service); i++) {
diff --git a/http-push.c b/http-push.c
index 34cb70f..d4b40c9 100644
--- a/http-push.c
+++ b/http-push.c
@@ -771,7 +771,7 @@
 			lock->owner = xmalloc(strlen(ctx->cdata) + 1);
 			strcpy(lock->owner, ctx->cdata);
 		} else if (!strcmp(ctx->name, DAV_ACTIVELOCK_TIMEOUT)) {
-			if (!prefixcmp(ctx->cdata, "Second-"))
+			if (starts_with(ctx->cdata, "Second-"))
 				lock->timeout =
 					strtol(ctx->cdata + 7, NULL, 10);
 		} else if (!strcmp(ctx->name, DAV_ACTIVELOCK_TOKEN)) {
@@ -1579,7 +1579,7 @@
 		return;
 
 	/* If it's a symref, set the refname; otherwise try for a sha1 */
-	if (!prefixcmp((char *)buffer.buf, "ref: ")) {
+	if (starts_with((char *)buffer.buf, "ref: ")) {
 		*symref = xmemdupz((char *)buffer.buf + 5, buffer.len - 6);
 	} else {
 		get_sha1_hex(buffer.buf, sha1);
diff --git a/http.c b/http.c
index bcf54aa..e6287b1 100644
--- a/http.c
+++ b/http.c
@@ -460,7 +460,7 @@
 		credential_from_url(&http_auth, url);
 		if (!ssl_cert_password_required &&
 		    getenv("GIT_SSL_CERT_PASSWORD_PROTECTED") &&
-		    !prefixcmp(url, "https://"))
+		    starts_with(url, "https://"))
 			ssl_cert_password_required = 1;
 	}
 
@@ -994,7 +994,7 @@
 	if (!strcmp(asked, got->buf))
 		return 0;
 
-	if (prefixcmp(asked, base->buf))
+	if (!starts_with(asked, base->buf))
 		die("BUG: update_url_from_redirect: %s is not a superset of %s",
 		    asked, base->buf);
 
@@ -1100,7 +1100,7 @@
 		strbuf_rtrim(&buffer);
 		if (buffer.len == 40)
 			ret = get_sha1_hex(buffer.buf, ref->old_sha1);
-		else if (!prefixcmp(buffer.buf, "ref: ")) {
+		else if (starts_with(buffer.buf, "ref: ")) {
 			ref->symref = xstrdup(buffer.buf + 5);
 			ret = 0;
 		}
@@ -1201,8 +1201,8 @@
 		case 'P':
 			i++;
 			if (i + 52 <= buf.len &&
-			    !prefixcmp(data + i, " pack-") &&
-			    !prefixcmp(data + i + 46, ".pack\n")) {
+			    starts_with(data + i, " pack-") &&
+			    starts_with(data + i + 46, ".pack\n")) {
 				get_sha1_hex(data + i + 6, sha1);
 				fetch_and_setup_pack_index(packs_head, sha1,
 						      base_url);
diff --git a/imap-send.c b/imap-send.c
index 6f5cc4f..0bc6f7f 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -1263,7 +1263,7 @@
 	char *p = all_msgs->buf;
 
 	while (1) {
-		if (!prefixcmp(p, "From ")) {
+		if (starts_with(p, "From ")) {
 			p = strstr(p+5, "\nFrom: ");
 			if (!p) break;
 			p = strstr(p+7, "\nDate: ");
@@ -1297,7 +1297,7 @@
 	data = &all_msgs->buf[*ofs];
 	len = all_msgs->len - *ofs;
 
-	if (len < 5 || prefixcmp(data, "From "))
+	if (len < 5 || !starts_with(data, "From "))
 		return 0;
 
 	p = strchr(data, '\n');
@@ -1339,13 +1339,13 @@
 	if (!strcmp("folder", key)) {
 		imap_folder = xstrdup(val);
 	} else if (!strcmp("host", key)) {
-		if (!prefixcmp(val, "imap:"))
+		if (starts_with(val, "imap:"))
 			val += 5;
-		else if (!prefixcmp(val, "imaps:")) {
+		else if (starts_with(val, "imaps:")) {
 			val += 6;
 			server.use_ssl = 1;
 		}
-		if (!prefixcmp(val, "//"))
+		if (starts_with(val, "//"))
 			val += 2;
 		server.host = xstrdup(val);
 	} else if (!strcmp("user", key))
diff --git a/log-tree.c b/log-tree.c
index 8534d91..40ef3ea 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -98,7 +98,7 @@
 	struct object *obj;
 	enum decoration_type type = DECORATION_NONE;
 
-	if (!prefixcmp(refname, "refs/replace/")) {
+	if (starts_with(refname, "refs/replace/")) {
 		unsigned char original_sha1[20];
 		if (!read_replace_refs)
 			return 0;
@@ -116,11 +116,11 @@
 	if (!obj)
 		return 0;
 
-	if (!prefixcmp(refname, "refs/heads/"))
+	if (starts_with(refname, "refs/heads/"))
 		type = DECORATION_REF_LOCAL;
-	else if (!prefixcmp(refname, "refs/remotes/"))
+	else if (starts_with(refname, "refs/remotes/"))
 		type = DECORATION_REF_REMOTE;
-	else if (!prefixcmp(refname, "refs/tags/"))
+	else if (starts_with(refname, "refs/tags/"))
 		type = DECORATION_REF_TAG;
 	else if (!strcmp(refname, "refs/stash"))
 		type = DECORATION_REF_STASH;
diff --git a/merge-recursive.c b/merge-recursive.c
index dbb7104..a18bd15 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -2063,13 +2063,13 @@
 		o->recursive_variant = MERGE_RECURSIVE_THEIRS;
 	else if (!strcmp(s, "subtree"))
 		o->subtree_shift = "";
-	else if (!prefixcmp(s, "subtree="))
+	else if (starts_with(s, "subtree="))
 		o->subtree_shift = s + strlen("subtree=");
 	else if (!strcmp(s, "patience"))
 		o->xdl_opts = DIFF_WITH_ALG(o, PATIENCE_DIFF);
 	else if (!strcmp(s, "histogram"))
 		o->xdl_opts = DIFF_WITH_ALG(o, HISTOGRAM_DIFF);
-	else if (!prefixcmp(s, "diff-algorithm=")) {
+	else if (starts_with(s, "diff-algorithm=")) {
 		long value = parse_algorithm_value(s + strlen("diff-algorithm="));
 		if (value < 0)
 			return -1;
@@ -2088,7 +2088,7 @@
 		o->renormalize = 1;
 	else if (!strcmp(s, "no-renormalize"))
 		o->renormalize = 0;
-	else if (!prefixcmp(s, "rename-threshold=")) {
+	else if (starts_with(s, "rename-threshold=")) {
 		const char *score = s + strlen("rename-threshold=");
 		if ((o->rename_score = parse_rename_score(&score)) == -1 || *score != 0)
 			return -1;
diff --git a/notes-utils.c b/notes-utils.c
index 9107c37..db43900 100644
--- a/notes-utils.c
+++ b/notes-utils.c
@@ -70,7 +70,7 @@
 static int notes_rewrite_config(const char *k, const char *v, void *cb)
 {
 	struct notes_rewrite_cfg *c = cb;
-	if (!prefixcmp(k, "notes.rewrite.") && !strcmp(k+14, c->cmd)) {
+	if (starts_with(k, "notes.rewrite.") && !strcmp(k+14, c->cmd)) {
 		c->enabled = git_config_bool(k, v);
 		return 0;
 	} else if (!c->mode_from_env && !strcmp(k, "notes.rewritemode")) {
@@ -85,7 +85,7 @@
 	} else if (!c->refs_from_env && !strcmp(k, "notes.rewriteref")) {
 		/* note that a refs/ prefix is implied in the
 		 * underlying for_each_glob_ref */
-		if (!prefixcmp(v, "refs/notes/"))
+		if (starts_with(v, "refs/notes/"))
 			string_list_add_refs_by_glob(c->refs, v);
 		else
 			warning(_("Refusing to rewrite notes in %s"
diff --git a/notes.c b/notes.c
index b69c0b8..5f07c0b 100644
--- a/notes.c
+++ b/notes.c
@@ -1243,9 +1243,9 @@
 		if (!ref || !strcmp(ref, GIT_NOTES_DEFAULT_REF)) {
 			strbuf_addstr(sb, "\nNotes:\n");
 		} else {
-			if (!prefixcmp(ref, "refs/"))
+			if (starts_with(ref, "refs/"))
 				ref += 5;
-			if (!prefixcmp(ref, "notes/"))
+			if (starts_with(ref, "notes/"))
 				ref += 6;
 			strbuf_addf(sb, "\nNotes (%s):\n", ref);
 		}
@@ -1293,9 +1293,9 @@
 
 void expand_notes_ref(struct strbuf *sb)
 {
-	if (!prefixcmp(sb->buf, "refs/notes/"))
+	if (starts_with(sb->buf, "refs/notes/"))
 		return; /* we're happy */
-	else if (!prefixcmp(sb->buf, "notes/"))
+	else if (starts_with(sb->buf, "notes/"))
 		strbuf_insert(sb, 0, "refs/", 5);
 	else
 		strbuf_insert(sb, 0, "refs/notes/", 11);
diff --git a/pager.c b/pager.c
index fa19765..345b0bc 100644
--- a/pager.c
+++ b/pager.c
@@ -151,7 +151,7 @@
 static int pager_command_config(const char *var, const char *value, void *data)
 {
 	struct pager_config *c = data;
-	if (!prefixcmp(var, "pager.") && !strcmp(var + 6, c->cmd)) {
+	if (starts_with(var, "pager.") && !strcmp(var + 6, c->cmd)) {
 		int b = git_config_maybe_bool(var, value);
 		if (b >= 0)
 			c->want = b;
diff --git a/parse-options.c b/parse-options.c
index 62e9b1c..7b8d3fa 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -273,13 +273,13 @@
 			if (options->flags & PARSE_OPT_NONEG)
 				continue;
 			/* negated and abbreviated very much? */
-			if (!prefixcmp("no-", arg)) {
+			if (starts_with("no-", arg)) {
 				flags |= OPT_UNSET;
 				goto is_abbreviated;
 			}
 			/* negated? */
-			if (prefixcmp(arg, "no-")) {
-				if (!prefixcmp(long_name, "no-")) {
+			if (!starts_with(arg, "no-")) {
+				if (starts_with(long_name, "no-")) {
 					long_name += 3;
 					opt_flags |= OPT_UNSET;
 					goto again;
@@ -289,7 +289,7 @@
 			flags |= OPT_UNSET;
 			rest = skip_prefix(arg + 3, long_name);
 			/* abbreviated and negated? */
-			if (!rest && !prefixcmp(long_name, arg + 3))
+			if (!rest && starts_with(long_name, arg + 3))
 				goto is_abbreviated;
 			if (!rest)
 				continue;
@@ -334,7 +334,7 @@
 	if (strlen(arg) < 3)
 		return;
 
-	if (!prefixcmp(arg, "no-")) {
+	if (starts_with(arg, "no-")) {
 		error ("did you mean `--%s` (with two dashes ?)", arg);
 		exit(129);
 	}
@@ -342,7 +342,7 @@
 	for (; options->type != OPTION_END; options++) {
 		if (!options->long_name)
 			continue;
-		if (!prefixcmp(options->long_name, arg)) {
+		if (starts_with(options->long_name, arg)) {
 			error ("did you mean `--%s` (with two dashes ?)", arg);
 			exit(129);
 		}
diff --git a/pathspec.c b/pathspec.c
index 4cf2bd3..4a7893e 100644
--- a/pathspec.c
+++ b/pathspec.c
@@ -154,7 +154,7 @@
 					magic |= pathspec_magic[i].bit;
 					break;
 				}
-				if (!prefixcmp(copyfrom, "prefix:")) {
+				if (starts_with(copyfrom, "prefix:")) {
 					char *endptr;
 					pathspec_prefix = strtol(copyfrom + 7,
 								 &endptr, 10);
diff --git a/pkt-line.c b/pkt-line.c
index 70f1950..bc63b3b 100644
--- a/pkt-line.c
+++ b/pkt-line.c
@@ -24,8 +24,8 @@
 	strbuf_addf(&out, "packet: %12s%c ",
 		    packet_trace_prefix, write ? '>' : '<');
 
-	if ((len >= 4 && !prefixcmp(buf, "PACK")) ||
-	    (len >= 5 && !prefixcmp(buf+1, "PACK"))) {
+	if ((len >= 4 && starts_with(buf, "PACK")) ||
+	    (len >= 5 && starts_with(buf+1, "PACK"))) {
 		strbuf_addstr(&out, "PACK ...");
 		unsetenv(trace_key);
 	}
diff --git a/pretty.c b/pretty.c
index 962e82b..87db08b 100644
--- a/pretty.c
+++ b/pretty.c
@@ -40,7 +40,7 @@
 	const char *fmt;
 	int i;
 
-	if (prefixcmp(var, "pretty."))
+	if (!starts_with(var, "pretty."))
 		return 0;
 
 	name = var + strlen("pretty.");
@@ -67,7 +67,7 @@
 	commit_format->name = xstrdup(name);
 	commit_format->format = CMIT_FMT_USERFORMAT;
 	git_config_string(&fmt, var, value);
-	if (!prefixcmp(fmt, "format:") || !prefixcmp(fmt, "tformat:")) {
+	if (starts_with(fmt, "format:") || starts_with(fmt, "tformat:")) {
 		commit_format->is_tformat = fmt[0] == 't';
 		fmt = strchr(fmt, ':') + 1;
 	} else if (strchr(fmt, '%'))
@@ -115,7 +115,7 @@
 	for (i = 0; i < commit_formats_len; i++) {
 		size_t match_len;
 
-		if (prefixcmp(commit_formats[i].name, sought))
+		if (!starts_with(commit_formats[i].name, sought))
 			continue;
 
 		match_len = strlen(commit_formats[i].name);
@@ -151,7 +151,7 @@
 		rev->commit_format = CMIT_FMT_DEFAULT;
 		return;
 	}
-	if (!prefixcmp(arg, "format:") || !prefixcmp(arg, "tformat:")) {
+	if (starts_with(arg, "format:") || starts_with(arg, "tformat:")) {
 		save_user_format(rev, strchr(arg, ':') + 1, arg[0] == 't');
 		return;
 	}
@@ -840,10 +840,10 @@
 
 		if (i == eol) {
 			break;
-		} else if (!prefixcmp(msg + i, "author ")) {
+		} else if (starts_with(msg + i, "author ")) {
 			context->author.off = i + 7;
 			context->author.len = eol - i - 7;
-		} else if (!prefixcmp(msg + i, "committer ")) {
+		} else if (starts_with(msg + i, "committer ")) {
 			context->committer.off = i + 10;
 			context->committer.len = eol - i - 10;
 		}
@@ -983,7 +983,7 @@
 
 		if (!end)
 			return 0;
-		if (!prefixcmp(begin, "auto,")) {
+		if (starts_with(begin, "auto,")) {
 			if (!want_color(c->pretty_ctx->color))
 				return end - placeholder + 1;
 			begin += 5;
@@ -994,16 +994,16 @@
 		strbuf_addstr(sb, color);
 		return end - placeholder + 1;
 	}
-	if (!prefixcmp(placeholder + 1, "red")) {
+	if (starts_with(placeholder + 1, "red")) {
 		strbuf_addstr(sb, GIT_COLOR_RED);
 		return 4;
-	} else if (!prefixcmp(placeholder + 1, "green")) {
+	} else if (starts_with(placeholder + 1, "green")) {
 		strbuf_addstr(sb, GIT_COLOR_GREEN);
 		return 6;
-	} else if (!prefixcmp(placeholder + 1, "blue")) {
+	} else if (starts_with(placeholder + 1, "blue")) {
 		strbuf_addstr(sb, GIT_COLOR_BLUE);
 		return 5;
-	} else if (!prefixcmp(placeholder + 1, "reset")) {
+	} else if (starts_with(placeholder + 1, "reset")) {
 		strbuf_addstr(sb, GIT_COLOR_RESET);
 		return 6;
 	} else
@@ -1060,11 +1060,11 @@
 			end = strchr(start, ')');
 			if (!end || end == start)
 				return 0;
-			if (!prefixcmp(start, "trunc)"))
+			if (starts_with(start, "trunc)"))
 				c->truncate = trunc_right;
-			else if (!prefixcmp(start, "ltrunc)"))
+			else if (starts_with(start, "ltrunc)"))
 				c->truncate = trunc_left;
-			else if (!prefixcmp(start, "mtrunc)"))
+			else if (starts_with(start, "mtrunc)"))
 				c->truncate = trunc_middle;
 			else
 				return 0;
@@ -1089,7 +1089,7 @@
 	/* these are independent of the commit */
 	switch (placeholder[0]) {
 	case 'C':
-		if (!prefixcmp(placeholder + 1, "(auto)")) {
+		if (starts_with(placeholder + 1, "(auto)")) {
 			c->auto_color = 1;
 			return 7; /* consumed 7 bytes, "C(auto)" */
 		} else {
@@ -1556,7 +1556,7 @@
 			continue;
 		}
 
-		if (!prefixcmp(line, "parent ")) {
+		if (starts_with(line, "parent ")) {
 			if (linelen != 48)
 				die("bad parent line in commit");
 			continue;
@@ -1580,11 +1580,11 @@
 		 * FULL shows both authors but not dates.
 		 * FULLER shows both authors and dates.
 		 */
-		if (!prefixcmp(line, "author ")) {
+		if (starts_with(line, "author ")) {
 			strbuf_grow(sb, linelen + 80);
 			pp_user_info(pp, "Author", sb, line + 7, encoding);
 		}
-		if (!prefixcmp(line, "committer ") &&
+		if (starts_with(line, "committer ") &&
 		    (pp->fmt == CMIT_FMT_FULL || pp->fmt == CMIT_FMT_FULLER)) {
 			strbuf_grow(sb, linelen + 80);
 			pp_user_info(pp, "Commit", sb, line + 10, encoding);
diff --git a/refs.c b/refs.c
index 5e5a382..3926136 100644
--- a/refs.c
+++ b/refs.c
@@ -637,7 +637,7 @@
 	struct ref_entry *old_current_ref;
 	int retval;
 
-	if (prefixcmp(entry->name, data->base))
+	if (!starts_with(entry->name, data->base))
 		return 0;
 
 	if (!(data->flags & DO_FOR_EACH_INCLUDE_BROKEN) &&
@@ -1042,7 +1042,7 @@
 		if (refname) {
 			last = create_ref_entry(refname, sha1, REF_ISPACKED, 1);
 			if (peeled == PEELED_FULLY ||
-			    (peeled == PEELED_TAGS && !prefixcmp(refname, "refs/tags/")))
+			    (peeled == PEELED_TAGS && starts_with(refname, "refs/tags/")))
 				last->flag |= REF_KNOWS_PEELED;
 			add_ref(dir, last);
 			continue;
@@ -1376,7 +1376,7 @@
 					return NULL;
 			}
 			buffer[len] = 0;
-			if (!prefixcmp(buffer, "refs/") &&
+			if (starts_with(buffer, "refs/") &&
 					!check_refname_format(buffer, 0)) {
 				strcpy(refname_buffer, buffer);
 				refname = refname_buffer;
@@ -1415,7 +1415,7 @@
 		/*
 		 * Is it a symbolic ref?
 		 */
-		if (prefixcmp(buffer, "ref:")) {
+		if (!starts_with(buffer, "ref:")) {
 			/*
 			 * Please note that FETCH_HEAD has a second
 			 * line containing other data.
@@ -1837,7 +1837,7 @@
 	struct ref_filter filter;
 	int ret;
 
-	if (!prefix && prefixcmp(pattern, "refs/"))
+	if (!prefix && !starts_with(pattern, "refs/"))
 		strbuf_addstr(&real_pattern, "refs/");
 	else if (prefix)
 		strbuf_addstr(&real_pattern, prefix);
@@ -1874,9 +1874,9 @@
 const char *prettify_refname(const char *name)
 {
 	return name + (
-		!prefixcmp(name, "refs/heads/") ? 11 :
-		!prefixcmp(name, "refs/tags/") ? 10 :
-		!prefixcmp(name, "refs/remotes/") ? 13 :
+		starts_with(name, "refs/heads/") ? 11 :
+		starts_with(name, "refs/tags/") ? 10 :
+		starts_with(name, "refs/remotes/") ? 13 :
 		0);
 }
 
@@ -2244,7 +2244,7 @@
 	struct pack_refs_cb_data *cb = cb_data;
 	enum peel_status peel_status;
 	struct ref_entry *packed_entry;
-	int is_tag_ref = !prefixcmp(entry->name, "refs/tags/");
+	int is_tag_ref = starts_with(entry->name, "refs/tags/");
 
 	/* ALWAYS pack tags */
 	if (!(cb->flags & PACK_REFS_ALL) && !is_tag_ref)
@@ -2679,9 +2679,9 @@
 
 	git_snpath(logfile, bufsize, "logs/%s", refname);
 	if (log_all_ref_updates &&
-	    (!prefixcmp(refname, "refs/heads/") ||
-	     !prefixcmp(refname, "refs/remotes/") ||
-	     !prefixcmp(refname, "refs/notes/") ||
+	    (starts_with(refname, "refs/heads/") ||
+	     starts_with(refname, "refs/remotes/") ||
+	     starts_with(refname, "refs/notes/") ||
 	     !strcmp(refname, "HEAD"))) {
 		if (safe_create_leading_directories(logfile) < 0)
 			return error("unable to create directory for %s",
@@ -2751,7 +2751,7 @@
 
 static int is_branch(const char *refname)
 {
-	return !strcmp(refname, "HEAD") || !prefixcmp(refname, "refs/heads/");
+	return !strcmp(refname, "HEAD") || starts_with(refname, "refs/heads/");
 }
 
 int write_ref_sha1(struct ref_lock *lock,
@@ -3450,7 +3450,7 @@
 {
 	if (!strcmp("transfer.hiderefs", var) ||
 	    /* NEEDSWORK: use parse_config_key() once both are merged */
-	    (!prefixcmp(var, section) && var[strlen(section)] == '.' &&
+	    (starts_with(var, section) && var[strlen(section)] == '.' &&
 	     !strcmp(var + strlen(section), ".hiderefs"))) {
 		char *ref;
 		int len;
@@ -3478,7 +3478,7 @@
 		return 0;
 	for_each_string_list_item(item, hide_refs) {
 		int len;
-		if (prefixcmp(refname, item->string))
+		if (!starts_with(refname, item->string))
 			continue;
 		len = strlen(item->string);
 		if (!refname[len] || refname[len] == '/')
diff --git a/remote-curl.c b/remote-curl.c
index c9b891a..65c403d 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -217,7 +217,7 @@
 	free_discovery(last);
 
 	strbuf_addf(&refs_url, "%sinfo/refs", url.buf);
-	if ((!prefixcmp(url.buf, "http://") || !prefixcmp(url.buf, "https://")) &&
+	if ((starts_with(url.buf, "http://") || starts_with(url.buf, "https://")) &&
 	     git_env_bool("GIT_SMART_HTTP", 1)) {
 		maybe_smart = 1;
 		if (!strchr(url.buf, '?'))
@@ -755,7 +755,7 @@
 	int alloc_heads = 0, nr_heads = 0;
 
 	do {
-		if (!prefixcmp(buf->buf, "fetch ")) {
+		if (starts_with(buf->buf, "fetch ")) {
 			char *p = buf->buf + strlen("fetch ");
 			char *name;
 			struct ref *ref;
@@ -878,7 +878,7 @@
 	int alloc_spec = 0, nr_spec = 0, i, ret;
 
 	do {
-		if (!prefixcmp(buf->buf, "push ")) {
+		if (starts_with(buf->buf, "push ")) {
 			ALLOC_GROW(specs, nr_spec + 1, alloc_spec);
 			specs[nr_spec++] = xstrdup(buf->buf + 5);
 		}
@@ -941,19 +941,19 @@
 		}
 		if (buf.len == 0)
 			break;
-		if (!prefixcmp(buf.buf, "fetch ")) {
+		if (starts_with(buf.buf, "fetch ")) {
 			if (nongit)
 				die("Fetch attempted without a local repo");
 			parse_fetch(&buf);
 
-		} else if (!strcmp(buf.buf, "list") || !prefixcmp(buf.buf, "list ")) {
+		} else if (!strcmp(buf.buf, "list") || starts_with(buf.buf, "list ")) {
 			int for_push = !!strstr(buf.buf + 4, "for-push");
 			output_refs(get_refs(for_push));
 
-		} else if (!prefixcmp(buf.buf, "push ")) {
+		} else if (starts_with(buf.buf, "push ")) {
 			parse_push(&buf);
 
-		} else if (!prefixcmp(buf.buf, "option ")) {
+		} else if (starts_with(buf.buf, "option ")) {
 			char *name = buf.buf + strlen("option ");
 			char *value = strchr(name, ' ');
 			int result;
diff --git a/remote-testsvn.c b/remote-testsvn.c
index d7cd5d2..078f1ff 100644
--- a/remote-testsvn.c
+++ b/remote-testsvn.c
@@ -82,7 +82,7 @@
 		len = end ? end - msg : strlen(msg);
 
 		key = "Revision-number: ";
-		if (!prefixcmp(msg, key)) {
+		if (starts_with(msg, key)) {
 			long i;
 			char *end;
 			value = msg + strlen(key);
@@ -154,7 +154,7 @@
 	} else {
 		strbuf_addf(&sb, ":%d ", latestrev);
 		while (strbuf_getline(&line, marksfile, '\n') != EOF) {
-			if (!prefixcmp(line.buf, sb.buf)) {
+			if (starts_with(line.buf, sb.buf)) {
 				found++;
 				break;
 			}
@@ -264,7 +264,7 @@
 		return 1;	/* end of command stream, quit */
 	}
 	if (batch_cmd) {
-		if (prefixcmp(batch_cmd->name, line->buf))
+		if (!starts_with(batch_cmd->name, line->buf))
 			die("Active %s batch interrupted by %s", batch_cmd->name, line->buf);
 		/* buffer batch lines */
 		string_list_append(&batchlines, line->buf);
@@ -272,7 +272,7 @@
 	}
 
 	for (p = input_command_list; p->name; p++) {
-		if (!prefixcmp(line->buf, p->name) && (strlen(p->name) == line->len ||
+		if (starts_with(line->buf, p->name) && (strlen(p->name) == line->len ||
 				line->buf[strlen(p->name)] == ' ')) {
 			if (p->batchable) {
 				batch_cmd = p;
@@ -304,7 +304,7 @@
 	remote = remote_get(argv[1]);
 	url_in = (argc == 3) ? argv[2] : remote->url[0];
 
-	if (!prefixcmp(url_in, "file://")) {
+	if (starts_with(url_in, "file://")) {
 		dump_from_file = 1;
 		url = url_decode(url_in + sizeof("file://")-1);
 	} else {
diff --git a/remote.c b/remote.c
index 9f1a8aa..01aa4b4 100644
--- a/remote.c
+++ b/remote.c
@@ -76,7 +76,7 @@
 		if (!r->rewrite[i])
 			continue;
 		for (j = 0; j < r->rewrite[i]->instead_of_nr; j++) {
-			if (!prefixcmp(url, r->rewrite[i]->instead_of[j].s) &&
+			if (starts_with(url, r->rewrite[i]->instead_of[j].s) &&
 			    (!longest ||
 			     longest->len < r->rewrite[i]->instead_of[j].len)) {
 				longest = &(r->rewrite[i]->instead_of[j]);
@@ -239,13 +239,13 @@
 		int value_list;
 		char *s, *p;
 
-		if (!prefixcmp(buffer, "URL:")) {
+		if (starts_with(buffer, "URL:")) {
 			value_list = 0;
 			s = buffer + 4;
-		} else if (!prefixcmp(buffer, "Push:")) {
+		} else if (starts_with(buffer, "Push:")) {
 			value_list = 1;
 			s = buffer + 5;
-		} else if (!prefixcmp(buffer, "Pull:")) {
+		} else if (starts_with(buffer, "Pull:")) {
 			value_list = 2;
 			s = buffer + 5;
 		} else
@@ -337,7 +337,7 @@
 	const char *subkey;
 	struct remote *remote;
 	struct branch *branch;
-	if (!prefixcmp(key, "branch.")) {
+	if (starts_with(key, "branch.")) {
 		name = key + 7;
 		subkey = strrchr(name, '.');
 		if (!subkey)
@@ -361,7 +361,7 @@
 		}
 		return 0;
 	}
-	if (!prefixcmp(key, "url.")) {
+	if (starts_with(key, "url.")) {
 		struct rewrite *rewrite;
 		name = key + 4;
 		subkey = strrchr(name, '.');
@@ -380,7 +380,7 @@
 		}
 	}
 
-	if (prefixcmp(key,  "remote."))
+	if (!starts_with(key,  "remote."))
 		return 0;
 	name = key + 7;
 
@@ -487,7 +487,7 @@
 	current_branch = NULL;
 	head_ref = resolve_ref_unsafe("HEAD", sha1, 0, &flag);
 	if (head_ref && (flag & REF_ISSYMREF) &&
-	    !prefixcmp(head_ref, "refs/heads/")) {
+	    starts_with(head_ref, "refs/heads/")) {
 		current_branch =
 			make_branch(head_ref + strlen("refs/heads/"), 0);
 	}
@@ -982,8 +982,8 @@
 		 */
 		if (namelen != patlen &&
 		    patlen != namelen - 5 &&
-		    prefixcmp(name, "refs/heads/") &&
-		    prefixcmp(name, "refs/tags/")) {
+		    !starts_with(name, "refs/heads/") &&
+		    !starts_with(name, "refs/tags/")) {
 			/* We want to catch the case where only weak
 			 * matches are found and there are multiple
 			 * matches, and where more than one strong
@@ -1054,9 +1054,9 @@
 	if (!r)
 		return NULL;
 
-	if (!prefixcmp(r, "refs/heads/"))
+	if (starts_with(r, "refs/heads/"))
 		strbuf_addstr(&buf, "refs/heads/");
-	else if (!prefixcmp(r, "refs/tags/"))
+	else if (starts_with(r, "refs/tags/"))
 		strbuf_addstr(&buf, "refs/tags/");
 	else
 		return NULL;
@@ -1104,7 +1104,7 @@
 		dst_value = resolve_ref_unsafe(matched_src->name, sha1, 1, &flag);
 		if (!dst_value ||
 		    ((flag & REF_ISSYMREF) &&
-		     prefixcmp(dst_value, "refs/heads/")))
+		     !starts_with(dst_value, "refs/heads/")))
 			die("%s cannot be resolved to branch.",
 			    matched_src->name);
 	}
@@ -1193,7 +1193,7 @@
 		 * including refs outside refs/heads/ hierarchy, but
 		 * that does not make much sense these days.
 		 */
-		if (!send_mirror && prefixcmp(ref->name, "refs/heads/"))
+		if (!send_mirror && !starts_with(ref->name, "refs/heads/"))
 			return NULL;
 		name = xstrdup(ref->name);
 	}
@@ -1248,7 +1248,7 @@
 			add_to_tips(&sent_tips, ref->peer_ref->new_sha1);
 		else
 			add_to_tips(&sent_tips, ref->old_sha1);
-		if (!prefixcmp(ref->name, "refs/tags/"))
+		if (starts_with(ref->name, "refs/tags/"))
 			string_list_append(&dst_tag, ref->name);
 	}
 	clear_commit_marks_many(sent_tips.nr, sent_tips.tip, TMP_MARK);
@@ -1257,7 +1257,7 @@
 
 	/* Collect tags they do not have. */
 	for (ref = src; ref; ref = ref->next) {
-		if (prefixcmp(ref->name, "refs/tags/"))
+		if (!starts_with(ref->name, "refs/tags/"))
 			continue; /* not a tag */
 		if (string_list_has_string(&dst_tag, ref->name))
 			continue; /* they already have it */
@@ -1481,7 +1481,7 @@
 		 */
 
 		else if (!ref->deletion && !is_null_sha1(ref->old_sha1)) {
-			if (!prefixcmp(ref->name, "refs/tags/"))
+			if (starts_with(ref->name, "refs/tags/"))
 				reject_reason = REF_STATUS_REJECT_ALREADY_EXISTS;
 			else if (!has_sha1_file(ref->old_sha1))
 				reject_reason = REF_STATUS_REJECT_FETCH_FIRST;
@@ -1607,12 +1607,12 @@
 	if (!name || name[0] == '\0')
 		return NULL;
 
-	if (!prefixcmp(name, "refs/"))
+	if (starts_with(name, "refs/"))
 		return alloc_ref(name);
 
-	if (!prefixcmp(name, "heads/") ||
-	    !prefixcmp(name, "tags/") ||
-	    !prefixcmp(name, "remotes/"))
+	if (starts_with(name, "heads/") ||
+	    starts_with(name, "tags/") ||
+	    starts_with(name, "remotes/"))
 		return alloc_ref_with_prefix("refs/", 5, name);
 
 	return alloc_ref_with_prefix("refs/heads/", 11, name);
@@ -1647,7 +1647,7 @@
 
 	for (rmp = &ref_map; *rmp; ) {
 		if ((*rmp)->peer_ref) {
-			if (prefixcmp((*rmp)->peer_ref->name, "refs/") ||
+			if (!starts_with((*rmp)->peer_ref->name, "refs/") ||
 			    check_refname_format((*rmp)->peer_ref->name, 0)) {
 				struct ref *ignore = *rmp;
 				error("* Ignoring funny ref '%s' locally",
@@ -1931,7 +1931,7 @@
 	/* Look for another ref that points there */
 	for (r = refs; r; r = r->next) {
 		if (r != head &&
-		    !prefixcmp(r->name, "refs/heads/") &&
+		    starts_with(r->name, "refs/heads/") &&
 		    !hashcmp(r->old_sha1, head->old_sha1)) {
 			*tail = copy_ref(r);
 			tail = &((*tail)->next);
diff --git a/revision.c b/revision.c
index a8adb3f..10854b0 100644
--- a/revision.c
+++ b/revision.c
@@ -1592,9 +1592,9 @@
 	    !strcmp(arg, "--tags") || !strcmp(arg, "--remotes") ||
 	    !strcmp(arg, "--reflog") || !strcmp(arg, "--not") ||
 	    !strcmp(arg, "--no-walk") || !strcmp(arg, "--do-walk") ||
-	    !strcmp(arg, "--bisect") || !prefixcmp(arg, "--glob=") ||
-	    !prefixcmp(arg, "--branches=") || !prefixcmp(arg, "--tags=") ||
-	    !prefixcmp(arg, "--remotes=") || !prefixcmp(arg, "--no-walk="))
+	    !strcmp(arg, "--bisect") || starts_with(arg, "--glob=") ||
+	    starts_with(arg, "--branches=") || starts_with(arg, "--tags=") ||
+	    starts_with(arg, "--remotes=") || starts_with(arg, "--no-walk="))
 	{
 		unkv[(*unkc)++] = arg;
 		return 1;
@@ -1617,7 +1617,7 @@
 		revs->max_count = atoi(argv[1]);
 		revs->no_walk = 0;
 		return 2;
-	} else if (!prefixcmp(arg, "-n")) {
+	} else if (starts_with(arg, "-n")) {
 		revs->max_count = atoi(arg + 2);
 		revs->no_walk = 0;
 	} else if ((argcount = parse_long_opt("max-age", argv, &optarg))) {
@@ -1677,7 +1677,7 @@
 	} else if (!strcmp(arg, "--author-date-order")) {
 		revs->sort_order = REV_SORT_BY_AUTHOR_DATE;
 		revs->topo_order = 1;
-	} else if (!prefixcmp(arg, "--early-output")) {
+	} else if (starts_with(arg, "--early-output")) {
 		int count = 100;
 		switch (arg[14]) {
 		case '=':
@@ -1702,13 +1702,13 @@
 		revs->min_parents = 2;
 	} else if (!strcmp(arg, "--no-merges")) {
 		revs->max_parents = 1;
-	} else if (!prefixcmp(arg, "--min-parents=")) {
+	} else if (starts_with(arg, "--min-parents=")) {
 		revs->min_parents = atoi(arg+14);
-	} else if (!prefixcmp(arg, "--no-min-parents")) {
+	} else if (starts_with(arg, "--no-min-parents")) {
 		revs->min_parents = 0;
-	} else if (!prefixcmp(arg, "--max-parents=")) {
+	} else if (starts_with(arg, "--max-parents=")) {
 		revs->max_parents = atoi(arg+14);
-	} else if (!prefixcmp(arg, "--no-max-parents")) {
+	} else if (starts_with(arg, "--no-max-parents")) {
 		revs->max_parents = -1;
 	} else if (!strcmp(arg, "--boundary")) {
 		revs->boundary = 1;
@@ -1758,7 +1758,7 @@
 		revs->verify_objects = 1;
 	} else if (!strcmp(arg, "--unpacked")) {
 		revs->unpacked = 1;
-	} else if (!prefixcmp(arg, "--unpacked=")) {
+	} else if (starts_with(arg, "--unpacked=")) {
 		die("--unpacked=<packfile> no longer supported.");
 	} else if (!strcmp(arg, "-r")) {
 		revs->diff = 1;
@@ -1783,7 +1783,7 @@
 		revs->verbose_header = 1;
 		revs->pretty_given = 1;
 		get_commit_format(arg+8, revs);
-	} else if (!prefixcmp(arg, "--pretty=") || !prefixcmp(arg, "--format=")) {
+	} else if (starts_with(arg, "--pretty=") || starts_with(arg, "--format=")) {
 		/*
 		 * Detached form ("--pretty X" as opposed to "--pretty=X")
 		 * not allowed, since the argument is optional.
@@ -1797,12 +1797,12 @@
 		revs->notes_opt.use_default_notes = 1;
 	} else if (!strcmp(arg, "--show-signature")) {
 		revs->show_signature = 1;
-	} else if (!prefixcmp(arg, "--show-notes=") ||
-		   !prefixcmp(arg, "--notes=")) {
+	} else if (starts_with(arg, "--show-notes=") ||
+		   starts_with(arg, "--notes=")) {
 		struct strbuf buf = STRBUF_INIT;
 		revs->show_notes = 1;
 		revs->show_notes_given = 1;
-		if (!prefixcmp(arg, "--show-notes")) {
+		if (starts_with(arg, "--show-notes")) {
 			if (revs->notes_opt.use_default_notes < 0)
 				revs->notes_opt.use_default_notes = 1;
 			strbuf_addstr(&buf, arg+13);
@@ -1845,7 +1845,7 @@
 		revs->abbrev = 0;
 	} else if (!strcmp(arg, "--abbrev")) {
 		revs->abbrev = DEFAULT_ABBREV;
-	} else if (!prefixcmp(arg, "--abbrev=")) {
+	} else if (starts_with(arg, "--abbrev=")) {
 		revs->abbrev = strtoul(arg + 9, NULL, 10);
 		if (revs->abbrev < MINIMUM_ABBREV)
 			revs->abbrev = MINIMUM_ABBREV;
@@ -1984,15 +1984,15 @@
 		init_all_refs_cb(&cb, revs, *flags);
 		for_each_glob_ref(handle_one_ref, optarg, &cb);
 		return argcount;
-	} else if (!prefixcmp(arg, "--branches=")) {
+	} else if (starts_with(arg, "--branches=")) {
 		struct all_refs_cb cb;
 		init_all_refs_cb(&cb, revs, *flags);
 		for_each_glob_ref_in(handle_one_ref, arg + 11, "refs/heads/", &cb);
-	} else if (!prefixcmp(arg, "--tags=")) {
+	} else if (starts_with(arg, "--tags=")) {
 		struct all_refs_cb cb;
 		init_all_refs_cb(&cb, revs, *flags);
 		for_each_glob_ref_in(handle_one_ref, arg + 7, "refs/tags/", &cb);
-	} else if (!prefixcmp(arg, "--remotes=")) {
+	} else if (starts_with(arg, "--remotes=")) {
 		struct all_refs_cb cb;
 		init_all_refs_cb(&cb, revs, *flags);
 		for_each_glob_ref_in(handle_one_ref, arg + 10, "refs/remotes/", &cb);
@@ -2002,7 +2002,7 @@
 		*flags ^= UNINTERESTING | BOTTOM;
 	} else if (!strcmp(arg, "--no-walk")) {
 		revs->no_walk = REVISION_WALK_NO_WALK_SORTED;
-	} else if (!prefixcmp(arg, "--no-walk=")) {
+	} else if (starts_with(arg, "--no-walk=")) {
 		/*
 		 * Detached form ("--no-walk X" as opposed to "--no-walk=X")
 		 * not allowed, since the argument is optional.
diff --git a/send-pack.c b/send-pack.c
index fab62e3..142f211 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -109,7 +109,7 @@
 	struct ref *hint;
 	int ret = 0;
 	char *line = packet_read_line(in, NULL);
-	if (prefixcmp(line, "unpack "))
+	if (!starts_with(line, "unpack "))
 		return error("did not receive remote status");
 	if (strcmp(line, "unpack ok")) {
 		error("unpack failed: %s", line + 7);
@@ -122,7 +122,7 @@
 		line = packet_read_line(in, NULL);
 		if (!line)
 			break;
-		if (prefixcmp(line, "ok ") && prefixcmp(line, "ng ")) {
+		if (!starts_with(line, "ok ") && !starts_with(line, "ng ")) {
 			error("invalid ref status from remote: %s", line);
 			ret = -1;
 			break;
diff --git a/sequencer.c b/sequencer.c
index 06e52b4..90cac7b 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -41,7 +41,7 @@
 	 * We only care that it looks roughly like (cherry picked from ...)
 	 */
 	return len > strlen(cherry_picked_prefix) + 1 &&
-		!prefixcmp(buf, cherry_picked_prefix) && buf[len - 1] == ')';
+		starts_with(buf, cherry_picked_prefix) && buf[len - 1] == ')';
 }
 
 /*
@@ -180,7 +180,7 @@
 	while (*p && *p != '\n') {
 		for (eol = p + 1; *eol && *eol != '\n'; eol++)
 			; /* do nothing */
-		if (!prefixcmp(p, "encoding ")) {
+		if (starts_with(p, "encoding ")) {
 			char *result = xmalloc(eol - 8 - p);
 			strlcpy(result, p + 9, eol - 8 - p);
 			return result;
@@ -705,10 +705,10 @@
 	char *end_of_object_name;
 	int saved, status, padding;
 
-	if (!prefixcmp(bol, "pick")) {
+	if (starts_with(bol, "pick")) {
 		action = REPLAY_PICK;
 		bol += strlen("pick");
-	} else if (!prefixcmp(bol, "revert")) {
+	} else if (starts_with(bol, "revert")) {
 		action = REPLAY_REVERT;
 		bol += strlen("revert");
 	} else
diff --git a/setup.c b/setup.c
index 5432a31..6c3f85f 100644
--- a/setup.c
+++ b/setup.c
@@ -82,7 +82,7 @@
 	const char *name;
 	struct stat st;
 
-	if (!prefixcmp(arg, ":/")) {
+	if (starts_with(arg, ":/")) {
 		if (arg[2] == '\0') /* ":/" is root dir, always exists */
 			return 1;
 		name = arg + 2;
@@ -304,7 +304,7 @@
 	if (len != st.st_size)
 		die("Error reading %s", path);
 	buf[len] = '\0';
-	if (prefixcmp(buf, "gitdir: "))
+	if (!starts_with(buf, "gitdir: "))
 		die("Invalid gitfile format: %s", path);
 	while (buf[len - 1] == '\n' || buf[len - 1] == '\r')
 		len--;
diff --git a/sha1_name.c b/sha1_name.c
index e9c2999..047477a 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -546,7 +546,7 @@
 		if (read_ref_at(real_ref, at_time, nth, sha1, NULL,
 				&co_time, &co_tz, &co_cnt)) {
 			if (!len) {
-				if (!prefixcmp(real_ref, "refs/heads/")) {
+				if (starts_with(real_ref, "refs/heads/")) {
 					str = real_ref + 11;
 					len = strlen(real_ref + 11);
 				} else {
@@ -676,15 +676,15 @@
 		return -1;
 
 	sp++; /* beginning of type name, or closing brace for empty */
-	if (!prefixcmp(sp, "commit}"))
+	if (starts_with(sp, "commit}"))
 		expected_type = OBJ_COMMIT;
-	else if (!prefixcmp(sp, "tag}"))
+	else if (starts_with(sp, "tag}"))
 		expected_type = OBJ_TAG;
-	else if (!prefixcmp(sp, "tree}"))
+	else if (starts_with(sp, "tree}"))
 		expected_type = OBJ_TREE;
-	else if (!prefixcmp(sp, "blob}"))
+	else if (starts_with(sp, "blob}"))
 		expected_type = OBJ_BLOB;
-	else if (!prefixcmp(sp, "object}"))
+	else if (starts_with(sp, "object}"))
 		expected_type = OBJ_ANY;
 	else if (sp[0] == '}')
 		expected_type = OBJ_NONE;
@@ -911,7 +911,7 @@
 	const char *match = NULL, *target = NULL;
 	size_t len;
 
-	if (!prefixcmp(message, "checkout: moving from ")) {
+	if (starts_with(message, "checkout: moving from ")) {
 		match = message + strlen("checkout: moving from ");
 		target = strstr(match, " to ");
 	}
@@ -1304,7 +1304,7 @@
 
 static char *resolve_relative_path(const char *rel)
 {
-	if (prefixcmp(rel, "./") && prefixcmp(rel, "../"))
+	if (!starts_with(rel, "./") && !starts_with(rel, "../"))
 		return NULL;
 
 	if (!startup_info)
diff --git a/shell.c b/shell.c
index 66350b2..5c0d47a 100644
--- a/shell.c
+++ b/shell.c
@@ -15,7 +15,7 @@
 	setup_path();
 	if (!arg || !(arg = sq_dequote(arg)))
 		die("bad argument");
-	if (prefixcmp(me, "git-"))
+	if (!starts_with(me, "git-"))
 		die("bad command");
 
 	my_argv[0] = me + 4;
diff --git a/submodule.c b/submodule.c
index 1905d75..613857e 100644
--- a/submodule.c
+++ b/submodule.c
@@ -201,7 +201,7 @@
 
 int submodule_config(const char *var, const char *value, void *cb)
 {
-	if (!prefixcmp(var, "submodule."))
+	if (starts_with(var, "submodule."))
 		return parse_submodule_config_option(var, value);
 	else if (!strcmp(var, "fetch.recursesubmodules")) {
 		config_fetch_recurse_submodules = parse_fetch_recurse_submodules_arg(var, value);
diff --git a/tag.c b/tag.c
index 78d272b..7b07921 100644
--- a/tag.c
+++ b/tag.c
@@ -86,7 +86,7 @@
 		return -1;
 	bufptr += 48; /* "object " + sha1 + "\n" */
 
-	if (prefixcmp(bufptr, "type "))
+	if (!starts_with(bufptr, "type "))
 		return -1;
 	bufptr += 5;
 	nl = memchr(bufptr, '\n', tail - bufptr);
@@ -109,7 +109,7 @@
 		item->tagged = NULL;
 	}
 
-	if (bufptr + 4 < tail && !prefixcmp(bufptr, "tag "))
+	if (bufptr + 4 < tail && starts_with(bufptr, "tag "))
 		; 		/* good */
 	else
 		return -1;
@@ -120,7 +120,7 @@
 	item->tag = xmemdupz(bufptr, nl - bufptr);
 	bufptr = nl + 1;
 
-	if (bufptr + 7 < tail && !prefixcmp(bufptr, "tagger "))
+	if (bufptr + 7 < tail && starts_with(bufptr, "tagger "))
 		item->date = parse_tag_date(bufptr, tail);
 	else
 		item->date = 0;
@@ -160,8 +160,8 @@
 {
 	char *eol;
 	size_t len = 0;
-	while (len < size && prefixcmp(buf + len, PGP_SIGNATURE) &&
-			prefixcmp(buf + len, PGP_MESSAGE)) {
+	while (len < size && !starts_with(buf + len, PGP_SIGNATURE) &&
+			!starts_with(buf + len, PGP_MESSAGE)) {
 		eol = memchr(buf + len, '\n', size - len);
 		len += eol ? eol - (buf + len) + 1 : size - len;
 	}
diff --git a/test-line-buffer.c b/test-line-buffer.c
index ef1d7ba..1e58f04 100644
--- a/test-line-buffer.c
+++ b/test-line-buffer.c
@@ -19,7 +19,7 @@
 {
 	switch (*command) {
 	case 'b':
-		if (!prefixcmp(command, "binary ")) {
+		if (starts_with(command, "binary ")) {
 			struct strbuf sb = STRBUF_INIT;
 			strbuf_addch(&sb, '>');
 			buffer_read_binary(buf, &sb, strtouint32(arg));
@@ -28,12 +28,12 @@
 			return;
 		}
 	case 'c':
-		if (!prefixcmp(command, "copy ")) {
+		if (starts_with(command, "copy ")) {
 			buffer_copy_bytes(buf, strtouint32(arg));
 			return;
 		}
 	case 's':
-		if (!prefixcmp(command, "skip ")) {
+		if (starts_with(command, "skip ")) {
 			buffer_skip_bytes(buf, strtouint32(arg));
 			return;
 		}
diff --git a/test-string-list.c b/test-string-list.c
index 00ce6c9..14bdf9d 100644
--- a/test-string-list.c
+++ b/test-string-list.c
@@ -38,7 +38,7 @@
 static int prefix_cb(struct string_list_item *item, void *cb_data)
 {
 	const char *prefix = (const char *)cb_data;
-	return !prefixcmp(item->string, prefix);
+	return starts_with(item->string, prefix);
 }
 
 int main(int argc, char **argv)
diff --git a/transport-helper.c b/transport-helper.c
index 673b7c2..2010674 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -190,7 +190,7 @@
 			data->export = 1;
 		else if (!strcmp(capname, "check-connectivity"))
 			data->check_connectivity = 1;
-		else if (!data->refspecs && !prefixcmp(capname, "refspec ")) {
+		else if (!data->refspecs && starts_with(capname, "refspec ")) {
 			ALLOC_GROW(refspecs,
 				   refspec_nr + 1,
 				   refspec_alloc);
@@ -199,17 +199,17 @@
 			data->connect = 1;
 		} else if (!strcmp(capname, "signed-tags")) {
 			data->signed_tags = 1;
-		} else if (!prefixcmp(capname, "export-marks ")) {
+		} else if (starts_with(capname, "export-marks ")) {
 			struct strbuf arg = STRBUF_INIT;
 			strbuf_addstr(&arg, "--export-marks=");
 			strbuf_addstr(&arg, capname + strlen("export-marks "));
 			data->export_marks = strbuf_detach(&arg, NULL);
-		} else if (!prefixcmp(capname, "import-marks")) {
+		} else if (starts_with(capname, "import-marks")) {
 			struct strbuf arg = STRBUF_INIT;
 			strbuf_addstr(&arg, "--import-marks=");
 			strbuf_addstr(&arg, capname + strlen("import-marks "));
 			data->import_marks = strbuf_detach(&arg, NULL);
-		} else if (!prefixcmp(capname, "no-private-update")) {
+		} else if (starts_with(capname, "no-private-update")) {
 			data->no_private_update = 1;
 		} else if (mandatory) {
 			die("Unknown mandatory capability %s. This remote "
@@ -311,7 +311,7 @@
 
 	if (!strcmp(buf.buf, "ok"))
 		ret = 0;
-	else if (!prefixcmp(buf.buf, "error")) {
+	else if (starts_with(buf.buf, "error")) {
 		ret = -1;
 	} else if (!strcmp(buf.buf, "unsupported"))
 		ret = 1;
@@ -375,7 +375,7 @@
 	while (1) {
 		recvline(data, &buf);
 
-		if (!prefixcmp(buf.buf, "lock ")) {
+		if (starts_with(buf.buf, "lock ")) {
 			const char *name = buf.buf + 5;
 			if (transport->pack_lockfile)
 				warning("%s also locked %s", data->name, name);
@@ -646,10 +646,10 @@
 	char *refname, *msg;
 	int status;
 
-	if (!prefixcmp(buf->buf, "ok ")) {
+	if (starts_with(buf->buf, "ok ")) {
 		status = REF_STATUS_OK;
 		refname = buf->buf + 3;
-	} else if (!prefixcmp(buf->buf, "error ")) {
+	} else if (starts_with(buf->buf, "error ")) {
 		status = REF_STATUS_REMOTE_REJECT;
 		refname = buf->buf + 6;
 	} else
diff --git a/transport.c b/transport.c
index 7202b77..8023956 100644
--- a/transport.c
+++ b/transport.c
@@ -169,13 +169,13 @@
 		remotename = ref->name;
 		tmp = resolve_ref_unsafe(localname, sha, 1, &flag);
 		if (tmp && flag & REF_ISSYMREF &&
-			!prefixcmp(tmp, "refs/heads/"))
+			starts_with(tmp, "refs/heads/"))
 			localname = tmp;
 
 		/* Both source and destination must be local branches. */
-		if (!localname || prefixcmp(localname, "refs/heads/"))
+		if (!localname || !starts_with(localname, "refs/heads/"))
 			continue;
-		if (!remotename || prefixcmp(remotename, "refs/heads/"))
+		if (!remotename || !starts_with(remotename, "refs/heads/"))
 			continue;
 
 		if (!pretend)
@@ -191,7 +191,7 @@
 
 static const char *rsync_url(const char *url)
 {
-	return prefixcmp(url, "rsync://") ? skip_prefix(url, "rsync:") : url;
+	return !starts_with(url, "rsync://") ? skip_prefix(url, "rsync:") : url;
 }
 
 static struct ref *get_refs_via_rsync(struct transport *transport, int for_push)
@@ -296,8 +296,8 @@
 	FILE *f;
 
 	/* when called via for_each_ref(), flags is non-zero */
-	if (flags && prefixcmp(name, "refs/heads/") &&
-			prefixcmp(name, "refs/tags/"))
+	if (flags && !starts_with(name, "refs/heads/") &&
+			!starts_with(name, "refs/tags/"))
 		return 0;
 
 	strbuf_addstr(buf, name);
@@ -652,7 +652,7 @@
 		print_ref_status('-', "[deleted]", ref, NULL, NULL, porcelain);
 	else if (is_null_sha1(ref->old_sha1))
 		print_ref_status('*',
-			(!prefixcmp(ref->name, "refs/tags/") ? "[new tag]" :
+			(starts_with(ref->name, "refs/tags/") ? "[new tag]" :
 			"[new branch]"),
 			ref, ref->peer_ref, NULL, porcelain);
 	else {
@@ -930,13 +930,13 @@
 
 		while (is_urlschemechar(p == url, *p))
 			p++;
-		if (!prefixcmp(p, "::"))
+		if (starts_with(p, "::"))
 			helper = xstrndup(url, p - url);
 	}
 
 	if (helper) {
 		transport_helper_init(ret, helper);
-	} else if (!prefixcmp(url, "rsync:")) {
+	} else if (starts_with(url, "rsync:")) {
 		ret->get_refs_list = get_refs_via_rsync;
 		ret->fetch = fetch_objs_via_rsync;
 		ret->push = rsync_transport_push;
@@ -949,11 +949,11 @@
 		ret->disconnect = close_bundle;
 		ret->smart_options = NULL;
 	} else if (!is_url(url)
-		|| !prefixcmp(url, "file://")
-		|| !prefixcmp(url, "git://")
-		|| !prefixcmp(url, "ssh://")
-		|| !prefixcmp(url, "git+ssh://")
-		|| !prefixcmp(url, "ssh+git://")) {
+		|| starts_with(url, "file://")
+		|| starts_with(url, "git://")
+		|| starts_with(url, "ssh://")
+		|| starts_with(url, "git+ssh://")
+		|| starts_with(url, "ssh+git://")) {
 		/* These are builtin smart transports. */
 		struct git_transport_data *data = xcalloc(1, sizeof(*data));
 		ret->data = data;
diff --git a/upload-pack.c b/upload-pack.c
index c989a73..dafd0e9 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -394,7 +394,7 @@
 			got_other = 0;
 			continue;
 		}
-		if (!prefixcmp(line, "have ")) {
+		if (starts_with(line, "have ")) {
 			switch (got_sha1(line+5, sha1)) {
 			case -1: /* they have what we do not */
 				got_other = 1;
@@ -540,7 +540,7 @@
 		if (!line)
 			break;
 
-		if (!prefixcmp(line, "shallow ")) {
+		if (starts_with(line, "shallow ")) {
 			unsigned char sha1[20];
 			struct object *object;
 			if (get_sha1_hex(line + 8, sha1))
@@ -556,14 +556,14 @@
 			}
 			continue;
 		}
-		if (!prefixcmp(line, "deepen ")) {
+		if (starts_with(line, "deepen ")) {
 			char *end;
 			depth = strtol(line + 7, &end, 0);
 			if (end == line + 7 || depth <= 0)
 				die("Invalid deepen: %s", line);
 			continue;
 		}
-		if (prefixcmp(line, "want ") ||
+		if (!starts_with(line, "want ") ||
 		    get_sha1_hex(line+5, sha1_buf))
 			die("git upload-pack: protocol error, "
 			    "expected to get sha, not '%s'", line);
@@ -815,7 +815,7 @@
 			strict = 1;
 			continue;
 		}
-		if (!prefixcmp(arg, "--timeout=")) {
+		if (starts_with(arg, "--timeout=")) {
 			timeout = atoi(arg+10);
 			daemon_mode = 1;
 			continue;
diff --git a/wt-status.c b/wt-status.c
index b4e44ba..f3c0088 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -803,7 +803,7 @@
 	int i;
 
 	assert(s->branch && !s->is_initial);
-	if (prefixcmp(s->branch, "refs/heads/"))
+	if (!starts_with(s->branch, "refs/heads/"))
 		return;
 	branch = branch_get(s->branch + 11);
 	if (!format_tracking_info(branch, &sb))
@@ -1062,9 +1062,9 @@
 		strbuf_setlen(&sb, sb.len - 1);
 	if (!sb.len)
 		goto got_nothing;
-	if (!prefixcmp(sb.buf, "refs/heads/"))
+	if (starts_with(sb.buf, "refs/heads/"))
 		strbuf_remove(&sb,0, strlen("refs/heads/"));
-	else if (!prefixcmp(sb.buf, "refs/"))
+	else if (starts_with(sb.buf, "refs/"))
 		;
 	else if (!get_sha1_hex(sb.buf, sha1)) {
 		const char *abbrev;
@@ -1094,7 +1094,7 @@
 	struct grab_1st_switch_cbdata *cb = cb_data;
 	const char *target = NULL, *end;
 
-	if (prefixcmp(message, "checkout: moving from "))
+	if (!starts_with(message, "checkout: moving from "))
 		return 0;
 	message += strlen("checkout: moving from ");
 	target = strstr(message, " to ");
@@ -1129,9 +1129,9 @@
 	     ((commit = lookup_commit_reference_gently(sha1, 1)) != NULL &&
 	      !hashcmp(cb.nsha1, commit->object.sha1)))) {
 		int ofs;
-		if (!prefixcmp(ref, "refs/tags/"))
+		if (starts_with(ref, "refs/tags/"))
 			ofs = strlen("refs/tags/");
-		else if (!prefixcmp(ref, "refs/remotes/"))
+		else if (starts_with(ref, "refs/remotes/"))
 			ofs = strlen("refs/remotes/");
 		else
 			ofs = 0;
@@ -1220,7 +1220,7 @@
 	if (s->branch) {
 		const char *on_what = _("On branch ");
 		const char *branch_name = s->branch;
-		if (!prefixcmp(branch_name, "refs/heads/"))
+		if (starts_with(branch_name, "refs/heads/"))
 			branch_name += 11;
 		else if (!strcmp(branch_name, "HEAD")) {
 			branch_status_color = color(WT_STATUS_NOBRANCH, s);
@@ -1421,7 +1421,7 @@
 		return;
 	branch_name = s->branch;
 
-	if (!prefixcmp(branch_name, "refs/heads/"))
+	if (starts_with(branch_name, "refs/heads/"))
 		branch_name += 11;
 	else if (!strcmp(branch_name, "HEAD")) {
 		branch_name = _("HEAD (no branch)");