diff --git a/CHANGELOG.md b/CHANGELOG.md index e0173bdad2..03aa854f47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * `jj git fetch`: when re-adding a remote repository that had been previously removed, in some situations the remote branches were not recreated. +* `jj git remote rename`: the git remote references were not rewritten with + the new name. If a new remote with the old name and containing the same + branches was added, the remote branches may not be recreated in some cases. + ## [0.7.0] - 2023-02-16 ### Breaking changes diff --git a/src/commands/git.rs b/src/commands/git.rs index c906d38514..b46d8f7566 100644 --- a/src/commands/git.rs +++ b/src/commands/git.rs @@ -230,6 +230,28 @@ fn cmd_git_remote_rename( let mut tx = workspace_command .start_transaction(&format!("rename git remote {} to {}", &args.old, &args.new)); tx.mut_repo().rename_remote(&args.old, &args.new); + + let prefix = format!("refs/remotes/{}/", args.old); + let git_refs = tx + .mut_repo() + .view() + .git_refs() + .iter() + .filter_map(|(r, target)| { + r.strip_prefix(&prefix).map(|p| { + ( + r.clone(), + format!("refs/remotes/{}/{p}", args.new), + target.clone(), + ) + }) + }) + .collect_vec(); + for (old, new, target) in git_refs { + tx.mut_repo().remove_git_ref(&old); + tx.mut_repo().set_git_ref(new, target); + } + if tx.mut_repo().has_changes() { tx.finish(ui)?; } diff --git a/tests/test_git_fetch.rs b/tests/test_git_fetch.rs index cb4e8da579..9b4f45f849 100644 --- a/tests/test_git_fetch.rs +++ b/tests/test_git_fetch.rs @@ -705,3 +705,41 @@ fn test_git_fetch_remove_fetch() { @origin (behind by 1 commits): ffecd2d67827 message "###); } + +#[test] +fn test_git_fetch_rename_fetch() { + let test_env = TestEnvironment::default(); + test_env.jj_cmd_success(test_env.env_root(), &["init", "repo", "--git"]); + let repo_path = test_env.env_root().join("repo"); + add_git_remote(&test_env, &repo_path, "origin"); + + test_env.jj_cmd_success(&repo_path, &["branch", "set", "origin"]); + insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###" + origin: 230dd059e1b0 (no description set) + "###); + + test_env.jj_cmd_success(&repo_path, &["git", "fetch"]); + insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###" + origin (conflicted): + + 230dd059e1b0 (no description set) + + ffecd2d67827 message + @origin (behind by 1 commits): ffecd2d67827 message + "###); + + test_env.jj_cmd_success( + &repo_path, + &["git", "remote", "rename", "origin", "upstream"], + ); + insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###" + origin (conflicted): + + 230dd059e1b0 (no description set) + + ffecd2d67827 message + @upstream (behind by 1 commits): ffecd2d67827 message + "###); + + // Check that jj indicates that nothing has changed + let stdout = test_env.jj_cmd_success(&repo_path, &["git", "fetch", "--remote", "upstream"]); + insta::assert_snapshot!(stdout, @r###" + Nothing changed. + "###); +}