From: Ivan Shapovalov <intelfx@intelfx.name>
To: phillip.wood@dunelm.org.uk, git@vger.kernel.org
Cc: Elijah Newren <newren@gmail.com>,
Derrick Stolee <stolee@gmail.com>,
Junio C Hamano <gitster@pobox.com>,
Alex Henrie <alexhenrie24@gmail.com>
Subject: Re: [PATCH] rebase: add `--update-refs=interactive`
Date: Wed, 12 Feb 2025 21:18:36 +0400 [thread overview]
Message-ID: <f0fa961084281b1d5948f59c42cf0c87e731d9bc.camel@intelfx.name> (raw)
In-Reply-To: <5b605c3e-ef6a-433a-9637-1e8f277dfde9@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 8096 bytes --]
On 2025-02-12 at 14:26 +0000, Phillip Wood wrote:
> Hi Ivan
>
> On 11/02/2025 18:11, Ivan Shapovalov wrote:
> > On 2025-02-11 at 14:36 +0000, Phillip Wood wrote:
> > > On 10/02/2025 19:16, Ivan Shapovalov wrote:
> > >
> > > I'm a bit surprised by this - I'd have thought there is more scope for
> > > messing things up by making a mistake when editing the todo list that
> > > for the non-interactive case. Are you able to explain a in a bit more
> > > detail the problem you have been experiencing please?
> >
> > I often find myself managing multiple interdependent downstream patch
> > branches, rebasing them en masse from release to release. Eventually,
> > I found myself typing `git rebase -i --update-refs` more often than
> > not, so I just stuck it into the config as `rebase.updateRefs=true`.
> >
> > However, sometimes I also maintain those patch branches for multiple
> > releases. Consider a (hypothetical) situation:
> >
> > - tag v1
> > - tag v2
> > - branch work/myfeature-v1 that is based on tag v1
> >
> > Now, I want to rebase myfeature onto v2, so I do this:
> >
> > $ git checkout work/myfeature-v1
> > $ git checkout -b work/myfeature-v2
> > $ git rebase --onto v2 v1 work/myfeature-v2
> >
> > With `rebase.updateRefs=true`, this ends up silently updating _both_
> > work/myfeature-v2 and work/myfeature-v1.
>
> Thanks for the explanation. So this is about copying a branch and then
> rebasing the copy without updating the original. A while ago there was a
> discussion[1] about excluding branches that match HEAD from
> "--update-refs". Maybe we should revisit that with a view to adding a
> config setting that excludes copies of the current branch from
> "--update-refs".
This idea stops working once you have a bunch of interdependent feature
branches (consider two branches work/myfeatureA and work/myfeatureB,
with the latter based on the former, with each having two versions as
described above, and then you rebase work/myfeatureB-v2 from v1 onto v2
and expect to update work/myfeatureA-v2 but not work/myfeatureA-v1).
Excluding branches that match HEAD is a very narrow workaround that
only fixes one particular instance of one particular workflow.
I don't understand the opposition, really — in my understanding, an
ability to restrict update-refs to interactive runs is a significantly
useful mechanism that does not impose any particular policy. It answers
the question of "I want git to _suggest_ updating refs by default, but
only if I have a chance to confirm/reject each particular update".
>
> Maintaining multiple versions of the same branch sounds like a lot of
> work - whats the advantage over merging a single branch into each release?
Different people, different workflows.
--
Ivan Shapovalov / intelfx /
>
> [1]
> https://lore.kernel.org/git/adb7f680-5bfa-6fa5-6d8a-61323fee7f53@haller-berlin.de/
>
> > With this in mind, I wrote this patch such that update-refs only
> > happens for interactive rebases, when I have the chance to inspect the
> > todo list and prune unwanted update-refs items.
> >
> > Does this make sense? I made an attempt to explain this motivation in
> > the commit message, so if this does make sense but the commit message
> > doesn't, please tell me how to improve/expand the latter.
>
> I think having the example in the commit message would help - I feel
> like I've now got a clear idea of the problem you are facing whereas I
> didn't understand what the issue was just from the commit message.
>
> > > > Try to find a middle ground by introducing a third value,
> > > > `--update-refs=interactive` (and `rebase.updateRefs=interactive`)
> > > > which means `--update-refs` when starting an interactive rebase and
> > > > `--no-update-refs` otherwise. This option is primarily intended to be
> > > > used in the gitconfig, but is also accepted on the command line
> > > > for completeness.
> > >
> > > I'm not convinced allowing "--update-refs=interactive" on the
> > > commandline improves the usability - why wouldn't I just say
> > > "--update-refs" if I want to update all the branches or
> > > "--no-update-refs" if I don't? I also think supporting
> > > --update-refs=(true|false) is verbose and unnecessary as the user can
> > > already specify their intent with the existing option.
> >
> > I make heavy use of aliases for various workflows, which invoke one
> > another (making use of the ability to override earlier command-line
> > options with the latter ones), and the ability to spell out
> > `alias.myRebase = rebase ... --update-refs=interactive ...` was useful.
>
> You can write your alias as
>
> alias.myRebase = -c rebase.updaterefs=interactive rebase ...
>
> instead. It is not quite as convenient but it means we don't have to add
> complexity to the command line interface that is only useful for aliases
> (I can't think of a use for "--update-refs=interactive" outside of an
> alias definition).
>
> > Re: specifying `=(true|false)`, the intention was to avoid unnecessary
> > divergence, both in UX and code (and reuse the parser to simplify said
> > code). If you think it will be harmful, I'll remove that.
>
> It would be even simpler if we didn't change the command line interface ;)
>
> > > > rebase.updateRefs::
> > > > - If set to true enable `--update-refs` option by default.
> > > > + If set to true, enable the `--update-refs` option of
> > > > + linkgit:git-rebase[1] by default. When set to 'interactive',
> > >
> > > Our existing documentation is inconsistent in how it formats config
> > > values. rebase.backend uses "apply", rebase.rebaseMerges uses
> > > `rebase-cousins` which I think matches other commands and is therefore
> > > what we should use here and rebase.missingCommitCheck uses a mixture
> > > with "warn" and `drop`.
> >
> > Apologies, I'm not sure I understood what exactly you were suggesting
> > here. Did you mean to suggest wrapping "interactive" in backticks
> > instead of single quotes?
>
> Sorry that wasn't very clear. Yes that is what I was trying to say.
>
> > > > + if (v >= 0)
> > > > + return v ? UPDATE_REFS_ALWAYS : UPDATE_REFS_NO;
> > > > + else if (!strcmp("interactive", value))
> > > > + return UPDATE_REFS_INTERACTIVE;
> > > > +
> > > > + die(_("bad %s value '%s'; valid values are boolean or \"interactive\""), desc, value);
> > >
> > > I think we normally say "invalid" or "unknown" rather than "bad" in our
> > > error messages. It'd be clearer just to list the possible values as
> > > there are only three of them.
> >
> > It's not just three (see other review from Junio), otherwise OK
>
> As this is a hint in a error message I don't think we need to
> exhaustively list all the possible synonyms git accepts for "true" and
> "false"
>
> > > > + /* coerce --update-refs=interactive into yes or no.
> > > > + * we do it here because there's just too much code below that handles
> > > > + * {,config_}update_refs in one way or another and modifying it to
> > > > + * account for the new state would be too invasive.
> > > > + * all further code uses {,config_}update_refs as a tristate. */
> > >
> > > I think we need to find a cleaner way of handling this. There are only
> > > two mentions of options.config_update_refs below this point - is it
> > > really so difficult for those to use the enum?
> >
> > See above; I opted to make this change as non-invasive as possible and
> > keep the complex argument validation logic (lines 1599, 1606-1609)
> > intact because I'm not even sure I understand it right.
> >
> > Besides, even if I convert those uses to use enumerators, I still
> > wouldn't want to deal with non-tristate values beyond this point.
>
> We could add a new boolean variable which is initalized here and use
> that instead in the code below. Of the code below could just call
> should_update_refs() to convert the enum to a boolean.
>
> Best Wishes
>
> Phillip
>
>
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 862 bytes --]
next prev parent reply other threads:[~2025-02-12 17:18 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-10 19:16 [PATCH] rebase: add `--update-refs=interactive` Ivan Shapovalov
2025-02-10 20:22 ` D. Ben Knoble
2025-02-11 11:33 ` Ivan Shapovalov
2025-02-11 16:50 ` Junio C Hamano
2025-02-11 17:36 ` Ivan Shapovalov
2025-02-11 19:28 ` D. Ben Knoble
2025-02-11 19:29 ` D. Ben Knoble
2025-02-11 14:36 ` Phillip Wood
2025-02-11 18:11 ` Ivan Shapovalov
2025-02-12 14:26 ` Phillip Wood
2025-02-12 16:58 ` Junio C Hamano
2025-02-13 9:43 ` Phillip Wood
2025-02-12 17:18 ` Ivan Shapovalov [this message]
2025-02-13 9:43 ` phillip.wood123
2025-02-13 12:04 ` Ivan Shapovalov
2025-02-19 14:52 ` phillip.wood123
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=f0fa961084281b1d5948f59c42cf0c87e731d9bc.camel@intelfx.name \
--to=intelfx@intelfx.name \
--cc=alexhenrie24@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=newren@gmail.com \
--cc=phillip.wood@dunelm.org.uk \
--cc=stolee@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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 NNTP newsgroup(s).