threads / discuss / 56375

How to interactively rebase-and-reword nth commit?

Subject: How to interactively rebase-and-reword nth commit?

## tl;dr

7 messages between Aug 25, 2021 and Aug 27, 2021.

replies: 6people: 5as markdown or json

Konstantin Kharlamov· Aug 25, 2021, 14:06 UTC · lore

I think, one of the most frequent git features used is `rebase -i`. There's a common workflow I think everyone knows: you have commits 1, 2, 3, then you decide "Nah, 2nd commit needs a change", so you do `git rebase -i HEAD~2`, then in popped up editor you modify the `pick` on the first line to become `edit`, then you do the change, then `git rebase --continue`.

The boilerplate part here: even though you know that you want to edit HEAD~2, there is no way to tell git that right away. Every time you have to launch editor, edit the line manually, then save it, close it.

I have seen here some discussions about improving that, someone even posted patches, but I'm not aware if it went anywhere. So I created 2 years ago a shell wrapper `rebase-at`¹, which upon called as `rebase-at e HEAD~2`, does the thing described above automatically. Under the hood I simply substitute EDITOR with `sed` command that replaces `pick` on the first line (the HEAD~2 commit) with `e`. If used with shell autocompletion, it is now practically instantaneous.

I'm almost happy with `rebase-at`, except I don't know of any way to make it work with `reword` git action. You see, "rewording a commit" requires to run EDITOR twice: first to substitute `pick` with `reword`, and then to actually edit the commit message. But since EDITOR was substituted with sed, the 2nd run won't give you an actual editor to change the commit message.

Any ideas, how can I tell `git` that I want to "reword" nth commit right away? Sure, I am not the first one to stumble upon it, am I? Any ideas?

1: https://github.com/Hi-Angel/dotfiles/blob/0b9418224e4ce7c9783dbc2d9473fd1991b9b0b2/.zshrc#L148-L160
Ævar Arnfjörð Bjarmason· Aug 25, 2021, 15:01 UTC · re: Konstantin Kharlamov · lore

Re: How to interactively rebase-and-reword nth commit?

On Wed, Aug 25 2021, Konstantin Kharlamov wrote:
Show 27 quoted lines
> I think, one of the most frequent git features used is `rebase -i`. There's a common
> workflow I think everyone knows: you have commits 1, 2, 3, then you decide "Nah, 2nd
> commit needs a change", so you do `git rebase -i HEAD~2`, then in popped up editor
> you modify the `pick` on the first line to become `edit`, then you do the change,
> then `git rebase --continue`.
>
> The boilerplate part here: even though you know that you want to edit HEAD~2, there
> is no way to tell git that right away. Every time you have to launch editor, edit the
> line manually, then save it, close it.
>
> I have seen here some discussions about improving that, someone even posted patches,
> but I'm not aware if it went anywhere. So I created 2 years ago a shell wrapper
> `rebase-at`¹, which upon called as `rebase-at e HEAD~2`, does the thing described
> above automatically. Under the hood I simply substitute EDITOR with `sed` command
> that replaces `pick` on the first line (the HEAD~2 commit) with `e`. If used with
> shell autocompletion, it is now practically instantaneous.
>
> I'm almost happy with `rebase-at`, except I don't know of any way to make it work
> with `reword` git action. You see, "rewording a commit" requires to run EDITOR twice:
> first to substitute `pick` with `reword`, and then to actually edit the commit
> message. But since EDITOR was substituted with sed, the 2nd run won't give you an
> actual editor to change the commit message.
>
> Any ideas, how can I tell `git` that I want to "reword" nth commit right away? Sure,
> I am not the first one to stumble upon it, am I? Any ideas?
>
> 1: https://github.com/Hi-Angel/dotfiles/blob/0b9418224e4ce7c9783dbc2d9473fd1991b9b0b2/.zshrc#L148-L160
Have your GIT_EDITOR do one thing or the other depending on whether it's
asked to edit git-rebase-todo. This works for me:
    
    # rebase-at <action> <comit-ids-and-co>
    function rebase-at() {
        local action=$1
        shift 1
        GIT_EDITOR='perl -MFile::Basename=basename -wE '"'"'
            my $f = shift;
    	exec qw[sed -i -E], q[1s/\\w+/'$action'/], $f
    	    if basename($f) eq q[git-rebase-todo];
            exec "$ENV{EDITOR} $f";
        '"'" git rebase -i "$@"
    }
Martin Ågren· Aug 25, 2021, 15:54 UTC · re: Konstantin Kharlamov · lore

Re: How to interactively rebase-and-reword nth commit?

Hi Konstantin,
On Wed, 25 Aug 2021 at 16:07, Konstantin Kharlamov <hi-angel@yandex.ru> wrote:
Show 5 quoted lines
> I'm almost happy with `rebase-at`, except I don't know of any way to make it work
> with `reword` git action. You see, "rewording a commit" requires to run EDITOR twice:
> first to substitute `pick` with `reword`, and then to actually edit the commit
> message. But since EDITOR was substituted with sed, the 2nd run won't give you an
> actual editor to change the commit message.
I think GIT_SEQUENCE_EDITOR is for pretty much exactly such a use-case:
  This environment variable overrides the configured Git editor when
  editing the todo list of an interactive rebase. See also git-
  rebase(1) and the sequence.editor option in git-config(1).
