From d8a3581b55e27c071e22a540620cf8a42291af87 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 18 Dec 2011 21:38:29 -0800 Subject: push: hint to use push.default=upstream when appropriate If you push into a shared repository that others push to, and you have local branches in your repository that matches the remote side but do not keep them up-to-date, then 'matching refs' is not an appropriate default for you. Detect when push failed due to non-fast-forward _and_ we did matching refs by default (i.e. if the user explicitly said ':' from the command line, or had push.default set to 'matching', then we do not want to advise), and give a hint to tell the user that the user may want to set 'push.default' configuration variable to 'upstream', if the remote repository receives pushes from other places. Signed-off-by: Junio C Hamano --- Documentation/config.txt | 6 ++++++ advice.c | 2 ++ advice.h | 1 + builtin/push.c | 25 +++++++++++++++++++++++++ cache.h | 3 ++- environment.c | 2 +- 6 files changed, 37 insertions(+), 2 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index f22d926777..681811095c 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -141,6 +141,12 @@ advice.*:: Advice shown when you used linkgit:git-checkout[1] to move to the detach HEAD state, to instruct how to create a local branch after the fact. + pushUseUpstream:: + Advice to set 'push.default' to 'upstream' when you ran + linkgit:git-push[1] and pushed 'matching refs' by default + (i.e. you did not have any explicit refspec on the command + line, and no 'push.default' configuration was set) and it + resulted in a non-fast-forward error. -- core.fileMode:: diff --git a/advice.c b/advice.c index e02e632df3..9b56709d2c 100644 --- a/advice.c +++ b/advice.c @@ -6,6 +6,7 @@ int advice_commit_before_merge = 1; int advice_resolve_conflict = 1; int advice_implicit_identity = 1; int advice_detached_head = 1; +int advice_push_use_upstream = 1; static struct { const char *name; @@ -17,6 +18,7 @@ static struct { { "resolveconflict", &advice_resolve_conflict }, { "implicitidentity", &advice_implicit_identity }, { "detachedhead", &advice_detached_head }, + { "pushuseupstream", &advice_push_use_upstream }, }; void advise(const char *advice, ...) diff --git a/advice.h b/advice.h index e5d0af782b..6bb89cdce0 100644 --- a/advice.h +++ b/advice.h @@ -9,6 +9,7 @@ extern int advice_commit_before_merge; extern int advice_resolve_conflict; extern int advice_implicit_identity; extern int advice_detached_head; +extern int advice_push_use_upstream; int git_default_advice_config(const char *var, const char *value); void advise(const char *advice, ...); diff --git a/builtin/push.c b/builtin/push.c index 35cce532f2..5f8c7f4917 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -9,6 +9,7 @@ #include "transport.h" #include "parse-options.h" #include "submodule.h" +#include "advice.h" static const char * const push_usage[] = { "git push [] [ [...]]", @@ -24,6 +25,7 @@ static int progress; static const char **refspec; static int refspec_nr; static int refspec_alloc; +static int default_matching_used; static void add_refspec(const char *ref) { @@ -95,6 +97,9 @@ static void setup_default_push_refspecs(struct remote *remote) { switch (push_default) { default: + case PUSH_DEFAULT_UNSPECIFIED: + default_matching_used = 1; + /* fallthru */ case PUSH_DEFAULT_MATCHING: add_refspec(":"); break; @@ -114,6 +119,23 @@ static void setup_default_push_refspecs(struct remote *remote) } } +static const char *message_advice_use_upstream[] = { + "If you are pushing into a repository that receives pushes from", + "repositories other than the current repository, you may want to", + "set 'push.default' configuration variable to 'upstream' to avoid", + "pushing branches you haven't worked on that others have updated.", +}; + +static void advise_use_upstream(void) +{ + int i; + + if (!advice_push_use_upstream) + return; + for (i = 0; i < ARRAY_SIZE(message_advice_use_upstream); i++) + advise(message_advice_use_upstream[i]); +} + static int push_with_options(struct transport *transport, int flags) { int err; @@ -136,6 +158,9 @@ static int push_with_options(struct transport *transport, int flags) err |= transport_disconnect(transport); + if (nonfastforward && default_matching_used) + advise_use_upstream(); + if (!err) return 0; diff --git a/cache.h b/cache.h index 2e6ad3604e..d5351fa566 100644 --- a/cache.h +++ b/cache.h @@ -623,7 +623,8 @@ enum push_default_type { PUSH_DEFAULT_NOTHING = 0, PUSH_DEFAULT_MATCHING, PUSH_DEFAULT_UPSTREAM, - PUSH_DEFAULT_CURRENT + PUSH_DEFAULT_CURRENT, + PUSH_DEFAULT_UNSPECIFIED }; extern enum branch_track git_branch_track; diff --git a/environment.c b/environment.c index 0bee6a7a88..e5fb862a9b 100644 --- a/environment.c +++ b/environment.c @@ -51,7 +51,7 @@ enum safe_crlf safe_crlf = SAFE_CRLF_WARN; unsigned whitespace_rule_cfg = WS_DEFAULT_RULE; enum branch_track git_branch_track = BRANCH_TRACK_REMOTE; enum rebase_setup_type autorebase = AUTOREBASE_NEVER; -enum push_default_type push_default = PUSH_DEFAULT_MATCHING; +enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED; #ifndef OBJECT_CREATION_MODE #define OBJECT_CREATION_MODE OBJECT_CREATION_USES_HARDLINKS #endif -- cgit v1.2.1