{"thread":{"id":"29990","subject":"[PATCH v2] push: Provide situational hints for non-fast-forward errors","startedAt":"2012-03-19T07:49:44Z","lastAt":"2012-03-19T22:41:40Z","messageCount":4,"participants":["Christopher Tiwald","Junio C Hamano"],"isPatch":true,"patchVersion":2,"patchTotal":null},"messages":[{"id":"187241","messageId":"20120319074944.GA18489@democracyinaction.org","threadId":"29990","inReplyTo":null,"subject":"[PATCH v2] push: Provide situational hints for non-fast-forward errors","fromName":"Christopher Tiwald","fromEmail":"christiwald@gmail.com","sentAt":"2012-03-19T07:49:44Z","receivedAt":"2012-03-19T07:49:44Z","isPatch":true,"sender":{"key":"christiwald@gmail.com","avatar":"https://avatars.githubusercontent.com/u/667276?v=4"},"body":"Pushing a non-fast-forward update to a remote repository will result in\nan error, but the hint text doesn't provide the correct resolution in\nevery case. Give better resolution advice in three push scenarios:\n\n1) If you push a non-fast-forward update to your current branch, you\nshould merge remote changes with 'git pull' before pushing again.\n\n2) If you push to a shared repository others push to, and your local\ntracking branches are not kept up to date, the 'matching refs' default\nwill generate non-fast-forward errors on outdated branches. If this is\nyour workflow, the 'matching refs' default is not for you. Consider\nsetting the 'push.default' configuration variable to 'current' or\n'upstream' to ensure only your current branch is pushed.\n\n3) If you explicitly specify a ref that is not your current branch or\npush matching branches with ':', you will generate a non-fast-forward\nerror if any pushed branch tip is out of date. You should checkout the\noffending branch and merge remote changes before pushing again.\n\nTeach transport.c to recognize these scenarios and push.c to hint for\nthem. Do it with a switch statement so if 'git push's default behavior\nchanges or we discover more scenarios, modification is easy. Standardize\non the advice API and replace 'advice.pushNonFastForward' with two new\nconfig variables, 'advice.pushNonFFCurrent' and 'advice.pushNonFFOther'.\nResolving a non-fast-forward error on your current branch requires\ndifferent operations than resolving one on a non-current branch. It\nshouldn't be possible to disable both types of advice with one config\noption.\n\nBased-on-patch-by: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Christopher Tiwald <christiwald@gmail.com>\n---\n Changes in v2:\n\t- Cleaned up language in both the commit and advice messages.\n\t- Uses advice.c::advise(), standardizing the API used and\n\t  providing support for i18n.\n\t- Uses a switch statement to select advice, rather than\n\t  if-statements, making this feature more extensible.\n\t- v1 used three non-ff advice variables and neglected to delete the\n\t  original. v2 replaces the original with two, which more\n\t  precisely matches the two types of errors we're trying to\n\t  advise:\n\n\t  non-ff errors on the current branch\n\t  non-ff errors on other branches, but not current\n\n\t- Shortened the nonfastforward enum name to make it more\n\t  readable.\n\n v2 should capture all the various comments about this patch, although\n I did make a few minor changes to the advice and settled on two config\n variables rather than one or three.\n \n There is one aspect about this patch about which I'm unsure: What to\n do with users who've set \"advice.pushNonFastForward = false\" already.\n I could leave the variable in advice.c and modify push.c to respect\n it easily, but at that point we're almost configuring advice.c to\n \"turn off advice for this command\".\n\n I don't know. Maybe that's the way we want to go with advice. I\n suppose it's largely a function of how much advice we have to give and\n whether or not it's useful to new users.\n\n Documentation/config.txt |   10 +++++---\n advice.c                 |    6 +++--\n advice.h                 |    3 ++-\n builtin/push.c           |   60 ++++++++++++++++++++++++++++++++++++++++++----\n cache.h                  |    8 +++++--\n environment.c            |    2 +-\n transport.c              |   13 ++++++++--\n 7 files changed, 86 insertions(+), 16 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex c081657..a2329b5 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -137,9 +137,13 @@ advice.*::\n \tcan tell Git that you do not need help by setting these to 'false':\n +\n --\n-\tpushNonFastForward::\n-\t\tAdvice shown when linkgit:git-push[1] refuses\n-\t\tnon-fast-forward refs.\n+\tpushNonFFCurrent::\n+\t\tAdvice shown when linkgit:git-push[1] fails due to a\n+\t\tnon-fast-forward update to the current branch.\n+\tpushNonFFOther::\n+\t\tAdvice shown when linkgit:git-push[1] fails due to a\n+\t\tnon-fast-forward update to a branch other than the\n+\t\tcurrent one.\n \tstatusHints::\n \t\tDirections on how to stage/unstage/add shown in the\n \t\toutput of linkgit:git-status[1] and the template shown\ndiff --git a/advice.c b/advice.c\nindex 01130e5..ee62e1b 100644\n--- a/advice.c\n+++ b/advice.c\n@@ -1,6 +1,7 @@\n #include \"cache.h\"\n \n-int advice_push_nonfastforward = 1;\n+int advice_push_non_ff_current = 1;\n+int advice_push_non_ff_other = 1;\n int advice_status_hints = 1;\n int advice_commit_before_merge = 1;\n int advice_resolve_conflict = 1;\n@@ -11,7 +12,8 @@ static struct {\n \tconst char *name;\n \tint *preference;\n } advice_config[] = {\n-\t{ \"pushnonfastforward\", &advice_push_nonfastforward },\n+\t{ \"pushnonffcurrent\", &advice_push_non_ff_current },\n+\t{ \"pushnonffother\", &advice_push_non_ff_other },\n \t{ \"statushints\", &advice_status_hints },\n \t{ \"commitbeforemerge\", &advice_commit_before_merge },\n \t{ \"resolveconflict\", &advice_resolve_conflict },\ndiff --git a/advice.h b/advice.h\nindex 7bda45b..98c675e 100644\n--- a/advice.h\n+++ b/advice.h\n@@ -3,7 +3,8 @@\n \n #include \"git-compat-util.h\"\n \n-extern int advice_push_nonfastforward;\n+extern int advice_push_non_ff_current;\n+extern int advice_push_non_ff_other;\n extern int advice_status_hints;\n extern int advice_commit_before_merge;\n extern int advice_resolve_conflict;\ndiff --git a/builtin/push.c b/builtin/push.c\nindex d315475..3de2737 100644\n--- a/builtin/push.c\n+++ b/builtin/push.c\n@@ -24,6 +24,7 @@ static int progress = -1;\n static const char **refspec;\n static int refspec_nr;\n static int refspec_alloc;\n+static int default_matching_used;\n \n static void add_refspec(const char *ref)\n {\n@@ -95,6 +96,9 @@ static void setup_default_push_refspecs(struct remote *remote)\n {\n \tswitch (push_default) {\n \tdefault:\n+\tcase PUSH_DEFAULT_UNSPECIFIED:\n+\t\tdefault_matching_used = 1;\n+\t\t/* fallthru */\n \tcase PUSH_DEFAULT_MATCHING:\n \t\tadd_refspec(\":\");\n \t\tbreak;\n@@ -114,6 +118,45 @@ static void setup_default_push_refspecs(struct remote *remote)\n \t}\n }\n \n+static const char message_advice_pull_before_push[] =\n+\tN_(\"Updates were rejected because the tip of your current branch is behind\\n\"\n+\t   \"its remote counterpart. Merge the remote changes (e.g. 'git pull')\\n\"\n+\t   \"before pushing again.\\n\"\n+\t   \"See the 'Note about fast-forwards' in 'git push --help' for details.\");\n+\n+static const char message_advice_use_upstream[] =\n+\tN_(\"Updates were rejected because a pushed branch tip is behind its remote\\n\"\n+\t   \"counterpart. If you did not intend to push that branch, you may want to\\n\"\n+\t   \"specify branches to push or set the 'push.default' configuration\\n\"\n+\t   \"variable to 'current' or 'upstream' to push only the current branch.\");\n+\n+static const char message_advice_checkout_pull_push[] =\n+\tN_(\"Updates were rejected because a pushed branch tip is behind its remote\\n\"\n+\t   \"counterpart. Check out this branch and merge the remote changes\\n\"\n+\t   \"(e.g. 'git pull') before pushing again.\\n\"\n+\t   \"See the 'Note about fast-forwards' in 'git push --help' for details.\");\n+\n+static void advise_pull_before_push(void)\n+{\n+\tif (!advice_push_non_ff_current)\n+\t\treturn;\n+\tadvise(_(message_advice_pull_before_push));\n+}\n+\n+static void advise_use_upstream(void)\n+{\n+\tif (!advice_push_non_ff_other)\n+\t\treturn;\n+\tadvise(_(message_advice_use_upstream));\n+}\n+\n+static void advise_checkout_pull_push(void)\n+{\n+\tif (!advice_push_non_ff_other)\n+\t\treturn;\n+\tadvise(_(message_advice_checkout_pull_push));\n+}\n+\n static int push_with_options(struct transport *transport, int flags)\n {\n \tint err;\n@@ -135,14 +178,21 @@ static int push_with_options(struct transport *transport, int flags)\n \t\terror(_(\"failed to push some refs to '%s'\"), transport->url);\n \n \terr |= transport_disconnect(transport);\n-\n \tif (!err)\n \t\treturn 0;\n \n-\tif (nonfastforward && advice_push_nonfastforward) {\n-\t\tfprintf(stderr, _(\"To prevent you from losing history, non-fast-forward updates were rejected\\n\"\n-\t\t\t\t\"Merge the remote changes (e.g. 'git pull') before pushing again.  See the\\n\"\n-\t\t\t\t\"'Note about fast-forwards' section of 'git push --help' for details.\\n\"));\n+\tswitch (nonfastforward) {\n+\tdefault:\n+\t\tbreak;\n+\tcase NON_FF_HEAD:\n+\t\tadvise_pull_before_push();\n+\t\tbreak;\n+\tcase NON_FF_OTHER:\n+\t\tif (default_matching_used)\n+\t\t\tadvise_use_upstream();\n+\t\telse\n+\t\t\tadvise_checkout_pull_push();\n+\t\tbreak;\n \t}\n \n \treturn 1;\ndiff --git a/cache.h b/cache.h\nindex e5e1aa4..427b600 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -625,7 +625,8 @@ enum push_default_type {\n \tPUSH_DEFAULT_NOTHING = 0,\n \tPUSH_DEFAULT_MATCHING,\n \tPUSH_DEFAULT_UPSTREAM,\n-\tPUSH_DEFAULT_CURRENT\n+\tPUSH_DEFAULT_CURRENT,\n+\tPUSH_DEFAULT_UNSPECIFIED\n };\n \n extern enum branch_track git_branch_track;\n@@ -1008,7 +1009,6 @@ struct ref {\n \tchar *symref;\n \tunsigned int force:1,\n \t\tmerge:1,\n-\t\tnonfastforward:1,\n \t\tdeletion:1;\n \tenum {\n \t\tREF_STATUS_NONE = 0,\n@@ -1019,6 +1019,10 @@ struct ref {\n \t\tREF_STATUS_REMOTE_REJECT,\n \t\tREF_STATUS_EXPECTING_REPORT\n \t} status;\n+\tenum {\n+\t\tNON_FF_HEAD = 1,\n+\t\tNON_FF_OTHER\n+\t} nonfastforward;\n \tchar *remote_status;\n \tstruct ref *peer_ref; /* when renaming */\n \tchar name[FLEX_ARRAY]; /* more */\ndiff --git a/environment.c b/environment.c\nindex c93b8f4..d7e6c65 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -52,7 +52,7 @@ enum safe_crlf safe_crlf = SAFE_CRLF_WARN;\n unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;\n enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;\n enum rebase_setup_type autorebase = AUTOREBASE_NEVER;\n-enum push_default_type push_default = PUSH_DEFAULT_MATCHING;\n+enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;\n #ifndef OBJECT_CREATION_MODE\n #define OBJECT_CREATION_MODE OBJECT_CREATION_USES_HARDLINKS\n #endif\ndiff --git a/transport.c b/transport.c\nindex 181f8f2..7864007 100644\n--- a/transport.c\n+++ b/transport.c\n@@ -721,6 +721,10 @@ void transport_print_push_status(const char *dest, struct ref *refs,\n {\n \tstruct ref *ref;\n \tint n = 0;\n+\tunsigned char head_sha1[20];\n+\tchar *head;\n+\n+\thead = resolve_refdup(\"HEAD\", head_sha1, 1, NULL);\n \n \tif (verbose) {\n \t\tfor (ref = refs; ref; ref = ref->next)\n@@ -738,8 +742,13 @@ void transport_print_push_status(const char *dest, struct ref *refs,\n \t\t    ref->status != REF_STATUS_UPTODATE &&\n \t\t    ref->status != REF_STATUS_OK)\n \t\t\tn += print_one_push_status(ref, dest, n, porcelain);\n-\t\tif (ref->status == REF_STATUS_REJECT_NONFASTFORWARD)\n-\t\t\t*nonfastforward = 1;\n+\t\tif (ref->status == REF_STATUS_REJECT_NONFASTFORWARD &&\n+\t\t    *nonfastforward != NON_FF_HEAD) {\n+\t\t\tif (!strcmp(head, ref->name))\n+\t\t\t\t*nonfastforward = NON_FF_HEAD;\n+\t\t\telse\n+\t\t\t\t*nonfastforward = NON_FF_OTHER;\n+\t\t}\n \t}\n }\n \n-- \n1.7.10.rc1.25.gff0ac.dirty\n"},{"id":"187268","messageId":"7vbonsbepx.fsf@alter.siamese.dyndns.org","threadId":"29990","inReplyTo":"20120319074944.GA18489@democracyinaction.org","subject":"Re: [PATCH v2] push: Provide situational hints for non-fast-forward errors","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-03-19T18:58:02Z","receivedAt":"2012-03-19T18:58:02Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Christopher Tiwald <christiwald@gmail.com> writes:\n\n> Pushing a non-fast-forward update to a remote repository will result in\n> an error, but the hint text doesn't provide the correct resolution in\n> every case. Give better resolution advice in three push scenarios:\n>\n> 1) If you push a non-fast-forward update to your current branch, you\n> should merge remote changes with 'git pull' before pushing again.\n\nI have always found \"update *to* your current branch\" very strange\nphrasing (the earlier one said \"to HEAD\", but it amounts to the same\nthing).  You do not push *to* your branch.  You push your branch to\nsomewhere else (namely, remote).  I would understand if it said \"If your\npush of your current branch triggers a non-ff error, ...\", though.\n\n> \t  non-ff errors on other branches, but not current\n\nI think the change in this patch comes from a realization that a blanket\n\"Here is all you need to know for any and all non-ff error cases\" is not\nvery useful, and it feels like it is going backwards to squash the \"non-ff\nbut not the current\" into one category.\n\nThe user may have been using the matching default, gets the use-upstream\nadvice and realizes that she is trying to push branches other than what\nshe wanted to push, and may say \"git push $there master\" to push only that\nbranch out.  Then she thinks she learned enough to squelch the message in\n$HOME/.gitconfig.\n\nShe may have another project with remote.$there.push set to push more than\none branches out (say, master and next), and while on 'master', may hit\nanother \"non-ff on other\" instance, because her 'next' was stale.\n\nShe never gets a chance to see the other checkout-pull-push message, does\nshe?\n\n>  There is one aspect about this patch about which I'm unsure: What to\n>  do with users who've set \"advice.pushNonFastForward = false\" already.\n\nThe change in this patch is merely clarifying what pushNonFastForward\nadvise has already taught them (\"Non-ff was rejected; the manual will tell\nyou what you wanted to do\") by dividing them into three categories and\ngiving different advices to these categories.  As the user says he\nunderstood what he is doing, I think squelching all of them is a sane\nchoice.\n\n> +static const char message_advice_pull_before_push[] =\n> +\tN_(\"Updates were rejected because the tip of your current branch is behind\\n\"\n> +\t   \"its remote counterpart. Merge the remote changes (e.g. 'git pull')\\n\"\n> +\t   \"before pushing again.\\n\"\n> +\t   \"See the 'Note about fast-forwards' in 'git push --help' for details.\");\n> +\n> +static const char message_advice_use_upstream[] =\n> +\tN_(\"Updates were rejected because a pushed branch tip is behind its remote\\n\"\n> +\t   \"counterpart. If you did not intend to push that branch, you may want to\\n\"\n> +\t   \"specify branches to push or set the 'push.default' configuration\\n\"\n> +\t   \"variable to 'current' or 'upstream' to push only the current branch.\");\n> +\n> +static const char message_advice_checkout_pull_push[] =\n> +\tN_(\"Updates were rejected because a pushed branch tip is behind its remote\\n\"\n> +\t   \"counterpart. Check out this branch and merge the remote changes\\n\"\n> +\t   \"(e.g. 'git pull') before pushing again.\\n\"\n> +\t   \"See the 'Note about fast-forwards' in 'git push --help' for details.\");\n\nIn any case, the updated messages read much better than the current non-ff\none (or the previous round for that matter).\n"},{"id":"187288","messageId":"20120319222225.GA36860@gmail.com","threadId":"29990","inReplyTo":"7vbonsbepx.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v2] push: Provide situational hints for non-fast-forward errors","fromName":"Christopher Tiwald","fromEmail":"christiwald@gmail.com","sentAt":"2012-03-19T22:22:25Z","receivedAt":"2012-03-19T22:22:25Z","isPatch":true,"sender":{"key":"christiwald@gmail.com","avatar":"https://avatars.githubusercontent.com/u/667276?v=4"},"body":"On Mon, Mar 19, 2012 at 11:58:02AM -0700, Junio C Hamano wrote:\n> Christopher Tiwald <christiwald@gmail.com> writes:\n> \n> > Pushing a non-fast-forward update to a remote repository will result in\n> > an error, but the hint text doesn't provide the correct resolution in\n> > every case. Give better resolution advice in three push scenarios:\n> >\n> > 1) If you push a non-fast-forward update to your current branch, you\n> > should merge remote changes with 'git pull' before pushing again.\n> \n> I have always found \"update *to* your current branch\" very strange\n> phrasing (the earlier one said \"to HEAD\", but it amounts to the same\n> thing).  You do not push *to* your branch.  You push your branch to\n> somewhere else (namely, remote).  I would understand if it said \"If your\n> push of your current branch triggers a non-ff error, ...\", though.\n\nAh. Yeah. I can see the problem with my phrasing now. How about something\nlike the following?\n\n\"If you push your current branch and it triggers a non-fast-forward\nerror, you should merge remote changes with 'git pull' before pushing\nagain.\"\n\n> She never gets a chance to see the other checkout-pull-push message, does\n> she?\n> \n> >  There is one aspect about this patch about which I'm unsure: What to\n> >  do with users who've set \"advice.pushNonFastForward = false\" already.\n> \n> The change in this patch is merely clarifying what pushNonFastForward\n> advise has already taught them (\"Non-ff was rejected; the manual will tell\n> you what you wanted to do\") by dividing them into three categories and\n> giving different advices to these categories.  As the user says he\n> understood what he is doing, I think squelching all of them is a sane\n> choice.\n\nHow about the something like the following fixup? This introduces two\nchanges to v2:\n\n- It breaks the new advice into three config variables. Users\n  who might benefit from the advice can't accidentally shut a message\n  off before being confronted with the situation it's designed to\n  advise.\n- It leaves pushNonFastForward in place, and if a user sets\n  'advice.pushNonFastForward = false', it'll disable all three pieces\n  of advice.\n\n--\nChristopher Tiwald\n--- 8< ---\nSigned-off-by: Christopher Tiwald <christiwald@gmail.com>\n---\n Documentation/config.txt |   19 +++++++++++++++----\n advice.c                 |    8 ++++++--\n advice.h                 |    4 +++-\n builtin/push.c           |    6 +++---\n 4 files changed, 27 insertions(+), 10 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex a2329b5..fb386ab 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -137,13 +137,24 @@ advice.*::\n \tcan tell Git that you do not need help by setting these to 'false':\n +\n --\n+\tpushNonFastForward::\n+\t\tSet this variable to 'false' if you want to disable\n+\t\t'pushNonFFCurrent', 'pushNonFFDefault', and\n+\t\t'pushNonFFMatching' simultaneously.\n \tpushNonFFCurrent::\n \t\tAdvice shown when linkgit:git-push[1] fails due to a\n \t\tnon-fast-forward update to the current branch.\n-\tpushNonFFOther::\n-\t\tAdvice shown when linkgit:git-push[1] fails due to a\n-\t\tnon-fast-forward update to a branch other than the\n-\t\tcurrent one.\n+\tpushNonFFDefault::\n+\t\tAdvice to set 'push.default' to 'upstream' or 'current'\n+\t\twhen you ran linkgit:git-push[1] and pushed 'matching\n+\t\trefs' by default (i.e. you did not provide an explicit\n+\t\trefspec, and no 'push.default' configuration was set)\n+\t\tand it resulted in a non-fast-forward error.\n+\tpushNonFFMatching::\n+\t\tAdvice shown when you ran linkgit:git-push[1] and pushed\n+\t\t'matching refs' explicitly (i.e. you used ':', or\n+\t\tspecified a refspec that isn't your current branch) and\n+\t\tit resulted in a non-fast-forward error.\n \tstatusHints::\n \t\tDirections on how to stage/unstage/add shown in the\n \t\toutput of linkgit:git-status[1] and the template shown\ndiff --git a/advice.c b/advice.c\nindex ee62e1b..a492eea 100644\n--- a/advice.c\n+++ b/advice.c\n@@ -1,7 +1,9 @@\n #include \"cache.h\"\n \n+int advice_push_nonfastforward = 1;\n int advice_push_non_ff_current = 1;\n-int advice_push_non_ff_other = 1;\n+int advice_push_non_ff_default = 1;\n+int advice_push_non_ff_matching = 1;\n int advice_status_hints = 1;\n int advice_commit_before_merge = 1;\n int advice_resolve_conflict = 1;\n@@ -12,8 +14,10 @@ static struct {\n \tconst char *name;\n \tint *preference;\n } advice_config[] = {\n+\t{ \"pushnonfastforward\", &advice_push_nonfastforward },\n \t{ \"pushnonffcurrent\", &advice_push_non_ff_current },\n-\t{ \"pushnonffother\", &advice_push_non_ff_other },\n+\t{ \"pushnonffdefault\", &advice_push_non_ff_default },\n+\t{ \"pushnonffmatching\", &advice_push_non_ff_matching },\n \t{ \"statushints\", &advice_status_hints },\n \t{ \"commitbeforemerge\", &advice_commit_before_merge },\n \t{ \"resolveconflict\", &advice_resolve_conflict },\ndiff --git a/advice.h b/advice.h\nindex 98c675e..f3cdbbf 100644\n--- a/advice.h\n+++ b/advice.h\n@@ -3,8 +3,10 @@\n \n #include \"git-compat-util.h\"\n \n+extern int advice_push_nonfastforward;\n extern int advice_push_non_ff_current;\n-extern int advice_push_non_ff_other;\n+extern int advice_push_non_ff_default;\n+extern int advice_push_non_ff_matching;\n extern int advice_status_hints;\n extern int advice_commit_before_merge;\n extern int advice_resolve_conflict;\ndiff --git a/builtin/push.c b/builtin/push.c\nindex 3de2737..a0ffbb3 100644\n--- a/builtin/push.c\n+++ b/builtin/push.c\n@@ -138,21 +138,21 @@ static const char message_advice_checkout_pull_push[] =\n \n static void advise_pull_before_push(void)\n {\n-\tif (!advice_push_non_ff_current)\n+\tif (!advice_push_non_ff_current | !advice_push_nonfastforward)\n \t\treturn;\n \tadvise(_(message_advice_pull_before_push));\n }\n \n static void advise_use_upstream(void)\n {\n-\tif (!advice_push_non_ff_other)\n+\tif (!advice_push_non_ff_default | !advice_push_nonfastforward)\n \t\treturn;\n \tadvise(_(message_advice_use_upstream));\n }\n \n static void advise_checkout_pull_push(void)\n {\n-\tif (!advice_push_non_ff_other)\n+\tif (!advice_push_non_ff_matching | !advice_push_nonfastforward)\n \t\treturn;\n \tadvise(_(message_advice_checkout_pull_push));\n }\n-- \n1.7.10.rc1.23.g2a051.dirty\n"},{"id":"187290","messageId":"7vwr6g8b8b.fsf@alter.siamese.dyndns.org","threadId":"29990","inReplyTo":"20120319222225.GA36860@gmail.com","subject":"Re: [PATCH v2] push: Provide situational hints for non-fast-forward errors","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-03-19T22:41:40Z","receivedAt":"2012-03-19T22:41:40Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Christopher Tiwald <christiwald@gmail.com> writes:\n\n> How about the something like the following fixup? This introduces two\n> changes to v2:\n>\n> - It breaks the new advice into three config variables. Users\n>   who might benefit from the advice can't accidentally shut a message\n>   off before being confronted with the situation it's designed to\n>   advise.\n> - It leaves pushNonFastForward in place, and if a user sets\n>   'advice.pushNonFastForward = false', it'll disable all three pieces\n>   of advice.\n\nSounds good.\n\n>  static void advise_pull_before_push(void)\n>  {\n> -\tif (!advice_push_non_ff_current)\n> +\tif (!advice_push_non_ff_current | !advice_push_nonfastforward)\n\nBitwise or would work OK as long as both sides are !var, but is not\nparticularly a style.  Please replace all of these with \"||\".\n\nOther than that, sounds sane to me.\n\nThanks.\n"}]}