Skip to content
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 log -r <change id prefix> can miss some commits in divergent change #2476

Closed
martinvonz opened this issue Oct 31, 2023 · 5 comments · Fixed by #3989
Closed

jj log -r <change id prefix> can miss some commits in divergent change #2476

martinvonz opened this issue Oct 31, 2023 · 5 comments · Fixed by #3989
Labels
🐛bug Something isn't working

Comments

@martinvonz
Copy link
Owner

Description

We currently resolve a change id prefix to the matching commits in revsets.short-prefixes. If there are commits with the given change id both inside and outside the configured revset, then those outside will be missed.

Steps to Reproduce the Problem

$ jj init --git
$ jj describe -m foo
$ jj describe -m bar --at-op=@-
$ jj log
◉  p?? [email protected] 1 minute ago a23dab61
│  (empty) bar
│ @  p?? [email protected] 1 minute ago a9f9bf7e
├─╯  (empty) foo
◉  z root() 00000000
$ jj log --config-toml "revsets.short-prefixes= '@'" -r p
@  p?? [email protected] 1 minute ago a9f9bf7e
│  (empty) foo
~

Expected Behavior

It's probably better to first resolve the change id prefix to a change id within revsets.short-prefixes and then resolve that change id among all visible commits.

Note that we currently depend on change id resolution within revsets.short-prefixes at Google. We don't yet have a solution for resolving a change id to commits. I hope we (Google) can find a solution for that soon, so that fixing this bug doesn't completely break the workflow at Google.

Specifications

  • Platform: All
  • Version: 0.10.0
@PhilipMetzger PhilipMetzger added the 🐛bug Something isn't working label Oct 31, 2023
@ilyagr
Copy link
Collaborator

ilyagr commented Jun 28, 2024

We just saw this bug in the wild: Discord.

There is a workaround: disable the short prefixes feature temporarily. One way to do so is to run commands with --config-toml "revsets.short-prefixes= 'none()'". Then, you resolve the divergence, and after that you can use short prefixes again.

@ilyagr
Copy link
Collaborator

ilyagr commented Jun 28, 2024

I think this could be fixed by adding to the algorithm for looking up change ids: if one change id is found for the prefix in the short prefix set, always try looking for the full change id in the entire repo. I supposed this behavior would have to be disabled at Google, though.

@ilyagr
Copy link
Collaborator

ilyagr commented Jun 28, 2024

I still need to write tests, but let me know if this won't work at Google or is otherwise not a good idea:

