diff --git a/docs/config.md b/docs/config.md index bab3d8f1fba..229675fbe92 100644 --- a/docs/config.md +++ b/docs/config.md @@ -188,8 +188,28 @@ partially resolved and parses the conflict markers to get the new state of the conflict. The conflict is considered fully resolved when there are no conflict markers left. +## Git settings +### Automatic local branch creation +By default, when `jj` imports a remote-tracking branch from Git, it also +creates a local branch with the same name. In some repositories, this +may be undesirable, e.g.: + +- There is a remote with a lot of historical branches that you don't + want to be exported to the co-located Git repo. +- There are multiple remotes with conflicting views of that branch, + resulting in an unhelpful conflicted state. + +You can disable this behavior by setting `git.auto-local-branch` like +so, + + git.auto-local-branch = false + +Note that this setting may make it easier to accidentally delete remote +branches. Since the local branch isn't created, the remote branch will be +deleted if you push the branch with `jj git push --branch` or `jj git push +--all`. # Alternative ways to specify configuration settings diff --git a/lib/src/git.rs b/lib/src/git.rs index 184c003c088..22c2ad99a3f 100644 --- a/lib/src/git.rs +++ b/lib/src/git.rs @@ -25,6 +25,7 @@ use crate::commit::Commit; use crate::git_backend::NO_GC_REF_NAMESPACE; use crate::op_store::RefTarget; use crate::repo::MutableRepo; +use crate::settings::GitSettings; use crate::view::RefName; #[derive(Error, Debug, PartialEq)] @@ -65,6 +66,7 @@ fn prevent_gc(git_repo: &git2::Repository, id: &CommitId) { pub fn import_refs( mut_repo: &mut MutableRepo, git_repo: &git2::Repository, + git_settings: &GitSettings, ) -> Result<(), GitImportError> { let store = mut_repo.store().clone(); let mut existing_git_refs = mut_repo.view().git_refs().clone(); @@ -141,6 +143,9 @@ pub fn import_refs( mut_repo.merge_single_ref(&ref_name, old_git_target.as_ref(), new_git_target.as_ref()); // If a git remote-tracking branch changed, apply the change to the local branch // as well + if !git_settings.auto_local_branch { + continue; + } if let RefName::RemoteBranch { branch, remote: _ } = ref_name { mut_repo.merge_single_ref( &RefName::LocalBranch(branch), @@ -336,6 +341,7 @@ pub fn fetch( git_repo: &git2::Repository, remote_name: &str, callbacks: RemoteCallbacks<'_>, + git_settings: &GitSettings, ) -> Result, GitFetchError> { let mut remote = git_repo @@ -378,7 +384,7 @@ pub fn fetch( tracing::debug!("remote.disconnect"); remote.disconnect()?; tracing::debug!("import_refs"); - import_refs(mut_repo, git_repo).map_err(|err| match err { + import_refs(mut_repo, git_repo, git_settings).map_err(|err| match err { GitImportError::InternalGitError(source) => GitFetchError::InternalGitError(source), })?; Ok(default_branch) diff --git a/lib/src/settings.rs b/lib/src/settings.rs index 348f2f293af..2a0ed1e9384 100644 --- a/lib/src/settings.rs +++ b/lib/src/settings.rs @@ -33,6 +33,28 @@ pub struct RepoSettings { _config: config::Config, } +#[derive(Debug, Clone)] +pub struct GitSettings { + pub auto_local_branch: bool, +} + +impl GitSettings { + pub fn from_config(config: &config::Config) -> Self { + let mut settings = GitSettings::default(); + + settings.auto_local_branch = config.get_bool("git.auto-local-branch").unwrap_or(true); + settings + } +} + +impl Default for GitSettings { + fn default() -> Self { + GitSettings { + auto_local_branch: true, + } + } +} + fn get_timestamp_config(config: &config::Config, key: &str) -> Option { match config.get_string(key) { Ok(timestamp_str) => match DateTime::parse_from_rfc3339(×tamp_str) { @@ -153,6 +175,10 @@ impl UserSettings { &self.config } + pub fn git_settings(&self) -> GitSettings { + GitSettings::from_config(&self.config) + } + pub fn graph_format(&self) -> String { self.config .get_string("ui.graph.format") diff --git a/lib/tests/test_git.rs b/lib/tests/test_git.rs index dda2228ed03..9189dacdcdf 100644 --- a/lib/tests/test_git.rs +++ b/lib/tests/test_git.rs @@ -24,7 +24,7 @@ use jujutsu_lib::git::{GitFetchError, GitPushError, GitRefUpdate}; use jujutsu_lib::git_backend::GitBackend; use jujutsu_lib::op_store::{BranchTarget, RefTarget}; use jujutsu_lib::repo::ReadonlyRepo; -use jujutsu_lib::settings::UserSettings; +use jujutsu_lib::settings::{GitSettings, UserSettings}; use maplit::{btreemap, hashset}; use tempfile::TempDir; use testutils::{create_random_commit, write_random_commit, TestRepo}; @@ -61,6 +61,7 @@ fn git_id(commit: &Commit) -> Oid { #[test] fn test_import_refs() { let settings = testutils::user_settings(); + let git_settings = GitSettings::default(); let test_repo = TestRepo::init(true); let repo = &test_repo.repo; let git_repo = repo.store().git_repo().unwrap(); @@ -80,7 +81,7 @@ fn test_import_refs() { let git_repo = repo.store().git_repo().unwrap(); let mut tx = repo.start_transaction(&settings, "test"); - git::import_refs(tx.mut_repo(), &git_repo).unwrap(); + git::import_refs(tx.mut_repo(), &git_repo, &git_settings).unwrap(); tx.mut_repo().rebase_descendants(&settings).unwrap(); let repo = tx.commit(); let view = repo.view(); @@ -166,6 +167,7 @@ fn test_import_refs() { #[test] fn test_import_refs_reimport() { let settings = testutils::user_settings(); + let git_settings = GitSettings::default(); let test_workspace = TestRepo::init(true); let repo = &test_workspace.repo; let git_repo = repo.store().git_repo().unwrap(); @@ -181,7 +183,7 @@ fn test_import_refs_reimport() { .unwrap(); let mut tx = repo.start_transaction(&settings, "test"); - git::import_refs(tx.mut_repo(), &git_repo).unwrap(); + git::import_refs(tx.mut_repo(), &git_repo, &git_settings).unwrap(); tx.mut_repo().rebase_descendants(&settings).unwrap(); let repo = tx.commit(); @@ -203,7 +205,7 @@ fn test_import_refs_reimport() { let repo = tx.commit(); let mut tx = repo.start_transaction(&settings, "test"); - git::import_refs(tx.mut_repo(), &git_repo).unwrap(); + git::import_refs(tx.mut_repo(), &git_repo, &git_settings).unwrap(); tx.mut_repo().rebase_descendants(&settings).unwrap(); let repo = tx.commit(); @@ -261,13 +263,14 @@ fn test_import_refs_reimport() { fn test_import_refs_reimport_head_removed() { // Test that re-importing refs doesn't cause a deleted head to come back let settings = testutils::user_settings(); + let git_settings = GitSettings::default(); let test_repo = TestRepo::init(true); let repo = &test_repo.repo; let git_repo = repo.store().git_repo().unwrap(); let commit = empty_git_commit(&git_repo, "refs/heads/main", &[]); let mut tx = repo.start_transaction(&settings, "test"); - git::import_refs(tx.mut_repo(), &git_repo).unwrap(); + git::import_refs(tx.mut_repo(), &git_repo, &git_settings).unwrap(); tx.mut_repo().rebase_descendants(&settings).unwrap(); let commit_id = jj_id(&commit); // Test the setup @@ -275,7 +278,7 @@ fn test_import_refs_reimport_head_removed() { // Remove the head and re-import tx.mut_repo().remove_head(&commit_id); - git::import_refs(tx.mut_repo(), &git_repo).unwrap(); + git::import_refs(tx.mut_repo(), &git_repo, &git_settings).unwrap(); tx.mut_repo().rebase_descendants(&settings).unwrap(); assert!(!tx.mut_repo().view().heads().contains(&commit_id)); } @@ -285,6 +288,7 @@ fn test_import_refs_reimport_git_head_counts() { // Test that if a branch is removed but the Git HEAD points to the commit (or a // descendant of it), we still keep it alive. let settings = testutils::user_settings(); + let git_settings = GitSettings::default(); let test_repo = TestRepo::init(true); let repo = &test_repo.repo; let git_repo = repo.store().git_repo().unwrap(); @@ -293,7 +297,7 @@ fn test_import_refs_reimport_git_head_counts() { git_repo.set_head_detached(commit.id()).unwrap(); let mut tx = repo.start_transaction(&settings, "test"); - git::import_refs(tx.mut_repo(), &git_repo).unwrap(); + git::import_refs(tx.mut_repo(), &git_repo, &git_settings).unwrap(); tx.mut_repo().rebase_descendants(&settings).unwrap(); // Delete the branch and re-import. The commit should still be there since HEAD @@ -303,7 +307,7 @@ fn test_import_refs_reimport_git_head_counts() { .unwrap() .delete() .unwrap(); - git::import_refs(tx.mut_repo(), &git_repo).unwrap(); + git::import_refs(tx.mut_repo(), &git_repo, &git_settings).unwrap(); tx.mut_repo().rebase_descendants(&settings).unwrap(); assert!(tx.mut_repo().view().heads().contains(&jj_id(&commit))); } @@ -313,13 +317,14 @@ fn test_import_refs_reimport_all_from_root_removed() { // Test that if a chain of commits all the way from the root gets unreferenced, // we abandon the whole stack, but not including the root commit. let settings = testutils::user_settings(); + let git_settings = GitSettings::default(); let test_repo = TestRepo::init(true); let repo = &test_repo.repo; let git_repo = repo.store().git_repo().unwrap(); let commit = empty_git_commit(&git_repo, "refs/heads/main", &[]); let mut tx = repo.start_transaction(&settings, "test"); - git::import_refs(tx.mut_repo(), &git_repo).unwrap(); + git::import_refs(tx.mut_repo(), &git_repo, &git_settings).unwrap(); tx.mut_repo().rebase_descendants(&settings).unwrap(); // Test the setup assert!(tx.mut_repo().view().heads().contains(&jj_id(&commit))); @@ -330,7 +335,7 @@ fn test_import_refs_reimport_all_from_root_removed() { .unwrap() .delete() .unwrap(); - git::import_refs(tx.mut_repo(), &git_repo).unwrap(); + git::import_refs(tx.mut_repo(), &git_repo, &git_settings).unwrap(); tx.mut_repo().rebase_descendants(&settings).unwrap(); assert!(!tx.mut_repo().view().heads().contains(&jj_id(&commit))); } @@ -383,11 +388,12 @@ impl GitRepoData { #[test] fn test_import_refs_empty_git_repo() { let test_data = GitRepoData::create(); + let git_settings = GitSettings::default(); let heads_before = test_data.repo.view().heads().clone(); let mut tx = test_data .repo .start_transaction(&test_data.settings, "test"); - git::import_refs(tx.mut_repo(), &test_data.git_repo).unwrap(); + git::import_refs(tx.mut_repo(), &test_data.git_repo, &git_settings).unwrap(); tx.mut_repo() .rebase_descendants(&test_data.settings) .unwrap(); @@ -402,6 +408,7 @@ fn test_import_refs_empty_git_repo() { #[test] fn test_import_refs_detached_head() { let test_data = GitRepoData::create(); + let git_settings = GitSettings::default(); let commit1 = empty_git_commit(&test_data.git_repo, "refs/heads/main", &[]); // Delete the reference. Check that the detached HEAD commit still gets added to // the set of heads @@ -416,7 +423,7 @@ fn test_import_refs_detached_head() { let mut tx = test_data .repo .start_transaction(&test_data.settings, "test"); - git::import_refs(tx.mut_repo(), &test_data.git_repo).unwrap(); + git::import_refs(tx.mut_repo(), &test_data.git_repo, &git_settings).unwrap(); tx.mut_repo() .rebase_descendants(&test_data.settings) .unwrap(); @@ -433,6 +440,7 @@ fn test_export_refs_no_detach() { // When exporting the branch that's current checked out, don't detach HEAD if // the target already matches let test_data = GitRepoData::create(); + let git_settings = GitSettings::default(); let git_repo = test_data.git_repo; let commit1 = empty_git_commit(&git_repo, "refs/heads/main", &[]); git_repo.set_head("refs/heads/main").unwrap(); @@ -440,7 +448,7 @@ fn test_export_refs_no_detach() { .repo .start_transaction(&test_data.settings, "test"); let mut_repo = tx.mut_repo(); - git::import_refs(mut_repo, &git_repo).unwrap(); + git::import_refs(mut_repo, &git_repo, &git_settings).unwrap(); mut_repo.rebase_descendants(&test_data.settings).unwrap(); // Do an initial export to make sure `main` is considered @@ -460,6 +468,7 @@ fn test_export_refs_no_detach() { fn test_export_refs_branch_changed() { // We can export a change to a branch let test_data = GitRepoData::create(); + let git_settings = GitSettings::default(); let git_repo = test_data.git_repo; let commit = empty_git_commit(&git_repo, "refs/heads/main", &[]); git_repo @@ -471,7 +480,7 @@ fn test_export_refs_branch_changed() { .repo .start_transaction(&test_data.settings, "test"); let mut_repo = tx.mut_repo(); - git::import_refs(mut_repo, &git_repo).unwrap(); + git::import_refs(mut_repo, &git_repo, &git_settings).unwrap(); mut_repo.rebase_descendants(&test_data.settings).unwrap(); assert_eq!(git::export_refs(mut_repo, &git_repo), Ok(vec![])); @@ -505,6 +514,7 @@ fn test_export_refs_branch_changed() { fn test_export_refs_current_branch_changed() { // If we update a branch that is checked out in the git repo, HEAD gets detached let test_data = GitRepoData::create(); + let git_settings = GitSettings::default(); let git_repo = test_data.git_repo; let commit1 = empty_git_commit(&git_repo, "refs/heads/main", &[]); git_repo.set_head("refs/heads/main").unwrap(); @@ -512,7 +522,7 @@ fn test_export_refs_current_branch_changed() { .repo .start_transaction(&test_data.settings, "test"); let mut_repo = tx.mut_repo(); - git::import_refs(mut_repo, &git_repo).unwrap(); + git::import_refs(mut_repo, &git_repo, &git_settings).unwrap(); mut_repo.rebase_descendants(&test_data.settings).unwrap(); assert_eq!(git::export_refs(mut_repo, &git_repo), Ok(vec![])); @@ -545,13 +555,14 @@ fn test_export_refs_current_branch_changed() { fn test_export_refs_unborn_git_branch() { // Can export to an empty Git repo (we can handle Git's "unborn branch" state) let test_data = GitRepoData::create(); + let git_settings = GitSettings::default(); let git_repo = test_data.git_repo; git_repo.set_head("refs/heads/main").unwrap(); let mut tx = test_data .repo .start_transaction(&test_data.settings, "test"); let mut_repo = tx.mut_repo(); - git::import_refs(mut_repo, &git_repo).unwrap(); + git::import_refs(mut_repo, &git_repo, &git_settings).unwrap(); mut_repo.rebase_descendants(&test_data.settings).unwrap(); assert_eq!(git::export_refs(mut_repo, &git_repo), Ok(vec![])); @@ -586,6 +597,7 @@ fn test_export_import_sequence() { // modify it in git to point to C, then import it again. There should be no // conflict. let test_data = GitRepoData::create(); + let git_settings = GitSettings::default(); let git_repo = test_data.git_repo; let mut tx = test_data .repo @@ -599,7 +611,7 @@ fn test_export_import_sequence() { git_repo .reference("refs/heads/main", git_id(&commit_a), true, "test") .unwrap(); - git::import_refs(mut_repo, &git_repo).unwrap(); + git::import_refs(mut_repo, &git_repo, &git_settings).unwrap(); assert_eq!( mut_repo.get_git_ref("refs/heads/main"), Some(RefTarget::Normal(commit_a.id().clone())) @@ -621,7 +633,7 @@ fn test_export_import_sequence() { .unwrap(); // Import from git - git::import_refs(mut_repo, &git_repo).unwrap(); + git::import_refs(mut_repo, &git_repo, &git_settings).unwrap(); assert_eq!( mut_repo.get_git_ref("refs/heads/main"), Some(RefTarget::Normal(commit_c.id().clone())) @@ -632,6 +644,44 @@ fn test_export_import_sequence() { ); } +#[test] +fn test_import_export_no_auto_local_branch() { + // Import a remote tracking branch and export it. We should not create a git + // branch. + let test_data = GitRepoData::create(); + let git_settings = GitSettings { + auto_local_branch: false, + }; + let git_repo = test_data.git_repo; + let git_commit = empty_git_commit(&git_repo, "refs/remotes/origin/main", &[]); + + let mut tx = test_data + .repo + .start_transaction(&test_data.settings, "test"); + let mut_repo = tx.mut_repo(); + + git::import_refs(mut_repo, &git_repo, &git_settings).unwrap(); + + let expected_branch = BranchTarget { + local_target: None, + remote_targets: btreemap! { + "origin".to_string() => RefTarget::Normal(jj_id(&git_commit)) + }, + }; + assert_eq!( + mut_repo.view().branches().get("main"), + Some(expected_branch).as_ref() + ); + assert_eq!( + mut_repo.get_git_ref("refs/remotes/origin/main"), + Some(RefTarget::Normal(jj_id(&git_commit))) + ); + + // Export the branch to git + assert_eq!(git::export_refs(mut_repo, &git_repo), Ok(vec![])); + assert_eq!(mut_repo.get_git_ref("refs/heads/main"), None); +} + #[test] fn test_export_conflicts() { // We skip export of conflicted branches @@ -895,6 +945,7 @@ fn test_init() { #[test] fn test_fetch_empty_repo() { let test_data = GitRepoData::create(); + let git_settings = GitSettings::default(); let mut tx = test_data .repo @@ -904,6 +955,7 @@ fn test_fetch_empty_repo() { &test_data.git_repo, "origin", git::RemoteCallbacks::default(), + &git_settings, ) .unwrap(); // No default branch and no refs @@ -915,6 +967,7 @@ fn test_fetch_empty_repo() { #[test] fn test_fetch_initial_commit() { let test_data = GitRepoData::create(); + let git_settings = GitSettings::default(); let initial_git_commit = empty_git_commit(&test_data.origin_repo, "refs/heads/main", &[]); let mut tx = test_data @@ -925,6 +978,7 @@ fn test_fetch_initial_commit() { &test_data.git_repo, "origin", git::RemoteCallbacks::default(), + &git_settings, ) .unwrap(); // No default branch because the origin repo's HEAD wasn't set @@ -954,6 +1008,7 @@ fn test_fetch_initial_commit() { #[test] fn test_fetch_success() { let mut test_data = GitRepoData::create(); + let git_settings = GitSettings::default(); let initial_git_commit = empty_git_commit(&test_data.origin_repo, "refs/heads/main", &[]); let mut tx = test_data @@ -964,6 +1019,7 @@ fn test_fetch_success() { &test_data.git_repo, "origin", git::RemoteCallbacks::default(), + &git_settings, ) .unwrap(); test_data.repo = tx.commit(); @@ -983,6 +1039,7 @@ fn test_fetch_success() { &test_data.git_repo, "origin", git::RemoteCallbacks::default(), + &git_settings, ) .unwrap(); // The default branch is "main" @@ -1012,6 +1069,7 @@ fn test_fetch_success() { #[test] fn test_fetch_prune_deleted_ref() { let test_data = GitRepoData::create(); + let git_settings = GitSettings::default(); empty_git_commit(&test_data.git_repo, "refs/heads/main", &[]); let mut tx = test_data @@ -1022,6 +1080,7 @@ fn test_fetch_prune_deleted_ref() { &test_data.git_repo, "origin", git::RemoteCallbacks::default(), + &git_settings, ) .unwrap(); // Test the setup @@ -1039,6 +1098,7 @@ fn test_fetch_prune_deleted_ref() { &test_data.git_repo, "origin", git::RemoteCallbacks::default(), + &git_settings, ) .unwrap(); assert!(tx.mut_repo().get_branch("main").is_none()); @@ -1047,6 +1107,7 @@ fn test_fetch_prune_deleted_ref() { #[test] fn test_fetch_no_default_branch() { let test_data = GitRepoData::create(); + let git_settings = GitSettings::default(); let initial_git_commit = empty_git_commit(&test_data.origin_repo, "refs/heads/main", &[]); let mut tx = test_data @@ -1057,6 +1118,7 @@ fn test_fetch_no_default_branch() { &test_data.git_repo, "origin", git::RemoteCallbacks::default(), + &git_settings, ) .unwrap(); @@ -1078,6 +1140,7 @@ fn test_fetch_no_default_branch() { &test_data.git_repo, "origin", git::RemoteCallbacks::default(), + &git_settings, ) .unwrap(); // There is no default branch @@ -1087,7 +1150,7 @@ fn test_fetch_no_default_branch() { #[test] fn test_fetch_no_such_remote() { let test_data = GitRepoData::create(); - + let git_settings = GitSettings::default(); let mut tx = test_data .repo .start_transaction(&test_data.settings, "test"); @@ -1096,6 +1159,7 @@ fn test_fetch_no_such_remote() { &test_data.git_repo, "invalid-remote", git::RemoteCallbacks::default(), + &git_settings, ); assert!(matches!(result, Err(GitFetchError::NoSuchRemote(_)))); } diff --git a/lib/tests/test_revset.rs b/lib/tests/test_revset.rs index c8d0c97c445..737f25ef8c9 100644 --- a/lib/tests/test_revset.rs +++ b/lib/tests/test_revset.rs @@ -25,6 +25,7 @@ use jujutsu_lib::revset::{ self, optimize, parse, resolve_symbol, RevsetAliasesMap, RevsetError, RevsetExpression, RevsetWorkspaceContext, }; +use jujutsu_lib::settings::GitSettings; use jujutsu_lib::workspace::Workspace; use test_case::test_case; use testutils::{ @@ -159,6 +160,7 @@ fn test_resolve_symbol_commit_id() { #[test] fn test_resolve_symbol_change_id() { let settings = testutils::user_settings(); + let git_settings = GitSettings::default(); // Test only with git so we can get predictable change ids let test_repo = TestRepo::init(true); let repo = &test_repo.repo; @@ -195,7 +197,7 @@ fn test_resolve_symbol_change_id() { } let mut tx = repo.start_transaction(&settings, "test"); - git::import_refs(tx.mut_repo(), &git_repo).unwrap(); + git::import_refs(tx.mut_repo(), &git_repo, &git_settings).unwrap(); let repo = tx.commit(); // Test the test setup diff --git a/src/cli_util.rs b/src/cli_util.rs index 9d4b7b521a2..cc092401933 100644 --- a/src/cli_util.rs +++ b/src/cli_util.rs @@ -506,7 +506,7 @@ impl WorkspaceCommandHelper { git_repo: &Repository, ) -> Result<(), CommandError> { let mut tx = self.start_transaction("import git refs").into_inner(); - git::import_refs(tx.mut_repo(), git_repo)?; + git::import_refs(tx.mut_repo(), git_repo, &self.settings.git_settings())?; if tx.mut_repo().has_changes() { let old_git_head = self.repo.view().git_head(); let new_git_head = tx.mut_repo().view().git_head(); diff --git a/src/commands/git.rs b/src/commands/git.rs index a998d5b264c..f4be0ddcffe 100644 --- a/src/commands/git.rs +++ b/src/commands/git.rs @@ -246,8 +246,16 @@ fn cmd_git_fetch( let repo = workspace_command.repo(); let git_repo = get_git_repo(repo.store())?; let mut tx = workspace_command.start_transaction(&format!("fetch from git remote {}", &remote)); - with_remote_callbacks(ui, |cb| git::fetch(tx.mut_repo(), &git_repo, &remote, cb)) - .map_err(|err| user_error(err.to_string()))?; + with_remote_callbacks(ui, |cb| { + git::fetch( + tx.mut_repo(), + &git_repo, + &remote, + cb, + &command.settings().git_settings(), + ) + }) + .map_err(|err| user_error(err.to_string()))?; tx.finish(ui)?; Ok(()) } @@ -365,7 +373,13 @@ fn do_git_clone( let mut fetch_tx = workspace_command.start_transaction("fetch from git remote into empty repo"); let maybe_default_branch = with_remote_callbacks(ui, |cb| { - git::fetch(fetch_tx.mut_repo(), &git_repo, remote_name, cb) + git::fetch( + fetch_tx.mut_repo(), + &git_repo, + remote_name, + cb, + &command.settings().git_settings(), + ) }) .map_err(|err| match err { GitFetchError::NoSuchRemote(_) => { @@ -792,7 +806,7 @@ fn cmd_git_push( git::push_updates(&git_repo, &remote, &ref_updates, cb) }) .map_err(|err| user_error(err.to_string()))?; - git::import_refs(tx.mut_repo(), &git_repo)?; + git::import_refs(tx.mut_repo(), &git_repo, &command.settings().git_settings())?; tx.finish(ui)?; Ok(()) } @@ -828,7 +842,7 @@ fn cmd_git_import( let repo = workspace_command.repo(); let git_repo = get_git_repo(repo.store())?; let mut tx = workspace_command.start_transaction("import git refs"); - git::import_refs(tx.mut_repo(), &git_repo)?; + git::import_refs(tx.mut_repo(), &git_repo, &command.settings().git_settings())?; tx.finish(ui)?; Ok(()) } diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 7c63cfe5050..a82571421f4 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -980,7 +980,11 @@ fn cmd_init(ui: &mut Ui, command: &CommandHelper, args: &InitArgs) -> Result<(), add_to_git_exclude(ui, &git_repo)?; } else { let mut tx = workspace_command.start_transaction("import git refs"); - jujutsu_lib::git::import_refs(tx.mut_repo(), &git_repo)?; + jujutsu_lib::git::import_refs( + tx.mut_repo(), + &git_repo, + &command.settings().git_settings(), + )?; if let Some(git_head_id) = tx.mut_repo().view().git_head() { let git_head_commit = tx.mut_repo().store().get_commit(&git_head_id)?; tx.check_out(&git_head_commit)?; diff --git a/tests/test_git_import_export.rs b/tests/test_git_import_export.rs index 927ab1c1dad..7e0f36bdb01 100644 --- a/tests/test_git_import_export.rs +++ b/tests/test_git_import_export.rs @@ -62,6 +62,7 @@ fn test_git_import_remote_only_branch() { &["git", "remote", "add", "origin", "../git-repo"], ); + // Import using default config git_repo .commit( Some("refs/heads/feature1"), @@ -76,6 +77,25 @@ fn test_git_import_remote_only_branch() { insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###" feature1: 9f01a0e04879 message "###); + + // Import using git.auto_local_branch = false + git_repo + .commit( + Some("refs/heads/feature2"), + &signature, + &signature, + "message", + &tree, + &[], + ) + .unwrap(); + test_env.add_config(b"git.auto-local-branch = false"); + test_env.jj_cmd_success(&repo_path, &["git", "fetch", "--remote=origin"]); + insta::assert_snapshot!(get_branch_output(&test_env, &repo_path), @r###" + feature1: 9f01a0e04879 message + feature2 (deleted) + @origin: 9f01a0e04879 message + "###); } fn get_branch_output(test_env: &TestEnvironment, repo_path: &Path) -> String {