builtin / push.con commit push: Provide situational hints for non-fast-forward errors (f25950f)
   1/*
   2 * "git push"
   3 */
   4#include "cache.h"
   5#include "refs.h"
   6#include "run-command.h"
   7#include "builtin.h"
   8#include "remote.h"
   9#include "transport.h"
  10#include "parse-options.h"
  11#include "submodule.h"
  12
  13static const char * const push_usage[] = {
  14        "git push [<options>] [<repository> [<refspec>...]]",
  15        NULL,
  16};
  17
  18static int thin;
  19static int deleterefs;
  20static const char *receivepack;
  21static int verbosity;
  22static int progress = -1;
  23
  24static const char **refspec;
  25static int refspec_nr;
  26static int refspec_alloc;
  27static int default_matching_used;
  28
  29static void add_refspec(const char *ref)
  30{
  31        refspec_nr++;
  32        ALLOC_GROW(refspec, refspec_nr, refspec_alloc);
  33        refspec[refspec_nr-1] = ref;
  34}
  35
  36static void set_refspecs(const char **refs, int nr)
  37{
  38        int i;
  39        for (i = 0; i < nr; i++) {
  40                const char *ref = refs[i];
  41                if (!strcmp("tag", ref)) {
  42                        char *tag;
  43                        int len;
  44                        if (nr <= ++i)
  45                                die(_("tag shorthand without <tag>"));
  46                        len = strlen(refs[i]) + 11;
  47                        if (deleterefs) {
  48                                tag = xmalloc(len+1);
  49                                strcpy(tag, ":refs/tags/");
  50                        } else {
  51                                tag = xmalloc(len);
  52                                strcpy(tag, "refs/tags/");
  53                        }
  54                        strcat(tag, refs[i]);
  55                        ref = tag;
  56                } else if (deleterefs && !strchr(ref, ':')) {
  57                        char *delref;
  58                        int len = strlen(ref)+1;
  59                        delref = xmalloc(len+1);
  60                        strcpy(delref, ":");
  61                        strcat(delref, ref);
  62                        ref = delref;
  63                } else if (deleterefs)
  64                        die(_("--delete only accepts plain target ref names"));
  65                add_refspec(ref);
  66        }
  67}
  68
  69static void setup_push_upstream(struct remote *remote)
  70{
  71        struct strbuf refspec = STRBUF_INIT;
  72        struct branch *branch = branch_get(NULL);
  73        if (!branch)
  74                die(_("You are not currently on a branch.\n"
  75                    "To push the history leading to the current (detached HEAD)\n"
  76                    "state now, use\n"
  77                    "\n"
  78                    "    git push %s HEAD:<name-of-remote-branch>\n"),
  79                    remote->name);
  80        if (!branch->merge_nr || !branch->merge)
  81                die(_("The current branch %s has no upstream branch.\n"
  82                    "To push the current branch and set the remote as upstream, use\n"
  83                    "\n"
  84                    "    git push --set-upstream %s %s\n"),
  85                    branch->name,
  86                    remote->name,
  87                    branch->name);
  88        if (branch->merge_nr != 1)
  89                die(_("The current branch %s has multiple upstream branches, "
  90                    "refusing to push."), branch->name);
  91        strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src);
  92        add_refspec(refspec.buf);
  93}
  94
  95static void setup_default_push_refspecs(struct remote *remote)
  96{
  97        switch (push_default) {
  98        default:
  99        case PUSH_DEFAULT_UNSPECIFIED:
 100                default_matching_used = 1;
 101                /* fallthru */
 102        case PUSH_DEFAULT_MATCHING:
 103                add_refspec(":");
 104                break;
 105
 106        case PUSH_DEFAULT_UPSTREAM:
 107                setup_push_upstream(remote);
 108                break;
 109
 110        case PUSH_DEFAULT_CURRENT:
 111                add_refspec("HEAD");
 112                break;
 113
 114        case PUSH_DEFAULT_NOTHING:
 115                die(_("You didn't specify any refspecs to push, and "
 116                    "push.default is \"nothing\"."));
 117                break;
 118        }
 119}
 120
 121static const char message_advice_pull_before_push[] =
 122        N_("Updates were rejected because the tip of your current branch is behind\n"
 123           "its remote counterpart. Merge the remote changes (e.g. 'git pull')\n"
 124           "before pushing again.\n"
 125           "See the 'Note about fast-forwards' in 'git push --help' for details.");
 126
 127static const char message_advice_use_upstream[] =
 128        N_("Updates were rejected because a pushed branch tip is behind its remote\n"
 129           "counterpart. If you did not intend to push that branch, you may want to\n"
 130           "specify branches to push or set the 'push.default' configuration\n"
 131           "variable to 'current' or 'upstream' to push only the current branch.");
 132
 133static const char message_advice_checkout_pull_push[] =
 134        N_("Updates were rejected because a pushed branch tip is behind its remote\n"
 135           "counterpart. Check out this branch and merge the remote changes\n"
 136           "(e.g. 'git pull') before pushing again.\n"
 137           "See the 'Note about fast-forwards' in 'git push --help' for details.");
 138
 139static void advise_pull_before_push(void)
 140{
 141        if (!advice_push_non_ff_current || !advice_push_nonfastforward)
 142                return;
 143        advise(_(message_advice_pull_before_push));
 144}
 145
 146static void advise_use_upstream(void)
 147{
 148        if (!advice_push_non_ff_default || !advice_push_nonfastforward)
 149                return;
 150        advise(_(message_advice_use_upstream));
 151}
 152
 153static void advise_checkout_pull_push(void)
 154{
 155        if (!advice_push_non_ff_matching || !advice_push_nonfastforward)
 156                return;
 157        advise(_(message_advice_checkout_pull_push));
 158}
 159
 160static int push_with_options(struct transport *transport, int flags)
 161{
 162        int err;
 163        int nonfastforward;
 164
 165        transport_set_verbosity(transport, verbosity, progress);
 166
 167        if (receivepack)
 168                transport_set_option(transport,
 169                                     TRANS_OPT_RECEIVEPACK, receivepack);
 170        if (thin)
 171                transport_set_option(transport, TRANS_OPT_THIN, "yes");
 172
 173        if (verbosity > 0)
 174                fprintf(stderr, _("Pushing to %s\n"), transport->url);
 175        err = transport_push(transport, refspec_nr, refspec, flags,
 176                             &nonfastforward);
 177        if (err != 0)
 178                error(_("failed to push some refs to '%s'"), transport->url);
 179
 180        err |= transport_disconnect(transport);
 181        if (!err)
 182                return 0;
 183
 184        switch (nonfastforward) {
 185        default:
 186                break;
 187        case NON_FF_HEAD:
 188                advise_pull_before_push();
 189                break;
 190        case NON_FF_OTHER:
 191                if (default_matching_used)
 192                        advise_use_upstream();
 193                else
 194                        advise_checkout_pull_push();
 195                break;
 196        }
 197
 198        return 1;
 199}
 200
 201static int do_push(const char *repo, int flags)
 202{
 203        int i, errs;
 204        struct remote *remote = remote_get(repo);
 205        const char **url;
 206        int url_nr;
 207
 208        if (!remote) {
 209                if (repo)
 210                        die(_("bad repository '%s'"), repo);
 211                die(_("No configured push destination.\n"
 212                    "Either specify the URL from the command-line or configure a remote repository using\n"
 213                    "\n"
 214                    "    git remote add <name> <url>\n"
 215                    "\n"
 216                    "and then push using the remote name\n"
 217                    "\n"
 218                    "    git push <name>\n"));
 219        }
 220
 221        if (remote->mirror)
 222                flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
 223
 224        if ((flags & TRANSPORT_PUSH_ALL) && refspec) {
 225                if (!strcmp(*refspec, "refs/tags/*"))
 226                        return error(_("--all and --tags are incompatible"));
 227                return error(_("--all can't be combined with refspecs"));
 228        }
 229
 230        if ((flags & TRANSPORT_PUSH_MIRROR) && refspec) {
 231                if (!strcmp(*refspec, "refs/tags/*"))
 232                        return error(_("--mirror and --tags are incompatible"));
 233                return error(_("--mirror can't be combined with refspecs"));
 234        }
 235
 236        if ((flags & (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) ==
 237                                (TRANSPORT_PUSH_ALL|TRANSPORT_PUSH_MIRROR)) {
 238                return error(_("--all and --mirror are incompatible"));
 239        }
 240
 241        if (!refspec && !(flags & TRANSPORT_PUSH_ALL)) {
 242                if (remote->push_refspec_nr) {
 243                        refspec = remote->push_refspec;
 244                        refspec_nr = remote->push_refspec_nr;
 245                } else if (!(flags & TRANSPORT_PUSH_MIRROR))
 246                        setup_default_push_refspecs(remote);
 247        }
 248        errs = 0;
 249        if (remote->pushurl_nr) {
 250                url = remote->pushurl;
 251                url_nr = remote->pushurl_nr;
 252        } else {
 253                url = remote->url;
 254                url_nr = remote->url_nr;
 255        }
 256        if (url_nr) {
 257                for (i = 0; i < url_nr; i++) {
 258                        struct transport *transport =
 259                                transport_get(remote, url[i]);
 260                        if (push_with_options(transport, flags))
 261                                errs++;
 262                }
 263        } else {
 264                struct transport *transport =
 265                        transport_get(remote, NULL);
 266
 267                if (push_with_options(transport, flags))
 268                        errs++;
 269        }
 270        return !!errs;
 271}
 272
 273static int option_parse_recurse_submodules(const struct option *opt,
 274                                   const char *arg, int unset)
 275{
 276        int *flags = opt->value;
 277        if (arg) {
 278                if (!strcmp(arg, "check"))
 279                        *flags |= TRANSPORT_RECURSE_SUBMODULES_CHECK;
 280                else
 281                        die("bad %s argument: %s", opt->long_name, arg);
 282        } else
 283                die("option %s needs an argument (check)", opt->long_name);
 284
 285        return 0;
 286}
 287
 288int cmd_push(int argc, const char **argv, const char *prefix)
 289{
 290        int flags = 0;
 291        int tags = 0;
 292        int rc;
 293        const char *repo = NULL;        /* default repository */
 294        struct option options[] = {
 295                OPT__VERBOSITY(&verbosity),
 296                OPT_STRING( 0 , "repo", &repo, "repository", "repository"),
 297                OPT_BIT( 0 , "all", &flags, "push all refs", TRANSPORT_PUSH_ALL),
 298                OPT_BIT( 0 , "mirror", &flags, "mirror all refs",
 299                            (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
 300                OPT_BOOLEAN( 0, "delete", &deleterefs, "delete refs"),
 301                OPT_BOOLEAN( 0 , "tags", &tags, "push tags (can't be used with --all or --mirror)"),
 302                OPT_BIT('n' , "dry-run", &flags, "dry run", TRANSPORT_PUSH_DRY_RUN),
 303                OPT_BIT( 0,  "porcelain", &flags, "machine-readable output", TRANSPORT_PUSH_PORCELAIN),
 304                OPT_BIT('f', "force", &flags, "force updates", TRANSPORT_PUSH_FORCE),
 305                { OPTION_CALLBACK, 0, "recurse-submodules", &flags, "check",
 306                        "controls recursive pushing of submodules",
 307                        PARSE_OPT_OPTARG, option_parse_recurse_submodules },
 308                OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"),
 309                OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"),
 310                OPT_STRING( 0 , "exec", &receivepack, "receive-pack", "receive pack program"),
 311                OPT_BIT('u', "set-upstream", &flags, "set upstream for git pull/status",
 312                        TRANSPORT_PUSH_SET_UPSTREAM),
 313                OPT_BOOL(0, "progress", &progress, "force progress reporting"),
 314                OPT_BIT(0, "prune", &flags, "prune locally removed refs",
 315                        TRANSPORT_PUSH_PRUNE),
 316                OPT_END()
 317        };
 318
 319        packet_trace_identity("push");
 320        git_config(git_default_config, NULL);
 321        argc = parse_options(argc, argv, prefix, options, push_usage, 0);
 322
 323        if (deleterefs && (tags || (flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR))))
 324                die(_("--delete is incompatible with --all, --mirror and --tags"));
 325        if (deleterefs && argc < 2)
 326                die(_("--delete doesn't make sense without any refs"));
 327
 328        if (tags)
 329                add_refspec("refs/tags/*");
 330
 331        if (argc > 0) {
 332                repo = argv[0];
 333                set_refspecs(argv + 1, argc - 1);
 334        }
 335
 336        rc = do_push(repo, flags);
 337        if (rc == -1)
 338                usage_with_options(push_usage, options);
 339        else
 340                return rc;
 341}