git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* rewinding interactive rebases
@ 2022-02-21 19:06 Oswald Buddenhagen
  2022-03-01  9:24 ` Erik Cervin Edin
  0 siblings, 1 reply; 4+ messages in thread
From: Oswald Buddenhagen @ 2022-02-21 19:06 UTC (permalink / raw)
  To: git

[-- Attachment #1: Type: text/plain, Size: 810 bytes --]

heya,

this post is basically a continuation of 
https://public-inbox.org/git/CAE1pOi1XtrWqG7mOdrNt10YoZG0LOAB7i9cc1Gi8oWhULxE57A@mail.gmail.com/ 
("Is there any way to "interrupt" a rebase?"), but i thought it's 
probably better to start a new thread rather than to revive a zombie.

the basic problem is that during significant reworks of (complex) 
branches, one will inevitably find oneself in the situation of wanting 
to "go back" in the process. fixup commits aren't always optimal, as 
subsequent re-ordering may cause conflicts. doing the amend in the right 
place to start with cuts away one of the conflict resolutions.

the solution to this is actually rather simple, as demonstrated by the 
attached script.

somebody feels like rewriting this as a nice 'git rebase --rewind' 
subcommand?

thanks

[-- Attachment #2: git-rebase-rewind --]
[-- Type: text/plain, Size: 942 bytes --]

#! /bin/bash
# Copyright (C) 2022 Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
#
# You may use this file under the terms of the 3-clause BSD license.

gitdir=$(git rev-parse --git-dir) || exit

if ! git diff --quiet HEAD; then
    echo "Working directory or index not clean." >&2
    exit 1
fi

rbdir=$gitdir/rebase-merge
if ! test -d "$rbdir"; then
    echo "No rebase ongoing?" >&2
    exit 1
fi

onto=$(<"$rbdir/onto") || exit
todo=$rbdir/git-rebase-todo

git log --reverse --pretty="tformat:pick %h %s" $onto.. > "$todo.new" || exit
(echo "break"; echo; cat "$todo") >> "$todo.new" || exit

mv "$todo" "$todo.old" || exit
mv "$todo.new" "$todo" || exit
if ! git rebase --edit-todo; then
    mv "$todo.old" "$todo"
    exit 1
fi
if ! test -s "$todo"; then
    echo "Empty todo; canceling rewind." >&2
    mv "$todo.old" "$todo"
    exit 1
fi
rm "$todo.old"
: > "$rbdir/done"

git reset --hard $onto || exit
git rebase --continue || exit

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: rewinding interactive rebases
  2022-02-21 19:06 rewinding interactive rebases Oswald Buddenhagen
@ 2022-03-01  9:24 ` Erik Cervin Edin
  2022-03-07 16:56   ` Johannes Schindelin
  0 siblings, 1 reply; 4+ messages in thread
From: Erik Cervin Edin @ 2022-03-01  9:24 UTC (permalink / raw)
  To: Oswald Buddenhagen; +Cc: git

On Tue, Mar 1, 2022 at 1:21 AM Oswald Buddenhagen
<oswald.buddenhagen@gmx.de> wrote:
> did you mean to answer only privately?

No, mea culpa :(

> On Mon, Feb 28, 2022 at 10:32:16PM +0100, Erik Cervin Edin wrote:
> >What's the connection to the original thread [...]?
> >
> that depends on what you want to interpret into the original thread,
> given that a bunch of use cases and solutions were mentioned. my
> solution is actually functionally identical to one of the later
> subthreads, as i found after the fact.

Sorry but it's a long thread and at least I am unsure which parts you
are referring to and how your script fits into that.

> >Maybe you could explain it a bit in the context of the problem.
> >
> there really isn't much to it. the git log + git reset are the essence.
> just run it in the middle of an interactive rebase to see yourself.

Could you elaborate on the intended/usual flow here?
Rebase => Get conflict => Fix conflict => run the script => ..??

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: rewinding interactive rebases
  2022-03-01  9:24 ` Erik Cervin Edin
@ 2022-03-07 16:56   ` Johannes Schindelin
  2022-03-07 19:08     ` Oswald Buddenhagen
  0 siblings, 1 reply; 4+ messages in thread
From: Johannes Schindelin @ 2022-03-07 16:56 UTC (permalink / raw)
  To: Erik Cervin Edin; +Cc: Oswald Buddenhagen, git

Hi Erik & Oswald,

