git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] Minor preparation for @{publish}
@ 2014-01-12 17:11 Ramkumar Ramachandra
  2014-01-12 17:11 ` [PATCH 1/3] t1507 (rev-parse-upstream): fix typo in test title Ramkumar Ramachandra
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Ramkumar Ramachandra @ 2014-01-12 17:11 UTC (permalink / raw)
  To: Git List; +Cc: Jeff King, Junio C Hamano

Hi,

I'm getting ready to switch timezones in a few days, so the @{publish}
series is on hold for some time. In the meantime, I thought I'd send
in a few patches early.

[1/3] is a minor typo fix I happened to notice while writing tests.

[2/3] is an is an excellent patch by Peff, that greatly helped
prettify the code. It's a pure refactor and should have no effect on
functionality.

[3/3] introduces branch->pushremote corresponding to branch->remote,
which is crucial for getting @{publish} from the branch_get()
interface. Peff had sent a similar patch, but mine has some subtle
differences.

Thanks.

Jeff King (1):
  interpret_branch_name: factor out upstream handling

Ramkumar Ramachandra (2):
  t1507 (rev-parse-upstream): fix typo in test title
  remote: introduce and fill branch->pushremote

 remote.c                      | 15 ++++++--
 remote.h                      |  3 ++
 sha1_name.c                   | 83 +++++++++++++++++++++++++++----------------
 t/t1507-rev-parse-upstream.sh |  2 +-
 4 files changed, 68 insertions(+), 35 deletions(-)

-- 
1.8.5.2.313.g5abf4c0.dirty

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

* [PATCH 1/3] t1507 (rev-parse-upstream): fix typo in test title
  2014-01-12 17:11 [PATCH 0/3] Minor preparation for @{publish} Ramkumar Ramachandra
@ 2014-01-12 17:11 ` Ramkumar Ramachandra
  2014-01-12 17:11 ` [PATCH 2/3] interpret_branch_name: factor out upstream handling Ramkumar Ramachandra
  2014-01-12 17:11 ` [PATCH 3/3] remote: introduce and fill branch->pushremote Ramkumar Ramachandra
  2 siblings, 0 replies; 9+ messages in thread
From: Ramkumar Ramachandra @ 2014-01-12 17:11 UTC (permalink / raw)
  To: Git List; +Cc: Jeff King, Junio C Hamano

Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
---
 t/t1507-rev-parse-upstream.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/t/t1507-rev-parse-upstream.sh b/t/t1507-rev-parse-upstream.sh
index 2a19e79..15f2e7e 100755
--- a/t/t1507-rev-parse-upstream.sh
+++ b/t/t1507-rev-parse-upstream.sh
@@ -54,7 +54,7 @@ test_expect_success 'my-side@{upstream} resolves to correct full name' '
 	test refs/remotes/origin/side = "$(full_name my-side@{u})"
 '
 
-test_expect_success 'refs/heads/my-side@{upstream} does not resolve to my-side{upstream}' '
+test_expect_success 'refs/heads/my-side@{upstream} does not resolve to my-side@{upstream}' '
 	test_must_fail full_name refs/heads/my-side@{upstream}
 '
 
-- 
1.8.5.2.313.g5abf4c0.dirty

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

