Skip to content

Commit

Permalink
git: add config to disable abandoning of unreachable commits
Browse files Browse the repository at this point in the history
Some users prefer to have commits not get abandoned when importing
refs. This adds a config option for that.

Closes #2504.
  • Loading branch information
martinvonz committed Nov 5, 2023
1 parent 39128b6 commit 745d8cb
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
create a new workspace with its working-copy commit on top of all the parents,
as if you had run `jj new r1 r2 r3 ...`.

* You can now set `git.abandon-unreachable-commits = false` to disable the
usual behavior where commits that became unreachable in the Git repo are
abandoned ([#2504](https://github.com/martinvonz/jj/pull/2504)).

### Fixed bugs


Expand Down
5 changes: 5 additions & 0 deletions cli/src/config-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,11 @@
"description": "Whether jj creates a local branch with the same name when it imports a remote-tracking branch from git. See https://github.com/martinvonz/jj/blob/main/docs/config.md#automatic-local-branch-creation",
"default": true
},
"abandon-unreachable-commits": {
"type": "boolean",
"description": "Whether jj should abandon commits that became unreachable in Git.",
"default": true
},
"push-branch-prefix": {
"type": "string",
"description": "Prefix used when pushing a change ID as a new branch",
Expand Down
14 changes: 14 additions & 0 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,20 @@ jj branch delete gh-pages
jj branch untrack gh-pages@upstream
```

### Abandon commits that became unreachable in Git

By default, when `jj` imports refs from Git, it will look for commits that used
to be [reachable][reachable] but no longer are reachable. Those commits will
then be abandoned, and any descendant commits will be rebased off of them (as
usual when commits are abandoned). You can disable this behavior and instead
leave the Git-unreachable commits in your repo by setting:

```toml
git.abandon-unreachable-commits = false
```

[reachable]: https://git-scm.com/docs/gitglossary/#Documentation/gitglossary.txt-aiddefreachableareachable

### Prefix for generated branches on push

`jj git push --change` generates branch names with a prefix of "push-" by
Expand Down
6 changes: 5 additions & 1 deletion lib/src/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,11 @@ pub fn import_some_refs(
}
}

let abandoned_commits = abandon_unreachable_commits(changed_remote_refs, mut_repo);
let abandoned_commits = if git_settings.abandon_unreachable_commits {
abandon_unreachable_commits(changed_remote_refs, mut_repo)
} else {
vec![]
};
let stats = GitImportStats { abandoned_commits };
Ok(stats)
}
Expand Down
5 changes: 5 additions & 0 deletions lib/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,16 @@ pub struct RepoSettings {
#[derive(Debug, Clone)]
pub struct GitSettings {
pub auto_local_branch: bool,
pub abandon_unreachable_commits: bool,
}

impl GitSettings {
pub fn from_config(config: &config::Config) -> Self {
GitSettings {
auto_local_branch: config.get_bool("git.auto-local-branch").unwrap_or(true),
abandon_unreachable_commits: config
.get_bool("git.abandon-unreachable-commits")
.unwrap_or(true),
}
}
}
Expand All @@ -54,6 +58,7 @@ impl Default for GitSettings {
fn default() -> Self {
GitSettings {
auto_local_branch: true,
abandon_unreachable_commits: true,
}
}
}
Expand Down
33 changes: 33 additions & 0 deletions lib/tests/test_git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,7 @@ fn test_import_refs_reimport_with_moved_untracked_remote_ref() {
let settings = testutils::user_settings();
let git_settings = GitSettings {
auto_local_branch: false,
..Default::default()
};
let test_workspace = TestRepo::init_with_backend(TestRepoBackend::Git);
let repo = &test_workspace.repo;
Expand Down Expand Up @@ -819,6 +820,37 @@ fn test_import_refs_reimport_all_from_root_removed() {
assert!(!tx.mut_repo().view().heads().contains(&jj_id(&commit)));
}

#[test]
fn test_import_refs_reimport_abandoning_disabled() {
// Test that we don't abandoned unreachable commits if configured not to
let settings = testutils::user_settings();
let git_settings = GitSettings {
abandon_unreachable_commits: false,
..Default::default()
};
let test_repo = TestRepo::init_with_backend(TestRepoBackend::Git);
let repo = &test_repo.repo;
let git_repo = get_git_repo(repo);

let commit1 = empty_git_commit(&git_repo, "refs/heads/main", &[]);
let commit2 = empty_git_commit(&git_repo, "refs/heads/delete-me", &[&commit1]);
let mut tx = repo.start_transaction(&settings, "test");
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(&commit2)));

// Remove the `delete-me` branch and re-import
git_repo
.find_reference("refs/heads/delete-me")
.unwrap()
.delete()
.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(&commit2)));
}

#[test]
fn test_import_refs_reimport_conflicted_remote_branch() {
let settings = testutils::user_settings();
Expand Down Expand Up @@ -1426,6 +1458,7 @@ fn test_import_export_non_tracking_branch() {
let test_data = GitRepoData::create();
let mut git_settings = GitSettings {
auto_local_branch: false,
..Default::default()
};
let git_repo = test_data.git_repo;
let commit_main_t0 = empty_git_commit(&git_repo, "refs/remotes/origin/main", &[]);
Expand Down

0 comments on commit 745d8cb

Please sign in to comment.