-
Notifications
You must be signed in to change notification settings - Fork 322
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
jj
unexpectedly simplifies ancestry when rewriting a commit that is both a direct child and an indirect descendant of another commit
#2600
Comments
If so, should I'm guessing Git supports it, in which case we have to be able to pull such commits from a remote. |
Yes, and GitHub (and probably GitLab and others) create these all the time. Projects that use GitHub's default way of integrating PRs (called "Merge", I think) will have lots of these merges.
I'm not sure. To me, it's surprising if commands like
If the user abandoned C, they would probably want D to become a child of only B, but it also seems reasonable to keep the shape of the history by making making D a child of B and A. There's also this degenerate case:
Here, I think it's clear that abandoning C should not leave B and B (duplicated) as parents of D. I think it's also clear that abandoning A should not change D's parents. I would also say that abandoning B should result in D having C and A as parents. |
For the degenerate case, I'm guessing Git does not allow duplicated parents? Here are a few thoughts about implementation difficulties. Let's say that
Abandoning From the implementation standpoint, however, the above behavior is not trivial to reconcile with the current behavior of abandoning
leaving If we change the behavior and make abandoning Lines 345 to 348 in 22ad4d7
will probably need reworking. The assumption there is already false, but the fact that |
Good point. I think that's a good argument for not having too much smarts in the auto-rebasing code. If the user wants to linearize history, they can manually update D to have just one parent with |
Instead of |
Specifically, I think it's this section that reshapes the graph in the case of Lines 445 to 456 in 16620e0
It dates back all the way to 4e0a89b, together with the test: Lines 525 to 537 in 16620e0
|
jj
unexpectedly simplifies ancestry when rewriting a commit that is both a direct child and an indirect descendant of another commit
It In Git, a commit's direct parent is allowed to also be an indirect ancestor at the same time. `jj` currently tries to prevent this situation, but does allow it. The correctness of `rebase -r A -d descendant_of_A` currently depends on this jj-specific behavior; we should change that. Cc martinvonz#2600 This is an independent problem from the one the parent commit describes, though it affects the same piece of code.
It In Git, a commit's direct parent is allowed to also be an indirect ancestor at the same time. `jj` currently tries to prevent this situation, but does allow it. The correctness of `rebase -r A -d descendant_of_A` currently depends on this jj-specific behavior; we should change that. Cc martinvonz#2600 This is an independent problem from the one the parent commit describes, though it affects the same piece of code.
It In Git, a commit's direct parent is allowed to also be an indirect ancestor at the same time. `jj` currently tries to prevent this situation, but does allow it. The correctness of `rebase -r A -d descendant_of_A` currently depends on this jj-specific behavior; we should change that. Cc martinvonz#2600 This is an independent problem from the one the parent commit describes, though it affects the same piece of code.
It In Git, a commit's direct parent is allowed to also be an indirect ancestor at the same time. `jj` currently tries to prevent this situation, but does allow it. The correctness of `rebase -r A -d descendant_of_A` currently depends on this jj-specific behavior; we should change that. Cc martinvonz#2600 This is an independent problem from the one the parent commit describes, though it affects the same piece of code.
This makes the code more robust, allowing complex rebases of perhaps already rebased commits. Thus, it is no longer dependent on martinvonz#2600. We could probably achieve that in other ways, but it would become quite difficult to reason about when implementing `rebase -r --before/--after`.
This makes the code more robust, allowing complex rebases of perhaps already rebased commits. Thus, it is no longer dependent on martinvonz#2600. We could probably achieve that in other ways, but it would become quite difficult to reason about when implementing `rebase -r --before/--after`.
This makes the code more robust, allowing complex rebases of perhaps already rebased commits. Thus, it is no longer dependent on martinvonz#2600. We could probably achieve that in other ways, but it would become quite difficult to reason about when implementing `rebase -r --before/--after`.
This makes the code more robust, allowing complex rebases of perhaps already rebased commits. Thus, it is no longer dependent on martinvonz#2600. We could probably achieve that in other ways, but it would become quite difficult to reason about when implementing `rebase -r --before/--after`.
This makes the code more robust, allowing complex rebases of perhaps already rebased commits. Thus, it is no longer dependent on martinvonz#2600. We could probably achieve that in other ways, but it would become quite difficult to reason about when implementing `rebase -r --before/--after`.
This makes the code more robust, allowing complex rebases of perhaps already rebased commits. Thus, it is no longer dependent on martinvonz#2600. We could probably achieve that in other ways, but it would become quite difficult to reason about when implementing `rebase -r --before/--after`.
This makes the code more robust, allowing complex rebases of perhaps already rebased commits. Thus, it is no longer dependent on martinvonz#2600. We could probably achieve that in other ways, but it would become quite difficult to reason about when implementing `rebase -r --before/--after`.
This makes the code more robust, allowing complex rebases of perhaps already rebased commits. Thus, it is no longer dependent on martinvonz#2600. We could probably achieve that in other ways, but it would become quite difficult to reason about when implementing `rebase -r --before/--after`.
This makes the code more robust, allowing complex rebases of perhaps already rebased commits. Thus, it is no longer dependent on martinvonz#2600. We could probably achieve that in other ways, but it would become quite difficult to reason about when implementing `rebase -r --before/--after`.
This makes the code more robust, allowing complex rebases of perhaps already rebased commits. Thus, it is no longer dependent on martinvonz#2600. We could probably achieve that in other ways, but it would become quite difficult to reason about when implementing `rebase -r --before/--after`.
This makes the code more robust, allowing complex rebases of perhaps already rebased commits. Thus, it is no longer dependent on martinvonz#2600. We could probably achieve that in other ways, but it would become quite difficult to reason about when implementing `rebase -r --before/--after`.
This makes the code more robust, allowing complex rebases of perhaps already rebased commits. Thus, it is no longer dependent on martinvonz#2600. We could probably achieve that in other ways, but it would become quite difficult to reason about when implementing `rebase -r --before/--after`.
This makes the code more robust, allowing complex rebases of perhaps already rebased commits. Thus, it is no longer dependent on martinvonz#2600. We could probably achieve that in other ways, but it would become quite difficult to reason about when implementing `rebase -r --before/--after`.
Note that one of the new tests panics; this is a newly discovered bug. In Git, a commit's direct parent is allowed to also be an indirect ancestor at the same time. `jj` currently tries to prevent this situation, but does allow it. The correctness of `rebase -r A -d descendant_of_A` currently depends on this jj-specific behavior; we should change that. Cc martinvonz#2600
Right now, I don't really know, but your vote for an error message is helpful. I agree that this will be rare for users doing real work. However, I can think of two situations where this seems unfortunate and likely to confuse people: when writing tests, and when somebody experiments with I think a more detailed hint with the error message might help, but I'm not sure what it should say. This also affects |
Also, right now, the error looks extra-scary. We'd probably want to make it look friendlier.
It shouldn't be too hard to special-case this specific error. I'm not sure if it's worth it to try to do something more elegant to do with it. |
There are more complicated tests in test_rebase_command and (shortly, hopefully) test_abandon_command, but it can't hurt to also have a simple demo of martinvonz#2600. cc: martinvonz#2600
There are more complicated tests in test_rebase_command and (shortly, hopefully) test_abandon_command, but it can't hurt to also have a simple demo of martinvonz#2600. cc: martinvonz#2600
See comment inline for details.
See comment inline for details.
See comments inline for details.
See comments inline for details. In particular, I wanted to make sure these behaviors are not affected by martinvonz#2646. They don't seem to be.
See comments inline for details. Cc martinvonz#2600. In particular, I wanted to make sure these behaviors are not affected by martinvonz#2646. They don't seem to be.
See comments inline for details. Cc martinvonz#2600. In particular, I wanted to make sure these behaviors are not affected by martinvonz#2646. They don't seem to be. The tests ended up weirder than expected because of martinvonz#2600 (comment). Even though, for now, the behavior of tests is unaffected by that issue, the *expected* behavior is different.
See comments inline for details. Cc martinvonz#2600. In particular, I wanted to make sure these behaviors are not affected by martinvonz#2646. They don't seem to be. The tests ended up weirder than expected because of martinvonz#2600 (comment). Even though, right now, the behavior of tests is unaffected by that issue, the *expected* behavior is different.
See comments inline for details. Cc #2600. In particular, I wanted to make sure these behaviors are not affected by #2646. They don't seem to be. The tests ended up weirder than expected because of #2600 (comment). Even though, right now, the behavior of tests is unaffected by that issue, the *expected* behavior is different.
I think the conclusion from #2600 is that at least auto-rebasing should not simplify merge commits that merge a commit with its ancestor. Let's start by adding an option for that in the library.
I think the conclusion from #2600 is that at least auto-rebasing should not simplify merge commits that merge a commit with its ancestor. Let's start by adding an option for that in the library.
I think the conclusion from #2600 is that at least auto-rebasing should not simplify merge commits that merge a commit with its ancestor. Let's start by adding an option for that in the library.
I think the conclusion from #2600 is that at least auto-rebasing should not simplify merge commits that merge a commit with its ancestor. Let's start by adding an option for that in the library.
I think the conclusion from #2600 is that at least auto-rebasing should not simplify merge commits that merge a commit with its ancestor. Let's start by adding an option for that in the library.
Following #3551, can this issue be closed? It looks like all the todo items have been addressed, unless I'm mistaken. |
I think so, yes. Ilya can reopen if he feels differently. |
Description
I have always assumed that we do not allow a commit to be a direct child and an indirect descendant of another commit at the same time. See, for example:
jj/cli/tests/test_rebase_command.rs
Lines 264 to 269 in 5186066
from #538.
jj abandon
has similar functionality, see #2601.However, it is actually possible to create such commits. Even simple commands like
jj describe
misbehave in such situations.I originally discovered this in ilyagr@rebase-bug (see the test), but that bug seemed less relevant after I realized
describe
is also affected.Is this a recent change? What is the desired behavior here?
Steps to Reproduce the Problem
Start with this tree:
jj new mpv zmk -m test
. (Aside:jj rebase -r another_commit -d mpv -d zmk
produces a similar result.).We get:
jj describe -r mpv -m newname
(Aside:jj edit mpv; touch qq; jj status
produces a similar result)Actual Behavior
Expected Behavior
Either
jj new
results in a linear history after step 1 orjj describe
keeps the shape of the graph after step 2.Specifications
Update: From the discussion below up to #2600 (comment), it seems this is actually 2.5 issues:
jj describe
,jj edit
messing up the shape and any similar bugs we can find.rebase
andabandon
(and others?) to create children that are also descendantsrebase -r
onto descendants and any similar issues.Lots of fun tests to write!
The text was updated successfully, but these errors were encountered: