git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: Should --update-refs exclude refs pointing to the current HEAD?

From
SHStefan Haller <lists@haller-berlin.de>
Date
Mar 6, 2024, 21:00 UTC
Message-ID
<845ced9a-1f35-4100-a1ff-4243db2ba34f@haller-berlin.de>
In-Reply-To
<CABPp-BGO2ftEMHJDrf6yg3J4AfpKn=rpf_5Wt_WAS+Hi70KqPQ@mail.gmail.com>
On 06.03.24 03:57, Elijah Newren wrote:
> 1) What if there is a branch that is "just a copy" of one of the
> branches earlier in the "stack"?  Since it's "just a copy", shouldn't
> it be excluded for similar reasons to what you are arguing?  And, if
> so, which branch is the copy?

This is a good point, but in my experience it's a lot more rare. Maybe I'm looking at all this just from my own experience, and there might be other usecases that are very different from mine, but as far as I am concerned, copies of branches are not long-lived. There is no point in having two branches point at the same commit. When I create a copy of a branch, I do that only to rebase the copy somewhere else _immediately_, leaving the original branch where it was. Which means that I encounter copied branches only at the top of the stack, not in the middle. Which means that I'm fine with keeping the current behavior of "rebase --update-ref" to update both copies of that middle-of-the-stack branch, because it never happens in practice for me.

Show 13 quoted lines
> 2) Further, a "stack", to me at least, suggests a linear history
> without branching (i.e. each commit has at most one parent _and_ at
> most one child among the commits in the stack).  I designed `git
> replay` to handle diverging histories (i.e. rebasing multiple branches
> that _might_ share a subset of common history but none necessarily
> need to fully contain the others, though perhaps the branches do share
> some other contained branches), and I want it to handle replaying
> merges as well.  While `git rebase --update-refs` is absolutely
> limited to "stacks", and thus your argument might make sense in the
> context of `git rebase`, since you are bringing `git replay` into the
> mix, it needs to apply beyond a stack of commits.  It's not clear to
> me how to genericize your suggestions to handle cases other than a
> simple stack of commits, though.

I don't see a contradiction here. I don't tend to do this in practice, but I can totally imagine a tree of stacked branches that share some common base branches in the beginning and then diverge into different branches from there. It's true that "rebase --update-refs", when told to rebase one of the leaf branches, will destroy this tree because it pulls the base branches away from under the other leaf branches, but this is unrelated to my proposal, it has this problem today already. And it's awesome that git replay has a way to avoid this by rebasing the whole tree at once, keeping everything intact. Still, I don't see what's bad about excluding branches that point at the same commits as the leaf branches it is told to rebase when using "replay --contains". (I suppose what I'm suggesting is to treat "--contains" to mean "is included in the half-open interval from base to tip" of the revision range you are rebasing, rather than the closed interval.)

Maybe I should make this more explicit again: I'm not trying to solve the problem of making a copy of a stack of branches, and rebasing that copy somewhere else. I think this can't be solved except by making branch stacks a new concept in git, which I'm not sure we want to do.

Show 6 quoted lines
> 3) This is mostly covered in (1) and (2), but to be explicit: `git
> replay` is completely against the HEAD-is-special assumptions that are
> pervasive within `git rebase`, and your problem is entirely phrased as
> HEAD-is-special due to your call out of "the current branch".  Is your
> argument limited to such special cases?  (If so, it might still be
> valid for `git rebase`, of course.)

No, I don't think I need HEAD to be special. "The thing that I'm rebasing" is special, and it is always HEAD for git rebase, but it can be something else for replay.

Show 5 quoted lines
> 4a) `git replay` does what Junio suggests naturally, since it doesn't
> update the refs but instead gives commands which can be fed to `git
> update-ref --stdin`.  Thus, users can inspect the output of `git
> replay` and only perform the updates they want (by feeding a subset of
> the lines to update-ref --stdin).

At this point I probably need to explain that I'm rarely using the command line. I'm a user and co-maintainer of lazygit, and I want to make lazygit work in such a way that "it does the right thing" in as many cases as possible.

> 4b) For `git replay`, --contained is just syntactic sugar -- it isn't
> necessary.  git replay will allow you to list multiple branches that
> you want replayed, so you can specify which branches are relevant to
> you.

That's great, even if it means that I have to redo some of the work that --contains would already do for me, just because I want a slightly different behavior.

> 4c) For `git rebase --update-refs`, you can add `--interactive` and
> then delete the `update-ref` line(s) corresponding to the refs you
> don't want updated.

Yes, that's what I always do today to work around the problem. It's just easy to forget, and I find it annoying that I have to take this extra step every time.

One last remark: whenever I describe my use case involving copies of branches, people tell me not to do that, use detached heads instead, or other ways to achieve what I want. But then I don't understand why my proposal would make a difference for them. If you don't use copied branches, then why do you care whether "rebase --update-refs" or "replay --contained" moves those copies or not? I still haven't heard a good argument for why the current behavior is desirable, except for the one example of a degenerate stack that Phillip Wood described in [1].

-Stefan
[1] <https://public-inbox.org/git/
     98548a5b-7d30-543b-b943-fd48d8926a33@gmail.com/>
Previous: Elijah NewrenNext: Elijah Newren
Message 11 of 18 in “Should --update-refs exclude refs pointing to the current HEAD?”
  1. Stefan HallerApr 17, 2023
  2. Stefan HallerApr 17, 2023
  3. Kristoffer HaugsbakkApr 17, 2023
  4. Stefan HallerApr 17, 2023
  5. Felipe ContrerasApr 18, 2023
  6. Phillip WoodApr 17, 2023
  7. Stefan HallerApr 20, 2023
  8. Stefan HallerMar 5, 2024
  9. Junio C HamanoMar 5, 2024
  10. Elijah NewrenMar 6, 2024
  11. Stefan HallerMar 6, 2024
  12. Elijah NewrenMar 7, 2024
  13. Stefan HallerMar 7, 2024
  14. Elijah NewrenMar 9, 2024
  15. Stefan HallerMar 12, 2024
  16. Kristoffer HaugsbakkMar 7, 2024
  17. Elijah NewrenMar 7, 2024
  18. Stefan HallerMar 24, 2024

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.