diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh
index 1e5ac82f9b..678dd1dc19 100755
--- a/contrib/subtree/git-subtree.sh
+++ b/contrib/subtree/git-subtree.sh
@@ -27,7 +27,7 @@ git subtree add   --prefix=<prefix> <repository> <ref>
 git subtree merge --prefix=<prefix> <commit>
 git subtree split --prefix=<prefix> [<commit>]
 git subtree pull  --prefix=<prefix> <repository> <ref>
-git subtree push  --prefix=<prefix> <repository> <ref>
+git subtree push  --prefix=<prefix> <repository> <refspec>
 --
 h,help        show the help
 q             quiet
@@ -950,20 +950,30 @@ cmd_pull () {
 	cmd_merge FETCH_HEAD
 }
 
-# Usage: cmd_push REPOSITORY REMOTEREF
+# Usage: cmd_push REPOSITORY [+][LOCALREV:]REMOTEREF
 cmd_push () {
 	if test $# -ne 2
 	then
-		die "You must provide <repository> <ref>"
+		die "You must provide <repository> <refspec>"
 	fi
-	ensure_valid_ref_format "$2"
 	if test -e "$dir"
 	then
 		repository=$1
-		refspec=$2
+		refspec=${2#+}
+		remoteref=${refspec#*:}
+		if test "$remoteref" = "$refspec"
+		then
+			localrevname_presplit=HEAD
+		else
+			localrevname_presplit=${refspec%%:*}
+		fi
+		ensure_valid_ref_format "$remoteref"
+		localrev_presplit=$(git rev-parse -q --verify "$localrevname_presplit^{commit}") ||
+			die "'$localrevname_presplit' does not refer to a commit"
+
 		echo "git push using: " "$repository" "$refspec"
-		localrev=$(cmd_split) || die
-		git push "$repository" "$localrev":"refs/heads/$refspec"
+		localrev=$(cmd_split "$localrev_presplit") || die
+		git push "$repository" "$localrev":"refs/heads/$remoteref"
 	else
 		die "'$dir' must already exist. Try 'git subtree add'."
 	fi
diff --git a/contrib/subtree/git-subtree.txt b/contrib/subtree/git-subtree.txt
index 1282aa705f..559b64aa96 100644
--- a/contrib/subtree/git-subtree.txt
+++ b/contrib/subtree/git-subtree.txt
@@ -16,7 +16,7 @@ SYNOPSIS
 
 [verse]
 'git subtree' [<options>] -P <prefix> pull <repository> <remote-ref>
-'git subtree' [<options>] -P <prefix> push <repository> <remote-ref>
+'git subtree' [<options>] -P <prefix> push <repository> <refspec>
 
 DESCRIPTION
 -----------
@@ -115,11 +115,13 @@ pull <repository> <remote-ref>::
 	it fetches the given ref from the specified remote
 	repository.
 
-push <repository> <remote-ref>::
-	Does a 'split' using the <prefix> subtree of HEAD and then
-	does a 'git push' to push the result to the <repository> and
-	<remote-ref>.  This can be used to push your subtree to
-	different branches of the remote repository.
+push <repository> [+][<local-commit>:]<remote-ref>::
+	Does a 'split' using the <prefix> subtree of <local-commit>
+	and then does a 'git push' to push the result to the
+	<repository> and <remote-ref>.  This can be used to push your
+	subtree to different branches of the remote repository.  Just
+	as with 'split', if no <local-commit> is given, then HEAD is
+	used.  The optional leading '+' is ignored.
 
 OPTIONS FOR ALL COMMANDS
 ------------------------
diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh
index 8bc0e488aa..8a3530305e 100755
--- a/contrib/subtree/t/t7900-subtree.sh
+++ b/contrib/subtree/t/t7900-subtree.sh
@@ -799,6 +799,28 @@ test_expect_success 'push "sub dir"/ with --branch for an incompatible branch' '
 	)
 '
 
+test_expect_success 'push "sub dir"/ with a local rev' '
+	subtree_test_create_repo "$test_count" &&
+	subtree_test_create_repo "$test_count/sub proj" &&
+	test_create_commit "$test_count" main1 &&
+	test_create_commit "$test_count/sub proj" sub1 &&
+	(
+		cd "$test_count" &&
+		git fetch ./"sub proj" HEAD &&
+		git subtree add --prefix="sub dir" FETCH_HEAD
+	) &&
+	test_create_commit "$test_count" "sub dir"/main-sub1 &&
+	test_create_commit "$test_count" "sub dir"/main-sub2 &&
+	(
+		cd "$test_count" &&
+		bad_tree=$(git rev-parse --verify HEAD:"sub dir") &&
+		good_tree=$(git rev-parse --verify HEAD^:"sub dir") &&
+		git subtree push --prefix="sub dir" --annotate="*" ./"sub proj" HEAD^:from-mainline &&
+		split_tree=$(git -C "sub proj" rev-parse --verify refs/heads/from-mainline:) &&
+		test "$split_tree" = "$good_tree"
+	)
+'
+
 #
 # Validity checking
 #
