{"thread":{"id":"64852","subject":"[PATCH] reset: avoid reflog update on no-op reset","startedAt":"2026-01-22T15:52:22Z","lastAt":"2026-01-22T19:09:46Z","messageCount":3,"participants":["Pushkar Singh","Junio C Hamano","Jeff King"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"534467","messageId":"20260122154743.20496-3-pushkarkumarsingh1970@gmail.com","threadId":"64852","inReplyTo":null,"subject":"[PATCH] reset: avoid reflog update on no-op reset","fromName":"Pushkar Singh","fromEmail":"pushkarkumarsingh1970@gmail.com","sentAt":"2026-01-22T15:47:45Z","receivedAt":"2026-01-22T15:52:22Z","isPatch":true,"sender":{"key":"pushkarkumarsingh1970@gmail.com","avatar":"https://avatars.githubusercontent.com/u/173247767?v=4"},"body":"When \"git reset\" is invoked with a target that already matches HEAD,\nit currently writes a reflog entry even though no reference is updated.\n\nDetect this no-op case and avoid updating ORIG_HEAD and HEAD, skipping\nthe reflog entry entirely.\n\nAdd a regression test to ensure no reflog entry is written for a no-op\nreset.\n\nSigned-off-by: Pushkar Singh <pushkarkumarsingh1970@gmail.com>\n---\n builtin/reset.c   |  4 ++++\n t/t1410-reflog.sh | 15 +++++++++++++++\n 2 files changed, 19 insertions(+)\n\ndiff --git a/builtin/reset.c b/builtin/reset.c\nindex ed35802af1..900c2f2fe8 100644\n--- a/builtin/reset.c\n+++ b/builtin/reset.c\n@@ -309,6 +309,10 @@ static int reset_refs(const char *rev, const struct object_id *oid)\n \t\told_orig = &oid_old_orig;\n \tif (!repo_get_oid(the_repository, \"HEAD\", &oid_orig)) {\n \t\torig = &oid_orig;\n+\t\tif (oideq(orig, oid)) {\n+\t\t\tstrbuf_release(&msg);\n+\t\t\treturn 0;\n+\t\t}\n \t\tset_reflog_message(&msg, \"updating ORIG_HEAD\", NULL);\n \t\trefs_update_ref(get_main_ref_store(the_repository), msg.buf,\n \t\t\t\t\"ORIG_HEAD\", orig, old_orig, 0,\ndiff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh\nindex ce71f9a30a..54f8692c53 100755\n--- a/t/t1410-reflog.sh\n+++ b/t/t1410-reflog.sh\n@@ -533,6 +533,21 @@ test_expect_success 'reflog for symref with unborn target can be listed' '\n \t)\n '\n \n+test_expect_success 'reset does not write reflog entry on no-op' '\n+\tgit init no-op-reset &&\n+\t(\n+\t\tcd no-op-reset &&\n+\t\techo a >file &&\n+\t\tgit add file &&\n+\t\tgit commit -m initial &&\n+\n+\t\tbefore=$(git reflog | wc -l) &&\n+\t\tgit reset HEAD &&\n+\t\tafter=$(git reflog | wc -l) &&\n+\t\ttest \"$before\" = \"$after\"\n+\t)\n+'\n+\n test_expect_success 'reflog with invalid object ID can be listed' '\n \ttest_when_finished \"rm -rf repo\" &&\n \tgit init repo &&\n-- \n2.43.0\n\n"},{"id":"534482","messageId":"xmqqwm19mq69.fsf@gitster.g","threadId":"64852","inReplyTo":"20260122154743.20496-3-pushkarkumarsingh1970@gmail.com","subject":"Re: [PATCH] reset: avoid reflog update on no-op reset","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-01-22T18:57:02Z","receivedAt":"2026-01-22T18:57:08Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Pushkar Singh <pushkarkumarsingh1970@gmail.com> writes:\n\n> When \"git reset\" is invoked with a target that already matches HEAD,\n> it currently writes a reflog entry even though no reference is updated.\n>\n> Detect this no-op case and avoid updating ORIG_HEAD and HEAD, skipping\n> the reflog entry entirely.\n\nI am mildly negative on this one.  A scripted use that gets which\ncommit to reset to from the caller in the outside world, e.g.,\n\n    #!/bin/sh\n    git reset --hard \"$1\"\n    git diff --stat @{1}\n\nwould be confused if reflog does not reliably store the state before\nrunning \"reset --hard\" to @{1}.  In other words ...\n\n> Add a regression test to ensure no reflog entry is written for a no-op\n> reset.\n\n... this change may already be a regression for existing users.\n"},{"id":"534484","messageId":"20260122190941.GB2098026@coredump.intra.peff.net","threadId":"64852","inReplyTo":"xmqqwm19mq69.fsf@gitster.g","subject":"Re: [PATCH] reset: avoid reflog update on no-op reset","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2026-01-22T19:09:41Z","receivedAt":"2026-01-22T19:09:46Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Jan 22, 2026 at 10:57:02AM -0800, Junio C Hamano wrote:\n\n> Pushkar Singh <pushkarkumarsingh1970@gmail.com> writes:\n> \n> > When \"git reset\" is invoked with a target that already matches HEAD,\n> > it currently writes a reflog entry even though no reference is updated.\n> >\n> > Detect this no-op case and avoid updating ORIG_HEAD and HEAD, skipping\n> > the reflog entry entirely.\n> \n> I am mildly negative on this one.  A scripted use that gets which\n> commit to reset to from the caller in the outside world, e.g.,\n> \n>     #!/bin/sh\n>     git reset --hard \"$1\"\n>     git diff --stat @{1}\n> \n> would be confused if reflog does not reliably store the state before\n> running \"reset --hard\" to @{1}.  In other words ...\n> \n> > Add a regression test to ensure no reflog entry is written for a no-op\n> > reset.\n> \n> ... this change may already be a regression for existing users.\n\nI was just writing the same message. ;) In addition to scripted use,\nthat reflog does contain some human-readable information: the message\nfield tells us what name we \"git reset --hard\" to. That might be helpful\nwhen digging through it trying to piece together what happened.\n\n-Peff\n"}]}