Merge branch 'fg/push-default'
* 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
This commit is contained in:
commit
2545c089e3
@ -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
|
||||
--------------------
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
@ -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++) {
|
||||
|
9
cache.h
9
cache.h
@ -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;
|
||||
|
28
config.c
28
config.c
@ -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"))
|
||||
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user