]> rtime.felk.cvut.cz Git - git.git/commitdiff
Merge branch 'jc/push-2.0-default-to-simple'
authorJunio C Hamano <gitster@pobox.com>
Fri, 7 Mar 2014 23:13:15 +0000 (15:13 -0800)
committerJunio C Hamano <gitster@pobox.com>
Fri, 7 Mar 2014 23:13:15 +0000 (15:13 -0800)
Finally update the "git push" default behaviour to "simple".

1  2 
Documentation/config.txt
Documentation/git-push.txt
advice.c
advice.h
builtin/push.c

index 02776e51c8c1abfc151d245259f61546e4ff598c,2fe88f00a84a5e0752b46c8dfb05733aa0b936a6..73904bce55ff1d78bd10a5eb6b83f5fdf36ea74a
@@@ -140,12 -140,10 +140,12 @@@ advice.*:
        can tell Git that you do not need help by setting these to 'false':
  +
  --
 -      pushNonFastForward::
 +      pushUpdateRejected::
                Set this variable to 'false' if you want to disable
-               'pushNonFFCurrent', 'pushNonFFDefault',
 -              'pushNonFFCurrent', and
 -              'pushNonFFMatching' simultaneously.
++              'pushNonFFCurrent',
 +              'pushNonFFMatching', 'pushAlreadyExists',
 +              'pushFetchFirst', and 'pushNeedsForce'
 +              simultaneously.
        pushNonFFCurrent::
                Advice shown when linkgit:git-push[1] fails due to a
                non-fast-forward update to the current branch.
@@@ -1950,59 -1730,38 +1944,59 @@@ 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. Possible values are:
 +      Defines the action `git push` should take if no refspec is
 +      explicitly given.  Different values are well-suited for
 +      specific workflows; for instance, in a purely central workflow
 +      (i.e. the fetch source is equal to the push destination),
 +      `upstream` is probably what you want.  Possible values are:
  +
  --
 -* `nothing` - do not push anything.
 -* `matching` - push all branches having the same name in both ends.
 -  This is for those who prepare all the branches into a publishable
 -  shape and then push them out with a single command.  It is not
 -  appropriate for pushing into a repository shared by multiple users,
 -  since locally stalled branches will attempt a non-fast forward push
 -  if other users updated the branch.
 -  +
 -  This used to be the default, and stale web sites may still say so,
 -  but Git 2.0 has changed the default to `simple`.
 -* `upstream` - push the current branch to its upstream branch.
 -  With this, `git push` will update the same remote ref as the one which
 -  is merged by `git pull`, making `push` and `pull` symmetrical.
 -  See "branch.<name>.merge" for how to configure the upstream branch.
 -* `simple` - like `upstream`, but refuses to push if the upstream
 -  branch's name is different from the local one. This is the safest
 -  option and is well-suited for beginners. It has become the default
 -  in Git 2.0.
 -* `current` - push the current branch to a branch of the same name.
 ---
 +
 +* `nothing` - do not push anything (error out) unless a refspec is
 +  explicitly given. This is primarily meant for people who want to
 +  avoid mistakes by always being explicit.
 +
 +* `current` - push the current branch to update a branch with the same
 +  name on the receiving end.  Works in both central and non-central
 +  workflows.
 +
 +* `upstream` - push the current branch back to the branch whose
 +  changes are usually integrated into the current branch (which is
 +  called `@{upstream}`).  This mode only makes sense if you are
 +  pushing to the same repository you would normally pull from
 +  (i.e. central workflow).
 +
 +* `simple` - in centralized workflow, work like `upstream` with an
 +  added safety to refuse to push if the upstream branch's name is
 +  different from the local one.
 ++
 +When pushing to a remote that is different from the remote you normally
 +pull from, work as `current`.  This is the safest option and is suited
 +for beginners.
 ++