Does that help, by not stomping on EDITOR/GIT_EDITOR?
Martin
Konstantin Kharlamov· Aug 25, 2021, 16:32 UTC · re: Martin Ågren · lore

Re: How to interactively rebase-and-reword nth commit?

Amazing, thank you, simple replacing EDITOR with GIT_SEQUENCE_EDITOR worked for me!

On Wed, 2021-08-25 at 17:54 +0200, Martin Ågren wrote:
Show 22 quoted lines
> Hi Konstantin,
> 
> On Wed, 25 Aug 2021 at 16:07, Konstantin Kharlamov <hi-angel@yandex.ru> wrote:
> > I'm almost happy with `rebase-at`, except I don't know of any way to make it
> > work
> > with `reword` git action. You see, "rewording a commit" requires to run
> > EDITOR twice:
> > first to substitute `pick` with `reword`, and then to actually edit the
> > commit
> > message. But since EDITOR was substituted with sed, the 2nd run won't give
> > you an
> > actual editor to change the commit message.
> 
> I think GIT_SEQUENCE_EDITOR is for pretty much exactly such a use-case:
> 
>   This environment variable overrides the configured Git editor when
>   editing the todo list of an interactive rebase. See also git-
>   rebase(1) and the sequence.editor option in git-config(1).
> 
> Does that help, by not stomping on EDITOR/GIT_EDITOR?
> 
> Martin
ZheNing Hu· Aug 26, 2021, 06:28 UTC · re: Konstantin Kharlamov · lore

Re: How to interactively rebase-and-reword nth commit?

Konstantin Kharlamov <hi-angel@yandex.ru> 于2021年8月25日周三 下午10:08写道:
Show 30 quoted lines
>
> I think, one of the most frequent git features used is `rebase -i`. There's a common
> workflow I think everyone knows: you have commits 1, 2, 3, then you decide "Nah, 2nd
> commit needs a change", so you do `git rebase -i HEAD~2`, then in popped up editor
> you modify the `pick` on the first line to become `edit`, then you do the change,
> then `git rebase --continue`.
>
> The boilerplate part here: even though you know that you want to edit HEAD~2, there
> is no way to tell git that right away. Every time you have to launch editor, edit the
> line manually, then save it, close it.
>
> I have seen here some discussions about improving that, someone even posted patches,
> but I'm not aware if it went anywhere. So I created 2 years ago a shell wrapper
> `rebase-at`¹, which upon called as `rebase-at e HEAD~2`, does the thing described
> above automatically. Under the hood I simply substitute EDITOR with `sed` command
> that replaces `pick` on the first line (the HEAD~2 commit) with `e`. If used with
> shell autocompletion, it is now practically instantaneous.
>
> I'm almost happy with `rebase-at`, except I don't know of any way to make it work
> with `reword` git action. You see, "rewording a commit" requires to run EDITOR twice:
> first to substitute `pick` with `reword`, and then to actually edit the commit
> message. But since EDITOR was substituted with sed, the 2nd run won't give you an
> actual editor to change the commit message.
>
> Any ideas, how can I tell `git` that I want to "reword" nth commit right away? Sure,
> I am not the first one to stumble upon it, am I? Any ideas?
>
> 1: https://github.com/Hi-Angel/dotfiles/blob/0b9418224e4ce7c9783dbc2d9473fd1991b9b0b2/.zshrc#L148-L160
>
>
Ha, this is simply a dream feature for me.
Jeff King· Aug 27, 2021, 02:04 UTC · re: Konstantin Kharlamov · lore

Re: How to interactively rebase-and-reword nth commit?

On Wed, Aug 25, 2021 at 05:06:03PM +0300, Konstantin Kharlamov wrote:
> Any ideas, how can I tell `git` that I want to "reword" nth commit right away? Sure,
> I am not the first one to stumble upon it, am I? Any ideas?
Have you looked at the new --fixup options in 2.32? E.g.:
  git commit --fixup reword:HEAD~2

will immediately drop you in an editor to adjust the commit message. The result is a new "fixup" commit which is then applied when you autosquash. So you could do multiple such adjustments, and then:

  GIT_EDITOR=: git rebase -i --autosquash
to apply them all to the appropriate spots.
-Peff
Konstantin Kharlamov· Aug 27, 2021, 09:18 UTC · re: Jeff King · lore

Re: How to interactively rebase-and-reword nth commit?

On Thu, 2021-08-26 at 22:04 -0400, Jeff King wrote:
Show 19 quoted lines
> On Wed, Aug 25, 2021 at 05:06:03PM +0300, Konstantin Kharlamov wrote:
> 
> > Any ideas, how can I tell `git` that I want to "reword" nth commit right
> > away? Sure,
> > I am not the first one to stumble upon it, am I? Any ideas?
> 
> Have you looked at the new --fixup options in 2.32? E.g.:
> 
>   git commit --fixup reword:HEAD~2
> 
> will immediately drop you in an editor to adjust the commit message. The
> result is a new "fixup" commit which is then applied when you
> autosquash. So you could do multiple such adjustments, and then:
> 
>   GIT_EDITOR=: git rebase -i --autosquash
> 
> to apply them all to the appropriate spots.
> 
> -Peff
Thank 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.
I 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).

← back to recent threads