static const char **refspec;
static int refspec_nr;
static int refspec_alloc;
-static int default_matching_used;
static void add_refspec(const char *ref)
{
}
if (push_default == PUSH_DEFAULT_UPSTREAM &&
- !prefixcmp(matched->name, "refs/heads/")) {
+ starts_with(matched->name, "refs/heads/")) {
struct branch *branch = branch_get(matched->name + 11);
if (branch->merge_nr == 1 && branch->merge[0]->src) {
struct strbuf buf = STRBUF_INIT;
* them the big ugly fully qualified ref.
*/
const char *advice_maybe = "";
- const char *short_upstream =
- skip_prefix(branch->merge[0]->src, "refs/heads/");
+ const char *short_upstream = branch->merge[0]->src;
+
+ skip_prefix(short_upstream, "refs/heads/", &short_upstream);
- if (!short_upstream)
- short_upstream = branch->merge[0]->src;
/*
* Don't show advice for people who explicitly set
* push.default.
" git push %s HEAD:<name-of-remote-branch>\n");
static void setup_push_upstream(struct remote *remote, struct branch *branch,
- int triangular)
+ int triangular, int simple)
{
struct strbuf refspec = STRBUF_INIT;
"to update which remote branch."),
remote->name, branch->name);
- if (push_default == PUSH_DEFAULT_SIMPLE) {
+ if (simple) {
/* Additional safety */
if (strcmp(branch->refname, branch->merge[0]->src))
die_push_simple(branch, remote);
}
static char warn_unspecified_push_default_msg[] =
-N_("push.default is unset; its implicit value is changing in\n"
+N_("push.default is unset; its implicit value has changed in\n"
"Git 2.0 from 'matching' to 'simple'. To squelch this message\n"
- "and maintain the current behavior after the default changes, use:\n"
+ "and maintain the traditional behavior, use:\n"
"\n"
" git config --global push.default matching\n"
"\n"
"When push.default is set to 'matching', git will push local branches\n"
"to the remote branches that already exist with the same name.\n"
"\n"
- "In Git 2.0, Git will default to the more conservative 'simple'\n"
+ "Since Git 2.0, Git defaults to the more conservative 'simple'\n"
"behavior, which only pushes the current branch to the corresponding\n"
"remote branch that 'git pull' uses to update the current branch.\n"
"\n"
switch (push_default) {
default:
- case PUSH_DEFAULT_UNSPECIFIED:
- default_matching_used = 1;
- warn_unspecified_push_default_configuration();
- /* fallthru */
case PUSH_DEFAULT_MATCHING:
add_refspec(":");
break;
+ case PUSH_DEFAULT_UNSPECIFIED:
+ warn_unspecified_push_default_configuration();
+ /* fallthru */
+
case PUSH_DEFAULT_SIMPLE:
if (triangular)
setup_push_current(remote, branch);
else
- setup_push_upstream(remote, branch, triangular);
+ setup_push_upstream(remote, branch, triangular, 1);
break;
case PUSH_DEFAULT_UPSTREAM:
- setup_push_upstream(remote, branch, triangular);
+ setup_push_upstream(remote, branch, triangular, 0);
break;
case PUSH_DEFAULT_CURRENT:
"'git pull ...') before pushing again.\n"
"See the 'Note about fast-forwards' in 'git push --help' for details.");
-static const char message_advice_use_upstream[] =
- N_("Updates were rejected because a pushed branch tip is behind its remote\n"
- "counterpart. If you did not intend to push that branch, you may want to\n"
- "specify branches to push or set the 'push.default' configuration variable\n"
- "to 'simple', 'current' or 'upstream' to push only the current branch.");
-
static const char message_advice_checkout_pull_push[] =
N_("Updates were rejected because a pushed branch tip is behind its remote\n"
"counterpart. Check out this branch and integrate the remote changes\n"
advise(_(message_advice_pull_before_push));
}
-static void advise_use_upstream(void)
-{
- if (!advice_push_non_ff_default || !advice_push_update_rejected)
- return;
- advise(_(message_advice_use_upstream));
-}
-
static void advise_checkout_pull_push(void)
{
if (!advice_push_non_ff_matching || !advice_push_update_rejected)
if (reject_reasons & REJECT_NON_FF_HEAD) {
advise_pull_before_push();
} else if (reject_reasons & REJECT_NON_FF_OTHER) {
- if (default_matching_used)
- advise_use_upstream();
- else
- advise_checkout_pull_push();
+ advise_checkout_pull_push();
} else if (reject_reasons & REJECT_ALREADY_EXISTS) {
advise_ref_already_exists();
} else if (reject_reasons & REJECT_FETCH_FIRST) {
return 0;
}
+static int git_push_config(const char *k, const char *v, void *cb)
+{
+ struct wt_status *s = cb;
+ int status;
+
+ status = git_gpg_config(k, v, NULL);
+ if (status)
+ return status;
+ return git_default_config(k, v, s);
+}
+
int cmd_push(int argc, const char **argv, const char *prefix)
{
int flags = 0;
int tags = 0;
int rc;
+ int atomic = 0;
const char *repo = NULL; /* default repository */
struct option options[] = {
OPT__VERBOSITY(&verbosity),
0, CAS_OPT_NAME, &cas, N_("refname>:<expect"),
N_("require old value of ref to be at this value"),
PARSE_OPT_OPTARG, parseopt_push_cas_option },
- { OPTION_CALLBACK, 0, "recurse-submodules", &flags, N_("check"),
+ { OPTION_CALLBACK, 0, "recurse-submodules", &flags, "check|on-demand",
N_("control recursive pushing of submodules"),
PARSE_OPT_OPTARG, option_parse_recurse_submodules },
OPT_BOOL( 0 , "thin", &thin, N_("use thin pack")),
OPT_BIT(0, "no-verify", &flags, N_("bypass pre-push hook"), TRANSPORT_PUSH_NO_HOOK),
OPT_BIT(0, "follow-tags", &flags, N_("push missing but relevant tags"),
TRANSPORT_PUSH_FOLLOW_TAGS),
+ OPT_BIT(0, "signed", &flags, N_("GPG sign the push"), TRANSPORT_PUSH_CERT),
+ OPT_BOOL(0, "atomic", &atomic, N_("request atomic transaction on remote side")),
OPT_END()
};
packet_trace_identity("push");
- git_config(git_default_config, NULL);
+ git_config(git_push_config, NULL);
argc = parse_options(argc, argv, prefix, options, push_usage, 0);
if (deleterefs && (tags || (flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR))))
if (tags)
add_refspec("refs/tags/*");
+ if (atomic)
+ flags |= TRANSPORT_PUSH_ATOMIC;
+
if (argc > 0) {
repo = argv[0];
set_refspecs(argv + 1, argc - 1, repo);