- This mode will become the default in Git 2.0.
++This mode has become the default in Git 2.0.
 +
 +* `matching` - push all branches having the same name on both ends.
 +  This makes the repository you are pushing to remember the set of
 +  branches that will be pushed out (e.g. if you always push 'maint'
 +  and 'master' there and no other branches, the repository you push
 +  to will have these two branches, and your local 'maint' and
 +  'master' will be pushed there).
 ++
 +To use this mode effectively, you have to make sure _all_ the
 +branches you would push out are ready to be pushed out before
 +running 'git push', as the whole point of this mode is to allow you
 +to push all of the branches in one go.  If you usually finish work
 +on only one branch and push out the result, while other branches are
 +unfinished, this mode is not for you.  Also this mode is not
 +suitable for pushing into a shared central repository, as other
 +people may add new branches there, or update the tip of existing
 +branches outside your control.
  +
- This is currently the default, but Git 2.0 will change the default
- to `simple`.
 -The `simple`, `current` and `upstream` modes are for those who want to
 -push out a single branch after finishing work, even when the other
 -branches are not yet ready to be pushed out. If you are working with
 -other people to push into the same shared repository, you would want
 -to use one of these.
++This used to be the default, but not since Git 2.0 (`simple` is the
++new default).
 +
 +--
  
  rebase.stat::
        Whether to show a diffstat of what changed upstream since the last
Simple merge
diff --cc advice.c
index 3eca9f5ffdd6e3596584ed0aa79e2634683bd496,5afed9367044242461a21be749216e2c081f3baa..486f823c78118212080a48e74debd7adae241cda
+++ b/advice.c
@@@ -1,14 -1,9 +1,13 @@@
  #include "cache.h"
  
 -int advice_push_nonfastforward = 1;
 +int advice_push_update_rejected = 1;
  int advice_push_non_ff_current = 1;
- int advice_push_non_ff_default = 1;
  int advice_push_non_ff_matching = 1;
 +int advice_push_already_exists = 1;
 +int advice_push_fetch_first = 1;
 +int advice_push_needs_force = 1;
  int advice_status_hints = 1;
 +int advice_status_u_option = 1;
  int advice_commit_before_merge = 1;
  int advice_resolve_conflict = 1;
  int advice_implicit_identity = 1;
