{"thread":{"id":"58316","subject":"Bug in rebase --autosquash","startedAt":"2022-08-17T09:50:24Z","lastAt":"2022-08-19T17:36:38Z","messageCount":4,"participants":["Uwe Kleine-König","Felipe Contreras","Johannes Schindelin","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"461357","messageId":"20220817094909.v2ev4rpsmxjnii4x@pengutronix.de","threadId":"58316","inReplyTo":null,"subject":"Bug in rebase --autosquash","fromName":"Uwe Kleine-König","fromEmail":"u.kleine-koenig@pengutronix.de","sentAt":"2022-08-17T09:49:09Z","receivedAt":"2022-08-17T09:50:24Z","isPatch":false,"sender":{"key":"u.kleine-koenig@pengutronix.de","avatar":"https://gravatar.com/avatar/354b5e3ceb2806a2f1e1e382ac29ddbdad18288654da62b61eb13583a857eee7?d=mp&s=160"},"body":"Hello,\n\nafter:\n\n\tuwe@taurus:~/tmp/git$ git version\n\tgit version 2.37.2\n\tuwe@taurus:~/tmp/git$ git init\n\tInitialized empty Git repository in /home/uwe/tmp/git/.git/\n\tuwe@taurus:~/tmp/git$ echo contnt > file\n\tuwe@taurus:~/tmp/git$ git add file\n\tuwe@taurus:~/tmp/git$ git commit -m 'file with content'\n\t...\n\tuwe@taurus:~/tmp/git$ echo 'content' > file\n\tuwe@taurus:~/tmp/git$ git commit --fixup=@ file\n\t[main ef8f0bd27a56] fixup! file with content\n\tuwe@taurus:~/tmp/git$ echo 'more content' >> file\n\tuwe@taurus:~/tmp/git$ git commit --fixup=@ file\n\t[main b40a214bf5fb] fixup! fixup! file with content\n\t 1 file changed, 1 insertion(+)\n\nrunning\n\n\tgit rebase -i --autosquash @~2\n\nmy editor presents me with:\n\n\tpick ef8f0bd27a56 fixup! file with content\n\tpick b40a214bf5fb fixup! fixup! file with content\n\nHowever I would have expected\n\n\tpick ef8f0bd27a56 fixup! file with content\n\tfixup b40a214bf5fb fixup! fixup! file with content\n\ninstead.\n\nIs this a feature I don't understand?\n\nWhen the original commit is in the range (i.e. with\n\n\tgit rebase -i --autosquash --root\n\n) it does the right thing, i.e. my editor then has:\n\n\tpick 0c1d21698c38 file with content\n\tfixup ef8f0bd27a56 fixup! file with content\n\tfixup b40a214bf5fb fixup! fixup! file with content\n\n. Unrelated to that, but annoying is, that\n\n\tgit rebase --autosquash --root\n\ndoesn't do the right thing. It doesn't change the history at all, while\nI expected it to only contain a single commit then.\n\nBest regards\nUwe\n\n-- \nPengutronix e.K.                           | Uwe Kleine-König            |\nIndustrial Linux Solutions                 | https://www.pengutronix.de/ |\n"},{"id":"461384","messageId":"CAMP44s3iRbqgA9U4SeyRQUXdfqk=Stsw3kGqoGrFDRDWkV6GKA@mail.gmail.com","threadId":"58316","inReplyTo":"20220817094909.v2ev4rpsmxjnii4x@pengutronix.de","subject":"Re: Bug in rebase --autosquash","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2022-08-17T19:40:44Z","receivedAt":"2022-08-17T19:41:14Z","isPatch":false,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"On Wed, Aug 17, 2022 at 4:54 AM Uwe Kleine-König\n<u.kleine-koenig@pengutronix.de> wrote:\n> after:\n\n...\n\n> running\n>\n>         git rebase -i --autosquash @~2\n>\n> my editor presents me with:\n>\n>         pick ef8f0bd27a56 fixup! file with content\n>         pick b40a214bf5fb fixup! fixup! file with content\n>\n> However I would have expected\n>\n>         pick ef8f0bd27a56 fixup! file with content\n>         fixup b40a214bf5fb fixup! fixup! file with content\n>\n> instead.\n>\n> Is this a feature I don't understand?\n\nThe problem is the code removes all \"fixup! \" prefixes and then tries\nto find a commit with that title, which isn't in the list. If you\nspecify the commit hash, then it finds it and it works as you\nintended.\n\nI don't see why the code would do that though, since you are clearly\nintending to fix \"fixup! file with content\", not \"file with content\".\n\nThis patch below (apologies for gmail auto wrapping in advance) should\nmake it work as you intend.\n\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -6213,12 +6213,8 @@ int todo_list_rearrange_squash(struct todo_list\n*todo_list)\n                if (skip_fixupish(subject, &p)) {\n                        struct commit *commit2;\n\n-                       for (;;) {\n-                               while (isspace(*p))\n-                                       p++;\n-                               if (!skip_fixupish(p, &p))\n-                                       break;\n-                       }\n+                       while (isspace(*p))\n+                               p++;\n\n                        entry = hashmap_get_entry_from_hash(&subject2item,\n                                                strhash(p), p,\n\n-- \nFelipe Contreras\n"},{"id":"461543","messageId":"8p78q4p9-9ro4-p5s4-r738-7sno17rqr414@tzk.qr","threadId":"58316","inReplyTo":"20220817094909.v2ev4rpsmxjnii4x@pengutronix.de","subject":"Re: Bug in rebase --autosquash","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2022-08-19T11:09:00Z","receivedAt":"2022-08-19T11:09:01Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Uwe,\n\nOn Wed, 17 Aug 2022, Uwe Kleine-König wrote:\n\n> after:\n>\n> \tuwe@taurus:~/tmp/git$ git version\n> \tgit version 2.37.2\n> \tuwe@taurus:~/tmp/git$ git init\n> \tInitialized empty Git repository in /home/uwe/tmp/git/.git/\n> \tuwe@taurus:~/tmp/git$ echo contnt > file\n> \tuwe@taurus:~/tmp/git$ git add file\n> \tuwe@taurus:~/tmp/git$ git commit -m 'file with content'\n> \t...\n> \tuwe@taurus:~/tmp/git$ echo 'content' > file\n> \tuwe@taurus:~/tmp/git$ git commit --fixup=@ file\n> \t[main ef8f0bd27a56] fixup! file with content\n> \tuwe@taurus:~/tmp/git$ echo 'more content' >> file\n> \tuwe@taurus:~/tmp/git$ git commit --fixup=@ file\n> \t[main b40a214bf5fb] fixup! fixup! file with content\n> \t 1 file changed, 1 insertion(+)\n>\n> running\n>\n> \tgit rebase -i --autosquash @~2\n>\n> my editor presents me with:\n>\n> \tpick ef8f0bd27a56 fixup! file with content\n> \tpick b40a214bf5fb fixup! fixup! file with content\n>\n> However I would have expected\n>\n> \tpick ef8f0bd27a56 fixup! file with content\n> \tfixup b40a214bf5fb fixup! fixup! file with content\n>\n> instead.\n>\n> Is this a feature I don't understand?\n\nThis demonstrates a somewhat obscure feature where the `fixup!` of a\n`fixup!` magically targets the original commit.\n\nI understand that it is somewhat unintuitive that `fixup! fixup! abc` does\nnot target `fixup! abc` but instead `abc`, but that's how the tool has\nbeen behaving forever.\n\nCiao,\nDscho\n"},{"id":"461581","messageId":"xmqqpmgwmaxx.fsf@gitster.g","threadId":"58316","inReplyTo":"8p78q4p9-9ro4-p5s4-r738-7sno17rqr414@tzk.qr","subject":"Re: Bug in rebase --autosquash","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2022-08-19T16:53:46Z","receivedAt":"2022-08-19T17:36:38Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> This demonstrates a somewhat obscure feature where the `fixup!` of a\n> `fixup!` magically targets the original commit.\n>\n> I understand that it is somewhat unintuitive that `fixup! fixup! abc` does\n> not target `fixup! abc` but instead `abc`, but that's how the tool has\n> been behaving forever.\n\nIt certainly is handy when the original commit A has a fixup commit\nB, which gets later fixed up by another commit C, resulting in a\nsequence like this:\n\n    $ git rebase -i A~1 C\n\n    pick A original commit\n    fixup B fixup! original commit\n    fixup C fixup! fixup! original commit\n\nBut if the user for some reason finds it is not quite ready to touch\nthe original commit by squashing in the fixes, it may be reasonable\nto want to squash the two fixes together, so that it can later be\napplied to the original commit.  And it would be one natural way to\nrequest that with\n\n    $ git rebase -i A C\n\nthat is, leave the history up to A intact, but everything above\ntweaked.  Without --autosquash, you would get\n\n    pick B fixup! original commit\n    pick C fixup! fixup! original commit\n\nand you would manually do\n\n    pick B fixup! original commit\n    fixup C fixup! fixup! original commit\n\nto squash B and C together into a single fix-up to be applied\nlater.  It does not look all too unreasonable to expect the\n\"--autosquash\" feature to do that automatically for you.\n\nThanks.\n\n    \n\n\n"}]}