Skip to content

Commit

Permalink
jj git push docs: document safety checks
Browse files Browse the repository at this point in the history
  • Loading branch information
ilyagr committed Jun 1, 2024
1 parent 3090adf commit 4ab7d50
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 0 deletions.
10 changes: 10 additions & 0 deletions cli/src/commands/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,16 @@ 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]. If there is a problem, you may need to run `jj git
/// fetch --remote <remote name>` and/or resolve some [branch conflicts].
///
/// [safety checks]:
/// https://martinvonz.github.io/jj/latest/branches/#pushing-branches-safety-checks
/// [branch conflicts]:
/// https://martinvonz.github.io/jj/latest/branches/#conflicts
#[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")))]
Expand Down
4 changes: 4 additions & 0 deletions cli/tests/[email protected]
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,10 @@ 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]. If there is a problem, you may need to run `jj git fetch --remote <remote name>` and/or resolve some [branch conflicts].
[safety checks]: https://martinvonz.github.io/jj/latest/branches/#pushing-branches-safety-checks [branch conflicts]: https://martinvonz.github.io/jj/latest/branches/#conflicts
**Usage:** `jj git push [OPTIONS]`
###### **Options:**
Expand Down
36 changes: 36 additions & 0 deletions docs/branches.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,42 @@ met:
You could describe the movement as following along the change-id of the
current branch commit, even if it isn't entirely accurate.

## Pushing branches: Safety checks
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 there is a
conflict, `jj` will refuse to push the branch. In this case, you need to run
`jj git fetch --remote <remote name>` and resolve the resulting branch
conflict. Then, you can try `jj git push` again.

If you are familiar with Git, this makes `jj git push` similar to `git
push --force-with-lease`.

There are a few cases where `jj git push` will succeed even though the remote
branch is in an unexpected location. These are the cases where `jj git fetch`
would not create a branch conflict and would not move the local branch, e.g.
if the unexpected location is identical to the local position of the branch.

2. The local branch must not be [conflicted](#conflicts). If it is, you would
need to use `jj branch set`, for example, to resolve the conflict.

This makes `jj git push` safe even if `jj git fetch` is performed on a timer
in the background (this situation is a known issue[^known-issue] with some
forms of `git push --force-with-lease`). If the branch moves on a remote in a
problematic way, `jj git fetch` will create a conflict. This should ensure
that the user becomes aware of the conflict before they can `jj git push` and
override the branch on the remote.

3. If the remote branch already exists on the remote, it must be
[tracked](#remotes-and-tracked-branches). If it does not already exist on the
remote, `jj git push` will create the branch and mark it as tracked.

[^known-issue]: See "a general note on safety" in
<https://git-scm.com/docs/git-push#Documentation/git-push.txt---no-force-with-lease>


## Conflicts

Branches can end up in a conflicted state. When that happens, `jj status` will
Expand Down

0 comments on commit 4ab7d50

Please sign in to comment.