diff --git a/lib/src/id_prefix.rs b/lib/src/id_prefix.rs
index f3a47e706d...766cbd502d 100644
--- a/lib/src/id_prefix.rs
+++ b/lib/src/id_prefix.rs
@@ -168,13 +168,16 @@
         prefix: &HexPrefix,
     ) -> PrefixResolution<Vec<CommitId>> {
         if let Some(indexes) = self.disambiguation_indexes(repo) {
-            let resolution = indexes.change_index.resolve_prefix_with(
-                &*indexes.commit_change_ids,
-                prefix,
-                |(commit_id, _)| commit_id.clone(),
-            );
-            if let PrefixResolution::SingleMatch((_, ids)) = resolution {
-                return PrefixResolution::SingleMatch(ids);
+            let resolution: PrefixResolution<(ChangeId, Vec<CommitId>)> = indexes
+                .change_index
+                .resolve_prefix_with(&*indexes.commit_change_ids, prefix, |(commit_id, _)| {
+                    commit_id.clone()
+                });
+            if let PrefixResolution::SingleMatch((change_id, _ids)) = resolution {
+                // There may be more commits with this change id outside the narrower sets.
+                return PrefixResolution::SingleMatch(repo.resolve_change_id(&change_id).expect(
+                    "Change ids present in narrower search set should be present globally.",
+                ));
             }
         }
         repo.resolve_change_id_prefix(prefix)

Aside: This is one example where word-diff shines:

image

Difftastic does an only slightly better job:

image

ilyagr added a commit to ilyagr/jj that referenced this issue Jun 28, 2024
ilyagr added a commit to ilyagr/jj that referenced this issue Jun 28, 2024
@martinvonz
Copy link
Owner Author

I still need to write tests, but let me know if this won't work at Google or is otherwise not a good idea:

The patch looks good to me.

The support for looking up a change id within the full repo at Google that I mentioned at the top is unfortunately still not done :( I don't like the idea of that blocking upstream. We can always patch out this fix at Google until we get proper support for looking up by change id implemented.

Thanks!

@yuja
Copy link
Collaborator

yuja commented Jun 28, 2024

nit: .resolve_prefix_to_key() can be used as we're no longer interested in commit ids.

ilyagr added a commit to ilyagr/jj that referenced this issue Jun 29, 2024
ilyagr added a commit to ilyagr/jj that referenced this issue Jun 29, 2024
ilyagr added a commit to ilyagr/jj that referenced this issue Jun 29, 2024
…tside short prefix set

Previously, if there was a change id match within the short prefix
lookup set, `jj` would not look for commits with that same change id
outside the short prefix set. So, it wouldn't find the conflicted
commits for a commit with a divergent (AKA conflicted) change id.
ilyagr added a commit to ilyagr/jj that referenced this issue Jun 29, 2024
Fixes martinvonz#2476.

Previously, if there was a change id match within the short prefix
lookup set, `jj` would not look for commits with that same change id
outside the short prefix set. So, it wouldn't find the conflicted
commits for a commit with a divergent (AKA conflicted) change id.
ilyagr added a commit to ilyagr/jj that referenced this issue Jun 29, 2024
ilyagr added a commit to ilyagr/jj that referenced this issue Jun 29, 2024
Fixes martinvonz#2476.

Previously, if there was a change id match within the short prefix
lookup set, `jj` would not look for commits with that same change id
outside the short prefix set. So, it wouldn't find the conflicted
commits for a commit with a divergent (AKA conflicted) change id.
ilyagr added a commit to ilyagr/jj that referenced this issue Jun 29, 2024
Fixes martinvonz#2476.

Previously, if there was a change id match within the short prefix
lookup set, `jj` would not look for commits with that same change id
outside the short prefix set. So, it wouldn't find the conflicted
commits for a commit with a divergent (AKA conflicted) change id.
ilyagr added a commit to ilyagr/jj that referenced this issue Jun 29, 2024
Fixes martinvonz#2476.

Previously, if there was a change id match within the short prefix
lookup set, `jj` would not look for commits with that same change id
outside the short prefix set. So, it wouldn't find the conflicted
commits for a commit with a divergent (AKA conflicted) change id.
ilyagr added a commit to ilyagr/jj that referenced this issue Jun 29, 2024
Fixes martinvonz#2476.

Previously, if there was a change id match within the short prefix
lookup set, `jj` would not look for commits with that same change id
outside the short prefix set. So, it wouldn't find the conflicted
commits for a commit with a divergent (AKA conflicted) change id.
ilyagr added a commit to ilyagr/jj that referenced this issue Jun 29, 2024
ilyagr added a commit to ilyagr/jj that referenced this issue Jun 29, 2024
Fixes martinvonz#2476.

Previously, if there was a change id match within the short prefix
lookup set, `jj` would not look for commits with that same change id
outside the short prefix set. So, it wouldn't find the conflicted
commits for a commit with a divergent (AKA conflicted) change id.
ilyagr added a commit that referenced this issue Jun 29, 2024
ilyagr added a commit that referenced this issue Jun 29, 2024
Fixes #2476.

Previously, if there was a change id match within the short prefix
lookup set, `jj` would not look for commits with that same change id
outside the short prefix set. So, it wouldn't find the conflicted
commits for a commit with a divergent (AKA conflicted) change id.
netbsd-srcmastr pushed a commit to NetBSD/pkgsrc that referenced this issue Jul 7, 2024
## [0.19.0] - 2024-07-03

### Breaking changes

* In revset aliases, top-level `kind:pattern` expression is now parsed as
  modifier. Surround with parentheses if it should be parsed as string/file
  pattern.

* Dropped support for automatic upgrade of repo formats used by versions before
  0.12.0.

* `jj fix` now defaults to the broader revset `-s reachable(@, mutable())`
  instead of `-s @`.

* Dropped support for deprecated `jj branch delete`/`forget` `--glob` option.

* `jj branch set` now creates new branch if it doesn't exist. Use `jj branch
  move` to ensure that the target branch already exists.
  [#3584](martinvonz/jj#3584)

### Deprecations

* Replacing `-l` shorthand for `--limit` with `-n` in `jj log`, `jj op log`
  and `jj obslog`.

* `jj split --siblings` is deprecated in favor of `jj split --parallel` (to
  match `jj parallelize`).

* A new `jj file` subcommand now replaces several existing uncategorized
  commands, which are deprecated.
  - `jj file show` replaces `jj cat`.
  - `jj file chmod` replaces `jj chmod`.
  - `jj file list` replaces `jj files`.

### New features

* Support background filesystem monitoring via watchman triggers enabled with
  the `core.watchman.register_snapshot_trigger = true` config.

* Show paths to config files when configuration errors occur.

* `jj fix` now supports configuring the default revset for `-s` using the
  `revsets.fix` config.

* The `descendants()` revset function now accepts an optional `depth` argument;
  like the `ancestors()` depth argument, it limits the depth of the set.

* Revset/template aliases now support function overloading.
  [#2966](martinvonz/jj#2966)

* Conflicted files are individually simplified before being materialized.

* The `jj file` subcommand now contains several existing file utilities.
  - `jj file show`, replacing `jj cat`.
  - `jj file chmod` replacing `jj chmod`.
  - `jj file list` replacing `jj files`.

* New command `jj branch move` let you update branches by name pattern or source
  revision.

* New diff option `jj diff --name-only` allows for easier shell scripting.

* In color-words diffs, hunks are now highlighted with underline. See [diff
  colors and styles](docs/config.md#diff-colors-and-styles) for customization.

* `jj git push -c <arg>` can now accept revsets that resolve to multiple
  revisions. This means that `jj git push -c xyz -c abc` is now equivalent to
  `jj git push -c 'all:(xyz | abc)'`.

* `jj prev` and `jj next` have gained a `--conflict` flag which moves you
  to the next conflict in a child commit.

* New command `jj git remote set-url` that sets the url of a git remote.

* Author timestamp is now reset when rewriting discardable commits (empty
  commits with no description) if authored by the current user.
  [#2000](martinvonz/jj#2000)

* `jj commit` now accepts `--reset-author` option to match `jj describe`.

* `jj squash` now accepts a `--keep-emptied` option to keep the source commit.

### Fixed bugs

* `jj git push` now ignores immutable commits when checking whether a
  to-be-pushed commit has conflicts, or has no description / committer / author
  set. [#3029](martinvonz/jj#3029)

* `jj` will look for divergent changes outside the short prefix set even if it
  finds the change id inside the short prefix set.
  [#2476](martinvonz/jj#2476)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐛bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants