martinvonz / jj

A Git-compatible VCS that is both simple and powerful
https://martinvonz.github.io/jj/
Apache License 2.0
8.39k stars 288 forks source link

`jj new` and `jj rebase` commit order does not produce #4499

Open chriskrycho opened 3 weeks ago

chriskrycho commented 3 weeks ago

Description

Steps to Reproduce the Problem

  1. Given parents a and b, create a merge commit by doing jj new a b -m "merge b into a".
  2. Create a new commit (it can be empty!) and rebase it, jj rebase -r c -d a -d b, providing the two destinations in the same order as given in the jj new (i.e. in step 1).
  3. Note that the merge topology is inverted between the two.

Expected Behavior

The graph produced by passing changes in the same order to the new and rebase operations should be the same.

Actual Behavior

The resulting graphs have the inverse orders.

Screenshot of Fork showing final state of repo

Working history to create the problem ```sh $ jj git init --colocate Initialized repo in "." $ jj desc -m "base (don't want separate histories in Git)" Working copy now at: q 5b8eccb1 (empty) base (don't want separate histories in Git) Parent commit : z 00000000 (empty) (no description set) $ jj new -m "a" Working copy now at: s 30db9a96 (empty) a Parent commit : q 5b8eccb1 (empty) base (don't want separate histories in Git) $ jj new q -m "b" Working copy now at: x 93a82b0e (empty) b Parent commit : q 5b8eccb1 (empty) base (don't want separate histories in Git) $ jj l @ x hello@chriskrycho.com 2024-09-17 19:36:13 93a82b0e │ (empty) b │ ○ s hello@chriskrycho.com 2024-09-17 19:36:08 30db9a96 ├─┘ (empty) a ○ q hello@chriskrycho.com 2024-09-17 19:35:56 HEAD@git 5b8eccb1 │ (empty) base (don't want separate histories in Git) ◆ z root() 00000000 $ jj new s x -m "merge s into x ('a' into 'b')" Working copy now at: t 1d8c9d26 (empty) merge s into x ('a' into 'b') Parent commit : s 30db9a96 (empty) a Parent commit : x 93a82b0e (empty) b $ jj l @ t hello@chriskrycho.com 2024-09-17 19:36:38 1d8c9d26 ├─┐ (empty) merge s into x ('a' into 'b') │ ○ x hello@chriskrycho.com 2024-09-17 19:36:13 93a82b0e │ │ (empty) b ○ │ s hello@chriskrycho.com 2024-09-17 19:36:08 HEAD@git 30db9a96 ├─┘ (empty) a ○ q hello@chriskrycho.com 2024-09-17 19:35:56 5b8eccb1 │ (empty) base (don't want separate histories in Git) ◆ z root() 00000000 $ jj new q -m "c" Working copy now at: m 7fd996e5 (empty) c Parent commit : q 5b8eccb1 (empty) base (don't want separate histories in Git) $ jj rebase -r m -d s -d x Rebased 1 commits onto destination Working copy now at: m 2e53189b (empty) c Parent commit : s 30db9a96 (empty) a Parent commit : x 93a82b0e (empty) b $ jj desc -m "The commit once described as 'c' (now a merge) This *should* have the same merge semantics as the `jj new` output" Working copy now at: m f96adeaa (empty) The commit once described as 'c' (now a merge) Parent commit : s 30db9a96 (empty) a Parent commit : x 93a82b0e (empty) b $ jj l @ m hello@chriskrycho.com 2024-09-17 19:40:45 f96adeaa ├─┐ (empty) The commit once described as 'c' (now a merge) │ │ ○ t hello@chriskrycho.com 2024-09-17 19:36:38 1d8c9d26 ┌─┬─┘ (empty) merge s into x ('a' into 'b') │ ○ x hello@chriskrycho.com 2024-09-17 19:36:13 93a82b0e │ │ (empty) b ○ │ s hello@chriskrycho.com 2024-09-17 19:36:08 HEAD@git 30db9a96 ├─┘ (empty) a ○ q hello@chriskrycho.com 2024-09-17 19:35:56 5b8eccb1 │ (empty) base (don't want separate histories in Git) ◆ z root() 00000000 $ jj bookmark create a -r s Created 1 bookmarks pointing to s 30db9a96 a | (empty) a $ jj bookmark create b -r x Created 1 bookmarks pointing to x 93a82b0e b | (empty) b $ jj bookmark create c -r m Created 1 bookmarks pointing to m f96adeaa c | (empty) The commit once described as 'c' (now a merge) $ jj new -m "just for the sake of Git" Working copy now at: mz adbe5ab1 (empty) just for the sake of Git Parent commit : mn f96adeaa c | (empty) The commit once described as 'c' (now a merge) $ jj l @ mz hello@chriskrycho.com 2024-09-17 19:42:01 adbe5ab1 │ (empty) just for the sake of Git ○ mn hello@chriskrycho.com 2024-09-17 19:40:45 c HEAD@git f96adeaa ├─┐ (empty) The commit once described as 'c' (now a merge) │ │ ○ t hello@chriskrycho.com 2024-09-17 19:36:38 1d8c9d26 ┌─┬─┘ (empty) merge s into x ('a' into 'b') │ ○ x hello@chriskrycho.com 2024-09-17 19:36:13 b 93a82b0e │ │ (empty) b ○ │ s hello@chriskrycho.com 2024-09-17 19:36:08 a 30db9a96 ├─┘ (empty) a ○ q hello@chriskrycho.com 2024-09-17 19:35:56 5b8eccb1 │ (empty) base (don't want separate histories in Git) ◆ z root() 00000000 ```

Specifications

yuja commented 3 weeks ago

The order of the rebased commit parents looks correct. Maybe it's a rendering issue of the tooling?

$ jj rebase -r m -d s -d x
Rebased 1 commits onto destination
Working copy now at: m 2e53189b (empty) c
Parent commit      : s 30db9a96 (empty) a
Parent commit      : x 93a82b0e (empty) b

You can use -Tparents.map(|c| c.commit_id()) to print parent commit ids in stored order.

chriskrycho commented 3 weeks ago

@yuja Hmm, maybe. I have seen this cause issues with GitHub as well, but I will try to confirm further. It may be a case of PEBKAC. 🤔