Skip to content

Commit 5215374

Browse files
Finn Arne Gangstadgitster
authored andcommitted
New config push.default to decide default behavior for push
When "git push" is not told what refspecs to push, it pushes all matching branches to the current remote. For some workflows this default is not useful, and surprises new users. Some have even found that this default behaviour is too easy to trigger by accident with unwanted consequences. Introduce a new configuration variable "push.default" that decides what action git push should take if no refspecs are given or implied by the command line arguments or the current remote configuration. Possible values are: 'nothing' : Push nothing; 'matching' : Current default behaviour, push all branches that already exist in the current remote; 'tracking' : Push the current branch to whatever it is tracking; 'current' : Push the current branch to a branch of the same name, i.e. HEAD. Signed-off-by: Finn Arne Gangstad <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 52e7787 commit 5215374

File tree

5 files changed

+104
-5
lines changed

5 files changed

+104
-5
lines changed

Documentation/config.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,6 +1160,24 @@ pull.octopus::
11601160
pull.twohead::
11611161
The default merge strategy to use when pulling a single branch.
11621162

1163+
push.default::
1164+
Defines the action git push should take if no refspec is given
1165+
on the command line, no refspec is configured in the remote, and
1166+
no refspec is implied by any of the options given on the command
1167+
line.
1168+
+
1169+
The term `current remote` means the remote configured for the current
1170+
branch, or `origin` if no remote is configured. `origin` is also used
1171+
if you are not on any branch. Possible values are:
1172+
+
1173+
* `nothing` do not push anything.
1174+
* `matching` push all matching branches to the current remote.
1175+
All branches having the same name in both ends are considered to be
1176+
matching. This is the current default value.
1177+
* `tracking` push the current branch to the branch it is tracking.
1178+
* `current` push the current branch to a branch of the same name on the
1179+
current remote.
1180+
11631181
receive.fsckObjects::
11641182
If it is set to true, git-receive-pack will check all received
11651183
objects. It will abort in the case of a malformed object or a

builtin-push.c

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,48 @@ static void set_refspecs(const char **refs, int nr)
4848
}
4949
}
5050

51+
static void setup_push_tracking(void)
52+
{
53+
struct strbuf refspec = STRBUF_INIT;
54+
struct branch *branch = branch_get(NULL);
55+
if (!branch)
56+
die("You are not currently on a branch.");
57+
if (!branch->merge_nr)
58+
die("The current branch %s is not tracking anything.",
59+
branch->name);
60+
if (branch->merge_nr != 1)
61+
die("The current branch %s is tracking multiple branches, "
62+
"refusing to push.", branch->name);
63+
strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src);
64+
add_refspec(refspec.buf);
65+
}
66+
67+
static void setup_default_push_refspecs(void)
68+
{
69+
git_config(git_default_config, NULL);
70+
switch (push_default) {
71+
case PUSH_DEFAULT_UNSPECIFIED:
72+
/* fallthrough */
73+
74+
case PUSH_DEFAULT_MATCHING:
75+
add_refspec(":");
76+
break;
77+
78+
case PUSH_DEFAULT_TRACKING:
79+
setup_push_tracking();
80+
break;
81+
82+
case PUSH_DEFAULT_CURRENT:
83+
add_refspec("HEAD");
84+
break;
85+
86+
case PUSH_DEFAULT_NOTHING:
87+
die("You didn't specify any refspecs to push, and "
88+
"push.default is \"nothing\".");
89+
break;
90+
}
91+
}
92+
5193
static int do_push(const char *repo, int flags)
5294
{
5395
int i, errs;
@@ -76,11 +118,12 @@ static int do_push(const char *repo, int flags)
76118
return error("--all and --mirror are incompatible");
77119
}
78120

79-
if (!refspec
80-
&& !(flags & TRANSPORT_PUSH_ALL)
81-
&& remote->push_refspec_nr) {
82-
refspec = remote->push_refspec;
83-
refspec_nr = remote->push_refspec_nr;
121+
if (!refspec && !(flags & TRANSPORT_PUSH_ALL)) {
122+
if (remote->push_refspec_nr) {
123+
refspec = remote->push_refspec;
124+
refspec_nr = remote->push_refspec_nr;
125+
} else if (!(flags & TRANSPORT_PUSH_MIRROR))
126+
setup_default_push_refspecs();
84127
}
85128
errs = 0;
86129
for (i = 0; i < remote->url_nr; i++) {

cache.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,8 +541,17 @@ enum rebase_setup_type {
541541
AUTOREBASE_ALWAYS,
542542
};
543543

544+
enum push_default_type {
545+
PUSH_DEFAULT_UNSPECIFIED = -1,
546+
PUSH_DEFAULT_NOTHING = 0,
547+
PUSH_DEFAULT_MATCHING,
548+
PUSH_DEFAULT_TRACKING,
549+
PUSH_DEFAULT_CURRENT,
550+
};
551+
544552
extern enum branch_track git_branch_track;
545553
extern enum rebase_setup_type autorebase;
554+
extern enum push_default_type push_default;
546555

547556
#define GIT_REPO_VERSION 0
548557
extern int repository_format_version;

config.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,31 @@ static int git_default_branch_config(const char *var, const char *value)
565565
return 0;
566566
}
567567

568+
static int git_default_push_config(const char *var, const char *value)
569+
{
570+
if (!strcmp(var, "push.default")) {
571+
if (!value)
572+
return config_error_nonbool(var);
573+
else if (!strcmp(value, "nothing"))
574+
push_default = PUSH_DEFAULT_NOTHING;
575+
else if (!strcmp(value, "matching"))
576+
push_default = PUSH_DEFAULT_MATCHING;
577+
else if (!strcmp(value, "tracking"))
578+
push_default = PUSH_DEFAULT_TRACKING;
579+
else if (!strcmp(value, "current"))
580+
push_default = PUSH_DEFAULT_CURRENT;
581+
else {
582+
error("Malformed value for %s: %s", var, value);
583+
return error("Must be one of nothing, matching, "
584+
"tracking or current.");
585+
}
586+
return 0;
587+
}
588+
589+
/* Add other config variables here and to Documentation/config.txt. */
590+
return 0;
591+
}
592+
568593
static int git_default_mailmap_config(const char *var, const char *value)
569594
{
570595
if (!strcmp(var, "mailmap.file"))
@@ -588,6 +613,9 @@ int git_default_config(const char *var, const char *value, void *dummy)
588613
if (!prefixcmp(var, "branch."))
589614
return git_default_branch_config(var, value);
590615

616+
if (!prefixcmp(var, "push."))
617+
return git_default_push_config(var, value);
618+
591619
if (!prefixcmp(var, "mailmap."))
592620
return git_default_mailmap_config(var, value);
593621

environment.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ enum safe_crlf safe_crlf = SAFE_CRLF_WARN;
4242
unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
4343
enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;
4444
enum rebase_setup_type autorebase = AUTOREBASE_NEVER;
45+
enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;
4546

4647
/* Parallel index stat data preload? */
4748
int core_preload_index = 0;

0 commit comments

Comments
 (0)