{"thread":{"id":"57453","subject":"rewinding interactive rebases","startedAt":"2022-02-21T19:15:56Z","lastAt":"2022-03-07T19:08:34Z","messageCount":4,"participants":["Oswald Buddenhagen","Erik Cervin Edin","Johannes Schindelin"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"449041","messageId":"YhPiqlM81XCjNWpk@ugly","threadId":"57453","inReplyTo":null,"subject":"rewinding interactive rebases","fromName":"Oswald Buddenhagen","fromEmail":"oswald.buddenhagen@gmx.de","sentAt":"2022-02-21T19:06:18Z","receivedAt":"2022-02-21T19:15:56Z","isPatch":false,"sender":{"key":"oswald.buddenhagen@gmx.de","avatar":"https://avatars.githubusercontent.com/u/812380?v=4"},"body":"heya,\n\nthis post is basically a continuation of \nhttps://public-inbox.org/git/CAE1pOi1XtrWqG7mOdrNt10YoZG0LOAB7i9cc1Gi8oWhULxE57A@mail.gmail.com/ \n(\"Is there any way to \"interrupt\" a rebase?\"), but i thought it's \nprobably better to start a new thread rather than to revive a zombie.\n\nthe basic problem is that during significant reworks of (complex) \nbranches, one will inevitably find oneself in the situation of wanting \nto \"go back\" in the process. fixup commits aren't always optimal, as \nsubsequent re-ordering may cause conflicts. doing the amend in the right \nplace to start with cuts away one of the conflict resolutions.\n\nthe solution to this is actually rather simple, as demonstrated by the \nattached script.\n\nsomebody feels like rewriting this as a nice 'git rebase --rewind' \nsubcommand?\n\nthanks\n\n\n#! /bin/bash\n# Copyright (C) 2022 Oswald Buddenhagen <oswald.buddenhagen@gmx.de>\n#\n# You may use this file under the terms of the 3-clause BSD license.\n\ngitdir=$(git rev-parse --git-dir) || exit\n\nif ! git diff --quiet HEAD; then\n    echo \"Working directory or index not clean.\" >&2\n    exit 1\nfi\n\nrbdir=$gitdir/rebase-merge\nif ! test -d \"$rbdir\"; then\n    echo \"No rebase ongoing?\" >&2\n    exit 1\nfi\n\nonto=$(<\"$rbdir/onto\") || exit\ntodo=$rbdir/git-rebase-todo\n\ngit log --reverse --pretty=\"tformat:pick %h %s\" $onto.. > \"$todo.new\" || exit\n(echo \"break\"; echo; cat \"$todo\") >> \"$todo.new\" || exit\n\nmv \"$todo\" \"$todo.old\" || exit\nmv \"$todo.new\" \"$todo\" || exit\nif ! git rebase --edit-todo; then\n    mv \"$todo.old\" \"$todo\"\n    exit 1\nfi\nif ! test -s \"$todo\"; then\n    echo \"Empty todo; canceling rewind.\" >&2\n    mv \"$todo.old\" \"$todo\"\n    exit 1\nfi\nrm \"$todo.old\"\n: > \"$rbdir/done\"\n\ngit reset --hard $onto || exit\ngit rebase --continue || exit\n"},{"id":"449888","messageId":"CA+JQ7M-+kq1MTh+DG+HCmXkpsF5Esm_0V=4=2_DS2_ZYdjP2+g@mail.gmail.com","threadId":"57453","inReplyTo":"YhPiqlM81XCjNWpk@ugly","subject":"Re: rewinding interactive rebases","fromName":"Erik Cervin Edin","fromEmail":"erik@cervined.in","sentAt":"2022-03-01T09:24:50Z","receivedAt":"2022-03-01T09:25:30Z","isPatch":false,"sender":{"key":"erik@cervined.in","avatar":null},"body":"On Tue, Mar 1, 2022 at 1:21 AM Oswald Buddenhagen\n<oswald.buddenhagen@gmx.de> wrote:\n> did you mean to answer only privately?\n\nNo, mea culpa :(\n\n> On Mon, Feb 28, 2022 at 10:32:16PM +0100, Erik Cervin Edin wrote:\n> >What's the connection to the original thread [...]?\n> >\n> that depends on what you want to interpret into the original thread,\n> given that a bunch of use cases and solutions were mentioned. my\n> solution is actually functionally identical to one of the later\n> subthreads, as i found after the fact.\n\nSorry but it's a long thread and at least I am unsure which parts you\nare referring to and how your script fits into that.\n\n> >Maybe you could explain it a bit in the context of the problem.\n> >\n> there really isn't much to it. the git log + git reset are the essence.\n> just run it in the middle of an interactive rebase to see yourself.\n\nCould you elaborate on the intended/usual flow here?\nRebase => Get conflict => Fix conflict => run the script => ..??\n"},{"id":"450615","messageId":"nycvar.QRO.7.76.6.2203071745590.11118@tvgsbejvaqbjf.bet","threadId":"57453","inReplyTo":"CA+JQ7M-+kq1MTh+DG+HCmXkpsF5Esm_0V=4=2_DS2_ZYdjP2+g@mail.gmail.com","subject":"Re: rewinding interactive rebases","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2022-03-07T16:56:22Z","receivedAt":"2022-03-07T16:56:33Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi Erik & Oswald,\n\nit's not really obvious from the text quoted below what is being discussed\nhere, so let me simply top-post some thoughts:\n\nProblem statement: in the middle of an interactive rebase, the user would\nlike to choose a different rebase target, without having to abort the\nrebase.\n\nSuggested approach: implement support for `git rebase -i --nested --onto\n<commit> <base-commit>`, i.e. a `--nested` option.\n\nThe idea here is to generate a todo list (just like a fresh `git rebase -i\n--onto <commit> <base-commit>` would have done) and _prepend_ it to the\ncurrent todo list.\n\nTo support a nested `git rebase --abort`, we would probably want to insert\nsome marker after the newly-generated todo list (maybe a\nspecially-formatted comment such as `## END NESTED ##`).\n\nTo support nested `git rebase --rebase-merges`, we would need to populate\n`state.labels` by reading `$GIT_DIR/rebase-merge/refs-to-delete` first\nthing when generating the todo list.\n\nFor good measure, we should probably populate `state.commit2label` with\nthis list, too, looking up the respective OIDs via\n`refs/rewritten/<label>`.\n\nI realize that this is quite dense information for anybody unfamiliar with\nthe `sequencer.c` code, and that the idea is _not_ fully fleshed out, but\nI lack the time to implement it and wanted to get even just a\nhalf-finished idea out there.\n\nCiao,\nJohannes\n\nOn Tue, 1 Mar 2022, Erik Cervin Edin wrote:\n\n> On Tue, Mar 1, 2022 at 1:21 AM Oswald Buddenhagen\n> <oswald.buddenhagen@gmx.de> wrote:\n>\n> > On Mon, Feb 28, 2022 at 10:32:16PM +0100, Erik Cervin Edin wrote:\n> > >What's the connection to the original thread [...]?\n> > >\n> > that depends on what you want to interpret into the original thread,\n> > given that a bunch of use cases and solutions were mentioned. my\n> > solution is actually functionally identical to one of the later\n> > subthreads, as i found after the fact.\n>\n> Sorry but it's a long thread and at least I am unsure which parts you\n> are referring to and how your script fits into that.\n>\n> > >Maybe you could explain it a bit in the context of the problem.\n> > >\n> > there really isn't much to it. the git log + git reset are the essence.\n> > just run it in the middle of an interactive rebase to see yourself.\n>\n> Could you elaborate on the intended/usual flow here?\n> Rebase => Get conflict => Fix conflict => run the script => ..??\n>\n"},{"id":"450634","messageId":"YiZYI8/jY37hZxxa@ugly","threadId":"57453","inReplyTo":"nycvar.QRO.7.76.6.2203071745590.11118@tvgsbejvaqbjf.bet","subject":"Re: rewinding interactive rebases","fromName":"Oswald Buddenhagen","fromEmail":"oswald.buddenhagen@gmx.de","sentAt":"2022-03-07T19:08:19Z","receivedAt":"2022-03-07T19:08:34Z","isPatch":false,"sender":{"key":"oswald.buddenhagen@gmx.de","avatar":"https://avatars.githubusercontent.com/u/812380?v=4"},"body":"On Mon, Mar 07, 2022 at 05:56:22PM +0100, Johannes Schindelin wrote:\n>Problem statement: in the middle of an interactive rebase, the user \n>would like to choose a different rebase target, without having to abort \n>the rebase.\n>\nit didn't even occur to me to actually change the base (note that my \nscript has no --onto option, even though it wouldn't be that hard to \ndo). that stems from that fact that i have *really* rarely \n(intentionally) made an interactive rebase without (the equivalent of) \n--keep-base.\n\nfor me, it's about noticing that i need to rewrite some earlier commits \nagain before going forward.\n\n>The idea here is to generate a todo list (just like a fresh `git rebase \n>-i --onto <commit> <base-commit>` would have done) and _prepend_ it to \n>the current todo list.\n>\nyeah, that's essentially what the script does.\n\n>To support a nested `git rebase --abort`, we would probably want to insert\n>some marker after the newly-generated todo list (maybe a\n>specially-formatted comment such as `## END NESTED ##`).\n>\nin the few weeks i've been using the script so far (with a by now 80+ \ncommit series), i'd have found nested abort useful about twice, while \nrepeated \"flat\" rewinds are par for the course. i'm also slightly \nworried that i'd lose track of the stack and throw away too much (though \nstrictly speaking that's actually not unique to nesting; it would just \namplify the problem). my script already inserts a marker in the form of \n\"break\\n\\n\", and it gets really weird after several rewinds if i don't \nclean up. to make it less weird (and error-prone), one would have to \nactually start a new todo list, that is, actually throw the rest of the \nold todo list on a stack rather than prepending to it. so basically, \nchoose between linear and nested, but don't mix the two.\n\n"}]}