Skip to content

Commit

Permalink
cli split: Add a config option controlling how bookmarks move during …
Browse files Browse the repository at this point in the history
…splits

Currently, `jj split` moves bookmarks from the target revision to the second
revision created by the split. Since the first revision inherits the change id
of the target revision, moving the bookmarks to the first revision is less
surprising (i.e. the bookmarks stay with the change id). This no-implicit-move
behavior also aligns with how `jj abandon` drops bookmarks instead of moving
them to the parent revision.

Two releases from now, `jj split` will no longer move bookmarks to the second
revision created by the split. Instead, local bookmarks associated with the
target revision will move to the first revision created by the split (which
inherits the target revision's change id). You can opt out of this change by
setting `split.legacy-bookmark-behavior = true`, but this will likely be
removed in a future release. You can also try the new behavior now by setting
`split.legacy-bookmark-behavior = false`.

Users who have not opted into the new behavior via the config setting will see
a warning when they run `jj split` informing them about the change. The default
behavior be changed in the future.

The `jj split` tests for bookmarks are updated to run in all three configurations:

- Config setting enabled
- Config setting disabled
- Config setting unset


#3419
  • Loading branch information
emesterhazy committed Feb 13, 2025
1 parent ae59bd8 commit d5d2164
Show file tree
Hide file tree
Showing 4 changed files with 202 additions and 32 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
a warning if the user does not specify target revision explicitly. In the near
future those commands will fail if target revision is not specified.

* In the next release, `jj split` will no longer move bookmarks to the second
revision created by the split. Instead, local bookmarks associated with the
target revision will move to the first revision created by the split (which
inherits the target revision's change id). You can opt out of this change by
setting `split.legacy-bookmark-behavior = true`, but this will likely be
removed in a future release. You can also try the new behavior now by setting
`split.legacy-bookmark-behavior = false`.
[#3419](https://github.com/jj-vcs/jj/issues/3419)


### New features

* `jj undo` now shows a hint when undoing an undo operation that the user may
Expand Down
65 changes: 55 additions & 10 deletions cli/src/commands/split.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use std::io::Write;

use clap_complete::ArgValueCandidates;
use clap_complete::ArgValueCompleter;
use jj_lib::config::ConfigGetResultExt;
use jj_lib::object_id::ObjectId;
use jj_lib::repo::Repo;
use tracing::instrument;
Expand Down Expand Up @@ -196,26 +197,37 @@ The remainder will be in the second commit.
commit_builder.write(tx.repo_mut())?
};

// Mark the commit being split as rewritten to the second commit. As a
// result, if @ points to the commit being split, it will point to the
// second commit after the command finishes. This also means that any
// bookmarks pointing to the commit being split are moved to the second
// commit.
tx.repo_mut()
.set_rewritten_commit(commit.id().clone(), second_commit.id().clone());
let legacy_bookmark_behavior = read_legacy_bookmark_behavior_setting(tx.settings(), ui)?;
if legacy_bookmark_behavior {
// Mark the commit being split as rewritten to the second commit. This
// moves any bookmarks pointing to the target commit to the second
// commit.
tx.repo_mut()
.set_rewritten_commit(commit.id().clone(), second_commit.id().clone());
}
let mut num_rebased = 0;
tx.repo_mut()
.transform_descendants(vec![commit.id().clone()], |mut rewriter| {
num_rebased += 1;
if args.parallel {
if args.parallel && legacy_bookmark_behavior {
// The old_parent is the second commit due to the rewrite above.
rewriter
.replace_parent(second_commit.id(), [first_commit.id(), second_commit.id()]);
} else if args.parallel {
rewriter.replace_parent(first_commit.id(), [first_commit.id(), second_commit.id()]);
} else {
rewriter.replace_parent(first_commit.id(), [second_commit.id()]);
}
// We don't need to do anything special for the non-parallel case
// since we already marked the original commit as rewritten.
rewriter.rebase()?.write()?;
Ok(())
})?;
// Move the working copy commit (@) to the second commit for any workspaces
// where the target commit is the working copy commit.
for (workspace_id, working_copy_commit) in tx.base_repo().clone().view().wc_commit_ids() {
if working_copy_commit == commit.id() {
tx.repo_mut().edit(workspace_id.clone(), &second_commit)?;
}
}

if let Some(mut formatter) = ui.status_formatter() {
if num_rebased > 0 {
Expand All @@ -230,3 +242,36 @@ The remainder will be in the second commit.
tx.finish(ui, format!("split commit {}", commit.id().hex()))?;
Ok(())
}

/// Reads 'split.legacy-bookmark-behavior' from settings and prints a warning if
/// the value is unset to alert the user to the behavior change.
fn read_legacy_bookmark_behavior_setting(
settings: &jj_lib::settings::UserSettings,
ui: &Ui,
) -> Result<bool, CommandError> {
match settings
.get_bool("split.legacy-bookmark-behavior")
.optional()?
{
// Use the new behavior.
Some(false) => Ok(false),
// Use the legacy behavior.
Some(true) | None => {
writeln!(
ui.warning_default(),
"`jj split` will leave bookmarks on the first commit in the next release."
)?;
writeln!(
ui.warning_default(),
"Run `jj config set --repo split.legacy-bookmark-behavior false` to silence this \
message and use the new behavior."
)?;
writeln!(
ui.warning_default(),
"See https://github.com/jj-vcs/jj/issues/3419"
)?;
// TODO: https://github.com/jj-vcs/jj/issues/3419 - Return false by default in v0.28.
Ok(true)
}
}
}
11 changes: 11 additions & 0 deletions cli/src/config-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,17 @@
"description": "Settings for tools run by jj fix"
}
}
},
"split": {
"type": "object",
"description": "Settings for jj split",
"properties": {
"legacy-bookmark-behavior": {
"type": "boolean",
"description": "If true, bookmarks will move to the second commit instead of the first.",
"default": false
}
}
}
}
}
Loading

0 comments on commit d5d2164

Please sign in to comment.