@@@ -21,15 -13,10 +20,14 @@@ static struct 
        const char *name;
        int *preference;
  } advice_config[] = {
 -      { "pushnonfastforward", &advice_push_nonfastforward },
 +      { "pushupdaterejected", &advice_push_update_rejected },
        { "pushnonffcurrent", &advice_push_non_ff_current },
-       { "pushnonffdefault", &advice_push_non_ff_default },
        { "pushnonffmatching", &advice_push_non_ff_matching },
 +      { "pushalreadyexists", &advice_push_already_exists },
 +      { "pushfetchfirst", &advice_push_fetch_first },
 +      { "pushneedsforce", &advice_push_needs_force },
        { "statushints", &advice_status_hints },
 +      { "statusuoption", &advice_status_u_option },
        { "commitbeforemerge", &advice_commit_before_merge },
        { "resolveconflict", &advice_resolve_conflict },
        { "implicitidentity", &advice_implicit_identity },
diff --cc advice.h
index 08fbc8ee3ce79f265bbe15b63e2ae561ee8a0857,2c800e6787546db9bff62388430a02cc20a40b95..5ecc6c154e5a7207d18bbb05da5e35b2b4eae230
+++ b/advice.h
@@@ -3,15 -3,10 +3,14 @@@
  
  #include "git-compat-util.h"
  
 -extern int advice_push_nonfastforward;
 +extern int advice_push_update_rejected;
  extern int advice_push_non_ff_current;
- extern int advice_push_non_ff_default;
  extern int advice_push_non_ff_matching;
 +extern int advice_push_already_exists;
 +extern int advice_push_fetch_first;
 +extern int advice_push_needs_force;
  extern int advice_status_hints;
 +extern int advice_status_u_option;
  extern int advice_commit_before_merge;
  extern int advice_resolve_conflict;
  extern int advice_implicit_identity;
diff --cc builtin/push.c
index 0e50ddbb01342128d9118217118726000bdeaff6,9f7c25209e972aab78bf1fd97529fcc10173fe3c..3dd160c6b6a9a6af5010163f86b8a1ac2095dee1
@@@ -196,17 -146,10 +195,17 @@@ static void setup_push_upstream(struct 
        add_refspec(refspec.buf);
  }
  
 +static void setup_push_current(struct remote *remote, struct branch *branch)
 +{
 +      if (!branch)
 +              die(_(message_detached_head_die), remote->name);
 +      add_refspec(branch->name);
 +}
 +
  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"
@@@ -234,32 -170,20 +233,32 @@@ static void warn_unspecified_push_defau
        warning("%s\n", _(warn_unspecified_push_default_msg));
  }
  
 +static int is_workflow_triangular(struct remote *remote)
 +{
 +      struct remote *fetch_remote = remote_get(NULL);
 +      return (fetch_remote && fetch_remote != remote);
 +}
 +
  static void setup_default_push_refspecs(struct remote *remote)
  {
 +      struct branch *branch = branch_get(NULL);
 +      int triangular = is_workflow_triangular(remote);
 +
        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:
 -              setup_push_upstream(remote, 1);
 +              if (triangular)
 +                      setup_push_current(remote, branch);
 +              else
 +                      setup_push_upstream(remote, branch, triangular);
                break;
  
        case PUSH_DEFAULT_UPSTREAM:
  
  static const char message_advice_pull_before_push[] =
        N_("Updates were rejected because the tip of your current branch is behind\n"
 -         "its remote counterpart. Merge the remote changes (e.g. 'git pull')\n"
 -         "before pushing again.\n"
 +         "its remote counterpart. Integrate the remote changes (e.g.\n"
 +         "'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 merge the remote changes\n"
 -         "(e.g. 'git pull') before pushing again.\n"
 +         "counterpart. Check out this branch and integrate the remote changes\n"
 +         "(e.g. 'git pull ...') before pushing again.\n"
           "See the 'Note about fast-forwards' in 'git push --help' for details.");
  
 +static const char message_advice_ref_fetch_first[] =
 +      N_("Updates were rejected because the remote contains work that you do\n"
 +         "not have locally. This is usually caused by another repository pushing\n"
 +         "to the same ref. You may want to first integrate the remote changes\n"
 +         "(e.g., 'git pull ...') before pushing again.\n"
 +         "See the 'Note about fast-forwards' in 'git push --help' for details.");
 +
 +static const char message_advice_ref_already_exists[] =
 +      N_("Updates were rejected because the tag already exists in the remote.");
 +
 +static const char message_advice_ref_needs_force[] =
 +      N_("You cannot update a remote ref that points at a non-commit object,\n"
 +         "or update a remote ref to make it point at a non-commit object,\n"
 +         "without using the '--force' option.\n");
 +
  static void advise_pull_before_push(void)
  {
 -      if (!advice_push_non_ff_current || !advice_push_nonfastforward)
 +      if (!advice_push_non_ff_current || !advice_push_update_rejected)
                return;
        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_nonfastforward)
 +      if (!advice_push_non_ff_matching || !advice_push_update_rejected)
                return;
        advise(_(message_advice_checkout_pull_push));
  }
@@@ -382,19 -251,15 +368,16 @@@ static int push_with_options(struct tra
        if (!err)
                return 0;
  
 -      switch (nonfastforward) {
 -      default:
 -              break;
 -      case NON_FF_HEAD:
 +      if (reject_reasons & REJECT_NON_FF_HEAD) {
                advise_pull_before_push();
 -              break;
 -      case NON_FF_OTHER:
 +      } else if (reject_reasons & REJECT_NON_FF_OTHER) {
-               if (default_matching_used)
-                       advise_use_upstream();
-               else
-                       advise_checkout_pull_push();
+               advise_checkout_pull_push();
 -              break;
 +      } else if (reject_reasons & REJECT_ALREADY_EXISTS) {
 +              advise_ref_already_exists();
 +      } else if (reject_reasons & REJECT_FETCH_FIRST) {
 +              advise_ref_fetch_first();
 +      } else if (reject_reasons & REJECT_NEEDS_FORCE) {
 +              advise_ref_needs_force();
        }
  
        return 1;