{"thread":{"id":"56375","subject":"How to interactively rebase-and-reword nth commit?","startedAt":"2021-08-25T14:06:10Z","lastAt":"2021-08-27T09:18:08Z","messageCount":7,"participants":["Konstantin Kharlamov","Ævar Arnfjörð Bjarmason","Martin Ågren","ZheNing Hu","Jeff King"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"433735","messageId":"eda317b080a2e75a170c051c339a76115cce5ad7.camel@yandex.ru","threadId":"56375","inReplyTo":null,"subject":"How to interactively rebase-and-reword nth commit?","fromName":"Konstantin Kharlamov","fromEmail":"hi-angel@yandex.ru","sentAt":"2021-08-25T14:06:03Z","receivedAt":"2021-08-25T14:06:10Z","isPatch":false,"sender":{"key":"hi-angel@yandex.ru","avatar":null},"body":"I think, one of the most frequent git features used is `rebase -i`. There's a common\nworkflow I think everyone knows: you have commits 1, 2, 3, then you decide \"Nah, 2nd\ncommit needs a change\", so you do `git rebase -i HEAD~2`, then in popped up editor\nyou modify the `pick` on the first line to become `edit`, then you do the change,\nthen `git rebase --continue`.\n\nThe boilerplate part here: even though you know that you want to edit HEAD~2, there\nis no way to tell git that right away. Every time you have to launch editor, edit the\nline manually, then save it, close it.\n\nI have seen here some discussions about improving that, someone even posted patches,\nbut I'm not aware if it went anywhere. So I created 2 years ago a shell wrapper\n`rebase-at`¹, which upon called as `rebase-at e HEAD~2`, does the thing described\nabove automatically. Under the hood I simply substitute EDITOR with `sed` command\nthat replaces `pick` on the first line (the HEAD~2 commit) with `e`. If used with\nshell autocompletion, it is now practically instantaneous.\n\nI'm almost happy with `rebase-at`, except I don't know of any way to make it work\nwith `reword` git action. You see, \"rewording a commit\" requires to run EDITOR twice:\nfirst to substitute `pick` with `reword`, and then to actually edit the commit\nmessage. But since EDITOR was substituted with sed, the 2nd run won't give you an\nactual editor to change the commit message.\n\nAny ideas, how can I tell `git` that I want to \"reword\" nth commit right away? Sure,\nI am not the first one to stumble upon it, am I? Any ideas?\n\n1: https://github.com/Hi-Angel/dotfiles/blob/0b9418224e4ce7c9783dbc2d9473fd1991b9b0b2/.zshrc#L148-L160\n\n\n"},{"id":"433744","messageId":"87pmu1czn7.fsf@evledraar.gmail.com","threadId":"56375","inReplyTo":"eda317b080a2e75a170c051c339a76115cce5ad7.camel@yandex.ru","subject":"Re: How to interactively rebase-and-reword nth commit?","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-08-25T15:01:18Z","receivedAt":"2021-08-25T15:28:16Z","isPatch":false,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Wed, Aug 25 2021, Konstantin Kharlamov wrote:\n\n> I think, one of the most frequent git features used is `rebase -i`. There's a common\n> workflow I think everyone knows: you have commits 1, 2, 3, then you decide \"Nah, 2nd\n> commit needs a change\", so you do `git rebase -i HEAD~2`, then in popped up editor\n> you modify the `pick` on the first line to become `edit`, then you do the change,\n> then `git rebase --continue`.\n>\n> The boilerplate part here: even though you know that you want to edit HEAD~2, there\n> is no way to tell git that right away. Every time you have to launch editor, edit the\n> line manually, then save it, close it.\n>\n> I have seen here some discussions about improving that, someone even posted patches,\n> but I'm not aware if it went anywhere. So I created 2 years ago a shell wrapper\n> `rebase-at`¹, which upon called as `rebase-at e HEAD~2`, does the thing described\n> above automatically. Under the hood I simply substitute EDITOR with `sed` command\n> that replaces `pick` on the first line (the HEAD~2 commit) with `e`. If used with\n> shell autocompletion, it is now practically instantaneous.\n>\n> I'm almost happy with `rebase-at`, except I don't know of any way to make it work\n> with `reword` git action. You see, \"rewording a commit\" requires to run EDITOR twice:\n> first to substitute `pick` with `reword`, and then to actually edit the commit\n> message. But since EDITOR was substituted with sed, the 2nd run won't give you an\n> actual editor to change the commit message.\n>\n> Any ideas, how can I tell `git` that I want to \"reword\" nth commit right away? Sure,\n> I am not the first one to stumble upon it, am I? Any ideas?\n>\n> 1: https://github.com/Hi-Angel/dotfiles/blob/0b9418224e4ce7c9783dbc2d9473fd1991b9b0b2/.zshrc#L148-L160\n\nHave your GIT_EDITOR do one thing or the other depending on whether it's\nasked to edit git-rebase-todo. This works for me:\n    \n    # rebase-at <action> <comit-ids-and-co>\n    function rebase-at() {\n        local action=$1\n        shift 1\n        GIT_EDITOR='perl -MFile::Basename=basename -wE '\"'\"'\n            my $f = shift;\n    \texec qw[sed -i -E], q[1s/\\\\w+/'$action'/], $f\n    \t    if basename($f) eq q[git-rebase-todo];\n            exec \"$ENV{EDITOR} $f\";\n        '\"'\" git rebase -i \"$@\"\n    }\n"},{"id":"433748","messageId":"CAN0heSoxE8zjzbYqRY6zvva=GEXEWx1k8FGhJMCf6N=pEcpZFw@mail.gmail.com","threadId":"56375","inReplyTo":"eda317b080a2e75a170c051c339a76115cce5ad7.camel@yandex.ru","subject":"Re: How to interactively rebase-and-reword nth commit?","fromName":"Martin Ågren","fromEmail":"martin.agren@gmail.com","sentAt":"2021-08-25T15:54:04Z","receivedAt":"2021-08-25T15:54:18Z","isPatch":false,"sender":{"key":"martin.agren@gmail.com","avatar":null},"body":"Hi Konstantin,\n\nOn Wed, 25 Aug 2021 at 16:07, Konstantin Kharlamov <hi-angel@yandex.ru> wrote:\n> I'm almost happy with `rebase-at`, except I don't know of any way to make it work\n> with `reword` git action. You see, \"rewording a commit\" requires to run EDITOR twice:\n> first to substitute `pick` with `reword`, and then to actually edit the commit\n> message. But since EDITOR was substituted with sed, the 2nd run won't give you an\n> actual editor to change the commit message.\n\nI think GIT_SEQUENCE_EDITOR is for pretty much exactly such a use-case:\n\n  This environment variable overrides the configured Git editor when\n  editing the todo list of an interactive rebase. See also git-\n  rebase(1) and the sequence.editor option in git-config(1).\n\nDoes that help, by not stomping on EDITOR/GIT_EDITOR?\n\nMartin\n"},{"id":"433752","messageId":"b1c62f6aa1eb06b64ee095dff23709a42d25cb16.camel@yandex.ru","threadId":"56375","inReplyTo":"CAN0heSoxE8zjzbYqRY6zvva=GEXEWx1k8FGhJMCf6N=pEcpZFw@mail.gmail.com","subject":"Re: How to interactively rebase-and-reword nth commit?","fromName":"Konstantin Kharlamov","fromEmail":"hi-angel@yandex.ru","sentAt":"2021-08-25T16:32:24Z","receivedAt":"2021-08-25T16:39:16Z","isPatch":false,"sender":{"key":"hi-angel@yandex.ru","avatar":null},"body":"Amazing, thank you, simple replacing EDITOR with GIT_SEQUENCE_EDITOR worked for\nme!\n\nOn Wed, 2021-08-25 at 17:54 +0200, Martin Ågren wrote:\n> Hi Konstantin,\n> \n> On Wed, 25 Aug 2021 at 16:07, Konstantin Kharlamov <hi-angel@yandex.ru> wrote:\n> > I'm almost happy with `rebase-at`, except I don't know of any way to make it\n> > work\n> > with `reword` git action. You see, \"rewording a commit\" requires to run\n> > EDITOR twice:\n> > first to substitute `pick` with `reword`, and then to actually edit the\n> > commit\n> > message. But since EDITOR was substituted with sed, the 2nd run won't give\n> > you an\n> > actual editor to change the commit message.\n> \n> I think GIT_SEQUENCE_EDITOR is for pretty much exactly such a use-case:\n> \n>   This environment variable overrides the configured Git editor when\n>   editing the todo list of an interactive rebase. See also git-\n>   rebase(1) and the sequence.editor option in git-config(1).\n> \n> Does that help, by not stomping on EDITOR/GIT_EDITOR?\n> \n> Martin\n\n\n"},{"id":"433809","messageId":"CAOLTT8QdbUOkacYEa812Qtam2Uc2Ug2cHR_iK=gLtsHTghZWZQ@mail.gmail.com","threadId":"56375","inReplyTo":"eda317b080a2e75a170c051c339a76115cce5ad7.camel@yandex.ru","subject":"Re: How to interactively rebase-and-reword nth commit?","fromName":"ZheNing Hu","fromEmail":"adlternative@gmail.com","sentAt":"2021-08-26T06:28:37Z","receivedAt":"2021-08-26T06:28:50Z","isPatch":false,"sender":{"key":"adlternative@gmail.com","avatar":"https://avatars.githubusercontent.com/u/58138461?v=4"},"body":"Konstantin Kharlamov <hi-angel@yandex.ru> 于2021年8月25日周三 下午10:08写道：\n>\n> I think, one of the most frequent git features used is `rebase -i`. There's a common\n> workflow I think everyone knows: you have commits 1, 2, 3, then you decide \"Nah, 2nd\n> commit needs a change\", so you do `git rebase -i HEAD~2`, then in popped up editor\n> you modify the `pick` on the first line to become `edit`, then you do the change,\n> then `git rebase --continue`.\n>\n> The boilerplate part here: even though you know that you want to edit HEAD~2, there\n> is no way to tell git that right away. Every time you have to launch editor, edit the\n> line manually, then save it, close it.\n>\n> I have seen here some discussions about improving that, someone even posted patches,\n> but I'm not aware if it went anywhere. So I created 2 years ago a shell wrapper\n> `rebase-at`¹, which upon called as `rebase-at e HEAD~2`, does the thing described\n> above automatically. Under the hood I simply substitute EDITOR with `sed` command\n> that replaces `pick` on the first line (the HEAD~2 commit) with `e`. If used with\n> shell autocompletion, it is now practically instantaneous.\n>\n> I'm almost happy with `rebase-at`, except I don't know of any way to make it work\n> with `reword` git action. You see, \"rewording a commit\" requires to run EDITOR twice:\n> first to substitute `pick` with `reword`, and then to actually edit the commit\n> message. But since EDITOR was substituted with sed, the 2nd run won't give you an\n> actual editor to change the commit message.\n>\n> Any ideas, how can I tell `git` that I want to \"reword\" nth commit right away? Sure,\n> I am not the first one to stumble upon it, am I? Any ideas?\n>\n> 1: https://github.com/Hi-Angel/dotfiles/blob/0b9418224e4ce7c9783dbc2d9473fd1991b9b0b2/.zshrc#L148-L160\n>\n>\n\nHa, this is simply a dream feature for me.\n"},{"id":"433896","messageId":"YShISkyN7stYtkV2@coredump.intra.peff.net","threadId":"56375","inReplyTo":"eda317b080a2e75a170c051c339a76115cce5ad7.camel@yandex.ru","subject":"Re: How to interactively rebase-and-reword nth commit?","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2021-08-27T02:04:58Z","receivedAt":"2021-08-27T02:05:00Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Aug 25, 2021 at 05:06:03PM +0300, Konstantin Kharlamov wrote:\n\n> Any ideas, how can I tell `git` that I want to \"reword\" nth commit right away? Sure,\n> I am not the first one to stumble upon it, am I? Any ideas?\n\nHave you looked at the new --fixup options in 2.32? E.g.:\n\n  git commit --fixup reword:HEAD~2\n\nwill immediately drop you in an editor to adjust the commit message. The\nresult is a new \"fixup\" commit which is then applied when you\nautosquash. So you could do multiple such adjustments, and then:\n\n  GIT_EDITOR=: git rebase -i --autosquash\n\nto apply them all to the appropriate spots.\n\n-Peff\n"},{"id":"433921","messageId":"826fa09ce470d1a3f06714cdd7f75891fecda676.camel@yandex.ru","threadId":"56375","inReplyTo":"YShISkyN7stYtkV2@coredump.intra.peff.net","subject":"Re: How to interactively rebase-and-reword nth commit?","fromName":"Konstantin Kharlamov","fromEmail":"hi-angel@yandex.ru","sentAt":"2021-08-27T09:18:00Z","receivedAt":"2021-08-27T09:18:08Z","isPatch":false,"sender":{"key":"hi-angel@yandex.ru","avatar":null},"body":"On Thu, 2021-08-26 at 22:04 -0400, Jeff King wrote:\n> On Wed, Aug 25, 2021 at 05:06:03PM +0300, Konstantin Kharlamov wrote:\n> \n> > Any ideas, how can I tell `git` that I want to \"reword\" nth commit right\n> > away? Sure,\n> > I am not the first one to stumble upon it, am I? Any ideas?\n> \n> Have you looked at the new --fixup options in 2.32? E.g.:\n> \n>   git commit --fixup reword:HEAD~2\n> \n> will immediately drop you in an editor to adjust the commit message. The\n> result is a new \"fixup\" commit which is then applied when you\n> autosquash. So you could do multiple such adjustments, and then:\n> \n>   GIT_EDITOR=: git rebase -i --autosquash\n> \n> to apply them all to the appropriate spots.\n> \n> -Peff\n\nThank you for the suggestion! I think I gonna stick to the `rebase-at` now that I know the way to solve my problem with GIT_SEQUENCE_EDITOR. The \"rebase-at\" workflow sounds better optimized to me, due to lack of the `git rebase -i --autosquash` step.\n\nI get that the idea with autosquash that you can remove the commit if you realize you did something wrong. But I usually have a copy of the local branch on a remote repo, so in rare cases I realize I want to undo the change I can simply run `git reset --hard origin/mybranch` ☺ (otherwise, reflog is also a thing).\n\n"}]}