From: Junio C Hamano Date: Fri, 7 Mar 2014 23:13:15 +0000 (-0800) Subject: Merge branch 'jc/push-2.0-default-to-simple' X-Git-Tag: v2.0.0-rc0~142 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=009055f3ecd8d9b4eb140429cb5ce5d2088174c7;p=git Merge branch 'jc/push-2.0-default-to-simple' Finally update the "git push" default behaviour to "simple". --- 009055f3ecd8d9b4eb140429cb5ce5d2088174c7 diff --cc Documentation/config.txt index 02776e51c8,2fe88f00a8..73904bce55 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@@ -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..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 diff --cc advice.c index 3eca9f5ffd,5afed93670..486f823c78 --- a/advice.c +++ 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 08fbc8ee3c,2c800e6787..5ecc6c154e --- a/advice.h +++ 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 0e50ddbb01,9f7c25209e..3dd160c6b6 --- a/builtin/push.c +++ b/builtin/push.c @@@ -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: @@@ -279,54 -203,26 +278,41 @@@ 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;