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

cli: deprecate jj checkout and jj merge #2842

Merged
merged 4 commits into from
Feb 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Deprecations

* `jj checkout` and `jj merge` are both deprecated; use `jj new` instead to
replace both of these commands in all instances.

**Rationale**: `jj checkout` and `jj merge` both implement identical
functionality, which is a subset of `jj new`. `checkout` creates a new working
copy commit on top of a single specified revision, i.e. with one parent.
`merge` creates a new working copy commit on top of *at least* two specified
revisions, i.e. with two or more parents.

The only difference between these commands and `jj new`, which *also* creates
a new working copy commit, is that `new` can create a working copy commit on
top of any arbitrary number of revisions, so it can handle both the previous
cases at once. The only actual difference between these three commands is the
command syntax and their name. These names were chosen to be familiar to users
of other version control systems, but we instead encourage all users to adopt
`jj new` instead; it is more general and easier to remember than both of
these.

`jj checkout` and `jj merge` will no longer be shown as part of `jj help`, but
will still function for now, emitting a warning about their deprecation.

**Deadline**: `jj checkout` and `jj merge` will be deleted and are expected
become a **hard error later in 2024**.

### Breaking changes

* (Minor) Diff summaries (e.g. `jj diff -s`) now use `D` for "Deleted" instead
Expand Down
8 changes: 8 additions & 0 deletions cli/src/commands/checkout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ pub(crate) fn cmd_checkout(
command: &CommandHelper,
args: &CheckoutArgs,
) -> Result<(), CommandError> {
writeln!(
ui.warning(),
"warning: `jj checkout` is deprecated; use `jj new` instead, which is equivalent"
)?;
writeln!(
ui.warning(),
"warning: `jj checkout` will be removed in a future version, and this will be a hard error"
)?;
let mut workspace_command = command.workspace_helper(ui)?;
let target = workspace_command.resolve_single_rev(&args.revision, ui)?;
let mut tx = workspace_command.start_transaction();
Expand Down
8 changes: 8 additions & 0 deletions cli/src/commands/merge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ pub(crate) fn cmd_merge(
command: &CommandHelper,
args: &new::NewArgs,
) -> Result<(), CommandError> {
writeln!(
ui.warning(),
"warning: `jj merge` is deprecated; use `jj new` instead, which is equivalent"
)?;
writeln!(
ui.warning(),
"warning: `jj merge` will be removed in a future version, and this will be a hard error"
)?;
if args.revisions.len() < 2 {
return Err(CommandError::CliError(String::from(
"Merge requires at least two revisions",
Expand Down
2 changes: 2 additions & 0 deletions cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ enum Command {
Branch(branch::BranchCommand),
#[command(alias = "print")]
Cat(cat::CatArgs),
#[command(hide = true)]
Checkout(checkout::CheckoutArgs),
Chmod(chmod::ChmodArgs),
Commit(commit::CommitArgs),
Expand Down Expand Up @@ -103,6 +104,7 @@ enum Command {
///
/// This is the same as `jj new`, except that it requires at least two
/// arguments.
#[command(hide = true)]
Merge(new::NewArgs),
Move(r#move::MoveArgs),
New(new::NewArgs),
Expand Down
72 changes: 0 additions & 72 deletions cli/tests/[email protected]
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ This document contains the help content for the `jj` command-line program.
* [`jj branch track`↴](#jj-branch-track)
* [`jj branch untrack`↴](#jj-branch-untrack)
* [`jj cat`↴](#jj-cat)
* [`jj checkout`↴](#jj-checkout)
* [`jj chmod`↴](#jj-chmod)
* [`jj commit`↴](#jj-commit)
* [`jj config`↴](#jj-config)
Expand Down Expand Up @@ -50,7 +49,6 @@ This document contains the help content for the `jj` command-line program.
* [`jj init`↴](#jj-init)
* [`jj interdiff`↴](#jj-interdiff)
* [`jj log`↴](#jj-log)
* [`jj merge`↴](#jj-merge)
* [`jj move`↴](#jj-move)
* [`jj new`↴](#jj-new)
* [`jj next`↴](#jj-next)
Expand Down Expand Up @@ -105,7 +103,6 @@ To get started, see the tutorial at https://github.com/martinvonz/jj/blob/main/d
* `backout` — Apply the reverse of a revision on top of another revision
* `branch` — Manage branches
* `cat` — Print contents of a file in a revision
* `checkout` — Create a new, empty change and edit it in the working copy
* `chmod` — Sets or removes the executable bit for paths in the repo
* `commit` — Update the description and create a new change on top
* `config` — Manage config options
Expand All @@ -119,7 +116,6 @@ To get started, see the tutorial at https://github.com/martinvonz/jj/blob/main/d
* `init` — Create a new repo in the given directory
* `interdiff` — Compare the changes of two commits
* `log` — Show commit history
* `merge` — Merge work from multiple branches
* `move` — Move changes from one revision into another
* `new` — Create a new, empty change and (by default) edit it in the working copy
* `next` — Move the current working copy commit to the next child revision in the
Expand Down Expand Up @@ -387,28 +383,6 @@ Print contents of a file in a revision



## `jj checkout`

Create a new, empty change and edit it in the working copy

For more information, see https://github.com/martinvonz/jj/blob/main/docs/working-copy.md.

**Usage:** `jj checkout [OPTIONS] <REVISION>`

###### **Arguments:**

* `<REVISION>` — The revision to update to

###### **Options:**

* `-r` — Ignored (but lets you pass `-r` for consistency with other commands)

Possible values: `true`, `false`

* `-m`, `--message <MESSAGE>` — The change description to use



## `jj chmod`

Sets or removes the executable bit for paths in the repo
Expand Down Expand Up @@ -1036,52 +1010,6 @@ Show commit history



## `jj merge`

Merge work from multiple branches

Unlike most other VCSs, `jj merge` does not implicitly include the working copy revision's parent as one of the parents of the merge; you need to explicitly list all revisions that should become parents of the merge.

This is the same as `jj new`, except that it requires at least two arguments.

**Usage:** `jj merge [OPTIONS] [REVISIONS]...`

###### **Arguments:**

* `<REVISIONS>` — Parent(s) of the new change

Default value: `@`

###### **Options:**

* `-r` — Ignored (but lets you pass `-r` for consistency with other commands)

Possible values: `true`, `false`

* `-m`, `--message <MESSAGE>` — The change description to use
* `-L`, `--allow-large-revsets` — Deprecated. Please prefix the revset with `all:` instead

Possible values: `true`, `false`

* `--no-edit` — Do not edit the newly created change

Possible values: `true`, `false`

* `--edit` — No-op flag to pair with --no-edit

Possible values: `true`, `false`

* `-A`, `--insert-after` — Insert the new change between the target commit(s) and their children

Possible values: `true`, `false`

* `-B`, `--insert-before` — Insert the new change between the target commit(s) and their parents

Possible values: `true`, `false`




## `jj move`

Move changes from one revision into another
Expand Down
67 changes: 10 additions & 57 deletions cli/tests/test_checkout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ fn test_checkout() {
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["checkout", "@"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @r###"
warning: `jj checkout` is deprecated; use `jj new` instead, which is equivalent
warning: `jj checkout` will be removed in a future version, and this will be a hard error
Working copy now at: zsuskuln 05ce7118 (empty) (no description set)
Parent commit : rlvkpnrz 5c52832c (empty) second
"###);
Expand Down Expand Up @@ -66,6 +68,8 @@ fn test_checkout_not_single_rev() {

let stderr = test_env.jj_cmd_failure(&repo_path, &["checkout", "root()..@"]);
insta::assert_snapshot!(stderr, @r###"
warning: `jj checkout` is deprecated; use `jj new` instead, which is equivalent
warning: `jj checkout` will be removed in a future version, and this will be a hard error
Error: Revset "root()..@" resolved to more than one revision
Hint: The revset "root()..@" resolved to these revisions:
royxmykx 2f859371 (empty) (no description set)
Expand All @@ -78,6 +82,8 @@ fn test_checkout_not_single_rev() {

let stderr = test_env.jj_cmd_failure(&repo_path, &["checkout", "root()..@-"]);
insta::assert_snapshot!(stderr, @r###"
warning: `jj checkout` is deprecated; use `jj new` instead, which is equivalent
warning: `jj checkout` will be removed in a future version, and this will be a hard error
Error: Revset "root()..@-" resolved to more than one revision
Hint: The revset "root()..@-" resolved to these revisions:
mzvwutvl 5c1afd8b (empty) fifth
Expand All @@ -89,6 +95,8 @@ fn test_checkout_not_single_rev() {

let stderr = test_env.jj_cmd_failure(&repo_path, &["checkout", "@-|@--"]);
insta::assert_snapshot!(stderr, @r###"
warning: `jj checkout` is deprecated; use `jj new` instead, which is equivalent
warning: `jj checkout` will be removed in a future version, and this will be a hard error
Error: Revset "@-|@--" resolved to more than one revision
Hint: The revset "@-|@--" resolved to these revisions:
mzvwutvl 5c1afd8b (empty) fifth
Expand All @@ -97,67 +105,12 @@ fn test_checkout_not_single_rev() {

let stderr = test_env.jj_cmd_failure(&repo_path, &["checkout", "none()"]);
insta::assert_snapshot!(stderr, @r###"
warning: `jj checkout` is deprecated; use `jj new` instead, which is equivalent
warning: `jj checkout` will be removed in a future version, and this will be a hard error
Error: Revset "none()" didn't resolve to any revisions
"###);
}

#[test]
fn test_checkout_conflicting_branches() {
let test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
let repo_path = test_env.env_root().join("repo");

test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "one"]);
test_env.jj_cmd_ok(&repo_path, &["new", "-m", "two", "@-"]);
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "foo"]);
test_env.jj_cmd_ok(
&repo_path,
&[
"--at-op=@-",
"branch",
"create",
"foo",
"-r",
r#"description("one")"#,
],
);

// Trigger resolution of concurrent operations
test_env.jj_cmd_ok(&repo_path, &["st"]);

let stderr = test_env.jj_cmd_failure(&repo_path, &["checkout", "foo"]);
insta::assert_snapshot!(stderr, @r###"
Error: Revset "foo" resolved to more than one revision
Hint: Branch foo resolved to multiple revisions because it's conflicted.
It resolved to these revisions:
kkmpptxz 66c6502d foo?? | (empty) two
qpvuntsm a9330854 foo?? | (empty) one
Set which revision the branch points to with `jj branch set foo -r <REVISION>`.
"###);
}

#[test]
fn test_checkout_conflicting_change_ids() {
let test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
let repo_path = test_env.env_root().join("repo");

test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "one"]);
test_env.jj_cmd_ok(&repo_path, &["--at-op=@-", "describe", "-m", "two"]);

// Trigger resolution of concurrent operations
test_env.jj_cmd_ok(&repo_path, &["st"]);

let stderr = test_env.jj_cmd_failure(&repo_path, &["checkout", "qpvuntsm"]);
insta::assert_snapshot!(stderr, @r###"
Error: Revset "qpvuntsm" resolved to more than one revision
Hint: The revset "qpvuntsm" resolved to these revisions:
qpvuntsm?? d2ae6806 (empty) two
qpvuntsm?? a9330854 (empty) one
Some of these commits have the same change id. Abandon one of them with `jj abandon -r <REVISION>`.
"###);
}

fn get_log_output(test_env: &TestEnvironment, cwd: &Path) -> String {
let template = r#"commit_id ++ " " ++ description"#;
test_env.jj_cmd_success(cwd, &["log", "-T", template])
Expand Down
4 changes: 2 additions & 2 deletions cli/tests/test_git_colocated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ fn test_git_colocated_unborn_branch() {

// Stage some change, and check out root. This shouldn't clobber the HEAD.
add_file_to_index("file0", "");
let (stdout, stderr) = test_env.jj_cmd_ok(&workspace_root, &["checkout", "root()"]);
let (stdout, stderr) = test_env.jj_cmd_ok(&workspace_root, &["new", "root()"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @r###"
Working copy now at: kkmpptxz fcdbbd73 (empty) (no description set)
Expand Down Expand Up @@ -188,7 +188,7 @@ fn test_git_colocated_unborn_branch() {
// Stage some change, and check out root again. This should unset the HEAD.
// https://github.com/martinvonz/jj/issues/1495
add_file_to_index("file2", "");
let (stdout, stderr) = test_env.jj_cmd_ok(&workspace_root, &["checkout", "root()"]);
let (stdout, stderr) = test_env.jj_cmd_ok(&workspace_root, &["new", "root()"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @r###"
Working copy now at: znkkpsqq 10dd328b (empty) (no description set)
Expand Down
63 changes: 63 additions & 0 deletions cli/tests/test_new_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,14 @@ fn test_new_merge() {
// `jj merge` with less than two arguments is an error
let stderr = test_env.jj_cmd_cli_error(&repo_path, &["merge"]);
insta::assert_snapshot!(stderr, @r###"
warning: `jj merge` is deprecated; use `jj new` instead, which is equivalent
warning: `jj merge` will be removed in a future version, and this will be a hard error
Error: Merge requires at least two revisions
"###);
let stderr = test_env.jj_cmd_cli_error(&repo_path, &["merge", "main"]);
insta::assert_snapshot!(stderr, @r###"
warning: `jj merge` is deprecated; use `jj new` instead, which is equivalent
warning: `jj merge` will be removed in a future version, and this will be a hard error
Error: Merge requires at least two revisions
"###);

Expand Down Expand Up @@ -464,6 +468,65 @@ fn test_new_insert_before_root() {
"###);
}

#[test]
fn test_new_conflicting_branches() {
let test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
let repo_path = test_env.env_root().join("repo");

test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "one"]);
test_env.jj_cmd_ok(&repo_path, &["new", "-m", "two", "@-"]);
test_env.jj_cmd_ok(&repo_path, &["branch", "create", "foo"]);
test_env.jj_cmd_ok(
&repo_path,
&[
"--at-op=@-",
"branch",
"create",
"foo",
"-r",
r#"description("one")"#,
],
);

// Trigger resolution of concurrent operations
test_env.jj_cmd_ok(&repo_path, &["st"]);

let stderr = test_env.jj_cmd_failure(&repo_path, &["new", "foo"]);
insta::assert_snapshot!(stderr, @r###"
Error: Revset "foo" resolved to more than one revision
Hint: Branch foo resolved to multiple revisions because it's conflicted.
It resolved to these revisions:
kkmpptxz 66c6502d foo?? | (empty) two
qpvuntsm a9330854 foo?? | (empty) one
Set which revision the branch points to with `jj branch set foo -r <REVISION>`.
Prefix the expression with 'all' to allow any number of revisions (i.e. 'all:foo').
"###);
}

#[test]
fn test_new_conflicting_change_ids() {
let test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["init", "repo", "--git"]);
let repo_path = test_env.env_root().join("repo");

test_env.jj_cmd_ok(&repo_path, &["describe", "-m", "one"]);
test_env.jj_cmd_ok(&repo_path, &["--at-op=@-", "describe", "-m", "two"]);

// Trigger resolution of concurrent operations
test_env.jj_cmd_ok(&repo_path, &["st"]);

let stderr = test_env.jj_cmd_failure(&repo_path, &["new", "qpvuntsm"]);
insta::assert_snapshot!(stderr, @r###"
Error: Revset "qpvuntsm" resolved to more than one revision
Hint: The revset "qpvuntsm" resolved to these revisions:
qpvuntsm?? d2ae6806 (empty) two
qpvuntsm?? a9330854 (empty) one
Some of these commits have the same change id. Abandon one of them with `jj abandon -r <REVISION>`.
Prefix the expression with 'all' to allow any number of revisions (i.e. 'all:qpvuntsm').
"###);
}

fn setup_before_insertion(test_env: &TestEnvironment, repo_path: &Path) {
test_env.jj_cmd_ok(repo_path, &["branch", "create", "A"]);
test_env.jj_cmd_ok(repo_path, &["commit", "-m", "A"]);
Expand Down
Loading