forked from mirrors/jj
git: on push, update jj's view of remote branches without using import_refs()
This means that the commits previously pinned by remote branches are no longer abandoned. I think that's more correct since "push" is the operation to propagate local view to remote, and uninteresting commits should have been locally abandoned.
This commit is contained in:
parent
c8a848d260
commit
e0965c4533
7 changed files with 131 additions and 18 deletions
|
@ -38,6 +38,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
See [automatic local branch creation](docs/config.md#automatic-local-branch-creation)
|
See [automatic local branch creation](docs/config.md#automatic-local-branch-creation)
|
||||||
for details.
|
for details.
|
||||||
|
|
||||||
|
* Pushing deleted/moved branches no longer abandons the local commits referenced
|
||||||
|
by the remote branches.
|
||||||
|
|
||||||
### New features
|
### New features
|
||||||
|
|
||||||
* `jj workspace add` now takes a `--revision` argument.
|
* `jj workspace add` now takes a `--revision` argument.
|
||||||
|
|
|
@ -977,7 +977,7 @@ fn cmd_git_push(
|
||||||
force_pushed_branches,
|
force_pushed_branches,
|
||||||
};
|
};
|
||||||
with_remote_callbacks(ui, |cb| {
|
with_remote_callbacks(ui, |cb| {
|
||||||
git::push_branches(&git_repo, &remote, &targets, cb)
|
git::push_branches(tx.mut_repo(), &git_repo, &remote, &targets, cb)
|
||||||
})
|
})
|
||||||
.map_err(|err| match err {
|
.map_err(|err| match err {
|
||||||
GitPushError::InternalGitError(err) => map_git_error(err),
|
GitPushError::InternalGitError(err) => map_git_error(err),
|
||||||
|
@ -988,9 +988,6 @@ fn cmd_git_push(
|
||||||
),
|
),
|
||||||
_ => user_error(err.to_string()),
|
_ => user_error(err.to_string()),
|
||||||
})?;
|
})?;
|
||||||
// TODO: mark pushed remote branches as tracking
|
|
||||||
let stats = git::import_refs(tx.mut_repo(), &git_repo, &command.settings().git_settings())?;
|
|
||||||
print_git_import_stats(ui, &stats)?;
|
|
||||||
tx.finish(ui)?;
|
tx.finish(ui)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -300,13 +300,22 @@ fn test_git_push_multiple() {
|
||||||
Delete branch branch1 from 45a3aa29e907
|
Delete branch branch1 from 45a3aa29e907
|
||||||
Force branch branch2 from 8476341eb395 to 15dcdaa4f12f
|
Force branch branch2 from 8476341eb395 to 15dcdaa4f12f
|
||||||
Add branch my-branch to 15dcdaa4f12f
|
Add branch my-branch to 15dcdaa4f12f
|
||||||
Abandoned 2 commits that are no longer reachable.
|
|
||||||
"###);
|
"###);
|
||||||
let stdout = test_env.jj_cmd_success(&workspace_root, &["branch", "list"]);
|
let stdout = test_env.jj_cmd_success(&workspace_root, &["branch", "list"]);
|
||||||
insta::assert_snapshot!(stdout, @r###"
|
insta::assert_snapshot!(stdout, @r###"
|
||||||
branch2: yqosqzyt 15dcdaa4 (empty) foo
|
branch2: yqosqzyt 15dcdaa4 (empty) foo
|
||||||
my-branch: yqosqzyt 15dcdaa4 (empty) foo
|
my-branch: yqosqzyt 15dcdaa4 (empty) foo
|
||||||
"###);
|
"###);
|
||||||
|
let stdout = test_env.jj_cmd_success(&workspace_root, &["log", "-rall()"]);
|
||||||
|
insta::assert_snapshot!(stdout, @r###"
|
||||||
|
@ yqosqzyt test.user@example.com 2001-02-03 04:05:17.000 +07:00 branch2 my-branch 15dcdaa4
|
||||||
|
│ (empty) foo
|
||||||
|
│ ◉ rlzusymt test.user@example.com 2001-02-03 04:05:10.000 +07:00 8476341e
|
||||||
|
├─╯ (empty) description 2
|
||||||
|
│ ◉ lzmmnrxq test.user@example.com 2001-02-03 04:05:08.000 +07:00 45a3aa29
|
||||||
|
├─╯ (empty) description 1
|
||||||
|
◉ zzzzzzzz root() 00000000
|
||||||
|
"###);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -588,7 +597,16 @@ fn test_git_push_deleted() {
|
||||||
insta::assert_snapshot!(stderr, @r###"
|
insta::assert_snapshot!(stderr, @r###"
|
||||||
Branch changes to push to origin:
|
Branch changes to push to origin:
|
||||||
Delete branch branch1 from 45a3aa29e907
|
Delete branch branch1 from 45a3aa29e907
|
||||||
Abandoned 1 commits that are no longer reachable.
|
"###);
|
||||||
|
let stdout = test_env.jj_cmd_success(&workspace_root, &["log", "-rall()"]);
|
||||||
|
insta::assert_snapshot!(stdout, @r###"
|
||||||
|
◉ rlzusymt test.user@example.com 2001-02-03 04:05:10.000 +07:00 branch2 8476341e
|
||||||
|
│ (empty) description 2
|
||||||
|
│ ◉ lzmmnrxq test.user@example.com 2001-02-03 04:05:08.000 +07:00 45a3aa29
|
||||||
|
├─╯ (empty) description 1
|
||||||
|
│ @ yqosqzyt test.user@example.com 2001-02-03 04:05:13.000 +07:00 5b36783c
|
||||||
|
├─╯ (empty) (no description set)
|
||||||
|
◉ zzzzzzzz root() 00000000
|
||||||
"###);
|
"###);
|
||||||
let (stdout, stderr) = test_env.jj_cmd_ok(&workspace_root, &["git", "push", "--deleted"]);
|
let (stdout, stderr) = test_env.jj_cmd_ok(&workspace_root, &["git", "push", "--deleted"]);
|
||||||
insta::assert_snapshot!(stdout, @"");
|
insta::assert_snapshot!(stdout, @"");
|
||||||
|
|
|
@ -197,8 +197,7 @@ In particular, a merge of local and remote targets is
|
||||||
* ~`tags`~ (not implemented, but should be the same as `branches`)
|
* ~`tags`~ (not implemented, but should be the same as `branches`)
|
||||||
2. Pushes diff to the remote Git repo (as well as remote tracking branches
|
2. Pushes diff to the remote Git repo (as well as remote tracking branches
|
||||||
in the backing Git repo.)
|
in the backing Git repo.)
|
||||||
3. Sets `remotes[remote].branches[name].state = tracking`
|
3. Updates `remotes[remote]` and `git_refs` reflecting the push.
|
||||||
4. Import changes only for `remotes[remote].branches[glob]`
|
|
||||||
|
|
||||||
* `jj git export`
|
* `jj git export`
|
||||||
1. Copies local `branches`/`tags` back to `remotes["git"]`.
|
1. Copies local `branches`/`tags` back to `remotes["git"]`.
|
||||||
|
@ -288,25 +287,22 @@ Note: desired behavior of `jj branch forget` is to
|
||||||
|
|
||||||
* Pushing new branch, remote doesn't exist
|
* Pushing new branch, remote doesn't exist
|
||||||
1. Pushes `[local, absent] - [absent]` -> `local`
|
1. Pushes `[local, absent] - [absent]` -> `local`
|
||||||
2. Sets `remotes[remote].branches[name].state = tracking`
|
2. Sets `remotes[remote].branches[name].target = local`, `.state = tracking`
|
||||||
3. `import_refs()` merges `[local, local] - [absent]` -> `local` (noop)
|
|
||||||
* Pushing new branch, untracked remote exists
|
* Pushing new branch, untracked remote exists
|
||||||
1. Pushes `[local, remote] - [absent]`
|
1. Pushes `[local, remote] - [absent]`
|
||||||
* Fails if `local` moved backwards or sideways
|
* Fails if `local` moved backwards or sideways
|
||||||
2. Sets `remotes[remote].branches[name].state = tracking`
|
2. Sets `remotes[remote].branches[name].target = local`, `.state = tracking`
|
||||||
3. `import_refs()` merges `[local, local] - [remote]` -> `local` (noop)
|
|
||||||
* Pushing existing branch to tracking remote
|
* Pushing existing branch to tracking remote
|
||||||
1. Pushes `[local, remote] - [remote]` -> `local`
|
1. Pushes `[local, remote] - [remote]` -> `local`
|
||||||
* Fails if `local` moved backwards or sideways, and if `remote` is out of
|
* Fails if `local` moved backwards or sideways, and if `remote` is out of
|
||||||
sync
|
sync
|
||||||
2. `import_refs()` merges `[local, local] - [remote]` -> `local` (noop)
|
2. Sets `remotes[remote].branches[name].target = local`
|
||||||
* Pushing existing branch to untracked remote
|
* Pushing existing branch to untracked remote
|
||||||
* Same as "new branch"
|
* Same as "new branch"
|
||||||
* Pushing deleted branch to tracking remote
|
* Pushing deleted branch to tracking remote
|
||||||
1. Pushes `[absent, remote] - [remote]` -> `absent`
|
1. Pushes `[absent, remote] - [remote]` -> `absent`
|
||||||
* TODO: Fails if `remote` is out of sync?
|
* TODO: Fails if `remote` is out of sync?
|
||||||
2. `import_refs()` merges `[absent, absent] - [remote]` -> `absent`
|
2. Removes `remotes[remote].branches[name]` (`target` becomes `absent`)
|
||||||
3. Removes `remotes[remote].branches[name]` (`target` becomes `absent`)
|
|
||||||
* Pushing deleted branch to untracked remote
|
* Pushing deleted branch to untracked remote
|
||||||
* Noop since `[absent, remote] - [absent]` -> `remote`
|
* Noop since `[absent, remote] - [absent]` -> `remote`
|
||||||
* Perhaps, UI will report error
|
* Perhaps, UI will report error
|
||||||
|
|
|
@ -1094,7 +1094,9 @@ pub struct GitRefUpdate {
|
||||||
pub new_target: Option<CommitId>,
|
pub new_target: Option<CommitId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Pushes the specified branches and updates the repo view accordingly.
|
||||||
pub fn push_branches(
|
pub fn push_branches(
|
||||||
|
mut_repo: &mut MutableRepo,
|
||||||
git_repo: &git2::Repository,
|
git_repo: &git2::Repository,
|
||||||
remote_name: &str,
|
remote_name: &str,
|
||||||
targets: &GitBranchPushTargets,
|
targets: &GitBranchPushTargets,
|
||||||
|
@ -1110,9 +1112,24 @@ pub fn push_branches(
|
||||||
})
|
})
|
||||||
.collect_vec();
|
.collect_vec();
|
||||||
push_updates(git_repo, remote_name, &ref_updates, callbacks)?;
|
push_updates(git_repo, remote_name, &ref_updates, callbacks)?;
|
||||||
|
|
||||||
|
// TODO: add support for partially pushed refs? we could update the view
|
||||||
|
// excluding rejected refs, but the transaction would be aborted anyway
|
||||||
|
// if we returned an Err.
|
||||||
|
for (branch_name, update) in &targets.branch_updates {
|
||||||
|
let git_ref_name = format!("refs/remotes/{remote_name}/{branch_name}");
|
||||||
|
let new_remote_ref = RemoteRef {
|
||||||
|
target: RefTarget::resolved(update.new_target.clone()),
|
||||||
|
state: RemoteRefState::Tracking,
|
||||||
|
};
|
||||||
|
mut_repo.set_git_ref_target(&git_ref_name, new_remote_ref.target.clone());
|
||||||
|
mut_repo.set_remote_branch(branch_name, remote_name, new_remote_ref);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Pushes the specified Git refs without updating the repo view.
|
||||||
pub fn push_updates(
|
pub fn push_updates(
|
||||||
git_repo: &git2::Repository,
|
git_repo: &git2::Repository,
|
||||||
remote_name: &str,
|
remote_name: &str,
|
||||||
|
|
|
@ -83,6 +83,11 @@ impl RefTarget {
|
||||||
&TARGET
|
&TARGET
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates non-conflicting target that optionally points to a commit.
|
||||||
|
pub fn resolved(maybe_id: Option<CommitId>) -> Self {
|
||||||
|
Self::from_merge(Merge::resolved(maybe_id))
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates non-conflicting target pointing to a commit.
|
/// Creates non-conflicting target pointing to a commit.
|
||||||
pub fn normal(id: CommitId) -> Self {
|
pub fn normal(id: CommitId) -> Self {
|
||||||
Self::from_merge(Merge::normal(id))
|
Self::from_merge(Merge::normal(id))
|
||||||
|
|
|
@ -2256,6 +2256,20 @@ fn set_up_push_repos(settings: &UserSettings, temp_dir: &TempDir) -> PushTestSet
|
||||||
.set_parents(vec![initial_commit.id().clone()])
|
.set_parents(vec![initial_commit.id().clone()])
|
||||||
.write()
|
.write()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
tx.mut_repo().set_git_ref_target(
|
||||||
|
"refs/remotes/origin/main",
|
||||||
|
RefTarget::normal(initial_commit.id().clone()),
|
||||||
|
);
|
||||||
|
tx.mut_repo().set_remote_branch(
|
||||||
|
"main",
|
||||||
|
"origin",
|
||||||
|
RemoteRef {
|
||||||
|
target: RefTarget::normal(initial_commit.id().clone()),
|
||||||
|
// Caller expects the main branch is tracked. The corresponding local branch will
|
||||||
|
// be created (or left as deleted) by caller.
|
||||||
|
state: RemoteRefState::Tracking,
|
||||||
|
},
|
||||||
|
);
|
||||||
let jj_repo = tx.commit();
|
let jj_repo = tx.commit();
|
||||||
PushTestSetup {
|
PushTestSetup {
|
||||||
source_repo_dir,
|
source_repo_dir,
|
||||||
|
@ -2269,8 +2283,9 @@ fn set_up_push_repos(settings: &UserSettings, temp_dir: &TempDir) -> PushTestSet
|
||||||
fn test_push_branches_success() {
|
fn test_push_branches_success() {
|
||||||
let settings = testutils::user_settings();
|
let settings = testutils::user_settings();
|
||||||
let temp_dir = testutils::new_temp_dir();
|
let temp_dir = testutils::new_temp_dir();
|
||||||
let setup = set_up_push_repos(&settings, &temp_dir);
|
let mut setup = set_up_push_repos(&settings, &temp_dir);
|
||||||
let clone_repo = get_git_repo(&setup.jj_repo);
|
let clone_repo = get_git_repo(&setup.jj_repo);
|
||||||
|
let mut tx = setup.jj_repo.start_transaction(&settings, "test");
|
||||||
|
|
||||||
let targets = GitBranchPushTargets {
|
let targets = GitBranchPushTargets {
|
||||||
branch_updates: vec![(
|
branch_updates: vec![(
|
||||||
|
@ -2283,6 +2298,7 @@ fn test_push_branches_success() {
|
||||||
force_pushed_branches: hashset! {},
|
force_pushed_branches: hashset! {},
|
||||||
};
|
};
|
||||||
let result = git::push_branches(
|
let result = git::push_branches(
|
||||||
|
tx.mut_repo(),
|
||||||
&clone_repo,
|
&clone_repo,
|
||||||
"origin",
|
"origin",
|
||||||
&targets,
|
&targets,
|
||||||
|
@ -2307,14 +2323,35 @@ fn test_push_branches_success() {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.target();
|
.target();
|
||||||
assert_eq!(new_target, Some(new_oid));
|
assert_eq!(new_target, Some(new_oid));
|
||||||
|
|
||||||
|
// Check that the repo view got updated
|
||||||
|
let view = tx.mut_repo().view();
|
||||||
|
assert_eq!(
|
||||||
|
*view.get_git_ref("refs/remotes/origin/main"),
|
||||||
|
RefTarget::normal(setup.new_commit.id().clone()),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
*view.get_remote_branch("main", "origin"),
|
||||||
|
RemoteRef {
|
||||||
|
target: RefTarget::normal(setup.new_commit.id().clone()),
|
||||||
|
state: RemoteRefState::Tracking,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check that the repo view reflects the changes in the Git repo
|
||||||
|
setup.jj_repo = tx.commit();
|
||||||
|
let mut tx = setup.jj_repo.start_transaction(&settings, "test");
|
||||||
|
git::import_refs(tx.mut_repo(), &clone_repo, &GitSettings::default()).unwrap();
|
||||||
|
assert!(!tx.mut_repo().has_changes());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_push_branches_deletion() {
|
fn test_push_branches_deletion() {
|
||||||
let settings = testutils::user_settings();
|
let settings = testutils::user_settings();
|
||||||
let temp_dir = testutils::new_temp_dir();
|
let temp_dir = testutils::new_temp_dir();
|
||||||
let setup = set_up_push_repos(&settings, &temp_dir);
|
let mut setup = set_up_push_repos(&settings, &temp_dir);
|
||||||
let clone_repo = get_git_repo(&setup.jj_repo);
|
let clone_repo = get_git_repo(&setup.jj_repo);
|
||||||
|
let mut tx = setup.jj_repo.start_transaction(&settings, "test");
|
||||||
|
|
||||||
let source_repo = git2::Repository::open(&setup.source_repo_dir).unwrap();
|
let source_repo = git2::Repository::open(&setup.source_repo_dir).unwrap();
|
||||||
// Test the setup
|
// Test the setup
|
||||||
|
@ -2331,6 +2368,7 @@ fn test_push_branches_deletion() {
|
||||||
force_pushed_branches: hashset! {},
|
force_pushed_branches: hashset! {},
|
||||||
};
|
};
|
||||||
let result = git::push_branches(
|
let result = git::push_branches(
|
||||||
|
tx.mut_repo(),
|
||||||
&get_git_repo(&setup.jj_repo),
|
&get_git_repo(&setup.jj_repo),
|
||||||
"origin",
|
"origin",
|
||||||
&targets,
|
&targets,
|
||||||
|
@ -2347,14 +2385,26 @@ fn test_push_branches_deletion() {
|
||||||
assert!(clone_repo
|
assert!(clone_repo
|
||||||
.find_reference("refs/remotes/origin/main")
|
.find_reference("refs/remotes/origin/main")
|
||||||
.is_err());
|
.is_err());
|
||||||
|
|
||||||
|
// Check that the repo view got updated
|
||||||
|
let view = tx.mut_repo().view();
|
||||||
|
assert!(view.get_git_ref("refs/remotes/origin/main").is_absent());
|
||||||
|
assert!(view.get_remote_branch("main", "origin").is_absent());
|
||||||
|
|
||||||
|
// Check that the repo view reflects the changes in the Git repo
|
||||||
|
setup.jj_repo = tx.commit();
|
||||||
|
let mut tx = setup.jj_repo.start_transaction(&settings, "test");
|
||||||
|
git::import_refs(tx.mut_repo(), &clone_repo, &GitSettings::default()).unwrap();
|
||||||
|
assert!(!tx.mut_repo().has_changes());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_push_branches_mixed_deletion_and_addition() {
|
fn test_push_branches_mixed_deletion_and_addition() {
|
||||||
let settings = testutils::user_settings();
|
let settings = testutils::user_settings();
|
||||||
let temp_dir = testutils::new_temp_dir();
|
let temp_dir = testutils::new_temp_dir();
|
||||||
let setup = set_up_push_repos(&settings, &temp_dir);
|
let mut setup = set_up_push_repos(&settings, &temp_dir);
|
||||||
let clone_repo = get_git_repo(&setup.jj_repo);
|
let clone_repo = get_git_repo(&setup.jj_repo);
|
||||||
|
let mut tx = setup.jj_repo.start_transaction(&settings, "test");
|
||||||
|
|
||||||
let targets = GitBranchPushTargets {
|
let targets = GitBranchPushTargets {
|
||||||
branch_updates: vec![
|
branch_updates: vec![
|
||||||
|
@ -2376,6 +2426,7 @@ fn test_push_branches_mixed_deletion_and_addition() {
|
||||||
force_pushed_branches: hashset! {},
|
force_pushed_branches: hashset! {},
|
||||||
};
|
};
|
||||||
let result = git::push_branches(
|
let result = git::push_branches(
|
||||||
|
tx.mut_repo(),
|
||||||
&clone_repo,
|
&clone_repo,
|
||||||
"origin",
|
"origin",
|
||||||
&targets,
|
&targets,
|
||||||
|
@ -2393,6 +2444,28 @@ fn test_push_branches_mixed_deletion_and_addition() {
|
||||||
|
|
||||||
// Check that the main ref got deleted in the source repo
|
// Check that the main ref got deleted in the source repo
|
||||||
assert!(source_repo.find_reference("refs/heads/main").is_err());
|
assert!(source_repo.find_reference("refs/heads/main").is_err());
|
||||||
|
|
||||||
|
// Check that the repo view got updated
|
||||||
|
let view = tx.mut_repo().view();
|
||||||
|
assert!(view.get_git_ref("refs/remotes/origin/main").is_absent());
|
||||||
|
assert!(view.get_remote_branch("main", "origin").is_absent());
|
||||||
|
assert_eq!(
|
||||||
|
*view.get_git_ref("refs/remotes/origin/topic"),
|
||||||
|
RefTarget::normal(setup.new_commit.id().clone()),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
*view.get_remote_branch("topic", "origin"),
|
||||||
|
RemoteRef {
|
||||||
|
target: RefTarget::normal(setup.new_commit.id().clone()),
|
||||||
|
state: RemoteRefState::Tracking,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check that the repo view reflects the changes in the Git repo
|
||||||
|
setup.jj_repo = tx.commit();
|
||||||
|
let mut tx = setup.jj_repo.start_transaction(&settings, "test");
|
||||||
|
git::import_refs(tx.mut_repo(), &clone_repo, &GitSettings::default()).unwrap();
|
||||||
|
assert!(!tx.mut_repo().has_changes());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -2403,6 +2476,7 @@ fn test_push_branches_not_fast_forward() {
|
||||||
let mut tx = setup.jj_repo.start_transaction(&settings, "test");
|
let mut tx = setup.jj_repo.start_transaction(&settings, "test");
|
||||||
let new_commit = write_random_commit(tx.mut_repo(), &settings);
|
let new_commit = write_random_commit(tx.mut_repo(), &settings);
|
||||||
setup.jj_repo = tx.commit();
|
setup.jj_repo = tx.commit();
|
||||||
|
let mut tx = setup.jj_repo.start_transaction(&settings, "test");
|
||||||
|
|
||||||
let targets = GitBranchPushTargets {
|
let targets = GitBranchPushTargets {
|
||||||
branch_updates: vec![(
|
branch_updates: vec![(
|
||||||
|
@ -2415,6 +2489,7 @@ fn test_push_branches_not_fast_forward() {
|
||||||
force_pushed_branches: hashset! {},
|
force_pushed_branches: hashset! {},
|
||||||
};
|
};
|
||||||
let result = git::push_branches(
|
let result = git::push_branches(
|
||||||
|
tx.mut_repo(),
|
||||||
&get_git_repo(&setup.jj_repo),
|
&get_git_repo(&setup.jj_repo),
|
||||||
"origin",
|
"origin",
|
||||||
&targets,
|
&targets,
|
||||||
|
@ -2431,6 +2506,7 @@ fn test_push_branches_not_fast_forward_with_force() {
|
||||||
let mut tx = setup.jj_repo.start_transaction(&settings, "test");
|
let mut tx = setup.jj_repo.start_transaction(&settings, "test");
|
||||||
let new_commit = write_random_commit(tx.mut_repo(), &settings);
|
let new_commit = write_random_commit(tx.mut_repo(), &settings);
|
||||||
setup.jj_repo = tx.commit();
|
setup.jj_repo = tx.commit();
|
||||||
|
let mut tx = setup.jj_repo.start_transaction(&settings, "test");
|
||||||
|
|
||||||
let targets = GitBranchPushTargets {
|
let targets = GitBranchPushTargets {
|
||||||
branch_updates: vec![(
|
branch_updates: vec![(
|
||||||
|
@ -2445,6 +2521,7 @@ fn test_push_branches_not_fast_forward_with_force() {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let result = git::push_branches(
|
let result = git::push_branches(
|
||||||
|
tx.mut_repo(),
|
||||||
&get_git_repo(&setup.jj_repo),
|
&get_git_repo(&setup.jj_repo),
|
||||||
"origin",
|
"origin",
|
||||||
&targets,
|
&targets,
|
||||||
|
|
Loading…
Reference in a new issue