it's not really obvious from the text quoted below what is being discussed
here, so let me simply top-post some thoughts:

Problem statement: in the middle of an interactive rebase, the user would
like to choose a different rebase target, without having to abort the
rebase.

Suggested approach: implement support for `git rebase -i --nested --onto
<commit> <base-commit>`, i.e. a `--nested` option.

The idea here is to generate a todo list (just like a fresh `git rebase -i
--onto <commit> <base-commit>` would have done) and _prepend_ it to the
current todo list.

To support a nested `git rebase --abort`, we would probably want to insert
some marker after the newly-generated todo list (maybe a
specially-formatted comment such as `## END NESTED ##`).

To support nested `git rebase --rebase-merges`, we would need to populate
`state.labels` by reading `$GIT_DIR/rebase-merge/refs-to-delete` first
thing when generating the todo list.

For good measure, we should probably populate `state.commit2label` with
this list, too, looking up the respective OIDs via
`refs/rewritten/<label>`.

I realize that this is quite dense information for anybody unfamiliar with
the `sequencer.c` code, and that the idea is _not_ fully fleshed out, but
I lack the time to implement it and wanted to get even just a
half-finished idea out there.

Ciao,
Johannes

On Tue, 1 Mar 2022, Erik Cervin Edin wrote:

> On Tue, Mar 1, 2022 at 1:21 AM Oswald Buddenhagen
> <oswald.buddenhagen@gmx.de> wrote:
>
> > On Mon, Feb 28, 2022 at 10:32:16PM +0100, Erik Cervin Edin wrote:
> > >What's the connection to the original thread [...]?
> > >
> > that depends on what you want to interpret into the original thread,
> > given that a bunch of use cases and solutions were mentioned. my
> > solution is actually functionally identical to one of the later
> > subthreads, as i found after the fact.
>
> Sorry but it's a long thread and at least I am unsure which parts you
> are referring to and how your script fits into that.
>
> > >Maybe you could explain it a bit in the context of the problem.
> > >
> > there really isn't much to it. the git log + git reset are the essence.
> > just run it in the middle of an interactive rebase to see yourself.
>
> Could you elaborate on the intended/usual flow here?
> Rebase => Get conflict => Fix conflict => run the script => ..??
>

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: rewinding interactive rebases
  2022-03-07 16:56   ` Johannes Schindelin
@ 2022-03-07 19:08     ` Oswald Buddenhagen
  0 siblings, 0 replies; 4+ messages in thread
From: Oswald Buddenhagen @ 2022-03-07 19:08 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Erik Cervin Edin, git

On Mon, Mar 07, 2022 at 05:56:22PM +0100, Johannes Schindelin wrote:
>Problem statement: in the middle of an interactive rebase, the user 
>would like to choose a different rebase target, without having to abort 
>the rebase.
>
it didn't even occur to me to actually change the base (note that my 
script has no --onto option, even though it wouldn't be that hard to 
do). that stems from that fact that i have *really* rarely 
(intentionally) made an interactive rebase without (the equivalent of) 
--keep-base.

for me, it's about noticing that i need to rewrite some earlier commits 
again before going forward.

>The idea here is to generate a todo list (just like a fresh `git rebase 
>-i --onto <commit> <base-commit>` would have done) and _prepend_ it to 
>the current todo list.
>
yeah, that's essentially what the script does.

>To support a nested `git rebase --abort`, we would probably want to insert
>some marker after the newly-generated todo list (maybe a
>specially-formatted comment such as `## END NESTED ##`).
>
in the few weeks i've been using the script so far (with a by now 80+ 
commit series), i'd have found nested abort useful about twice, while 
repeated "flat" rewinds are par for the course. i'm also slightly 
worried that i'd lose track of the stack and throw away too much (though 
strictly speaking that's actually not unique to nesting; it would just 
amplify the problem). my script already inserts a marker in the form of 
"break\n\n", and it gets really weird after several rewinds if i don't 
clean up. to make it less weird (and error-prone), one would have to 
actually start a new todo list, that is, actually throw the rest of the 
old todo list on a stack rather than prepending to it. so basically, 
choose between linear and nested, but don't mix the two.


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2022-03-07 19:08 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-21 19:06 rewinding interactive rebases Oswald Buddenhagen
2022-03-01  9:24 ` Erik Cervin Edin
2022-03-07 16:56   ` Johannes Schindelin
2022-03-07 19:08     ` Oswald Buddenhagen

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).