diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index 9b7cfbc5c1..44d1e04931 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -11,7 +11,7 @@ SYNOPSIS
 [verse]
 'git push' [--all | --branches | --mirror | --tags] [--follow-tags] [--atomic] [-n | --dry-run] [--receive-pack=<git-receive-pack>]
 	   [--repo=<repository>] [-f | --force] [-d | --delete] [--prune] [-q | --quiet] [-v | --verbose]
-	   [-u | --set-upstream] [-o <string> | --push-option=<string>]
+	   [-u | --set-upstream] [-o <string> | --push-option=<string>] [--send-up-to-date]
 	   [--[no-]signed|--signed=(true|false|if-asked)]
 	   [--force-with-lease[=<refname>[:<expect>]] [--force-if-includes]]
 	   [--no-verify] [<repository> [<refspec>...]]
@@ -225,6 +225,12 @@ already exists on the remote side.
 	line, the values of configuration variable `push.pushOption`
 	are used instead.
 
+--send-up-to-date::
+	Usually, the command will not send a local ref when the remote ref
+	already matches, as no change would occur if it did.  This flag
+	disables that check.  This allows push options to be sent alongside
+	up-to-date references on the remote.
+
 --receive-pack=<git-receive-pack>::
 --exec=<git-receive-pack>::
 	Path to the 'git-receive-pack' program on the remote
diff --git a/Documentation/git-send-pack.txt b/Documentation/git-send-pack.txt
index b9e73f2e77..2517d226d0 100644
--- a/Documentation/git-send-pack.txt
+++ b/Documentation/git-send-pack.txt
@@ -13,6 +13,7 @@ SYNOPSIS
 		[--receive-pack=<git-receive-pack>]
 		[--verbose] [--thin] [--atomic]
 		[--[no-]signed | --signed=(true|false|if-asked)]
+		[--send-up-to-date]
 		[<host>:]<directory> (--all | <ref>...)
 
 DESCRIPTION
@@ -88,6 +89,12 @@ be in a separate packet, and the list must end with a flush packet.
 	options, error out.  See linkgit:git-push[1] and
 	linkgit:githooks[5] for details.
 
+--send-up-to-date::
+	Usually, the command will not send a local ref when the remote ref
+	already matches, as no change would occur if it did.  This flag
+	disables that check.  This allows push options to be sent alongside
+	up-to-date references on the remote.
+
 <host>::
 	A remote host to house the repository.  When this
 	part is specified, 'git-receive-pack' is invoked via
diff --git a/builtin/push.c b/builtin/push.c
index 2fbb31c3ad..555e8b53fe 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -617,6 +617,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 		OPT_BIT(0, "no-verify", &flags, N_("bypass pre-push hook"), TRANSPORT_PUSH_NO_HOOK),
 		OPT_BIT(0, "follow-tags", &flags, N_("push missing but relevant tags"),
 			TRANSPORT_PUSH_FOLLOW_TAGS),
+		OPT_BIT(0, "send-up-to-date", &flags, N_("send refs when there is no change"), TRANSPORT_PUSH_SEND_UPTODATE),
 		OPT_CALLBACK_F(0, "signed", &push_cert, "(yes|no|if-asked)", N_("GPG sign the push"),
 				PARSE_OPT_OPTARG, option_parse_push_signed),
 		OPT_BIT(0, "atomic", &flags, N_("request atomic transaction on remote side"), TRANSPORT_PUSH_ATOMIC),
diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index 3df9eaad09..da6630fa12 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -19,6 +19,7 @@ static const char * const send_pack_usage[] = {
 	   "              [--receive-pack=<git-receive-pack>]\n"
 	   "              [--verbose] [--thin] [--atomic]\n"
 	   "              [--[no-]signed | --signed=(true|false|if-asked)]\n"
+	   "              [--send-up-to-date]\n"
 	   "              [<host>:]<directory> (--all | <ref>...)"),
 	NULL,
 };
@@ -165,6 +166,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
 	const char *receivepack = "git-receive-pack";
 	unsigned dry_run = 0;
 	unsigned send_mirror = 0;
+	unsigned send_uptodate = 0;
 	unsigned force_update = 0;
 	unsigned quiet = 0;
 	int push_cert = 0;
