All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/9] Introduce publish tracking branch
@ 2014-04-10 19:04 Felipe Contreras
  2014-04-10 19:04 ` [PATCH v2 1/9] push: trivial reorganization Felipe Contreras
                   ` (10 more replies)
  0 siblings, 11 replies; 34+ messages in thread
From: Felipe Contreras @ 2014-04-10 19:04 UTC (permalink / raw)
  To: git
  Cc: Matthieu Moy, Ramkumar Ramachandra, Jeff King, John Szakmeister,
	Felipe Contreras

As it has been discussed before, our support for triangular workflows is
lacking, and the following patch series aims to improve that situation.

We have the concept of upstream branch (e.g. 'origin/master') which is to where
our topic branches eventually should be merged to, so it makes sense that
'git rebase' uses that as the destination, but most people would not push to
such upstream branch, they would push to a publish branch
(e.g. 'github/feature-a'). We could set our upstream to the place we push, and
'git push' would be able to use that as default, and 'git branch --vv' would
show how ahead/behind we are in comparisson to that branch, but then
'git rebase' (or 'git merge') would be using the wrong branch.

This patch series adds:

 1) git push --set-publish
 2) git branch --set-publish
 3) git branch -vv # uses and shows the publish branch when configured
 4) @{publish} and @{p} marks
 5) branch.$name.{push,pushremote} configurations

After this, it becomes much easier to track branches in a triangular workflow.

The publish branch is used instead of the upstream branch for tracking
information in 'git branch --vv' and 'git status' if present, otherwise there
are no changes (upstream is used).

  master          e230c56 [origin/master, gh/master] Git 1.8.4
* fc/publish      0a105fd [master, gh/fc/publish: ahead 1] branch: display publish branch
  fc/branch/fast  177dcad [master, gh/fc/branch/fast] branch: reorganize verbose options
  fc/trivial      f289b9a [master: ahead 7] branch: trivial style fix
  fc/leaks        d101af4 [master: ahead 2] read-cache: plug a possible leak
  stable          e230c56 Git 1.8.4

Changes since v1:

 * Added @{publish} and @{p} marks

Felipe Contreras (9):
  push: trivial reorganization
  Add concept of 'publish' branch
  branch: allow configuring the publish branch
  t: branch add publish branch tests
  push: add --set-publish option
  branch: display publish branch
  sha1_name: cleanup interpret_branch_name()
  sha1_name: simplify track finding
  sha1_name: add support for @{publish} marks

 Documentation/git-branch.txt | 11 +++++++
 Documentation/git-push.txt   |  9 +++++-
 Documentation/revisions.txt  |  4 +++
 branch.c                     | 43 +++++++++++++++++++++++++
 branch.h                     |  2 ++
 builtin/branch.c             | 74 ++++++++++++++++++++++++++++++++++++++----
 builtin/push.c               | 52 +++++++++++++++++++-----------
 remote.c                     | 34 ++++++++++++++++----
 remote.h                     |  4 +++
 sha1_name.c                  | 62 ++++++++++++++++++++++--------------
 t/t1508-at-combinations.sh   |  5 +++
 t/t3200-branch.sh            | 76 ++++++++++++++++++++++++++++++++++++++++++++
 t/t5529-push-publish.sh      | 70 ++++++++++++++++++++++++++++++++++++++++
 t/t6040-tracking-info.sh     |  5 +--
 transport.c                  | 28 ++++++++++------
 transport.h                  |  1 +
 16 files changed, 415 insertions(+), 65 deletions(-)
 create mode 100755 t/t5529-push-publish.sh

-- 
1.9.1+fc1

^ permalink raw reply	[flat|nested] 34+ messages in thread

* [PATCH v2 1/9] push: trivial reorganization
  2014-04-10 19:04 [PATCH v2 0/9] Introduce publish tracking branch Felipe Contreras
@ 2014-04-10 19:04 ` Felipe Contreras
  2014-04-10 19:04 ` [PATCH v2 2/9] Add concept of 'publish' branch Felipe Contreras
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 34+ messages in thread
From: Felipe Contreras @ 2014-04-10 19:04 UTC (permalink / raw)
  To: git
  Cc: Matthieu Moy, Ramkumar Ramachandra, Jeff King, John Szakmeister,
	Felipe Contreras

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 builtin/push.c | 35 +++++++++++++++++++----------------
 1 file changed, 19 insertions(+), 16 deletions(-)

diff --git a/builtin/push.c b/builtin/push.c
index 0e50ddb..d10aefc 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -155,20 +155,11 @@ static NORETURN int die_push_simple(struct branch *branch, struct remote *remote
 	    remote->name, branch->name, advice_maybe);
 }
 
