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

[PATCH 3/7] git push: New options --matching and --current

From
Finn Arne Gangstad <finnag@pvv.org>
Date
Mar 9, 2009, 22:35 UTC
Message-ID
<1236638151-6465-4-git-send-email-finnag@pvv.org>
In-Reply-To
<1236638151-6465-1-git-send-email-finnag@pvv.org>

--matching: Push all branches that already exist with the same name in the remote --current: Push the current branch to whatever it is tracking

Signed-off-by: Finn Arne Gangstad <finnag@pvv.org>
---
 Documentation/git-push.txt |   10 +++++-
 builtin-push.c             |   87 +++++++++++++++++++++++++++++++++++---------
 transport.h                |    9 +++++
 3 files changed, 87 insertions(+), 19 deletions(-)
diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index 4e7e5a7..cb7b3d2 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -9,7 +9,8 @@ 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 | --tags | --matching | --current]
+	   [--dry-run] [--receive-pack=<git-receive-pack>]
 	   [--repo=<repository>] [-f | --force] [-v | --verbose]
 	   [<repository> <refspec>...]
 
@@ -82,6 +83,13 @@ nor in any Push line of the corresponding remotes file---see below).
 	if the configuration option `remote.<remote>.mirror` is
 	set.
 
+--matching::
+	For every branch on the local side, the remote side is updated if
+	a branch of the same name already exists there.
+
+--current::
+	Push the current branch to the branch it is tracking on the remote.
+
 --dry-run::
 	Do everything except actually send the updates.
 
diff --git a/builtin-push.c b/builtin-push.c
index 122fdcf..5706c99 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 | --current | --matching] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>] [--repo=<repository>] [-f | --force] [-v] [<repository> <refspec>...]",
 	NULL,
 };
 
@@ -48,6 +48,53 @@ static void set_refspecs(const char **refs, int nr)
 	}
 }
 
