[Restoring part of Stefan's earlier message so I can respond to both that piece, as well as add to the ideas Junio presents.] Hi, On Tue, Mar 5, 2024 at 8:22 AM Junio C Hamano <gitster@xxxxxxxxx> wrote: > > Stefan Haller <lists@xxxxxxxxxxxxxxxx> writes: > > >> And I now see that "git replay --contained --onto" has the same problem, > >> which I find very unfortunate. In my opinion, "contained" should only > >> include refs that form a stack, but not copies of the current branch. I wouldn't want to change the default. Even if we were to add an option, I'm not entirely sure what it should even implement. In addition to Phillip's previous response in the thread, and part of Junio's response below (which I'll add to): 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? 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. 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.) 4) Aren't there easier ways to handle this -- for both rebase and replay? I'll suggest some alternatives below... > >> Both of these cases could be fixed by --update-refs not touching any > >> refs that point to the current HEAD. I'm having a hard time coming up > >> with cases where you would ever want those to be updated, in fact. > > The point of "update-refs", as I understand it, is that in addition > to the end point of the history (E in "git rebase --onto N O E"), > any branch tips that are between O..E can be migrated to point at > their rewritten counterparts. So I am not sure how it fundamentally > solves much by protecting only refs that point at a single commit > ("the current HEAD" in your statement). > > When I want to see how the rebased history would look like without > touching the original, I often rebase a detached HEAD (i.e. instead > of the earlier one, use "git rebase --onto N O E^0", or when > rebasing the current branch, "git rebase [--onto N] O HEAD^0") and > that would protect the current branch well, but --update-refs of > course would not work well. There is no handy place like detached > HEAD that can be used to save rewritten version of these extra > branch tips. > > If branch tips A, B, and C are involved in the range of commits > being rewritten, one way to help us in such a situation may be to > teach "git rebase" to (1) somehow create a new set of proposed-A, > proposed-B, and proposed-C refs (they do not have to be branches), > while keeping the original A, B, and C intact, (2) allow us to > inspect the resulting refs, compare the corresponding ones from > these two sets, and (3) allow us to promote (possibly a subset of) > proposed- ones to their counterpart real branches after we inspect > them. The latter two do not have to be subcommands of "git rebase" > but can be separate and new commands. Here, Junio is suggesting one alternative, and it's already implemented in `git replay`. Let me extend upon it and add two other alternatives as well: 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). 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. (This doesn't help with `git rebase`, because `--update-refs` is the only way to get additional branches replayed.) 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.