-static const char message_detached_head_die[] =
-	N_("You are not currently on a branch.\n"
-	   "To push the history leading to the current (detached HEAD)\n"
-	   "state now, use\n"
-	   "\n"
-	   "    git push %s HEAD:<name-of-remote-branch>\n");
-
 static void setup_push_upstream(struct remote *remote, struct branch *branch,
 				int triangular)
 {
 	struct strbuf refspec = STRBUF_INIT;
 
-	if (!branch)
-		die(_(message_detached_head_die), remote->name);
 	if (!branch->merge_nr || !branch->merge || !branch->remote_name)
 		die(_("The current branch %s has no upstream branch.\n"
 		    "To push the current branch and set the remote as upstream, use\n"
@@ -198,8 +189,6 @@ static void setup_push_upstream(struct remote *remote, struct branch *branch,
 
 static void setup_push_current(struct remote *remote, struct branch *branch)
 {
-	if (!branch)
-		die(_(message_detached_head_die), remote->name);
 	add_refspec(branch->name);
 }
 
@@ -240,9 +229,23 @@ static int is_workflow_triangular(struct remote *remote)
 	return (fetch_remote && fetch_remote != remote);
 }
 
-static void setup_default_push_refspecs(struct remote *remote)
+static const char message_detached_head_die[] =
+	N_("You are not currently on a branch.\n"
+	   "To push the history leading to the current (detached HEAD)\n"
+	   "state now, use\n"
+	   "\n"
+	   "    git push %s HEAD:<name-of-remote-branch>\n");
+
+static struct branch *get_current_branch(struct remote *remote)
 {
 	struct branch *branch = branch_get(NULL);
+	if (!branch)
+		die(_(message_detached_head_die), remote->name);
+	return branch;
+}
+
+static void setup_default_push_refspecs(struct remote *remote)
+{
 	int triangular = is_workflow_triangular(remote);
 
 	switch (push_default) {
@@ -257,17 +260,17 @@ static void setup_default_push_refspecs(struct remote *remote)
 
 	case PUSH_DEFAULT_SIMPLE:
 		if (triangular)
-			setup_push_current(remote, branch);
+			setup_push_current(remote, get_current_branch(remote));
 		else
-			setup_push_upstream(remote, branch, triangular);
+			setup_push_upstream(remote, get_current_branch(remote), triangular);
 		break;
 
 	case PUSH_DEFAULT_UPSTREAM:
-		setup_push_upstream(remote, branch, triangular);
+		setup_push_upstream(remote, get_current_branch(remote), triangular);
 		break;
 
 	case PUSH_DEFAULT_CURRENT:
-		setup_push_current(remote, branch);
+		setup_push_current(remote, get_current_branch(remote));
 		break;
 
 	case PUSH_DEFAULT_NOTHING:
-- 
1.9.1+fc1

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH v2 2/9] Add concept of 'publish' branch
  2014-04-10 19:04 [PATCH v2 0/9] Introduce publish tracking branch Felipe Contreras
  2014-04-10 19:04 ` [PATCH v2 1/9] push: trivial reorganization Felipe Contreras
@ 2014-04-10 19:04 ` Felipe Contreras
  2014-04-10 19:04 ` [PATCH v2 3/9] branch: allow configuring the publish branch Felipe Contreras
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 34+ messages in thread
From: Felipe Contreras @ 2014-04-10 19:04 UTC (permalink / raw)
  To: git
  Cc: Matthieu Moy, Ramkumar Ramachandra, Jeff King, John Szakmeister,
	Felipe Contreras

The upstream branch is:

  branch.$name.remote
  branch.$name.merge

The publish branch is:

  branch.$name.pushremote
  branch.$name.push

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 builtin/push.c | 19 +++++++++++++++----
 remote.c       | 34 ++++++++++++++++++++++++++++------
 remote.h       |  4 ++++
 3 files changed, 47 insertions(+), 10 deletions(-)

diff --git a/builtin/push.c b/builtin/push.c
index d10aefc..a1fdc49 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -192,6 +192,20 @@ static void setup_push_current(struct remote *remote, struct branch *branch)
 	add_refspec(branch->name);
 }
 
+static void setup_push_simple(struct remote *remote, struct branch *branch,
+		int triangular)
+{
+	if (branch->push_name) {
+		struct strbuf refspec = STRBUF_INIT;
+		strbuf_addf(&refspec, "%s:%s", branch->name, branch->push_name);
+		add_refspec(refspec.buf);
+	} else if (triangular) {
+		setup_push_current(remote, branch);
+	} else {
+		setup_push_upstream(remote, branch, triangular);
+	}
+}
+
 static char warn_unspecified_push_default_msg[] =
 N_("push.default is unset; its implicit value is changing in\n"
    "Git 2.0 from 'matching' to 'simple'. To squelch this message\n"
@@ -259,10 +273,7 @@ static void setup_default_push_refspecs(struct remote *remote)
 		break;
 
 	case PUSH_DEFAULT_SIMPLE:
-		if (triangular)
-			setup_push_current(remote, get_current_branch(remote));
-		else
-			setup_push_upstream(remote, get_current_branch(remote), triangular);
+		setup_push_simple(remote, get_current_branch(remote), triangular);
 		break;
 
 	case PUSH_DEFAULT_UPSTREAM:
diff --git a/remote.c b/remote.c
index 5f63d55..3437d1f 100644
--- a/remote.c
+++ b/remote.c
@@ -352,13 +352,17 @@ static int handle_config(const char *key, const char *value, void *cb)
 				explicit_default_remote_name = 1;
 			}
 		} else if (!strcmp(subkey, ".pushremote")) {
+			if (git_config_string(&branch->pushremote_name, key, value))
+				return -1;
 			if (branch == current_branch)
-				if (git_config_string(&branch_pushremote_name, key, value))
-					return -1;
+				branch_pushremote_name = xstrdup(branch->pushremote_name);
 		} else if (!strcmp(subkey, ".merge")) {
 			if (!value)
 				return config_error_nonbool(key);
 			add_merge(branch, xstrdup(value));
+		} else if (!strcmp(subkey, ".push")) {
+			if (git_config_string(&branch->push_name, key, value))
+				return -1;
 		}
 		return 0;
 	}
@@ -1562,6 +1566,14 @@ struct branch *branch_get(const char *name)
 			}
 		}
 	}
+	if (ret && ret->pushremote_name) {
+		struct remote *pushremote;
+		pushremote = pushremote_get(ret->pushremote_name);
+		ret->push.src = xstrdup(ret->push_name);
+		if (remote_find_tracking(pushremote, &ret->push)
+		    && !strcmp(ret->pushremote_name, "."))
+			ret->push.dst = xstrdup(ret->push_name);
+	}
 	return ret;
 }
 
@@ -1771,6 +1783,15 @@ int ref_newer(const unsigned char *new_sha1, const unsigned char *old_sha1)
 	return found;
 }
 
+static char *get_base(struct branch *branch)
+{
+	if (branch->push.dst)
+		return branch->push.dst;
+	if (branch->merge && branch->merge[0] && branch->merge[0]->dst)
+		return branch->merge[0]->dst;
+	return NULL;
+}
+
 /*
  * Compare a branch with its upstream, and save their differences (number
  * of commits) in *num_ours and *num_theirs.
@@ -1788,12 +1809,13 @@ int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs)
 	int rev_argc;
 
 	/* Cannot stat unless we are marked to build on top of somebody else. */
-	if (!branch ||
-	    !branch->merge || !branch->merge[0] || !branch->merge[0]->dst)
+	if (!branch)
+		return 0;
+	base = get_base(branch);
+	if (!base)
 		return 0;
 
 	/* Cannot stat if what we used to build on no longer exists */
-	base = branch->merge[0]->dst;
 	if (read_ref(base, sha1))
 		return -1;
 	theirs = lookup_commit_reference(sha1);
@@ -1869,7 +1891,7 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb)
 		break;
 	}
 
-	base = branch->merge[0]->dst;
+	base = get_base(branch);
 	base = shorten_unambiguous_ref(base, 0);
 	if (upstream_is_gone) {
 		strbuf_addf(sb,
diff --git a/remote.h b/remote.h
index fb7647f..08e93c4 100644
--- a/remote.h
+++ b/remote.h
@@ -204,6 +204,10 @@ struct branch {
 	struct refspec **merge;
 	int merge_nr;
 	int merge_alloc;
+
+	const char *pushremote_name;
+	const char *push_name;
+	struct refspec push;
 };
 
 struct branch *branch_get(const char *name);
-- 
1.9.1+fc1

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH v2 3/9] branch: allow configuring the publish branch
  2014-04-10 19:04 [PATCH v2 0/9] Introduce publish tracking branch Felipe Contreras
  2014-04-10 19:04 ` [PATCH v2 1/9] push: trivial reorganization Felipe Contreras
  2014-04-10 19:04 ` [PATCH v2 2/9] Add concept of 'publish' branch Felipe Contreras
@ 2014-04-10 19:04 ` Felipe Contreras
  2014-04-10 19:04 ` [PATCH v2 4/9] t: branch add publish branch tests Felipe Contreras
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 34+ messages in thread
From: Felipe Contreras @ 2014-04-10 19:04 UTC (permalink / raw)
  To: git
  Cc: Matthieu Moy, Ramkumar Ramachandra, Jeff King, John Szakmeister,
	Felipe Contreras

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 Documentation/git-branch.txt | 11 +++++++++
 branch.c                     | 43 +++++++++++++++++++++++++++++++++
 branch.h                     |  2 ++
 builtin/branch.c             | 57 ++++++++++++++++++++++++++++++++++++++++----
 4 files changed, 108 insertions(+), 5 deletions(-)

diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index 311b336..914fd62 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -14,7 +14,9 @@ SYNOPSIS
 	[(--merged | --no-merged | --contains) [<commit>]] [<pattern>...]
 'git branch' [--set-upstream | --track | --no-track] [-l] [-f] <branchname> [<start-point>]
 'git branch' (--set-upstream-to=<upstream> | -u <upstream>) [<branchname>]
+'git branch' (--set-publish-to=<publish> | -p <publish>) [<branchname>]
 'git branch' --unset-upstream [<branchname>]
+'git branch' --unset-publish [<branchname>]
 'git branch' (-m | -M) [<oldbranch>] <newbranch>
 'git branch' (-d | -D) [-r] <branchname>...
 'git branch' --edit-description [<branchname>]
@@ -191,6 +193,15 @@ start-point is either a local or remote-tracking branch.
 	Remove the upstream information for <branchname>. If no branch
 	is specified it defaults to the current branch.
 
+-p <publish>::
+--set-publish-to=<publish>::
+	Set up <branchname>'s publish tracking information. If no
+	<branchname> is specified, then it defaults to the current branch.
+
+--unset-publish::
+	Remove the publish information for <branchname>. If no branch
+	is specified it defaults to the current branch.
+
 --edit-description::
 	Open an editor and edit the text to explain what the branch is
 	for, to be used by various other commands (e.g. `request-pull`).
diff --git a/branch.c b/branch.c
index 723a36b..6f4fe7f 100644
--- a/branch.c
+++ b/branch.c
@@ -144,6 +144,49 @@ static int setup_tracking(const char *new_ref, const char *orig_ref,
 	return 0;
 }
 
+void install_branch_publish(const char *name, const char *remote, const char *remote_ref)
+{
+	struct strbuf key = STRBUF_INIT;
+
+	if (!remote && !strcmp(name, remote_ref + 11) && !prefixcmp(remote_ref, "refs/heads")) {
+		warning(_("Not setting branch %s as its own publish branch."), name);
+		return;
+	}
+
+	strbuf_addf(&key, "branch.%s.pushremote", name);
+	git_config_set(key.buf, remote ? remote : ".");
+
+	strbuf_reset(&key);
+	strbuf_addf(&key, "branch.%s.push", name);
+	git_config_set(key.buf, remote_ref);
+
+	strbuf_release(&key);
+}
+
+int setup_publish(const char *name, const char *ref)
+{
+	struct tracking tracking;
+	const char *remote, *remote_ref;
+
+	memset(&tracking, 0, sizeof(tracking));
+	tracking.spec.dst = (char*)ref;
+	if (for_each_remote(find_tracked_branch, &tracking))
+		return 1;
+
+	if (tracking.matches > 1)
+		return error(_("Not tracking: ambiguous information for ref %s"),
+				ref);
+
+	remote = tracking.remote;
+	remote_ref = tracking.src ? tracking.src : ref;
+
+	install_branch_publish(name, remote, remote_ref);
+
+	free(tracking.src);
+
+	return 0;
+}
+
 struct branch_desc_cb {
 	const char *config_name;
 	const char *value;
diff --git a/branch.h b/branch.h
index 64173ab..c9b6aa9 100644
--- a/branch.h
+++ b/branch.h
@@ -51,5 +51,7 @@ extern void install_branch_config(int flag, const char *local, const char *origi
  * Read branch description
  */
 extern int read_branch_desc(struct strbuf *, const char *branch_name);
+extern int setup_publish(const char *name, const char *ref);
+extern void install_branch_publish(const char *name, const char *remote, const char *remote_ref);
 
 #endif
diff --git a/builtin/branch.c b/builtin/branch.c
index b4d7716..17773d7 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -793,8 +793,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 	int delete = 0, rename = 0, force_create = 0, list = 0;
 	int verbose = 0, abbrev = -1, detached = 0;
 	int reflog = 0, edit_description = 0;
-	int quiet = 0, unset_upstream = 0;
-	const char *new_upstream = NULL;
+	int quiet = 0, unset_upstream = 0, unset_publish = 0;
+	const char *new_upstream = NULL, *publish = NULL;
 	enum branch_track track;
 	int kinds = REF_LOCAL_BRANCH;
 	struct commit_list *with_commit = NULL;
@@ -809,7 +809,9 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 		OPT_SET_INT( 0, "set-upstream",  &track, N_("change upstream info"),
 			BRANCH_TRACK_OVERRIDE),
 		OPT_STRING('u', "set-upstream-to", &new_upstream, "upstream", "change the upstream info"),
+		OPT_STRING('p', "set-publish-to", &publish, "publish", "change the publish info"),
 		OPT_BOOL(0, "unset-upstream", &unset_upstream, "Unset the upstream info"),
+		OPT_BOOL(0, "unset-publish", &unset_publish, "Unset the publish info"),
 		OPT__COLOR(&branch_use_color, N_("use colored output")),
 		OPT_SET_INT('r', "remotes",     &kinds, N_("act on remote-tracking branches"),
 			REF_REMOTE_BRANCH),
@@ -878,14 +880,15 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 	argc = parse_options(argc, argv, prefix, options, builtin_branch_usage,
 			     0);
 
-	if (!delete && !rename && !edit_description && !new_upstream && !unset_upstream && argc == 0)
+	if (!delete && !rename && !edit_description && !new_upstream && !publish &&
+	    !unset_upstream && !unset_publish && argc == 0)
 		list = 1;
 
 	if (with_commit || merge_filter != NO_FILTER)
 		list = 1;
 
-	if (!!delete + !!rename + !!force_create + !!new_upstream +
-	    list + unset_upstream > 1)
+	if (!!delete + !!rename + !!force_create + !!new_upstream + !!publish +
+	    list + unset_upstream + unset_publish > 1)
 		usage_with_options(builtin_branch_usage, options);
 
 	if (abbrev == -1)
@@ -990,6 +993,50 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 		strbuf_addf(&buf, "branch.%s.merge", branch->name);
 		git_config_set_multivar(buf.buf, NULL, NULL, 1);
 		strbuf_release(&buf);
+	} else if (publish) {
+		struct branch *branch = branch_get(argv[0]);
+		char *real_ref = NULL;
+		unsigned char sha1[20];
+
+		if (argc > 1)
+			die(_("too many branches to set new publish branch"));
+
+		if (!branch) {
+			if (!argc || !strcmp(argv[0], "HEAD"))
+				die(_("could not set publish branch of HEAD when "
+				      "it does not point to any branch."));
+			die(_("no such branch '%s'"), argv[0]);
+		}
+
+		if (!ref_exists(branch->refname))
+			die(_("branch '%s' does not exist"), branch->name);
+
+		if (dwim_ref(publish, strlen(publish), sha1, &real_ref) != 1 ||
+				setup_publish(branch->name, real_ref))
+			die(_("Cannot setup publish branch to '%s'."), publish);
+	} else if (unset_publish) {
+		struct branch *branch = branch_get(argv[0]);
+		struct strbuf buf = STRBUF_INIT;
+
+		if (argc > 1)
+			die(_("too many branches to unset publish branch"));
+
+		if (!branch) {
+			if (!argc || !strcmp(argv[0], "HEAD"))
+				die(_("could not unset publish branch of HEAD when "
+				      "it does not point to any branch."));
+			die(_("no such branch '%s'"), argv[0]);
+		}
+
+		if (!branch->push_name)
+			die(_("Branch '%s' has no publish information"), branch->name);
+
+		strbuf_addf(&buf, "branch.%s.pushremote", branch->name);
+		git_config_set_multivar(buf.buf, NULL, NULL, 1);
+		strbuf_reset(&buf);
+		strbuf_addf(&buf, "branch.%s.push", branch->name);
+		git_config_set_multivar(buf.buf, NULL, NULL, 1);
+		strbuf_release(&buf);
 	} else if (argc > 0 && argc <= 2) {
 		struct branch *branch = branch_get(argv[0]);
 		int branch_existed = 0, remote_tracking = 0;
-- 
1.9.1+fc1

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH v2 4/9] t: branch add publish branch tests
  2014-04-10 19:04 [PATCH v2 0/9] Introduce publish tracking branch Felipe Contreras
                   ` (2 preceding siblings ...)
  2014-04-10 19:04 ` [PATCH v2 3/9] branch: allow configuring the publish branch Felipe Contreras
@ 2014-04-10 19:04 ` Felipe Contreras
  2014-04-10 19:04 ` [PATCH v2 5/9] push: add --set-publish option Felipe Contreras
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 34+ messages in thread
From: Felipe Contreras @ 2014-04-10 19:04 UTC (permalink / raw)
  To: git
  Cc: Matthieu Moy, Ramkumar Ramachandra, Jeff King, John Szakmeister,
	Felipe Contreras

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 t/t3200-branch.sh | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 76 insertions(+)

diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index fcdb867..8cd21d1 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -907,4 +907,80 @@ test_expect_success 'tracking with unexpected .fetch refspec' '
 	)
 '
 
+test_expect_success '--set-publish-to fails on multiple branches' '
+	test_must_fail git branch --set-publish-to master a b c
+'
+
+test_expect_success '--set-publish-to fails on detached HEAD' '
+	test_when_finished "git checkout master" &&
+	git checkout master^{} &&
+	test_must_fail git branch --set-publish-to master
+'
+
+test_expect_success '--set-publish-to fails on a missing dst branch' '
+	test_must_fail git branch --set-publish-to master does-not-exist
+'
+
+test_expect_success '--set-publish-to fails on a missing src branch' '
+	test_must_fail git branch --set-publish-to does-not-exist master
+'
+
+test_expect_success '--set-publish-to fails on a non-ref' '
+	test_must_fail git branch --set-publish-to HEAD^{}
+'
+
+test_expect_success 'use --set-publish-to modify HEAD' '
+	git checkout master &&
+	test_config branch.master.pushremote foo &&
+	test_config branch.master.push foo &&
+	git branch -f test &&
+	git branch --set-publish-to test &&
+	test "$(git config branch.master.pushremote)" = "." &&
+	test "$(git config branch.master.push)" = "refs/heads/test"
+'
+
+test_expect_success 'use --set-publish-to modify a particular branch' '
+	git branch -f test &&
+	git branch -f test2 &&
+	git branch --set-publish-to test2 test &&
+	test "$(git config branch.test.pushremote)" = "." &&
+	test "$(git config branch.test.push)" = "refs/heads/test2"
+'
+
+test_expect_success '--unset-publish should fail if given a non-existent branch' '
+	test_must_fail git branch --unset-publish i-dont-exist
+'
+
+test_expect_success 'test --unset-publish on HEAD' '
+	git checkout master &&
+	git branch -f test &&
+	test_config branch.master.pushremote foo &&
+	test_config branch.master.push foo &&
+	git branch --set-publish-to test &&
+	git branch --unset-publish &&
+	test_must_fail git config branch.master.pushremote &&
+	test_must_fail git config branch.master.push &&
+	# fail for a branch without publish set
+	test_must_fail git branch --unset-publish
+'
+
+test_expect_success '--unset-publish should fail on multiple branches' '
+	test_must_fail git branch --unset-publish a b c
+'
+
+test_expect_success '--unset-publish should fail on detached HEAD' '
+	test_when_finished "git checkout -" &&
+	git checkout HEAD^{} &&
+	test_must_fail git branch --unset-publish
+'
+
+test_expect_success 'test --unset-publish on a particular branch' '
+	git branch -f test &&
+	git branch -f test2 &&
+	git branch --set-publish-to test2 test &&
+	git branch --unset-publish test &&
+	test_must_fail git config branch.test2.pushremote &&
+	test_must_fail git config branch.test2.push
+'
+
 test_done
-- 
1.9.1+fc1

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH v2 5/9] push: add --set-publish option
  2014-04-10 19:04 [PATCH v2 0/9] Introduce publish tracking branch Felipe Contreras
                   ` (3 preceding siblings ...)
  2014-04-10 19:04 ` [PATCH v2 4/9] t: branch add publish branch tests Felipe Contreras
@ 2014-04-10 19:04 ` Felipe Contreras
  2014-04-10 19:04 ` [PATCH v2 6/9] branch: display publish branch Felipe Contreras
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 34+ messages in thread
From: Felipe Contreras @ 2014-04-10 19:04 UTC (permalink / raw)
  To: git
  Cc: Matthieu Moy, Ramkumar Ramachandra, Jeff King, John Szakmeister,
	Felipe Contreras

To setup publish tracking branch, like 'git branch --set-publish'.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 Documentation/git-push.txt |  9 +++++-
 builtin/push.c             |  2 ++
 t/t5529-push-publish.sh    | 70 ++++++++++++++++++++++++++++++++++++++++++++++
 transport.c                | 28 +++++++++++++------
 transport.h                |  1 +
 5 files changed, 100 insertions(+), 10 deletions(-)
 create mode 100755 t/t5529-push-publish.sh

diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index 2b7f4f9..bf6ff9c 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -10,7 +10,8 @@ SYNOPSIS
 --------
 [verse]
 'git push' [--all | --mirror | --tags] [--follow-tags] [-n | --dry-run] [--receive-pack=<git-receive-pack>]
-	   [--repo=<repository>] [-f | --force] [--prune] [-v | --verbose] [-u | --set-upstream]
+	   [--repo=<repository>] [-f | --force] [--prune] [-v | --verbose]
+	   [-u | --set-upstream] [-p | --set-publish]
 	   [--force-with-lease[=<refname>[:<expect>]]]
 	   [--no-verify] [<repository> [<refspec>...]]
 
@@ -231,6 +232,12 @@ useful if you write an alias or script around 'git push'.
 	linkgit:git-pull[1] and other commands. For more information,
 	see 'branch.<name>.merge' in linkgit:git-config[1].
 
+-p::
+--set-publish::
+	For every branch that is up to date or successfully pushed, add
+	publish branch tracking reference, used by argument-less
+	linkgit:git-pull[1] and other commands.
+
 --[no-]thin::
 	These options are passed to linkgit:git-send-pack[1]. A thin transfer
 	significantly reduces the amount of sent data when the sender and
diff --git a/builtin/push.c b/builtin/push.c
index a1fdc49..9e61b8f 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -532,6 +532,8 @@ int cmd_push(int argc, const char **argv, const char *prefix)
 		OPT_STRING( 0 , "exec", &receivepack, "receive-pack", N_("receive pack program")),
 		OPT_BIT('u', "set-upstream", &flags, N_("set upstream for git pull/status"),
 			TRANSPORT_PUSH_SET_UPSTREAM),
+		OPT_BIT('p', "set-publish", &flags, N_("set publish for git pull/status"),
+			TRANSPORT_PUSH_SET_PUBLISH),
 		OPT_BOOL(0, "progress", &progress, N_("force progress reporting")),
 		OPT_BIT(0, "prune", &flags, N_("prune locally removed refs"),
 			TRANSPORT_PUSH_PRUNE),
diff --git a/t/t5529-push-publish.sh b/t/t5529-push-publish.sh
new file mode 100755
index 0000000..2037026
--- /dev/null
+++ b/t/t5529-push-publish.sh
@@ -0,0 +1,70 @@
+#!/bin/sh
+
+test_description='push with --set-publish'
+
+. ./test-lib.sh
+
+test_expect_success 'setup bare parent' '
+	git init --bare parent &&
+	git remote add publish parent
+'
+
+test_expect_success 'setup local commit' '
+	echo content >file &&
+	git add file &&
+	git commit -m one
+'
+
+check_config() {
+	(echo $2; echo $3) >expect.$1
+	(git config branch.$1.pushremote
+	 git config branch.$1.push) >actual.$1
+	test_cmp expect.$1 actual.$1
+}
+
+test_expect_success 'push -p master:master' '
+	git push -p publish master:master &&
+	check_config master publish refs/heads/master
+'
+
+test_expect_success 'push -u master:other' '
+	git push -p publish master:other &&
+	check_config master publish refs/heads/other
+'
+
+test_expect_success 'push -p --dry-run master:otherX' '
+	git push -p --dry-run publish master:otherX &&
+	check_config master publish refs/heads/other
+'
+
+test_expect_success 'push -p master2:master2' '
+	git branch master2 &&
+	git push -p publish master2:master2 &&
+	check_config master2 publish refs/heads/master2
+'
+
+test_expect_success 'push -p master2:other2' '
+	git push -p publish master2:other2 &&
+	check_config master2 publish refs/heads/other2
+'
+
+test_expect_success 'push -p :master2' '
+	git push -p publish :master2 &&
+	check_config master2 publish refs/heads/other2
+'
+
+test_expect_success 'push -u --all' '
+	git branch all1 &&
+	git branch all2 &&
+	git push -p --all &&
+	check_config all1 publish refs/heads/all1 &&
+	check_config all2 publish refs/heads/all2
+'
+
+test_expect_success 'push -p HEAD' '
+	git checkout -b headbranch &&
+	git push -p publish HEAD &&
+	check_config headbranch publish refs/heads/headbranch
+'
+
+test_done
diff --git a/transport.c b/transport.c
index ca7bb44..dfcddfe 100644
--- a/transport.c
+++ b/transport.c
@@ -143,8 +143,8 @@ static void insert_packed_refs(const char *packed_refs, struct ref **list)
 	}
 }
 
-static void set_upstreams(struct transport *transport, struct ref *refs,
-	int pretend)
+static void set_tracking(struct transport *transport, struct ref *refs,
+	int pretend, int publish)
 {
 	struct ref *ref;
 	for (ref = refs; ref; ref = ref->next) {
@@ -179,12 +179,18 @@ static void set_upstreams(struct transport *transport, struct ref *refs,
 		if (!remotename || !starts_with(remotename, "refs/heads/"))
 			continue;
 
-		if (!pretend)
-			install_branch_config(BRANCH_CONFIG_VERBOSE,
-				localname + 11, transport->remote->name,
-				remotename);
-		else
-			printf("Would set upstream of '%s' to '%s' of '%s'\n",
+		if (!pretend) {
+			if (publish)
+				install_branch_publish(localname + 11,
+						transport->remote->name,
+						remotename);
+			else
+				install_branch_config(BRANCH_CONFIG_VERBOSE,
+						localname + 11, transport->remote->name,
+						remotename);
+		} else
+			printf("Would set %s of '%s' to '%s' of '%s'\n",
+				publish ? "publish" : "upstream",
 				localname + 11, remotename + 11,
 				transport->remote->name);
 	}
@@ -1129,6 +1135,8 @@ int transport_push(struct transport *transport,
 		/* Maybe FIXME. But no important transport uses this case. */
 		if (flags & TRANSPORT_PUSH_SET_UPSTREAM)
 			die("This transport does not support using --set-upstream");
+		if (flags & TRANSPORT_PUSH_SET_PUBLISH)
+			die("This transport does not support using --set-publish");
 
 		return transport->push(transport, refspec_nr, refspec, flags);
 	} else if (transport->push_refs) {
@@ -1203,7 +1211,9 @@ int transport_push(struct transport *transport,
 					reject_reasons);
 
 		if (flags & TRANSPORT_PUSH_SET_UPSTREAM)
-			set_upstreams(transport, remote_refs, pretend);
+			set_tracking(transport, remote_refs, pretend, 0);
+		if (flags & TRANSPORT_PUSH_SET_PUBLISH)
+			set_tracking(transport, remote_refs, pretend, 1);
 
 		if (!(flags & TRANSPORT_PUSH_DRY_RUN)) {
 			struct ref *ref;
diff --git a/transport.h b/transport.h
index 02ea248..324997c 100644
--- a/transport.h
+++ b/transport.h
@@ -123,6 +123,7 @@ struct transport {
 #define TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND 256
 #define TRANSPORT_PUSH_NO_HOOK 512
 #define TRANSPORT_PUSH_FOLLOW_TAGS 1024
+#define TRANSPORT_PUSH_SET_PUBLISH 2048
 
 #define TRANSPORT_SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3)
 #define TRANSPORT_SUMMARY(x) (int)(TRANSPORT_SUMMARY_WIDTH + strlen(x) - gettext_width(x)), (x)
-- 
1.9.1+fc1

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH v2 6/9] branch: display publish branch
  2014-04-10 19:04 [PATCH v2 0/9] Introduce publish tracking branch Felipe Contreras
                   ` (4 preceding siblings ...)
  2014-04-10 19:04 ` [PATCH v2 5/9] push: add --set-publish option Felipe Contreras
@ 2014-04-10 19:04 ` Felipe Contreras
  2014-04-10 22:03   ` Ramkumar Ramachandra
  2014-04-10 19:04 ` [PATCH v2 7/9] sha1_name: cleanup interpret_branch_name() Felipe Contreras
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 34+ messages in thread
From: Felipe Contreras @ 2014-04-10 19:04 UTC (permalink / raw)
  To: git
  Cc: Matthieu Moy, Ramkumar Ramachandra, Jeff King, John Szakmeister,
	Felipe Contreras

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 builtin/branch.c         | 17 ++++++++++++++++-
 t/t6040-tracking-info.sh |  5 +++--
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/builtin/branch.c b/builtin/branch.c
index 17773d7..e0a8d0a 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -42,6 +42,7 @@ static char branch_colors[][COLOR_MAXLEN] = {
 	GIT_COLOR_NORMAL,	/* LOCAL */
 	GIT_COLOR_GREEN,	/* CURRENT */
 	GIT_COLOR_BLUE,		/* UPSTREAM */
+	GIT_COLOR_YELLOW,	/* PUBLISH */
 };
 enum color_branch {
 	BRANCH_COLOR_RESET = 0,
@@ -49,7 +50,8 @@ enum color_branch {
 	BRANCH_COLOR_REMOTE = 2,
 	BRANCH_COLOR_LOCAL = 3,
 	BRANCH_COLOR_CURRENT = 4,
-	BRANCH_COLOR_UPSTREAM = 5
+	BRANCH_COLOR_UPSTREAM = 5,
+	BRANCH_COLOR_PUBLISH = 6
 };
 
 static enum merge_filter {
@@ -76,6 +78,8 @@ static int parse_branch_color_slot(const char *var, int ofs)
 		return BRANCH_COLOR_CURRENT;
 	if (!strcasecmp(var+ofs, "upstream"))
 		return BRANCH_COLOR_UPSTREAM;
+	if (!strcasecmp(var+ofs, "publish"))
+		return BRANCH_COLOR_PUBLISH;
 	return -1;
 }
 
@@ -448,6 +452,17 @@ static void fill_tracking_info(struct strbuf *stat, const char *branch_name,
 		else
 			strbuf_addstr(&fancy, ref);
 	}
+	if (branch->push.dst) {
+		ref = shorten_unambiguous_ref(branch->push.dst, 0);
+		if (fancy.len)
+			strbuf_addstr(&fancy, ", ");
+		if (want_color(branch_use_color))
+			strbuf_addf(&fancy, "%s%s%s",
+					branch_get_color(BRANCH_COLOR_PUBLISH),
+					ref, branch_get_color(BRANCH_COLOR_RESET));
+		else
+			strbuf_addstr(&fancy, ref);
+	}
 
 	if (upstream_is_gone) {
 		if (show_upstream_ref)
diff --git a/t/t6040-tracking-info.sh b/t/t6040-tracking-info.sh
index 7ac8fd0..8b9ef63 100755
--- a/t/t6040-tracking-info.sh
+++ b/t/t6040-tracking-info.sh
@@ -33,7 +33,8 @@ test_expect_success setup '
 		git checkout -b b5 --track brokenbase &&
 		advance g &&
 		git branch -d brokenbase &&
-		git checkout -b b6 origin
+		git checkout -b b6 origin &&
+		git branch --set-publish origin/master b6
 	) &&
 	git checkout -b follower --track master &&
 	advance h
@@ -64,7 +65,7 @@ b2 [origin/master: ahead 1, behind 1] d
 b3 [origin/master: behind 1] b
 b4 [origin/master: ahead 2] f
 b5 [brokenbase: gone] g
-b6 [origin/master] c
+b6 [origin/master, origin/master] c
 EOF
 
 test_expect_success 'branch -vv' '
-- 
1.9.1+fc1

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH v2 7/9] sha1_name: cleanup interpret_branch_name()
  2014-04-10 19:04 [PATCH v2 0/9] Introduce publish tracking branch Felipe Contreras
                   ` (5 preceding siblings ...)
  2014-04-10 19:04 ` [PATCH v2 6/9] branch: display publish branch Felipe Contreras
@ 2014-04-10 19:04 ` Felipe Contreras
  2014-04-10 21:45   ` Ramkumar Ramachandra
  2014-04-10 19:04 ` [PATCH v2 8/9] sha1_name: simplify track finding Felipe Contreras
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 34+ messages in thread
From: Felipe Contreras @ 2014-04-10 19:04 UTC (permalink / raw)
  To: git
  Cc: Matthieu Moy, Ramkumar Ramachandra, Jeff King, John Szakmeister,
	Felipe Contreras

The 'upstream' variable doesn't hold an "upstream", but a branch, so
make it clearer.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 sha1_name.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/sha1_name.c b/sha1_name.c
index 6fca869..906f09d 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -1057,31 +1057,31 @@ static void set_shortened_ref(struct strbuf *buf, const char *ref)
 	free(s);
 }
 
-static const char *get_upstream_branch(const char *branch_buf, int len)
+static const char *get_upstream_branch(const char *name_buf, int len)
 {
-	char *branch = xstrndup(branch_buf, len);
-	struct branch *upstream = branch_get(*branch ? branch : NULL);
+	char *name = xstrndup(name_buf, len);
+	struct branch *branch = branch_get(*name ? name : NULL);
 
 	/*
 	 * Upstream can be NULL only if branch refers to HEAD and HEAD
 	 * points to something different than a branch.
 	 */
-	if (!upstream)
+	if (!branch)
 		die(_("HEAD does not point to a branch"));
-	if (!upstream->merge || !upstream->merge[0]->dst) {
-		if (!ref_exists(upstream->refname))
-			die(_("No such branch: '%s'"), branch);
-		if (!upstream->merge) {
+	if (!branch->merge || !branch->merge[0]->dst) {
+		if (!ref_exists(branch->refname))
+			die(_("No such branch: '%s'"), name);
+		if (!branch->merge) {
 			die(_("No upstream configured for branch '%s'"),
-				upstream->name);
+				branch->name);
 		}
 		die(
 			_("Upstream branch '%s' not stored as a remote-tracking branch"),
-			upstream->merge[0]->src);
+			branch->merge[0]->src);
 	}
-	free(branch);
+	free(name);
 
-	return upstream->merge[0]->dst;
+	return branch->merge[0]->dst;
 }
 
 static int interpret_upstream_mark(const char *name, int namelen,
-- 
1.9.1+fc1

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH v2 8/9] sha1_name: simplify track finding
  2014-04-10 19:04 [PATCH v2 0/9] Introduce publish tracking branch Felipe Contreras
                   ` (6 preceding siblings ...)
  2014-04-10 19:04 ` [PATCH v2 7/9] sha1_name: cleanup interpret_branch_name() Felipe Contreras
@ 2014-04-10 19:04 ` Felipe Contreras
  2014-04-10 21:44   ` Ramkumar Ramachandra
  2014-04-10 19:04 ` [PATCH v2 9/9] sha1_name: add support for @{publish} marks Felipe Contreras
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 34+ messages in thread
From: Felipe Contreras @ 2014-04-10 19:04 UTC (permalink / raw)
  To: git
  Cc: Matthieu Moy, Ramkumar Ramachandra, Jeff King, John Szakmeister,
	Felipe Contreras

It's more efficient to check for the braces first.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 sha1_name.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/sha1_name.c b/sha1_name.c
index 906f09d..aa3f3e0 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -417,7 +417,7 @@ static int ambiguous_path(const char *path, int len)
 
 static inline int upstream_mark(const char *string, int len)
 {
-	const char *suffix[] = { "@{upstream}", "@{u}" };
+	const char *suffix[] = { "upstream", "u" };
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(suffix); i++) {
@@ -475,7 +475,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
 					nth_prior = 1;
 					continue;
 				}
-				if (!upstream_mark(str + at, len - at)) {
+				if (!upstream_mark(str + at + 2, len - at - 3)) {
 					reflog_len = (len-1) - (at+2);
 					len = at;
 				}
@@ -1089,7 +1089,10 @@ static int interpret_upstream_mark(const char *name, int namelen,
 {
 	int len;
 
-	len = upstream_mark(name + at, namelen - at);
+	if (name[at + 1] != '{' || name[namelen - 1] != '}')
+		return -1;
+
+	len = upstream_mark(name + at + 2, namelen - at - 3);
 	if (!len)
 		return -1;
 
@@ -1097,7 +1100,7 @@ static int interpret_upstream_mark(const char *name, int namelen,
 		return -1;
 
 	set_shortened_ref(buf, get_upstream_branch(name, at));
-	return len + at;
+	return len + at + 3;
 }
 
 /*
-- 
1.9.1+fc1

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* [PATCH v2 9/9] sha1_name: add support for @{publish} marks
  2014-04-10 19:04 [PATCH v2 0/9] Introduce publish tracking branch Felipe Contreras
                   ` (7 preceding siblings ...)
  2014-04-10 19:04 ` [PATCH v2 8/9] sha1_name: simplify track finding Felipe Contreras
@ 2014-04-10 19:04 ` Felipe Contreras
  2014-04-10 21:40   ` Ramkumar Ramachandra
  2014-04-10 21:49   ` Ramkumar Ramachandra
  2014-04-10 21:21 ` [PATCH v2 0/9] Introduce publish tracking branch Junio C Hamano
  2014-04-11  9:15 ` Matthieu Moy
  10 siblings, 2 replies; 34+ messages in thread
From: Felipe Contreras @ 2014-04-10 19:04 UTC (permalink / raw)
  To: git
  Cc: Matthieu Moy, Ramkumar Ramachandra, Jeff King, John Szakmeister,
	Felipe Contreras

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 Documentation/revisions.txt |  4 ++++
 sha1_name.c                 | 49 ++++++++++++++++++++++++++++-----------------
 t/t1508-at-combinations.sh  |  5 +++++
 3 files changed, 40 insertions(+), 18 deletions(-)

diff --git a/Documentation/revisions.txt b/Documentation/revisions.txt
index 5a286d0..fd01cb4 100644
--- a/Documentation/revisions.txt
+++ b/Documentation/revisions.txt
@@ -96,6 +96,10 @@ some output processing may assume ref names in UTF-8.
   refers to the branch that the branch specified by branchname is set to build on
   top of.  A missing branchname defaults to the current one.
 
+'<branchname>@\{publish\}', e.g. 'master@\{publish\}', '@\{p\}'::
+  The suffix '@\{publish\}' to a branchname refers to the remote branch to
+  push to. A missing branchname defaults to the current one.
+
 '<rev>{caret}', e.g. 'HEAD{caret}, v1.5.1{caret}0'::
   A suffix '{caret}' to a revision parameter means the first parent of
   that commit object.  '{caret}<n>' means the <n>th parent (i.e.
diff --git a/sha1_name.c b/sha1_name.c
index aa3f3e0..a36852d 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -415,9 +415,9 @@ static int ambiguous_path(const char *path, int len)
 	return slash;
 }
 
-static inline int upstream_mark(const char *string, int len)
+static inline int tracking_mark(const char *string, int len)
 {
-	const char *suffix[] = { "upstream", "u" };
+	const char *suffix[] = { "upstream", "u", "publish", "p" };
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(suffix); i++) {
@@ -475,7 +475,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
 					nth_prior = 1;
 					continue;
 				}
-				if (!upstream_mark(str + at + 2, len - at - 3)) {
+				if (!tracking_mark(str + at + 2, len - at - 3)) {
 					reflog_len = (len-1) - (at+2);
 					len = at;
 				}
@@ -1057,10 +1057,11 @@ static void set_shortened_ref(struct strbuf *buf, const char *ref)
 	free(s);
 }
 
-static const char *get_upstream_branch(const char *name_buf, int len)
+static const char *get_tracking_branch(const char *name_buf, int len, char type)
 {
 	char *name = xstrndup(name_buf, len);
 	struct branch *branch = branch_get(*name ? name : NULL);
+	char *tracking = NULL;
 
 	/*
 	 * Upstream can be NULL only if branch refers to HEAD and HEAD
@@ -1068,23 +1069,35 @@ static const char *get_upstream_branch(const char *name_buf, int len)
 	 */
 	if (!branch)
 		die(_("HEAD does not point to a branch"));
-	if (!branch->merge || !branch->merge[0]->dst) {
-		if (!ref_exists(branch->refname))
-			die(_("No such branch: '%s'"), name);
-		if (!branch->merge) {
-			die(_("No upstream configured for branch '%s'"),
-				branch->name);
+	switch (type) {
+	case 'u':
+		if (!branch->merge || !branch->merge[0]->dst) {
+			if (!ref_exists(branch->refname))
+				die(_("No such branch: '%s'"), name);
+			if (!branch->merge) {
+				die(_("No upstream configured for branch '%s'"),
+					branch->name);
+			}
+			die(
+				_("Upstream branch '%s' not stored as a remote-tracking branch"),
+				branch->merge[0]->src);
+		}
+		tracking = branch->merge[0]->dst;
+		break;
+	case 'p':
+		if (!branch->push.dst) {
+			die(_("No publish configured for branch '%s'"),
+					branch->name);
 		}
-		die(
-			_("Upstream branch '%s' not stored as a remote-tracking branch"),
-			branch->merge[0]->src);
+		tracking = branch->push.dst;
+		break;
 	}
 	free(name);
 
-	return branch->merge[0]->dst;
+	return tracking;
 }
 
-static int interpret_upstream_mark(const char *name, int namelen,
+static int interpret_tracking_mark(const char *name, int namelen,
 				   int at, struct strbuf *buf)
 {
 	int len;
@@ -1092,14 +1105,14 @@ static int interpret_upstream_mark(const char *name, int namelen,
 	if (name[at + 1] != '{' || name[namelen - 1] != '}')
 		return -1;
 
-	len = upstream_mark(name + at + 2, namelen - at - 3);
+	len = tracking_mark(name + at + 2, namelen - at - 3);
 	if (!len)
 		return -1;
 
 	if (memchr(name, ':', at))
 		return -1;
 
-	set_shortened_ref(buf, get_upstream_branch(name, at));
+	set_shortened_ref(buf, get_tracking_branch(name, at, name[at + 2]));
 	return len + at + 3;
 }
 
@@ -1150,7 +1163,7 @@ int interpret_branch_name(const char *name, int namelen, struct strbuf *buf)
 		if (len > 0)
 			return reinterpret(name, namelen, len, buf);
 
-		len = interpret_upstream_mark(name, namelen, at - name, buf);
+		len = interpret_tracking_mark(name, namelen, at - name, buf);
 		if (len > 0)
 			return len;
 	}
diff --git a/t/t1508-at-combinations.sh b/t/t1508-at-combinations.sh
index 078e119..f67aab3 100755
--- a/t/t1508-at-combinations.sh
+++ b/t/t1508-at-combinations.sh
@@ -32,6 +32,7 @@ fail() {
 test_expect_success 'setup' '
 	test_commit master-one &&
 	test_commit master-two &&
+	git checkout -b publish-branch &&
 	git checkout -b upstream-branch &&
 	test_commit upstream-one &&
 	test_commit upstream-two &&
@@ -46,6 +47,7 @@ test_expect_success 'setup' '
 	test_commit new-two &&
 	git branch -u master old-branch &&
 	git branch -u upstream-branch new-branch
+	git branch -p publish-branch new-branch
 '
 
 check HEAD ref refs/heads/new-branch
@@ -61,8 +63,11 @@ check "HEAD@{u}" ref refs/heads/upstream-branch
 check "@{u}@{1}" commit upstream-one
 check "@{-1}@{u}" ref refs/heads/master
 check "@{-1}@{u}@{1}" commit master-one
+check "@{p}" ref refs/heads/publish-branch
+check "HEAD@{p}" ref refs/heads/publish-branch
 check "@" commit new-two
 check "@@{u}" ref refs/heads/upstream-branch
+check "@@{p}" ref refs/heads/publish-branch
 check "@@/at-test" ref refs/heads/@@/at-test
 check "@/at-test" ref refs/heads/@/at-test
 check "@at-test" ref refs/heads/@at-test
-- 
1.9.1+fc1

^ permalink raw reply related	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 0/9] Introduce publish tracking branch
  2014-04-10 19:04 [PATCH v2 0/9] Introduce publish tracking branch Felipe Contreras
                   ` (8 preceding siblings ...)
  2014-04-10 19:04 ` [PATCH v2 9/9] sha1_name: add support for @{publish} marks Felipe Contreras
@ 2014-04-10 21:21 ` Junio C Hamano
  2014-04-11  9:15 ` Matthieu Moy
  10 siblings, 0 replies; 34+ messages in thread
From: Junio C Hamano @ 2014-04-10 21:21 UTC (permalink / raw)
  To: Felipe Contreras
  Cc: git, Matthieu Moy, Ramkumar Ramachandra, Jeff King, John Szakmeister

A handful of minimum tweaks [*1*] here and there were necessary in
order to queue the series on 'pu', but to me, the feature looked
like quite a straight-forward addition.

I'd be dropping the jk/branch-at-publish-rebased from 'pu', at least
tentatively, as that one was primarily Peff giving Ram a base to
build on top to achieve essentially the same thing as this series
does.  I didn't bother to check if this series could have reused
some from that series (primarily because I was short of time, had to
take the work laptop to service, etc. etc.) before doing so.

I didn't think too deeply about the workflow ramifications of this
series brings in, either---that is left for the reviewers Cc'ed on
the patches.


[Footnote]

*1* Things like these:

 - the context in builtin/push.c has already changed at the tip of
   'master' (we already pretend to be Git 2.0) and the patch text
   needed to be adjusted.

 - an instance of cast to "(char*)" fixed to "(char *)". 

 - t/t5529 is already used by other topics, renaming the new test to
   t/t5534-push-publish.sh.

 - !prefixcmp() is already removed for Git 2.0, replacing its use
   with starts_with().

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 9/9] sha1_name: add support for @{publish} marks
  2014-04-10 19:04 ` [PATCH v2 9/9] sha1_name: add support for @{publish} marks Felipe Contreras
@ 2014-04-10 21:40   ` Ramkumar Ramachandra
  2014-04-10 22:25     ` Felipe Contreras
  2014-04-10 21:49   ` Ramkumar Ramachandra
  1 sibling, 1 reply; 34+ messages in thread
From: Ramkumar Ramachandra @ 2014-04-10 21:40 UTC (permalink / raw)
  To: Felipe Contreras; +Cc: Git List, Matthieu Moy, Jeff King, John Szakmeister

Felipe Contreras wrote:
> @@ -1068,23 +1069,35 @@ static const char *get_upstream_branch(const char *name_buf, int len)
>          */
>         if (!branch)
>                 die(_("HEAD does not point to a branch"));
> -       if (!branch->merge || !branch->merge[0]->dst) {
> -               if (!ref_exists(branch->refname))
> -                       die(_("No such branch: '%s'"), name);
> -               if (!branch->merge) {
> -                       die(_("No upstream configured for branch '%s'"),
> -                               branch->name);
> +       switch (type) {
> +       case 'u':
> +               if (!branch->merge || !branch->merge[0]->dst) {
> +                       if (!ref_exists(branch->refname))
> +                               die(_("No such branch: '%s'"), name);
> +                       if (!branch->merge) {
> +                               die(_("No upstream configured for branch '%s'"),
> +                                       branch->name);
> +                       }
> +                       die(
> +                               _("Upstream branch '%s' not stored as a remote-tracking branch"),
> +                               branch->merge[0]->src);
> +               }
> +               tracking = branch->merge[0]->dst;
> +               break;
> +       case 'p':
> +               if (!branch->push.dst) {
> +                       die(_("No publish configured for branch '%s'"),
> +                                       branch->name);

This assumes a push.default value of 'current' or 'matching'. What
happens if push.default is set to 'nothing' or 'upstream', for
instance?

p.s- Good to see you back on the list :)

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 8/9] sha1_name: simplify track finding
  2014-04-10 19:04 ` [PATCH v2 8/9] sha1_name: simplify track finding Felipe Contreras
@ 2014-04-10 21:44   ` Ramkumar Ramachandra
  2014-04-10 22:27     ` Felipe Contreras
  0 siblings, 1 reply; 34+ messages in thread
From: Ramkumar Ramachandra @ 2014-04-10 21:44 UTC (permalink / raw)
  To: Felipe Contreras; +Cc: Git List, Matthieu Moy, Jeff King, John Szakmeister

Felipe Contreras wrote:
> It's more efficient to check for the braces first.

Why is it more efficient? So you can error out quickly in the case of
a malformed string? I'm personally not thrilled about this change.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 7/9] sha1_name: cleanup interpret_branch_name()
  2014-04-10 19:04 ` [PATCH v2 7/9] sha1_name: cleanup interpret_branch_name() Felipe Contreras
@ 2014-04-10 21:45   ` Ramkumar Ramachandra
  0 siblings, 0 replies; 34+ messages in thread
From: Ramkumar Ramachandra @ 2014-04-10 21:45 UTC (permalink / raw)
  To: Felipe Contreras; +Cc: Git List, Matthieu Moy, Jeff King, John Szakmeister

Felipe Contreras wrote:
>  sha1_name.c | 24 ++++++++++++------------
>  1 file changed, 12 insertions(+), 12 deletions(-)

I like this variable rename. This instance has annoyed me in the past.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 9/9] sha1_name: add support for @{publish} marks
  2014-04-10 19:04 ` [PATCH v2 9/9] sha1_name: add support for @{publish} marks Felipe Contreras
  2014-04-10 21:40   ` Ramkumar Ramachandra
@ 2014-04-10 21:49   ` Ramkumar Ramachandra
  2014-04-10 22:28     ` Felipe Contreras
  1 sibling, 1 reply; 34+ messages in thread
From: Ramkumar Ramachandra @ 2014-04-10 21:49 UTC (permalink / raw)
  To: Felipe Contreras; +Cc: Git List, Matthieu Moy, Jeff King, John Szakmeister

Felipe Contreras wrote:
> diff --git a/sha1_name.c b/sha1_name.c
> index aa3f3e0..a36852d 100644
> --- a/sha1_name.c
> +++ b/sha1_name.c
> @@ -415,9 +415,9 @@ static int ambiguous_path(const char *path, int len)
>         return slash;
>  }
>
> -static inline int upstream_mark(const char *string, int len)
> +static inline int tracking_mark(const char *string, int len)
>  {
> -       const char *suffix[] = { "upstream", "u" };
> +       const char *suffix[] = { "upstream", "u", "publish", "p" };

Oh, another thing: on some threads, people decided that "@{push}"
would be a more apt name (+ alias @{u} to @{pull} for symmetry).

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 6/9] branch: display publish branch
  2014-04-10 19:04 ` [PATCH v2 6/9] branch: display publish branch Felipe Contreras
@ 2014-04-10 22:03   ` Ramkumar Ramachandra
  2014-04-10 22:36     ` Felipe Contreras
  0 siblings, 1 reply; 34+ messages in thread
From: Ramkumar Ramachandra @ 2014-04-10 22:03 UTC (permalink / raw)
  To: Felipe Contreras; +Cc: Git List, Matthieu Moy, Jeff King, John Szakmeister

Felipe Contreras wrote:
> Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>

Please write a commit message, preferably showing the new git-branch output.

I noticed that this only picks up a publish-branch if
branch.*.pushremote is configured. What happened to the case when
remote.pushdefault is configured?

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 9/9] sha1_name: add support for @{publish} marks
  2014-04-10 21:40   ` Ramkumar Ramachandra
@ 2014-04-10 22:25     ` Felipe Contreras
  0 siblings, 0 replies; 34+ messages in thread
From: Felipe Contreras @ 2014-04-10 22:25 UTC (permalink / raw)
  To: Ramkumar Ramachandra, Felipe Contreras
  Cc: Git List, Matthieu Moy, Jeff King, John Szakmeister

Ramkumar Ramachandra wrote:
> Felipe Contreras wrote:
> > @@ -1068,23 +1069,35 @@ static const char *get_upstream_branch(const char *name_buf, int len)
> >          */
> >         if (!branch)
> >                 die(_("HEAD does not point to a branch"));
> > -       if (!branch->merge || !branch->merge[0]->dst) {
> > -               if (!ref_exists(branch->refname))
> > -                       die(_("No such branch: '%s'"), name);
> > -               if (!branch->merge) {
> > -                       die(_("No upstream configured for branch '%s'"),
> > -                               branch->name);
> > +       switch (type) {
> > +       case 'u':
> > +               if (!branch->merge || !branch->merge[0]->dst) {
> > +                       if (!ref_exists(branch->refname))
> > +                               die(_("No such branch: '%s'"), name);
> > +                       if (!branch->merge) {
> > +                               die(_("No upstream configured for branch '%s'"),
> > +                                       branch->name);
> > +                       }
> > +                       die(
> > +                               _("Upstream branch '%s' not stored as a remote-tracking branch"),
> > +                               branch->merge[0]->src);
> > +               }
> > +               tracking = branch->merge[0]->dst;
> > +               break;
> > +       case 'p':
> > +               if (!branch->push.dst) {
> > +                       die(_("No publish configured for branch '%s'"),
> > +                                       branch->name);
> 
> This assumes a push.default value of 'current' or 'matching'. What
> happens if push.default is set to 'nothing' or 'upstream', for
> instance?

Why would that matter? @{upstream} doesn't depend on this, neither does
@{publish}; @{upstream} is .remote+.merge, @{publish} is .pushremote+.push.

If the user hasn't configured a publish branch, @{publish} fails.

-- 
Felipe Contreras

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 8/9] sha1_name: simplify track finding
  2014-04-10 21:44   ` Ramkumar Ramachandra
@ 2014-04-10 22:27     ` Felipe Contreras
  0 siblings, 0 replies; 34+ messages in thread
From: Felipe Contreras @ 2014-04-10 22:27 UTC (permalink / raw)
  To: Ramkumar Ramachandra, Felipe Contreras
  Cc: Git List, Matthieu Moy, Jeff King, John Szakmeister

Ramkumar Ramachandra wrote:
> Felipe Contreras wrote:
> > It's more efficient to check for the braces first.
> 
> Why is it more efficient? So you can error out quickly in the case of
> a malformed string?

That's one reason. The other is that get_sha1_basic() calls upstream_mark()
when we _already_ know there's a @{foo}.

-- 
Felipe Contreras

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 9/9] sha1_name: add support for @{publish} marks
  2014-04-10 21:49   ` Ramkumar Ramachandra
@ 2014-04-10 22:28     ` Felipe Contreras
  0 siblings, 0 replies; 34+ messages in thread
From: Felipe Contreras @ 2014-04-10 22:28 UTC (permalink / raw)
  To: Ramkumar Ramachandra, Felipe Contreras
  Cc: Git List, Matthieu Moy, Jeff King, John Szakmeister

Ramkumar Ramachandra wrote:
> Felipe Contreras wrote:
> > diff --git a/sha1_name.c b/sha1_name.c
> > index aa3f3e0..a36852d 100644
> > --- a/sha1_name.c
> > +++ b/sha1_name.c
> > @@ -415,9 +415,9 @@ static int ambiguous_path(const char *path, int len)
> >         return slash;
> >  }
> >
> > -static inline int upstream_mark(const char *string, int len)
> > +static inline int tracking_mark(const char *string, int len)
> >  {
> > -       const char *suffix[] = { "upstream", "u" };
> > +       const char *suffix[] = { "upstream", "u", "publish", "p" };
> 
> Oh, another thing: on some threads, people decided that "@{push}"
> would be a more apt name (+ alias @{u} to @{pull} for symmetry).

@{push} is the name I originally suggested, but it's weird to talk about
"the push branch", so I decided on "the publish branch", which is more natural.

-- 
Felipe Contreras

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 6/9] branch: display publish branch
  2014-04-10 22:03   ` Ramkumar Ramachandra
@ 2014-04-10 22:36     ` Felipe Contreras
  2014-04-11 11:17       ` Jeff King
  0 siblings, 1 reply; 34+ messages in thread
From: Felipe Contreras @ 2014-04-10 22:36 UTC (permalink / raw)
  To: Ramkumar Ramachandra, Felipe Contreras
  Cc: Git List, Matthieu Moy, Jeff King, John Szakmeister

Ramkumar Ramachandra wrote:
> Felipe Contreras wrote:
> > Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
> 
> Please write a commit message, preferably showing the new git-branch output.

Yeah... this has been sitting in git-fc for quite a while, I wasn't expecting
to send this patch series again given that nobody commented on v1.

> I noticed that this only picks up a publish-branch if
> branch.*.pushremote is configured. What happened to the case when
> remote.pushdefault is configured?

What happens when branch.*.remote is not configured for @{upstream}? The same
thing.

It might be useful to visualize what would be the name of the branch when
pushing it (without a refspec) even if the publish branch hasn't been
configured, but I think the code would be much more coplicated, and it would
break symetry with @{upstream}, besides, the user can just do 'git push -p
branch', and from that moment on it will be visible.

-- 
Felipe Contreras

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 0/9] Introduce publish tracking branch
  2014-04-10 19:04 [PATCH v2 0/9] Introduce publish tracking branch Felipe Contreras
                   ` (9 preceding siblings ...)
  2014-04-10 21:21 ` [PATCH v2 0/9] Introduce publish tracking branch Junio C Hamano
@ 2014-04-11  9:15 ` Matthieu Moy
  2014-04-11 14:25   ` Felipe Contreras
  10 siblings, 1 reply; 34+ messages in thread
From: Matthieu Moy @ 2014-04-11  9:15 UTC (permalink / raw)
  To: Felipe Contreras; +Cc: git, Ramkumar Ramachandra, Jeff King, John Szakmeister

Felipe Contreras <felipe.contreras@gmail.com> writes:

> As it has been discussed before, our support for triangular workflows is
> lacking, and the following patch series aims to improve that situation.

I'm not a heavy user of triangular workflow, so I'm not in the best
position to comment (and I have no time for a real review, sorry).

On overall, I do like the change. I played a bit with it, and do not
understand what "git push" does:

  $ git status
  On branch master
  Your branch is ahead of 'origin/new' by 4 commits.
    (use "git push" to publish your local commits)

=> OK, it's using the publish branch to tell me whether I should push.

  $ git push -v
  Pushing to /tmp/git
  To /tmp/git
   = [up to date]      master -> master
  updating local tracking ref 'refs/remotes/origin/master'
  Everything up-to-date

=> Err, it still pushes to the upstream branch ... Wasn't that the point
of the change to push to publish? Did I do something wrong?


Your series lacks documentation of branch.<name>.* in
Documentation/config.txt.

It seems strange to me to name the config variables "branch.<name>.push"
and "branch.<name>.pushremote" and call the same thing "@{publish}"
elsewhere. We're already not consistant with @{upstream} corresponding
to branch.<name>.merge, but I do not consider it as a good reason to
introduce one more inconsistancy.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 6/9] branch: display publish branch
  2014-04-10 22:36     ` Felipe Contreras
@ 2014-04-11 11:17       ` Jeff King
  2014-04-11 13:48         ` Felipe Contreras
  2014-04-11 19:24         ` Junio C Hamano
  0 siblings, 2 replies; 34+ messages in thread
From: Jeff King @ 2014-04-11 11:17 UTC (permalink / raw)
  To: Felipe Contreras
  Cc: Ramkumar Ramachandra, Git List, Matthieu Moy, John Szakmeister

On Thu, Apr 10, 2014 at 05:36:59PM -0500, Felipe Contreras wrote:

> > I noticed that this only picks up a publish-branch if
> > branch.*.pushremote is configured. What happened to the case when
> > remote.pushdefault is configured?
> 
> What happens when branch.*.remote is not configured for @{upstream}? The same
> thing.

I don't know if that is a good comparison.

In other threads, the discussed meaning of @{publish} was something like
"the tracking branch of the ref you would push to if you ran 'git push'
without arguments".

That is consistent with @{upstream} being "the tracking branch of the
ref you would pull from with 'git pull'". But "git pull" without a
branch.*.remote will do nothing, so "what pull would do" is the same as
"what you have configured in your branch.*.remote".

Whereas "git push" does not depend on having branch.*.pushremote
configured. Its behavior is based on push.default and push refspecs, so
"what push would do" must take that into account.

> It might be useful to visualize what would be the name of the branch when
> pushing it (without a refspec) even if the publish branch hasn't been
> configured, but I think the code would be much more coplicated, and it would
> break symetry with @{upstream}, besides, the user can just do 'git push -p
> branch', and from that moment on it will be visible.

It is more complicated (see the patches that Junio had at
jk/branch-at-publish), but I think it is more likely to do what the user
expects.

For instance, it looks like your @{publish} requires config like:

  [branch "master"]
  pushremote = foo
  push = refs/heads/bar

to operate. Setting "pushremote" affects what "git push" does; it will
go to the "foo" remote. But the branch.master.push setting does not do
anything to "git push". Only a push refspec (or push.default setting)
will change that. So the "branch.*.push" must be kept in sync manually
(perhaps by running "git push -p").

Whereas if @{publish} means "where you would push to", then
"branch.*.push" does not need to exist at all. The values can be taken
automatically from the other push settings.

-Peff

PS I first tried just setting "branch.master.pushremote" without setting
   "branch.master.push". This results in a segfault, as branch_get()
   assumes that push_name is always set and tries to xstrdup() it.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 6/9] branch: display publish branch
  2014-04-11 11:17       ` Jeff King
@ 2014-04-11 13:48         ` Felipe Contreras
  2014-04-12 11:23           ` Jeff King
  2014-04-11 19:24         ` Junio C Hamano
  1 sibling, 1 reply; 34+ messages in thread
From: Felipe Contreras @ 2014-04-11 13:48 UTC (permalink / raw)
  To: Jeff King; +Cc: Ramkumar Ramachandra, Git List, Matthieu Moy, John Szakmeister

Jeff King wrote:
> On Thu, Apr 10, 2014 at 05:36:59PM -0500, Felipe Contreras wrote:
> 
> > > I noticed that this only picks up a publish-branch if
> > > branch.*.pushremote is configured. What happened to the case when
> > > remote.pushdefault is configured?
> > 
> > What happens when branch.*.remote is not configured for @{upstream}? The same
> > thing.
> 
> I don't know if that is a good comparison.

I think it is. @{publish} is like @{upstream}. Period.

> In other threads, the discussed meaning of @{publish} was something like
> "the tracking branch of the ref you would push to if you ran 'git push'
> without arguments".

And I disagree.

> That is consistent with @{upstream} being "the tracking branch of the
> ref you would pull from with 'git pull'". But "git pull" without a
> branch.*.remote will do nothing, so "what pull would do" is the same as
> "what you have configured in your branch.*.remote".
> 
> Whereas "git push" does not depend on having branch.*.pushremote
> configured. Its behavior is based on push.default and push refspecs, so
> "what push would do" must take that into account.

Yes, but we are not talking about 'git push', we are talking about
@{publish}.

I think of @{publish} as "the branch the user has configured to push
to"; it overrides all other configurations (push.default and push
refspecs). I wouldn't mind having a @{push} *in addition* to @{publish}
that would have the behavior you mention, but for @{publish} I'm pretty
certain the behavior I want is that it maps *directly* to what the user
has configured.

Similarly, I don't want 'git branch -vv' to show @{push}; it would be a
mess to show something on all the branches, probably origin/$branch, and
probably all "ahead/behind". I want it to show @{publish}, so only the
branches the user has *explicitly* configured.

> > It might be useful to visualize what would be the name of the branch when
> > pushing it (without a refspec) even if the publish branch hasn't been
> > configured, but I think the code would be much more coplicated, and it would
> > break symetry with @{upstream}, besides, the user can just do 'git push -p
> > branch', and from that moment on it will be visible.
> 
> It is more complicated (see the patches that Junio had at
> jk/branch-at-publish), but I think it is more likely to do what the user
> expects.
> 
> For instance, it looks like your @{publish} requires config like:
> 
>   [branch "master"]
>   pushremote = foo
>   push = refs/heads/bar
> 
> to operate. Setting "pushremote" affects what "git push" does; it will
> go to the "foo" remote. But the branch.master.push setting does not do
> anything to "git push". Only a push refspec (or push.default setting)
> will change that. So the "branch.*.push" must be kept in sync manually
> (perhaps by running "git push -p").
> 
> Whereas if @{publish} means "where you would push to"

It doesn't mean that to me.

For the record, I've been thinking about this for a long long time, and
I argued for @{push} and @{publish} long before you discussed this in
January (which apparently you forgot). I implemented this more than half
a year ago, and have been using it since; it works great. The problem of
triangular workflows is pretty much solved for me.

-- 
Felipe Contreras

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 0/9] Introduce publish tracking branch
  2014-04-11  9:15 ` Matthieu Moy
@ 2014-04-11 14:25   ` Felipe Contreras
  2014-04-11 17:25     ` Matthieu Moy
  0 siblings, 1 reply; 34+ messages in thread
From: Felipe Contreras @ 2014-04-11 14:25 UTC (permalink / raw)
  To: Matthieu Moy; +Cc: git, Ramkumar Ramachandra, Jeff King, John Szakmeister

Matthieu Moy wrote:
> Felipe Contreras <felipe.contreras@gmail.com> writes:
> 
> > As it has been discussed before, our support for triangular workflows is
> > lacking, and the following patch series aims to improve that situation.
> 
> I'm not a heavy user of triangular workflow, so I'm not in the best
> position to comment (and I have no time for a real review, sorry).
> 
> On overall, I do like the change. I played a bit with it, and do not
> understand what "git push" does:
> 
>   $ git status
>   On branch master
>   Your branch is ahead of 'origin/new' by 4 commits.
>     (use "git push" to publish your local commits)
> 
> => OK, it's using the publish branch to tell me whether I should push.
> 
>   $ git push -v
>   Pushing to /tmp/git
>   To /tmp/git
>    = [up to date]      master -> master
>   updating local tracking ref 'refs/remotes/origin/master'
>   Everything up-to-date
> 
> => Err, it still pushes to the upstream branch ... Wasn't that the point
> of the change to push to publish? Did I do something wrong?

My patch series only affects push.default=simple, perhaps you have a
different configuration.

Maybe we want the publish branch to override any push.default, so:

--- a/builtin/push.c
+++ b/builtin/push.c
@@ -195,11 +195,7 @@ static void setup_push_current(struct remote *remote, struct branch *branch)
 static void setup_push_simple(struct remote *remote, struct branch *branch,
                int triangular)
 {
-       if (branch->push_name) {
-               struct strbuf refspec = STRBUF_INIT;
-               strbuf_addf(&refspec, "%s:%s", branch->name, branch->push_name);
-               add_refspec(refspec.buf);
-       } else if (triangular) {
+       if (triangular) {
                setup_push_current(remote, branch);
        } else {
                setup_push_upstream(remote, branch, triangular);
@@ -260,8 +256,16 @@ static struct branch *get_current_branch(struct remote *remote)
 
 static void setup_default_push_refspecs(struct remote *remote)
 {
+       struct branch *branch = branch_get(NULL);
        int triangular = is_workflow_triangular(remote);
 
+       if (branch && branch->push_name) {
+               struct strbuf refspec = STRBUF_INIT;
+               strbuf_addf(&refspec, "%s:%s", branch->name, branch->push_name);
+               add_refspec(refspec.buf);
+               return;
+       }
+
        switch (push_default) {
        default:
        case PUSH_DEFAULT_UNSPECIFIED:

-- 
Felipe Contreras

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 0/9] Introduce publish tracking branch
  2014-04-11 14:25   ` Felipe Contreras
@ 2014-04-11 17:25     ` Matthieu Moy
  2014-04-11 19:16       ` Felipe Contreras
  0 siblings, 1 reply; 34+ messages in thread
From: Matthieu Moy @ 2014-04-11 17:25 UTC (permalink / raw)
  To: Felipe Contreras; +Cc: git, Ramkumar Ramachandra, Jeff King, John Szakmeister

Felipe Contreras <felipe.contreras@gmail.com> writes:

> My patch series only affects push.default=simple, perhaps you have a
> different configuration.

Good catch. I have push.default=upstream (essentially for compatibility
with old Git versions, I'd prefer simple actually).

> Maybe we want the publish branch to override any push.default, so:

Not sure actually. If a user says "push.default=upstream", it seems
weird to push to something other than upstream indeed. What's clear to
me is that your patch in its current form clearly makes "simple" a much
better default than "upstream" (good news, it it the default!).

That said, the advice given by "git status" is clearly wrong:

> >   $ git status
> >   On branch master
> >   Your branch is ahead of 'origin/new' by 4 commits.
> >     (use "git push" to publish your local commits)

It should say (use "git push origin new" to publish your local commits)
with push.default=upstream and the current behavior of the patch.

Perhaps argumentless "git push" could warn when push.default=upstream
and branch.<name>.publish is configured, I'm not sure.

Sorry, more questions and "I'm not sure" than actual suggestion :-(.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 0/9] Introduce publish tracking branch
  2014-04-11 17:25     ` Matthieu Moy
@ 2014-04-11 19:16       ` Felipe Contreras
  0 siblings, 0 replies; 34+ messages in thread
From: Felipe Contreras @ 2014-04-11 19:16 UTC (permalink / raw)
  To: Matthieu Moy, Felipe Contreras
  Cc: git, Ramkumar Ramachandra, Jeff King, John Szakmeister

Matthieu Moy wrote:
> Felipe Contreras <felipe.contreras@gmail.com> writes:
> 
> > My patch series only affects push.default=simple, perhaps you have a
> > different configuration.
> 
> Good catch. I have push.default=upstream (essentially for compatibility
> with old Git versions, I'd prefer simple actually).
> 
> > Maybe we want the publish branch to override any push.default, so:
> 
> Not sure actually. If a user says "push.default=upstream", it seems
> weird to push to something other than upstream indeed. What's clear to
> me is that your patch in its current form clearly makes "simple" a much
> better default than "upstream" (good news, it it the default!).

As you said in another email; that's just the default. If the user explicitely
told Git to use certain branch (git push -p), Git should use that branch.

> That said, the advice given by "git status" is clearly wrong:
> 
> > >   $ git status
> > >   On branch master
> > >   Your branch is ahead of 'origin/new' by 4 commits.
> > >     (use "git push" to publish your local commits)
> 
> It should say (use "git push origin new" to publish your local commits)
> with push.default=upstream and the current behavior of the patch.
> 
> Perhaps argumentless "git push" could warn when push.default=upstream
> and branch.<name>.publish is configured, I'm not sure.
> 
> Sorry, more questions and "I'm not sure" than actual suggestion :-(.

I believe in v3 of the patch series "git push" will actually do it correctly.

Cheers.

-- 
Felipe Contreras

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 6/9] branch: display publish branch
  2014-04-11 11:17       ` Jeff King
  2014-04-11 13:48         ` Felipe Contreras
@ 2014-04-11 19:24         ` Junio C Hamano
  2014-04-11 19:50           ` Felipe Contreras
  2014-04-12 11:42           ` Jeff King
  1 sibling, 2 replies; 34+ messages in thread
From: Junio C Hamano @ 2014-04-11 19:24 UTC (permalink / raw)
  To: Jeff King
  Cc: Felipe Contreras, Ramkumar Ramachandra, Git List, Matthieu Moy,
	John Szakmeister

Jeff King <peff@peff.net> writes:

> For instance, it looks like your @{publish} requires config like:
>
>   [branch "master"]
>   pushremote = foo
>   push = refs/heads/bar
>
> to operate. Setting "pushremote" affects what "git push" does; it will
> go to the "foo" remote.

OK, and the same thing would happen if branch.*.pushremote is not
set for any branch, but remote.pushdefault is set to 'foo', right?

> But the branch.master.push setting does not do
> anything to "git push".

I am not sure I understand this.  I thought that the desire behind
the branch.*.push is to allow something like:

	... other things in the config ...
	[remote]
        	pushdefault = foo
	[remote "foo"]
		url = ...
        	push = +refs/heads/*:refs/remotes/satellite/*
                fetch = +refs/heads/*:refs/remotes/foo/*
	[branch "master"]
		; pushremote = foo
        	push = refs/heads/bar

so that "git push" on 'master' will override the more generic "all
local branches here will go to their remote-tracking hierarchy for
this satellite" refspec.  And in that sense branch.master.push would
do something to "git push".

I personally think that kind of override adds any more values than
it causes confusion, so I think it is OK not to support such uses of
branch.*.push at all.  A configuration without branch.master.push
may cause "git push" on 'master' to update refs/heads/master at the
remote, and if we fetched from 'foo' immediately after pushing
there, it would come back as refs/remotes/foo/master, and it would
be natural for users to expect that master@{publish} would be
refs/remotes/foo/master in such a case.

If we supported setting branch.master.push to refs/heads/bar, then
master would be pushed as refs/heads/bar over there and it would
come back as refs/remotes/foo/bar here, so I would expect that to be
the value of master@{publish}.

> Only a push refspec (or push.default setting)
> will change that. So the "branch.*.push" must be kept in sync manually
> (perhaps by running "git push -p").
>
> Whereas if @{publish} means "where you would push to", then
> "branch.*.push" does not need to exist at all. The values can be taken
> automatically from the other push settings.
>
> -Peff
>
> PS I first tried just setting "branch.master.pushremote" without setting
>    "branch.master.push". This results in a segfault, as branch_get()
>    assumes that push_name is always set and tries to xstrdup() it.

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 6/9] branch: display publish branch
  2014-04-11 19:24         ` Junio C Hamano
@ 2014-04-11 19:50           ` Felipe Contreras
  2014-04-12 11:42           ` Jeff King
  1 sibling, 0 replies; 34+ messages in thread
From: Felipe Contreras @ 2014-04-11 19:50 UTC (permalink / raw)
  To: Junio C Hamano, Jeff King
  Cc: Felipe Contreras, Ramkumar Ramachandra, Git List, Matthieu Moy,
	John Szakmeister

Junio C Hamano wrote:
> Jeff King <peff@peff.net> writes:
> 
> > For instance, it looks like your @{publish} requires config like:
> >
> >   [branch "master"]
> >   pushremote = foo
> >   push = refs/heads/bar
> >
> > to operate. Setting "pushremote" affects what "git push" does; it will
> > go to the "foo" remote.
> 
> OK, and the same thing would happen if branch.*.pushremote is not
> set for any branch, but remote.pushdefault is set to 'foo', right?
> 
> > But the branch.master.push setting does not do
> > anything to "git push".
> 
> I am not sure I understand this.  I thought that the desire behind
> the branch.*.push is to allow something like:
> 
> 	... other things in the config ...
> 	[remote]
>         	pushdefault = foo
> 	[remote "foo"]
> 		url = ...
>         	push = +refs/heads/*:refs/remotes/satellite/*
>                 fetch = +refs/heads/*:refs/remotes/foo/*
> 	[branch "master"]
> 		; pushremote = foo
>         	push = refs/heads/bar
> 
> so that "git push" on 'master' will override the more generic "all
> local branches here will go to their remote-tracking hierarchy for
> this satellite" refspec.  And in that sense branch.master.push would
> do something to "git push".

In my patches the above doesn't work; branch.master.push doesn't do anything if
.pushremote isn't there.

I'm always thinking from the common user's point of view, and the common user
doesn't know what branch.master.push is, but he knows he did
`git branch -p foo/bar master` (or something like that), and
`git branch -v` would corroborate that.

So you would have something like this:

	[remote "foo"]
		url = ...
		push = +refs/heads/*:refs/remotes/satellite/*
		fetch = +refs/heads/*:refs/remotes/foo/*
	[branch "master"]
		pushremote = foo
		push = refs/heads/bar

> I personally think that kind of override adds any more values than
> it causes confusion, so I think it is OK not to support such uses of
> branch.*.push at all.  A configuration without branch.master.push
> may cause "git push" on 'master' to update refs/heads/master at the
> remote,

How? If branch.master.push is not configured, then "git push" would push
'master' to refs/remotes/satellite/master on the remote.

-- 
Felipe Contreras

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 6/9] branch: display publish branch
  2014-04-11 13:48         ` Felipe Contreras
@ 2014-04-12 11:23           ` Jeff King
  2014-04-12 14:34             ` Felipe Contreras
  0 siblings, 1 reply; 34+ messages in thread
From: Jeff King @ 2014-04-12 11:23 UTC (permalink / raw)
  To: Felipe Contreras
  Cc: Ramkumar Ramachandra, Git List, Matthieu Moy, John Szakmeister

On Fri, Apr 11, 2014 at 08:48:01AM -0500, Felipe Contreras wrote:

> I think of @{publish} as "the branch the user has configured to push
> to"; it overrides all other configurations (push.default and push
> refspecs). I wouldn't mind having a @{push} *in addition* to @{publish}
> that would have the behavior you mention, but for @{publish} I'm pretty
> certain the behavior I want is that it maps *directly* to what the user
> has configured.

I guess I don't understand why we need "branch.*.push" when we already
have push refspecs that do the same thing (and are more powerful, as
they can glob).

The behavior you describe is not useful to me, as it would mean having
to manage branch.*.push as a duplicate of the information that is
already found in "remote.$(git config remote.pushdefault).push".  I do
not mind if the two co-exist, but please do not take the short @{p} as
your series does (not only because of @{push}, but also because @{pull}
has been mentioned elsewhere as a possible other name for @{upstream}).

-Peff

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 6/9] branch: display publish branch
  2014-04-11 19:24         ` Junio C Hamano
  2014-04-11 19:50           ` Felipe Contreras
@ 2014-04-12 11:42           ` Jeff King
  2014-04-12 15:05             ` Felipe Contreras
  1 sibling, 1 reply; 34+ messages in thread
From: Jeff King @ 2014-04-12 11:42 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Felipe Contreras, Ramkumar Ramachandra, Git List, Matthieu Moy,
	John Szakmeister

On Fri, Apr 11, 2014 at 12:24:35PM -0700, Junio C Hamano wrote:

> > But the branch.master.push setting does not do
> > anything to "git push".
> 
> I am not sure I understand this.  I thought that the desire behind
> the branch.*.push is to allow something like:
> 
> 	... other things in the config ...
> 	[remote]
>         	pushdefault = foo
> 	[remote "foo"]
> 		url = ...
>         	push = +refs/heads/*:refs/remotes/satellite/*
>                 fetch = +refs/heads/*:refs/remotes/foo/*
> 	[branch "master"]
> 		; pushremote = foo
>         	push = refs/heads/bar
> 
> so that "git push" on 'master' will override the more generic "all
> local branches here will go to their remote-tracking hierarchy for
> this satellite" refspec.  And in that sense branch.master.push would
> do something to "git push".

Ah, I see. If I set "push.default" to "upstream", then the config I
showed before _does_ affect "git push". But I do not usually do that. I
have push.default set to "current", and sometimes override it using push
refspecs on certain repositories.

And that is why I find branch.*.push and Felipe's @{publish} useless for
my workflow. Pushes already go where I want them to, and I just want a
way to ask git to perform that config resolution for me. Whereas
Felipe's workflow is (I think) something like:

  # make a new branch...
  git checkout -b topic origin/master

  # now publish our branch, and remember our publishing point
  git push -p my-repo topic

  # and now further pushes automatically go to my-repo/topic
  git push

I can see there is some value in that override if you do things like:

  git push -p my-repo topic:some-other-name

because the "-p" means "remember this other name I gave".

I would think in such a workflow that most of your branches would end up
with publish config, though. And therefore @{publish} would become
equivalent to "where you would push". But Felipe indicated that he would
not want "branch -vv" to match where all branches would be pushed, but
rather only those that were specifically configured. So maybe I do not
understand his workflow after all.

-Peff

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 6/9] branch: display publish branch
  2014-04-12 11:23           ` Jeff King
@ 2014-04-12 14:34             ` Felipe Contreras
  0 siblings, 0 replies; 34+ messages in thread
From: Felipe Contreras @ 2014-04-12 14:34 UTC (permalink / raw)
  To: Jeff King, Felipe Contreras
  Cc: Ramkumar Ramachandra, Git List, Matthieu Moy, John Szakmeister

Jeff King wrote:
> On Fri, Apr 11, 2014 at 08:48:01AM -0500, Felipe Contreras wrote:
> 
> > I think of @{publish} as "the branch the user has configured to push
> > to"; it overrides all other configurations (push.default and push
> > refspecs). I wouldn't mind having a @{push} *in addition* to @{publish}
> > that would have the behavior you mention, but for @{publish} I'm pretty
> > certain the behavior I want is that it maps *directly* to what the user
> > has configured.
> 
> I guess I don't understand why we need "branch.*.push" when we already
> have push refspecs that do the same thing (and are more powerful, as
> they can glob).

Really? I think it's pretty simple.

I have a configuration similar to the following

  [remote "gh"]
  	url = git@github.com:felipec/git.git
  [branch "master"]
  	pushremote = gh
  	push = refs/heads/master
  [branch "fc/master"]
  	pushremote = gh
  	push = refs/heads/fc/master
  [branch "up/publish"]
  	pushremote = gh
  	push = refs/heads/fc/publish

Now, if I didn't, I could create it easily with something like this:

  % git push -p gh master
  % git push -p gh fc/master
  % git push -p gh up/publish:fc/publish

How would that translate to push refspecs?

  [remote "gh"]
  	url = git@github.com:felipec/git.git
  	push = refs/heads/master:refs/heads/master
  	push = refs/heads/fc/master:refs/heads/fc/master
  	push = refs/heads/up/master:refs/heads/fc/publish
  [branch "master"]
  	pushremote = gh
  [branch "fc/master"]
  	pushremote = gh
  [branch "up/publish"]
  	pushremote = gh

So in theory it could be possible to make it work without branch.x.push.

If I run `git branch -v`, it would show the publish branch correctly.

  master cee0c27 [origin/master, gh/master] Git 1.9.1

However, if I have a configuration like this:

  [remote "gh"]
  	url = git@github.com:felipec/git.git
  	push = refs/heads/*:refs/heads/*

Git would still show the same publish branch, even though the user never
explicitely told it do to so (e.g. with `git push -p`). To me this is not OK;
if I haven't specifically set a publish branch, it shouldn't be shown.

And then, what happens when I do:

  % git branch --unset-upstream up/publish

Or:

  % git branch -d up/publish

Should Git remove the appropriate push refspec? What if that refspec was
manually added by the user before the concept of the publish branch even
existed?

To me using the refspec just adds more complications, and it's not symetric
with @{upstream}. With branch.x.push, the symetry is very much there; the code
is similar to @{upstream}, the configuration as well, and what the user expects
too; it's much simpler. Also, the user can clearly see what are his manually
configured refspecs, as opposed to the ones added by `git push -p`.

It's just neat.

-- 
Felipe Contreras

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 6/9] branch: display publish branch
  2014-04-12 11:42           ` Jeff King
@ 2014-04-12 15:05             ` Felipe Contreras
  2014-04-15  5:43               ` Jeff King
  0 siblings, 1 reply; 34+ messages in thread
From: Felipe Contreras @ 2014-04-12 15:05 UTC (permalink / raw)
  To: Jeff King, Junio C Hamano
  Cc: Felipe Contreras, Ramkumar Ramachandra, Git List, Matthieu Moy,
	John Szakmeister

Jeff King wrote:
> On Fri, Apr 11, 2014 at 12:24:35PM -0700, Junio C Hamano wrote:
> 
> > > But the branch.master.push setting does not do
> > > anything to "git push".
> > 
> > I am not sure I understand this.  I thought that the desire behind
> > the branch.*.push is to allow something like:
> > 
> > 	... other things in the config ...
> > 	[remote]
> >         	pushdefault = foo
> > 	[remote "foo"]
> > 		url = ...
> >         	push = +refs/heads/*:refs/remotes/satellite/*
> >                 fetch = +refs/heads/*:refs/remotes/foo/*
> > 	[branch "master"]
> > 		; pushremote = foo
> >         	push = refs/heads/bar
> > 
> > so that "git push" on 'master' will override the more generic "all
> > local branches here will go to their remote-tracking hierarchy for
> > this satellite" refspec.  And in that sense branch.master.push would
> > do something to "git push".
> 
> Ah, I see. If I set "push.default" to "upstream", then the config I
> showed before _does_ affect "git push". But I do not usually do that. I
> have push.default set to "current", and sometimes override it using push
> refspecs on certain repositories.
> 
> And that is why I find branch.*.push and Felipe's @{publish} useless for
> my workflow. Pushes already go where I want them to, and I just want a
> way to ask git to perform that config resolution for me. Whereas
> Felipe's workflow is (I think) something like:
> 
>   # make a new branch...
>   git checkout -b topic origin/master
> 
>   # now publish our branch, and remember our publishing point
>   git push -p my-repo topic
> 
>   # and now further pushes automatically go to my-repo/topic
>   git push
> 
> I can see there is some value in that override if you do things like:
> 
>   git push -p my-repo topic:some-other-name
> 
> because the "-p" means "remember this other name I gave".
> 
> I would think in such a workflow that most of your branches would end up with
> publish config, though. And therefore @{publish} would become equivalent to
> "where you would push".

> But Felipe indicated that he would not want "branch -vv" to match where all
> branches would be pushed, but rather only those that were specifically
> configured. So maybe I do not understand his workflow after all.

It's a pretty typical triangular workflow, with a touch of fork maintainership.

Here are some types of branches I have:

* master [origin/master, gh/master] Git 1.9.1

My main master branch, I use it as a base point for many other branches. I
don't use origin/master because that's a moving target.

* dev/remote/hg-extra [master] remote-hg: store extra hg information in notes

A development branch. I don't publish those, therefore no @{publish}.

* fc/publish [fc/branch/nice-verbose, gh/fc/publish] sha1_name: add support for @{publish} marks

A branch that is all good. I publish those, and use them for git-fc (my fork).
I think they should be in Git's core, but haven't been merged for some reason
or another.

Notice that the upstream branch is another local branch, not master. Strictly
speaking it's not an "upstream" branch, but I want 'git rebase' to use that as
the base point. Another @{base} concept might be more appropriate, but those
patches are a different story.

* up/publish [master] sha1_name: add support for @{publish} marks

A branch that should be sent upstream. I don't publish those.

Notice up/publish is different from fc/publish because the later depends on
another fc/* branch, which wasn't accepted upstream.

* fc/master [gh/fc/master] prompt: fix missing file errors in zsh

My main branch, used for git-fc. I merge Git's master, and cherry-pick various
fixes, so it has always the latest and greatest stuff.

Notice that 'gh/fc/master' is the publish branch, there is no upstream.

* pu [] Merge branch 'travis-ci' into pu

Similar to Junio's pu, I use `git reintegrate` to generate this branch using
'master' as the baseline, and merging all the fc/* branches. The result should
be identical to fc/master, if not, we are missing something from upstream, or
there's something missing in the fc/* branches.

It's not published, and has no upstream.


As you can see; some branches are published, others are not. The ones that are
not published don't have a @{publish}, and `git branch -v` doesn't show them.
Why is that hard to understand?

-- 
Felipe Contreras

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 6/9] branch: display publish branch
  2014-04-12 15:05             ` Felipe Contreras
@ 2014-04-15  5:43               ` Jeff King
  2014-04-18 23:29                 ` Felipe Contreras
  0 siblings, 1 reply; 34+ messages in thread
From: Jeff King @ 2014-04-15  5:43 UTC (permalink / raw)
  To: Felipe Contreras
  Cc: Junio C Hamano, Ramkumar Ramachandra, Git List, Matthieu Moy,
	John Szakmeister

On Sat, Apr 12, 2014 at 10:05:15AM -0500, Felipe Contreras wrote:

> As you can see; some branches are published, others are not. The ones that are
> not published don't have a @{publish}, and `git branch -v` doesn't show them.
> Why is that hard to understand?

Do you ever push the unpublished branches anywhere at all? If not, then
you would not have a tracking branch. E.g., git _would_ push to remote
"gh", branch "refs/heads/topic", but there is no remote tracking branch
"refs/remotes/gh/topic", because you have never actually pushed there.
So there is no @{publish} branch.

Or do you have some branches in a state where they are "pushed, but not
published"? It wasn't clear to me from your example if your "pu" or
"dev/remote/hg-extra" ever get pushed.

I do not use "git branch -v" myself, so I don't personally care that
much how it behaves. But I do use a separate script that does the same
thing, and I would want it to show the ahead/behind relationship between
each branch and where it would be pushed to (and as I said, I define
mine with refspecs). Right now it uses nasty hackery to guess at where
things will be pushed, but ideally it would ask git via @{push} or some
similar mechanism.

If the former (you do not actually push them), then I think the
semantics I am looking for and the ones you want would coincide. If not,
then I think we are really talking about two different things.

-Peff

^ permalink raw reply	[flat|nested] 34+ messages in thread

* Re: [PATCH v2 6/9] branch: display publish branch
  2014-04-15  5:43               ` Jeff King
@ 2014-04-18 23:29                 ` Felipe Contreras
  0 siblings, 0 replies; 34+ messages in thread
From: Felipe Contreras @ 2014-04-18 23:29 UTC (permalink / raw)
  To: Jeff King, Felipe Contreras
  Cc: Junio C Hamano, Ramkumar Ramachandra, Git List, Matthieu Moy,
	John Szakmeister

Jeff King wrote:
> On Sat, Apr 12, 2014 at 10:05:15AM -0500, Felipe Contreras wrote:
> 
> > As you can see; some branches are published, others are not. The ones that are
> > not published don't have a @{publish}, and `git branch -v` doesn't show them.
> > Why is that hard to understand?
> 
> Do you ever push the unpublished branches anywhere at all? If not, then
> you would not have a tracking branch. E.g., git _would_ push to remote
> "gh", branch "refs/heads/topic", but there is no remote tracking branch
> "refs/remotes/gh/topic", because you have never actually pushed there.
> So there is no @{publish} branch.
> 
> Or do you have some branches in a state where they are "pushed, but not
> published"? It wasn't clear to me from your example if your "pu" or
> "dev/remote/hg-extra" ever get pushed.

Sometimes I do push these branches, but I don't understand what you mean by
"pushed state". When you push something no states are changed. Say I do:

 % git push tmp wip-feature
 % git push backup wip-feature

So I pushed a branch to two different repositories, the former one might not
even exist any more. Who cares? No states have changed. The fact that this
branch was pushed doesn't change anything about the nature of the branch.

> I do not use "git branch -v" myself,

Me neither (at least not the upstream version).

> so I don't personally care that much how it behaves. But I do use a separate
> script that does the same thing, and I would want it to show the ahead/behind
> relationship between each branch and where it would be pushed to (and as I
> said, I define mine with refspecs). Right now it uses nasty hackery to guess
> at where things will be pushed, but ideally it would ask git via @{push} or
> some similar mechanism.

Yes, but you can push a branch to many locations, to which one should the
script show the tracking information? IMO it should be the one location you
explicitly configured, and in the case of "wip-feature" is "no location".

> If the former (you do not actually push them), then I think the semantics I
> am looking for and the ones you want would coincide. If not, then I think we
> are really talking about two different things.

I ask again what is so difficult about the notion that there are two kinds of branches?

A)

% git checkout ready-feature
% git push tmp ready-feature
% git push -p github ready-feature
% git push backup ready-feature

B)

% git checkout wip-feature
% git push tmp wip-feature
% git push backup wip-feature

In a haste these branches might not look very different, but conceptually they
are. One has a location where it is publicly visible, and where you wish to
push regularly, the other one doesn't.

Whether you push a branch or not is not really important, it's whether or not
the branch has a *special* place where you push to.

-- 
Felipe Contreras

^ permalink raw reply	[flat|nested] 34+ messages in thread

end of thread, other threads:[~2014-04-18 23:40 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-10 19:04 [PATCH v2 0/9] Introduce publish tracking branch Felipe Contreras
2014-04-10 19:04 ` [PATCH v2 1/9] push: trivial reorganization Felipe Contreras
2014-04-10 19:04 ` [PATCH v2 2/9] Add concept of 'publish' branch Felipe Contreras
2014-04-10 19:04 ` [PATCH v2 3/9] branch: allow configuring the publish branch Felipe Contreras
2014-04-10 19:04 ` [PATCH v2 4/9] t: branch add publish branch tests Felipe Contreras
2014-04-10 19:04 ` [PATCH v2 5/9] push: add --set-publish option Felipe Contreras
2014-04-10 19:04 ` [PATCH v2 6/9] branch: display publish branch Felipe Contreras
2014-04-10 22:03   ` Ramkumar Ramachandra
2014-04-10 22:36     ` Felipe Contreras
2014-04-11 11:17       ` Jeff King
2014-04-11 13:48         ` Felipe Contreras
2014-04-12 11:23           ` Jeff King
2014-04-12 14:34             ` Felipe Contreras
2014-04-11 19:24         ` Junio C Hamano
2014-04-11 19:50           ` Felipe Contreras
2014-04-12 11:42           ` Jeff King
2014-04-12 15:05             ` Felipe Contreras
2014-04-15  5:43               ` Jeff King
2014-04-18 23:29                 ` Felipe Contreras
2014-04-10 19:04 ` [PATCH v2 7/9] sha1_name: cleanup interpret_branch_name() Felipe Contreras
2014-04-10 21:45   ` Ramkumar Ramachandra
2014-04-10 19:04 ` [PATCH v2 8/9] sha1_name: simplify track finding Felipe Contreras
2014-04-10 21:44   ` Ramkumar Ramachandra
2014-04-10 22:27     ` Felipe Contreras
2014-04-10 19:04 ` [PATCH v2 9/9] sha1_name: add support for @{publish} marks Felipe Contreras
2014-04-10 21:40   ` Ramkumar Ramachandra
2014-04-10 22:25     ` Felipe Contreras
2014-04-10 21:49   ` Ramkumar Ramachandra
2014-04-10 22:28     ` Felipe Contreras
2014-04-10 21:21 ` [PATCH v2 0/9] Introduce publish tracking branch Junio C Hamano
2014-04-11  9:15 ` Matthieu Moy
2014-04-11 14:25   ` Felipe Contreras
2014-04-11 17:25     ` Matthieu Moy
2014-04-11 19:16       ` Felipe Contreras

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.