From baaeff045c6e726d8ad2d4bf5a7cb489a716ae4a Mon Sep 17 00:00:00 2001 From: Ilya Grigoriev Date: Mon, 8 Apr 2024 14:18:58 -0700 Subject: [PATCH] `jj git push` docs: document safety checks As discussed in https://discord.com/channels/968932220549103686/1226363798483636265/1226415448615288864 --- cli/src/commands/git.rs | 24 ++++++++++++++++++++++++ cli/tests/cli-reference@.md.snap | 12 ++++++++++++ 2 files changed, 36 insertions(+) diff --git a/cli/src/commands/git.rs b/cli/src/commands/git.rs index 3628df2de4..1178897bd7 100644 --- a/cli/src/commands/git.rs +++ b/cli/src/commands/git.rs @@ -189,6 +189,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 c3a50add63..e6e877acb9 100644 --- a/cli/tests/cli-reference@.md.snap +++ b/cli/tests/cli-reference@.md.snap @@ -909,6 +909,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:**