{"thread":{"id":"65766","subject":"[PATCH RFC 0/2] builtin/history: change git history reword behavior and feedback","startedAt":"2026-06-07T20:07:35Z","lastAt":"2026-07-08T12:04:56Z","messageCount":36,"participants":["Pablo Sabater","Patrick Steinhardt","Junio C Hamano","Ben Knoble","Kristoffer Haugsbakk","Phillip Wood","Justin Tobler","Dominique Martinet","D. Ben Knoble"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"544853","messageId":"20260607-ps-history-reword-v1-0-ba43a3cbb81b@gmail.com","threadId":"65766","inReplyTo":null,"subject":"[PATCH RFC 0/2] builtin/history: change git history reword behavior and feedback","fromName":"Pablo Sabater","fromEmail":"pabloosabaterr@gmail.com","sentAt":"2026-06-07T20:07:19Z","receivedAt":"2026-06-07T20:07:35Z","isPatch":true,"body":"This small series contains two commits that aim to improve\n`git history reword`:\n1. Abort the reword when the original message and the new message are\n   the same to avoid unnecessary history changes.\n2. Print feedback after a successful reword so the user knows about it.\n\n`git commit --amend` and `git rebase -i` with reword don't abort if\nthe commit message is the same as the original and they update as if\nit was a new message in favor of changing this behavior for\n`git history reword`:\n- As noted in the `git history` documentation, the command by\n  default updates all branches that contain the original commit [1]\n  this makes `git history reword` more expensive than other options\n  like `git rebase -i` that only updates the current branch.\n- `git history` works in-memory without touching the worktree or index\n  [2], because it doesn't use the sequencer and `git history reword`\n  doesn't care about the staged files only about the commit message, it\n  should have no problems.\n\nAbout the last fact in favor of 1, I'm not completely sure if it's\nbecause of staged files that's the reason why `git commit --amend` or\n`git rebase -i` with reword still updates even if the commit message\nis the same one. I'm not very up to sequencer.c to be sure but maybe\nthere's a historical reason about it that someone knows. Anyways I\nbelieve that given this new command is a good idea to discuss it.\n\nThe commit message of 1 mentions staged files as a possible justification\nfor why --amend and rebase behave this way, but that's just an\nassumption that I'll be happy to change if I'm wrong.\n\n[1]: https://git-scm.com/docs/git-history#_description\n[2]: https://lore.kernel.org/git/20260113-b4-pks-history-builtin-v11-8-e74ebfa2652d@pks.im/\n\nTo: git@vger.kernel.org\nCc: Patrick Steinhardt <ps@pks.im>\nCc: Kaartic Sivaraam <kaartic.sivaraam@gmail.com>\n\nSigned-off-by: Pablo Sabater <pabloosabaterr@gmail.com>\n---\nPablo Sabater (2):\n      builtin/history: abort reword on unchanged message\n      builtin/history: print feedback after successful reword\n\n builtin/history.c         | 14 ++++++++++++++\n t/t3451-history-reword.sh | 34 ++++++++++++++++++++++++++++++++++\n 2 files changed, 48 insertions(+)\n---\nbase-commit: 9ac3f193c05c2237e2b14ebaa1149e9fc8a1abe0\nchange-id: 20260607-ps-history-reword-fcb70eaa4aa9\n\nBest regards,\n--  \nPablo Sabater <pabloosabaterr@gmail.com>\n\n"},{"id":"544854","messageId":"20260607-ps-history-reword-v1-1-ba43a3cbb81b@gmail.com","threadId":"65766","inReplyTo":"20260607-ps-history-reword-v1-0-ba43a3cbb81b@gmail.com","subject":"[PATCH RFC 1/2] builtin/history: abort reword on unchanged message","fromName":"Pablo Sabater","fromEmail":"pabloosabaterr@gmail.com","sentAt":"2026-06-07T20:07:20Z","receivedAt":"2026-06-07T20:07:36Z","isPatch":true,"body":"When using `git history reword` if the new message is the same as the\noriginal it continues anyway creating a new commit with the same\nmessage and updates its descendants, modifying the history after this\n'reworded' commit even though there was no actual change.\n\n`git commit --amend` and `git rebase -i` + reword share this behavior,\nhowever `git history reword` is different:\n1. Works in-memory without touching the index or the worktree [1], so\n   there are no side effects like staged files that could justify\n   rewriting the history when the commit message is the same.\n2. `git history` by default updates all the branches [2] that contain the\n   original commit making it more costly than `git rebase -i` that only\n   updates the current branch.\n\nAdd a check if the original commit message is the same as the new one\nand abort if so.\n\n[1]: https://lore.kernel.org/git/20260113-b4-pks-history-builtin-v11-8-e74ebfa2652d@pks.im/\n[2]: https://git-scm.com/docs/git-history#_description\n\nSigned-off-by: Pablo Sabater <pabloosabaterr@gmail.com>\n---\n builtin/history.c         | 10 ++++++++++\n t/t3451-history-reword.sh | 20 ++++++++++++++++++++\n 2 files changed, 30 insertions(+)\n\ndiff --git a/builtin/history.c b/builtin/history.c\nindex 0fc06fb204..51a22a9a1c 100644\n--- a/builtin/history.c\n+++ b/builtin/history.c\n@@ -135,6 +135,13 @@ static int commit_tree_ext(struct repository *repo,\n \t\t\t\t\t  original_body, action, &commit_message);\n \t\tif (ret < 0)\n \t\t\tgoto out;\n+\n+\t\tif (!strcmp(original_body, commit_message.buf)) {\n+\t\t\tfprintf(stderr, _(\"Message unchanged,\"\n+\t\t\t\t\t  \" aborting reword.\\n\"));\n+\t\t\tret = 1;\n+\t\t\tgoto out;\n+\t\t}\n \t} else {\n \t\tstrbuf_addstr(&commit_message, original_body);\n \t}\n@@ -718,6 +725,9 @@ static int cmd_history_reword(int argc,\n \tif (ret < 0) {\n \t\tret = error(_(\"failed writing reworded commit\"));\n \t\tgoto out;\n+\t} else if (ret == 1) {\n+\t\tret = 0;\n+\t\tgoto out;\n \t}\n \n \tstrbuf_addf(&reflog_msg, \"reword: updating %s\", argv[0]);\ndiff --git a/t/t3451-history-reword.sh b/t/t3451-history-reword.sh\nindex de7b357685..54ea8a7207 100755\n--- a/t/t3451-history-reword.sh\n+++ b/t/t3451-history-reword.sh\n@@ -396,4 +396,24 @@ test_expect_success 'retains changes in the worktree and index' '\n \t)\n '\n \n+test_expect_success 'aborts if the commit message is the same' '\n+\ttest_when_finished \"rm -rf repo\" &&\n+\tgit init repo &&\n+\t(\n+\t\tcd repo &&\n+\t\ttest_commit first &&\n+\t\ttest_commit second &&\n+\n+\t\tgit rev-parse HEAD >oid-before &&\n+\t\twrite_script fake-editor.sh <<-\\EOF &&\n+\t\ttrue\n+\t\tEOF\n+\t\ttest_set_editor \"$(pwd)\"/fake-editor.sh &&\n+\t\tgit history reword HEAD 2>err &&\n+\t\tgit rev-parse HEAD >oid-after &&\n+\t\ttest_cmp oid-before oid-after &&\n+\t\ttest_grep \"Message unchanged\" err\n+\t)\n+'\n+\n test_done\n\n-- \n2.54.0\n\n"},{"id":"544855","messageId":"20260607-ps-history-reword-v1-2-ba43a3cbb81b@gmail.com","threadId":"65766","inReplyTo":"20260607-ps-history-reword-v1-0-ba43a3cbb81b@gmail.com","subject":"[PATCH RFC 2/2] builtin/history: print feedback after successful reword","fromName":"Pablo Sabater","fromEmail":"pabloosabaterr@gmail.com","sentAt":"2026-06-07T20:07:21Z","receivedAt":"2026-06-07T20:07:37Z","isPatch":true,"body":"Unlike `git commit --amend` and `git rebase -i`, `git history reword`\ndoesn't print anything, this makes it feel empty for a porcelain command\nand hard to tell if the command did anything without using other\ncommands like `git log <commit>` to check if the reword was done.\n\nPrint a message on successful rewords so the user has feedback about it.\n\nSigned-off-by: Pablo Sabater <pabloosabaterr@gmail.com>\n---\n builtin/history.c         |  4 ++++\n t/t3451-history-reword.sh | 14 ++++++++++++++\n 2 files changed, 18 insertions(+)\n\ndiff --git a/builtin/history.c b/builtin/history.c\nindex 51a22a9a1c..0f1ba3b531 100644\n--- a/builtin/history.c\n+++ b/builtin/history.c\n@@ -739,6 +739,10 @@ static int cmd_history_reword(int argc,\n \t\tgoto out;\n \t}\n \n+\tfprintf(stderr, _(\"Successfully reworded commit %s to %s\\n\"),\n+\t\trepo_find_unique_abbrev(repo, &original->object.oid, DEFAULT_ABBREV),\n+\t\trepo_find_unique_abbrev(repo, &rewritten->object.oid, DEFAULT_ABBREV));\n+\n \tret = 0;\n \n out:\ndiff --git a/t/t3451-history-reword.sh b/t/t3451-history-reword.sh\nindex 54ea8a7207..4b22d761e3 100755\n--- a/t/t3451-history-reword.sh\n+++ b/t/t3451-history-reword.sh\n@@ -416,4 +416,18 @@ test_expect_success 'aborts if the commit message is the same' '\n \t)\n '\n \n+test_expect_success 'prints feedback on successful reword' '\n+\ttest_when_finished \"rm -rf repo\" &&\n+\tgit init repo &&\n+\t(\n+\t\tcd repo &&\n+\t\ttest_commit first &&\n+\n+\t\treword_with_message HEAD 2>err <<-EOF &&\n+\t\tfirst reworded\n+\t\tEOF\n+\t\ttest_grep \"Successfully reworded\" err\n+\t)\n+'\n+\n test_done\n\n-- \n2.54.0\n\n"},{"id":"544879","messageId":"aiaLxNwGPko5HS2G@pks.im","threadId":"65766","inReplyTo":"20260607-ps-history-reword-v1-1-ba43a3cbb81b@gmail.com","subject":"Re: [PATCH RFC 1/2] builtin/history: abort reword on unchanged message","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-06-08T09:30:44Z","receivedAt":"2026-06-08T09:30:50Z","isPatch":true,"body":"On Sun, Jun 07, 2026 at 10:07:20PM +0200, Pablo Sabater wrote:\n> When using `git history reword` if the new message is the same as the\n> original it continues anyway creating a new commit with the same\n> message and updates its descendants, modifying the history after this\n> 'reworded' commit even though there was no actual change.\n> \n> `git commit --amend` and `git rebase -i` + reword share this behavior,\n> however `git history reword` is different:\n> 1. Works in-memory without touching the index or the worktree [1], so\n>    there are no side effects like staged files that could justify\n>    rewriting the history when the commit message is the same.\n> 2. `git history` by default updates all the branches [2] that contain the\n>    original commit making it more costly than `git rebase -i` that only\n>    updates the current branch.\n> \n> Add a check if the original commit message is the same as the new one\n> and abort if so.\n> \n> [1]: https://lore.kernel.org/git/20260113-b4-pks-history-builtin-v11-8-e74ebfa2652d@pks.im/\n> [2]: https://git-scm.com/docs/git-history#_description\n\nNit: I feel like both of the links don't really add much value.\n\n> Signed-off-by: Pablo Sabater <pabloosabaterr@gmail.com>\n> ---\n>  builtin/history.c         | 10 ++++++++++\n>  t/t3451-history-reword.sh | 20 ++++++++++++++++++++\n>  2 files changed, 30 insertions(+)\n> \n> diff --git a/builtin/history.c b/builtin/history.c\n> index 0fc06fb204..51a22a9a1c 100644\n> --- a/builtin/history.c\n> +++ b/builtin/history.c\n> @@ -135,6 +135,13 @@ static int commit_tree_ext(struct repository *repo,\n>  \t\t\t\t\t  original_body, action, &commit_message);\n>  \t\tif (ret < 0)\n>  \t\t\tgoto out;\n> +\n> +\t\tif (!strcmp(original_body, commit_message.buf)) {\n> +\t\t\tfprintf(stderr, _(\"Message unchanged,\"\n> +\t\t\t\t\t  \" aborting reword.\\n\"));\n> +\t\t\tret = 1;\n> +\t\t\tgoto out;\n> +\t\t}\n>  \t} else {\n>  \t\tstrbuf_addstr(&commit_message, original_body);\n>  \t}\n\nWe also execute this logic via \"git history fixup --reedit-message\", and\nhere it wouldn't make sense to abort the commit in case the message is\nunchanged.\n\nPatrick\n"},{"id":"544880","messageId":"aiaLyQvo8kqfv4js@pks.im","threadId":"65766","inReplyTo":"20260607-ps-history-reword-v1-2-ba43a3cbb81b@gmail.com","subject":"Re: [PATCH RFC 2/2] builtin/history: print feedback after successful reword","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-06-08T09:30:49Z","receivedAt":"2026-06-08T09:30:53Z","isPatch":true,"body":"On Sun, Jun 07, 2026 at 10:07:21PM +0200, Pablo Sabater wrote:\n> Unlike `git commit --amend` and `git rebase -i`, `git history reword`\n> doesn't print anything, this makes it feel empty for a porcelain command\n> and hard to tell if the command did anything without using other\n> commands like `git log <commit>` to check if the reword was done.\n> \n> Print a message on successful rewords so the user has feedback about it.\n\nI dunno about this one. My take here is that a command should be silent\nunless it has something to say, for example when it couldn't honor the\nuser's request [1].\n\n> diff --git a/builtin/history.c b/builtin/history.c\n> index 51a22a9a1c..0f1ba3b531 100644\n> --- a/builtin/history.c\n> +++ b/builtin/history.c\n> @@ -739,6 +739,10 @@ static int cmd_history_reword(int argc,\n>  \t\tgoto out;\n>  \t}\n>  \n> +\tfprintf(stderr, _(\"Successfully reworded commit %s to %s\\n\"),\n> +\t\trepo_find_unique_abbrev(repo, &original->object.oid, DEFAULT_ABBREV),\n> +\t\trepo_find_unique_abbrev(repo, &rewritten->object.oid, DEFAULT_ABBREV));\n> +\n\nSeeing the implementation also raises a couple of questions:\n\n  - Why do we mention the rewritten commit, only? Shouldn't we also\n    print the changed HEAD?\n\n  - Why don't we print any of the other rewritten branches?\n\n  - What makes \"git history reword\" so special as compared to for\n    example \"git history fixup\" or \"git history split\" so that it needs\n    a message while the others don't?\n\nIt might make sense to maybe introduce a verbose mode where we do print\nsuch information. But if so, we should have good answers to the above\nquestions and implement this in a way that makes sense for the other\nsubcommands, too, so that we can apply the same principle to all of\nthem.\n\nThanks!\n\nPatrick\n\n[1]: https://www.linfo.org/rule_of_silence.html\n"},{"id":"544904","messageId":"CAN5EUNT-21_RMuhRJwdk-vNbZmU=vNxBJEuG9mdaA_3spxwODQ@mail.gmail.com","threadId":"65766","inReplyTo":"aiaLyQvo8kqfv4js@pks.im","subject":"Re: [PATCH RFC 2/2] builtin/history: print feedback after successful reword","fromName":"Pablo Sabater","fromEmail":"pabloosabaterr@gmail.com","sentAt":"2026-06-08T10:45:59Z","receivedAt":"2026-06-08T10:46:11Z","isPatch":true,"body":"El lun, 8 jun 2026 a las 11:30, Patrick Steinhardt (<ps@pks.im>) escribió:\n>\n> On Sun, Jun 07, 2026 at 10:07:21PM +0200, Pablo Sabater wrote:\n> > Unlike `git commit --amend` and `git rebase -i`, `git history reword`\n> > doesn't print anything, this makes it feel empty for a porcelain command\n> > and hard to tell if the command did anything without using other\n> > commands like `git log <commit>` to check if the reword was done.\n> >\n> > Print a message on successful rewords so the user has feedback about it.\n>\n> I dunno about this one. My take here is that a command should be silent\n> unless it has something to say, for example when it couldn't honor the\n> user's request [1].\n\nBut neither `git commit --amend` nor `git rebase -i` follow this rule\nof silence.\n>\n> > diff --git a/builtin/history.c b/builtin/history.c\n> > index 51a22a9a1c..0f1ba3b531 100644\n> > --- a/builtin/history.c\n> > +++ b/builtin/history.c\n> > @@ -739,6 +739,10 @@ static int cmd_history_reword(int argc,\n> >               goto out;\n> >       }\n> >\n> > +     fprintf(stderr, _(\"Successfully reworded commit %s to %s\\n\"),\n> > +             repo_find_unique_abbrev(repo, &original->object.oid, DEFAULT_ABBREV),\n> > +             repo_find_unique_abbrev(repo, &rewritten->object.oid, DEFAULT_ABBREV));\n> > +\n>\n> Seeing the implementation also raises a couple of questions:\n>\n>   - Why do we mention the rewritten commit, only? Shouldn't we also\n>     print the changed HEAD?\n\nBecause `git history reword <commit>` is for a single commit. After\nthe reword the hash changes and the original hash is no longer useful\nto check the rewritten message. If I want to see how it is now:\n\n  $ git history reword aabb\n  $ git log aabb <- I can't check how it is now because this is the old one\n\nSo to check the new one I have to search the new hash. Imagine if it's\nthe first of 20 long commit messages, I have to git log --oneline, get\nthe hash and then git log new_hash, which IMO is unnecessary when git\nhistory reword can output the new hash.\n\n>\n>   - Why don't we print any of the other rewritten branches?\n\nHaven't thought of that, it's nice that it does modify all branches, I\njust assumed that the most relevant is the current branch new commit\nhash. The other rewritten branches have the same commit message, just\ndifferent hashes.\n\n>\n>   - What makes \"git history reword\" so special as compared to for\n>     example \"git history fixup\" or \"git history split\" so that it needs\n>     a message while the others don't?\n\nNothing, I just wanted this specifically for reword and sent this very\nsimple as an RFC to discuss the idea, I could extend this where it\nfits.\n\n>\n> It might make sense to maybe introduce a verbose mode where we do print\n> such information. But if so, we should have good answers to the above\n> questions and implement this in a way that makes sense for the other\n> subcommands, too, so that we can apply the same principle to all of\n> them.\n\nI like the verbose mode idea but I still think that on non-verbose\nsomething should be printed, on verbose it could be printed\nadditionally all the rewritten commits (though it could get very\nnoisy), the changed HEAD, etc.\n\n>\n> Thanks!\n>\n> Patrick\n>\n> [1]: https://www.linfo.org/rule_of_silence.html\n\n--\nPablo\n"},{"id":"544905","messageId":"CAN5EUNSAOMRvmLGVfzQiwWoOn9VGNVU5rVMZizOryn_q2fbCNA@mail.gmail.com","threadId":"65766","inReplyTo":"aiaLxNwGPko5HS2G@pks.im","subject":"Re: [PATCH RFC 1/2] builtin/history: abort reword on unchanged message","fromName":"Pablo Sabater","fromEmail":"pabloosabaterr@gmail.com","sentAt":"2026-06-08T10:52:49Z","receivedAt":"2026-06-08T10:53:01Z","isPatch":true,"body":"El lun, 8 jun 2026 a las 11:30, Patrick Steinhardt (<ps@pks.im>) escribió:\n>\n> On Sun, Jun 07, 2026 at 10:07:20PM +0200, Pablo Sabater wrote:\n> > When using `git history reword` if the new message is the same as the\n> > original it continues anyway creating a new commit with the same\n> > message and updates its descendants, modifying the history after this\n> > 'reworded' commit even though there was no actual change.\n> >\n> > `git commit --amend` and `git rebase -i` + reword share this behavior,\n> > however `git history reword` is different:\n> > 1. Works in-memory without touching the index or the worktree [1], so\n> >    there are no side effects like staged files that could justify\n> >    rewriting the history when the commit message is the same.\n> > 2. `git history` by default updates all the branches [2] that contain the\n> >    original commit making it more costly than `git rebase -i` that only\n> >    updates the current branch.\n> >\n> > Add a check if the original commit message is the same as the new one\n> > and abort if so.\n> >\n> > [1]: https://lore.kernel.org/git/20260113-b4-pks-history-builtin-v11-8-e74ebfa2652d@pks.im/\n> > [2]: https://git-scm.com/docs/git-history#_description\n>\n> Nit: I feel like both of the links don't really add much value.\n\nI'll just drop em.\n\n>\n> > Signed-off-by: Pablo Sabater <pabloosabaterr@gmail.com>\n> > ---\n> >  builtin/history.c         | 10 ++++++++++\n> >  t/t3451-history-reword.sh | 20 ++++++++++++++++++++\n> >  2 files changed, 30 insertions(+)\n> >\n> > diff --git a/builtin/history.c b/builtin/history.c\n> > index 0fc06fb204..51a22a9a1c 100644\n> > --- a/builtin/history.c\n> > +++ b/builtin/history.c\n> > @@ -135,6 +135,13 @@ static int commit_tree_ext(struct repository *repo,\n> >                                         original_body, action, &commit_message);\n> >               if (ret < 0)\n> >                       goto out;\n> > +\n> > +             if (!strcmp(original_body, commit_message.buf)) {\n> > +                     fprintf(stderr, _(\"Message unchanged,\"\n> > +                                       \" aborting reword.\\n\"));\n> > +                     ret = 1;\n> > +                     goto out;\n> > +             }\n> >       } else {\n> >               strbuf_addstr(&commit_message, original_body);\n> >       }\n>\n> We also execute this logic via \"git history fixup --reedit-message\", and\n> here it wouldn't make sense to abort the commit in case the message is\n> unchanged.\n\nTrue I hadn't thought that, I made it here because we have both the\noriginal and new message before creating the new commit. We could let\nret = 1 mean that the commit message is the same and then\ncmd_history_fixup ignores ret = 1 and for cmd_history_reword handle\nthe abort.\nWhat do you think?\n\n>\n> Patrick\n\n--\nPablo\n"},{"id":"544912","messageId":"xmqqqzmhz0pq.fsf@gitster.g","threadId":"65766","inReplyTo":"20260607-ps-history-reword-v1-2-ba43a3cbb81b@gmail.com","subject":"Re: [PATCH RFC 2/2] builtin/history: print feedback after successful reword","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-06-08T12:16:33Z","receivedAt":"2026-06-08T12:16:35Z","isPatch":true,"body":"Pablo Sabater <pabloosabaterr@gmail.com> writes:\n\n> Unlike `git commit --amend` and `git rebase -i`, `git history reword`\n> doesn't print anything, this makes it feel empty for a porcelain command\n> and hard to tell if the command did anything without using other\n> commands like `git log <commit>` to check if the reword was done.\n>\n> Print a message on successful rewords so the user has feedback about it.\n>\n> Signed-off-by: Pablo Sabater <pabloosabaterr@gmail.com>\n> ---\n>  builtin/history.c         |  4 ++++\n>  t/t3451-history-reword.sh | 14 ++++++++++++++\n>  2 files changed, 18 insertions(+)\n>\n> diff --git a/builtin/history.c b/builtin/history.c\n> index 51a22a9a1c..0f1ba3b531 100644\n> --- a/builtin/history.c\n> +++ b/builtin/history.c\n> @@ -739,6 +739,10 @@ static int cmd_history_reword(int argc,\n>  \t\tgoto out;\n>  \t}\n>  \n> +\tfprintf(stderr, _(\"Successfully reworded commit %s to %s\\n\"),\n> +\t\trepo_find_unique_abbrev(repo, &original->object.oid, DEFAULT_ABBREV),\n> +\t\trepo_find_unique_abbrev(repo, &rewritten->object.oid, DEFAULT_ABBREV));\n> +\n>  \tret = 0;\n>  \n>  out:\n\nDo other commands in \"git history\" (split is in 'master', drop and\nfixup are cooking) behave with similar verbosity?  Consistency within\nthe same \"history\" umbrella matters more than being similar with\nother commands that can be used for similar purposes.\n\n> diff --git a/t/t3451-history-reword.sh b/t/t3451-history-reword.sh\n> index 54ea8a7207..4b22d761e3 100755\n> --- a/t/t3451-history-reword.sh\n> +++ b/t/t3451-history-reword.sh\n> @@ -416,4 +416,18 @@ test_expect_success 'aborts if the commit message is the same' '\n>  \t)\n>  '\n>  \n> +test_expect_success 'prints feedback on successful reword' '\n> +\ttest_when_finished \"rm -rf repo\" &&\n> +\tgit init repo &&\n> +\t(\n> +\t\tcd repo &&\n> +\t\ttest_commit first &&\n> +\n> +\t\treword_with_message HEAD 2>err <<-EOF &&\n> +\t\tfirst reworded\n> +\t\tEOF\n> +\t\ttest_grep \"Successfully reworded\" err\n> +\t)\n> +'\n> +\n>  test_done\n"},{"id":"544913","messageId":"xmqqmrx5z0po.fsf@gitster.g","threadId":"65766","inReplyTo":"20260607-ps-history-reword-v1-1-ba43a3cbb81b@gmail.com","subject":"Re: [PATCH RFC 1/2] builtin/history: abort reword on unchanged message","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-06-08T12:16:35Z","receivedAt":"2026-06-08T12:16:37Z","isPatch":true,"body":"Pablo Sabater <pabloosabaterr@gmail.com> writes:\n\n> When using `git history reword` if the new message is the same as the\n> original it continues anyway creating a new commit with the same\n> message and updates its descendants, modifying the history after this\n> 'reworded' commit even though there was no actual change.\n>\n> `git commit --amend` and `git rebase -i` + reword share this behavior,\n> however `git history reword` is different:\n> 1. Works in-memory without touching the index or the worktree [1], so\n>    there are no side effects like staged files that could justify\n>    rewriting the history when the commit message is the same.\n> 2. `git history` by default updates all the branches [2] that contain the\n>    original commit making it more costly than `git rebase -i` that only\n>    updates the current branch.\n\nI think the reasoning is flawed.\n\nBoth \"git commit --amend\" and \"git rebase -i\", even with no changes\nto the tree, parents, or the message, update the committer timestamp\n(and perhaps the committer identity running the command may be\ndifferent from the original).  Updating this info is one of the\nimportant effects of the command.\n\nAnd \"history\" being more capable than \"rebase\" is a wrong excuse to\nmake the system behave inconsistently between commands that have\nsimilar features [*1*].  In a situation where letting 'history'\nupdate all the relevant branches, if a command behaves differently\nfrom the way the user likes (and if the way 'rebase -i' works is the\none the user likes), you'd end up forcing the user to use 'rebase\n-i' when 'history' would have been more appropriate.\n\nHaving said that, I personally think that the current behaviour of\n`commit --amend` and `history reword` are both _wrong_ [*2*].\n\nYou may start `git commit --amend`, and after staring at the\nexisting commit log message for some time in your editor, it is\nquite natural for you to decide that leaving the commit as-is is the\nright thing [*3*] in your situation.  It may have been a better\ndesign for the system to notice this situation and leave the commit\nas-is, with an override option `--force` to allow users to forcibly\nupdate the committer ident and timestamp in the commit header.  I am\nnot a `history reword` user (yet), but from the motivation you\ndescribed for this patch, I sense that the story is the same there.\n\n`git rebase -i A`, when A is truly an ancestor at the bottom of a\nlinear history leading to HEAD, behaves slightly better.  It gives\nyou a todo list with a bunch of `pick` insns, and when you do not\nedit earliest 'pick's the todo list, these earliest commits are left\nas-is.  It may still share the same issue that a 'reword' that you\nended up not rewording (or 'edit' that you ended up not touching its\ntree or log message) does still recreate a new commit object, though.\n\n`git rebase -i` may have an excuse that because it, unlike \"git\ncommit --amend\", operates on multiple commits by design.  A single\n\"--force\" option given to the command would not have worked as an\nescape hatch to allow the user to tell the command \"in this reword\nof this particular commit, I ended up doing nothing, but I still\nwant an updated committer log timestamp\".  Perhaps giving the\n\"--force\" (or --force-rewrite\") option at \"rebase --continue\" time\nmay work, but in any case, unless we plan to transition to these\n\"better\" default behaviour at a big version boundary, speculating\nwhat a \"better\" behaviour would have been may be fun but not very\nproductive.\n\n\n[Footnote]\n\n *1* Besides, doesn't \"--update-refs\" in \"rebase -i\" allow you to\n     adjust the branches?\n\n *2* But it is an established behaviour people _rely_ on, so even\n     though it may have been better if these commands behaved\n     differently, it probably is a bit too late to change it now.\n\n *3* This includes the case where the original author is especially\n     difficult to work with and would complain any change to their\n     commits, even if the only change you made for them is a\n     typofix.  Fixing a small typo/grammo may not be worth your time\n     and unpleasant exchanges with them after touching their commit.\n"},{"id":"544920","messageId":"CAN5EUNQNj86Q+hi6PouOZNWo1T4QTQ6sE5Hs9USZXWpkTedTcw@mail.gmail.com","threadId":"65766","inReplyTo":"xmqqqzmhz0pq.fsf@gitster.g","subject":"Re: [PATCH RFC 2/2] builtin/history: print feedback after successful reword","fromName":"Pablo Sabater","fromEmail":"pabloosabaterr@gmail.com","sentAt":"2026-06-08T13:23:46Z","receivedAt":"2026-06-08T13:23:58Z","isPatch":true,"body":"El lun, 8 jun 2026 a las 14:16, Junio C Hamano (<gitster@pobox.com>) escribió:\n>\n> Pablo Sabater <pabloosabaterr@gmail.com> writes:\n>\n> > Unlike `git commit --amend` and `git rebase -i`, `git history reword`\n> > doesn't print anything, this makes it feel empty for a porcelain command\n> > and hard to tell if the command did anything without using other\n> > commands like `git log <commit>` to check if the reword was done.\n> >\n> > Print a message on successful rewords so the user has feedback about it.\n> >\n> > Signed-off-by: Pablo Sabater <pabloosabaterr@gmail.com>\n> > ---\n> >  builtin/history.c         |  4 ++++\n> >  t/t3451-history-reword.sh | 14 ++++++++++++++\n> >  2 files changed, 18 insertions(+)\n> >\n> > diff --git a/builtin/history.c b/builtin/history.c\n> > index 51a22a9a1c..0f1ba3b531 100644\n> > --- a/builtin/history.c\n> > +++ b/builtin/history.c\n> > @@ -739,6 +739,10 @@ static int cmd_history_reword(int argc,\n> >               goto out;\n> >       }\n> >\n> > +     fprintf(stderr, _(\"Successfully reworded commit %s to %s\\n\"),\n> > +             repo_find_unique_abbrev(repo, &original->object.oid, DEFAULT_ABBREV),\n> > +             repo_find_unique_abbrev(repo, &rewritten->object.oid, DEFAULT_ABBREV));\n> > +\n> >       ret = 0;\n> >\n> >  out:\n>\n> Do other commands in \"git history\" (split is in 'master', drop and\n> fixup are cooking) behave with similar verbosity?  Consistency within\n> the same \"history\" umbrella matters more than being similar with\n> other commands that can be used for similar purposes.\n\nThey do not, they are thought with the rule of silence in mind.\nHowever I think that this output is valuable information I might have\nexplained myself better at [1] but my thought is:\n\ngit history reword aabb\n\nNow that I have my commit aabb rewritten I want to check it again just\nto make sure I did what I wanted correctly, but git log aabb is still\nthe old commit, the rewritten one has a different hash which I do not\nknow unless I search for it, if it's far from HEAD I'd have to git log\n--oneline, get the hash and then git log new_hash. I think that git\nhistory reword that does have the information about the new hash\nshould print it to avoid this search.\nWhat I want is something like:\n\ngit history reword aabb\nSuccessfully reworded aabb to ccdd\n\nSo I can just git log ccdd without having to search.\n\nI want to say I haven't looked as much as I'd like to split, drop and\nfixup, but I think it would be a good addition for them also. On [1]\nPatrick wrote about a --verbose for git history, I think that the\nbasic information i.e. at reword which is the new hash should be\nalways printed but if it's preferred it could go there.\n\nFor split it can print the hashes of the new commits like:\n\"...split into ccdd and eeff.\"\nFor fixup the commit hash also changes, so the same as reword.\nThe one that will have more friction would be drop is the one that\ndoesn't end up with new commits.\n\n[1]: https://lore.kernel.org/git/CAN5EUNSAOMRvmLGVfzQiwWoOn9VGNVU5rVMZizOryn_q2fbCNA@mail.gmail.com/\n\n>\n> > diff --git a/t/t3451-history-reword.sh b/t/t3451-history-reword.sh\n> > index 54ea8a7207..4b22d761e3 100755\n> > --- a/t/t3451-history-reword.sh\n> > +++ b/t/t3451-history-reword.sh\n> > @@ -416,4 +416,18 @@ test_expect_success 'aborts if the commit message is the same' '\n> >       )\n> >  '\n> >\n> > +test_expect_success 'prints feedback on successful reword' '\n> > +     test_when_finished \"rm -rf repo\" &&\n> > +     git init repo &&\n> > +     (\n> > +             cd repo &&\n> > +             test_commit first &&\n> > +\n> > +             reword_with_message HEAD 2>err <<-EOF &&\n> > +             first reworded\n> > +             EOF\n> > +             test_grep \"Successfully reworded\" err\n> > +     )\n> > +'\n> > +\n> >  test_done\n"},{"id":"544946","messageId":"9A2F74F1-66D0-4015-B387-35B107ED6F7A@gmail.com","threadId":"65766","inReplyTo":"20260607-ps-history-reword-v1-1-ba43a3cbb81b@gmail.com","subject":"Re: [PATCH RFC 1/2] builtin/history: abort reword on unchanged message","fromName":"Ben Knoble","fromEmail":"ben.knoble@gmail.com","sentAt":"2026-06-08T16:37:47Z","receivedAt":"2026-06-08T16:37:59Z","isPatch":true,"body":"I don’t have any strong opinions on the rest…\n\n> Le 7 juin 2026 à 16:08, Pablo Sabater <pabloosabaterr@gmail.com> a écrit :\n> \n> ﻿When using `git history reword` if the new message is the same as the\n> original it continues anyway creating a new commit with the same\n> message and updates its descendants, modifying the history after this\n> 'reworded' commit even though there was no actual change.\n> \n> `git commit --amend` and `git rebase -i` + reword share this behavior,\n> however `git history reword` is different:\n> 1. Works in-memory without touching the index or the worktree [1], so\n>   there are no side effects like staged files that could justify\n>   rewriting the history when the commit message is the same.\n> 2. `git history` by default updates all the branches [2] that contain the\n>   original commit making it more costly than `git rebase -i` that only\n>   updates the current branch.\n> \n> Add a check if the original commit message is the same as the new one\n> and abort if so.\n> \n> [1]: https://lore.kernel.org/git/20260113-b4-pks-history-builtin-v11-8-e74ebfa2652d@pks.im/\n> [2]: https://git-scm.com/docs/git-history#_description\n> \n> Signed-off-by: Pablo Sabater <pabloosabaterr@gmail.com>\n> ---\n> builtin/history.c         | 10 ++++++++++\n> t/t3451-history-reword.sh | 20 ++++++++++++++++++++\n> 2 files changed, 30 insertions(+)\n> \n> diff --git a/builtin/history.c b/builtin/history.c\n> index 0fc06fb204..51a22a9a1c 100644\n> --- a/builtin/history.c\n> +++ b/builtin/history.c\n> @@ -135,6 +135,13 @@ static int commit_tree_ext(struct repository *repo,\n>                      original_body, action, &commit_message);\n>        if (ret < 0)\n>            goto out;\n> +\n> +        if (!strcmp(original_body, commit_message.buf)) {\n> +            fprintf(stderr, _(\"Message unchanged,\"\n> +                      \" aborting reword.\\n\"));\n> +            ret = 1;\n> +            goto out;\n> +        }\n>    } else {\n>        strbuf_addstr(&commit_message, original_body);\n>    }\n> @@ -718,6 +725,9 @@ static int cmd_history_reword(int argc,\n>    if (ret < 0) {\n>        ret = error(_(\"failed writing reworded commit\"));\n>        goto out;\n> +    } else if (ret == 1) {\n> +        ret = 0;\n> +        goto out;\n>    }\n> \n>    strbuf_addf(&reflog_msg, \"reword: updating %s\", argv[0]);\n> diff --git a/t/t3451-history-reword.sh b/t/t3451-history-reword.sh\n> index de7b357685..54ea8a7207 100755\n> --- a/t/t3451-history-reword.sh\n> +++ b/t/t3451-history-reword.sh\n> @@ -396,4 +396,24 @@ test_expect_success 'retains changes in the worktree and index' '\n>    )\n> '\n> \n> +test_expect_success 'aborts if the commit message is the same' '\n> +    test_when_finished \"rm -rf repo\" &&\n> +    git init repo &&\n> +    (\n> +        cd repo &&\n> +        test_commit first &&\n> +        test_commit second &&\n> +\n> +        git rev-parse HEAD >oid-before &&\n> +        write_script fake-editor.sh <<-\\EOF &&\n> +        true\n> +        EOF\n> +        test_set_editor \"$(pwd)\"/fake-editor.sh &&\n> +        git history reword HEAD 2>err &&\n> +        git rev-parse HEAD >oid-after &&\n> +        test_cmp oid-before oid-after &&\n> +        test_grep \"Message unchanged\" err\n> +    )\n\n…but I think this test case could do something like \"GIT_EDITOR=true git history reword HEAD\" and avoid the script?\n\n> +'\n> +\n> test_done\n> \n> --\n> 2.54.0\n\nBest,\nBen"},{"id":"544947","messageId":"3D9034D8-C38F-48A1-B637-4342BE4954AC@gmail.com","threadId":"65766","inReplyTo":"xmqqmrx5z0po.fsf@gitster.g","subject":"Re: [PATCH RFC 1/2] builtin/history: abort reword on unchanged message","fromName":"Ben Knoble","fromEmail":"ben.knoble@gmail.com","sentAt":"2026-06-08T16:44:43Z","receivedAt":"2026-06-08T16:44:55Z","isPatch":true,"body":"\n> Le 8 juin 2026 à 08:23, Junio C Hamano <gitster@pobox.com> a écrit :\n> \n[snip]\n\n> Having said that, I personally think that the current behaviour of\n> `commit --amend` and `history reword` are both _wrong_ [*2*].\n> \n> You may start `git commit --amend`, and after staring at the\n> existing commit log message for some time in your editor, it is\n> quite natural for you to decide that leaving the commit as-is is the\n> right thing [*3*] in your situation.  It may have been a better\n> design for the system to notice this situation and leave the commit\n> as-is, with an override option `--force` to allow users to forcibly\n> update the committer ident and timestamp in the commit header.  I am\n> not a `history reword` user (yet), but from the motivation you\n> described for this patch, I sense that the story is the same there.\n\nFWIW, in this situation I abort my editor (:cquit in Vim) so that the amend gets an error-valued exit code from the subprocess and aborts itself. \n\nPerhaps there could/should be a better side-channel for communicating that, though? I do not know how easy it is to tell other editors to « quit with errors ».\n\n> [Footnote]\n> \n> *1* Besides, doesn't \"--update-refs\" in \"rebase -i\" allow you to\n>     adjust the branches?\n> \n> *2* But it is an established behaviour people _rely_ on, so even\n>     though it may have been better if these commands behaved\n>     differently, it probably is a bit too late to change it now.\n> \n> *3* This includes the case where the original author is especially\n>     difficult to work with and would complain any change to their\n>     commits, even if the only change you made for them is a\n>     typofix.  Fixing a small typo/grammo may not be worth your time\n>     and unpleasant exchanges with them after touching their commit.\n"},{"id":"544948","messageId":"9C91B027-C24A-4D7B-A3BC-5CF3B04D990C@gmail.com","threadId":"65766","inReplyTo":"CAN5EUNQNj86Q+hi6PouOZNWo1T4QTQ6sE5Hs9USZXWpkTedTcw@mail.gmail.com","subject":"Re: [PATCH RFC 2/2] builtin/history: print feedback after successful reword","fromName":"Ben Knoble","fromEmail":"ben.knoble@gmail.com","sentAt":"2026-06-08T16:47:41Z","receivedAt":"2026-06-08T16:47:53Z","isPatch":true,"body":"\n> Le 8 juin 2026 à 09:29, Pablo Sabater <pabloosabaterr@gmail.com> a écrit :\n> \n> ﻿El lun, 8 jun 2026 a las 14:16, Junio C Hamano (<gitster@pobox.com>) escribió:\n>> \n>> Pablo Sabater <pabloosabaterr@gmail.com> writes:\n>> \n>>> Unlike `git commit --amend` and `git rebase -i`, `git history reword`\n>>> doesn't print anything, this makes it feel empty for a porcelain command\n>>> and hard to tell if the command did anything without using other\n>>> commands like `git log <commit>` to check if the reword was done.\n>>> \n>>> Print a message on successful rewords so the user has feedback about it.\n>>> \n>>> Signed-off-by: Pablo Sabater <pabloosabaterr@gmail.com>\n>>> ---\n>>> builtin/history.c         |  4 ++++\n>>> t/t3451-history-reword.sh | 14 ++++++++++++++\n>>> 2 files changed, 18 insertions(+)\n>>> \n>>> diff --git a/builtin/history.c b/builtin/history.c\n>>> index 51a22a9a1c..0f1ba3b531 100644\n>>> --- a/builtin/history.c\n>>> +++ b/builtin/history.c\n>>> @@ -739,6 +739,10 @@ static int cmd_history_reword(int argc,\n>>>              goto out;\n>>>      }\n>>> \n>>> +     fprintf(stderr, _(\"Successfully reworded commit %s to %s\\n\"),\n>>> +             repo_find_unique_abbrev(repo, &original->object.oid, DEFAULT_ABBREV),\n>>> +             repo_find_unique_abbrev(repo, &rewritten->object.oid, DEFAULT_ABBREV));\n>>> +\n>>>      ret = 0;\n>>> \n>>> out:\n>> \n>> Do other commands in \"git history\" (split is in 'master', drop and\n>> fixup are cooking) behave with similar verbosity?  Consistency within\n>> the same \"history\" umbrella matters more than being similar with\n>> other commands that can be used for similar purposes.\n> \n> They do not, they are thought with the rule of silence in mind.\n> However I think that this output is valuable information I might have\n> explained myself better at [1] but my thought is:\n> \n> git history reword aabb\n> \n> Now that I have my commit aabb rewritten I want to check it again just\n> to make sure I did what I wanted correctly,\n\nSome thoughts:\n\n- If the rewritten commit is an ancestor of HEAD, look at the log of HEAD@{1} or the log between HEAD and the aforementioned reflog entry. (git-range-diff may also be helpful there.)\n- Similarly, if the rewritten commit is reachable from some ref R, check R@{1} etc. \n\n> but git log aabb is still\n> the old commit, the rewritten one has a different hash which I do not\n> know unless I search for it, if it's far from HEAD I'd have to git log\n> --oneline, get the hash and then git log new_hash. I think that git\n> history reword that does have the information about the new hash\n> should print it to avoid this search.\n> What I want is something like:\n> \n> git history reword aabb\n> Successfully reworded aabb to ccdd\n> \n> So I can just git log ccdd without having to search.\n> \n> I want to say I haven't looked as much as I'd like to split, drop and\n> fixup, but I think it would be a good addition for them also. On [1]\n> Patrick wrote about a --verbose for git history, I think that the\n> basic information i.e. at reword which is the new hash should be\n> always printed but if it's preferred it could go there.\n> \n> For split it can print the hashes of the new commits like:\n> \"...split into ccdd and eeff.\"\n> For fixup the commit hash also changes, so the same as reword.\n> The one that will have more friction would be drop is the one that\n> doesn't end up with new commits.\n> \n> [1]: https://lore.kernel.org/git/CAN5EUNSAOMRvmLGVfzQiwWoOn9VGNVU5rVMZizOryn_q2fbCNA@mail.gmail.com/\n"},{"id":"545042","messageId":"CAN5EUNRcMO-ZB9_4kdSb-ddhDdU1t6C_moAdg3NM7D26xKV7+Q@mail.gmail.com","threadId":"65766","inReplyTo":"9A2F74F1-66D0-4015-B387-35B107ED6F7A@gmail.com","subject":"Re: [PATCH RFC 1/2] builtin/history: abort reword on unchanged message","fromName":"Pablo Sabater","fromEmail":"pabloosabaterr@gmail.com","sentAt":"2026-06-09T09:59:24Z","receivedAt":"2026-06-09T09:59:36Z","isPatch":true,"body":"El lun, 8 jun 2026 a las 18:37, Ben Knoble (<ben.knoble@gmail.com>) escribió:\n[snip]\n> > +test_expect_success 'aborts if the commit message is the same' '\n> > +    test_when_finished \"rm -rf repo\" &&\n> > +    git init repo &&\n> > +    (\n> > +        cd repo &&\n> > +        test_commit first &&\n> > +        test_commit second &&\n> > +\n> > +        git rev-parse HEAD >oid-before &&\n> > +        write_script fake-editor.sh <<-\\EOF &&\n> > +        true\n> > +        EOF\n> > +        test_set_editor \"$(pwd)\"/fake-editor.sh &&\n> > +        git history reword HEAD 2>err &&\n> > +        git rev-parse HEAD >oid-after &&\n> > +        test_cmp oid-before oid-after &&\n> > +        test_grep \"Message unchanged\" err\n> > +    )\n>\n> …but I think this test case could do something like \"GIT_EDITOR=true git history reword HEAD\" and avoid the script?\n\nIt does work, thanks.\n\n>\n> > +'\n> > +\n> > test_done\n> >\n> > --\n> > 2.54.0\n>\n> Best,\n> Ben\n--\nPablo\n"},{"id":"545044","messageId":"CAN5EUNS98DYTKNCYjSFRSLvQv-UgewyV4PnafcDVROd0MvdmBQ@mail.gmail.com","threadId":"65766","inReplyTo":"3D9034D8-C38F-48A1-B637-4342BE4954AC@gmail.com","subject":"Re: [PATCH RFC 1/2] builtin/history: abort reword on unchanged message","fromName":"Pablo Sabater","fromEmail":"pabloosabaterr@gmail.com","sentAt":"2026-06-09T10:03:18Z","receivedAt":"2026-06-09T10:03:31Z","isPatch":true,"body":"El lun, 8 jun 2026 a las 18:44, Ben Knoble (<ben.knoble@gmail.com>) escribió:\n>\n>\n> > Le 8 juin 2026 à 08:23, Junio C Hamano <gitster@pobox.com> a écrit :\n> >\n> [snip]\n>\n> > Having said that, I personally think that the current behaviour of\n> > `commit --amend` and `history reword` are both _wrong_ [*2*].\n> >\n> > You may start `git commit --amend`, and after staring at the\n> > existing commit log message for some time in your editor, it is\n> > quite natural for you to decide that leaving the commit as-is is the\n> > right thing [*3*] in your situation.  It may have been a better\n> > design for the system to notice this situation and leave the commit\n> > as-is, with an override option `--force` to allow users to forcibly\n> > update the committer ident and timestamp in the commit header.  I am\n> > not a `history reword` user (yet), but from the motivation you\n> > described for this patch, I sense that the story is the same there.\n>\n> FWIW, in this situation I abort my editor (:cquit in Vim) so that the amend gets an error-valued exit code from the subprocess and aborts itself.\n>\n> Perhaps there could/should be a better side-channel for communicating that, though? I do not know how easy it is to tell other editors to « quit with errors ».\n\nWell, I didn't know that I could exit with errors (:cq in NeoVim),\ncan't say much about other editors, but It would be better to abort if\nthe messages are the same and forget about editors.\n\n>\n> > [Footnote]\n> >\n> > *1* Besides, doesn't \"--update-refs\" in \"rebase -i\" allow you to\n> >     adjust the branches?\n> >\n> > *2* But it is an established behaviour people _rely_ on, so even\n> >     though it may have been better if these commands behaved\n> >     differently, it probably is a bit too late to change it now.\n> >\n> > *3* This includes the case where the original author is especially\n> >     difficult to work with and would complain any change to their\n> >     commits, even if the only change you made for them is a\n> >     typofix.  Fixing a small typo/grammo may not be worth your time\n> >     and unpleasant exchanges with them after touching their commit.\n\nThanks,\nPablo\n"},{"id":"545053","messageId":"CAN5EUNRW3gyLKGC7x5BBMTNKtunoQks9AaXJse4PHvCziRF87A@mail.gmail.com","threadId":"65766","inReplyTo":"xmqqmrx5z0po.fsf@gitster.g","subject":"Re: [PATCH RFC 1/2] builtin/history: abort reword on unchanged message","fromName":"Pablo Sabater","fromEmail":"pabloosabaterr@gmail.com","sentAt":"2026-06-09T10:14:05Z","receivedAt":"2026-06-09T10:14:17Z","isPatch":true,"body":"El lun, 8 jun 2026 a las 14:16, Junio C Hamano (<gitster@pobox.com>) escribió:\n>\n[snip]\n>\n> `git rebase -i` may have an excuse that because it, unlike \"git\n> commit --amend\", operates on multiple commits by design.  A single\n> \"--force\" option given to the command would not have worked as an\n> escape hatch to allow the user to tell the command \"in this reword\n> of this particular commit, I ended up doing nothing, but I still\n> want an updated committer log timestamp\".  Perhaps giving the\n> \"--force\" (or --force-rewrite\") option at \"rebase --continue\" time\n> may work, but in any case, unless we plan to transition to these\n> \"better\" default behaviour at a big version boundary, speculating\n> what a \"better\" behaviour would have been may be fun but not very\n> productive.\n>\n>\n> [Footnote]\n>\n>  *1* Besides, doesn't \"--update-refs\" in \"rebase -i\" allow you to\n>      adjust the branches?\n>\n>  *2* But it is an established behaviour people _rely_ on, so even\n>      though it may have been better if these commands behaved\n>      differently, it probably is a bit too late to change it now.\n>\n>  *3* This includes the case where the original author is especially\n>      difficult to work with and would complain any change to their\n>      commits, even if the only change you made for them is a\n>      typofix.  Fixing a small typo/grammo may not be worth your time\n>      and unpleasant exchanges with them after touching their commit.\n\nTrue, after reading it, history being more costly or the in memory are\nnot good args.\nI do agree that these commands that do reword should check if the\nreword ends up being the same message, given that history is a new\ncommand we can have it from the start so users do not really expect\nother behavior.\nAbout the --force sounds good to me. I could seek to implement it in\nthis series if it's ok.\nThe footnote 3 is indeed a good example haha, but yeah, why rewrite\nthe history unnecessarily.\n\nThanks,\nPablo\n"},{"id":"545055","messageId":"cfaa5636-f722-4217-b49e-e0354f1b80ef@app.fastmail.com","threadId":"65766","inReplyTo":"CAN5EUNRW3gyLKGC7x5BBMTNKtunoQks9AaXJse4PHvCziRF87A@mail.gmail.com","subject":"Re: [PATCH RFC 1/2] builtin/history: abort reword on unchanged message","fromName":"Kristoffer Haugsbakk","fromEmail":"kristofferhaugsbakk@fastmail.com","sentAt":"2026-06-09T10:30:16Z","receivedAt":"2026-06-09T10:30:38Z","isPatch":true,"body":"On Tue, Jun 9, 2026, at 12:14, Pablo Sabater wrote:\n> El lun, 8 jun 2026 a las 14:16, Junio C Hamano (<gitster@pobox.com>) escribió:\n>>\n> [snip]\n>>\n>> `git rebase -i` may have an excuse that because it, unlike \"git\n>> commit --amend\", operates on multiple commits by design.  A single\n>> \"--force\" option given to the command would not have worked as an\n>> escape hatch to allow the user to tell the command \"in this reword\n>> of this particular commit, I ended up doing nothing, but I still\n>> want an updated committer log timestamp\".  Perhaps giving the\n>> \"--force\" (or --force-rewrite\") option at \"rebase --continue\" time\n>> may work, but in any case, unless we plan to transition to these\n>> \"better\" default behaviour at a big version boundary, speculating\n>> what a \"better\" behaviour would have been may be fun but not very\n>> productive.\n>>\n>>\n>> [Footnote]\n>>\n>>  *1* Besides, doesn't \"--update-refs\" in \"rebase -i\" allow you to\n>>      adjust the branches?\n>>\n>>  *2* But it is an established behaviour people _rely_ on, so even\n>>      though it may have been better if these commands behaved\n>>      differently, it probably is a bit too late to change it now.\n>>\n>>  *3* This includes the case where the original author is especially\n>>      difficult to work with and would complain any change to their\n>>      commits, even if the only change you made for them is a\n>>      typofix.  Fixing a small typo/grammo may not be worth your time\n>>      and unpleasant exchanges with them after touching their commit.\n>\n>[snip]\n>\n> About the --force sounds good to me. I could seek to implement it in\n> this series if it's ok.\n\nWhen starting without historical baggage anyway, I have doubts about the\n`--force` name in general. This often just begs me to ask what it is\nforcing. Why not name the thing that is being forced? Verbosity\nshouldn’t be a problem for a “force” option. So `--force-rewrite` if you\nare forcing new commits to be created (like already mentioned).\n\nSee git-clean(1) which has two levels of `--force`.\n\n> The footnote 3 is indeed a good example haha, but yeah, why rewrite\n> the history unnecessarily.\n"},{"id":"545057","messageId":"20260609-ps-history-reword-v2-0-a0e6028ca9b4@gmail.com","threadId":"65766","inReplyTo":"20260607-ps-history-reword-v1-0-ba43a3cbb81b@gmail.com","subject":"[PATCH RFC v2 0/2] builtin/history: abort reword on same message","fromName":"Pablo Sabater","fromEmail":"pabloosabaterr@gmail.com","sentAt":"2026-06-09T10:42:06Z","receivedAt":"2026-06-09T10:42:18Z","isPatch":true,"body":"This short series aims to improve the behavior of `git history reword`\nto abort when the new commit message is the same as the original,\navoiding unnecessary history rewrites.\n\n`git commit --amend` and `git rebase -i` with reword share this flaw but\nchanging them faces not just technical challenges but also breaks what\npeople are used to, so that is not a viable option. Let's take the\nopportunity that `git history` is a new command and handle this\ncorrectly from the start.\n\nThis is made so any other future subcommand or option that does want\nthis behavior just has to add the abort flag.\n\nA questions I have is why don't we want this abort behavior on\n`git history fixup --reedit-message` it makes more sense on\n`git history reword` because if the message is the same then it has\nnothing to do while fixup can still have files to update, but\n--reedit-message is still a redundant option there.\n\nSigned-off-by: Pablo Sabater <pabloosabaterr@gmail.com>\n---\nChanges in v2:\n- Changed the reason on why is this needed.\n- Changed tests with same message to use GIT_EDITOR=true instead of the\n  script.\n- Abort on same message only happens when its own flag is set so no\n  other subcommand that does not want this behavior and depend on\n  commit_tree_ext() is affected.\n- Dropped the feedback on successful reword for another series.\n\n---\nPablo Sabater (2):\n      builtin/history: refactor function signature\n      builtin/history: abort reword on same message\n\n builtin/history.c         | 21 ++++++++++++++++++---\n t/t3451-history-reword.sh | 16 ++++++++++++++++\n t/t3453-history-fixup.sh  | 22 ++++++++++++++++++++++\n 3 files changed, 56 insertions(+), 3 deletions(-)\n---\nbase-commit: 9ac3f193c05c2237e2b14ebaa1149e9fc8a1abe0\nchange-id: 20260607-ps-history-reword-fcb70eaa4aa9\n\nBest regards,\n--  \nPablo Sabater <pabloosabaterr@gmail.com>\n"},{"id":"545058","messageId":"20260609-ps-history-reword-v2-1-a0e6028ca9b4@gmail.com","threadId":"65766","inReplyTo":"20260609-ps-history-reword-v2-0-a0e6028ca9b4@gmail.com","subject":"[PATCH RFC v2 1/2] builtin/history: refactor function signature","fromName":"Pablo Sabater","fromEmail":"pabloosabaterr@gmail.com","sentAt":"2026-06-09T10:42:07Z","receivedAt":"2026-06-09T10:42:19Z","isPatch":true,"body":"commit_tree_with_edited_message() calls commit_tree_ext() with the flag\nCOMMIT_TREE_EDIT_MESSAGE hardcoded and we can't set new flags on callers\nlike cmd_history_reword() to choose their own flags.\n\nThis refactor is needed for a subsequent commit.\n\nRefactor commit_tree_with_edited_message() signature to accept flags\nwhich are passed down to commit_tree_ext() instead of the hardcoded one.\n\nSigned-off-by: Pablo Sabater <pabloosabaterr@gmail.com>\n---\n builtin/history.c | 9 ++++++---\n 1 file changed, 6 insertions(+), 3 deletions(-)\n\ndiff --git a/builtin/history.c b/builtin/history.c\nindex 0fc06fb204..b3e2e5270d 100644\n--- a/builtin/history.c\n+++ b/builtin/history.c\n@@ -160,7 +160,8 @@ static int commit_tree_ext(struct repository *repo,\n static int commit_tree_with_edited_message(struct repository *repo,\n \t\t\t\t\t   const char *action,\n \t\t\t\t\t   struct commit *original,\n-\t\t\t\t\t   struct commit **out)\n+\t\t\t\t\t   struct commit **out,\n+\t\t\t\t\t   enum commit_tree_flags flags)\n {\n \tstruct object_id parent_tree_oid;\n \tconst struct object_id *tree_oid;\n@@ -181,7 +182,7 @@ static int commit_tree_with_edited_message(struct repository *repo,\n \t}\n \n \treturn commit_tree_ext(repo, action, original, original->parents,\n-\t\t\t       &parent_tree_oid, tree_oid, out, COMMIT_TREE_EDIT_MESSAGE);\n+\t\t\t       &parent_tree_oid, tree_oid, out, flags);\n }\n \n enum ref_action {\n@@ -692,6 +693,7 @@ static int cmd_history_reword(int argc,\n \tstruct strbuf reflog_msg = STRBUF_INIT;\n \tstruct commit *original, *rewritten;\n \tstruct rev_info revs = { 0 };\n+\tenum commit_tree_flags flags = COMMIT_TREE_EDIT_MESSAGE;\n \tint ret;\n \n \targc = parse_options(argc, argv, prefix, options, usage, 0);\n@@ -714,7 +716,8 @@ static int cmd_history_reword(int argc,\n \tif (ret)\n \t\tgoto out;\n \n-\tret = commit_tree_with_edited_message(repo, \"reworded\", original, &rewritten);\n+\tret = commit_tree_with_edited_message(repo, \"reworded\", original,\n+\t\t\t\t\t      &rewritten, flags);\n \tif (ret < 0) {\n \t\tret = error(_(\"failed writing reworded commit\"));\n \t\tgoto out;\n\n-- \n2.54.0\n"},{"id":"545059","messageId":"20260609-ps-history-reword-v2-2-a0e6028ca9b4@gmail.com","threadId":"65766","inReplyTo":"20260609-ps-history-reword-v2-0-a0e6028ca9b4@gmail.com","subject":"[PATCH RFC v2 2/2] builtin/history: abort reword on same message","fromName":"Pablo Sabater","fromEmail":"pabloosabaterr@gmail.com","sentAt":"2026-06-09T10:42:08Z","receivedAt":"2026-06-09T10:42:20Z","isPatch":true,"body":"When using `git history reword <commit>` if the new message is the same\nas the original, it continues and rewrites the history when nothing\nchanged.\n\n`git commit --amend` and `git rebase -i` with reword share this behavior\nand it is wrong as well, but changing them breaks what people are used\nto. Take the opportunity of `git history` being a new command and handle\nit correctly from the start.\n\nCreate COMMIT_TREE_ABORT_ON_SAME_MESSAGE and make a check for if the\nmessages are the same and the flag is set so other subcommands like\nfixup that do not want this behavior just don't send the abort flag.\n\nMake commit_tree_ext() return 1 when facing the same message so its\ncallers can choose what to do.\n\nSigned-off-by: Pablo Sabater <pabloosabaterr@gmail.com>\n---\n builtin/history.c         | 14 +++++++++++++-\n t/t3451-history-reword.sh | 16 ++++++++++++++++\n t/t3453-history-fixup.sh  | 22 ++++++++++++++++++++++\n 3 files changed, 51 insertions(+), 1 deletion(-)\n\ndiff --git a/builtin/history.c b/builtin/history.c\nindex b3e2e5270d..be07690da4 100644\n--- a/builtin/history.c\n+++ b/builtin/history.c\n@@ -96,6 +96,7 @@ static int fill_commit_message(struct repository *repo,\n \n enum commit_tree_flags {\n \tCOMMIT_TREE_EDIT_MESSAGE = (1 << 0),\n+\tCOMMIT_TREE_ABORT_ON_SAME_MESSAGE = (1 << 1),\n };\n \n static int commit_tree_ext(struct repository *repo,\n@@ -135,6 +136,13 @@ static int commit_tree_ext(struct repository *repo,\n \t\t\t\t\t  original_body, action, &commit_message);\n \t\tif (ret < 0)\n \t\t\tgoto out;\n+\n+\t\tif (flags & COMMIT_TREE_ABORT_ON_SAME_MESSAGE &&\n+\t\t    !strcmp(original_body, commit_message.buf)) {\n+\t\t\tfprintf(stderr, _(\"Message unchanged, aborting reword.\\n\"));\n+\t\t\tret = 1;\n+\t\t\tgoto out;\n+\t\t}\n \t} else {\n \t\tstrbuf_addstr(&commit_message, original_body);\n \t}\n@@ -693,7 +701,8 @@ static int cmd_history_reword(int argc,\n \tstruct strbuf reflog_msg = STRBUF_INIT;\n \tstruct commit *original, *rewritten;\n \tstruct rev_info revs = { 0 };\n-\tenum commit_tree_flags flags = COMMIT_TREE_EDIT_MESSAGE;\n+\tenum commit_tree_flags flags = COMMIT_TREE_EDIT_MESSAGE |\n+\t\t\t\t       COMMIT_TREE_ABORT_ON_SAME_MESSAGE;\n \tint ret;\n \n \targc = parse_options(argc, argv, prefix, options, usage, 0);\n@@ -721,6 +730,9 @@ static int cmd_history_reword(int argc,\n \tif (ret < 0) {\n \t\tret = error(_(\"failed writing reworded commit\"));\n \t\tgoto out;\n+\t} else if (ret == 1) {\n+\t\tret = 0;\n+\t\tgoto out;\n \t}\n \n \tstrbuf_addf(&reflog_msg, \"reword: updating %s\", argv[0]);\ndiff --git a/t/t3451-history-reword.sh b/t/t3451-history-reword.sh\nindex de7b357685..6e0e278c42 100755\n--- a/t/t3451-history-reword.sh\n+++ b/t/t3451-history-reword.sh\n@@ -396,4 +396,20 @@ test_expect_success 'retains changes in the worktree and index' '\n \t)\n '\n \n+test_expect_success 'aborts if the commit message is the same' '\n+\ttest_when_finished \"rm -rf repo\" &&\n+\tgit init repo &&\n+\t(\n+\t\tcd repo &&\n+\t\ttest_commit first &&\n+\t\ttest_commit second &&\n+\n+\t\tgit rev-parse HEAD >oid-before &&\n+\t\tGIT_EDITOR=true git history reword HEAD 2>err &&\n+\t\tgit rev-parse HEAD >oid-after &&\n+\t\ttest_cmp oid-before oid-after &&\n+\t\ttest_grep \"Message unchanged\" err\n+\t)\n+'\n+\n test_done\ndiff --git a/t/t3453-history-fixup.sh b/t/t3453-history-fixup.sh\nindex 868298e248..9f9a3c93de 100755\n--- a/t/t3453-history-fixup.sh\n+++ b/t/t3453-history-fixup.sh\n@@ -443,6 +443,28 @@ test_expect_success '--reedit-message opens editor for the commit message' '\n \t)\n '\n \n+test_expect_success 'fixup --reedit-message does not abort with the same commit message' '\n+\ttest_when_finished \"rm -rf repo\" &&\n+\tgit init repo &&\n+\t(\n+\t\tcd repo &&\n+\t\ttest_commit initial &&\n+\t\techo content > file.txt &&\n+\t\tgit add file.txt &&\n+\t\tgit commit -m \"add file\" &&\n+\n+\t\techo fix >>file.txt &&\n+\t\tgit add file.txt &&\n+\t\tGIT_EDITOR=true git history fixup --reedit-message HEAD &&\n+\t\texpect_changes --branches <<-\\EOF\n+\t\tadd file\n+\t\t2\t0\tfile.txt\n+\t\tinitial\n+\t\t1\t0\tinitial.t\n+\t\tEOF\n+\t)\n+'\n+\n test_expect_success 'retains unstaged working tree changes after fixup' '\n \ttest_when_finished \"rm -rf repo\" &&\n \tgit init repo &&\n\n-- \n2.54.0\n"},{"id":"545069","messageId":"xmqqtsrbsvcm.fsf@gitster.g","threadId":"65766","inReplyTo":"CAN5EUNRW3gyLKGC7x5BBMTNKtunoQks9AaXJse4PHvCziRF87A@mail.gmail.com","subject":"Re: [PATCH RFC 1/2] builtin/history: abort reword on unchanged message","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-06-09T13:21:13Z","receivedAt":"2026-06-09T13:21:17Z","isPatch":true,"body":"Pablo Sabater <pabloosabaterr@gmail.com> writes:\n\n> True, after reading it, history being more costly or the in memory are\n> not good args.\n\nAnd no argument, including that history is new, is a good excuse to\nmake these three things inconsistent, period.\n\nOne of the patches in your updated iteration claims\n\n    When using `git history reword <commit>` if the new message is the same\n    as the original, it continues and rewrites the history when nothing\n    changed.\n\n    `git commit --amend` and `git rebase -i` with reword share this behavior\n    and it is wrong as well, but changing them breaks what people are used\n    to. Take the opportunity of `git history` being a new command and handle\n    it correctly from the start.\n\nand I think this is a totally wrong attitude to go about this.\n\nI may have said that it may have been a better default to try hard\nto avoid making a change that is a no-op, other than that it changes\ncommitter timestamp, while making the current \"always create a new\ncommit object\" behaviour optionally available, for these three\ncommands, and cited that the behaviour of 'pick' in 'rebase -i' that\navoids unnecessary rewrite as an example of a good practice.\n\nBut I do not think the existing behaviour to always rewrite is\n*wrong* at all.  It may be wrong not to offer the other choice of\npretending no content change means no commit object change, but that\nis a different story.\n\nI also do not think *aborting* only when the message happens to be\nthe same is a valid mode of operation at all.\n\nThe most sensible first step, I think, is to add a new command line\noption to \"git history\" (which will gain more history editing\nsubcommands) that tells the command to leave the original history\nas-is when the only change rewriting commits would make would be to\nthe committer ident or timestamp information.  If in a future a new\nreplace-tree subcommand is added, e.g. if\n\n    $ git history replace-tree HEAD~20 HEAD~27^{tree}\n\nwere a command to rewrite the history in such a way that 20th direct\nancestor of the current HEAD had a tree object HEAD~27^{tree}, by\nderfault the command _should_ rewrite HEAD~10 and everything that\nhas it as an ancestor.  With the \"--avoid-unnecsssary-rewrite\"\noptimization feature on, however, it may silently become a no-op\nwhen HEAD~27^{tree} happened to be the same tree as HEAD~20^{tree}\nso the only difference between rewritten and original HEAD~20 would\nbe when that commit object was created and by whom.\n\nAnd give the same option to \"rebase -i\" or \"commit --amend\".  We can\ndiscuss, educate the users, and flip the default at a major version\nboundary, if the \"avoid unnecessary rewrite\" truly turns out to be a\nbetter default (right now it is merely our speculation, and we do\nnot even know if the current behaviour is a worse default).\n"},{"id":"545072","messageId":"54bd36e9-3d21-4f83-86d6-2882a14779de@gmail.com","threadId":"65766","inReplyTo":"20260609-ps-history-reword-v2-2-a0e6028ca9b4@gmail.com","subject":"Re: [PATCH RFC v2 2/2] builtin/history: abort reword on same message","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2026-06-09T13:25:39Z","receivedAt":"2026-06-09T13:25:43Z","isPatch":true,"body":"Hi Pablo\n\nOn 09/06/2026 11:42, Pablo Sabater wrote:\n>   static int commit_tree_ext(struct repository *repo,\n> @@ -135,6 +136,13 @@ static int commit_tree_ext(struct repository *repo,\n>   \t\t\t\t\t  original_body, action, &commit_message);\n>   \t\tif (ret < 0)\n>   \t\t\tgoto out;\n> +\n> +\t\tif (flags & COMMIT_TREE_ABORT_ON_SAME_MESSAGE &&\n> +\t\t    !strcmp(original_body, commit_message.buf)) {\n> +\t\t\tfprintf(stderr, _(\"Message unchanged, aborting reword.\\n\"));\n> +\t\t\tret = 1;\n> +\t\t\tgoto out;\n> +\t\t}\n\nI wonder if we should check that the committer identity is unchanged as \nwell in case anyone is using this to fix commits after committing with \nthe wrong identity.\n\nAborting when the message and committer identity are unchanged seems \nlike a good idea.\n\nThanks\n\nPhillip\n\n>   \t} else {\n>   \t\tstrbuf_addstr(&commit_message, original_body);\n>   \t}\n> @@ -693,7 +701,8 @@ static int cmd_history_reword(int argc,\n>   \tstruct strbuf reflog_msg = STRBUF_INIT;\n>   \tstruct commit *original, *rewritten;\n>   \tstruct rev_info revs = { 0 };\n> -\tenum commit_tree_flags flags = COMMIT_TREE_EDIT_MESSAGE;\n> +\tenum commit_tree_flags flags = COMMIT_TREE_EDIT_MESSAGE |\n> +\t\t\t\t       COMMIT_TREE_ABORT_ON_SAME_MESSAGE;\n>   \tint ret;\n>   \n>   \targc = parse_options(argc, argv, prefix, options, usage, 0);\n> @@ -721,6 +730,9 @@ static int cmd_history_reword(int argc,\n>   \tif (ret < 0) {\n>   \t\tret = error(_(\"failed writing reworded commit\"));\n>   \t\tgoto out;\n> +\t} else if (ret == 1) {\n> +\t\tret = 0;\n> +\t\tgoto out;\n>   \t}\n>   \n>   \tstrbuf_addf(&reflog_msg, \"reword: updating %s\", argv[0]);\n> diff --git a/t/t3451-history-reword.sh b/t/t3451-history-reword.sh\n> index de7b357685..6e0e278c42 100755\n> --- a/t/t3451-history-reword.sh\n> +++ b/t/t3451-history-reword.sh\n> @@ -396,4 +396,20 @@ test_expect_success 'retains changes in the worktree and index' '\n>   \t)\n>   '\n>   \n> +test_expect_success 'aborts if the commit message is the same' '\n> +\ttest_when_finished \"rm -rf repo\" &&\n> +\tgit init repo &&\n> +\t(\n> +\t\tcd repo &&\n> +\t\ttest_commit first &&\n> +\t\ttest_commit second &&\n> +\n> +\t\tgit rev-parse HEAD >oid-before &&\n> +\t\tGIT_EDITOR=true git history reword HEAD 2>err &&\n> +\t\tgit rev-parse HEAD >oid-after &&\n> +\t\ttest_cmp oid-before oid-after &&\n> +\t\ttest_grep \"Message unchanged\" err\n> +\t)\n> +'\n> +\n>   test_done\n> diff --git a/t/t3453-history-fixup.sh b/t/t3453-history-fixup.sh\n> index 868298e248..9f9a3c93de 100755\n> --- a/t/t3453-history-fixup.sh\n> +++ b/t/t3453-history-fixup.sh\n> @@ -443,6 +443,28 @@ test_expect_success '--reedit-message opens editor for the commit message' '\n>   \t)\n>   '\n>   \n> +test_expect_success 'fixup --reedit-message does not abort with the same commit message' '\n> +\ttest_when_finished \"rm -rf repo\" &&\n> +\tgit init repo &&\n> +\t(\n> +\t\tcd repo &&\n> +\t\ttest_commit initial &&\n> +\t\techo content > file.txt &&\n> +\t\tgit add file.txt &&\n> +\t\tgit commit -m \"add file\" &&\n> +\n> +\t\techo fix >>file.txt &&\n> +\t\tgit add file.txt &&\n> +\t\tGIT_EDITOR=true git history fixup --reedit-message HEAD &&\n> +\t\texpect_changes --branches <<-\\EOF\n> +\t\tadd file\n> +\t\t2\t0\tfile.txt\n> +\t\tinitial\n> +\t\t1\t0\tinitial.t\n> +\t\tEOF\n> +\t)\n> +'\n> +\n>   test_expect_success 'retains unstaged working tree changes after fixup' '\n>   \ttest_when_finished \"rm -rf repo\" &&\n>   \tgit init repo &&\n> \n\n"},{"id":"545080","messageId":"CAN5EUNSuuz61pxEk1ZK8RAr0HOtt1f-_mCRpm7RBwoHAcgVAOA@mail.gmail.com","threadId":"65766","inReplyTo":"xmqqtsrbsvcm.fsf@gitster.g","subject":"Re: [PATCH RFC 1/2] builtin/history: abort reword on unchanged message","fromName":"Pablo Sabater","fromEmail":"pabloosabaterr@gmail.com","sentAt":"2026-06-09T15:51:51Z","receivedAt":"2026-06-09T15:52:03Z","isPatch":true,"body":"El mar, 9 jun 2026 a las 15:21, Junio C Hamano (<gitster@pobox.com>) escribió:\n>\n> Pablo Sabater <pabloosabaterr@gmail.com> writes:\n>\n> > True, after reading it, history being more costly or the in memory are\n> > not good args.\n>\n> And no argument, including that history is new, is a good excuse to\n> make these three things inconsistent, period.\n>\n> One of the patches in your updated iteration claims\n>\n>     When using `git history reword <commit>` if the new message is the same\n>     as the original, it continues and rewrites the history when nothing\n>     changed.\n>\n>     `git commit --amend` and `git rebase -i` with reword share this behavior\n>     and it is wrong as well, but changing them breaks what people are used\n>     to. Take the opportunity of `git history` being a new command and handle\n>     it correctly from the start.\n>\n> and I think this is a totally wrong attitude to go about this.\n>\n> I may have said that it may have been a better default to try hard\n> to avoid making a change that is a no-op, other than that it changes\n> committer timestamp, while making the current \"always create a new\n> commit object\" behaviour optionally available, for these three\n> commands, and cited that the behaviour of 'pick' in 'rebase -i' that\n> avoids unnecessary rewrite as an example of a good practice.\n>\n> But I do not think the existing behaviour to always rewrite is\n> *wrong* at all.  It may be wrong not to offer the other choice of\n> pretending no content change means no commit object change, but that\n> is a different story.\n>\n> I also do not think *aborting* only when the message happens to be\n> the same is a valid mode of operation at all.\n>\n> The most sensible first step, I think, is to add a new command line\n> option to \"git history\" (which will gain more history editing\n> subcommands) that tells the command to leave the original history\n> as-is when the only change rewriting commits would make would be to\n> the committer ident or timestamp information.  If in a future a new\n> replace-tree subcommand is added, e.g. if\n>\n>     $ git history replace-tree HEAD~20 HEAD~27^{tree}\n>\n> were a command to rewrite the history in such a way that 20th direct\n> ancestor of the current HEAD had a tree object HEAD~27^{tree}, by\n> derfault the command _should_ rewrite HEAD~10 and everything that\n> has it as an ancestor.  With the \"--avoid-unnecsssary-rewrite\"\n> optimization feature on, however, it may silently become a no-op\n> when HEAD~27^{tree} happened to be the same tree as HEAD~20^{tree}\n> so the only difference between rewritten and original HEAD~20 would\n> be when that commit object was created and by whom.\n>\n> And give the same option to \"rebase -i\" or \"commit --amend\".  We can\n> discuss, educate the users, and flip the default at a major version\n> boundary, if the \"avoid unnecessary rewrite\" truly turns out to be a\n> better default (right now it is merely our speculation, and we do\n> not even know if the current behaviour is a worse default).\n\nHi Junio,\n\nSorry about how I expressed myself. I didn't mean by wrong to be bad\nor anything similar, I just noticed this when testing `git history\nreword` and thought that I would like it this other way.\n\nSaying that git history is new or I would like this to be different\nare not good arguments to have `git history` inconsistent with other\ncommands.\n\nMy idea was more of a defensive thing, where you would need a\n\"--force-rewrite\" opt to explicitly change timestamps. But I see the\npoint of having it in an `--avoid-unnecessary-rewrite` so without\noptions it has the same behavior as other commands.\n\nI'll try to express myself better in the next version and go with the\nopt direction.\n\nSorry again,\nPablo\n"},{"id":"545081","messageId":"xmqq4ijbsn2m.fsf@gitster.g","threadId":"65766","inReplyTo":"54bd36e9-3d21-4f83-86d6-2882a14779de@gmail.com","subject":"Re: [PATCH RFC v2 2/2] builtin/history: abort reword on same message","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-06-09T16:20:01Z","receivedAt":"2026-06-09T16:20:08Z","isPatch":true,"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n> Hi Pablo\n>\n> On 09/06/2026 11:42, Pablo Sabater wrote:\n>>   static int commit_tree_ext(struct repository *repo,\n>> @@ -135,6 +136,13 @@ static int commit_tree_ext(struct repository *repo,\n>>   \t\t\t\t\t  original_body, action, &commit_message);\n>>   \t\tif (ret < 0)\n>>   \t\t\tgoto out;\n>> +\n>> +\t\tif (flags & COMMIT_TREE_ABORT_ON_SAME_MESSAGE &&\n>> +\t\t    !strcmp(original_body, commit_message.buf)) {\n>> +\t\t\tfprintf(stderr, _(\"Message unchanged, aborting reword.\\n\"));\n>> +\t\t\tret = 1;\n>> +\t\t\tgoto out;\n>> +\t\t}\n>\n> I wonder if we should check that the committer identity is unchanged as \n> well in case anyone is using this to fix commits after committing with \n> the wrong identity.\n>\n> Aborting when the message and committer identity are unchanged seems \n> like a good idea.\n\nI am not sure why it would be a good idea.  The user wanted to make\nthe commit have this message, and the commit ended up having the\nsame message as the user gave.  That message may have been identical\nto what the commit originally had, or it may be different.  Why is\nthe former an abort-worthy event?  A simple note, I may understand,\nbut aborting with an error message?\n\nThanks.\n"},{"id":"545082","messageId":"CAN5EUNRz9F+njb_O=Q4DzVMec-q+rDf83Ow+MPJE4yLCBq9qww@mail.gmail.com","threadId":"65766","inReplyTo":"xmqq4ijbsn2m.fsf@gitster.g","subject":"Re: [PATCH RFC v2 2/2] builtin/history: abort reword on same message","fromName":"Pablo Sabater","fromEmail":"pabloosabaterr@gmail.com","sentAt":"2026-06-09T17:12:17Z","receivedAt":"2026-06-09T17:12:29Z","isPatch":true,"body":"El mar, 9 jun 2026 a las 18:20, Junio C Hamano (<gitster@pobox.com>) escribió:\n>\n> Phillip Wood <phillip.wood123@gmail.com> writes:\n>\n> > Hi Pablo\n> >\n> > On 09/06/2026 11:42, Pablo Sabater wrote:\n> >>   static int commit_tree_ext(struct repository *repo,\n> >> @@ -135,6 +136,13 @@ static int commit_tree_ext(struct repository *repo,\n> >>                                        original_body, action, &commit_message);\n> >>              if (ret < 0)\n> >>                      goto out;\n> >> +\n> >> +            if (flags & COMMIT_TREE_ABORT_ON_SAME_MESSAGE &&\n> >> +                !strcmp(original_body, commit_message.buf)) {\n> >> +                    fprintf(stderr, _(\"Message unchanged, aborting reword.\\n\"));\n> >> +                    ret = 1;\n> >> +                    goto out;\n> >> +            }\n> >\n> > I wonder if we should check that the committer identity is unchanged as\n> > well in case anyone is using this to fix commits after committing with\n> > the wrong identity.\n\nI think that if you reword a commit committed by someone else but end\nup with no changes I want it to be kept as it was.\n\n> >\n> > Aborting when the message and committer identity are unchanged seems\n> > like a good idea.\n>\n> I am not sure why it would be a good idea.  The user wanted to make\n> the commit have this message, and the commit ended up having the\n> same message as the user gave.  That message may have been identical\n> to what the commit originally had, or it may be different.  Why is\n> the former an abort-worthy event?  A simple note, I may understand,\n> but aborting with an error message?\n\nWith what you said at [1], having this in an\n\"--avoid-unnecessary-rewrite\" I think that the abort might be too much\nas with the flag the user already expects this to happen and silent\nmight be better.\n\nBy the way, I feel that \"--avoid-unnecessary-rewrite\" is too long,\ncould it be something shorter? If not it could be set \"-r\" as the\nshort and leave the long as it is.\n\n>\n> Thanks.\n\n[1]: https://lore.kernel.org/git/xmqqtsrbsvcm.fsf@gitster.g/\n\nThanks,\nPablo\n"},{"id":"545087","messageId":"aihH8ye-r4QuXlRD@denethor","threadId":"65766","inReplyTo":"xmqq4ijbsn2m.fsf@gitster.g","subject":"Re: [PATCH RFC v2 2/2] builtin/history: abort reword on same message","fromName":"Justin Tobler","fromEmail":"jltobler@gmail.com","sentAt":"2026-06-09T18:02:15Z","receivedAt":"2026-06-09T18:02:20Z","isPatch":true,"body":"On 26/06/09 09:20AM, Junio C Hamano wrote:\n> Phillip Wood <phillip.wood123@gmail.com> writes:\n> \n> > Hi Pablo\n> >\n> > On 09/06/2026 11:42, Pablo Sabater wrote:\n> >>   static int commit_tree_ext(struct repository *repo,\n> >> @@ -135,6 +136,13 @@ static int commit_tree_ext(struct repository *repo,\n> >>   \t\t\t\t\t  original_body, action, &commit_message);\n> >>   \t\tif (ret < 0)\n> >>   \t\t\tgoto out;\n> >> +\n> >> +\t\tif (flags & COMMIT_TREE_ABORT_ON_SAME_MESSAGE &&\n> >> +\t\t    !strcmp(original_body, commit_message.buf)) {\n> >> +\t\t\tfprintf(stderr, _(\"Message unchanged, aborting reword.\\n\"));\n> >> +\t\t\tret = 1;\n> >> +\t\t\tgoto out;\n> >> +\t\t}\n> >\n> > I wonder if we should check that the committer identity is unchanged as \n> > well in case anyone is using this to fix commits after committing with \n> > the wrong identity.\n> >\n> > Aborting when the message and committer identity are unchanged seems \n> > like a good idea.\n> \n> I am not sure why it would be a good idea.  The user wanted to make\n> the commit have this message, and the commit ended up having the\n> same message as the user gave.  That message may have been identical\n> to what the commit originally had, or it may be different.  Why is\n> the former an abort-worthy event?  A simple note, I may understand,\n> but aborting with an error message?\n\nI can see a situation where a user performs:\n\n  git history reword abcd1234\n\nwith the intention to modify a commit message, but then for some reason\nchanges their mind and doesn't want history to change. Maybe the wrong\ncommit was referenced, or they decide the current message is actually\nfine. From my understanding, there isn't a great way to abort rewording\na commit during editing and thus the user would have to reset history\nafterwards if they care enough to go back to the previous point.\n\nSo I do see some value in a mechanism to abort rewriting a commit\nmessage. An unchanged commit message does seem like a reasonable signal\nto essentially abort the reword. I'm not sure committer identity should\nbe taken into consideration though since it would inhibit a users\nability to abort the reword if they ever touch a commit that they\nthemselves are not the previous committer. \n\nI don't think there is a need to have an error message though. Even in\nthe case where the user leaves the commit message unchanged and history\nis left untouched, git-history(1) would be following exactly what the\nuser instructed it to do. I don't really see why the user should care\nwhether history was actually modified or not in such a scenario.\n\n-Justin\n"},{"id":"545089","messageId":"xmqqbjdj1q1s.fsf@gitster.g","threadId":"65766","inReplyTo":"CAN5EUNRz9F+njb_O=Q4DzVMec-q+rDf83Ow+MPJE4yLCBq9qww@mail.gmail.com","subject":"Re: [PATCH RFC v2 2/2] builtin/history: abort reword on same message","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-06-09T19:17:51Z","receivedAt":"2026-06-09T19:17:54Z","isPatch":true,"body":"Pablo Sabater <pabloosabaterr@gmail.com> writes:\n\n>> > I wonder if we should check that the committer identity is unchanged as\n>> > well in case anyone is using this to fix commits after committing with\n>> > the wrong identity.\n>\n> I think that if you reword a commit committed by someone else but end\n> up with no changes I want it to be kept as it was.\n\nThat depends on the reason why the feature to \"reword\" the commit is\nbeing used, and the use case Phillip is talking about is a bit\ndifferent.\n\nA very common mistake a new user makes when starting a repository is\nto make commits before they realize that they used a wrong identity\nto create them.  They are happy with what they committed, except\nthat they want these commits to be attributed to user.{name,email}\nthey corrected.\n\nAlso, people often use multiple identities (e.g., corp vs personal),\nand when making commits to the project for their employer they do\nnot want to use their personal identity (and vice versa).  After\nmaking a mistake to create commits under wrong identity, they want\nto fix these commits.\n\nIn such situations, there is no room for leaving the committer name\nas \"someone else\".  The user wants to get rid of the \"someone else\"s\nidentity out of these commits.\n\n\n"},{"id":"545091","messageId":"xmqq5x3r1ph0.fsf@gitster.g","threadId":"65766","inReplyTo":"aihH8ye-r4QuXlRD@denethor","subject":"Re: [PATCH RFC v2 2/2] builtin/history: abort reword on same message","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-06-09T19:30:19Z","receivedAt":"2026-06-09T19:30:22Z","isPatch":true,"body":"Justin Tobler <jltobler@gmail.com> writes:\n\n> I can see a situation where a user performs:\n>\n>   git history reword abcd1234\n>\n> with the intention to modify a commit message, but then for some reason\n> changes their mind and doesn't want history to change. Maybe the wrong\n> commit was referenced, or they decide the current message is actually\n> fine. From my understanding, there isn't a great way to abort rewording\n> a commit during editing and thus the user would have to reset history\n> afterwards if they care enough to go back to the previous point.\n>\n> So I do see some value in a mechanism to abort rewriting a commit\n> message.\n\nI think we are saying the same thing in different ways.  I want to\nsee that command \"succeed\" either case (normally we create a new\ncommit object because we record an updated committer timestamp, but\nif there is no need to create a new commit object only to record an\nupdated committer timestamp, we may choose not to and leave the\nhistory intact) and I do not want it to *abort*.\n\nThe mechanism to do so may be exactly the same, i.e., accept an\nupdated log message, then try to \"hash-object\" (without -w) the\ncommit object with everything, except for the updated commit log\nmessage, taken from the original commit, plus the updated log\nmessage.  And if the resulting hash is the same as the original, do\nnot do anything further and return happily.  Aborting sounds more\nlike complaining loudly \"baa, you asked me to reword but you gave me\nthe same message? is anything wrong with you?\" with non-zero exit\nstatus, which I think the user does not deserve in such a case.\n"},{"id":"545092","messageId":"aihwS9aQ1b_8q_5u@denethor","threadId":"65766","inReplyTo":"xmqq5x3r1ph0.fsf@gitster.g","subject":"Re: [PATCH RFC v2 2/2] builtin/history: abort reword on same message","fromName":"Justin Tobler","fromEmail":"jltobler@gmail.com","sentAt":"2026-06-09T20:14:24Z","receivedAt":"2026-06-09T20:14:29Z","isPatch":true,"body":"On 26/06/09 12:30PM, Junio C Hamano wrote:\n> Justin Tobler <jltobler@gmail.com> writes:\n> \n> > I can see a situation where a user performs:\n> >\n> >   git history reword abcd1234\n> >\n> > with the intention to modify a commit message, but then for some reason\n> > changes their mind and doesn't want history to change. Maybe the wrong\n> > commit was referenced, or they decide the current message is actually\n> > fine. From my understanding, there isn't a great way to abort rewording\n> > a commit during editing and thus the user would have to reset history\n> > afterwards if they care enough to go back to the previous point.\n> >\n> > So I do see some value in a mechanism to abort rewriting a commit\n> > message.\n> \n> I think we are saying the same thing in different ways.  I want to\n> see that command \"succeed\" either case (normally we create a new\n> commit object because we record an updated committer timestamp, but\n> if there is no need to create a new commit object only to record an\n> updated committer timestamp, we may choose not to and leave the\n> history intact) and I do not want it to *abort*.\n> \n> The mechanism to do so may be exactly the same, i.e., accept an\n> updated log message, then try to \"hash-object\" (without -w) the\n> commit object with everything, except for the updated commit log\n> message, taken from the original commit, plus the updated log\n> message.  And if the resulting hash is the same as the original, do\n> not do anything further and return happily.  Aborting sounds more\n> like complaining loudly \"baa, you asked me to reword but you gave me\n> the same message? is anything wrong with you?\" with non-zero exit\n> status, which I think the user does not deserve in such a case.\n\nYes, I completely agree. If the user doesn't update the commit message,\nfor whatever reason, that should still be considered a success since it\nfollows the user's intent. I don't think it makes sense to exit with a\nnon-zero code in such cases. I would also question if we should print\nany message/note to the user at all for the same reasons.\n\n-Justin\n"},{"id":"545106","messageId":"aikMLBCC9Rc7q9S7@pks.im","threadId":"65766","inReplyTo":"xmqqbjdj1q1s.fsf@gitster.g","subject":"Re: [PATCH RFC v2 2/2] builtin/history: abort reword on same message","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-06-10T07:03:08Z","receivedAt":"2026-06-10T07:03:14Z","isPatch":true,"body":"On Tue, Jun 09, 2026 at 12:17:51PM -0700, Junio C Hamano wrote:\n> Pablo Sabater <pabloosabaterr@gmail.com> writes:\n> \n> >> > I wonder if we should check that the committer identity is unchanged as\n> >> > well in case anyone is using this to fix commits after committing with\n> >> > the wrong identity.\n> >\n> > I think that if you reword a commit committed by someone else but end\n> > up with no changes I want it to be kept as it was.\n> \n> That depends on the reason why the feature to \"reword\" the commit is\n> being used, and the use case Phillip is talking about is a bit\n> different.\n\nSo the answer is \"it depends\". Maybe we should do handle this the same\nas git-commit(1) does with its \"--reset-author\" flag?\n\nPatrick\n"},{"id":"545121","messageId":"56beb82a-9d6b-45d9-b795-c66e945c03db@gmail.com","threadId":"65766","inReplyTo":"xmqq4ijbsn2m.fsf@gitster.g","subject":"Re: [PATCH RFC v2 2/2] builtin/history: abort reword on same message","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2026-06-10T09:24:02Z","receivedAt":"2026-06-10T09:24:07Z","isPatch":true,"body":"On 09/06/2026 17:20, Junio C Hamano wrote:\n> Phillip Wood <phillip.wood123@gmail.com> writes:\n> \n>> Hi Pablo\n>>\n>> On 09/06/2026 11:42, Pablo Sabater wrote:\n>>>    static int commit_tree_ext(struct repository *repo,\n>>> @@ -135,6 +136,13 @@ static int commit_tree_ext(struct repository *repo,\n>>>    \t\t\t\t\t  original_body, action, &commit_message);\n>>>    \t\tif (ret < 0)\n>>>    \t\t\tgoto out;\n>>> +\n>>> +\t\tif (flags & COMMIT_TREE_ABORT_ON_SAME_MESSAGE &&\n>>> +\t\t    !strcmp(original_body, commit_message.buf)) {\n>>> +\t\t\tfprintf(stderr, _(\"Message unchanged, aborting reword.\\n\"));\n>>> +\t\t\tret = 1;\n>>> +\t\t\tgoto out;\n>>> +\t\t}\n>>\n>> I wonder if we should check that the committer identity is unchanged as\n>> well in case anyone is using this to fix commits after committing with\n>> the wrong identity.\n>>\n>> Aborting when the message and committer identity are unchanged seems\n>> like a good idea.\n> \n> I am not sure why it would be a good idea.  The user wanted to make\n> the commit have this message, and the commit ended up having the\n> same message as the user gave.  That message may have been identical\n> to what the commit originally had, or it may be different.  Why is\n> the former an abort-worthy event?  A simple note, I may understand,\n> but aborting with an error message?\n\nWhat I really meant was skipping rewriting history makes sense, I don't \nhave a strong opinion on the exit code. My feeling is that some kind of \nmessage saying we haven't rewritten anything probably a good idea.\n\nThanks\n\nPhillip\n\n"},{"id":"545122","messageId":"e033b216-d8e7-4c16-8fb5-0455125b71a3@gmail.com","threadId":"65766","inReplyTo":"aikMLBCC9Rc7q9S7@pks.im","subject":"Re: [PATCH RFC v2 2/2] builtin/history: abort reword on same message","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2026-06-10T09:33:56Z","receivedAt":"2026-06-10T09:34:02Z","isPatch":true,"body":"Hi Patrick\n\nOn 10/06/2026 08:03, Patrick Steinhardt wrote:\n> On Tue, Jun 09, 2026 at 12:17:51PM -0700, Junio C Hamano wrote:\n>> Pablo Sabater <pabloosabaterr@gmail.com> writes:\n>>\n>>>>> I wonder if we should check that the committer identity is unchanged as\n>>>>> well in case anyone is using this to fix commits after committing with\n>>>>> the wrong identity.\n>>>\n>>> I think that if you reword a commit committed by someone else but end\n>>> up with no changes I want it to be kept as it was.\n>>\n>> That depends on the reason why the feature to \"reword\" the commit is\n>> being used, and the use case Phillip is talking about is a bit\n>> different.\n> \n> So the answer is \"it depends\". Maybe we should do handle this the same\n> as git-commit(1) does with its \"--reset-author\" flag?\n\nFor the case I was talking about we'd want to reset the committer but I \nagree that making \"reset the committer\" explicit and just comparing the \nold and new messages when deciding whether to skip rewriting is a good \nway forward.\n\nThanks\n\nPhillip\n\n"},{"id":"545169","messageId":"xmqq33yuxu1x.fsf@gitster.g","threadId":"65766","inReplyTo":"aikMLBCC9Rc7q9S7@pks.im","subject":"Re: [PATCH RFC v2 2/2] builtin/history: abort reword on same message","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-06-10T16:02:34Z","receivedAt":"2026-06-10T16:02:37Z","isPatch":true,"body":"Patrick Steinhardt <ps@pks.im> writes:\n\n> On Tue, Jun 09, 2026 at 12:17:51PM -0700, Junio C Hamano wrote:\n>> Pablo Sabater <pabloosabaterr@gmail.com> writes:\n>> \n>> >> > I wonder if we should check that the committer identity is unchanged as\n>> >> > well in case anyone is using this to fix commits after committing with\n>> >> > the wrong identity.\n>> >\n>> > I think that if you reword a commit committed by someone else but end\n>> > up with no changes I want it to be kept as it was.\n>> \n>> That depends on the reason why the feature to \"reword\" the commit is\n>> being used, and the use case Phillip is talking about is a bit\n>> different.\n>\n> So the answer is \"it depends\". Maybe we should do handle this the same\n> as git-commit(1) does with its \"--reset-author\" flag?\n\nInteresting.  I was mostly focusing on the committer identity, but\nthe same argument of courese also applies to the author identity.\n\nHaving said that, if the user who used to commit others' patches\nunder a wrong identity (i.e., the only thing incorrect about these\ncommits is the committer identity, and author identity of them are\nnot to be updated), \"--reset-author\" would not be usable, as they\nwant to keep the authorship information recorded.  I think \n\n (1) in the shorter term, always create a new commit by default even\n     if the only difference were the committer timestamp.  But add a\n     mechanism to allow users to tell the tool to skip the update\n     in such a case.\n\n (2) at a big version bump, flip the default, making the \"always\n     create a new commit\" an optional feature.\n\nwould be the way to go, and the way to trigger that mechanism needs\nto be separate from \"--reset-author\".\n\nThanks.\n"},{"id":"547293","messageId":"akyKDtuHTHZGEpFx@codewreck.org","threadId":"65766","inReplyTo":"9C91B027-C24A-4D7B-A3BC-5CF3B04D990C@gmail.com","subject":"Re: [PATCH RFC 2/2] builtin/history: print feedback after successful reword","fromName":"Dominique Martinet","fromEmail":"asmadeus@codewreck.org","sentAt":"2026-07-07T05:09:34Z","receivedAt":"2026-07-07T05:10:01Z","isPatch":true,"body":"[context: I just played with git history reword/fixup and dug through\narchives for anything like this, so chiming in.\nFirst, thanks for the new git history commands, they all look promising!]\n\nBen Knoble wrote on Mon, Jun 08, 2026 at 12:47:41PM -0400:\n>>> Do other commands in \"git history\" (split is in 'master', drop and\n>>> fixup are cooking) behave with similar verbosity?  Consistency within\n>>> the same \"history\" umbrella matters more than being similar with\n>>> other commands that can be used for similar purposes.\n\nI agree with the sentiment of needing consistency, but rather than say\n\"the other commands are not verbose\" (as they are) I'd say they're new\nenough we can afford to \"make them all verbose\" instead.\n\nIn particular, for git history reword there is an editor opening up, so\nI didn't have much trouble assuming silence was success, but I was\ndisturbed by `git history fixup` which just returns immediately (much\nfaster than rebase) with no feedback at all.\n\n>> They do not, they are thought with the rule of silence in mind.\n>> However I think that this output is valuable information I might have\n>> explained myself better at [1] but my thought is:\n>> \n>> git history reword aabb\n>> \n>> Now that I have my commit aabb rewritten I want to check it again just\n>> to make sure I did what I wanted correctly,\n>\n> Some thoughts:\n> \n> - If the rewritten commit is an ancestor of HEAD, look at the log of HEAD@{1} or the log between HEAD and the aforementioned reflog entry. (git-range-diff may also be helpful there.)\n> - Similarly, if the rewritten commit is reachable from some ref R, check R@{1} etc. \n\nDuring my quick tests I was surprised with how git history reword/fixup\nbehave with commits that aren't ancestors of HEAD/any branch (that can\nhappen for example if you print `git log --oneline` once and refer to it\nafter editing.\n\nThis transcript is a bit ugly but should illustrate the issue:\n```\n$ git init\nInitialized empty Git repository in ...test/.git/\n$ echo a > aa\n$ git add aa\n$ git commit -m init\n[master (root-commit) 62884dc4d43c] init\n 1 file changed, 1 insertion(+)\n create mode 100644 aa\n$ echo b > b\n$ git add b\n$ git commit -m b\n[master 058294f87a36] b\n 1 file changed, 1 insertion(+)\n create mode 100644 b\n$ echo c > c\n$ git add c\n$ git commit -m c\n[master 0c4ad0c9337c] c\n 1 file changed, 1 insertion(+)\n create mode 100644 c\n$ git log --oneline --graph\n* 0c4ad0c9337c (HEAD -> master) c\n* 058294f87a36 b\n* 62884dc4d43c init\n$ echo d > d\n$ git add d\n$ git history fixup HEAD^\n$ echo e > e\n$ git add e\n$ git history fixup 058294f87a36\n$ git status\nOn branch master\nChanges to be committed:\n  (use \"git restore --staged <file>...\" to unstage)\n\tnew file:   e\n$ git history reword 058294f87a36\n(editor showed up, commit message modified and saved)\n$ git log --oneline --graph\n* 5cc5551381a3 (HEAD -> master) c\n* 0b7ab36bf167 b\n* 62884dc4d43c init\n```\n-> fixup didn't show any message (and exited with 0), but didn't unstage\nthe hunk either and didn't do anything, so one cannot differentiate with\nthe fixup actually happening\n-> reword showed up editor but didn't actually do anything visible\n(probably did create a new commit somewhere that's unreachable?)\n\nSo I agree with Pablo's suggestion: printing old/new short hash on\nsuccess would help visualy confirming something worked.\n\n... But it might be worth to ensure that the commit has any ref we can\nhandle (if --update-refs is set then the commit we edit is ancestor to\nsome branch, if not set then it must be an ancestor of HEAD)\n\nWhat do you think?\n-- \nDominique Martinet | Asmadeus\n"},{"id":"547357","messageId":"CALnO6CAjZfK3hPWn1vOxgw=4=cjRYEHabYJmJrpVVDU8yyQn_g@mail.gmail.com","threadId":"65766","inReplyTo":"akyKDtuHTHZGEpFx@codewreck.org","subject":"Re: [PATCH RFC 2/2] builtin/history: print feedback after successful reword","fromName":"D. Ben Knoble","fromEmail":"ben.knoble@gmail.com","sentAt":"2026-07-07T16:10:12Z","receivedAt":"2026-07-07T16:10:24Z","isPatch":true,"body":"On Tue, Jul 7, 2026 at 1:09 AM Dominique Martinet\n<asmadeus@codewreck.org> wrote:\n>\n> [context: I just played with git history reword/fixup and dug through\n> archives for anything like this, so chiming in.\n> First, thanks for the new git history commands, they all look promising!]\n>\n> Ben Knoble wrote on Mon, Jun 08, 2026 at 12:47:41PM -0400:\n[snip]\n> >> They do not, they are thought with the rule of silence in mind.\n> >> However I think that this output is valuable information I might have\n> >> explained myself better at [1] but my thought is:\n> >>\n> >> git history reword aabb\n> >>\n> >> Now that I have my commit aabb rewritten I want to check it again just\n> >> to make sure I did what I wanted correctly,\n> >\n> > Some thoughts:\n> >\n> > - If the rewritten commit is an ancestor of HEAD, look at the log of HEAD@{1} or the log between HEAD and the aforementioned reflog entry. (git-range-diff may also be helpful there.)\n> > - Similarly, if the rewritten commit is reachable from some ref R, check R@{1} etc.\n>\n> During my quick tests I was surprised with how git history reword/fixup\n> behave with commits that aren't ancestors of HEAD/any branch (that can\n> happen for example if you print `git log --oneline` once and refer to it\n> after editing.\n\nIndeed, this is a bit of a \"trap\":\n\n> This transcript is a bit ugly but should illustrate the issue:\n> ```\n> $ git init\n> Initialized empty Git repository in ...test/.git/\n> $ echo a > aa\n> $ git add aa\n> $ git commit -m init\n> [master (root-commit) 62884dc4d43c] init\n>  1 file changed, 1 insertion(+)\n>  create mode 100644 aa\n> $ echo b > b\n> $ git add b\n> $ git commit -m b\n> [master 058294f87a36] b\n>  1 file changed, 1 insertion(+)\n>  create mode 100644 b\n> $ echo c > c\n> $ git add c\n> $ git commit -m c\n> [master 0c4ad0c9337c] c\n>  1 file changed, 1 insertion(+)\n>  create mode 100644 c\n> $ git log --oneline --graph\n> * 0c4ad0c9337c (HEAD -> master) c\n> * 058294f87a36 b\n> * 62884dc4d43c init\n> $ echo d > d\n> $ git add d\n> $ git history fixup HEAD^\n> $ echo e > e\n> $ git add e\n> $ git history fixup 058294f87a36\n> $ git status\n> On branch master\n> Changes to be committed:\n>   (use \"git restore --staged <file>...\" to unstage)\n>         new file:   e\n> $ git history reword 058294f87a36\n> (editor showed up, commit message modified and saved)\n> $ git log --oneline --graph\n> * 5cc5551381a3 (HEAD -> master) c\n> * 0b7ab36bf167 b\n> * 62884dc4d43c init\n> ```\n> -> fixup didn't show any message (and exited with 0), but didn't unstage\n> the hunk either and didn't do anything, so one cannot differentiate with\n> the fixup actually happening\n> -> reword showed up editor but didn't actually do anything visible\n> (probably did create a new commit somewhere that's unreachable?)\n\nI think what probably happened here (and what you might find with `git\nfsck` for example) is that you have new commit objects in chains\ncorresponding to those operations, but no refs were rewritten.\n\n> So I agree with Pablo's suggestion: printing old/new short hash on\n> success would help visualy confirming something worked.\n\nI think we have the machinery for this (see --update-refs=print for\ngit-replay, for example), but I'm surprised to learn that we don't\naccept --update-refs=print for history.\n\nIn any case, I second the \"we should emit something\"—I wonder what, though.\n\n- In the case of rewritten refs, we might like to emit the list of\nrewrites, a bit like a fetch or push will do: \"+ $old...$new $ref\n(forced update)\" or something\n- For new objects that aren't pointed to… maybe silence is a better\nindicator that \"we didn't do what you intended\"? Or we could just\nprint the new commit objects \"$new [unreferenced object]\" or something\n\n> ... But it might be worth to ensure that the commit has any ref we can\n> handle (if --update-refs is set then the commit we edit is ancestor to\n> some branch, if not set then it must be an ancestor of HEAD)\n>\n> What do you think?\n\nI don't think it's worth restricting the operation (I can imagine a\nuse case where someone creates an unpointed-to object and later makes\nthe ref, even if that's a bit weird), but\n\n- we could have a \"strict\" mode that ensured inputs are pointed to\n- we could warn when only unreferenced objects are rewritten\n\n? I see git-history as very \"porcelain\"/user-focused, so I think it's\nfeasible to add output niceties (and optionally a quiet mode to\nsuppress the messages).\n\n-- \nD. Ben Knoble\n"},{"id":"547487","messageId":"ak484Ywk97k-8ULs@pks.im","threadId":"65766","inReplyTo":"CALnO6CAjZfK3hPWn1vOxgw=4=cjRYEHabYJmJrpVVDU8yyQn_g@mail.gmail.com","subject":"Re: [PATCH RFC 2/2] builtin/history: print feedback after successful reword","fromName":"Patrick Steinhardt","fromEmail":"ps@pks.im","sentAt":"2026-07-08T12:04:49Z","receivedAt":"2026-07-08T12:04:56Z","isPatch":true,"body":"On Tue, Jul 07, 2026 at 12:10:12PM -0400, D. Ben Knoble wrote:\n> On Tue, Jul 7, 2026 at 1:09 AM Dominique Martinet\n> <asmadeus@codewreck.org> wrote:\n[snip]\n> > So I agree with Pablo's suggestion: printing old/new short hash on\n> > success would help visualy confirming something worked.\n> \n> I think we have the machinery for this (see --update-refs=print for\n> git-replay, for example), but I'm surprised to learn that we don't\n> accept --update-refs=print for history.\n> \n> In any case, I second the \"we should emit something\"—I wonder what, though.\n> \n> - In the case of rewritten refs, we might like to emit the list of\n> rewrites, a bit like a fetch or push will do: \"+ $old...$new $ref\n> (forced update)\" or something\n> - For new objects that aren't pointed to… maybe silence is a better\n> indicator that \"we didn't do what you intended\"? Or we could just\n> print the new commit objects \"$new [unreferenced object]\" or something\n\nThat's exactly my issue, as well. I'm slightly in favor of not writing\nanything, but if we're able to figure out how exactly to represent\nresults to users in a nice and consistent way then I'm very happy to\nchange my opinion.\n\nBut that definitely needs to account not only for the case where the\ncurrent HEAD gets rewritten, but it needs to account for any reference\n(including detached HEAD) that may be updated along the way.\n\n> > ... But it might be worth to ensure that the commit has any ref we can\n> > handle (if --update-refs is set then the commit we edit is ancestor to\n> > some branch, if not set then it must be an ancestor of HEAD)\n> >\n> > What do you think?\n> \n> I don't think it's worth restricting the operation (I can imagine a\n> use case where someone creates an unpointed-to object and later makes\n> the ref, even if that's a bit weird), but\n> \n> - we could have a \"strict\" mode that ensured inputs are pointed to\n> - we could warn when only unreferenced objects are rewritten\n> \n> ? I see git-history as very \"porcelain\"/user-focused, so I think it's\n> feasible to add output niceties (and optionally a quiet mode to\n> suppress the messages).\n\nYeah, I don't see any issue with having such a \"strict\" mode, either.\nBut I definitely don't want to enforce \"arbitrary\" restrictions that\nrequire the user to work around them. It's intentional that you can\nrewrite history of commits that aren't even reachable from HEAD.\n\nIt might be sensible to even make the strict mode the default, where you\nneed to pass a switch to rewrite commits that are not reachable from\nHEAD. But if so, we need to have a switch that disables this mode.\n\nPatrick\n"}]}