diff --git a/cli/src/commands/git.rs b/cli/src/commands/git.rs index 36601f7e98..b16ff37be3 100644 --- a/cli/src/commands/git.rs +++ b/cli/src/commands/git.rs @@ -188,6 +188,30 @@ pub struct GitCloneArgs { /// `remote_branches(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 `. 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]. +/// If it does not already exist on the remote, `jj git push` will create the +/// branch and mark it as 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 c74cbbfa50..10831b3977 100644 --- a/cli/tests/cli-reference@.md.snap +++ b/cli/tests/cli-reference@.md.snap @@ -914,6 +914,18 @@ Push to a Git remote By default, pushes any branches pointing to `remote_branches(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 `. 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]. If it does not already exist on the remote, `jj git push` will create the branch and mark it as 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:**