* [PATCH 2/3] interpret_branch_name: factor out upstream handling
  2014-01-12 17:11 [PATCH 0/3] Minor preparation for @{publish} Ramkumar Ramachandra
  2014-01-12 17:11 ` [PATCH 1/3] t1507 (rev-parse-upstream): fix typo in test title Ramkumar Ramachandra
@ 2014-01-12 17:11 ` Ramkumar Ramachandra
  2014-01-12 17:11 ` [PATCH 3/3] remote: introduce and fill branch->pushremote Ramkumar Ramachandra
  2 siblings, 0 replies; 9+ messages in thread
From: Ramkumar Ramachandra @ 2014-01-12 17:11 UTC (permalink / raw)
  To: Git List; +Cc: Jeff King, Junio C Hamano

From: Jeff King <peff@peff.net>

This function checks a few different @{}-constructs. The
early part checks for and dispatches us to helpers for each
construct, but the code for handling @{upstream} is inline.

Let's factor this out into its own function. This makes
interpret_branch_name more readable, and will make it much
simpler to add more constructs in future patches.

While we're at it, let's also break apart the refactored
code into a few helper functions. These will be useful when
we implement similar @{upstream}-like constructs.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
---
 sha1_name.c | 83 ++++++++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 52 insertions(+), 31 deletions(-)

diff --git a/sha1_name.c b/sha1_name.c
index b1873d8..7ebb8ee 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -1046,6 +1046,54 @@ static int reinterpret(const char *name, int namelen, int len, struct strbuf *bu
 	return ret - used + len;
 }
 
+static void set_shortened_ref(struct strbuf *buf, const char *ref)
+{
+	char *s = shorten_unambiguous_ref(ref, 0);
+	strbuf_reset(buf);
+	strbuf_addstr(buf, s);
+	free(s);
+}
+
+static const char *get_upstream_branch(const char *branch_buf, int len)
+{
+	char *branch = xstrndup(branch_buf, len);
+	struct branch *upstream = branch_get(*branch ? branch : NULL);
+
+	/*
+	 * Upstream can be NULL only if branch refers to HEAD and HEAD
+	 * points to something different than a branch.
+	 */
+	if (!upstream)
+		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) {
+			die(_("No upstream configured for branch '%s'"),
+				upstream->name);
+		}
+		die(
+			_("Upstream branch '%s' not stored as a remote-tracking branch"),
+			upstream->merge[0]->src);
+	}
+	free(branch);
+
+	return upstream->merge[0]->dst;
+}
+
+static int interpret_upstream_mark(const char *name, int namelen,
+				   int at, struct strbuf *buf)
+{
+	int len;
+
+	len = upstream_mark(name + at, namelen - at);
+	if (!len)
+		return -1;
+
+	set_shortened_ref(buf, get_upstream_branch(name, at));
+	return len + at;
+}
+
 /*
  * This reads short-hand syntax that not only evaluates to a commit
  * object name, but also can act as if the end user spelled the name
@@ -1070,9 +1118,7 @@ static int reinterpret(const char *name, int namelen, int len, struct strbuf *bu
 int interpret_branch_name(const char *name, int namelen, struct strbuf *buf)
 {
 	char *cp;
-	struct branch *upstream;
 	int len = interpret_nth_prior_checkout(name, buf);
-	int tmp_len;
 
 	if (!namelen)
 		namelen = strlen(name);
@@ -1094,36 +1140,11 @@ int interpret_branch_name(const char *name, int namelen, struct strbuf *buf)
 	if (len > 0)
 		return reinterpret(name, namelen, len, buf);
 
-	tmp_len = upstream_mark(cp, namelen - (cp - name));
-	if (!tmp_len)
-		return -1;
+	len = interpret_upstream_mark(name, namelen, cp - name, buf);
+	if (len > 0)
+		return len;
 
-	len = cp + tmp_len - name;
-	cp = xstrndup(name, cp - name);
-	upstream = branch_get(*cp ? cp : NULL);
-	/*
-	 * Upstream can be NULL only if cp refers to HEAD and HEAD
-	 * points to something different than a branch.
-	 */
-	if (!upstream)
-		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'"), cp);
-		if (!upstream->merge) {
-			die(_("No upstream configured for branch '%s'"),
-				upstream->name);
-		}
-		die(
-			_("Upstream branch '%s' not stored as a remote-tracking branch"),
-			upstream->merge[0]->src);
-	}
-	free(cp);
-	cp = shorten_unambiguous_ref(upstream->merge[0]->dst, 0);
-	strbuf_reset(buf);
-	strbuf_addstr(buf, cp);
-	free(cp);
-	return len;
+	return -1;
 }
 
 int strbuf_branchname(struct strbuf *sb, const char *name)
-- 
1.8.5.2.313.g5abf4c0.dirty

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

* [PATCH 3/3] remote: introduce and fill branch->pushremote
  2014-01-12 17:11 [PATCH 0/3] Minor preparation for @{publish} Ramkumar Ramachandra
  2014-01-12 17:11 ` [PATCH 1/3] t1507 (rev-parse-upstream): fix typo in test title Ramkumar Ramachandra
  2014-01-12 17:11 ` [PATCH 2/3] interpret_branch_name: factor out upstream handling Ramkumar Ramachandra
@ 2014-01-12 17:11 ` Ramkumar Ramachandra
  2014-01-13  8:34   ` Jeff King
  2 siblings, 1 reply; 9+ messages in thread
From: Ramkumar Ramachandra @ 2014-01-12 17:11 UTC (permalink / raw)
  To: Git List; +Cc: Jeff King, Junio C Hamano

When a caller uses branch_get() to retrieve a "struct branch", they get
the per-branch remote name and a pointer to the remote struct. However,
they have no way of knowing about the per-branch pushremote from this
interface. So, let's expose that information via fields similar to
"remote" and "remote_name"; "pushremote" and "pushremote_name".

Helped-by: Jeff King <peff@peff.net>
Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
---
 remote.c | 15 ++++++++++++---
 remote.h |  3 +++
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/remote.c b/remote.c
index a89efab..286cdce 100644
--- a/remote.c
+++ b/remote.c
@@ -351,9 +351,10 @@ 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(&pushremote_name, key, value))
-					return -1;
+				pushremote_name = branch->pushremote_name;
 		} else if (!strcmp(subkey, ".merge")) {
 			if (!value)
 				return config_error_nonbool(key);
@@ -1543,7 +1544,9 @@ struct branch *branch_get(const char *name)
 		ret = current_branch;
 	else
 		ret = make_branch(name, 0);
-	if (ret && ret->remote_name) {
+	if (!ret)
+		return ret;
+	if (ret->remote_name) {
 		ret->remote = remote_get(ret->remote_name);
 		if (ret->merge_nr) {
 			int i;
@@ -1557,6 +1560,12 @@ struct branch *branch_get(const char *name)
 			}
 		}
 	}
+	if (ret->pushremote_name)
+		ret->pushremote = remote_get(ret->pushremote_name);
+	else if (pushremote_name)
+		ret->pushremote = remote_get(pushremote_name);
+	else
+		ret->pushremote = ret->remote;
 	return ret;
 }
 
diff --git a/remote.h b/remote.h
index 00c6a76..ac5aadc 100644
--- a/remote.h
+++ b/remote.h
@@ -201,6 +201,9 @@ struct branch {
 	const char *remote_name;
 	struct remote *remote;
 
+	const char *pushremote_name;
+	struct remote *pushremote;
+
 	const char **merge_name;
 	struct refspec **merge;
 	int merge_nr;
-- 
1.8.5.2.313.g5abf4c0.dirty

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

* Re: [PATCH 3/3] remote: introduce and fill branch->pushremote
  2014-01-12 17:11 ` [PATCH 3/3] remote: introduce and fill branch->pushremote Ramkumar Ramachandra