@@ -200,6 +202,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
 		OPT_BOOL(0, "stateless-rpc", &stateless_rpc, N_("use stateless RPC protocol")),
 		OPT_BOOL(0, "stdin", &from_stdin, N_("read refs from stdin")),
 		OPT_BOOL(0, "helper-status", &helper_status, N_("print status from remote helper")),
+		OPT_BOOL(0, "send-up-to-date", &send_uptodate, N_("send refs when there is no change")),
 		OPT_CALLBACK_F(0, "force-with-lease", &cas, N_("<refname>:<expect>"),
 		  N_("require old value of ref to be at this value"),
 		  PARSE_OPT_OPTARG, parseopt_push_cas_option),
@@ -221,6 +224,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
 	args.verbose = verbose;
 	args.dry_run = dry_run;
 	args.send_mirror = send_mirror;
+	args.send_uptodate = send_uptodate;
 	args.force_update = force_update;
 	args.quiet = quiet;
 	args.push_cert = push_cert;
diff --git a/send-pack.c b/send-pack.c
index 37f59d4f66..30b0f2f276 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -313,7 +313,7 @@ static int check_to_send_update(const struct ref *ref, const struct send_pack_ar
 	case REF_STATUS_REJECT_NODELETE:
 		return CHECK_REF_STATUS_REJECTED;
 	case REF_STATUS_UPTODATE:
-		return CHECK_REF_UPTODATE;
+		return args->send_uptodate ? 0 : CHECK_REF_UPTODATE;
 
 	default:
 	case REF_STATUS_EXPECTING_REPORT:
diff --git a/send-pack.h b/send-pack.h
index 7edb80596c..241b4278bc 100644
--- a/send-pack.h
+++ b/send-pack.h
@@ -27,7 +27,8 @@ struct send_pack_args {
 		push_cert:2,
 		stateless_rpc:1,
 		atomic:1,
-		disable_bitmaps:1;
+		disable_bitmaps:1,
+		send_uptodate:1;
 	const struct string_list *push_options;
 };
 
diff --git a/transport-helper.c b/transport-helper.c
index dd6002b393..115f46f6b8 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -983,6 +983,7 @@ static int push_refs_with_push(struct transport *transport,
 	int force_all = flags & TRANSPORT_PUSH_FORCE;
 	int mirror = flags & TRANSPORT_PUSH_MIRROR;
 	int atomic = flags & TRANSPORT_PUSH_ATOMIC;
+	int do_nop = flags & TRANSPORT_PUSH_SEND_UPTODATE;
 	struct helper_data *data = transport->data;
 	struct strbuf buf = STRBUF_INIT;
 	struct ref *ref;
@@ -1010,7 +1011,11 @@ static int push_refs_with_push(struct transport *transport,
 			} else
 				continue;
 		case REF_STATUS_UPTODATE:
-			continue;
+			if (do_nop) {
+				; /* do nothing */
+			}
+			else
+				continue;
 		default:
 			; /* do nothing */
 		}
diff --git a/transport.c b/transport.c
index df518ead70..84deadd2b6 100644
--- a/transport.c
+++ b/transport.c
@@ -867,6 +867,7 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re
 
 	memset(&args, 0, sizeof(args));
 	args.send_mirror = !!(flags & TRANSPORT_PUSH_MIRROR);
+	args.send_uptodate = !!(flags & TRANSPORT_PUSH_SEND_UPTODATE);
 	args.force_update = !!(flags & TRANSPORT_PUSH_FORCE);
 	args.use_thin_pack = data->options.thin;
 	args.verbose = (transport->verbose > 0);
diff --git a/transport.h b/transport.h
index 6393cd9823..61a20e84f0 100644
--- a/transport.h
+++ b/transport.h
@@ -158,6 +158,7 @@ struct transport {
 #define TRANSPORT_RECURSE_SUBMODULES_ONLY	(1<<15)
 #define TRANSPORT_PUSH_FORCE_IF_INCLUDES	(1<<16)
 #define TRANSPORT_PUSH_AUTO_UPSTREAM		(1<<17)
+#define TRANSPORT_PUSH_SEND_UPTODATE		(1<<18)
 
 int transport_summary_width(const struct ref *refs);
 
