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

[PATCH] push: Learn to set up branch tracking with '--track'

From
Johannes Schindelin <johannes.schindelin@gmx.de>
Date
Jan 29, 2009, 13:38 UTC
Message-ID
<alpine.DEB.1.00.0901291438030.3586@pacific.mpi-cbg.de>
In-Reply-To
<cover.1233236267u.git.johannes.schindelin@gmx.de>

When pushing a branch to a remote repository that the remote side did not know beforehand, it is often handy to set up the branch tracking such that

	$ git checkout xyz
	$ git push --track origin xyz:abc
	$ git pull

will pull the branch 'abc' from the remote 'origin' into the branch 'xyz'.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
	This is a companion patch to the one I sent earlier:
	http://article.gmane.org/gmane.comp.version-control.git/13735
 Documentation/git-push.txt |    7 ++++++-
 builtin-push.c             |   42 ++++++++++++++++++++++++++++++++++++++++++
 t/t5516-fetch-push.sh      |   11 +++++++++++
 3 files changed, 59 insertions(+), 1 deletions(-)
diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index 7d1eced..fa1d54c 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -10,7 +10,7 @@ SYNOPSIS
 --------
 [verse]
 'git push' [--all | --mirror] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>]
-	   [--repo=<repository>] [-f | --force] [-v | --verbose]
+	   [--repo=<repository>] [-f | --force] [-v | --verbose] [-t | --track]
 	   [<repository> <refspec>...]
 
 DESCRIPTION
@@ -126,6 +126,11 @@ useful if you write an alias or script around 'git-push'.
 	transfer spends extra cycles to minimize the number of
 	objects to be sent and meant to be used on slower connection.
 
+-t::
+--track::
+	Set up tracking information for the pushed branches, so that
+	'git pull' will remember the indicated mapping.
+
 -v::
 --verbose::
 	Run verbosely.
diff --git a/builtin-push.c b/builtin-push.c
index 122fdcf..9fd445d 100644
--- a/builtin-push.c
+++ b/builtin-push.c
@@ -16,6 +16,7 @@ static const char * const push_usage[] = {
 
 static int thin;
 static const char *receivepack;
+static int track;
 
 static const char **refspec;
 static int refspec_nr;
@@ -48,6 +49,41 @@ static void set_refspecs(const char **refs, int nr)
 	}
 }
 
+static void setup_tracking(const char *url)
+{
+	struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT;
+	int i;
+
+	for (i = 0; i < refspec_nr; i++) {
+		const char *branch = refspec[i], *colon;
+
+		/* skip non-branches */
+		if (!prefixcmp("refs/", branch)) {
+			if (prefixcmp("refs/heads/", branch))
+				continue;
+			branch += strlen("refs/heads/");
+		}
+		colon = strchrnul(branch, ':');
+
+		strbuf_reset(&buf);
+		strbuf_addf(&buf, "branch.%.*s.remote",
+				(int)(colon - branch), branch);
+		git_config_set(buf.buf, url);
+
+		strbuf_reset(&buf);
+		strbuf_addf(&buf, "branch.%.*s.merge",
+				(int)(colon - branch), branch);
+		strbuf_reset(&buf2);
+		strbuf_addf(&buf2, "%s%s",
+			*colon && !prefixcmp("refs/heads/", colon + 1) ?
+			"" : "refs/heads/",
+			*colon ? colon + 1 : branch);
+		git_config_set(buf.buf, buf2.buf);
+	}
+	strbuf_release(&buf);
+	strbuf_release(&buf2);
+}
+
 static int do_push(const char *repo, int flags)
 {
 	int i, errs;
@@ -96,6 +132,8 @@ static int do_push(const char *repo, int flags)
 		if (flags & TRANSPORT_PUSH_VERBOSE)
 			fprintf(stderr, "Pushing to %s\n", remote->url[i]);
 		err = transport_push(transport, refspec_nr, refspec, flags);
+		if (!err && track)
+			setup_tracking(transport->url);
 		err |= transport_disconnect(transport);
 
 		if (!err)
@@ -126,11 +164,15 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 		OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"),
 		OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"),
 		OPT_STRING( 0 , "exec", &receivepack, "receive-pack", "receive pack program"),
+		OPT_BOOLEAN('t', "track", &track, "set up branch tracking information"),
 		OPT_END()
 	};
 
 	argc = parse_options(argc, argv, options, push_usage, 0);
 
+	if (track && !tags && !argc)
+		die ("Need explicit arguments for branch tracking");
+
 	if (tags)
 		add_refspec("refs/tags/*");
 
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 4426df9..e18b2f6 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -573,4 +573,15 @@ test_expect_success 'push with branches containing #' '
 	git checkout master
 '
 
+test_expect_success 'push --track' '
+
+	git push --track testrepo master &&
+	test ! -z "$(git ls-remote testrepo master)" &&
+	test "testrepo" = $(git config branch.master.remote) &&
+	test "refs/heads/master" = $(git config branch.master.merge) &&
+	git push --track testrepo master:test &&
+	test "refs/heads/test" = $(git config branch.master.merge)
+
+'
+
 test_done
-- 
1.6.1.1.506.gdbe181
Next: Sverre Rabbelier
Message 1 of 15 in “push: Learn to set up branch tracking with '--track'”
  1. push: Learn to set up branch tracking with '--track'Johannes Schindelin, Jan 29, 2009
  2. Sverre RabbelierJan 29, 2009
  3. Johannes SchindelinJan 29, 2009
  4. Johannes SchindelinJan 29, 2009
  5. Jeff KingJan 29, 2009
  6. Jeff KingJan 29, 2009
  7. Johannes SchindelinJan 30, 2009
  8. Jeff KingJan 30, 2009
  9. Johannes SchindelinJan 30, 2009
  10. Jeff KingJan 30, 2009
  11. Johannes SchindelinJan 30, 2009
  12. Jeff KingFeb 2, 2009
  13. Johannes SchindelinFeb 2, 2009
  14. Jeff KingFeb 6, 2009
  15. Johannes SchindelinFeb 6, 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.