git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[RFC PATCH] git push: Push nothing if no refspecs are given or configured

From
Finn Arne Gangstad <finnag@pvv.org>
Date
Mar 5, 2009, 22:15 UTC
Message-ID
<20090305221529.GA25871@pvv.org>

Previously, git push [remote] with no arguments would behave like "git push <remote> :" if no push refspecs were configured for the remote. It may be too easy for novice users to write "git push" or "git push origin" by accident, so git will now push nothing, and give an error message in such cases.

Teach git push a new option "--matching" that keeps the old behavior of pushing all matching branches when none are configured.

Signed-off-by: Finn Arne Gangstad <finnag@pvv.org>
---
 Documentation/git-push.txt |   10 ++++++++--
 builtin-push.c             |   32 +++++++++++++++++++++++---------
 transport.h                |    1 +
 3 files changed, 32 insertions(+), 11 deletions(-)
diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index 4e7e5a7..77a4792 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -9,7 +9,7 @@ git-push - Update remote refs along with associated objects
 SYNOPSIS
 --------
 [verse]
-'git push' [--all | --mirror | --tags] [--dry-run] [--receive-pack=<git-receive-pack>]
+'git push' [--all | --mirror | --matching | --tags] [--dry-run] [--receive-pack=<git-receive-pack>]
 	   [--repo=<repository>] [-f | --force] [-v | --verbose]
 	   [<repository> <refspec>...]
 
@@ -63,10 +63,11 @@ the remote repository.
 The special refspec `:` (or `{plus}:` to allow non-fast forward updates)
 directs git to push "matching" branches: for every branch that exists on
 the local side, the remote side is updated if a branch of the same name
-already exists on the remote side.  This is the default operation mode
+already exists on the remote side. Nothing will be pushed
 if no explicit refspec is found (that is neither on the command line
 nor in any Push line of the corresponding remotes file---see below).
 
+
 --all::
 	Instead of naming each ref to push, specifies that all
 	refs under `$GIT_DIR/refs/heads/` be pushed.
@@ -82,6 +83,11 @@ nor in any Push line of the corresponding remotes file---see below).
 	if the configuration option `remote.<remote>.mirror` is
 	set.
 
+--matching::
+	If no explicit refspecs are given, and no push refspecs are
+	configured for the remote, push all matching branches
+	(branches that exist in both ends) instead of nothing.
+
 --dry-run::
 	Do everything except actually send the updates.
 
diff --git a/builtin-push.c b/builtin-push.c
index 122fdcf..ffc648d 100644
--- a/builtin-push.c
+++ b/builtin-push.c
@@ -10,7 +10,7 @@
 #include "parse-options.h"
 
 static const char * const push_usage[] = {
-	"git push [--all | --mirror] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>] [--repo=<repository>] [-f | --force] [-v] [<repository> <refspec>...]",
+	"git push [--all | --mirror | --matching] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>] [--repo=<repository>] [-f | --force] [-v] [<repository> <refspec>...]",
 	NULL,
 };
 
@@ -48,6 +48,12 @@ static void set_refspecs(const char **refs, int nr)
 	}
 }
 
+
+static int has_multiple_bits(unsigned int x)
+{
+	return (x & (x - 1)) != 0;
+}
+
 static int do_push(const char *repo, int flags)
 {
 	int i, errs;
@@ -71,17 +77,24 @@ static int do_push(const char *repo, int flags)
 		return error("--mirror can't be combined with refspecs");
 	}
 
-	if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) ==
-				(TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) {
-		return error("--all and --mirror are incompatible");
+	if (has_multiple_bits(flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR | TRANSPORT_PUSH_MATCHING))) {
+		return error("--all, --mirror and --matching are incompatible");
 	}
 
-	if (!refspec
-		&& !(flags & TRANSPORT_PUSH_ALL)
-		&& remote->push_refspec_nr) {
-		refspec = remote->push_refspec;
-		refspec_nr = remote->push_refspec_nr;
+	if ((flags & TRANSPORT_PUSH_MATCHING)  && refspec) {
+		return error("--matching cannot be combined with refspecs");
 	}
+
+
+	if (!refspec && !(flags & TRANSPORT_PUSH_ALL)) {
+		if (remote->push_refspec_nr) {
+			refspec = remote->push_refspec;
+			refspec_nr = remote->push_refspec_nr;
+		} else if (!(flags & TRANSPORT_PUSH_MATCHING)) {
+			return error("No refspecs given and none configured for %s, nothing to push.", remote->name);
+		}
+	}
+
 	errs = 0;
 	for (i = 0; i < remote->url_nr; i++) {
 		struct transport *transport =
@@ -120,6 +133,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 		OPT_BIT( 0 , "all", &flags, "push all refs", TRANSPORT_PUSH_ALL),
 		OPT_BIT( 0 , "mirror", &flags, "mirror all refs",
 			    (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
+		OPT_BIT( 0, "matching", &flags, "push all matching refs", TRANSPORT_PUSH_MATCHING),
 		OPT_BOOLEAN( 0 , "tags", &tags, "push tags"),
 		OPT_BIT( 0 , "dry-run", &flags, "dry run", TRANSPORT_PUSH_DRY_RUN),
 		OPT_BIT('f', "force", &flags, "force updates", TRANSPORT_PUSH_FORCE),
diff --git a/transport.h b/transport.h
index 6bbc1a8..fb98128 100644
--- a/transport.h
+++ b/transport.h
@@ -34,6 +34,7 @@ struct transport {
 #define TRANSPORT_PUSH_DRY_RUN 4
 #define TRANSPORT_PUSH_MIRROR 8
 #define TRANSPORT_PUSH_VERBOSE 16
+#define TRANSPORT_PUSH_MATCHING 32
 
 /* Returns a transport suitable for the url */
 struct transport *transport_get(struct remote *, const char *);
-- 
1.6.2.12.g83676.dirty
Next: Sverre Rabbelier
Message 1 of 23 in “git push: Push nothing if no refspecs are given or configured”
  1. git push: Push nothing if no refspecs are given or configuredFinn Arne Gangstad, Mar 5, 2009
  2. Sverre RabbelierMar 5, 2009
  3. Markus HeidelbergMar 5, 2009
  4. Markus HeidelbergMar 5, 2009
  5. Sverre RabbelierMar 5, 2009
  6. Johannes SchindelinMar 6, 2009
  7. Junio C HamanoMar 6, 2009
  8. Sverre RabbelierMar 6, 2009
  9. Finn Arne GangstadMar 6, 2009
  10. Johannes SchindelinMar 6, 2009
  11. Finn Arne GangstadMar 6, 2009
  12. Jakub NarebskiMar 6, 2009
  13. Junio C HamanoMar 6, 2009
  14. Johannes SchindelinMar 7, 2009
  15. Johannes SchindelinMar 6, 2009
  16. John TapsellMar 6, 2009
  17. Jakub NarebskiMar 6, 2009
  18. Junio C HamanoMar 5, 2009
  19. Johannes SchindelinMar 6, 2009
  20. Markus HeidelbergMar 9, 2009
  21. Johannes SchindelinMar 9, 2009
  22. Markus HeidelbergMar 9, 2009
  23. Jeff KingMar 9, 2009

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.