mirror of
https://github.com/martinvonz/jj.git
synced 2025-01-12 07:14:38 +00:00
cli: push only branches pointing to @
by default
Since we now allow pushing open commits, we can implement support for pushing the "current" branch by defining a "current" branch as any branch pointing to `@`. That definition of a current/active seems to have been the consensus in discussion #411. Closes #246.
This commit is contained in:
parent
78e7a7d176
commit
8bc4574ee5
4 changed files with 109 additions and 9 deletions
|
@ -41,6 +41,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
* `jj git push` no longer aborts if you attempt to push an open commit (but it
|
* `jj git push` no longer aborts if you attempt to push an open commit (but it
|
||||||
now aborts if a commit does not have a description).
|
now aborts if a commit does not have a description).
|
||||||
|
|
||||||
|
* `jj git push` now pushes only branches pointing to the `@` by default. Use
|
||||||
|
`--all` to push all branches.
|
||||||
|
|
||||||
### New features
|
### New features
|
||||||
|
|
||||||
* `jj rebase` now accepts a `--branch/-b <revision>` argument, which can be used
|
* `jj rebase` now accepts a `--branch/-b <revision>` argument, which can be used
|
||||||
|
|
|
@ -108,7 +108,7 @@ parent.
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Update a remote repo with all branches from the local repo</td>
|
<td>Update a remote repo with all branches from the local repo</td>
|
||||||
<td><code>jj git push [--remote <remote>]</code> (there is no
|
<td><code>jj git push --all [--remote <remote>]</code> (there is no
|
||||||
support for pushing from non-Git repos yet)</td>
|
support for pushing from non-Git repos yet)</td>
|
||||||
<td><code>git push --all [<remote>]</code></td>
|
<td><code>git push --all [<remote>]</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -1858,9 +1858,11 @@ struct GitCloneArgs {
|
||||||
|
|
||||||
/// Push to a Git remote
|
/// Push to a Git remote
|
||||||
///
|
///
|
||||||
/// By default, all branches are pushed. Use `--branch` if you want to push only
|
/// By default, pushes any branches pointing to `@`. Use `--branch` to push a
|
||||||
/// one branch.
|
/// specific branch. Use `--all` to push all branches. Use `--change` to
|
||||||
|
/// generate a branch name based on a specific commit's change ID.
|
||||||
#[derive(clap::Args, Clone, Debug)]
|
#[derive(clap::Args, Clone, Debug)]
|
||||||
|
#[clap(group(ArgGroup::new("what").args(&["branch", "all", "change"])))]
|
||||||
struct GitPushArgs {
|
struct GitPushArgs {
|
||||||
/// The remote to push to (only named remotes are supported)
|
/// The remote to push to (only named remotes are supported)
|
||||||
#[clap(long, default_value = "origin")]
|
#[clap(long, default_value = "origin")]
|
||||||
|
@ -1868,6 +1870,9 @@ struct GitPushArgs {
|
||||||
/// Push only this branch
|
/// Push only this branch
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
branch: Option<String>,
|
branch: Option<String>,
|
||||||
|
/// Push all branches
|
||||||
|
#[clap(long)]
|
||||||
|
all: bool,
|
||||||
/// Push this commit by creating a branch based on its change ID
|
/// Push this commit by creating a branch based on its change ID
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
change: Option<String>,
|
change: Option<String>,
|
||||||
|
@ -5123,7 +5128,7 @@ fn cmd_git_push(
|
||||||
branch_name, &args.remote, branch_name
|
branch_name, &args.remote, branch_name
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
} else {
|
} else if args.all {
|
||||||
// TODO: Is it useful to warn about conflicted branches?
|
// TODO: Is it useful to warn about conflicted branches?
|
||||||
for (branch_name, branch_target) in workspace_command.repo().view().branches() {
|
for (branch_name, branch_target) in workspace_command.repo().view().branches() {
|
||||||
let push_action = classify_branch_push_action(branch_target, &args.remote);
|
let push_action = classify_branch_push_action(branch_target, &args.remote);
|
||||||
|
@ -5138,6 +5143,41 @@ fn cmd_git_push(
|
||||||
}
|
}
|
||||||
tx = workspace_command
|
tx = workspace_command
|
||||||
.start_transaction(&format!("push all branches to git remote {}", &args.remote));
|
.start_transaction(&format!("push all branches to git remote {}", &args.remote));
|
||||||
|
} else {
|
||||||
|
match workspace_command
|
||||||
|
.repo()
|
||||||
|
.view()
|
||||||
|
.get_checkout(&workspace_command.workspace_id())
|
||||||
|
{
|
||||||
|
None => {
|
||||||
|
return Err(UserError(
|
||||||
|
"Nothing checked out in this workspace".to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Some(checkout) => {
|
||||||
|
let desired_target = Some(RefTarget::Normal(checkout.clone()));
|
||||||
|
for (branch_name, branch_target) in workspace_command.repo().view().branches() {
|
||||||
|
if branch_target.local_target == desired_target {
|
||||||
|
let push_action = classify_branch_push_action(branch_target, &args.remote);
|
||||||
|
match push_action {
|
||||||
|
BranchPushAction::AlreadyMatches => {}
|
||||||
|
BranchPushAction::LocalConflicted => {}
|
||||||
|
BranchPushAction::RemoteConflicted => {}
|
||||||
|
BranchPushAction::Update(update) => {
|
||||||
|
branch_updates.push((branch_name.clone(), update));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if branch_updates.is_empty() {
|
||||||
|
return Err(UserError("No current branch.".to_string()));
|
||||||
|
}
|
||||||
|
tx = workspace_command.start_transaction(&format!(
|
||||||
|
"push current branch(es) to git remote {}",
|
||||||
|
&args.remote
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if branch_updates.is_empty() {
|
if branch_updates.is_empty() {
|
||||||
|
|
|
@ -64,14 +64,71 @@ fn set_up() -> (TestEnvironment, PathBuf) {
|
||||||
fn test_git_push_nothing() {
|
fn test_git_push_nothing() {
|
||||||
let (test_env, workspace_root) = set_up();
|
let (test_env, workspace_root) = set_up();
|
||||||
// No branches to push yet
|
// No branches to push yet
|
||||||
let stdout = test_env.jj_cmd_success(&workspace_root, &["git", "push"]);
|
let stdout = test_env.jj_cmd_success(&workspace_root, &["git", "push", "--all"]);
|
||||||
insta::assert_snapshot!(stdout, @r###"
|
insta::assert_snapshot!(stdout, @r###"
|
||||||
Nothing changed.
|
Nothing changed.
|
||||||
"###);
|
"###);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_git_push_success() {
|
fn test_git_push_current_branch() {
|
||||||
|
let (test_env, workspace_root) = set_up();
|
||||||
|
// Update some branches. `branch1` is not a current branch, but `branch2` and
|
||||||
|
// `my-branch` are.
|
||||||
|
test_env.jj_cmd_success(
|
||||||
|
&workspace_root,
|
||||||
|
&["describe", "branch1", "-m", "modified branch1 commit"],
|
||||||
|
);
|
||||||
|
test_env.jj_cmd_success(
|
||||||
|
&workspace_root,
|
||||||
|
&["branch", "set", "--allow-backwards", "branch2"],
|
||||||
|
);
|
||||||
|
test_env.jj_cmd_success(&workspace_root, &["branch", "create", "my-branch"]);
|
||||||
|
test_env.jj_cmd_success(&workspace_root, &["describe", "-m", "foo"]);
|
||||||
|
// Check the setup
|
||||||
|
let stdout = test_env.jj_cmd_success(&workspace_root, &["branch", "list"]);
|
||||||
|
insta::assert_snapshot!(stdout, @r###"
|
||||||
|
branch1: 5d0d85ed3da7 modified branch1 commit
|
||||||
|
@origin (ahead by 1 commits, behind by 1 commits): 545acdb23f70 description
|
||||||
|
branch2: 7840c9885676 foo
|
||||||
|
@origin (ahead by 1 commits, behind by 1 commits): 545acdb23f70 description
|
||||||
|
my-branch: 7840c9885676 foo
|
||||||
|
"###);
|
||||||
|
// First dry-run. `branch1` should not get pushed.
|
||||||
|
let stdout = test_env.jj_cmd_success(&workspace_root, &["git", "push", "--dry-run"]);
|
||||||
|
insta::assert_snapshot!(stdout, @r###"
|
||||||
|
Branch changes to push to origin:
|
||||||
|
Move branch branch2 from 545acdb23f70 to 7840c9885676
|
||||||
|
Add branch my-branch to 7840c9885676
|
||||||
|
Dry-run requested, not pushing.
|
||||||
|
"###);
|
||||||
|
let stdout = test_env.jj_cmd_success(&workspace_root, &["git", "push"]);
|
||||||
|
insta::assert_snapshot!(stdout, @r###"
|
||||||
|
Branch changes to push to origin:
|
||||||
|
Move branch branch2 from 545acdb23f70 to 7840c9885676
|
||||||
|
Add branch my-branch to 7840c9885676
|
||||||
|
"###);
|
||||||
|
let stdout = test_env.jj_cmd_success(&workspace_root, &["branch", "list"]);
|
||||||
|
insta::assert_snapshot!(stdout, @r###"
|
||||||
|
branch1: 5d0d85ed3da7 modified branch1 commit
|
||||||
|
@origin (ahead by 1 commits, behind by 1 commits): 545acdb23f70 description
|
||||||
|
branch2: 7840c9885676 foo
|
||||||
|
my-branch: 7840c9885676 foo
|
||||||
|
"###);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_git_push_no_current_branch() {
|
||||||
|
let (test_env, workspace_root) = set_up();
|
||||||
|
test_env.jj_cmd_success(&workspace_root, &["new"]);
|
||||||
|
let stderr = test_env.jj_cmd_failure(&workspace_root, &["git", "push"]);
|
||||||
|
insta::assert_snapshot!(stderr, @r###"
|
||||||
|
Error: No current branch.
|
||||||
|
"###);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_git_push_all() {
|
||||||
let (test_env, workspace_root) = set_up();
|
let (test_env, workspace_root) = set_up();
|
||||||
test_env.jj_cmd_success(&workspace_root, &["branch", "delete", "branch1"]);
|
test_env.jj_cmd_success(&workspace_root, &["branch", "delete", "branch1"]);
|
||||||
test_env.jj_cmd_success(
|
test_env.jj_cmd_success(
|
||||||
|
@ -90,7 +147,7 @@ fn test_git_push_success() {
|
||||||
my-branch: 7840c9885676 foo
|
my-branch: 7840c9885676 foo
|
||||||
"###);
|
"###);
|
||||||
// First dry-run
|
// First dry-run
|
||||||
let stdout = test_env.jj_cmd_success(&workspace_root, &["git", "push", "--dry-run"]);
|
let stdout = test_env.jj_cmd_success(&workspace_root, &["git", "push", "--all", "--dry-run"]);
|
||||||
insta::assert_snapshot!(stdout, @r###"
|
insta::assert_snapshot!(stdout, @r###"
|
||||||
Branch changes to push to origin:
|
Branch changes to push to origin:
|
||||||
Delete branch branch1 from 545acdb23f70
|
Delete branch branch1 from 545acdb23f70
|
||||||
|
@ -98,7 +155,7 @@ fn test_git_push_success() {
|
||||||
Add branch my-branch to 7840c9885676
|
Add branch my-branch to 7840c9885676
|
||||||
Dry-run requested, not pushing.
|
Dry-run requested, not pushing.
|
||||||
"###);
|
"###);
|
||||||
let stdout = test_env.jj_cmd_success(&workspace_root, &["git", "push"]);
|
let stdout = test_env.jj_cmd_success(&workspace_root, &["git", "push", "--all"]);
|
||||||
insta::assert_snapshot!(stdout, @r###"
|
insta::assert_snapshot!(stdout, @r###"
|
||||||
Branch changes to push to origin:
|
Branch changes to push to origin:
|
||||||
Delete branch branch1 from 545acdb23f70
|
Delete branch branch1 from 545acdb23f70
|
||||||
|
@ -133,7 +190,7 @@ fn test_git_push_conflict() {
|
||||||
test_env.jj_cmd_success(&workspace_root, &["rebase", "-r", "@", "-d", "@--"]);
|
test_env.jj_cmd_success(&workspace_root, &["rebase", "-r", "@", "-d", "@--"]);
|
||||||
test_env.jj_cmd_success(&workspace_root, &["branch", "set", "my-branch"]);
|
test_env.jj_cmd_success(&workspace_root, &["branch", "set", "my-branch"]);
|
||||||
test_env.jj_cmd_success(&workspace_root, &["close", "-m", "third"]);
|
test_env.jj_cmd_success(&workspace_root, &["close", "-m", "third"]);
|
||||||
let stderr = test_env.jj_cmd_failure(&workspace_root, &["git", "push"]);
|
let stderr = test_env.jj_cmd_failure(&workspace_root, &["git", "push", "--all"]);
|
||||||
insta::assert_snapshot!(stderr, @r###"
|
insta::assert_snapshot!(stderr, @r###"
|
||||||
Error: Won't push commit 50ccff1aeab0 since it has conflicts
|
Error: Won't push commit 50ccff1aeab0 since it has conflicts
|
||||||
"###);
|
"###);
|
||||||
|
|
Loading…
Reference in a new issue