cli: git clone: add config to not track default remote bookmark

Since jj operates in detached HEAD state, a tracking bookmark isn't technically
needed in order to check out a commit. I usually employ this and delete
unmanaged local bookmarks after cloning repository. This option will automate
the setup.
This commit is contained in:
Yuya Nishihara 2025-05-14 11:32:41 +09:00
parent 2ac5ba0c18
commit dd33f9ae08
6 changed files with 91 additions and 2 deletions

View File

@ -40,6 +40,9 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
anywhere in the revision tree with the `--insert-before`, `--insert-after` and
`--destination` command line flags.
* Added `git.track-default-bookmark-on-clone` setting to control whether to
track the default remote bookmark on `jj git clone`.
### Fixed bugs
* Work around a git issue that could cause subprocess operations to hang if the

View File

@ -214,7 +214,9 @@ fn fetch_new_remote(
r#"Fetching into new repo in "{}""#,
workspace_command.workspace_root().display()
)?;
let git_settings = workspace_command.settings().git_settings()?;
let settings = workspace_command.settings();
let git_settings = settings.git_settings()?;
let track_default = settings.get_bool("git.track-default-bookmark-on-clone")?;
let mut tx = workspace_command.start_transaction();
let mut git_fetch = GitFetch::new(tx.repo_mut(), &git_settings)?;
with_remote_git_callbacks(ui, |cb| {
@ -225,12 +227,19 @@ fn fetch_new_remote(
if let Some(name) = &default_branch {
let remote_symbol = name.to_remote_symbol(remote_name);
let remote_ref = tx.repo().get_remote_bookmark(remote_symbol);
if remote_ref.is_present() {
if track_default && remote_ref.is_present() {
// For convenience, create local bookmark as Git would do.
tx.repo_mut().track_remote_bookmark(remote_symbol);
}
}
print_git_import_stats(ui, tx.repo(), &import_stats, true)?;
if git_settings.auto_local_bookmark && !track_default {
writeln!(
ui.hint_default(),
"`git.track-default-bookmark-on-clone=false` has no effect if \
`git.auto-local-bookmark` is enabled."
)?;
}
tx.finish(ui, "fetch from git remote into empty repo")?;
Ok(default_branch)
}

View File

@ -474,6 +474,11 @@
"description": "Whether jj should sign commits before pushing",
"default": false
},
"track-default-bookmark-on-clone": {
"type": "boolean",
"description": "Whether `jj git clone` creates a local bookmark tracking the default remote bookmark",
"default": true
},
"write-change-id-header": {
"type": "boolean",
"description": "Whether the change id should be stored in the Git commit object",

View File

@ -18,6 +18,7 @@ private-commits = "none()"
push-bookmark-prefix = "push-"
push-new-bookmarks = false
sign-on-push = false
track-default-bookmark-on-clone = true
[ui]
always-allow-large-revsets = false

View File

@ -469,6 +469,63 @@ fn test_git_clone_remote_default_bookmark() {
revset-aliases.'trunk()' = "feature1@origin"
[EOF]
"#);
// No bookmarks should be imported if both auto-local-bookmark and
// track-default-bookmark-on-clone are turned off
let output = root_dir.run_jj([
"git",
"clone",
"--config=git.track-default-bookmark-on-clone=false",
"source",
"clone4",
]);
insta::assert_snapshot!(output, @r#"
------- stderr -------
Fetching into new repo in "$TEST_ENV/clone4"
bookmark: feature1@origin [new] untracked
bookmark: main@origin [new] untracked
Setting the revset alias `trunk()` to `feature1@origin`
Working copy (@) now at: wmwvqwsz 5068d576 (empty) (no description set)
Parent commit (@-) : qomsplrm ebeb70d8 feature1@origin main@origin | message
Added 1 files, modified 0 files, removed 0 files
[EOF]
"#);
let clone_dir4 = test_env.work_dir("clone4");
insta::assert_snapshot!(get_bookmark_output(&clone_dir4), @r"
feature1@origin: qomsplrm ebeb70d8 message
main@origin: qomsplrm ebeb70d8 message
[EOF]
");
// Show hint if track-default-bookmark-on-clone=false has no effect
let output = root_dir.run_jj([
"git",
"clone",
"--config=git.auto-local-bookmark=true",
"--config=git.track-default-bookmark-on-clone=false",
"source",
"clone5",
]);
insta::assert_snapshot!(output, @r#"
------- stderr -------
Fetching into new repo in "$TEST_ENV/clone5"
bookmark: feature1@origin [new] tracked
bookmark: main@origin [new] tracked
Hint: `git.track-default-bookmark-on-clone=false` has no effect if `git.auto-local-bookmark` is enabled.
Setting the revset alias `trunk()` to `feature1@origin`
Working copy (@) now at: vzqnnsmr fea36bca (empty) (no description set)
Parent commit (@-) : qomsplrm ebeb70d8 feature1 main | message
Added 1 files, modified 0 files, removed 0 files
[EOF]
"#);
let clone_dir5 = test_env.work_dir("clone5");
insta::assert_snapshot!(get_bookmark_output(&clone_dir5), @r"
feature1: qomsplrm ebeb70d8 message
@origin: qomsplrm ebeb70d8 message
main: qomsplrm ebeb70d8 message
@origin: qomsplrm ebeb70d8 message
[EOF]
");
}
// A branch with a strange name should get quoted in the config. Windows doesn't

View File

@ -1458,6 +1458,20 @@ jj bookmark delete gh-pages
jj bookmark untrack gh-pages@upstream
```
### Automatic local bookmark creation on `jj git clone`
When cloning a new Git repository, `jj` by default creates a local bookmark
tracking the default remote bookmark (such as `main` for `main@origin`.) If you
aren't going to update the `main` bookmark locally, the tracking bookmark isn't
necessary.
This behavior can be disabled by
```toml
[git]
track-default-bookmark-on-clone = false
```
### Abandon commits that became unreachable in Git
By default, when `jj` imports refs from Git, it will look for commits that used