{"thread":{"id":"60692","subject":"Leveraging --rebase-merges --update-refs mechanism to rebase several branches in one run","startedAt":"2024-01-06T19:14:16Z","lastAt":"2024-01-07T15:31:22Z","messageCount":4,"participants":["Yann Dirson","Johannes Sixt"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"486366","messageId":"133456672.1820149400.1704567932308.JavaMail.root@zimbra39-e7","threadId":"60692","inReplyTo":"763603689.1820092086.1704566524953.JavaMail.root@zimbra39-e7","subject":"Leveraging --rebase-merges --update-refs mechanism to rebase several branches in one run","fromName":"Yann Dirson","fromEmail":"ydirson@free.fr","sentAt":"2024-01-06T19:05:32Z","receivedAt":"2024-01-06T19:14:16Z","isPatch":false,"sender":{"key":"ydirson@free.fr","avatar":null},"body":"This idea comes from a repo[1] where I am experimenting with code variants:\non one side I have a branch where I add to the core mechanisms, and on the\nother(s) I have several branches where I experiment with different rendering\noptions.\n\nThere are indeed 2 different workflows here:\n- improving the variants themselves, where occasionally some fixup or new\n  commit for the core branch gets introduced\n- adding feature to the core branch, then merging that into each variant,\n  where fixups already appear quite regularly\n\nThat produces a set closely-related branches with lots of merges, and applying\nthe fixups is a bit tricky.\n\nThe \"core + 1 variant\" case pretty much works out of the box, with --rebase-merges\nand --update-refs generating a perfect instructions sheet.\n\nBut if I was to rebase just one variant while rewriting the core branch, obviously\nall other variants would still fork off the pre-rewrite core branch, and we'd loose\nall chances of automating the same work on the other variants.\n\nOTOH, if I get `git-rebase` to generate the instruction sheets for those other\nvariants first, strip them (manually) from the common part, and insert them in the\ninstruction sheet of my \"core + 1 variant\" case ... I do get the whole of my branches\nrebased together, and sharing the updated core.\n\n\nSo the question is, would there be any obstacles to let git-rebase automate this\ncompletely?  By chance it could even be a trivial change?\nI guess we'd only want this feature to be enabled under certain conditions, like\n--update-refs being specified so the many heads of the rebase would be reachable.\n\n\n[1] https://github.com/ydirson/test-yew-tutorial/tree/opr is the \"core\" branch,\nand branches opr-* are the variants\n\n"},{"id":"486372","messageId":"ed9f9fc5-c398-4424-9b5b-dbe618cca2ed@kdbg.org","threadId":"60692","inReplyTo":"133456672.1820149400.1704567932308.JavaMail.root@zimbra39-e7","subject":"Re: Leveraging --rebase-merges --update-refs mechanism to rebase several branches in one run","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2024-01-07T08:57:45Z","receivedAt":"2024-01-07T09:39:42Z","isPatch":false,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Am 06.01.24 um 20:05 schrieb Yann Dirson:\n> The \"core + 1 variant\" case pretty much works out of the box, with --rebase-merges\n> and --update-refs generating a perfect instructions sheet.\n> \n> But if I was to rebase just one variant while rewriting the core branch, obviously\n> all other variants would still fork off the pre-rewrite core branch, and we'd loose\n> all chances of automating the same work on the other variants.\n> \n> OTOH, if I get `git-rebase` to generate the instruction sheets for those other\n> variants first, strip them (manually) from the common part, and insert them in the\n> instruction sheet of my \"core + 1 variant\" case ... I do get the whole of my branches\n> rebased together, and sharing the updated core.\n\nNot a complete automation, but... You can merge all variant branches\ninto a temporary branch (or detached HEAD), even if that are merely -s\nours merges, and then rebase the temporary branch with --rebase-merges\n--update-refs. This will generate the instruction sheet that you want.\nYou can remove the final merge instructions (the temporary ones) from\nthe instruction sheet if you do not want them to be executed.\n\n-- Hannes\n\n"},{"id":"486373","messageId":"1930018756.1822864601.1704627466836.JavaMail.root@zimbra39-e7","threadId":"60692","inReplyTo":"ed9f9fc5-c398-4424-9b5b-dbe618cca2ed@kdbg.org","subject":"Re: Leveraging --rebase-merges --update-refs mechanism to rebase several branches in one run","fromName":"Yann Dirson","fromEmail":"ydirson@free.fr","sentAt":"2024-01-07T11:37:46Z","receivedAt":"2024-01-07T11:38:03Z","isPatch":false,"sender":{"key":"ydirson@free.fr","avatar":null},"body":"Johannes Sixt wrote:\n> Am 06.01.24 um 20:05 schrieb Yann Dirson:\n> > The \"core + 1 variant\" case pretty much works out of the box, with\n> > --rebase-merges\n> > and --update-refs generating a perfect instructions sheet.\n> > \n> > But if I was to rebase just one variant while rewriting the core\n> > branch, obviously\n> > all other variants would still fork off the pre-rewrite core\n> > branch, and we'd loose\n> > all chances of automating the same work on the other variants.\n> > \n> > OTOH, if I get `git-rebase` to generate the instruction sheets for\n> > those other\n> > variants first, strip them (manually) from the common part, and\n> > insert them in the\n> > instruction sheet of my \"core + 1 variant\" case ... I do get the\n> > whole of my branches\n> > rebased together, and sharing the updated core.\n> \n> Not a complete automation, but... You can merge all variant branches\n> into a temporary branch (or detached HEAD), even if that are merely\n> -s\n> ours merges, and then rebase the temporary branch with\n> --rebase-merges\n> --update-refs. This will generate the instruction sheet that you\n> want.\n> You can remove the final merge instructions (the temporary ones) from\n> the instruction sheet if you do not want them to be executed.\n\nNice idea, and this is indeed automatable for the most part, Q&D PoC below.\n\nThere are a few things I can see missing in this PoC:\n\n- removal of the final merge from instruction sheet\n\n  Could be done by wrapping $EDITOR - I'm not particularly fond doing things\n  behind the user's back, but I lack better ideas.\n\n- restoration of HEAD\n\n  In the general case it cannot be done from the script, so we would naturally\n  want to do that from the instruction sheet?\n\n  While I was at manually removing the final merge, I experimented with changing\n  the \"reset onto\" to \"reset <a branch name>\", but that resulted in moving HEAD\n  to the pre-rebase version of the requested branch.\n\n- When aborting the rebase HEAD still points to the extra merge\n\n  This is indeed a special case of the above, where instruction sheet cannot\n  be used, and where the script could help since we won't be in the middle of\n  a rebase when git-rebase stops.\n\n  There does not seem to be any documented exit-code protocol to tell the\n  git-rebase caller the user aborted.  I guess \"HEAD pointing to this commit\"\n  could be used to identify the abort.\n\n\n\n---- 8< ---- git-rebase-batch\n#!/bin/bash\nset -e\n\ndie() {\n    echo >&2 \"ERROR: $0: $*\"\n    exit 1\n}\n\nREBASE_OPTS=(--interactive --rebase-merges --update-refs)\n# all args before \"--\" are passed to git-rebase\nwhile [ $# -ge 1 ]; do\n    case \"$1\" in\n        --) shift; break;;\n        *) REBASE_OPTS+=(\"$1\"); shift;;\n    esac\ndone\n\n[ $# -ge 3 ] || die \"need cutting-point and at least 2 refs to rebase\"\nCUT=\"$1\"\nshift\n\ngit checkout --detach \"$CUT\"\ngit merge -s ours \"$@\" -m \"temporary handle for all rebased branches\"\ngit rebase \"${REBASE_OPTS[@]}\" \"$CUT\" HEAD\n\n# here we can be in the middle of interactive rebase, cannot perform\n# any kind of cleanup (which would include restoring HEAD ref to its\n# original destination)\n---- 8< ----\n\n"},{"id":"486377","messageId":"2065332308.1823640486.1704641474724.JavaMail.root@zimbra39-e7","threadId":"60692","inReplyTo":"1930018756.1822864601.1704627466836.JavaMail.root@zimbra39-e7","subject":"Interactive rebase doc (Was: Leveraging --rebase-merges --update-refs mechanism to rebase several branches in one run)","fromName":"Yann Dirson","fromEmail":"ydirson@free.fr","sentAt":"2024-01-07T15:31:14Z","receivedAt":"2024-01-07T15:31:22Z","isPatch":false,"sender":{"key":"ydirson@free.fr","avatar":null},"body":"> Johannes Sixt wrote:\n> > Am 06.01.24 um 20:05 schrieb Yann Dirson:\n> > > The \"core + 1 variant\" case pretty much works out of the box,\n> > > with\n> > > --rebase-merges\n> > > and --update-refs generating a perfect instructions sheet.\n> > > \n> > > But if I was to rebase just one variant while rewriting the core\n> > > branch, obviously\n> > > all other variants would still fork off the pre-rewrite core\n> > > branch, and we'd loose\n> > > all chances of automating the same work on the other variants.\n> > > \n> > > OTOH, if I get `git-rebase` to generate the instruction sheets\n> > > for\n> > > those other\n> > > variants first, strip them (manually) from the common part, and\n> > > insert them in the\n> > > instruction sheet of my \"core + 1 variant\" case ... I do get the\n> > > whole of my branches\n> > > rebased together, and sharing the updated core.\n> > \n> > Not a complete automation, but... You can merge all variant\n> > branches\n> > into a temporary branch (or detached HEAD), even if that are merely\n> > -s\n> > ours merges, and then rebase the temporary branch with\n> > --rebase-merges\n> > --update-refs. This will generate the instruction sheet that you\n> > want.\n> > You can remove the final merge instructions (the temporary ones)\n> > from\n> > the instruction sheet if you do not want them to be executed.\n> \n> Nice idea, and this is indeed automatable for the most part, Q&D PoC\n> below.\n> \n> There are a few things I can see missing in this PoC:\n> \n> - removal of the final merge from instruction sheet\n> \n>   Could be done by wrapping $EDITOR - I'm not particularly fond doing\n>   things\n>   behind the user's back, but I lack better ideas.\n> \n> - restoration of HEAD\n> \n>   In the general case it cannot be done from the script, so we would\n>   naturally\n>   want to do that from the instruction sheet?\n> \n>   While I was at manually removing the final merge, I experimented\n>   with changing\n>   the \"reset onto\" to \"reset <a branch name>\", but that resulted in\n>   moving HEAD\n>   to the pre-rebase version of the requested branch.\n\nRelated to this, I turned to the rebase manpage to get reference\ninformation about update-ref, but I could not find anything about it:\nonly --update-refs is described, but this description also only seems to\naddress the non-interactive behavior.\n\nIn fact:\n- there does not appear to be a reference to the interactive\ninstruction sheet in the rebase doc, only in the default template\n- --interactive only directs the user to \"Splitting commits\", not to\n\"interactive mode\"\n- the \"interactive mode\" section really looks more like a didactic intro\nto interactive rebase than like a reference doc\n\nWould it seem OK to change things as follows?\n\n- move current \"interactive mode\", \"splitting commits\", and \"rebasing merges\"\ncontents into a new gitrebase(7) guide\n- leave in git-rebase(1) only an \"interactive mode\" with the reference doc\nfor the instruction sheet, and a pointer to the guide for detailed walkthrough\n- selectively move back a few things like --strategy paragraph from\n\"rebasing merges\"\n\nBest regards,\n-- \nYann\n"}]}