Skip to content

Commit

Permalink
git: add git.auto-local-branch
Browse files Browse the repository at this point in the history
Add a new git.auto-local-branch config option. When set to false, a
remote-tracking branch imported from Git will not automatically create a
local branch target. This is implemented by a new GitSettings struct
that passes Git-related settings from UserSettings.

This behavior is particularly useful in a co-located jj and Git repo,
because a Git remote might have branches that are not of everyday
interest to the user, so it does not make sense to export them as local
branches in Git. E.g. https://github.com/gitster/git, the maintainer's
fork of Git, has 379 branches, most of which are topic branches kept
around for historical reasons, and Git developers wouldn't be expected
to have local branches for each remote-tracking branch.
  • Loading branch information
chooglen committed Jan 30, 2023
1 parent 0169a69 commit a967923
Show file tree
Hide file tree
Showing 9 changed files with 184 additions and 28 deletions.
20 changes: 20 additions & 0 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
8 changes: 7 additions & 1 deletion lib/src/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -336,6 +341,7 @@ pub fn fetch(
git_repo: &git2::Repository,
remote_name: &str,
callbacks: RemoteCallbacks<'_>,
git_settings: &GitSettings,
) -> Result<Option<String>, GitFetchError> {
let mut remote =
git_repo
Expand Down Expand Up @@ -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)
Expand Down
26 changes: 26 additions & 0 deletions lib/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Timestamp> {
match config.get_string(key) {
Ok(timestamp_str) => match DateTime::parse_from_rfc3339(&timestamp_str) {
Expand Down Expand Up @@ -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")
Expand Down
Loading

0 comments on commit a967923

Please sign in to comment.