diff --git a/cli/src/commands/git.rs b/cli/src/commands/git.rs index 9122399631..f014617df4 100644 --- a/cli/src/commands/git.rs +++ b/cli/src/commands/git.rs @@ -189,6 +189,28 @@ pub struct GitCloneArgs { /// `remote_branches(remote=<remote>)..@`. Use `--branch` to push specific /// branches. Use `--all` to push all branches. Use `--change` to generate /// branch names based on the change IDs of specific commits. +/// +/// Before the command actually moves or creates a remote branch, it makes +/// several safety checks. +/// +/// 1. `jj` will contact the remote and check that the actual state of the +/// remote branch matches `jj`'s record of its last known position. If they +/// do not match, `jj` will refuse to push the branch. In this case, you need +/// to `jj git fetch --remote <remote name>`. This may create some branch +/// conflicts, which you'll need to resolve before trying `jj git push` +/// again. +/// +/// If you are familiar with Git, this makes `jj git push` similar to `git +/// push --force-with-lease`. +/// +/// 2. The local branch must not be [conflicted]. If it is, you would need to +/// use `jj branch set`, for example, to resolve the conflict. +/// +/// 3. If the remote branch already exists on the remote, it must be [tracked]. +/// +/// [conflicted]: https://martinvonz.github.io/jj/latest/branches/#conflicts +/// [tracked]: https://martinvonz.github.io/jj/latest/branches/#remotes-and-tracked-branches + #[derive(clap::Args, Clone, Debug)] #[command(group(ArgGroup::new("specific").args(&["branch", "change", "revisions"]).multiple(true)))] #[command(group(ArgGroup::new("what").args(&["all", "deleted", "tracked"]).conflicts_with("specific")))] diff --git a/cli/tests/cli-reference@.md.snap b/cli/tests/cli-reference@.md.snap index 6b0a01137a..ce45fa8994 100644 --- a/cli/tests/cli-reference@.md.snap +++ b/cli/tests/cli-reference@.md.snap @@ -905,6 +905,18 @@ Push to a Git remote By default, pushes any branches pointing to `remote_branches(remote=<remote>)..@`. Use `--branch` to push specific branches. Use `--all` to push all branches. Use `--change` to generate branch names based on the change IDs of specific commits. +Before the command actually moves or creates a remote branch, it makes several safety checks. + +1. `jj` will contact the remote and check that the actual state of the remote branch matches `jj`'s record of its last known position. If they do not match, `jj` will refuse to push the branch. In this case, you need to `jj git fetch --remote <remote name>`. This may create some branch conflicts, which you'll need to resolve before trying `jj git push` again. + +If you are familiar with Git, this makes `jj git push` similar to `git push --force-with-lease`. + +2. The local branch must not be [conflicted]. If it is, you would need to use `jj branch set`, for example, to resolve the conflict. + +3. If the remote branch already exists on the remote, it must be [tracked]. + +[conflicted]: https://martinvonz.github.io/jj/latest/branches/#conflicts [tracked]: https://martinvonz.github.io/jj/latest/branches/#remotes-and-tracked-branches + **Usage:** `jj git push [OPTIONS]` ###### **Options:**