diff --git a/cli/src/commands/branch.rs b/cli/src/commands/branch.rs index 11a05c6b978..bcef65f29f7 100644 --- a/cli/src/commands/branch.rs +++ b/cli/src/commands/branch.rs @@ -60,10 +60,10 @@ pub struct BranchDeleteArgs { /// List branches and their targets /// -/// A remote branch will be included only if its target is different from -/// the local target. For a conflicted branch (both local and remote), old -/// target revisions are preceded by a "-" and new target revisions are -/// preceded by a "+". For information about branches, see +/// A tracking remote branch will be included only if its target is different +/// from the local target. For a conflicted branch (both local and remote), old +/// target revisions are preceded by a "-" and new target revisions are preceded +/// by a "+". For information about branches, see /// https://github.com/martinvonz/jj/blob/main/docs/branches.md. #[derive(clap::Args, Clone, Debug)] pub struct BranchListArgs { @@ -389,14 +389,22 @@ fn cmd_branch_list( .map_or(true, |branch_names| branch_names.contains(name)) }); for (name, branch_target) in branches_to_list { - write!(formatter.labeled("branch"), "{name}")?; - if branch_target.local_target.is_present() { - print_branch_target(formatter, branch_target.local_target)?; - } else { - writeln!(formatter, " (deleted)")?; + let (tracking_remote_refs, untracked_remote_refs) = + branch_target + .remote_refs + .into_iter() + .partition::, _>(|&(_, remote_ref)| remote_ref.is_tracking()); + + if branch_target.local_target.is_present() || !tracking_remote_refs.is_empty() { + write!(formatter.labeled("branch"), "{name}")?; + if branch_target.local_target.is_present() { + print_branch_target(formatter, branch_target.local_target)?; + } else { + writeln!(formatter, " (deleted)")?; + } } - for &(remote, remote_ref) in &branch_target.remote_refs { + for &(remote, remote_ref) in &tracking_remote_refs { if remote_ref.target == *branch_target.local_target { continue; } @@ -425,9 +433,8 @@ fn cmd_branch_list( print_branch_target(formatter, &remote_ref.target)?; } - if branch_target.local_target.is_absent() { - let found_non_git_remote = branch_target - .remote_refs + if branch_target.local_target.is_absent() && !tracking_remote_refs.is_empty() { + let found_non_git_remote = tracking_remote_refs .iter() .any(|&(remote, _)| remote != git::REMOTE_NAME_FOR_LOCAL_GIT_REPO); if found_non_git_remote { @@ -444,6 +451,12 @@ fn cmd_branch_list( )?; } } + + // TODO: hide non-tracking remotes by default? + for &(remote, remote_ref) in &untracked_remote_refs { + write!(formatter.labeled("branch"), "{name}@{remote}")?; + print_branch_target(formatter, &remote_ref.target)?; + } } Ok(()) diff --git a/cli/tests/test_git_fetch.rs b/cli/tests/test_git_fetch.rs index c37933b5285..e3806122db4 100644 --- a/cli/tests/test_git_fetch.rs +++ b/cli/tests/test_git_fetch.rs @@ -1159,11 +1159,14 @@ fn test_git_fetch_remote_only_branch() { // Fetch using git.auto_local_branch = false test_env.add_config("git.auto-local-branch = false"); test_env.jj_cmd_ok(&repo_path, &["git", "fetch", "--remote=origin"]); + insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r###" + ◉ 9f01a0e04879 message feature1 feature2@origin + │ @ 230dd059e1b0 + ├─╯ + ◉ 000000000000 + "###); insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###" feature1: mzyxwzks 9f01a0e0 message - feature2 (deleted) - @origin: mzyxwzks 9f01a0e0 message - (this branch will be *deleted permanently* on the remote on the - next `jj git push`. Use `jj branch forget` to prevent this) + feature2@origin: mzyxwzks 9f01a0e0 message "###); }