Skip to content

Commit

Permalink
Merge branch 'fg/push-default'
Browse files Browse the repository at this point in the history
* fg/push-default:
  builtin-push.c: Fix typo: "anythig" -> "anything"
  Display warning for default git push with no push.default config
  New config push.default to decide default behavior for push

Conflicts:
	Documentation/config.txt
  • Loading branch information
gitster committed Mar 26, 2009
2 parents 0b3035f + b2655cd commit 2545c08
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 5 deletions.
7 changes: 7 additions & 0 deletions Documentation/RelNotes-1.6.3.txt
Expand Up @@ -22,6 +22,13 @@ branch pointed at by its HEAD, gets a large warning. You can choose what
should happen upon such a push by setting the configuration variable
receive.denyDeleteCurrent in the receiving repository.

In a future release, the default of "git push" without further
arguments might be changed. Currently, it will push all matching
refspecs to the current remote. A configuration variable push.default
has been introduced to select the default behaviour. To ease the
transition, a big warning is issued if this is not configured and a
git push without arguments is attempted.


Updates since v1.6.2
--------------------
Expand Down
18 changes: 18 additions & 0 deletions Documentation/config.txt
Expand Up @@ -1194,6 +1194,24 @@ pull.octopus::
pull.twohead::
The default merge strategy to use when pulling a single branch.

push.default::
Defines the action git push should take if no refspec is given
on the command line, no refspec is configured in the remote, and
no refspec is implied by any of the options given on the command
line.
+
The term `current remote` means the remote configured for the current
branch, or `origin` if no remote is configured. `origin` is also used
if you are not on any branch. Possible values are:
+
* `nothing` do not push anything.
* `matching` push all matching branches to the current remote.
All branches having the same name in both ends are considered to be
matching. This is the current default value.
* `tracking` push the current branch to the branch it is tracking.
* `current` push the current branch to a branch of the same name on the
current remote.

rebase.stat::
Whether to show a diffstat of what changed upstream since the last
rebase. False by default.
Expand Down
76 changes: 71 additions & 5 deletions builtin-push.c
Expand Up @@ -48,6 +48,71 @@ static void set_refspecs(const char **refs, int nr)
}
}

static void setup_push_tracking(void)
{
struct strbuf refspec = STRBUF_INIT;
struct branch *branch = branch_get(NULL);
if (!branch)
die("You are not currently on a branch.");
if (!branch->merge_nr)
die("The current branch %s is not tracking anything.",
branch->name);
if (branch->merge_nr != 1)
die("The current branch %s is tracking multiple branches, "
"refusing to push.", branch->name);
strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src);
add_refspec(refspec.buf);
}

static const char *warn_unconfigured_push_msg[] = {
"You did not specify any refspecs to push, and the current remote",
"has not configured any push refspecs. The default action in this",
"case is to push all matching refspecs, that is, all branches",
"that exist both locally and remotely will be updated. This may",
"not necessarily be what you want to happen.",
"",
"You can specify what action you want to take in this case, and",
"avoid seeing this message again, by configuring 'push.default' to:",
" 'nothing' : Do not push anything",
" 'matching' : Push all matching branches (default)",
" 'tracking' : Push the current branch to whatever it is tracking",
" 'current' : Push the current branch"
};

static void warn_unconfigured_push(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(warn_unconfigured_push_msg); i++)
warning("%s", warn_unconfigured_push_msg[i]);
}

static void setup_default_push_refspecs(void)
{
git_config(git_default_config, NULL);
switch (push_default) {
case PUSH_DEFAULT_UNSPECIFIED:
warn_unconfigured_push();
/* fallthrough */

case PUSH_DEFAULT_MATCHING:
add_refspec(":");
break;

case PUSH_DEFAULT_TRACKING:
setup_push_tracking();
break;

case PUSH_DEFAULT_CURRENT:
add_refspec("HEAD");
break;

case PUSH_DEFAULT_NOTHING:
die("You didn't specify any refspecs to push, and "
"push.default is \"nothing\".");
break;
}
}

static int do_push(const char *repo, int flags)
{
int i, errs;
Expand Down Expand Up @@ -79,11 +144,12 @@ static int do_push(const char *repo, int flags)
return error("--all and --mirror are incompatible");
}

if (!refspec
&& !(flags & TRANSPORT_PUSH_ALL)
&& remote->push_refspec_nr) {
refspec = remote->push_refspec;
refspec_nr = remote->push_refspec_nr;
if (!refspec && !(flags & TRANSPORT_PUSH_ALL)) {
if (remote->push_refspec_nr) {
refspec = remote->push_refspec;
refspec_nr = remote->push_refspec_nr;
} else if (!(flags & TRANSPORT_PUSH_MIRROR))
setup_default_push_refspecs();
}
errs = 0;
for (i = 0; i < remote->url_nr; i++) {
Expand Down
9 changes: 9 additions & 0 deletions cache.h
Expand Up @@ -542,8 +542,17 @@ enum rebase_setup_type {
AUTOREBASE_ALWAYS,
};

enum push_default_type {
PUSH_DEFAULT_UNSPECIFIED = -1,
PUSH_DEFAULT_NOTHING = 0,
PUSH_DEFAULT_MATCHING,
PUSH_DEFAULT_TRACKING,
PUSH_DEFAULT_CURRENT,
};

extern enum branch_track git_branch_track;
extern enum rebase_setup_type autorebase;
extern enum push_default_type push_default;

#define GIT_REPO_VERSION 0
extern int repository_format_version;
Expand Down
28 changes: 28 additions & 0 deletions config.c
Expand Up @@ -565,6 +565,31 @@ static int git_default_branch_config(const char *var, const char *value)
return 0;
}

static int git_default_push_config(const char *var, const char *value)
{
if (!strcmp(var, "push.default")) {
if (!value)
return config_error_nonbool(var);
else if (!strcmp(value, "nothing"))
push_default = PUSH_DEFAULT_NOTHING;
else if (!strcmp(value, "matching"))
push_default = PUSH_DEFAULT_MATCHING;
else if (!strcmp(value, "tracking"))
push_default = PUSH_DEFAULT_TRACKING;
else if (!strcmp(value, "current"))
push_default = PUSH_DEFAULT_CURRENT;
else {
error("Malformed value for %s: %s", var, value);
return error("Must be one of nothing, matching, "
"tracking or current.");
}
return 0;
}

/* Add other config variables here and to Documentation/config.txt. */
return 0;
}

static int git_default_mailmap_config(const char *var, const char *value)
{
if (!strcmp(var, "mailmap.file"))
Expand All @@ -588,6 +613,9 @@ int git_default_config(const char *var, const char *value, void *dummy)
if (!prefixcmp(var, "branch."))
return git_default_branch_config(var, value);

if (!prefixcmp(var, "push."))
return git_default_push_config(var, value);

if (!prefixcmp(var, "mailmap."))
return git_default_mailmap_config(var, value);

Expand Down
1 change: 1 addition & 0 deletions environment.c
Expand Up @@ -42,6 +42,7 @@ enum safe_crlf safe_crlf = SAFE_CRLF_WARN;
unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;
enum rebase_setup_type autorebase = AUTOREBASE_NEVER;
enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;

/* Parallel index stat data preload? */
int core_preload_index = 0;
Expand Down

0 comments on commit 2545c08

Please sign in to comment.