{"thread":{"id":"59944","subject":"[PATCH 0/2] advise about force-pushing as an alternative to reconciliation","startedAt":"2023-07-02T20:10:43Z","lastAt":"2023-07-13T16:15:44Z","messageCount":45,"participants":["Alex Henrie","Phillip Wood","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"479097","messageId":"20230702200818.1038494-1-alexhenrie24@gmail.com","threadId":"59944","inReplyTo":null,"subject":"[PATCH 0/2] advise about force-pushing as an alternative to reconciliation","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-02T20:08:15Z","receivedAt":"2023-07-02T20:10:43Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"Many times now, I have seen novices do the following:\n\n1. Start work on their own personal topic branch\n2. Push the branch to origin\n3. Rebase the branch onto origin/master\n4. Try to push again, but Git says they need to pull\n5. Pull and make a mess trying to reconcile the older topic branch with\n   the rebased topic branch\n\nHelp avoid this mistake by giving advice that mentions force-pushing,\nrather than assuming that the user always wants to do reconciliation.\n\nAlex Henrie (2):\n  remote: advise about force-pushing as an alternative to reconciliation\n  push: advise about force-pushing as an alternative to reconciliation\n\n builtin/push.c | 22 +++++++++++++---------\n remote.c       |  3 ++-\n 2 files changed, 15 insertions(+), 10 deletions(-)\n\n-- \n2.41.0\n\n"},{"id":"479098","messageId":"20230702200818.1038494-3-alexhenrie24@gmail.com","threadId":"59944","inReplyTo":"20230702200818.1038494-1-alexhenrie24@gmail.com","subject":"[PATCH 2/2] push: advise about force-pushing as an alternative to reconciliation","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-02T20:08:17Z","receivedAt":"2023-07-02T20:10:44Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"Also, don't put `git pull` in an awkward parenthetical, because\n`git pull` can always be used to reconcile branches and is the normal\nway to do so.\n\nSigned-off-by: Alex Henrie <alexhenrie24@gmail.com>\n---\n builtin/push.c | 22 +++++++++++++---------\n 1 file changed, 13 insertions(+), 9 deletions(-)\n\ndiff --git a/builtin/push.c b/builtin/push.c\nindex 6f8a8dc711..9441c71bb0 100644\n--- a/builtin/push.c\n+++ b/builtin/push.c\n@@ -301,21 +301,24 @@ static void setup_default_push_refspecs(int *flags, struct remote *remote)\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. Integrate the remote changes (e.g.\\n\"\n-\t   \"'git pull ...') before pushing again.\\n\"\n+\t   \"its remote counterpart. Use 'git pull' to integrate the remote changes\\n\"\n+\t   \"before pushing again, or use 'git push --force' to delete the remote\\n\"\n+\t   \"changes and replace them with your own.\\n\"\n \t   \"See the 'Note about fast-forwards' in 'git push --help' for details.\");\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 integrate the remote changes\\n\"\n-\t   \"(e.g. 'git pull ...') before pushing again.\\n\"\n+\t   \"counterpart. Check out this branch and use 'git pull' to integrate the\\n\"\n+\t   \"remote changes before pushing again, or use 'git push --force' to\\n\"\n+\t   \"delete the remote changes and replace them with your own.\\n\"\n \t   \"See the 'Note about fast-forwards' in 'git push --help' for details.\");\n \n static const char message_advice_ref_fetch_first[] =\n \tN_(\"Updates were rejected because the remote contains work that you do\\n\"\n \t   \"not have locally. This is usually caused by another repository pushing\\n\"\n-\t   \"to the same ref. You may want to first integrate the remote changes\\n\"\n-\t   \"(e.g., 'git pull ...') before pushing again.\\n\"\n+\t   \"to the same ref. Use 'git pull' to integrate the remote changes before\\n\"\n+\t   \"pushing again, or use 'git push --force' to delete the remote changes\\n\"\n+\t   \"and replace them with your own.\\n\"\n \t   \"See the 'Note about fast-forwards' in 'git push --help' for details.\");\n \n static const char message_advice_ref_already_exists[] =\n@@ -328,9 +331,10 @@ static const char message_advice_ref_needs_force[] =\n \n static const char message_advice_ref_needs_update[] =\n \tN_(\"Updates were rejected because the tip of the remote-tracking\\n\"\n-\t   \"branch has been updated since the last checkout. You may want\\n\"\n-\t   \"to integrate those changes locally (e.g., 'git pull ...')\\n\"\n-\t   \"before forcing an update.\\n\");\n+\t   \"branch has been updated since the last checkout. Use 'git pull' to\\n\"\n+\t   \"integrate the remote changes before pushing again, or use\\n\"\n+\t   \"'git push --force' to delete the remote changes and replace them\\n\"\n+\t   \"with your own.\\n\");\n \n static void advise_pull_before_push(void)\n {\n-- \n2.41.0\n\n"},{"id":"479099","messageId":"20230702200818.1038494-2-alexhenrie24@gmail.com","threadId":"59944","inReplyTo":"20230702200818.1038494-1-alexhenrie24@gmail.com","subject":"[PATCH 1/2] remote: advise about force-pushing as an alternative to reconciliation","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-02T20:08:16Z","receivedAt":"2023-07-02T20:10:46Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"Also, don't imply that `git pull` is only for merging.\n\nSigned-off-by: Alex Henrie <alexhenrie24@gmail.com>\n---\n remote.c | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/remote.c b/remote.c\nindex a81f2e2f17..161d0cfe96 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -2323,7 +2323,8 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb,\n \t\t\tbase, ours, theirs);\n \t\tif (advice_enabled(ADVICE_STATUS_HINTS))\n \t\t\tstrbuf_addstr(sb,\n-\t\t\t\t_(\"  (use \\\"git pull\\\" to merge the remote branch into yours)\\n\"));\n+\t\t\t\t_(\"  (use \\\"git pull\\\" to reconcile your local branch with the remote branch,\\n\"\n+\t\t\t\t  \"  or \\\"git push --force\\\" to overwrite the remote branch with your local branch)\\n\"));\n \t}\n \tfree(base);\n \treturn 1;\n-- \n2.41.0\n\n"},{"id":"479136","messageId":"c3c36f93-3fc5-7f7d-1c24-e6925729cc96@gmail.com","threadId":"59944","inReplyTo":"20230702200818.1038494-1-alexhenrie24@gmail.com","subject":"Re: [PATCH 0/2] advise about force-pushing as an alternative to reconciliation","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2023-07-03T15:33:02Z","receivedAt":"2023-07-03T15:33:15Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Alex\n\nOn 02/07/2023 21:08, Alex Henrie wrote:\n> Many times now, I have seen novices do the following:\n> \n> 1. Start work on their own personal topic branch\n> 2. Push the branch to origin\n> 3. Rebase the branch onto origin/master\n> 4. Try to push again, but Git says they need to pull\n> 5. Pull and make a mess trying to reconcile the older topic branch with\n>     the rebased topic branch\n> \n> Help avoid this mistake by giving advice that mentions force-pushing,\n> rather than assuming that the user always wants to do reconciliation.\n\nI don't think we want to be advising users to force push. For the case \nyou mention above I think it would be much safer to advise them to use\n\n\tgit push --force-if-includes\n\nIn the absence of background fetches even\n\n\tgit push --force-with-lease\n\nis still safer than\n\n\tgit push --force\n\nBest Wishes\n\nPhillip\n\n> Alex Henrie (2):\n>    remote: advise about force-pushing as an alternative to reconciliation\n>    push: advise about force-pushing as an alternative to reconciliation\n> \n>   builtin/push.c | 22 +++++++++++++---------\n>   remote.c       |  3 ++-\n>   2 files changed, 15 insertions(+), 10 deletions(-)\n> \n"},{"id":"479138","messageId":"CAMMLpeTDqABQij5=h5aaJT4auCoKzhX7LEX02bxRFn=YtCPZfw@mail.gmail.com","threadId":"59944","inReplyTo":"c3c36f93-3fc5-7f7d-1c24-e6925729cc96@gmail.com","subject":"Re: [PATCH 0/2] advise about force-pushing as an alternative to reconciliation","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-03T16:26:23Z","receivedAt":"2023-07-03T16:27:02Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"On Mon, Jul 3, 2023 at 9:33 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n\n> On 02/07/2023 21:08, Alex Henrie wrote:\n> > Many times now, I have seen novices do the following:\n> >\n> > 1. Start work on their own personal topic branch\n> > 2. Push the branch to origin\n> > 3. Rebase the branch onto origin/master\n> > 4. Try to push again, but Git says they need to pull\n> > 5. Pull and make a mess trying to reconcile the older topic branch with\n> >     the rebased topic branch\n> >\n> > Help avoid this mistake by giving advice that mentions force-pushing,\n> > rather than assuming that the user always wants to do reconciliation.\n>\n> I don't think we want to be advising users to force push. For the case\n> you mention above I think it would be much safer to advise them to use\n>\n>         git push --force-if-includes\n>\n> In the absence of background fetches even\n>\n>         git push --force-with-lease\n>\n> is still safer than\n>\n>         git push --force\n\nHi Phillip, thanks for the feedback. --force-with-lease would be fine.\nI'll make that change in v2.\n\nRegarding your other suggestion, --force-if-includes doesn't do\nanything unless --force-with-lease is also specified, and I think\nrecommending that users always type --force-with-lease\n--force-if-includes is a bit much to ask of them. It also could lead\nto confusion if the user has decided to delete the local branch and\nstart over, and is now trying to push the new local branch over the\nold one on the remote.\n\n-Alex\n"},{"id":"479170","messageId":"20230704194756.166111-3-alexhenrie24@gmail.com","threadId":"59944","inReplyTo":"20230704194756.166111-1-alexhenrie24@gmail.com","subject":"[PATCH v2 2/2] push: advise about force-pushing as an alternative to reconciliation","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-04T19:47:47Z","receivedAt":"2023-07-04T19:48:37Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"Also, don't put `git pull` in an awkward parenthetical, because\n`git pull` can always be used to reconcile branches and is the normal\nway to do so.\n\nSigned-off-by: Alex Henrie <alexhenrie24@gmail.com>\n---\n builtin/push.c | 29 +++++++++++++++++------------\n 1 file changed, 17 insertions(+), 12 deletions(-)\n\ndiff --git a/builtin/push.c b/builtin/push.c\nindex 6f8a8dc711..8e70046304 100644\n--- a/builtin/push.c\n+++ b/builtin/push.c\n@@ -301,21 +301,25 @@ static void setup_default_push_refspecs(int *flags, struct remote *remote)\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. Integrate the remote changes (e.g.\\n\"\n-\t   \"'git pull ...') before pushing again.\\n\"\n+\t   \"its remote counterpart. Use 'git pull' to integrate the remote changes\\n\"\n+\t   \"before pushing again, or use 'git push --force-with-lease' to delete the\\n\"\n+\t   \"remote changes and replace them with your own.\\n\"\n \t   \"See the 'Note about fast-forwards' in 'git push --help' for details.\");\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 integrate the remote changes\\n\"\n-\t   \"(e.g. 'git pull ...') before pushing again.\\n\"\n+\t   \"counterpart. Check out this branch and use 'git pull' to integrate the\\n\"\n+\t   \"remote changes before pushing again, or use\\n\"\n+\t   \"'git push --force-with-lease' to delete the remote changes and replace\\n\"\n+\t   \"them with your own.\\n\"\n \t   \"See the 'Note about fast-forwards' in 'git push --help' for details.\");\n \n static const char message_advice_ref_fetch_first[] =\n-\tN_(\"Updates were rejected because the remote contains work that you do\\n\"\n-\t   \"not have locally. This is usually caused by another repository pushing\\n\"\n-\t   \"to the same ref. You may want to first integrate the remote changes\\n\"\n-\t   \"(e.g., 'git pull ...') before pushing again.\\n\"\n+\tN_(\"Updates were rejected because the remote contains work that you do not\\n\"\n+\t   \"have locally. This is usually caused by another repository pushing to\\n\"\n+\t   \"the same ref. Use 'git pull' to integrate the remote changes before\\n\"\n+\t   \"pushing again, or use 'git push --force-with-lease' to delete the\\n\"\n+\t   \"remote changes and replace them with your own.\\n\"\n \t   \"See the 'Note about fast-forwards' in 'git push --help' for details.\");\n \n static const char message_advice_ref_already_exists[] =\n@@ -327,10 +331,11 @@ static const char message_advice_ref_needs_force[] =\n \t   \"without using the '--force' option.\\n\");\n \n static const char message_advice_ref_needs_update[] =\n-\tN_(\"Updates were rejected because the tip of the remote-tracking\\n\"\n-\t   \"branch has been updated since the last checkout. You may want\\n\"\n-\t   \"to integrate those changes locally (e.g., 'git pull ...')\\n\"\n-\t   \"before forcing an update.\\n\");\n+\tN_(\"Updates were rejected because the tip of the remote-tracking branch has\\n\"\n+\t   \"been updated since the last checkout. Use 'git pull' to integrate the\\n\"\n+\t   \"remote changes before pushing again, or use\\n\"\n+\t   \"'git push --force-with-lease' to delete the remote changes and replace\\n\"\n+\t   \"them with your own.\\n\");\n \n static void advise_pull_before_push(void)\n {\n-- \n2.41.0\n\n"},{"id":"479171","messageId":"20230704194756.166111-1-alexhenrie24@gmail.com","threadId":"59944","inReplyTo":"20230702200818.1038494-1-alexhenrie24@gmail.com","subject":"[PATCH v2 0/2] advise about force-pushing as an alternative to reconciliation","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-04T19:47:45Z","receivedAt":"2023-07-04T19:48:41Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"Many times now, I have seen novices do the following:\n\n1. Start work on their own personal topic branch\n2. Push the branch to origin\n3. Rebase the branch onto origin/master\n4. Try to push again, but Git says they need to pull\n5. Pull and make a mess trying to reconcile the older topic branch with\n   the rebased topic branch\n\nHelp avoid this mistake by giving advice that mentions force-pushing,\nrather than assuming that the user always wants to do reconciliation.\n\nChanges from v1:\n- Recommend --force-with-lease instead of plain --force\n- Consistently wrap messages to 72 characters\n\nAlex Henrie (2):\n  remote: advise about force-pushing as an alternative to reconciliation\n  push: advise about force-pushing as an alternative to reconciliation\n\n builtin/push.c | 29 +++++++++++++++++------------\n remote.c       |  4 +++-\n 2 files changed, 20 insertions(+), 13 deletions(-)\n\nRange-diff against v1:\n1:  48a9f6b1fa ! 1:  d0cb607225 remote: advise about force-pushing as an alternative to reconciliation\n    @@ remote.c: int format_tracking_info(struct branch *branch, struct strbuf *sb,\n      \t\t\tstrbuf_addstr(sb,\n     -\t\t\t\t_(\"  (use \\\"git pull\\\" to merge the remote branch into yours)\\n\"));\n     +\t\t\t\t_(\"  (use \\\"git pull\\\" to reconcile your local branch with the remote branch,\\n\"\n    -+\t\t\t\t  \"  or \\\"git push --force\\\" to overwrite the remote branch with your local branch)\\n\"));\n    ++\t\t\t\t  \"  or \\\"git push --force-with-lease\\\" to overwrite the remote branch with\\n\"\n    ++\t\t\t\t  \"  your local branch)\\n\"));\n      \t}\n      \tfree(base);\n      \treturn 1;\n2:  0d47c23320 < -:  ---------- push: advise about force-pushing as an alternative to reconciliation\n-:  ---------- > 2:  3295f0bb2b push: advise about force-pushing as an alternative to reconciliation\n-- \n2.41.0\n\n"},{"id":"479172","messageId":"20230704194756.166111-2-alexhenrie24@gmail.com","threadId":"59944","inReplyTo":"20230704194756.166111-1-alexhenrie24@gmail.com","subject":"[PATCH v2 1/2] remote: advise about force-pushing as an alternative to reconciliation","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-04T19:47:46Z","receivedAt":"2023-07-04T19:48:41Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"Also, don't imply that `git pull` is only for merging.\n\nSigned-off-by: Alex Henrie <alexhenrie24@gmail.com>\n---\n remote.c | 4 +++-\n 1 file changed, 3 insertions(+), 1 deletion(-)\n\ndiff --git a/remote.c b/remote.c\nindex a81f2e2f17..009034ecde 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -2323,7 +2323,9 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb,\n \t\t\tbase, ours, theirs);\n \t\tif (advice_enabled(ADVICE_STATUS_HINTS))\n \t\t\tstrbuf_addstr(sb,\n-\t\t\t\t_(\"  (use \\\"git pull\\\" to merge the remote branch into yours)\\n\"));\n+\t\t\t\t_(\"  (use \\\"git pull\\\" to reconcile your local branch with the remote branch,\\n\"\n+\t\t\t\t  \"  or \\\"git push --force-with-lease\\\" to overwrite the remote branch with\\n\"\n+\t\t\t\t  \"  your local branch)\\n\"));\n \t}\n \tfree(base);\n \treturn 1;\n-- \n2.41.0\n\n"},{"id":"479173","messageId":"xmqqv8ez4ajb.fsf@gitster.g","threadId":"59944","inReplyTo":"c3c36f93-3fc5-7f7d-1c24-e6925729cc96@gmail.com","subject":"Re: [PATCH 0/2] advise about force-pushing as an alternative to reconciliation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-07-04T21:44:08Z","receivedAt":"2023-07-04T21:44:26Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n> Hi Alex\n>\n> On 02/07/2023 21:08, Alex Henrie wrote:\n>> Many times now, I have seen novices do the following:\n>> 1. Start work on their own personal topic branch\n>> 2. Push the branch to origin\n\nAnd did this succeed, or did this fail?  I'd assume that it failed,\nbecause othrewise you would not be rebasing your work done in #1 on\ntop of what the central repository has.  Also ...\n\n>> 3. Rebase the branch onto origin/master\n\n... the user's better have done \"git fetch\" to update origin/master\nbefore this step.  And that means this can just be done with \"git\npull --rebase\" (or you may already have configured pull to do so).\n\nIn any case, assuming that this was indeed the intention of the\nuser, i.e. the user never wanted to discard the changes made in the\ncentral repository (presumably by others)...\n\n>> 4. Try to push again, but Git says they need to pull\n\n... if this happened, it is because somebody else pushed in the\nmeantime, right?  Then ...\n\n>> 5. Pull and make a mess trying to reconcile the older topic branch with\n>>     the rebased topic branch\n\n... this means that somebody else's work was something that\noverlapped with what you did in #1, and then you do want to clean up\nthe mess carefully, so that you do not lose the work by that\nsomebody else.  So ...\n\n>> Help avoid this mistake by giving advice that mentions\n>> force-pushing,\n\n... why would it possibly be a good idea to suggest force pushing,\nwhich discards other's work?  I do not quite understand.\n\n> I don't think we want to be advising users to force push. For the case\n> you mention above I think it would be much safer to advise them to use\n>\n> \tgit push --force-if-includes\n>\n> In the absence of background fetches even\n>\n> \tgit push --force-with-lease\n>\n> is still safer than\n>\n> \tgit push --force\n\nAbsolutely.  git push --force-with-lease=$(git merge-base HEAD origin/master)\nor something, perhaps, would be even better.\n\nThanks.\n"},{"id":"479174","messageId":"xmqqr0pn4a6c.fsf@gitster.g","threadId":"59944","inReplyTo":"20230704194756.166111-2-alexhenrie24@gmail.com","subject":"Re: [PATCH v2 1/2] remote: advise about force-pushing as an alternative to reconciliation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-07-04T21:51:55Z","receivedAt":"2023-07-04T21:52:03Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Alex Henrie <alexhenrie24@gmail.com> writes:\n\n> Also, don't imply that `git pull` is only for merging.\n>\n> Signed-off-by: Alex Henrie <alexhenrie24@gmail.com>\n> ---\n>  remote.c | 4 +++-\n>  1 file changed, 3 insertions(+), 1 deletion(-)\n>\n> diff --git a/remote.c b/remote.c\n> index a81f2e2f17..009034ecde 100644\n> --- a/remote.c\n> +++ b/remote.c\n> @@ -2323,7 +2323,9 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb,\n>  \t\t\tbase, ours, theirs);\n>  \t\tif (advice_enabled(ADVICE_STATUS_HINTS))\n>  \t\t\tstrbuf_addstr(sb,\n> -\t\t\t\t_(\"  (use \\\"git pull\\\" to merge the remote branch into yours)\\n\"));\n> +\t\t\t\t_(\"  (use \\\"git pull\\\" to reconcile your local branch with the remote branch,\\n\"\n> +\t\t\t\t  \"  or \\\"git push --force-with-lease\\\" to overwrite the remote branch with\\n\"\n> +\t\t\t\t  \"  your local branch)\\n\"));\n>  \t}\n>  \tfree(base);\n>  \treturn 1;\n\nUse of --force-with-lease without which commit you assume to be at\nthe tip of their branch is just as risky as blind use of --force.\n\nAs I said in a separate message, I do not think \"reconcile\" and\n\"force\" cannot both be sensible choices at the same time.  If the\nuser wants not to lose the work by themselves and by others,\nreconciling would be the only sensible choice and forcing cannot be\na sane substitute for that (if the user knows what is at the tip of\ncentral repository is wrong and wants to get rid of it, forcing\nwould be a very sensible choice, but then reconciling would not be a\nsubsitute for that in such a case---\"merge --ours\" does not count as\n\"reconciling\").\n\nSo, I'd suggest to make it a bit more clear that they are not\nalternatives in the message, and discourage forcing in the first\nplace by using not \"overwrite\" but a bit stronger word, like discard\nor destroy.  e.g.\n\n    To reconcile your local changes with the work at the remote, you\n    can use 'git pull' and then 'git push'.  To discard the work at\n    the remote and replace it with what you did (alone), you can use\n    'git push --force'.\n\nor something, perhaps.\n\nThanks.\n"},{"id":"479177","messageId":"CAMMLpeS5QJrFFnN14n33_LiaN9MP5Ea=HV24ZFM30zPnmhoqZw@mail.gmail.com","threadId":"59944","inReplyTo":"xmqqv8ez4ajb.fsf@gitster.g","subject":"Re: [PATCH 0/2] advise about force-pushing as an alternative to reconciliation","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-04T22:24:00Z","receivedAt":"2023-07-04T22:24:26Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"On Tue, Jul 4, 2023 at 3:44 PM Junio C Hamano <gitster@pobox.com> wrote:\n\n> > On 02/07/2023 21:08, Alex Henrie wrote:\n> >> Many times now, I have seen novices do the following:\n> >> 1. Start work on their own personal topic branch\n> >> 2. Push the branch to origin\n>\n> And did this succeed, or did this fail?  I'd assume that it failed,\n> because othrewise you would not be rebasing your work done in #1 on\n> top of what the central repository has.  Also ...\n\nIt succeeded; the new branch was created on origin.\n\n> >> 3. Rebase the branch onto origin/master\n>\n> ... the user's better have done \"git fetch\" to update origin/master\n> before this step.  And that means this can just be done with \"git\n> pull --rebase\" (or you may already have configured pull to do so).\n\nYes, the rebase was performed with `git pull -r origin master`. Other\nwork had been done on master while the topic branch was being worked\non.\n\n> In any case, assuming that this was indeed the intention of the\n> user, i.e. the user never wanted to discard the changes made in the\n> central repository (presumably by others)...\n\nThe user did not want to discard anything from master, but they\nabsolutely did want to discard the obsolete version of their own\nbranch, which they made themself.\n\n> >> 4. Try to push again, but Git says they need to pull\n>\n> ... if this happened, it is because somebody else pushed in the\n> meantime, right?  Then ...\n\nNo one pushed between steps 3 and 4.\n\n> >> 5. Pull and make a mess trying to reconcile the older topic branch with\n> >>     the rebased topic branch\n>\n> ... this means that somebody else's work was something that\n> overlapped with what you did in #1, and then you do want to clean up\n> the mess carefully, so that you do not lose the work by that\n> somebody else.  So ...\n\nThe conflicts came from trying to reconcile an older version of the\nuser's work with a rebased version of the user's work. The user\ndoesn't want to end up with a history that has two commits from the\nsame author with the same message.\n\n> >> Help avoid this mistake by giving advice that mentions\n> >> force-pushing,\n>\n> ... why would it possibly be a good idea to suggest force pushing,\n> which discards other's work?  I do not quite understand.\n\nThe user was only trying to overwrite the old version of their own\nbranch, which no one cares about. This scenario comes up commonly when\nusing a single shared remote repository, or when using a forked remote\nrepository and running `git pull -r upstream master` to incorporate\nchanges from the upstream remote repository.\n\nI hope that's more clear now. Please let me know if it's not.\n\n-Alex\n"},{"id":"479178","messageId":"CAMMLpeQQk8ik9rJxNNKo9-3hGUuts5W70V=ABB=k9mNwVp+2KQ@mail.gmail.com","threadId":"59944","inReplyTo":"xmqqr0pn4a6c.fsf@gitster.g","subject":"Re: [PATCH v2 1/2] remote: advise about force-pushing as an alternative to reconciliation","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-04T22:41:16Z","receivedAt":"2023-07-04T22:45:42Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"On Tue, Jul 4, 2023 at 3:52 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Alex Henrie <alexhenrie24@gmail.com> writes:\n>\n> > Also, don't imply that `git pull` is only for merging.\n> >\n> > Signed-off-by: Alex Henrie <alexhenrie24@gmail.com>\n> > ---\n> >  remote.c | 4 +++-\n> >  1 file changed, 3 insertions(+), 1 deletion(-)\n> >\n> > diff --git a/remote.c b/remote.c\n> > index a81f2e2f17..009034ecde 100644\n> > --- a/remote.c\n> > +++ b/remote.c\n> > @@ -2323,7 +2323,9 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb,\n> >                       base, ours, theirs);\n> >               if (advice_enabled(ADVICE_STATUS_HINTS))\n> >                       strbuf_addstr(sb,\n> > -                             _(\"  (use \\\"git pull\\\" to merge the remote branch into yours)\\n\"));\n> > +                             _(\"  (use \\\"git pull\\\" to reconcile your local branch with the remote branch,\\n\"\n> > +                               \"  or \\\"git push --force-with-lease\\\" to overwrite the remote branch with\\n\"\n> > +                               \"  your local branch)\\n\"));\n> >       }\n> >       free(base);\n> >       return 1;\n>\n> Use of --force-with-lease without which commit you assume to be at\n> the tip of their branch is just as risky as blind use of --force.\n>\n> As I said in a separate message, I do not think \"reconcile\" and\n> \"force\" cannot both be sensible choices at the same time.  If the\n> user wants not to lose the work by themselves and by others,\n> reconciling would be the only sensible choice and forcing cannot be\n> a sane substitute for that (if the user knows what is at the tip of\n> central repository is wrong and wants to get rid of it, forcing\n> would be a very sensible choice, but then reconciling would not be a\n> subsitute for that in such a case---\"merge --ours\" does not count as\n> \"reconciling\").\n>\n> So, I'd suggest to make it a bit more clear that they are not\n> alternatives in the message, and discourage forcing in the first\n> place by using not \"overwrite\" but a bit stronger word, like discard\n> or destroy.  e.g.\n>\n>     To reconcile your local changes with the work at the remote, you\n>     can use 'git pull' and then 'git push'.  To discard the work at\n>     the remote and replace it with what you did (alone), you can use\n>     'git push --force'.\n>\n> or something, perhaps.\n\nI think we're splitting hairs about what the word \"alternative\" means.\nThe user has two ways to get their work onto the remote branch:\nReconcile it with what's already there, or delete what's already\nthere. I would call those two ways \"alternatives\" and that does not\nimply that either one is always a sensible choice, but if you can\nthink of a word that's more clear, I'm happy to use it instead in\nthese commit messages.\n\nAt any rate, your proposed wording for the advice message in remote.c\nis perfectly fine. Thanks, I'll use it in v3. Would you like the same\ntext in push.c, or was my proposed text there already OK?\n\n-Alex\n"},{"id":"479179","messageId":"xmqq5y6z3oym.fsf@gitster.g","threadId":"59944","inReplyTo":"CAMMLpeS5QJrFFnN14n33_LiaN9MP5Ea=HV24ZFM30zPnmhoqZw@mail.gmail.com","subject":"Re: [PATCH 0/2] advise about force-pushing as an alternative to reconciliation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-07-05T05:30:09Z","receivedAt":"2023-07-05T05:30:28Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Alex Henrie <alexhenrie24@gmail.com> writes:\n\n> I hope that's more clear now. Please let me know if it's not.\n\nI think the description in the cover was prone to be misunderstood,\nbut I think I got it now.  Where you are pushing from your topic\nbranch is your \"publishing\" branch that only you would push into,\nand the primary way you update it is by rebasing your local copy of\nit on the updated 'master' branch to keep up with others' work\nintegrated into the shared 'master'.\n\nIn such a workflow, the way to update your \"publishing\" branch will\nnormally be to force push to overwrite.  And in this very narrow use\ncase, where nobody else is pushing into your \"publishing\" branch,\nyour remote-tracking branch would be always up-to-date with the\nremote repository and use of --force-with-lease that does not say\nwhich commit you expect there to be is safe.  In fact, you do not\neven have to use --force-with-lease in such a use case, because its\nadditional safety (relative to --force) relies on the assumption\nthat you would be the only one who is pushing into the remote\nrepository to update that branch---and at that point, --force\nwithout lease is just as good.\n\nThanks.\n"},{"id":"479251","messageId":"CAMMLpeRPcw8WbGJwbeS_E+qxKvCukNc3g-3BXeNP5BrRJJ5ifA@mail.gmail.com","threadId":"59944","inReplyTo":"xmqq5y6z3oym.fsf@gitster.g","subject":"Re: [PATCH 0/2] advise about force-pushing as an alternative to reconciliation","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-06T02:32:56Z","receivedAt":"2023-07-06T02:33:36Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"On Tue, Jul 4, 2023 at 11:30 PM Junio C Hamano <gitster@pobox.com> wrote:\n\n> I think the description in the cover was prone to be misunderstood,\n> but I think I got it now.  Where you are pushing from your topic\n> branch is your \"publishing\" branch that only you would push into,\n> and the primary way you update it is by rebasing your local copy of\n> it on the updated 'master' branch to keep up with others' work\n> integrated into the shared 'master'.\n\nRight. It's a narrow case, but it's quite common. For example, GitHub\nand GitLab keep permanent references to every version of a branch that\nwas pushed while a pull request was open for that branch. On those\nplatforms, force-pushing is analogous to emailing a new version of a\npatchset.\n\n> In such a workflow, the way to update your \"publishing\" branch will\n> normally be to force push to overwrite.  And in this very narrow use\n> case, where nobody else is pushing into your \"publishing\" branch,\n> your remote-tracking branch would be always up-to-date with the\n> remote repository and use of --force-with-lease that does not say\n> which commit you expect there to be is safe.  In fact, you do not\n> even have to use --force-with-lease in such a use case, because its\n> additional safety (relative to --force) relies on the assumption\n> that you would be the only one who is pushing into the remote\n> repository to update that branch---and at that point, --force\n> without lease is just as good.\n\nOK, I'll switch back to --force in v3. Thanks for the feedback!\n\n-Alex\n"},{"id":"479252","messageId":"20230706040111.81110-2-alexhenrie24@gmail.com","threadId":"59944","inReplyTo":"20230706040111.81110-1-alexhenrie24@gmail.com","subject":"[PATCH v3 1/2] remote: advise about force-pushing as an alternative to reconciliation","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-06T04:01:02Z","receivedAt":"2023-07-06T04:03:40Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"Also, don't imply that `git pull` is only for merging.\n\nCo-authored-by: Junio C Hamano <gitster@pobox.com>\nSigned-off-by: Alex Henrie <alexhenrie24@gmail.com>\n---\n remote.c | 5 ++++-\n 1 file changed, 4 insertions(+), 1 deletion(-)\n\ndiff --git a/remote.c b/remote.c\nindex a81f2e2f17..1fe86f8b23 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -2323,7 +2323,10 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb,\n \t\t\tbase, ours, theirs);\n \t\tif (advice_enabled(ADVICE_STATUS_HINTS))\n \t\t\tstrbuf_addstr(sb,\n-\t\t\t\t_(\"  (use \\\"git pull\\\" to merge the remote branch into yours)\\n\"));\n+\t\t\t\t_(\"  (To reconcile your local changes with the work at the remote, you can\\n\"\n+\t\t\t\t  \"  use 'git pull' and then 'git push'. To discard the work at the remote\\n\"\n+\t\t\t\t  \"  and replace it with what you did (alone), you can use\\n\"\n+\t\t\t\t  \"  'git push --force'.)\\n\"));\n \t}\n \tfree(base);\n \treturn 1;\n-- \n2.41.0\n\n"},{"id":"479253","messageId":"20230706040111.81110-3-alexhenrie24@gmail.com","threadId":"59944","inReplyTo":"20230706040111.81110-1-alexhenrie24@gmail.com","subject":"[PATCH v3 2/2] push: advise about force-pushing as an alternative to reconciliation","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-06T04:01:03Z","receivedAt":"2023-07-06T04:03:40Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"Also, don't put `git pull` in an awkward parenthetical, because\n`git pull` can always be used to reconcile branches and is the normal\nway to do so.\n\nSigned-off-by: Alex Henrie <alexhenrie24@gmail.com>\n---\n builtin/push.c | 27 +++++++++++++++------------\n 1 file changed, 15 insertions(+), 12 deletions(-)\n\ndiff --git a/builtin/push.c b/builtin/push.c\nindex 6f8a8dc711..b2f0a64e7c 100644\n--- a/builtin/push.c\n+++ b/builtin/push.c\n@@ -301,21 +301,24 @@ static void setup_default_push_refspecs(int *flags, struct remote *remote)\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. Integrate the remote changes (e.g.\\n\"\n-\t   \"'git pull ...') before pushing again.\\n\"\n+\t   \"its remote counterpart. Use 'git pull' to integrate the remote changes\\n\"\n+\t   \"before pushing again, or use 'git push --force' to delete the remote\\n\"\n+\t   \"changes and replace them with your own.\\n\"\n \t   \"See the 'Note about fast-forwards' in 'git push --help' for details.\");\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 integrate the remote changes\\n\"\n-\t   \"(e.g. 'git pull ...') before pushing again.\\n\"\n+\t   \"counterpart. Check out this branch and use 'git pull' to integrate the\\n\"\n+\t   \"remote changes before pushing again, or use 'git push --force' to delete\\n\"\n+\t   \"the remote changes and replace them with your own.\\n\"\n \t   \"See the 'Note about fast-forwards' in 'git push --help' for details.\");\n \n static const char message_advice_ref_fetch_first[] =\n-\tN_(\"Updates were rejected because the remote contains work that you do\\n\"\n-\t   \"not have locally. This is usually caused by another repository pushing\\n\"\n-\t   \"to the same ref. You may want to first integrate the remote changes\\n\"\n-\t   \"(e.g., 'git pull ...') before pushing again.\\n\"\n+\tN_(\"Updates were rejected because the remote contains work that you do not\\n\"\n+\t   \"have locally. This is usually caused by another repository pushing to\\n\"\n+\t   \"the same ref. Use 'git pull' to integrate the remote changes before\\n\"\n+\t   \"pushing again, or use 'git push --force' to delete the remote changes\\n\"\n+\t   \"and replace them with your own.\\n\"\n \t   \"See the 'Note about fast-forwards' in 'git push --help' for details.\");\n \n static const char message_advice_ref_already_exists[] =\n@@ -327,10 +330,10 @@ static const char message_advice_ref_needs_force[] =\n \t   \"without using the '--force' option.\\n\");\n \n static const char message_advice_ref_needs_update[] =\n-\tN_(\"Updates were rejected because the tip of the remote-tracking\\n\"\n-\t   \"branch has been updated since the last checkout. You may want\\n\"\n-\t   \"to integrate those changes locally (e.g., 'git pull ...')\\n\"\n-\t   \"before forcing an update.\\n\");\n+\tN_(\"Updates were rejected because the tip of the remote-tracking branch has\\n\"\n+\t   \"been updated since the last checkout. Use 'git pull' to integrate the\\n\"\n+\t   \"remote changes before pushing again, or use 'git push --force' to delete\\n\"\n+\t   \"the remote changes and replace them with your own.\\n\");\n \n static void advise_pull_before_push(void)\n {\n-- \n2.41.0\n\n"},{"id":"479254","messageId":"20230706040111.81110-1-alexhenrie24@gmail.com","threadId":"59944","inReplyTo":"20230704194756.166111-1-alexhenrie24@gmail.com","subject":"[PATCH v3 0/2] advise about force-pushing as an alternative to reconciliation","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-06T04:01:01Z","receivedAt":"2023-07-06T04:03:40Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"Many times now, I have seen novices do the following:\n\n1. Start work on their own personal topic branch\n2. Push the branch to origin\n3. Rebase the branch onto origin/master\n4. Try to push again, but Git says they need to pull\n5. Pull and make a mess trying to reconcile the older topic branch with\n   the rebased topic branch\n\nHelp avoid this mistake by giving advice that mentions force-pushing,\nrather than assuming that the user always wants to do reconciliation.\n\nChanges from v2:\n- Switch back to recommending plain --force in these cases\n- Use Junio's proposed wording in remote.c\n\nAlex Henrie (2):\n  remote: advise about force-pushing as an alternative to reconciliation\n  push: advise about force-pushing as an alternative to reconciliation\n\n builtin/push.c | 27 +++++++++++++++------------\n remote.c       |  5 ++++-\n 2 files changed, 19 insertions(+), 13 deletions(-)\n\nRange-diff against v2:\n1:  d0cb607225 < -:  ---------- remote: advise about force-pushing as an alternative to reconciliation\n-:  ---------- > 1:  9cbf5f138e remote: advise about force-pushing as an alternative to reconciliation\n2:  3295f0bb2b ! 2:  727e1f7636 push: advise about force-pushing as an alternative to reconciliation\n    @@ builtin/push.c: static void setup_default_push_refspecs(int *flags, struct remot\n     -\t   \"its remote counterpart. Integrate the remote changes (e.g.\\n\"\n     -\t   \"'git pull ...') before pushing again.\\n\"\n     +\t   \"its remote counterpart. Use 'git pull' to integrate the remote changes\\n\"\n    -+\t   \"before pushing again, or use 'git push --force-with-lease' to delete the\\n\"\n    -+\t   \"remote changes and replace them with your own.\\n\"\n    ++\t   \"before pushing again, or use 'git push --force' to delete the remote\\n\"\n    ++\t   \"changes and replace them with your own.\\n\"\n      \t   \"See the 'Note about fast-forwards' in 'git push --help' for details.\");\n      \n      static const char message_advice_checkout_pull_push[] =\n    @@ builtin/push.c: static void setup_default_push_refspecs(int *flags, struct remot\n     -\t   \"counterpart. Check out this branch and integrate the remote changes\\n\"\n     -\t   \"(e.g. 'git pull ...') before pushing again.\\n\"\n     +\t   \"counterpart. Check out this branch and use 'git pull' to integrate the\\n\"\n    -+\t   \"remote changes before pushing again, or use\\n\"\n    -+\t   \"'git push --force-with-lease' to delete the remote changes and replace\\n\"\n    -+\t   \"them with your own.\\n\"\n    ++\t   \"remote changes before pushing again, or use 'git push --force' to delete\\n\"\n    ++\t   \"the remote changes and replace them with your own.\\n\"\n      \t   \"See the 'Note about fast-forwards' in 'git push --help' for details.\");\n      \n      static const char message_advice_ref_fetch_first[] =\n    @@ builtin/push.c: static void setup_default_push_refspecs(int *flags, struct remot\n     +\tN_(\"Updates were rejected because the remote contains work that you do not\\n\"\n     +\t   \"have locally. This is usually caused by another repository pushing to\\n\"\n     +\t   \"the same ref. Use 'git pull' to integrate the remote changes before\\n\"\n    -+\t   \"pushing again, or use 'git push --force-with-lease' to delete the\\n\"\n    -+\t   \"remote changes and replace them with your own.\\n\"\n    ++\t   \"pushing again, or use 'git push --force' to delete the remote changes\\n\"\n    ++\t   \"and replace them with your own.\\n\"\n      \t   \"See the 'Note about fast-forwards' in 'git push --help' for details.\");\n      \n      static const char message_advice_ref_already_exists[] =\n    @@ builtin/push.c: static const char message_advice_ref_needs_force[] =\n     -\t   \"before forcing an update.\\n\");\n     +\tN_(\"Updates were rejected because the tip of the remote-tracking branch has\\n\"\n     +\t   \"been updated since the last checkout. Use 'git pull' to integrate the\\n\"\n    -+\t   \"remote changes before pushing again, or use\\n\"\n    -+\t   \"'git push --force-with-lease' to delete the remote changes and replace\\n\"\n    -+\t   \"them with your own.\\n\");\n    ++\t   \"remote changes before pushing again, or use 'git push --force' to delete\\n\"\n    ++\t   \"the remote changes and replace them with your own.\\n\");\n      \n      static void advise_pull_before_push(void)\n      {\n-- \n2.41.0\n\n"},{"id":"479262","messageId":"xmqqttugbxds.fsf@gitster.g","threadId":"59944","inReplyTo":"20230706040111.81110-2-alexhenrie24@gmail.com","subject":"Re: [PATCH v3 1/2] remote: advise about force-pushing as an alternative to reconciliation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-07-06T20:25:35Z","receivedAt":"2023-07-06T20:25:45Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Alex Henrie <alexhenrie24@gmail.com> writes:\n\n> Also, don't imply that `git pull` is only for merging.\n>\n> Co-authored-by: Junio C Hamano <gitster@pobox.com>\n\nI appreciate, but do not need, the credit; in any way, I didn't\nco-author this one.\n\n> Signed-off-by: Alex Henrie <alexhenrie24@gmail.com>\n> ---\n>  remote.c | 5 ++++-\n>  1 file changed, 4 insertions(+), 1 deletion(-)\n>\n> diff --git a/remote.c b/remote.c\n> index a81f2e2f17..1fe86f8b23 100644\n> --- a/remote.c\n> +++ b/remote.c\n> @@ -2323,7 +2323,10 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb,\n>  \t\t\tbase, ours, theirs);\n>  \t\tif (advice_enabled(ADVICE_STATUS_HINTS))\n>  \t\t\tstrbuf_addstr(sb,\n> -\t\t\t\t_(\"  (use \\\"git pull\\\" to merge the remote branch into yours)\\n\"));\n> +\t\t\t\t_(\"  (To reconcile your local changes with the work at the remote, you can\\n\"\n> +\t\t\t\t  \"  use 'git pull' and then 'git push'. To discard the work at the remote\\n\"\n> +\t\t\t\t  \"  and replace it with what you did (alone), you can use\\n\"\n> +\t\t\t\t  \"  'git push --force'.)\\n\"));\n>  \t}\n\nSince wt-status.c:wt_longstatus_print_tracking() calls this\nfunction, I would expect that this change would manifest as test\nbreakage in \"git status\" (or \"git commit\" whose commit log edit\nbuffer is examined) tests.  Are we lacking test coverage?\n\nThanks.\n\n\n\n"},{"id":"479263","messageId":"xmqqo7kobwpj.fsf@gitster.g","threadId":"59944","inReplyTo":"xmqqttugbxds.fsf@gitster.g","subject":"Re: [PATCH v3 1/2] remote: advise about force-pushing as an alternative to reconciliation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-07-06T20:40:08Z","receivedAt":"2023-07-06T20:40:17Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n>> diff --git a/remote.c b/remote.c\n>> index a81f2e2f17..1fe86f8b23 100644\n>> --- a/remote.c\n>> +++ b/remote.c\n>> @@ -2323,7 +2323,10 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb,\n>>  \t\t\tbase, ours, theirs);\n>>  \t\tif (advice_enabled(ADVICE_STATUS_HINTS))\n>>  \t\t\tstrbuf_addstr(sb,\n>> -\t\t\t\t_(\"  (use \\\"git pull\\\" to merge the remote branch into yours)\\n\"));\n>> +\t\t\t\t_(\"  (To reconcile your local changes with the work at the remote, you can\\n\"\n>> +\t\t\t\t  \"  use 'git pull' and then 'git push'. To discard the work at the remote\\n\"\n>> +\t\t\t\t  \"  and replace it with what you did (alone), you can use\\n\"\n>> +\t\t\t\t  \"  'git push --force'.)\\n\"));\n>>  \t}\n>\n> Since wt-status.c:wt_longstatus_print_tracking() calls this\n> function, I would expect that this change would manifest as test\n> breakage in \"git status\" (or \"git commit\" whose commit log edit\n> buffer is examined) tests.  Are we lacking test coverage?\n\nThe other callsite of format_tracking_info() is \"git checkout\".\nWhen you start working on your own topic forked from upstream by\nswitching to it, if Git notices that your topic's base has become\nbehind (so that you would later need to merge or rebase to avoid\nlosing others' work), the \"git pull\" message is given to tell you\nthat it is OK if you want to catch up first before working on it.\n\nBut the new message does not fit well in the workflow.  It is\nprimarily targetted for the users who are about to push out.  They\nare at the point where they are way before being ready to \"discard\nthe work at the remote\".\n\nI guess the updated message in the context of \"git status\" has\nexactly the same issue.  The user is about to make a commit, which\nwill later be pushed out.\n\nSo, while I agree that new users may need to be made aware of\nsituations where they should not afraid of overwriting the remote\nrepository by forcing a non-ff push, I am not sure if this is a good\nadvice message to convey it.\n\n"},{"id":"479268","messageId":"CAMMLpeS9_P=XXMoOdTAM3jZbaxfLEJNwYArS6p9pMXisT3TRtw@mail.gmail.com","threadId":"59944","inReplyTo":"xmqqo7kobwpj.fsf@gitster.g","subject":"Re: [PATCH v3 1/2] remote: advise about force-pushing as an alternative to reconciliation","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-06T23:23:42Z","receivedAt":"2023-07-06T23:24:23Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"On Thu, Jul 6, 2023 at 2:40 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Junio C Hamano <gitster@pobox.com> writes:\n>\n> >> diff --git a/remote.c b/remote.c\n> >> index a81f2e2f17..1fe86f8b23 100644\n> >> --- a/remote.c\n> >> +++ b/remote.c\n> >> @@ -2323,7 +2323,10 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb,\n> >>                      base, ours, theirs);\n> >>              if (advice_enabled(ADVICE_STATUS_HINTS))\n> >>                      strbuf_addstr(sb,\n> >> -                            _(\"  (use \\\"git pull\\\" to merge the remote branch into yours)\\n\"));\n> >> +                            _(\"  (To reconcile your local changes with the work at the remote, you can\\n\"\n> >> +                              \"  use 'git pull' and then 'git push'. To discard the work at the remote\\n\"\n> >> +                              \"  and replace it with what you did (alone), you can use\\n\"\n> >> +                              \"  'git push --force'.)\\n\"));\n> >>      }\n> >\n> > Since wt-status.c:wt_longstatus_print_tracking() calls this\n> > function, I would expect that this change would manifest as test\n> > breakage in \"git status\" (or \"git commit\" whose commit log edit\n> > buffer is examined) tests.  Are we lacking test coverage?\n\nBecause I was only changing advice messages and not any functionality,\nI didn't think to run the tests. They are indeed failing, sorry. I\nwill fix that in v4.\n\n> The other callsite of format_tracking_info() is \"git checkout\".\n> When you start working on your own topic forked from upstream by\n> switching to it, if Git notices that your topic's base has become\n> behind (so that you would later need to merge or rebase to avoid\n> losing others' work), the \"git pull\" message is given to tell you\n> that it is OK if you want to catch up first before working on it.\n>\n> But the new message does not fit well in the workflow.  It is\n> primarily targetted for the users who are about to push out.  They\n> are at the point where they are way before being ready to \"discard\n> the work at the remote\".\n\nIf the branch is merely behind, format_tracking_info prints \"(use \"git\npull\" to update your local branch)\", which is perfectly reasonable.\nThe problem is only with the message that appears when the branches\nare divergent, \"(use \"git pull\" to merge the remote branch into\nyours)\", which is bad advice for the common GitHub/GitLab workflow\nthat expects force-pushing.\n\n> I guess the updated message in the context of \"git status\" has\n> exactly the same issue.  The user is about to make a commit, which\n> will later be pushed out.\n>\n> So, while I agree that new users may need to be made aware of\n> situations where they should not afraid of overwriting the remote\n> repository by forcing a non-ff push, I am not sure if this is a good\n> advice message to convey it.\n\nFor more context, the coworker who most recently had this problem\ntried to pull because he looked at `git status` _after_ committing.\nGit can't assume that certain commands go with certain workflows (at\nleast, not when it comes to divergent branches). Even if the user\nswitches to a different branch and switches back, the first branch\nmight be divergent simply because the user forgot to force-push before\nswitching off of it. So, let's please give the user all of the\ninformation (two ways forward: reconcile or delete) and encourage them\nto make the most appropriate decision for their particular workflow.\n\n-Alex\n"},{"id":"479270","messageId":"20230707054257.3366355-1-alexhenrie24@gmail.com","threadId":"59944","inReplyTo":"20230706040111.81110-1-alexhenrie24@gmail.com","subject":"[PATCH v4 0/2] advise about force-pushing as an alternative to reconciliation","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-07T05:42:46Z","receivedAt":"2023-07-07T05:43:30Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"Many times now, I have seen novices do the following:\n\n1. Start work on their own personal topic branch\n2. Push the branch to origin\n3. Rebase the branch onto origin/master\n4. Try to push again, but Git says they need to pull\n5. Pull and make a mess trying to reconcile the older topic branch with\n   the rebased topic branch\n\nHelp avoid this mistake by giving advice that mentions force-pushing,\nrather than assuming that the user always wants to do reconciliation.\n\nChanges from v3:\n- Update the tests\n- Don't explicitly credit Junio\n\nAlex Henrie (2):\n  remote: advise about force-pushing as an alternative to reconciliation\n  push: advise about force-pushing as an alternative to reconciliation\n\n builtin/push.c    |  27 +++++++-----\n remote.c          |   5 ++-\n t/t7508-status.sh | 110 ++++++++++++++++++++++++++++++++++++----------\n 3 files changed, 107 insertions(+), 35 deletions(-)\n\nRange-diff against v3:\n1:  9cbf5f138e < -:  ---------- remote: advise about force-pushing as an alternative to reconciliation\n-:  ---------- > 1:  9626721c13 remote: advise about force-pushing as an alternative to reconciliation\n2:  727e1f7636 = 2:  209e86588a push: advise about force-pushing as an alternative to reconciliation\n-- \n2.41.0\n\n"},{"id":"479271","messageId":"20230707054257.3366355-2-alexhenrie24@gmail.com","threadId":"59944","inReplyTo":"20230707054257.3366355-1-alexhenrie24@gmail.com","subject":"[PATCH v4 1/2] remote: advise about force-pushing as an alternative to reconciliation","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-07T05:42:47Z","receivedAt":"2023-07-07T05:43:32Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"Also, don't imply that `git pull` is only for merging.\n\nSigned-off-by: Alex Henrie <alexhenrie24@gmail.com>\n---\n remote.c          |   5 ++-\n t/t7508-status.sh | 110 ++++++++++++++++++++++++++++++++++++----------\n 2 files changed, 92 insertions(+), 23 deletions(-)\n\ndiff --git a/remote.c b/remote.c\nindex a81f2e2f17..1fe86f8b23 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -2323,7 +2323,10 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb,\n \t\t\tbase, ours, theirs);\n \t\tif (advice_enabled(ADVICE_STATUS_HINTS))\n \t\t\tstrbuf_addstr(sb,\n-\t\t\t\t_(\"  (use \\\"git pull\\\" to merge the remote branch into yours)\\n\"));\n+\t\t\t\t_(\"  (To reconcile your local changes with the work at the remote, you can\\n\"\n+\t\t\t\t  \"  use 'git pull' and then 'git push'. To discard the work at the remote\\n\"\n+\t\t\t\t  \"  and replace it with what you did (alone), you can use\\n\"\n+\t\t\t\t  \"  'git push --force'.)\\n\"));\n \t}\n \tfree(base);\n \treturn 1;\ndiff --git a/t/t7508-status.sh b/t/t7508-status.sh\nindex 36567708f5..2a17e84793 100755\n--- a/t/t7508-status.sh\n+++ b/t/t7508-status.sh\n@@ -92,7 +92,10 @@ test_expect_success 'status --column' '\n # On branch main\n # Your branch and '\\''upstream'\\'' have diverged,\n # and have 1 and 2 different commits each, respectively.\n-#   (use \"git pull\" to merge the remote branch into yours)\n+#   (To reconcile your local changes with the work at the remote, you can\n+#   use '\\''git pull'\\'' and then '\\''git push'\\''. To discard the work at the remote\n+#   and replace it with what you did (alone), you can use\n+#   '\\''git push --force'\\''.)\n #\n # Changes to be committed:\n #   (use \"git restore --staged <file>...\" to unstage)\n@@ -123,7 +126,10 @@ cat >expect <<\\EOF\n # On branch main\n # Your branch and 'upstream' have diverged,\n # and have 1 and 2 different commits each, respectively.\n-#   (use \"git pull\" to merge the remote branch into yours)\n+#   (To reconcile your local changes with the work at the remote, you can\n+#   use 'git pull' and then 'git push'. To discard the work at the remote\n+#   and replace it with what you did (alone), you can use\n+#   'git push --force'.)\n #\n # Changes to be committed:\n #   (use \"git restore --staged <file>...\" to unstage)\n@@ -270,7 +276,10 @@ test_expect_success 'status with gitignore' '\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 1 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (To reconcile your local changes with the work at the remote, you can\n+  use '\\''git pull'\\'' and then '\\''git push'\\''. To discard the work at the remote\n+  and replace it with what you did (alone), you can use\n+  '\\''git push --force'\\''.)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -335,7 +344,10 @@ test_expect_success 'status with gitignore (nothing untracked)' '\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 1 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (To reconcile your local changes with the work at the remote, you can\n+  use '\\''git pull'\\'' and then '\\''git push'\\''. To discard the work at the remote\n+  and replace it with what you did (alone), you can use\n+  '\\''git push --force'\\''.)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -405,7 +417,10 @@ test_expect_success 'status -uno' '\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 1 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (To reconcile your local changes with the work at the remote, you can\n+  use '\\''git pull'\\'' and then '\\''git push'\\''. To discard the work at the remote\n+  and replace it with what you did (alone), you can use\n+  '\\''git push --force'\\''.)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -467,7 +482,10 @@ test_expect_success 'status -unormal' '\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 1 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (To reconcile your local changes with the work at the remote, you can\n+  use '\\''git pull'\\'' and then '\\''git push'\\''. To discard the work at the remote\n+  and replace it with what you did (alone), you can use\n+  '\\''git push --force'\\''.)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -522,7 +540,10 @@ test_expect_success 'status -uall' '\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 1 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (To reconcile your local changes with the work at the remote, you can\n+  use '\\''git pull'\\'' and then '\\''git push'\\''. To discard the work at the remote\n+  and replace it with what you did (alone), you can use\n+  '\\''git push --force'\\''.)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -582,7 +603,10 @@ test_expect_success 'status with relative paths' '\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 1 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (To reconcile your local changes with the work at the remote, you can\n+  use '\\''git pull'\\'' and then '\\''git push'\\''. To discard the work at the remote\n+  and replace it with what you did (alone), you can use\n+  '\\''git push --force'\\''.)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -650,7 +674,10 @@ test_expect_success TTY 'status with color.ui' '\n On branch <GREEN>main<RESET>\n Your branch and '\\''upstream'\\'' have diverged,\n and have 1 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (To reconcile your local changes with the work at the remote, you can\n+  use '\\''git pull'\\'' and then '\\''git push'\\''. To discard the work at the remote\n+  and replace it with what you did (alone), you can use\n+  '\\''git push --force'\\''.)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -773,7 +800,10 @@ test_expect_success 'status without relative paths' '\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 1 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (To reconcile your local changes with the work at the remote, you can\n+  use '\\''git pull'\\'' and then '\\''git push'\\''. To discard the work at the remote\n+  and replace it with what you did (alone), you can use\n+  '\\''git push --force'\\''.)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -847,7 +877,10 @@ test_expect_success 'dry-run of partial commit excluding new file in index' '\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 1 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (To reconcile your local changes with the work at the remote, you can\n+  use '\\''git pull'\\'' and then '\\''git push'\\''. To discard the work at the remote\n+  and replace it with what you did (alone), you can use\n+  '\\''git push --force'\\''.)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -901,7 +934,10 @@ test_expect_success 'status submodule summary is disabled by default' '\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 1 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (To reconcile your local changes with the work at the remote, you can\n+  use '\\''git pull'\\'' and then '\\''git push'\\''. To discard the work at the remote\n+  and replace it with what you did (alone), you can use\n+  '\\''git push --force'\\''.)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -958,7 +994,10 @@ test_expect_success 'status submodule summary' '\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 1 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (To reconcile your local changes with the work at the remote, you can\n+  use '\\''git pull'\\'' and then '\\''git push'\\''. To discard the work at the remote\n+  and replace it with what you did (alone), you can use\n+  '\\''git push --force'\\''.)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -1017,7 +1056,10 @@ test_expect_success 'status submodule summary (clean submodule): commit' '\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 2 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (To reconcile your local changes with the work at the remote, you can\n+  use '\\''git pull'\\'' and then '\\''git push'\\''. To discard the work at the remote\n+  and replace it with what you did (alone), you can use\n+  '\\''git push --force'\\''.)\n \n Changes not staged for commit:\n   (use \"git add <file>...\" to update what will be committed)\n@@ -1065,7 +1107,10 @@ test_expect_success 'commit --dry-run submodule summary (--amend)' '\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 2 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (To reconcile your local changes with the work at the remote, you can\n+  use '\\''git pull'\\'' and then '\\''git push'\\''. To discard the work at the remote\n+  and replace it with what you did (alone), you can use\n+  '\\''git push --force'\\''.)\n \n Changes to be committed:\n   (use \"git restore --source=HEAD^1 --staged <file>...\" to unstage)\n@@ -1117,7 +1162,10 @@ test_expect_success '--ignore-submodules=untracked suppresses submodules with un\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 2 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (To reconcile your local changes with the work at the remote, you can\n+  use '\\''git pull'\\'' and then '\\''git push'\\''. To discard the work at the remote\n+  and replace it with what you did (alone), you can use\n+  '\\''git push --force'\\''.)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -1226,7 +1274,10 @@ test_expect_success \"--ignore-submodules=untracked doesn't suppress submodules w\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 2 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (To reconcile your local changes with the work at the remote, you can\n+  use '\\''git pull'\\'' and then '\\''git push'\\''. To discard the work at the remote\n+  and replace it with what you did (alone), you can use\n+  '\\''git push --force'\\''.)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -1283,7 +1334,10 @@ test_expect_success \"--ignore-submodules=untracked doesn't suppress submodule su\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 2 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (To reconcile your local changes with the work at the remote, you can\n+  use '\\''git pull'\\'' and then '\\''git push'\\''. To discard the work at the remote\n+  and replace it with what you did (alone), you can use\n+  '\\''git push --force'\\''.)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -1364,7 +1418,10 @@ cat > expect << EOF\n ; On branch main\n ; Your branch and 'upstream' have diverged,\n ; and have 2 and 2 different commits each, respectively.\n-;   (use \"git pull\" to merge the remote branch into yours)\n+;   (To reconcile your local changes with the work at the remote, you can\n+;   use 'git pull' and then 'git push'. To discard the work at the remote\n+;   and replace it with what you did (alone), you can use\n+;   'git push --force'.)\n ;\n ; Changes to be committed:\n ;   (use \"git restore --staged <file>...\" to unstage)\n@@ -1412,7 +1469,10 @@ test_expect_success \"--ignore-submodules=all suppresses submodule summary\" '\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 2 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (To reconcile your local changes with the work at the remote, you can\n+  use '\\''git pull'\\'' and then '\\''git push'\\''. To discard the work at the remote\n+  and replace it with what you did (alone), you can use\n+  '\\''git push --force'\\''.)\n \n Changes not staged for commit:\n   (use \"git add <file>...\" to update what will be committed)\n@@ -1438,7 +1498,10 @@ test_expect_success '.gitmodules ignore=all suppresses unstaged submodule summar\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 2 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (To reconcile your local changes with the work at the remote, you can\n+  use '\\''git pull'\\'' and then '\\''git push'\\''. To discard the work at the remote\n+  and replace it with what you did (alone), you can use\n+  '\\''git push --force'\\''.)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -1558,7 +1621,10 @@ test_expect_success 'git commit --dry-run will show a staged but ignored submodu\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 2 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (To reconcile your local changes with the work at the remote, you can\n+  use '\\''git pull'\\'' and then '\\''git push'\\''. To discard the work at the remote\n+  and replace it with what you did (alone), you can use\n+  '\\''git push --force'\\''.)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n-- \n2.41.0\n\n"},{"id":"479272","messageId":"20230707054257.3366355-3-alexhenrie24@gmail.com","threadId":"59944","inReplyTo":"20230707054257.3366355-1-alexhenrie24@gmail.com","subject":"[PATCH v4 2/2] push: advise about force-pushing as an alternative to reconciliation","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-07T05:42:48Z","receivedAt":"2023-07-07T05:43:33Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"Also, don't put `git pull` in an awkward parenthetical, because\n`git pull` can always be used to reconcile branches and is the normal\nway to do so.\n\nSigned-off-by: Alex Henrie <alexhenrie24@gmail.com>\n---\n builtin/push.c | 27 +++++++++++++++------------\n 1 file changed, 15 insertions(+), 12 deletions(-)\n\ndiff --git a/builtin/push.c b/builtin/push.c\nindex 6f8a8dc711..b2f0a64e7c 100644\n--- a/builtin/push.c\n+++ b/builtin/push.c\n@@ -301,21 +301,24 @@ static void setup_default_push_refspecs(int *flags, struct remote *remote)\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. Integrate the remote changes (e.g.\\n\"\n-\t   \"'git pull ...') before pushing again.\\n\"\n+\t   \"its remote counterpart. Use 'git pull' to integrate the remote changes\\n\"\n+\t   \"before pushing again, or use 'git push --force' to delete the remote\\n\"\n+\t   \"changes and replace them with your own.\\n\"\n \t   \"See the 'Note about fast-forwards' in 'git push --help' for details.\");\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 integrate the remote changes\\n\"\n-\t   \"(e.g. 'git pull ...') before pushing again.\\n\"\n+\t   \"counterpart. Check out this branch and use 'git pull' to integrate the\\n\"\n+\t   \"remote changes before pushing again, or use 'git push --force' to delete\\n\"\n+\t   \"the remote changes and replace them with your own.\\n\"\n \t   \"See the 'Note about fast-forwards' in 'git push --help' for details.\");\n \n static const char message_advice_ref_fetch_first[] =\n-\tN_(\"Updates were rejected because the remote contains work that you do\\n\"\n-\t   \"not have locally. This is usually caused by another repository pushing\\n\"\n-\t   \"to the same ref. You may want to first integrate the remote changes\\n\"\n-\t   \"(e.g., 'git pull ...') before pushing again.\\n\"\n+\tN_(\"Updates were rejected because the remote contains work that you do not\\n\"\n+\t   \"have locally. This is usually caused by another repository pushing to\\n\"\n+\t   \"the same ref. Use 'git pull' to integrate the remote changes before\\n\"\n+\t   \"pushing again, or use 'git push --force' to delete the remote changes\\n\"\n+\t   \"and replace them with your own.\\n\"\n \t   \"See the 'Note about fast-forwards' in 'git push --help' for details.\");\n \n static const char message_advice_ref_already_exists[] =\n@@ -327,10 +330,10 @@ static const char message_advice_ref_needs_force[] =\n \t   \"without using the '--force' option.\\n\");\n \n static const char message_advice_ref_needs_update[] =\n-\tN_(\"Updates were rejected because the tip of the remote-tracking\\n\"\n-\t   \"branch has been updated since the last checkout. You may want\\n\"\n-\t   \"to integrate those changes locally (e.g., 'git pull ...')\\n\"\n-\t   \"before forcing an update.\\n\");\n+\tN_(\"Updates were rejected because the tip of the remote-tracking branch has\\n\"\n+\t   \"been updated since the last checkout. Use 'git pull' to integrate the\\n\"\n+\t   \"remote changes before pushing again, or use 'git push --force' to delete\\n\"\n+\t   \"the remote changes and replace them with your own.\\n\");\n \n static void advise_pull_before_push(void)\n {\n-- \n2.41.0\n\n"},{"id":"479274","messageId":"0a001080-4d1a-75b6-1b76-ed132f126bf4@gmail.com","threadId":"59944","inReplyTo":"20230706040111.81110-2-alexhenrie24@gmail.com","subject":"Re: [PATCH v3 1/2] remote: advise about force-pushing as an alternative to reconciliation","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2023-07-07T08:48:33Z","receivedAt":"2023-07-07T08:48:45Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Alex\n\nOn 06/07/2023 05:01, Alex Henrie wrote:\n> Also, don't imply that `git pull` is only for merging.\n\nWhile the cover letter gives some background for the reason behind this \nchange the commit message does not explain why the proposed changes are \ndesirable.\n\n> @@ -2323,7 +2323,10 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb,\n>   \t\t\tbase, ours, theirs);\n>   \t\tif (advice_enabled(ADVICE_STATUS_HINTS))\n>   \t\t\tstrbuf_addstr(sb,\n> -\t\t\t\t_(\"  (use \\\"git pull\\\" to merge the remote branch into yours)\\n\"));\n> +\t\t\t\t_(\"  (To reconcile your local changes with the work at the remote, you can\\n\"\n\nThis is a welcome improvement but I think it would be better to say \n\"integrate\" rather than \"reconcile\" to keep the wording aligned with the \nadvice is builtin/push.c.\n\n> +\t\t\t\t  \"  use 'git pull' and then 'git push'. To discard the work at the remote\\n\"\n> +\t\t\t\t  \"  and replace it with what you did (alone), you can use\\n\"\n> +\t\t\t\t  \"  'git push --force'.)\\n\"));\n\nI share Junio's concerns about giving this advice after \"git status\" or \n\"git checkout\" especially as we don't know if our remote tracking ref \naccurately reflects the current state of the remote branch.\n\nBest Wishes\n\nPhillip\n\n>   \t}\n>   \tfree(base);\n>   \treturn 1;\n"},{"id":"479275","messageId":"82255166-49ac-3c10-1744-27d6d436822e@gmail.com","threadId":"59944","inReplyTo":"20230706040111.81110-3-alexhenrie24@gmail.com","subject":"Re: [PATCH v3 2/2] push: advise about force-pushing as an alternative to reconciliation","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2023-07-07T08:49:22Z","receivedAt":"2023-07-07T08:49:29Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Alex\n\nOn 06/07/2023 05:01, Alex Henrie wrote:\n> Also, don't put `git pull` in an awkward parenthetical, because\n> `git pull` can always be used to reconcile branches and is the normal\n> way to do so.\n\nThis message would also benefit from adding explanation as to why this \nchange is desirable.\n\n> Signed-off-by: Alex Henrie <alexhenrie24@gmail.com>\n> ---\n>   builtin/push.c | 27 +++++++++++++++------------\n>   1 file changed, 15 insertions(+), 12 deletions(-)\n> \n> diff --git a/builtin/push.c b/builtin/push.c\n> index 6f8a8dc711..b2f0a64e7c 100644\n> --- a/builtin/push.c\n> +++ b/builtin/push.c\n> @@ -301,21 +301,24 @@ static void setup_default_push_refspecs(int *flags, struct remote *remote)\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. Integrate the remote changes (e.g.\\n\"\n> -\t   \"'git pull ...') before pushing again.\\n\"\n> +\t   \"its remote counterpart. Use 'git pull' to integrate the remote changes\\n\"\n\nThis is much clearer than \"(e.g. 'git pull ...')\"\n\n> +\t   \"before pushing again, or use 'git push --force' to delete the remote\\n\"\n> +\t   \"changes and replace them with your own.\\n\"\n\nI think it would be good to give a bit more context here as to when \nforce pushing is a good idea. For example something like\n\n     If you have rebased the branch since you last integrated remote\n     changes then you can use\n     'git push --force-with-lease=<branch-ref> --force-if-includes' to\n     safely replace the remote branch.\n\n     If you have deleted and then recreated the branch since you last\n     integrated remote changes then you can use 'git push +<branch>' to\n     replace the remote. Note that if anyone else has pushed work to\n     this branch it will be deleted.\n\nIt makes the advice longer  but the user get a specific suggestion for \ntheir current situation rather than a generic suggestion to delete the \nremote changes without discussing the implications. In this case we know \nthat it was the current branch that was rejected and so should fill in \nthe branch name in the advice as well.\n\nMy main issue with the changes in this series is that they seem to \nassume the user is (a) pushing a single branch and (b) they are the only \nperson who works on that branch. That is a common but narrow case where \nforce pushing is perfectly sensible but there are many other scenarios \nwhere suggesting \"push --force\" would not be a good idea.\n\nBest Wishes\n\nPhillip\n\n>   \t   \"See the 'Note about fast-forwards' in 'git push --help' for details.\");\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 integrate the remote changes\\n\"\n> -\t   \"(e.g. 'git pull ...') before pushing again.\\n\"\n> +\t   \"counterpart. Check out this branch and use 'git pull' to integrate the\\n\"\n> +\t   \"remote changes before pushing again, or use 'git push --force' to delete\\n\"\n> +\t   \"the remote changes and replace them with your own.\\n\"\n>   \t   \"See the 'Note about fast-forwards' in 'git push --help' for details.\");\n>   \n>   static const char message_advice_ref_fetch_first[] =\n> -\tN_(\"Updates were rejected because the remote contains work that you do\\n\"\n> -\t   \"not have locally. This is usually caused by another repository pushing\\n\"\n> -\t   \"to the same ref. You may want to first integrate the remote changes\\n\"\n> -\t   \"(e.g., 'git pull ...') before pushing again.\\n\"\n> +\tN_(\"Updates were rejected because the remote contains work that you do not\\n\"\n> +\t   \"have locally. This is usually caused by another repository pushing to\\n\"\n> +\t   \"the same ref. Use 'git pull' to integrate the remote changes before\\n\"\n> +\t   \"pushing again, or use 'git push --force' to delete the remote changes\\n\"\n> +\t   \"and replace them with your own.\\n\"\n>   \t   \"See the 'Note about fast-forwards' in 'git push --help' for details.\");\n>   \n>   static const char message_advice_ref_already_exists[] =\n> @@ -327,10 +330,10 @@ static const char message_advice_ref_needs_force[] =\n>   \t   \"without using the '--force' option.\\n\");\n>   \n>   static const char message_advice_ref_needs_update[] =\n> -\tN_(\"Updates were rejected because the tip of the remote-tracking\\n\"\n> -\t   \"branch has been updated since the last checkout. You may want\\n\"\n> -\t   \"to integrate those changes locally (e.g., 'git pull ...')\\n\"\n> -\t   \"before forcing an update.\\n\");\n> +\tN_(\"Updates were rejected because the tip of the remote-tracking branch has\\n\"\n> +\t   \"been updated since the last checkout. Use 'git pull' to integrate the\\n\"\n> +\t   \"remote changes before pushing again, or use 'git push --force' to delete\\n\"\n> +\t   \"the remote changes and replace them with your own.\\n\");\n>   \n>   static void advise_pull_before_push(void)\n>   {\n"},{"id":"479285","messageId":"xmqqttufaam0.fsf@gitster.g","threadId":"59944","inReplyTo":"CAMMLpeS9_P=XXMoOdTAM3jZbaxfLEJNwYArS6p9pMXisT3TRtw@mail.gmail.com","subject":"Re: [PATCH v3 1/2] remote: advise about force-pushing as an alternative to reconciliation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-07-07T17:35:03Z","receivedAt":"2023-07-07T17:35:21Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Alex Henrie <alexhenrie24@gmail.com> writes:\n\n>> When you start working on your own topic forked from upstream by\n>> switching to it, if Git notices that your topic's base has become\n>> behind (so that you would later need to merge or rebase to avoid\n>> losing others' work), the \"git pull\" message is given to tell you\n>> that it is OK if you want to catch up first before working on it.\n>>\n>> But the new message does not fit well in the workflow.  It is\n>> primarily targetted for the users who are about to push out.  They\n>> are at the point where they are way before being ready to \"discard\n>> the work at the remote\".\n>\n> If the branch is merely behind, format_tracking_info prints \"(use \"git\n> pull\" to update your local branch)\", which is perfectly reasonable.\n\nCorrect.  The message you are changing is not the \"your topic has\nbecome behind\" case, and it is exactly why I said \"your topic's base\nhas become behind\", i.e. your upstream has diverged.\n\n> The problem is only with the message that appears when the branches\n> are divergent, \"(use \"git pull\" to merge the remote branch into\n> yours)\", which is bad advice for the common GitHub/GitLab workflow\n> that expects force-pushing.\n\nWe are in agreement in that \"you must always reconcile\" is not a\ngood message in general to give, but I do not think \"git checkout\"\nand \"git status\" are good places to give the new advice \"depending\non your workflow, you do not necessarily have to pay attention to\nwhat the upstream has and just overwrite it may be good\".  That is\nabout how to \"push\", but the user is a few steps before they are\nready to start thinking about how to \"push\" when they get this\nmessage.\n\nThese places in \"checkout\" and \"status\", where the message is given,\nwere perfectly good places to say \"by the way, you are divergent and\neven long before you are ready to push your work out, you may want\nto refresh your work to work better with the updated upstream\",\nwhich was the \"use git pull to reconcile\" message was all about.\n\n"},{"id":"479286","messageId":"xmqq8rbra9ti.fsf@gitster.g","threadId":"59944","inReplyTo":"CAMMLpeS9_P=XXMoOdTAM3jZbaxfLEJNwYArS6p9pMXisT3TRtw@mail.gmail.com","subject":"Re: [PATCH v3 1/2] remote: advise about force-pushing as an alternative to reconciliation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-07-07T17:52:09Z","receivedAt":"2023-07-07T17:52:15Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Alex Henrie <alexhenrie24@gmail.com> writes:\n\n> So, let's please give the user all of the\n> information (two ways forward: reconcile or delete) and encourage them\n> to make the most appropriate decision for their particular workflow.\n\nIt may be OK to do so in \"git status\".\n\nIt does not make any sense in \"git checkout\" to talk about \"you can\nforce push\".  That happens AFTER the work is done, and a message\nthat tells them BEFORE they start the work and asking them to\nremember doing the right thing is an unnecessary noise.\n\nI would rather see us toning the message down, e.g. \"Your branches\nhave diverged. **IF** you intend to eventually reconcile the work on\nthe remote with yours, you could use `git pull` to do so now\" is all\nwe should say.  If they do not want to keep the work on the remote,\nat the point of seeing \"you have diverged\", there is nothing they\nneed to do.  There is no need to talk about \"push --force\" and force\nthe user to remember that they have to do so later.  When they try\n\"git push\", an appropriate message should be given anyway, but that\nis not the message you are touching in this patch.\n\nFor that matter, it does not make ANY sense to give \"you can pull to\nreconcile\" message in the comment you are editing the log message\nwhile running \"git commit\".  It would be the most inconvenient time\nto do so.  So it might be necessary to first tweak the code so that\ndifferent messages depending on the codepath are shown, perhaps by\nteaching format_tracking_info() who is calling.\n\nThanks.\n"},{"id":"479288","messageId":"xmqqy1jr8sul.fsf@gitster.g","threadId":"59944","inReplyTo":"82255166-49ac-3c10-1744-27d6d436822e@gmail.com","subject":"Re: [PATCH v3 2/2] push: advise about force-pushing as an alternative to reconciliation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-07-07T18:44:02Z","receivedAt":"2023-07-07T18:44:12Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n> Hi Alex\n>\n> On 06/07/2023 05:01, Alex Henrie wrote:\n>> Also, don't put `git pull` in an awkward parenthetical, because\n>> `git pull` can always be used to reconcile branches and is the normal\n>> way to do so.\n>\n> This message would also benefit from adding explanation as to why this\n> change is desirable.\n\nYes, at least some essence from the lengthy discussion we had in the\nreview threads for the expected use cases deserve to be summarized\nto help future developers who run \"git log\" (and \"git blame\") to\nfind this commit.\n\nUnlike the [1/2] step, where the commands like \"status\" and\n\"checkout\" that are detached far away from the actual \"push\" are\naffected, this is exactly about \"push has failed, now what\"\nsituation, where a change from \"you must reconcile\" to \"if you want\nto reconcile, you could do this, but it may be that discarding the\nwork on the other side is the right thing, if that is just a stale\ncopy of what you are pushing\" is very much welcome.\n\n> It makes the advice longer  but the user get a specific suggestion for\n> their current situation rather than a generic suggestion to delete the\n> remote changes without discussing the implications. In this case we\n> know that it was the current branch that was rejected and so should\n> fill in the branch name in the advice as well.\n>\n> My main issue with the changes in this series is that they seem to\n> assume the user is (a) pushing a single branch and (b) they are the\n> only person who works on that branch. That is a common but narrow case\n> where force pushing is perfectly sensible but there are many other\n> scenarios where suggesting \"push --force\" would not be a good idea.\n\nYup.  Thanks for a review.\n"},{"id":"479332","messageId":"CAMMLpeQ2P+qQxo17dEdWhMHcmAfTiBoEifp2wUjWVrP+oGSzxQ@mail.gmail.com","threadId":"59944","inReplyTo":"xmqq8rbra9ti.fsf@gitster.g","subject":"Re: [PATCH v3 1/2] remote: advise about force-pushing as an alternative to reconciliation","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-08T18:55:40Z","receivedAt":"2023-07-08T18:56:23Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"On Fri, Jul 7, 2023 at 11:52 AM Junio C Hamano <gitster@pobox.com> wrote:\n\n> I would rather see us toning the message down, e.g. \"Your branches\n> have diverged. **IF** you intend to eventually reconcile the work on\n> the remote with yours, you could use `git pull` to do so now\" is all\n> we should say.  If they do not want to keep the work on the remote,\n> at the point of seeing \"you have diverged\", there is nothing they\n> need to do.  There is no need to talk about \"push --force\" and force\n> the user to remember that they have to do so later.  When they try\n> \"git push\", an appropriate message should be given anyway, but that\n> is not the message you are touching in this patch.\n\nI would be satisfied with toning down this message as you suggest;\nyou're right that we don't necessarily have to mention force-pushing\nhere. To keep the message short, we could just replace \"(use \"git\npull\" to merge the remote branch into yours)\" with \"(use \"git pull\" if\nyou want to integrate the remote branch into yours)\".\n\n> For that matter, it does not make ANY sense to give \"you can pull to\n> reconcile\" message in the comment you are editing the log message\n> while running \"git commit\".  It would be the most inconvenient time\n> to do so.  So it might be necessary to first tweak the code so that\n> different messages depending on the codepath are shown, perhaps by\n> teaching format_tracking_info() who is calling.\n\nI agree, showing this message in the middle of `git commit` is not\nideal. However, that's a separate issue that can be fixed later; it's\nnot part of the problem I'm trying to solve in this series.\n\nThanks for the feedback,\n\n-Alex\n"},{"id":"479333","messageId":"CAMMLpeSk7_2xn_atUoVeyFSHwE3TNDijSwDMo6PVbvf4XFUvtw@mail.gmail.com","threadId":"59944","inReplyTo":"82255166-49ac-3c10-1744-27d6d436822e@gmail.com","subject":"Re: [PATCH v3 2/2] push: advise about force-pushing as an alternative to reconciliation","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-08T18:56:43Z","receivedAt":"2023-07-08T18:57:23Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"On Fri, Jul 7, 2023 at 2:49 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n\n> This message would also benefit from adding explanation as to why this\n> change is desirable.\n\nOK, in v5 I'll add more explanation to the commit messages, including\npoints brought up in this discussion.\n\n> >   static const char message_advice_pull_before_push[] =\n> >       N_(\"Updates were rejected because the tip of your current branch is behind\\n\"\n> > -        \"its remote counterpart. Integrate the remote changes (e.g.\\n\"\n> > -        \"'git pull ...') before pushing again.\\n\"\n> > +        \"its remote counterpart. Use 'git pull' to integrate the remote changes\\n\"\n>\n> This is much clearer than \"(e.g. 'git pull ...')\"\n>\n> > +        \"before pushing again, or use 'git push --force' to delete the remote\\n\"\n> > +        \"changes and replace them with your own.\\n\"\n>\n> I think it would be good to give a bit more context here as to when\n> force pushing is a good idea. For example something like\n>\n>      If you have rebased the branch since you last integrated remote\n>      changes then you can use\n>      'git push --force-with-lease=<branch-ref> --force-if-includes' to\n>      safely replace the remote branch.\n>\n>      If you have deleted and then recreated the branch since you last\n>      integrated remote changes then you can use 'git push +<branch>' to\n>      replace the remote. Note that if anyone else has pushed work to\n>      this branch it will be deleted.\n>\n> It makes the advice longer  but the user get a specific suggestion for\n> their current situation rather than a generic suggestion to delete the\n> remote changes without discussing the implications. In this case we know\n> that it was the current branch that was rejected and so should fill in\n> the branch name in the advice as well.\n\nEven if we could fill in <branch-ref> automatically, it's too much to\nask the user to type out --force-with-lease=<branch-ref>\n--force-if-includes. Mentioning `git push --force` with a fat warning\nabout how it only makes sense in a narrow (but common) case would be\nenough to make users aware of it while deterring them from abusing it.\nThe advice already refers the user to the man page for more\ninformation, which includes a discussion of --force-with-lease and\n--force-if-includes as alternatives to plain --force.\n\n> My main issue with the changes in this series is that they seem to\n> assume the user is (a) pushing a single branch and (b) they are the only\n> person who works on that branch. That is a common but narrow case where\n> force pushing is perfectly sensible but there are many other scenarios\n> where suggesting \"push --force\" would not be a good idea.\n\nThe goal of the series is not to assume that the user's situation is\nthat narrow but common case, but rather to not assume that the user's\nsituation is not that case. The most important thing is to make the\nuser aware that integration/reconciliation is not the only possible\nway forward.\n\nThanks for the feedback,\n\n-Alex\n"},{"id":"479336","messageId":"xmqqbkgl6f04.fsf@gitster.g","threadId":"59944","inReplyTo":"CAMMLpeQ2P+qQxo17dEdWhMHcmAfTiBoEifp2wUjWVrP+oGSzxQ@mail.gmail.com","subject":"Re: [PATCH v3 1/2] remote: advise about force-pushing as an alternative to reconciliation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-07-09T01:38:19Z","receivedAt":"2023-07-09T01:40:24Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Alex Henrie <alexhenrie24@gmail.com> writes:\n\n> I agree, showing this message in the middle of `git commit` is not\n> ideal. However, that's a separate issue that can be fixed later; it's\n> not part of the problem I'm trying to solve in this series.\n\nThat is debatable.  Even \"by the way you can pull and reconcile\nearly before you have fully finished working on the topic and are\nready to push back\" is irrelevant during `git commit`.  \"Reconciling\nthe differences is not the only way to deal with divergence; you may\ndecide to simply discard what they have with push --force\" is even\nless relevant at that time.  So it seems to be very much an integral\npart of the problem you are tackling, at least to me.\n"},{"id":"479341","messageId":"CAMMLpeSwadTcd+z0-J1t=vUgz0wFiVaE5KaT-Wy1cckT3=fFGQ@mail.gmail.com","threadId":"59944","inReplyTo":"xmqqbkgl6f04.fsf@gitster.g","subject":"Re: [PATCH v3 1/2] remote: advise about force-pushing as an alternative to reconciliation","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-10T04:44:21Z","receivedAt":"2023-07-10T04:45:02Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"On Sat, Jul 8, 2023 at 7:38 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Alex Henrie <alexhenrie24@gmail.com> writes:\n>\n> > I agree, showing this message in the middle of `git commit` is not\n> > ideal. However, that's a separate issue that can be fixed later; it's\n> > not part of the problem I'm trying to solve in this series.\n>\n> That is debatable.  Even \"by the way you can pull and reconcile\n> early before you have fully finished working on the topic and are\n> ready to push back\" is irrelevant during `git commit`.  \"Reconciling\n> the differences is not the only way to deal with divergence; you may\n> decide to simply discard what they have with push --force\" is even\n> less relevant at that time.  So it seems to be very much an integral\n> part of the problem you are tackling, at least to me.\n\nI thought we just agreed that we don't need to mention force-pushing\nin this particular message? I guess you're saying that we'd still be\nover-encouraging `git pull` if we don't remove this message from `git\ncommit` altogether?\n\n-Alex\n"},{"id":"479370","messageId":"xmqqsf9v2roa.fsf@gitster.g","threadId":"59944","inReplyTo":"CAMMLpeSwadTcd+z0-J1t=vUgz0wFiVaE5KaT-Wy1cckT3=fFGQ@mail.gmail.com","subject":"Re: [PATCH v3 1/2] remote: advise about force-pushing as an alternative to reconciliation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-07-11T00:55:01Z","receivedAt":"2023-07-11T00:55:09Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Alex Henrie <alexhenrie24@gmail.com> writes:\n\n> On Sat, Jul 8, 2023 at 7:38 PM Junio C Hamano <gitster@pobox.com> wrote:\n>>\n>> Alex Henrie <alexhenrie24@gmail.com> writes:\n>>\n>> > I agree, showing this message in the middle of `git commit` is not\n>> > ideal. However, that's a separate issue that can be fixed later; it's\n>> > not part of the problem I'm trying to solve in this series.\n>>\n>> That is debatable.  Even \"by the way you can pull and reconcile\n>> early before you have fully finished working on the topic and are\n>> ready to push back\" is irrelevant during `git commit`.  \"Reconciling\n>> the differences is not the only way to deal with divergence; you may\n>> decide to simply discard what they have with push --force\" is even\n>> less relevant at that time.  So it seems to be very much an integral\n>> part of the problem you are tackling, at least to me.\n>\n> I thought we just agreed that we don't need to mention force-pushing\n> in this particular message? I guess you're saying that we'd still be\n> over-encouraging `git pull` if we don't remove this message from `git\n> commit` altogether?\n\nI do not think so.\n\nI was saying that, when the user during `git commit` is wondering\nwhat to write in the log message of the commit they are working on\n(which may not yet make the current branch ready to be pushed to or\nintegrated with the remote), the user is not ready to even choose\nbetween \"forcing push to overwrite\" and \"integrate and then push\".\n\nIt can be fixed later, but it is a part of \"how to avoid giving\nconfusing message to users, especially the new ones\" theme.  After\nall, \"do not make it sound like they always have to integrate\" is\nhow you started this journey, no?\n\nThanks.\n\n"},{"id":"479390","messageId":"3479e947-76ce-2eb6-8ae0-5360311c5967@gmail.com","threadId":"59944","inReplyTo":"CAMMLpeSk7_2xn_atUoVeyFSHwE3TNDijSwDMo6PVbvf4XFUvtw@mail.gmail.com","subject":"Re: [PATCH v3 2/2] push: advise about force-pushing as an alternative to reconciliation","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2023-07-11T18:33:25Z","receivedAt":"2023-07-11T18:33:33Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Alex\n\nOn 08/07/2023 19:56, Alex Henrie wrote:\n> On Fri, Jul 7, 2023 at 2:49 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n>>> +        \"before pushing again, or use 'git push --force' to delete the remote\\n\"\n>>> +        \"changes and replace them with your own.\\n\"\n>>\n>> I think it would be good to give a bit more context here as to when\n>> force pushing is a good idea. For example something like\n>>\n>>       If you have rebased the branch since you last integrated remote\n>>       changes then you can use\n>>       'git push --force-with-lease=<branch-ref> --force-if-includes' to\n>>       safely replace the remote branch.\n>>\n>>       If you have deleted and then recreated the branch since you last\n>>       integrated remote changes then you can use 'git push +<branch>' to\n>>       replace the remote. Note that if anyone else has pushed work to\n>>       this branch it will be deleted.\n>>\n>> It makes the advice longer  but the user get a specific suggestion for\n>> their current situation rather than a generic suggestion to delete the\n>> remote changes without discussing the implications. In this case we know\n>> that it was the current branch that was rejected and so should fill in\n>> the branch name in the advice as well.\n> \n> Even if we could fill in <branch-ref> automatically, it's too much to\n> ask the user to type out --force-with-lease=<branch-ref>\n> --force-if-includes.\n\nCan't they just copy and paste the command from the advice message? Even \nif the user does not copy and paste it is not that hard to type it out \nwith the benefit of the shell's tab completion. You're basically saying \nthis combination of options is unusable in practice because it is too \nmuch effort to type them. We could look to see if we can make it less \nunwieldy by changing push to allow --force-if-includes=ref imply \n--force-with-lease for instance.\n\n> Mentioning `git push --force` with a fat warning\n> about how it only makes sense in a narrow (but common) case would be\n> enough to make users aware of it while deterring them from abusing it.\n\nHaving a warning in the advice message would definitely help\n\n> The advice already refers the user to the man page for more\n> information, which includes a discussion of --force-with-lease and\n> --force-if-includes as alternatives to plain --force.\n\nIt is good to mention the man page in the advice but we shouldn't assume \nthat users will actually go and read it before running the suggested \ncommand.\n\n>> My main issue with the changes in this series is that they seem to\n>> assume the user is (a) pushing a single branch and (b) they are the only\n>> person who works on that branch. That is a common but narrow case where\n>> force pushing is perfectly sensible but there are many other scenarios\n>> where suggesting \"push --force\" would not be a good idea.\n> \n> The goal of the series is not to assume that the user's situation is\n> that narrow but common case, but rather to not assume that the user's\n> situation is not that case. The most important thing is to make the\n> user aware that integration/reconciliation is not the only possible\n> way forward.\n\nThanks for clarifying, that is the sort of thing that should be in the \ncommit message.\n\nBest Wishes\n\nPhillip\n\n> Thanks for the feedback,\n> \n> -Alex\n"},{"id":"479401","messageId":"CAMMLpeTNMaVk7M2nLSJJzDMWPDVdyOr27Ae2-Usky5tW-dRqJQ@mail.gmail.com","threadId":"59944","inReplyTo":"xmqqsf9v2roa.fsf@gitster.g","subject":"Re: [PATCH v3 1/2] remote: advise about force-pushing as an alternative to reconciliation","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-12T04:47:00Z","receivedAt":"2023-07-12T04:47:43Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"On Mon, Jul 10, 2023 at 6:55 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Alex Henrie <alexhenrie24@gmail.com> writes:\n>\n> > On Sat, Jul 8, 2023 at 7:38 PM Junio C Hamano <gitster@pobox.com> wrote:\n> >>\n> >> Alex Henrie <alexhenrie24@gmail.com> writes:\n> >>\n> >> > I agree, showing this message in the middle of `git commit` is not\n> >> > ideal. However, that's a separate issue that can be fixed later; it's\n> >> > not part of the problem I'm trying to solve in this series.\n> >>\n> >> That is debatable.  Even \"by the way you can pull and reconcile\n> >> early before you have fully finished working on the topic and are\n> >> ready to push back\" is irrelevant during `git commit`.  \"Reconciling\n> >> the differences is not the only way to deal with divergence; you may\n> >> decide to simply discard what they have with push --force\" is even\n> >> less relevant at that time.  So it seems to be very much an integral\n> >> part of the problem you are tackling, at least to me.\n> >\n> > I thought we just agreed that we don't need to mention force-pushing\n> > in this particular message? I guess you're saying that we'd still be\n> > over-encouraging `git pull` if we don't remove this message from `git\n> > commit` altogether?\n>\n> I do not think so.\n>\n> I was saying that, when the user during `git commit` is wondering\n> what to write in the log message of the commit they are working on\n> (which may not yet make the current branch ready to be pushed to or\n> integrated with the remote), the user is not ready to even choose\n> between \"forcing push to overwrite\" and \"integrate and then push\".\n>\n> It can be fixed later, but it is a part of \"how to avoid giving\n> confusing message to users, especially the new ones\" theme.  After\n> all, \"do not make it sound like they always have to integrate\" is\n> how you started this journey, no?\n\nTo me, one of those things is bad advice, and the other is irrelevant\nadvice. They're both confusing, but one of them is more likely to\ncause trouble than the other.\n\nOmitting this message from `git commit` isn't technically difficult,\nmy main worry is that that change will be picked to death in code\nreview and it will hold up the more important changes. I have to find\ntime for Git outside of work and I'm already feeling pretty burned out\ntrying to communicate the problem and integrate the feedback on this\nseries so far. Even so, because it's important to you, and because I\nappreciate your willingness to work with me on this problem, I'm\nwilling to take a stab at fixing both the bad advice and the\nirrelevant advice in the same series.\n\nJust to be sure that we're on the same page, when I said \"I thought we\njust agreed that we don't need to mention force-pushing...\" and you\nreplied \"I do not think so\", were you only saying that you think that\nchanges to `git commit` are essential, or were you also saying that we\nhave not come to an agreement about whether to include force-pushing\nadvice in this message?\n\nThanks,\n\n-Alex\n"},{"id":"479402","messageId":"CAMMLpeQ5fqCQnxT9cPhYV0pwr+PB5WCVeum21YVUR153hnSFnQ@mail.gmail.com","threadId":"59944","inReplyTo":"3479e947-76ce-2eb6-8ae0-5360311c5967@gmail.com","subject":"Re: [PATCH v3 2/2] push: advise about force-pushing as an alternative to reconciliation","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-12T04:47:43Z","receivedAt":"2023-07-12T04:48:24Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"On Tue, Jul 11, 2023 at 12:33 PM Phillip Wood <phillip.wood123@gmail.com> wrote:\n\n> On 08/07/2023 19:56, Alex Henrie wrote:\n> > On Fri, Jul 7, 2023 at 2:49 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n> >>> +        \"before pushing again, or use 'git push --force' to delete the remote\\n\"\n> >>> +        \"changes and replace them with your own.\\n\"\n> >>\n> >> I think it would be good to give a bit more context here as to when\n> >> force pushing is a good idea. For example something like\n> >>\n> >>       If you have rebased the branch since you last integrated remote\n> >>       changes then you can use\n> >>       'git push --force-with-lease=<branch-ref> --force-if-includes' to\n> >>       safely replace the remote branch.\n> >>\n> >>       If you have deleted and then recreated the branch since you last\n> >>       integrated remote changes then you can use 'git push +<branch>' to\n> >>       replace the remote. Note that if anyone else has pushed work to\n> >>       this branch it will be deleted.\n> >>\n> >> It makes the advice longer  but the user get a specific suggestion for\n> >> their current situation rather than a generic suggestion to delete the\n> >> remote changes without discussing the implications. In this case we know\n> >> that it was the current branch that was rejected and so should fill in\n> >> the branch name in the advice as well.\n> >\n> > Even if we could fill in <branch-ref> automatically, it's too much to\n> > ask the user to type out --force-with-lease=<branch-ref>\n> > --force-if-includes.\n>\n> Can't they just copy and paste the command from the advice message? Even\n> if the user does not copy and paste it is not that hard to type it out\n> with the benefit of the shell's tab completion. You're basically saying\n> this combination of options is unusable in practice because it is too\n> much effort to type them. We could look to see if we can make it less\n> unwieldy by changing push to allow --force-if-includes=ref imply\n> --force-with-lease for instance.\n\nYes, `git push --force-with-lease=<branch-ref> --force-if-includes` is\ncryptic and unwieldy, and even asking users to copy and paste a\ncommand is a bit much. If that's what's presented as the alternative\nto integration via `git pull`, it could make users who want to\noverwrite the remote branch think that force-pushing isn't what they\nwant because what they want is conceptually very simple, so they\nexpect it to have a simple user interface.\n\nIt's possible that improvements will be made to this user interface in\nthe future, but that's definitely not something that I'm going to\ntackle. I just want Git to give decent advice about what is available\nright now. If we can't agree on what specific command to recommend,\nmaybe we can at least agree to tone down these messages to not sound\nso prescriptive. Just changing \"Use 'git pull' to integrate...\" to\n\"You can use 'git pull' to integrate...' would be a big improvement.\n\nThanks,\n\n-Alex\n"},{"id":"479403","messageId":"CAMMLpeQGjqsP0cFGw-RB7P2OozkpN6e-1H2=4C3VHWqpPuf8PA@mail.gmail.com","threadId":"59944","inReplyTo":"CAMMLpeQ5fqCQnxT9cPhYV0pwr+PB5WCVeum21YVUR153hnSFnQ@mail.gmail.com","subject":"Re: [PATCH v3 2/2] push: advise about force-pushing as an alternative to reconciliation","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-12T04:55:26Z","receivedAt":"2023-07-12T04:56:07Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"On Tue, Jul 11, 2023 at 10:47 PM Alex Henrie <alexhenrie24@gmail.com> wrote:\n>\n> On Tue, Jul 11, 2023 at 12:33 PM Phillip Wood <phillip.wood123@gmail.com> wrote:\n>\n> > On 08/07/2023 19:56, Alex Henrie wrote:\n> > > On Fri, Jul 7, 2023 at 2:49 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n> > >>> +        \"before pushing again, or use 'git push --force' to delete the remote\\n\"\n> > >>> +        \"changes and replace them with your own.\\n\"\n> > >>\n> > >> I think it would be good to give a bit more context here as to when\n> > >> force pushing is a good idea. For example something like\n> > >>\n> > >>       If you have rebased the branch since you last integrated remote\n> > >>       changes then you can use\n> > >>       'git push --force-with-lease=<branch-ref> --force-if-includes' to\n> > >>       safely replace the remote branch.\n> > >>\n> > >>       If you have deleted and then recreated the branch since you last\n> > >>       integrated remote changes then you can use 'git push +<branch>' to\n> > >>       replace the remote. Note that if anyone else has pushed work to\n> > >>       this branch it will be deleted.\n> > >>\n> > >> It makes the advice longer  but the user get a specific suggestion for\n> > >> their current situation rather than a generic suggestion to delete the\n> > >> remote changes without discussing the implications. In this case we know\n> > >> that it was the current branch that was rejected and so should fill in\n> > >> the branch name in the advice as well.\n> > >\n> > > Even if we could fill in <branch-ref> automatically, it's too much to\n> > > ask the user to type out --force-with-lease=<branch-ref>\n> > > --force-if-includes.\n> >\n> > Can't they just copy and paste the command from the advice message? Even\n> > if the user does not copy and paste it is not that hard to type it out\n> > with the benefit of the shell's tab completion. You're basically saying\n> > this combination of options is unusable in practice because it is too\n> > much effort to type them. We could look to see if we can make it less\n> > unwieldy by changing push to allow --force-if-includes=ref imply\n> > --force-with-lease for instance.\n>\n> Yes, `git push --force-with-lease=<branch-ref> --force-if-includes` is\n> cryptic and unwieldy, and even asking users to copy and paste a\n> command is a bit much. If that's what's presented as the alternative\n> to integration via `git pull`, it could make users who want to\n> overwrite the remote branch think that force-pushing isn't what they\n> want because what they want is conceptually very simple, so they\n> expect it to have a simple user interface.\n>\n> It's possible that improvements will be made to this user interface in\n> the future, but that's definitely not something that I'm going to\n> tackle. I just want Git to give decent advice about what is available\n> right now. If we can't agree on what specific command to recommend,\n> maybe we can at least agree to tone down these messages to not sound\n> so prescriptive. Just changing \"Use 'git pull' to integrate...\" to\n> \"You can use 'git pull' to integrate...' would be a big improvement.\n\nWhoops, I accidentally quoted my own proposed text as if it were the\ncurrent text. The current text is in fact \"Integrate the remote\nchanges...\" which is stronger still.\n\n-Alex\n"},{"id":"479408","messageId":"xmqqo7khupjh.fsf@gitster.g","threadId":"59944","inReplyTo":"CAMMLpeTNMaVk7M2nLSJJzDMWPDVdyOr27Ae2-Usky5tW-dRqJQ@mail.gmail.com","subject":"Re: [PATCH v3 1/2] remote: advise about force-pushing as an alternative to reconciliation","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-07-12T15:18:10Z","receivedAt":"2023-07-12T15:19:20Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Alex Henrie <alexhenrie24@gmail.com> writes:\n\n> Just to be sure that we're on the same page, when I said \"I thought we\n> just agreed that we don't need to mention force-pushing...\" and you\n> replied \"I do not think so\", were you only saying that you think that\n> changes to `git commit` are essential, or were you also saying that we\n> have not come to an agreement about whether to include force-pushing\n> advice in this message?\n\nNone of the above ;-)\n\nWith that \"I do not think so\", I meant that I do not agree with \"I\nguess you're saying that we'd still be over-encouraging `git pull`\"\nthat was in your message.  In the message you were responding to, I\nwas saying that the time the user runs `git commit` is not a good\ntime for the user to decide how to eventually update the remote\ntarget, and it does not matter which one we encourage more between\n\"`git pull [--rebase]` then `git push`\" and \"`git push --force`\".\n\nI am fine dropping patch [1/2]; we would not be touching output from\n\"git status\", \"git commit\", or \"git checkout\", and \"we should not\ntalk about 'git pull' (or how the eventual remote update should go,\nfor that matter) when we notice that the base of the user's branch\nhas become stale\" becomes totally out of the scope of this topic.  I\nthink that we all are in agreement that [2/2] is the more important\npart of this topic, as it more directly improves the guidance for\nthe end-users when their \"push\" triggers the non-ff check.\n\nThanks.\n"},{"id":"479449","messageId":"CAMMLpeR9yLA3zM0GfTMhuFa8HW5fDCRBN7Gnft6Mof59Tk7i0Q@mail.gmail.com","threadId":"59944","inReplyTo":"xmqqo7khupjh.fsf@gitster.g","subject":"Re: [PATCH v3 1/2] remote: advise about force-pushing as an alternative to reconciliation","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-13T04:09:42Z","receivedAt":"2023-07-13T04:10:52Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"On Wed, Jul 12, 2023 at 9:18 AM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Alex Henrie <alexhenrie24@gmail.com> writes:\n>\n> > Just to be sure that we're on the same page, when I said \"I thought we\n> > just agreed that we don't need to mention force-pushing...\" and you\n> > replied \"I do not think so\", were you only saying that you think that\n> > changes to `git commit` are essential, or were you also saying that we\n> > have not come to an agreement about whether to include force-pushing\n> > advice in this message?\n>\n> None of the above ;-)\n>\n> With that \"I do not think so\", I meant that I do not agree with \"I\n> guess you're saying that we'd still be over-encouraging `git pull`\"\n> that was in your message.  In the message you were responding to, I\n> was saying that the time the user runs `git commit` is not a good\n> time for the user to decide how to eventually update the remote\n> target, and it does not matter which one we encourage more between\n> \"`git pull [--rebase]` then `git push`\" and \"`git push --force`\".\n>\n> I am fine dropping patch [1/2]; we would not be touching output from\n> \"git status\", \"git commit\", or \"git checkout\", and \"we should not\n> talk about 'git pull' (or how the eventual remote update should go,\n> for that matter) when we notice that the base of the user's branch\n> has become stale\" becomes totally out of the scope of this topic.  I\n> think that we all are in agreement that [2/2] is the more important\n> part of this topic, as it more directly improves the guidance for\n> the end-users when their \"push\" triggers the non-ff check.\n\nThanks for the clarification. This all started because of the message\nin `git status`, so despite it being the less important message, I\nfeel pretty strongly that that message does need to be toned down\nslightly. There's also the problem of that message assuming that `git\npull` will do a merge when it can do either a merge or a rebase,\ndepending on the user's Git config.\n\nI've already written a patch to suppress the irrelevant advice in `git\ncommit`, so I might as well send it. I'm hoping that we can agree to\nmake a few tweaks to these advice messages without going as far as I\noriginally proposed.\n\n-Alex\n"},{"id":"479450","messageId":"20230713044128.3771818-1-alexhenrie24@gmail.com","threadId":"59944","inReplyTo":"20230707054257.3366355-1-alexhenrie24@gmail.com","subject":"[PATCH v5 0/3] don't imply that integration is always required before pushing","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-13T04:41:12Z","receivedAt":"2023-07-13T04:42:44Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"Many times now, I have seen novices do the following:\n\n1. Start work on their own personal topic branch\n2. Push the branch to origin\n3. Rebase the branch onto origin/master\n4. Try to push again, but Git says they need to pull\n5. Pull and make a mess trying to reconcile the older topic branch with\n   the rebased topic branch\n\nHelp avoid this mistake by giving somewhat more general advice that does\nnot assume that the user always wants to do reconciliation.\n\nChanges from v4:\n- Don't show divergent branch advice in the middle of `git commit`\n- Soften the advice, but don't specifically mention force-pushing\n\nAlex Henrie (3):\n  wt-status: don't show divergence advice when committing\n  remote: don't imply that integration is always required before pushing\n  push: don't imply that integration is always required before pushing\n\n builtin/checkout.c |  2 +-\n builtin/push.c     | 24 +++++++++++------------\n remote.c           |  8 +++++---\n remote.h           |  3 ++-\n t/t7508-status.sh  | 48 ++++++++++++++++++++++------------------------\n wt-status.c        |  3 ++-\n 6 files changed, 45 insertions(+), 43 deletions(-)\n\nRange-diff against v4:\n1:  9626721c13 < -:  ---------- remote: advise about force-pushing as an alternative to reconciliation\n-:  ---------- > 1:  e84989c4a6 wt-status: don't show divergence advice when committing\n-:  ---------- > 2:  9bb643df7e remote: don't imply that integration is always required before pushing\n2:  209e86588a ! 3:  5ff9ecb51b push: advise about force-pushing as an alternative to reconciliation\n    @@ Metadata\n     Author: Alex Henrie <alexhenrie24@gmail.com>\n     \n      ## Commit message ##\n    -    push: advise about force-pushing as an alternative to reconciliation\n    +    push: don't imply that integration is always required before pushing\n     \n    -    Also, don't put `git pull` in an awkward parenthetical, because\n    -    `git pull` can always be used to reconcile branches and is the normal\n    -    way to do so.\n    +    In a narrow but common case, the user is the only author of a branch and\n    +    doesn't mind overwriting the corresponding branch on the remote. This\n    +    workflow is especially common on GitHub, GitLab, and Gerrit, which keep\n    +    a permanent record of every version of a branch that is pushed while a\n    +    pull request is open for that branch. On those platforms, force-pushing\n    +    is encouraged and is analogous to emailing a new version of a patchset.\n    +\n    +    When giving advice about divergent branches, tell the user about\n    +    `git pull`, but don't unconditionally instruct the user to do it. A less\n    +    prescriptive message will help prevent users from thinking that they are\n    +    required to create an integrated history instead of simply replacing the\n    +    previous history. Also, don't put `git pull` in an awkward\n    +    parenthetical, because `git pull` can always be used to reconcile\n    +    branches and is the normal way to do so.\n    +\n    +    Due to the difficulty of knowing which command for force-pushing is best\n    +    suited to the user's situation, no specific advice is given about\n    +    force-pushing. Instead, the user is directed to the Git documentation to\n    +    read about possible ways forward that do not involve integration.\n     \n         Signed-off-by: Alex Henrie <alexhenrie24@gmail.com>\n     \n    @@ builtin/push.c: static void setup_default_push_refspecs(int *flags, struct remot\n      \tN_(\"Updates were rejected because the tip of your current branch is behind\\n\"\n     -\t   \"its remote counterpart. Integrate the remote changes (e.g.\\n\"\n     -\t   \"'git pull ...') before pushing again.\\n\"\n    -+\t   \"its remote counterpart. Use 'git pull' to integrate the remote changes\\n\"\n    -+\t   \"before pushing again, or use 'git push --force' to delete the remote\\n\"\n    -+\t   \"changes and replace them with your own.\\n\"\n    ++\t   \"its remote counterpart. If you want to integrate the remote changes,\\n\"\n    ++\t   \"use 'git pull' 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_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 integrate the remote changes\\n\"\n     -\t   \"(e.g. 'git pull ...') before pushing again.\\n\"\n    -+\t   \"counterpart. Check out this branch and use 'git pull' to integrate the\\n\"\n    -+\t   \"remote changes before pushing again, or use 'git push --force' to delete\\n\"\n    -+\t   \"the remote changes and replace them with your own.\\n\"\n    ++\t   \"counterpart. If you want to integrate the remote changes, use '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_ref_fetch_first[] =\n    @@ builtin/push.c: static void setup_default_push_refspecs(int *flags, struct remot\n     -\t   \"(e.g., 'git pull ...') before pushing again.\\n\"\n     +\tN_(\"Updates were rejected because the remote contains work that you do not\\n\"\n     +\t   \"have locally. This is usually caused by another repository pushing to\\n\"\n    -+\t   \"the same ref. Use 'git pull' to integrate the remote changes before\\n\"\n    -+\t   \"pushing again, or use 'git push --force' to delete the remote changes\\n\"\n    -+\t   \"and replace them with your own.\\n\"\n    ++\t   \"the same ref. If you want to integrate the remote changes, use\\n\"\n    ++\t   \"'git pull' 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_ref_already_exists[] =\n    @@ builtin/push.c: static const char message_advice_ref_needs_force[] =\n     -\t   \"to integrate those changes locally (e.g., 'git pull ...')\\n\"\n     -\t   \"before forcing an update.\\n\");\n     +\tN_(\"Updates were rejected because the tip of the remote-tracking branch has\\n\"\n    -+\t   \"been updated since the last checkout. Use 'git pull' to integrate the\\n\"\n    -+\t   \"remote changes before pushing again, or use 'git push --force' to delete\\n\"\n    -+\t   \"the remote changes and replace them with your own.\\n\");\n    ++\t   \"been updated since the last checkout. If you want to integrate the\\n\"\n    ++\t   \"remote changes, use '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-- \n2.41.0\n\n"},{"id":"479451","messageId":"20230713044128.3771818-2-alexhenrie24@gmail.com","threadId":"59944","inReplyTo":"20230713044128.3771818-1-alexhenrie24@gmail.com","subject":"[PATCH v5 1/3] wt-status: don't show divergence advice when committing","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-13T04:41:13Z","receivedAt":"2023-07-13T04:42:48Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"When the user is in the middle of making a commit, they are not yet at\nthe point where they are ready to think about integrating their local\nbranch with the corresponding remote branch or force-pushing over the\nremote branch. Don't include advice on how to deal with divergent\nbranches in the commit template, to avoid giving the impression that the\ndivergence needs to be dealt with immediately. Similar advice will be\nprinted when it is most relevant, that is, if the user does try to push\nwithout first reconciling the two branches.\n\nSigned-off-by: Alex Henrie <alexhenrie24@gmail.com>\n---\n builtin/checkout.c |  2 +-\n remote.c           |  6 ++++--\n remote.h           |  3 ++-\n t/t7508-status.sh  | 10 ++++------\n wt-status.c        |  3 ++-\n 5 files changed, 13 insertions(+), 11 deletions(-)\n\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex fd6ee8c272..c278c2169d 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -916,7 +916,7 @@ static void report_tracking(struct branch_info *new_branch_info)\n \tstruct strbuf sb = STRBUF_INIT;\n \tstruct branch *branch = branch_get(new_branch_info->name);\n \n-\tif (!format_tracking_info(branch, &sb, AHEAD_BEHIND_FULL))\n+\tif (!format_tracking_info(branch, &sb, AHEAD_BEHIND_FULL, 1))\n \t\treturn;\n \tfputs(sb.buf, stdout);\n \tstrbuf_release(&sb);\ndiff --git a/remote.c b/remote.c\nindex a81f2e2f17..d79aae0d76 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -2258,7 +2258,8 @@ int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs,\n  * Return true when there is anything to report, otherwise false.\n  */\n int format_tracking_info(struct branch *branch, struct strbuf *sb,\n-\t\t\t enum ahead_behind_flags abf)\n+\t\t\t enum ahead_behind_flags abf,\n+\t\t\t int show_divergence_advice)\n {\n \tint ours, theirs, sti;\n \tconst char *full_base;\n@@ -2321,7 +2322,8 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb,\n \t\t\t       \"respectively.\\n\",\n \t\t\t   ours + theirs),\n \t\t\tbase, ours, theirs);\n-\t\tif (advice_enabled(ADVICE_STATUS_HINTS))\n+\t\tif (show_divergence_advice &&\n+\t\t    advice_enabled(ADVICE_STATUS_HINTS))\n \t\t\tstrbuf_addstr(sb,\n \t\t\t\t_(\"  (use \\\"git pull\\\" to merge the remote branch into yours)\\n\"));\n \t}\ndiff --git a/remote.h b/remote.h\nindex 929c7c676d..cdc8b1db42 100644\n--- a/remote.h\n+++ b/remote.h\n@@ -380,7 +380,8 @@ int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs,\n \t\t       const char **upstream_name, int for_push,\n \t\t       enum ahead_behind_flags abf);\n int format_tracking_info(struct branch *branch, struct strbuf *sb,\n-\t\t\t enum ahead_behind_flags abf);\n+\t\t\t enum ahead_behind_flags abf,\n+\t\t\t int show_divergence_advice);\n \n struct ref *get_local_heads(void);\n /*\ndiff --git a/t/t7508-status.sh b/t/t7508-status.sh\nindex 36567708f5..845af287d7 100755\n--- a/t/t7508-status.sh\n+++ b/t/t7508-status.sh\n@@ -847,7 +847,6 @@ test_expect_success 'dry-run of partial commit excluding new file in index' '\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 1 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -1013,7 +1012,7 @@ test_expect_success 'status -s submodule summary' '\n '\n \n test_expect_success 'status submodule summary (clean submodule): commit' '\n-\tcat >expect <<EOF &&\n+\tcat >expect-status <<EOF &&\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 2 and 2 different commits each, respectively.\n@@ -1033,12 +1032,13 @@ Untracked files:\n \n no changes added to commit (use \"git add\" and/or \"git commit -a\")\n EOF\n+\tsed \"/git pull/d\" expect-status > expect-commit &&\n \tgit commit -m \"commit submodule\" &&\n \tgit config status.submodulesummary 10 &&\n \ttest_must_fail git commit --dry-run >output &&\n-\ttest_cmp expect output &&\n+\ttest_cmp expect-commit output &&\n \tgit status >output &&\n-\ttest_cmp expect output\n+\ttest_cmp expect-status output\n '\n \n cat >expect <<EOF\n@@ -1065,7 +1065,6 @@ test_expect_success 'commit --dry-run submodule summary (--amend)' '\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 2 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n \n Changes to be committed:\n   (use \"git restore --source=HEAD^1 --staged <file>...\" to unstage)\n@@ -1558,7 +1557,6 @@ test_expect_success 'git commit --dry-run will show a staged but ignored submodu\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 2 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\ndiff --git a/wt-status.c b/wt-status.c\nindex bcd0ef8044..e3e3732ea2 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -1186,7 +1186,8 @@ static void wt_longstatus_print_tracking(struct wt_status *s)\n \n \tt_begin = getnanotime();\n \n-\tif (!format_tracking_info(branch, &sb, s->ahead_behind_flags))\n+\tif (!format_tracking_info(branch, &sb, s->ahead_behind_flags,\n+\t\t\t\t  !s->commit_template))\n \t\treturn;\n \n \tif (advice_enabled(ADVICE_STATUS_AHEAD_BEHIND_WARNING) &&\n-- \n2.41.0\n\n"},{"id":"479452","messageId":"20230713044128.3771818-3-alexhenrie24@gmail.com","threadId":"59944","inReplyTo":"20230713044128.3771818-1-alexhenrie24@gmail.com","subject":"[PATCH v5 2/3] remote: don't imply that integration is always required before pushing","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-13T04:41:14Z","receivedAt":"2023-07-13T04:43:06Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"In a narrow but common case, the user is the only author of a branch and\ndoesn't mind overwriting the corresponding branch on the remote. This\nworkflow is especially common on GitHub, GitLab, and Gerrit, which keep\na permanent record of every version of a branch that is pushed while a\npull request is open for that branch. On those platforms, force-pushing\nis encouraged and is analogous to emailing a new version of a patchset.\n\nWhen giving advice about divergent branches, tell the user about\n`git pull`, but don't unconditionally instruct the user to do it. A less\nprescriptive message will help prevent users from thinking that they are\nrequired to create an integrated history instead of simply replacing the\nprevious history. Likewise, don't imply that `git pull` is only for\nmerging.\n\nSigned-off-by: Alex Henrie <alexhenrie24@gmail.com>\n---\n remote.c          |  2 +-\n t/t7508-status.sh | 38 +++++++++++++++++++-------------------\n 2 files changed, 20 insertions(+), 20 deletions(-)\n\ndiff --git a/remote.c b/remote.c\nindex d79aae0d76..71019564d5 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -2325,7 +2325,7 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb,\n \t\tif (show_divergence_advice &&\n \t\t    advice_enabled(ADVICE_STATUS_HINTS))\n \t\t\tstrbuf_addstr(sb,\n-\t\t\t\t_(\"  (use \\\"git pull\\\" to merge the remote branch into yours)\\n\"));\n+\t\t\t\t_(\"  (use \\\"git pull\\\" if you want to integrate the remote branch with yours)\\n\"));\n \t}\n \tfree(base);\n \treturn 1;\ndiff --git a/t/t7508-status.sh b/t/t7508-status.sh\nindex 845af287d7..6928fd89f5 100755\n--- a/t/t7508-status.sh\n+++ b/t/t7508-status.sh\n@@ -92,7 +92,7 @@ test_expect_success 'status --column' '\n # On branch main\n # Your branch and '\\''upstream'\\'' have diverged,\n # and have 1 and 2 different commits each, respectively.\n-#   (use \"git pull\" to merge the remote branch into yours)\n+#   (use \"git pull\" if you want to integrate the remote branch with yours)\n #\n # Changes to be committed:\n #   (use \"git restore --staged <file>...\" to unstage)\n@@ -123,7 +123,7 @@ cat >expect <<\\EOF\n # On branch main\n # Your branch and 'upstream' have diverged,\n # and have 1 and 2 different commits each, respectively.\n-#   (use \"git pull\" to merge the remote branch into yours)\n+#   (use \"git pull\" if you want to integrate the remote branch with yours)\n #\n # Changes to be committed:\n #   (use \"git restore --staged <file>...\" to unstage)\n@@ -270,7 +270,7 @@ test_expect_success 'status with gitignore' '\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 1 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (use \"git pull\" if you want to integrate the remote branch with yours)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -335,7 +335,7 @@ test_expect_success 'status with gitignore (nothing untracked)' '\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 1 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (use \"git pull\" if you want to integrate the remote branch with yours)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -405,7 +405,7 @@ test_expect_success 'status -uno' '\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 1 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (use \"git pull\" if you want to integrate the remote branch with yours)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -467,7 +467,7 @@ test_expect_success 'status -unormal' '\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 1 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (use \"git pull\" if you want to integrate the remote branch with yours)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -522,7 +522,7 @@ test_expect_success 'status -uall' '\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 1 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (use \"git pull\" if you want to integrate the remote branch with yours)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -582,7 +582,7 @@ test_expect_success 'status with relative paths' '\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 1 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (use \"git pull\" if you want to integrate the remote branch with yours)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -650,7 +650,7 @@ test_expect_success TTY 'status with color.ui' '\n On branch <GREEN>main<RESET>\n Your branch and '\\''upstream'\\'' have diverged,\n and have 1 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (use \"git pull\" if you want to integrate the remote branch with yours)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -773,7 +773,7 @@ test_expect_success 'status without relative paths' '\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 1 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (use \"git pull\" if you want to integrate the remote branch with yours)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -900,7 +900,7 @@ test_expect_success 'status submodule summary is disabled by default' '\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 1 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (use \"git pull\" if you want to integrate the remote branch with yours)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -957,7 +957,7 @@ test_expect_success 'status submodule summary' '\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 1 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (use \"git pull\" if you want to integrate the remote branch with yours)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -1016,7 +1016,7 @@ test_expect_success 'status submodule summary (clean submodule): commit' '\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 2 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (use \"git pull\" if you want to integrate the remote branch with yours)\n \n Changes not staged for commit:\n   (use \"git add <file>...\" to update what will be committed)\n@@ -1116,7 +1116,7 @@ test_expect_success '--ignore-submodules=untracked suppresses submodules with un\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 2 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (use \"git pull\" if you want to integrate the remote branch with yours)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -1225,7 +1225,7 @@ test_expect_success \"--ignore-submodules=untracked doesn't suppress submodules w\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 2 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (use \"git pull\" if you want to integrate the remote branch with yours)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -1282,7 +1282,7 @@ test_expect_success \"--ignore-submodules=untracked doesn't suppress submodule su\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 2 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (use \"git pull\" if you want to integrate the remote branch with yours)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n@@ -1363,7 +1363,7 @@ cat > expect << EOF\n ; On branch main\n ; Your branch and 'upstream' have diverged,\n ; and have 2 and 2 different commits each, respectively.\n-;   (use \"git pull\" to merge the remote branch into yours)\n+;   (use \"git pull\" if you want to integrate the remote branch with yours)\n ;\n ; Changes to be committed:\n ;   (use \"git restore --staged <file>...\" to unstage)\n@@ -1411,7 +1411,7 @@ test_expect_success \"--ignore-submodules=all suppresses submodule summary\" '\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 2 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (use \"git pull\" if you want to integrate the remote branch with yours)\n \n Changes not staged for commit:\n   (use \"git add <file>...\" to update what will be committed)\n@@ -1437,7 +1437,7 @@ test_expect_success '.gitmodules ignore=all suppresses unstaged submodule summar\n On branch main\n Your branch and '\\''upstream'\\'' have diverged,\n and have 2 and 2 different commits each, respectively.\n-  (use \"git pull\" to merge the remote branch into yours)\n+  (use \"git pull\" if you want to integrate the remote branch with yours)\n \n Changes to be committed:\n   (use \"git restore --staged <file>...\" to unstage)\n-- \n2.41.0\n\n"},{"id":"479453","messageId":"20230713044128.3771818-4-alexhenrie24@gmail.com","threadId":"59944","inReplyTo":"20230713044128.3771818-1-alexhenrie24@gmail.com","subject":"[PATCH v5 3/3] push: don't imply that integration is always required before pushing","fromName":"Alex Henrie","fromEmail":"alexhenrie24@gmail.com","sentAt":"2023-07-13T04:41:15Z","receivedAt":"2023-07-13T04:43:09Z","isPatch":true,"sender":{"key":"alexhenrie24@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5951993?v=4"},"body":"In a narrow but common case, the user is the only author of a branch and\ndoesn't mind overwriting the corresponding branch on the remote. This\nworkflow is especially common on GitHub, GitLab, and Gerrit, which keep\na permanent record of every version of a branch that is pushed while a\npull request is open for that branch. On those platforms, force-pushing\nis encouraged and is analogous to emailing a new version of a patchset.\n\nWhen giving advice about divergent branches, tell the user about\n`git pull`, but don't unconditionally instruct the user to do it. A less\nprescriptive message will help prevent users from thinking that they are\nrequired to create an integrated history instead of simply replacing the\nprevious history. Also, don't put `git pull` in an awkward\nparenthetical, because `git pull` can always be used to reconcile\nbranches and is the normal way to do so.\n\nDue to the difficulty of knowing which command for force-pushing is best\nsuited to the user's situation, no specific advice is given about\nforce-pushing. Instead, the user is directed to the Git documentation to\nread about possible ways forward that do not involve integration.\n\nSigned-off-by: Alex Henrie <alexhenrie24@gmail.com>\n---\n builtin/push.c | 24 ++++++++++++------------\n 1 file changed, 12 insertions(+), 12 deletions(-)\n\ndiff --git a/builtin/push.c b/builtin/push.c\nindex 6f8a8dc711..61a251c50a 100644\n--- a/builtin/push.c\n+++ b/builtin/push.c\n@@ -301,21 +301,21 @@ static void setup_default_push_refspecs(int *flags, struct remote *remote)\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. Integrate the remote changes (e.g.\\n\"\n-\t   \"'git pull ...') before pushing again.\\n\"\n+\t   \"its remote counterpart. If you want to integrate the remote changes,\\n\"\n+\t   \"use 'git pull' 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_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 integrate the remote changes\\n\"\n-\t   \"(e.g. 'git pull ...') before pushing again.\\n\"\n+\t   \"counterpart. If you want to integrate the remote changes, use '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_ref_fetch_first[] =\n-\tN_(\"Updates were rejected because the remote contains work that you do\\n\"\n-\t   \"not have locally. This is usually caused by another repository pushing\\n\"\n-\t   \"to the same ref. You may want to first integrate the remote changes\\n\"\n-\t   \"(e.g., 'git pull ...') before pushing again.\\n\"\n+\tN_(\"Updates were rejected because the remote contains work that you do not\\n\"\n+\t   \"have locally. This is usually caused by another repository pushing to\\n\"\n+\t   \"the same ref. If you want to integrate the remote changes, use\\n\"\n+\t   \"'git pull' 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_ref_already_exists[] =\n@@ -327,10 +327,10 @@ static const char message_advice_ref_needs_force[] =\n \t   \"without using the '--force' option.\\n\");\n \n static const char message_advice_ref_needs_update[] =\n-\tN_(\"Updates were rejected because the tip of the remote-tracking\\n\"\n-\t   \"branch has been updated since the last checkout. You may want\\n\"\n-\t   \"to integrate those changes locally (e.g., 'git pull ...')\\n\"\n-\t   \"before forcing an update.\\n\");\n+\tN_(\"Updates were rejected because the tip of the remote-tracking branch has\\n\"\n+\t   \"been updated since the last checkout. If you want to integrate the\\n\"\n+\t   \"remote changes, use '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-- \n2.41.0\n\n"},{"id":"479456","messageId":"919d1ba8-bb8b-a77b-cef3-db14f168ed4a@gmail.com","threadId":"59944","inReplyTo":"20230713044128.3771818-1-alexhenrie24@gmail.com","subject":"Re: [PATCH v5 0/3] don't imply that integration is always required before pushing","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2023-07-13T09:51:09Z","receivedAt":"2023-07-13T09:51:17Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"Hi Alex\n\nOn 13/07/2023 05:41, Alex Henrie wrote:\n> Many times now, I have seen novices do the following:\n> \n> 1. Start work on their own personal topic branch\n> 2. Push the branch to origin\n> 3. Rebase the branch onto origin/master\n> 4. Try to push again, but Git says they need to pull\n> 5. Pull and make a mess trying to reconcile the older topic branch with\n>     the rebased topic branch\n> \n> Help avoid this mistake by giving somewhat more general advice that does\n> not assume that the user always wants to do reconciliation.\n> \n> Changes from v4:\n> - Don't show divergent branch advice in the middle of `git commit`\n> - Soften the advice, but don't specifically mention force-pushing\n\nAll three patches look fine to me, they are definitely an improvement on \nthe current advice.\n\nThanks for working on this,\n\nPhillip\n\n> Alex Henrie (3):\n>    wt-status: don't show divergence advice when committing\n>    remote: don't imply that integration is always required before pushing\n>    push: don't imply that integration is always required before pushing\n> \n>   builtin/checkout.c |  2 +-\n>   builtin/push.c     | 24 +++++++++++------------\n>   remote.c           |  8 +++++---\n>   remote.h           |  3 ++-\n>   t/t7508-status.sh  | 48 ++++++++++++++++++++++------------------------\n>   wt-status.c        |  3 ++-\n>   6 files changed, 45 insertions(+), 43 deletions(-)\n> \n> Range-diff against v4:\n> 1:  9626721c13 < -:  ---------- remote: advise about force-pushing as an alternative to reconciliation\n> -:  ---------- > 1:  e84989c4a6 wt-status: don't show divergence advice when committing\n> -:  ---------- > 2:  9bb643df7e remote: don't imply that integration is always required before pushing\n> 2:  209e86588a ! 3:  5ff9ecb51b push: advise about force-pushing as an alternative to reconciliation\n>      @@ Metadata\n>       Author: Alex Henrie <alexhenrie24@gmail.com>\n>       \n>        ## Commit message ##\n>      -    push: advise about force-pushing as an alternative to reconciliation\n>      +    push: don't imply that integration is always required before pushing\n>       \n>      -    Also, don't put `git pull` in an awkward parenthetical, because\n>      -    `git pull` can always be used to reconcile branches and is the normal\n>      -    way to do so.\n>      +    In a narrow but common case, the user is the only author of a branch and\n>      +    doesn't mind overwriting the corresponding branch on the remote. This\n>      +    workflow is especially common on GitHub, GitLab, and Gerrit, which keep\n>      +    a permanent record of every version of a branch that is pushed while a\n>      +    pull request is open for that branch. On those platforms, force-pushing\n>      +    is encouraged and is analogous to emailing a new version of a patchset.\n>      +\n>      +    When giving advice about divergent branches, tell the user about\n>      +    `git pull`, but don't unconditionally instruct the user to do it. A less\n>      +    prescriptive message will help prevent users from thinking that they are\n>      +    required to create an integrated history instead of simply replacing the\n>      +    previous history. Also, don't put `git pull` in an awkward\n>      +    parenthetical, because `git pull` can always be used to reconcile\n>      +    branches and is the normal way to do so.\n>      +\n>      +    Due to the difficulty of knowing which command for force-pushing is best\n>      +    suited to the user's situation, no specific advice is given about\n>      +    force-pushing. Instead, the user is directed to the Git documentation to\n>      +    read about possible ways forward that do not involve integration.\n>       \n>           Signed-off-by: Alex Henrie <alexhenrie24@gmail.com>\n>       \n>      @@ builtin/push.c: static void setup_default_push_refspecs(int *flags, struct remot\n>        \tN_(\"Updates were rejected because the tip of your current branch is behind\\n\"\n>       -\t   \"its remote counterpart. Integrate the remote changes (e.g.\\n\"\n>       -\t   \"'git pull ...') before pushing again.\\n\"\n>      -+\t   \"its remote counterpart. Use 'git pull' to integrate the remote changes\\n\"\n>      -+\t   \"before pushing again, or use 'git push --force' to delete the remote\\n\"\n>      -+\t   \"changes and replace them with your own.\\n\"\n>      ++\t   \"its remote counterpart. If you want to integrate the remote changes,\\n\"\n>      ++\t   \"use 'git pull' 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_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 integrate the remote changes\\n\"\n>       -\t   \"(e.g. 'git pull ...') before pushing again.\\n\"\n>      -+\t   \"counterpart. Check out this branch and use 'git pull' to integrate the\\n\"\n>      -+\t   \"remote changes before pushing again, or use 'git push --force' to delete\\n\"\n>      -+\t   \"the remote changes and replace them with your own.\\n\"\n>      ++\t   \"counterpart. If you want to integrate the remote changes, use '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_ref_fetch_first[] =\n>      @@ builtin/push.c: static void setup_default_push_refspecs(int *flags, struct remot\n>       -\t   \"(e.g., 'git pull ...') before pushing again.\\n\"\n>       +\tN_(\"Updates were rejected because the remote contains work that you do not\\n\"\n>       +\t   \"have locally. This is usually caused by another repository pushing to\\n\"\n>      -+\t   \"the same ref. Use 'git pull' to integrate the remote changes before\\n\"\n>      -+\t   \"pushing again, or use 'git push --force' to delete the remote changes\\n\"\n>      -+\t   \"and replace them with your own.\\n\"\n>      ++\t   \"the same ref. If you want to integrate the remote changes, use\\n\"\n>      ++\t   \"'git pull' 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_ref_already_exists[] =\n>      @@ builtin/push.c: static const char message_advice_ref_needs_force[] =\n>       -\t   \"to integrate those changes locally (e.g., 'git pull ...')\\n\"\n>       -\t   \"before forcing an update.\\n\");\n>       +\tN_(\"Updates were rejected because the tip of the remote-tracking branch has\\n\"\n>      -+\t   \"been updated since the last checkout. Use 'git pull' to integrate the\\n\"\n>      -+\t   \"remote changes before pushing again, or use 'git push --force' to delete\\n\"\n>      -+\t   \"the remote changes and replace them with your own.\\n\");\n>      ++\t   \"been updated since the last checkout. If you want to integrate the\\n\"\n>      ++\t   \"remote changes, use '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\n"},{"id":"479461","messageId":"xmqqpm4vrdn8.fsf@gitster.g","threadId":"59944","inReplyTo":"919d1ba8-bb8b-a77b-cef3-db14f168ed4a@gmail.com","subject":"Re: [PATCH v5 0/3] don't imply that integration is always required before pushing","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2023-07-13T16:15:39Z","receivedAt":"2023-07-13T16:15:44Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n> Hi Alex\n>\n> On 13/07/2023 05:41, Alex Henrie wrote:\n>> Many times now, I have seen novices do the following:\n>> 1. Start work on their own personal topic branch\n>> 2. Push the branch to origin\n>> 3. Rebase the branch onto origin/master\n>> 4. Try to push again, but Git says they need to pull\n>> 5. Pull and make a mess trying to reconcile the older topic branch with\n>>     the rebased topic branch\n>> Help avoid this mistake by giving somewhat more general advice that\n>> does\n>> not assume that the user always wants to do reconciliation.\n>> Changes from v4:\n>> - Don't show divergent branch advice in the middle of `git commit`\n>> - Soften the advice, but don't specifically mention force-pushing\n>\n> All three patches look fine to me, they are definitely an improvement\n> on the current advice.\n>\n> Thanks for working on this,\n>\n> Phillip\n\nThanks, both.  Will queue after taking another look.\n"}]}