diff --git a/Documentation/git-name-rev.txt b/Documentation/git-name-rev.txt
index ad1d1468c99..6b0f1ba75fc 100644
--- a/Documentation/git-name-rev.txt
+++ b/Documentation/git-name-rev.txt
@@ -25,7 +25,8 @@ OPTIONS
 	Do not use branch names, but only tags to name the commits
 
 --refs=<pattern>::
-	Only use refs whose names match a given shell pattern.
+	Only use refs whose names match a given shell pattern.  The pattern
+	can be one of branch name, tag name or fully qualified ref name.
 
 --all::
 	List all commits reachable from all refs
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 62382479749..87d485496fd 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -82,6 +82,20 @@ copy_data:
 	}
 }
 
+static int subpath_matches(const char *path, const char *filter)
+{
+	const char *subpath = path;
+
+	while (subpath) {
+		if (!fnmatch(filter, subpath, 0))
+			return subpath - path;
+		subpath = strchr(subpath, '/');
+		if (subpath)
+			subpath++;
+	}
+	return -1;
+}
+
 struct name_ref_data {
 	int tags_only;
 	int name_only;
@@ -92,13 +106,23 @@ static int name_ref(const char *path, const unsigned char *sha1, int flags, void
 {
 	struct object *o = parse_object(sha1);
 	struct name_ref_data *data = cb_data;
+	int can_abbreviate_output = data->tags_only && data->name_only;
 	int deref = 0;
 
 	if (data->tags_only && prefixcmp(path, "refs/tags/"))
 		return 0;
 
-	if (data->ref_filter && fnmatch(data->ref_filter, path, 0))
-		return 0;
+	if (data->ref_filter) {
+		switch (subpath_matches(path, data->ref_filter)) {
+		case -1: /* did not match */
+			return 0;
+		case 0:  /* matched fully */
+			break;
+		default: /* matched subpath */
+			can_abbreviate_output = 1;
+			break;
+		}
+	}
 
 	while (o && o->type == OBJ_TAG) {
 		struct tag *t = (struct tag *) o;
@@ -110,12 +134,10 @@ static int name_ref(const char *path, const unsigned char *sha1, int flags, void
 	if (o && o->type == OBJ_COMMIT) {
 		struct commit *commit = (struct commit *)o;
 
-		if (!prefixcmp(path, "refs/heads/"))
+		if (can_abbreviate_output)
+			path = shorten_unambiguous_ref(path, 0);
+		else if (!prefixcmp(path, "refs/heads/"))
 			path = path + 11;
-		else if (data->tags_only
-		    && data->name_only
-		    && !prefixcmp(path, "refs/tags/"))
-			path = path + 10;
 		else if (!prefixcmp(path, "refs/"))
 			path = path + 5;