+static const char *make_push_ref(const char *a, const char *b)
+{
+	char *buf = xmalloc(strlen(a) + strlen(b) + 2);
+	strcpy(buf, a);
+	strcat(buf, ":");
+	strcat(buf, b);
+	return buf;
+}
+
+static void setup_push_current(struct remote *remote)
+{
+	int n;
+	struct branch *branch = branch_get(NULL);
+	if (!branch)
+		die("You are not currently on a branch.");
+	if (!branch->merge_nr)
+		die("The current branch %s is not tracking anything.",
+		    branch->name);
+	if (branch->remote != remote)
+		die("The current branch is tracking \"%s\", not \"%s\"!",
+		    branch->remote->name, remote->name);
+	for (n = 0; n < branch->merge_nr; n++)
+		add_refspec(make_push_ref(branch->name,
+						branch->merge[n]->src));
+}
+
+static void handle_default_push(struct remote *remote, int *flags)
+{
+	git_config(git_default_config, NULL);
+	switch (push_default) {
+	case PUSH_DEFAULT_UNSPECIFIED:
+		/* fallthrough */
+
+	case PUSH_DEFAULT_MATCHING:
+		add_refspec(":");
+		break;
+
+	case PUSH_DEFAULT_CURRENT:
+		setup_push_current(remote);
+		break;
+
+	case PUSH_DEFAULT_NOTHING:
+		die("No refspec given, and none configured.");
+		break;
+	}
+}
+
 static int do_push(const char *repo, int flags)
 {
 	int i, errs;
@@ -59,29 +106,29 @@ static int do_push(const char *repo, int flags)
 	if (remote->mirror)
 		flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
 
-	if ((flags & TRANSPORT_PUSH_ALL) && refspec) {
+	if ((flags & TRANSPORT_PUSH_MODE_MASK) && refspec) {
 		if (!strcmp(*refspec, "refs/tags/*"))
-			return error("--all and --tags are incompatible");
-		return error("--all can't be combined with refspecs");
+			return error("--tags cannot be combined with a push mode");
+		return error("push modes cannot be combined with explicit refspecs");
 	}
 
-	if ((flags & TRANSPORT_PUSH_MIRROR) && refspec) {
-		if (!strcmp(*refspec, "refs/tags/*"))
-			return error("--mirror and --tags are incompatible");
-		return error("--mirror can't be combined with refspecs");
-	}
+	if (HAS_MULTI_BITS(flags & TRANSPORT_PUSH_MODE_MASK))
+		return error("Multiple push modes specified");
 
-	if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) ==
-				(TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) {
-		return error("--all and --mirror are incompatible");
-	}
+	if (flags & TRANSPORT_PUSH_CURRENT)
+		setup_push_current(remote);
+	else if (flags & TRANSPORT_PUSH_MATCHING)
+		add_refspec(":");
 
-	if (!refspec
-		&& !(flags & TRANSPORT_PUSH_ALL)
-		&& remote->push_refspec_nr) {
-		refspec = remote->push_refspec;
-		refspec_nr = remote->push_refspec_nr;
+	if (!refspec && !(flags & TRANSPORT_PUSH_MODE_MASK)) {
+		if (remote->push_refspec_nr) {
+			refspec = remote->push_refspec;
+			refspec_nr = remote->push_refspec_nr;
+		} else {
+			handle_default_push(remote, &flags);
+		}
 	}
+
 	errs = 0;
 	for (i = 0; i < remote->url_nr; i++) {
 		struct transport *transport =
@@ -120,6 +167,10 @@ 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_BIT( 0 , "current", &flags, "push current branch",
+			 TRANSPORT_PUSH_CURRENT),
 		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..b897d0c 100644
--- a/transport.h
+++ b/transport.h
@@ -34,6 +34,15 @@ struct transport {
 #define TRANSPORT_PUSH_DRY_RUN 4
 #define TRANSPORT_PUSH_MIRROR 8
 #define TRANSPORT_PUSH_VERBOSE 16
+#define TRANSPORT_PUSH_MATCHING 32
+#define TRANSPORT_PUSH_CURRENT 64
+/**
+ * All push flags that imply a certain set of refspecs to be pushed must
+ * be combined into TRANSPORT_PUSH_MODE_MASK
+ **/
+#define TRANSPORT_PUSH_MODE_MASK \
+    (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR | TRANSPORT_PUSH_MATCHING | \
+    TRANSPORT_PUSH_CURRENT)
 
 /* Returns a transport suitable for the url */
 struct transport *transport_get(struct remote *, const char *);
-- 
1.6.2.105.g6ff1f.dirty
Previous: Finn Arne GangstadNext: Daniel Barkalow
Message 4 of 31 in “git push usability improvements and default change”
  1. git push usability improvements and default changeFinn Arne Gangstad, Mar 9, 2009
  2. 1/7 remote: Make "-" an alias for the current remoteFinn Arne Gangstad, Mar 9, 2009
  3. 2/7 New config option push.defaultFinn Arne Gangstad, Mar 9, 2009
  4. 3/7 git push: New options --matching and --currentFinn Arne Gangstad, Mar 9, 2009
  5. Daniel BarkalowMar 9, 2009
  6. Finn Arne GangstadMar 10, 2009
  7. 4/7 git push: Display warning on unconfigured default pushFinn Arne Gangstad, Mar 9, 2009
  8. Jay SoffianMar 10, 2009
  9. 5/7 git push: Document that "nothing" is the future push defaultFinn Arne Gangstad, Mar 9, 2009
  10. 6/7 git push: Change default for "git push" to nothing.Finn Arne Gangstad, Mar 9, 2009
  11. 7/7 git push: Remove warning for "git push" default changeFinn Arne Gangstad, Mar 9, 2009
  12. Johannes SchindelinMar 9, 2009
  13. Junio C HamanoMar 10, 2009
  14. Finn Arne GangstadMar 10, 2009
  15. Johannes SchindelinMar 10, 2009
  16. Finn Arne GangstadMar 10, 2009
  17. Junio C HamanoMar 10, 2009
  18. Junio C HamanoMar 10, 2009
  19. Finn Arne GangstadMar 10, 2009
  20. Jay SoffianMar 10, 2009
  21. Junio C HamanoMar 11, 2009
  22. Nanako ShiraishiMar 12, 2009
  23. Finn Arne GangstadMar 12, 2009
  24. Miles BaderMar 12, 2009
  25. Finn Arne GangstadMar 12, 2009
  26. Miles BaderMar 13, 2009
  27. John TapsellMar 13, 2009
  28. Jeff KingMar 10, 2009
  29. Finn Arne GangstadMar 10, 2009
  30. Jeff KingMar 10, 2009
  31. Jay SoffianMar 11, 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.