Skip to content

Commit

Permalink
Merge branch 'rr/triangle'
Browse files Browse the repository at this point in the history
Support "pull from one place, push to another place" workflow
better by introducing remote.pushdefault (overrides the "origin"
thing) and branch.*.pushremote (overrides the branch.*.remote).

* rr/triangle:
  remote.c: introduce branch.<name>.pushremote
  remote.c: introduce remote.pushdefault
  remote.c: introduce a way to have different remotes for fetch/push
  t5516 (fetch-push): drop implicit arguments from helper functions
  t5516 (fetch-push): update test description
  remote.c: simplify a bit of code using git_config_string()
  • Loading branch information
Junio C Hamano committed Apr 7, 2013
2 parents e64734b + 9f765ce commit 4d35924
Show file tree
Hide file tree
Showing 5 changed files with 241 additions and 149 deletions.
24 changes: 21 additions & 3 deletions Documentation/config.txt
Original file line number Diff line number Diff line change
Expand Up @@ -727,9 +727,22 @@ branch.autosetuprebase::
This option defaults to never.

branch.<name>.remote::
When in branch <name>, it tells 'git fetch' and 'git push' which
remote to fetch from/push to. It defaults to `origin` if no remote is
configured. `origin` is also used if you are not on any branch.
When on branch <name>, it tells 'git fetch' and 'git push'
which remote to fetch from/push to. The remote to push to
may be overridden with `remote.pushdefault` (for all branches).
The remote to push to, for the current branch, may be further
overridden by `branch.<name>.pushremote`. If no remote is
configured, or if you are not on any branch, it defaults to
`origin` for fetching and `remote.pushdefault` for pushing.

branch.<name>.pushremote::
When on branch <name>, it overrides `branch.<name>.remote` for
pushing. It also overrides `remote.pushdefault` for pushing
from branch <name>. When you pull from one place (e.g. your
upstream) and push to another place (e.g. your own publishing
repository), you would want to set `remote.pushdefault` to
specify the remote to push to for all branches, and use this
option to override it for a specific branch.

branch.<name>.merge::
Defines, together with branch.<name>.remote, the upstream branch
Expand Down Expand Up @@ -1898,6 +1911,11 @@ receive.updateserverinfo::
If set to true, git-receive-pack will run git-update-server-info
after receiving data from git-push and updating refs.

remote.pushdefault::
The remote to push to by default. Overrides
`branch.<name>.remote` for all branches, and is overridden by
`branch.<name>.pushremote` for specific branches.

remote.<name>.url::
The URL of a remote repository. See linkgit:git-fetch[1] or
linkgit:git-push[1].
Expand Down
2 changes: 1 addition & 1 deletion builtin/push.c
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ static int push_with_options(struct transport *transport, int flags)
static int do_push(const char *repo, int flags)
{
int i, errs;
struct remote *remote = remote_get(repo);
struct remote *remote = pushremote_get(repo);
const char **url;
int url_nr;

Expand Down
41 changes: 34 additions & 7 deletions remote.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ static int branches_nr;

static struct branch *current_branch;
static const char *default_remote_name;
static const char *pushremote_name;
static int explicit_default_remote_name;

static struct rewrites rewrites;
Expand Down Expand Up @@ -357,13 +358,16 @@ static int handle_config(const char *key, const char *value, void *cb)
return 0;
branch = make_branch(name, subkey - name);
if (!strcmp(subkey, ".remote")) {
if (!value)
return config_error_nonbool(key);
branch->remote_name = xstrdup(value);
if (git_config_string(&branch->remote_name, key, value))
return -1;
if (branch == current_branch) {
default_remote_name = branch->remote_name;
explicit_default_remote_name = 1;
}
} else if (!strcmp(subkey, ".pushremote")) {
if (branch == current_branch)
if (git_config_string(&pushremote_name, key, value))
return -1;
} else if (!strcmp(subkey, ".merge")) {
if (!value)
return config_error_nonbool(key);
Expand All @@ -389,9 +393,16 @@ static int handle_config(const char *key, const char *value, void *cb)
add_instead_of(rewrite, xstrdup(value));
}
}

if (prefixcmp(key, "remote."))
return 0;
name = key + 7;

/* Handle remote.* variables */
if (!strcmp(name, "pushdefault"))
return git_config_string(&pushremote_name, key, value);

/* Handle remote.<name>.* variables */
if (*name == '/') {
warning("Config remote shorthand cannot begin with '/': %s",
name);
Expand Down Expand Up @@ -671,17 +682,21 @@ static int valid_remote_nick(const char *name)
return !strchr(name, '/'); /* no slash */
}

struct remote *remote_get(const char *name)
static struct remote *remote_get_1(const char *name, const char *pushremote_name)
{
struct remote *ret;
int name_given = 0;

read_config();
if (name)
name_given = 1;
else {
name = default_remote_name;
name_given = explicit_default_remote_name;
if (pushremote_name) {
name = pushremote_name;
name_given = 1;
} else {
name = default_remote_name;
name_given = explicit_default_remote_name;
}
}

ret = make_remote(name, 0);
Expand All @@ -700,6 +715,18 @@ struct remote *remote_get(const char *name)
return ret;
}

struct remote *remote_get(const char *name)
{
read_config();
return remote_get_1(name, NULL);
}

struct remote *pushremote_get(const char *name)
{
read_config();
return remote_get_1(name, pushremote_name);
}

int remote_is_configured(const char *name)
{
int i;
Expand Down
1 change: 1 addition & 0 deletions remote.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ struct remote {
};

struct remote *remote_get(const char *name);
struct remote *pushremote_get(const char *name);
int remote_is_configured(const char *name);

typedef int each_remote_fn(struct remote *remote, void *priv);
Expand Down
Loading

0 comments on commit 4d35924

Please sign in to comment.