@ 2014-01-13  8:34   ` Jeff King
  2014-01-13 11:22     ` Ramkumar Ramachandra
  0 siblings, 1 reply; 9+ messages in thread
From: Jeff King @ 2014-01-13  8:34 UTC (permalink / raw)
  To: Ramkumar Ramachandra; +Cc: Git List, Junio C Hamano

On Sun, Jan 12, 2014 at 10:41:06PM +0530, Ramkumar Ramachandra wrote:

> When a caller uses branch_get() to retrieve a "struct branch", they get
> the per-branch remote name and a pointer to the remote struct. However,
> they have no way of knowing about the per-branch pushremote from this
> interface. So, let's expose that information via fields similar to
> "remote" and "remote_name"; "pushremote" and "pushremote_name".

Makes sense. This is similar to what I posted before, but stops short of
setting branch->pushremote based on "default.pushremote". I think that's
a good thing. Your patch matches branch->remote better, and the logic
for doing that fallback should probably stay outside of the "struct
branch" construct.

All 3 patches look like sane building blocks to me.

One comment on this hunk, though:

>  		} else if (!strcmp(subkey, ".pushremote")) {
> +			if (git_config_string(&branch->pushremote_name, key, value))
> +				return -1;
>  			if (branch == current_branch)
> -				if (git_config_string(&pushremote_name, key, value))
> -					return -1;
> +				pushremote_name = branch->pushremote_name;

In this code (both before and after your patch), pushremote_name does
double-duty for storing both "remote.pushdefault", and the current
branch's "branch.*.pushremote". I introduced an extra variable in my
version of the patch to store "remote.pushdefault" directly, and turned
pushremote_name into an alias (either to the current branch config, or
to the global config).

I did that for two reasons, one minor and one that I think will come up
further in the topic:

  1. After your patch "pushremote_name" sometimes owns its memory (if
     allocated for remote.pushdefault), and sometimes not (if an alias to
     branch.*.pushremote). This isn't a problem in the current code,
     because we never actually free() the string, meaning that if you
     set push.default twice, we leak. But that probably does not matter
     too much, and we have many such minor leaks of global config.

  2. If the current branch has a branch.*.pushremote set, but we want to
     know where a _different_ branch would be pushed, we have no way to
     access remote.pushdefault (it gets overwritten in the hunk above).

     @{upstream} does not have this problem, because it is _only_
     defined if branch.*.remote is set. There is no such thing as
     defaulting to a "remote.default" (or "origin") there, and we never
     need to look at default_remote_name.

     For @{publish}, though, I think we will want that default. The
     common config will be to simply set "remote.pushdefault", rather
     than setting up "branch.*.pushremote" for each branch, and we would
     want @{publish} to handle that properly.

So I think your patch is OK as-is, as the problem in (2) does not show
up until later in the series. But I suspect you will need to do
something to address it (and I think it is fine as a patch that comes
later to do that refactoring).

-Peff

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

* Re: [PATCH 3/3] remote: introduce and fill branch->pushremote
  2014-01-13  8:34   ` Jeff King
@ 2014-01-13 11:22     ` Ramkumar Ramachandra
  2014-01-13 18:59       ` Jeff King
  0 siblings, 1 reply; 9+ messages in thread
From: Ramkumar Ramachandra @ 2014-01-13 11:22 UTC (permalink / raw)
  To: Jeff King; +Cc: Git List, Junio C Hamano

Jeff King wrote:
>   2. If the current branch has a branch.*.pushremote set, but we want to
>      know where a _different_ branch would be pushed, we have no way to
>      access remote.pushdefault (it gets overwritten in the hunk above).
>
>      @{upstream} does not have this problem, because it is _only_
>      defined if branch.*.remote is set. There is no such thing as
>      defaulting to a "remote.default" (or "origin") there, and we never
>      need to look at default_remote_name.
>
>      For @{publish}, though, I think we will want that default. The
>      common config will be to simply set "remote.pushdefault", rather
>      than setting up "branch.*.pushremote" for each branch, and we would
>      want @{publish} to handle that properly.

Not sure I understand what the problem is. Let's say we have two
branches: "master", and "side" with remote.pushdefault = ram,
branch.*.remote = origin, and branch.side.pushremote = peff. Now, when
I query master's pushremote, I get "ram" and when I query side's
pushremote, I get "peff"; all the logic for falling-back from
branch.*.pushremote to remote.pushdefault to branch.*.remote is in
branch_get(), so I need to do nothing extra on the caller-side. From
the caller's perspective, why does it matter if the pushremote of a
particular branch is due to branch.*.pushremote or remote.pushdefault?

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

* Re: [PATCH 3/3] remote: introduce and fill branch->pushremote
  2014-01-13 11:22     ` Ramkumar Ramachandra
@ 2014-01-13 18:59       ` Jeff King
  2014-01-13 20:15         ` Junio C Hamano
  0 siblings, 1 reply; 9+ messages in thread
From: Jeff King @ 2014-01-13 18:59 UTC (permalink / raw)
  To: Ramkumar Ramachandra; +Cc: Git List, Junio C Hamano

On Mon, Jan 13, 2014 at 04:52:52PM +0530, Ramkumar Ramachandra wrote:

> Not sure I understand what the problem is. Let's say we have two
> branches: "master", and "side" with remote.pushdefault = ram,
> branch.*.remote = origin, and branch.side.pushremote = peff. Now, when
> I query master's pushremote, I get "ram" and when I query side's
> pushremote, I get "peff"; all the logic for falling-back from
> branch.*.pushremote to remote.pushdefault to branch.*.remote is in
> branch_get(), so I need to do nothing extra on the caller-side. From
> the caller's perspective, why does it matter if the pushremote of a
> particular branch is due to branch.*.pushremote or remote.pushdefault?

Imagine your HEAD is at "side". What should "master@{publish}" produce?
I would argue "ram/master". Where does "ram" come from in your code?

It does not matter for actually pushing, because to do a non-default
push, you must always specify a remote. But "@{publish}" will ask the
question "even if I am on 'side' now, what would happen if I were to
default-push on 'master'?".

-Peff

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

* Re: [PATCH 3/3] remote: introduce and fill branch->pushremote
  2014-01-13 18:59       ` Jeff King
@ 2014-01-13 20:15         ` Junio C Hamano
  2014-01-13 20:27           ` Jeff King
  0 siblings, 1 reply; 9+ messages in thread
From: Junio C Hamano @ 2014-01-13 20:15 UTC (permalink / raw)
  To: Jeff King; +Cc: Ramkumar Ramachandra, Git List

Jeff King <peff@peff.net> writes:

> It does not matter for actually pushing, because to do a non-default
> push, you must always specify a remote. But "@{publish}" will ask the
> question "even if I am on 'side' now, what would happen if I were to
> default-push on 'master'?".

In a similar wording to yours, it can be said that B@{upstream} is
"what would happen if I were to default-pull on 'B'?".

A related tangent is what should B@{publish} should yield when there
is no triangular configuration variables like remote.pushdefault,
branch.B.pushremote and a possible future extension branch.B.push
are defined.  The definition you gave, i.e. "if I were to
default-push", gives a good guideline, I think.

I.e. "git push origin master" does tell us to push out 'master', but
it does not explicitly say what ref to update.  It may be set to
update their remotes/satellite/master when we are emulating a fetch
in reverse by pushing, via e.g.

	[remote "origin"]
        	push = refs/heads/master:refs/remotes/satellite/master

and it would be intuitive if we make "master@{publish}" resolve to
"refs/remotes/satellite/master" in such a case.

One thing that makes things a bit fuzzy is what should happen if
you have more than one push destinations.  For example:

	[remote "home"]
        	pushurl = ...
                push = refs/heads/master:refs/remotes/satellite/master

	[remote "github"]
        	pushurl = ...
                mirror

	[remote]
        	pushdefault = ???

"git push home" updates their 'refs/remotes/satellite/master' with
my 'master' with the above, while "git push github" will update
their 'refs/heads/master' with 'master'.

We can say master@{publish} is 'remotes/satellite/master' if
remote.pushdefault (or 'branch.master.pushremote") is set to 'home',
it is 'master' if it is 'github', and if "git push" while sitting on
'master' does not push it anywhere then master@{publish} is an
error.  There may be a better definition of what "if I were to
default-push" really means, but I don't think of any offhand.

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

* Re: [PATCH 3/3] remote: introduce and fill branch->pushremote
  2014-01-13 20:15         ` Junio C Hamano
@ 2014-01-13 20:27           ` Jeff King
  0 siblings, 0 replies; 9+ messages in thread
From: Jeff King @ 2014-01-13 20:27 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Ramkumar Ramachandra, Git List

On Mon, Jan 13, 2014 at 12:15:08PM -0800, Junio C Hamano wrote:

> Jeff King <peff@peff.net> writes:
> 
> > It does not matter for actually pushing, because to do a non-default
> > push, you must always specify a remote. But "@{publish}" will ask the
> > question "even if I am on 'side' now, what would happen if I were to
> > default-push on 'master'?".
> 
> In a similar wording to yours, it can be said that B@{upstream} is
> "what would happen if I were to default-pull on 'B'?".

Right. I wondered at first if there was a similar bug in @{upstream},
but as I noted earlier, it is not defined if a per-branch remote is not
set. The answer to your question above is "nothing", so we do not have
to worry about it. :)

> A related tangent is what should B@{publish} should yield when there
> is no triangular configuration variables like remote.pushdefault,
> branch.B.pushremote and a possible future extension branch.B.push
> are defined.  The definition you gave, i.e. "if I were to
> default-push", gives a good guideline, I think.

Yes, that is what I tried for with my original patches. (e.g.,
"push.default=upstream" should just make @{publish} a synonym for
@{upstream}, which is what my patch did). I punted on "simple", but it
would ideally do the same thing as "push". Which is why I do not think
my patches are appropriate as-is; they need to somehow share the logic
with "git push" rather than try to reimplement it.

> I.e. "git push origin master" does tell us to push out 'master', but
> it does not explicitly say what ref to update.  It may be set to
> update their remotes/satellite/master when we are emulating a fetch
> in reverse by pushing, via e.g.
> 
> 	[remote "origin"]
>         	push = refs/heads/master:refs/remotes/satellite/master
> 
> and it would be intuitive if we make "master@{publish}" resolve to
> "refs/remotes/satellite/master" in such a case.

Right. And my patches did that (or at least I intended them to :) ) by
applying the push refspec (if any), and then applying the fetch refspec
on top of that. But again, that seems like policy that should be shared
with "git push".

That being said, I do not think your example is the best one for
@{publish}. You have not specified any remote at all. I think the
closest "push" behavior for @{publish} would be something like:

  git checkout master && git push

I.e., where would _that_ push go?

> One thing that makes things a bit fuzzy is what should happen if
> you have more than one push destinations.  For example:
> 
> 	[remote "home"]
>         	pushurl = ...
>                 push = refs/heads/master:refs/remotes/satellite/master
> 
> 	[remote "github"]
>         	pushurl = ...
>                 mirror
> 
> 	[remote]
>         	pushdefault = ???
> 
> "git push home" updates their 'refs/remotes/satellite/master' with
> my 'master' with the above, while "git push github" will update
> their 'refs/heads/master' with 'master'.
> 
> We can say master@{publish} is 'remotes/satellite/master' if
> remote.pushdefault (or 'branch.master.pushremote") is set to 'home',
> it is 'master' if it is 'github', and if "git push" while sitting on
> 'master' does not push it anywhere then master@{publish} is an
> error.  There may be a better definition of what "if I were to
> default-push" really means, but I don't think of any offhand.

Exactly.  I do not think the multiple push destinations matter here,
because it is always "what would I do if I were on the branch".  At most
one of them can be the default in that case (based on the config as you
noted).

-Peff

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

end of thread, other threads:[~2014-01-13 20:27 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-01-12 17:11 [PATCH 0/3] Minor preparation for @{publish} Ramkumar Ramachandra
2014-01-12 17:11 ` [PATCH 1/3] t1507 (rev-parse-upstream): fix typo in test title Ramkumar Ramachandra
2014-01-12 17:11 ` [PATCH 2/3] interpret_branch_name: factor out upstream handling Ramkumar Ramachandra
2014-01-12 17:11 ` [PATCH 3/3] remote: introduce and fill branch->pushremote Ramkumar Ramachandra
2014-01-13  8:34   ` Jeff King
2014-01-13 11:22     ` Ramkumar Ramachandra
2014-01-13 18:59       ` Jeff King
2014-01-13 20:15         ` Junio C Hamano
2014-01-13 20:27           ` Jeff King

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).