init
This commit is contained in:
commit
ba8f925eed
121 files changed
+19786
No files matched your search
@@ -0,0 +1,125 @@
|
||||
# Collaboration
|
||||
|
||||
Commands for working with Git remotes, bookmarks, and pushing/pulling changes.
|
||||
|
||||
## jj git clone
|
||||
|
||||
Clone a remote Git repository into a jj-backed repo.
|
||||
|
||||
```
|
||||
jj git clone <URL> # clone and checkout default branch
|
||||
jj git clone <URL> --colocate # clone as a colocated repo (works with git commands too)
|
||||
```
|
||||
|
||||
## jj git fetch
|
||||
|
||||
Fetch changes from a remote. Unlike `git fetch`, this fetches all bookmarks by default and can automatically track new bookmarks based on config.
|
||||
|
||||
```
|
||||
jj git fetch # fetch all remotes
|
||||
jj git fetch --remote origin # fetch only origin
|
||||
jj git fetch --remote origin main # fetch specific bookmark(s)
|
||||
```
|
||||
|
||||
After fetch, new remote bookmarks appear as `BOOKMARK@remote`. They aren't automatically tracked — you must explicitly `jj bookmark track` them.
|
||||
|
||||
## jj git push
|
||||
|
||||
Push changes to a remote. By default, pushes all bookmarks that have a remote counterpart.
|
||||
|
||||
```
|
||||
jj git push # push all tracked bookmarks
|
||||
jj git push --remote origin # push to specific remote
|
||||
jj git push --bookmark main # push only specific bookmark(s)
|
||||
jj git push --deleted BOOKMARK # propagate a bookmark deletion
|
||||
jj git push --change CHANGE_ID # push a specific change by change ID
|
||||
```
|
||||
|
||||
- `--bookmark` / `-b`: specify which bookmarks to push
|
||||
- `--change`: push a single change to the remote as a draft PR (creates a bookmark on the remote)
|
||||
- `--remote`: specify the remote
|
||||
- `--deleted`: confirm you want to push a bookmark deletion to the remote
|
||||
|
||||
**Push checklist:**
|
||||
1. The revision has a description: `jj describe -m "msg"`
|
||||
2. The bookmark points at the right revision: `jj bookmark move --to=REV BOOKMARK` or use `jj bookmark set BOOKMARK` (creates or moves)
|
||||
3. The revision does not have conflicts: `jj status` will show them
|
||||
4. You're not upstream of others' work (if collaborating)
|
||||
5. Push: `jj git push`
|
||||
|
||||
## jj bookmark
|
||||
|
||||
Bookmark management. Short alias: `jj b`.
|
||||
|
||||
```
|
||||
jj bookmark list # list all bookmarks and their targets (aliases: l)
|
||||
jj bookmark create NAME # create a new bookmark at @ (aliases: c)
|
||||
jj bookmark move --to REV NAME # move bookmark NAME to point at REV (aliases: m)
|
||||
jj bookmark set NAME # create or update bookmark NAME at @ (aliases: s)
|
||||
jj bookmark track NAME --remote R # track a remote bookmark locally (aliases: t)
|
||||
jj bookmark untrack NAME # stop tracking a remote bookmark
|
||||
jj bookmark delete NAME # delete a local bookmark (aliases: d)
|
||||
jj bookmark forget NAME # forget a bookmark without pushing deletion
|
||||
jj bookmark advance NAME # advance bookmark to nearest descendant of current target
|
||||
jj bookmark rename OLD NEW # rename a bookmark
|
||||
```
|
||||
|
||||
**Bookmark workflow for pushing changes:**
|
||||
1. Work in `@` (on top of main)
|
||||
2. When ready: `jj bookmark move --to=@ main` (move the main bookmark to `@`)
|
||||
3. `jj git push` (pushes main to origin/main)
|
||||
|
||||
Or use a feature-branch workflow:
|
||||
1. `jj bookmark create my-feature` (creates bookmark at `@`)
|
||||
2. Work, describe, etc.
|
||||
3. `jj git push -b my-feature` (pushes just `my-feature`)
|
||||
|
||||
**Tracking:** When you clone a repo, remote bookmarks like `main@origin` exist but aren't automatically tracked. `jj bookmark track main --remote origin` creates a local `main` bookmark that follows `main@origin`. Without this, `jj git push` may not know which local bookmark corresponds to which remote bookmark.
|
||||
|
||||
## jj git remote
|
||||
|
||||
Manage Git remotes.
|
||||
|
||||
```
|
||||
jj git remote list # list remotes
|
||||
jj git remote add NAME URL # add a remote
|
||||
jj git remote remove NAME # remove a remote
|
||||
jj git remote set-url NAME URL # change a remote's URL
|
||||
```
|
||||
|
||||
## jj git colocation
|
||||
|
||||
Manage colocation with an underlying Git repo. Colocation means the `.jj` repo works on the same working copy as a `.git` repo, allowing both `jj` and `git` commands.
|
||||
|
||||
```
|
||||
jj git colocation init # initialize colocation
|
||||
jj git colocation deinit # remove colocation
|
||||
jj git export # manually sync jj changes to git
|
||||
jj git import # manually sync git changes to jj
|
||||
```
|
||||
|
||||
With colocation, export/import happens automatically on most commands. Use manual `jj git export` or `jj git import` if you've made changes in git that jj doesn't see yet.
|
||||
|
||||
## jj gerrit
|
||||
|
||||
Interact with Gerrit Code Review.
|
||||
|
||||
```
|
||||
jj gerrit submit CHANGE_ID # submit a change to Gerrit
|
||||
jj gerrit abandon CHANGE_ID # abandon a change in Gerrit
|
||||
```
|
||||
|
||||
## Working with stacks
|
||||
|
||||
jj excels at stacking changes. Common pattern:
|
||||
|
||||
1. `jj new main` — start from main
|
||||
2. `jj describe -m "part 1"` — describe first change
|
||||
3. `jj new` — start second change
|
||||
4. `jj describe -m "part 2"` — describe second change
|
||||
5. `jj bookmark create stack-1` — save both (bookmark on latest)
|
||||
6. `jj bookmark create stack-2` — or just push with `jj git push -b stack-1`
|
||||
|
||||
To restack after reviews:
|
||||
1. `jj rebase -b stack-1 -o main` — move whole stack
|
||||
2. `jj git push` — update remote
|
||||
@@ -0,0 +1,51 @@
|
||||
# Command quick reference
|
||||
|
||||
Every jj command with a one-line description and key flags. Read this when you need a quick overview of what commands are available.
|
||||
|
||||
| Command | Description | Key flags |
|
||||
|---|---|---|
|
||||
| `jj abandon [-r REV]` | Drop a revision from history | `-r` revision to drop (default: `@`) |
|
||||
| `jj absorb` | Auto-merge changes into their logical parent revisions | — |
|
||||
| `jj arrange` | Interactively rearrange the commit graph | — |
|
||||
| `jj bisect -r GOOD..BAD` | Binary search for a bad revision | Standard bisect: start, good, bad, skip |
|
||||
| `jj bookmark <SUB>` | Manage bookmarks | Subcommands: list, create, delete, move, set, track, untrack, forget, advance, rename |
|
||||
| `jj commit -m "msg"` | Describe `@` and create a new empty change on top | `-m`, `-i` interactive |
|
||||
| `jj config <SUB>` | Manage configuration | Subcommands: get, set, edit, list, default |
|
||||
| `jj describe -r REV -m "msg"` | Set or edit a revision's description | `-r` revision, `-m` message, `--stdin`, `--editor` |
|
||||
| `jj diff [-r REV]` | Show diff of a revision | `-r`, `--git`, `-s` summary, `--stat`, `--name-only`, `--color-words` |
|
||||
| `jj diffedit -r REV` | Edit a revision's content diff interactively | `-r`, `-i` |
|
||||
| `jj duplicate -r REV` | Copy a revision's content to a new change ID | `-r` |
|
||||
| `jj edit REV` | Switch working copy to an existing revision | — |
|
||||
| `jj evolog -r REV` | Show how a change's content evolved over time | `-r`, `-p` patch |
|
||||
| `jj file <SUB>` | File operations | Subcommands: list, show, chmod, track, untrack |
|
||||
| `jj fix [-r REV]` | Apply formatting/linting tools to files in a revision | `-r`, `-s` source revsets, `--tool`, `-i` |
|
||||
| `jj git <SUB>` | Git remote operations | Subcommands: clone, fetch, push, remote, init, export, import, colocation |
|
||||
| `jj gerrit <SUB>` | Interact with Gerrit Code Review | Subcommands: submit, abandon |
|
||||
| `jj help [CMD]` | Show help for jj or a specific command | — |
|
||||
| `jj interdiff --from A --to B` | Show differences between two revisions' diffs | `--from`, `--to` |
|
||||
| `jj log [-r REVSET]` | Show revision history graph | `-r`, `-n`, `--no-graph`, `-p`, `--reversed`, `--count`, `-T` template |
|
||||
| `jj metaedit -r REV` | Edit revision metadata (author, date, description) | `-r`, `--reset-author` |
|
||||
| `jj new [REV]...` | Create a new empty change (child of given revision) | `-m`, `--no-edit`, `--insert-after`, `--insert-before` |
|
||||
| `jj next` | Move working copy to the child revision | `-e` edit the destination |
|
||||
| `jj op <SUB>` | Operation log commands | Subcommands: log, restore, undo, discard, integrate |
|
||||
| `jj parallelize -r REVS` | Make sibling revisions into parallel branches | `-r` |
|
||||
| `jj prev` | Move working copy to the parent revision | `-e` edit the destination |
|
||||
| `jj rebase -r REV -o DEST` | Move revisions to different parent(s) | `-r`, `-s`, `-b`, `-o/\!--onto`, `--insert-after`, `--insert-before`, `--skip-emptied` |
|
||||
| `jj redo` | Redo the last undone operation | — |
|
||||
| `jj resolve PATH...` | Resolve merge conflicts | `--list` |
|
||||
| `jj restore [PATH]...` | Restore file contents (undo changes to a path or revision) | `--from`, `--into`, `--changes-in`, `-i` |
|
||||
| `jj revert [-r REV]` | Apply reverse of the given revision(s) | `-r` (same as `jj restore --changes-in REV`) |
|
||||
| `jj root` | Show workspace root directory | — |
|
||||
| `jj show [-r REV]` | Show revision description and its diff | `-r` |
|
||||
| `jj sign -r REV` | Cryptographically sign a revision | `-r` |
|
||||
| `jj simplify-parents -r REV` | Remove redundant parent edges | `-r` |
|
||||
| `jj sparse <SUB>` | Manage sparse checkout patterns | Subcommands: set, edit, list, clear, reset |
|
||||
| `jj split [-r REV]` | Split a revision into two | `-r`, `-i`, `-m`, `--parallel`, `--insert-after`, `--insert-before` |
|
||||
| `jj squash [-f FROM -t INTO]` | Move changes between revisions | `-f` from, `-t` into, `-i`, `-k` keep-emptied, `-m`, `--insert-after` |
|
||||
| `jj status` | Show working copy status (aliases: `st`) | — |
|
||||
| `jj tag <SUB>` | Manage tags | Subcommands: list, set, delete |
|
||||
| `jj undo` | Undo the last operation | `--undo` (un-undo) |
|
||||
| `jj unsign -r REV` | Drop cryptographic signature from a revision | `-r` |
|
||||
| `jj util <SUB>` | Infrequently used utilities | Subcommands: gc, completion, config-schema, etc. |
|
||||
| `jj version` | Show version information | — |
|
||||
| `jj workspace <SUB>` | Manage workspaces | Subcommands: root, list, add, forget, upgrade |
|
||||
@@ -0,0 +1,95 @@
|
||||
# Core concepts
|
||||
|
||||
Understanding these concepts is essential for using jj correctly. Read this when the user seems new to jj, or when you need to reason about jj behavior beyond simple commands.
|
||||
|
||||
## Change IDs vs commit hashes
|
||||
|
||||
Every revision in jj has two identifiers:
|
||||
|
||||
- **Change ID** — A stable identifier (e.g., `abc12345`) that follows the revision across rebases, squashes, and splits. Use this when referring to a logical change over time.
|
||||
- **Commit hash** — A hash of the commit content (like Git). Changes every time the diff changes. Use this when you need to reference exact content.
|
||||
|
||||
Commands that take revisions (almost all of them) accept change IDs, commit hashes, or revset expressions. Prefer change IDs for user-facing references since they're stable.
|
||||
|
||||
## The working copy (`@`)
|
||||
|
||||
The `@` symbol represents the working copy revision. Unlike Git's detached HEAD or branch-based model:
|
||||
|
||||
- `@` is always a regular commit. It can have a description, parent(s), and children.
|
||||
- When you edit files, those changes belong to `@`.
|
||||
- `jj new` creates a new *empty* commit on top of `@` and makes that the new `@`. The old `@` becomes `@-` (parent of working copy).
|
||||
- `jj edit REV` sets the working copy to revision REV. Edits go directly into that revision's diff. Use `jj new` instead unless you specifically need to amend an existing change.
|
||||
- `jj status` shows the diff between `@` and its parent (`@-`).
|
||||
|
||||
## Operation log
|
||||
|
||||
Every jj command creates an **operation** in the operation log. This is jj's safety net:
|
||||
|
||||
- `jj op log` shows the history of commands (like shell history but richer)
|
||||
- `jj undo` creates a new operation that reverses the last one
|
||||
- `jj op restore OP_ID` restores the repo to the state after a given operation
|
||||
- `jj --at-op OP_ID <command>` runs a command as if the repo were at that operation (read-only inspection)
|
||||
|
||||
Nothing is permanently lost unless you run `jj util gc` (garbage collection). The operation log is append-only.
|
||||
|
||||
## Revsets
|
||||
|
||||
Revsets are jj's query language for selecting revisions. They appear everywhere a command accepts revisions. Key patterns:
|
||||
|
||||
| Expression | Meaning |
|
||||
|---|---|
|
||||
| `@` | The working copy revision |
|
||||
| `main` | The revision pointed to by bookmark `main` |
|
||||
| `main@origin` | The revision pointed to by `main` on the `origin` remote |
|
||||
| `root()` | The root revision (virtual, all repos share it) |
|
||||
| `all()` | Every revision in the repo |
|
||||
| `mine()` | Revisions authored by the current user |
|
||||
| `none()` | Empty set |
|
||||
| `parents(REVSET)` | Parents of revisions in the set |
|
||||
| `children(REVSET)` | Children of revisions in the set |
|
||||
| `ancestors(REVSET)` | All ancestors (recursive parents) |
|
||||
| `descendants(REVSET)` | All descendants (recursive children) |
|
||||
| `::` | DAG range — `A::B` means "A and B and everything between them" |
|
||||
| `..` | Reachable from B but not from A — `A..B` means "B and ancestors of B not also ancestors of jj" |
|
||||
| `X \ Y` | Set difference |
|
||||
| `X + Y` | Set union |
|
||||
| `X & Y` | Set intersection |
|
||||
| `empty()` | Revisions with no diff from their parent |
|
||||
| `description(REGEX)` | Revisions whose description matches REGEX |
|
||||
| `author("NAME")` | Revisions authored by NAME (partial match) |
|
||||
| `bookmarks()` | Revisions that have bookmarks |
|
||||
| `immutable_heads()` | The configured immutable set |
|
||||
| `latest(N, REVSET)` | The latest N revisions in the set |
|
||||
| `merged()` | Merge commits |
|
||||
|
||||
**Practical examples:**
|
||||
- `main..@` — revisions in `@`'s ancestors that aren't in main (what you changed since main)
|
||||
- `ancestors(@) & ~immutable_heads()` — everything you can safely rewrite
|
||||
- `@-` — the parent of the working copy (one commit back)
|
||||
- `@--` — grandparent of the working copy
|
||||
- `description("fix.*")` — revisions with descriptions starting with "fix"
|
||||
- `empty() & ~@` — revisions that are empty but not the working copy (candidates for abandonment)
|
||||
|
||||
## Bookmarks
|
||||
|
||||
Bookmarks are labels attached to revisions. They serve the same conceptual role as Git branches but behave differently:
|
||||
|
||||
- Bookmarks can coexist at the same revision (no conflict)
|
||||
- Moving a bookmark doesn't affect the revision it points to — the revision keeps its change ID
|
||||
- Tracking a remote bookmark (`jj bookmark track NAME --remote origin`) creates a local bookmark that follows the remote's updates
|
||||
- Git branches are represented as bookmarks with `@remote` suffixes (e.g., `main@origin`)
|
||||
- `jj bookmark list` shows all bookmarks; the output format is `BOOKMARK: CHANGE_ID commit_hash`
|
||||
|
||||
## The immutable set
|
||||
|
||||
By default, jj prevents rewriting commits that are ancestors of any remote-tracking bookmark. This is configured by `revsets.immutable_heads` in the config (typically `immutable_heads() & ~@` plus `bookmarks()@remote`). Use `--ignore-immutable` to bypass this check (e.g., `jj rebase --ignore-immutable -r OLD_REV`).
|
||||
|
||||
## Global flags
|
||||
|
||||
These work with any jj command:
|
||||
|
||||
- `--at-op OP` — run as if repo were at a past operation (read-only)
|
||||
- `--ignore-immutable` — allow rewriting protected commits
|
||||
- `--ignore-working-copy` — skip snapshotting the working copy (faster, but may show stale state)
|
||||
- `-R PATH` — operate on a different repository
|
||||
- `--config NAME=VAL` — set config options inline (TOML syntax)
|
||||
@@ -0,0 +1,117 @@
|
||||
# Daily work
|
||||
|
||||
Commands and patterns for the core edit/describe/log cycle.
|
||||
|
||||
## jj status
|
||||
|
||||
Shows the diff between the working copy (`@`) and its parent. This is the first thing to run when a user asks "what's going on?" or "what have I changed?".
|
||||
|
||||
Key alias: `jj st` (the most common form used in practice).
|
||||
|
||||
Output shows:
|
||||
- Which revision you're on (change ID, commit hash, bookmark)
|
||||
- Whether `@` is empty or has changes
|
||||
- The diff (added/modified/deleted files)
|
||||
- Any conflicts
|
||||
|
||||
## jj new
|
||||
|
||||
Creates a new empty revision as a child of the given revision (default: `@`) and makes it the working copy. This is the closest jj equivalent to starting a new branch of work.
|
||||
|
||||
```
|
||||
jj new # new child of @, empty, becomes new @
|
||||
jj new REV # new child of REV
|
||||
jj new A B # new merge revision with parents A and B
|
||||
```
|
||||
|
||||
- `--insert-after REV` — insert the new revision after REV (between REV and its children)
|
||||
- `--insert-before REV` — insert before REV (between REV and its parents)
|
||||
- `-m "msg"` — set description immediately
|
||||
- `--no-edit` — create the revision but don't switch working copy to it
|
||||
|
||||
## jj describe
|
||||
|
||||
Sets or edits the description (commit message) of a revision.
|
||||
|
||||
```
|
||||
jj describe # opens editor to edit @'s description
|
||||
jj describe -m "msg" # set description of @ inline
|
||||
jj describe -r REV # describe a specific revision
|
||||
```
|
||||
|
||||
- `-m "msg"` — set description from command line (no editor)
|
||||
- `--stdin` — read description from stdin
|
||||
- `-r REV` — describe a different revision (default: `@`)
|
||||
|
||||
**Important:** A revision needs a description before it can be pushed. Always use `jj describe` (not `jj commit`) when the user says "write a commit message."
|
||||
|
||||
## jj commit
|
||||
|
||||
Combines `jj describe -m "msg"` followed by `jj new`. Records the current change's description and immediately starts a fresh empty revision on top.
|
||||
|
||||
```
|
||||
jj commit -m "feat: add user auth"
|
||||
```
|
||||
|
||||
This is the jj equivalent of git's `commit` but note: there's no staging step. Any changes to tracked files are included.
|
||||
|
||||
## jj log
|
||||
|
||||
Shows the revision graph. This is your primary tool for understanding history.
|
||||
|
||||
```
|
||||
jj log # default view (configurable via revsets.log)
|
||||
jj log -r "main..@" # changes you've made since main
|
||||
jj log -r "author(me)" # your changes
|
||||
jj log -r "all()" # everything
|
||||
jj log -r REV # log starting from REV
|
||||
```
|
||||
|
||||
Key flags:
|
||||
- `-r REVSET` — which revisions to show (revset)
|
||||
- `-n N` / `--limit N` — limit to N results
|
||||
- `--no-graph` — flat list (good for scripting)
|
||||
- `--reversed` — oldest first
|
||||
- `-p` / `--patch` — show the diff for each revision
|
||||
- `-T TEMPLATE` — custom template
|
||||
- `--count` — just print the count
|
||||
|
||||
## jj diff
|
||||
|
||||
Shows the diff of a revision. Unlike `jj log -p`, this focuses purely on the content diff.
|
||||
|
||||
```
|
||||
jj diff # diff of @ vs its parent
|
||||
jj diff -r REV # diff of REV vs its parent
|
||||
jj diff --from A --to B # diff between two specific revisions
|
||||
```
|
||||
|
||||
Key flags:
|
||||
- `--git` — git-format diff (good for piping or review)
|
||||
- `-s` / `--summary` — just show which files changed
|
||||
- `--stat` — histogram of changes
|
||||
- `--name-only` — just file paths
|
||||
- `--color-words` — word-level diff
|
||||
- `--context N` — lines of context
|
||||
|
||||
## jj edit
|
||||
|
||||
Sets the working copy to an existing revision. Edits go directly into that revision's diff — this rewrites history.
|
||||
|
||||
```
|
||||
jj edit REV # switch working copy to REV
|
||||
```
|
||||
|
||||
Prefer `jj new REV` over `jj edit REV` in most cases: `jj new` creates a child so you can't accidentally rewrite the parent. Use `jj edit` when you intentionally want to amend an existing change (e.g., you forgot to include a file).
|
||||
|
||||
## jj file
|
||||
|
||||
File-level operations.
|
||||
|
||||
```
|
||||
jj file list [-r REV] # list tracked files in REV
|
||||
jj file show -r REV PATH # show file contents from REV
|
||||
jj file chmod MODE PATH # change file mode (e.g., +x, -x)
|
||||
jj file untrack PATH # stop tracking a file (adds to .gitignore automatically)
|
||||
jj file track PATH # start tracking a file (reverses untrack)
|
||||
```
|
||||
@@ -0,0 +1,130 @@
|
||||
# History rewriting
|
||||
|
||||
Commands for restructuring the commit graph. jj's operation log makes history rewriting safe — nothing is permanently lost.
|
||||
|
||||
## jj rebase
|
||||
|
||||
Move revisions to different parent(s). The most fundamental history-rewriting command.
|
||||
|
||||
```
|
||||
jj rebase -r REV -o DEST # rebase single revision REV onto DEST
|
||||
jj rebase -b REV -o DEST # rebase REV and all its descendants onto DEST
|
||||
jj rebase -r REV --insert-after ANCHOR # reorder: put REV after ANCHOR
|
||||
jj rebase -r REV --insert-before ANCHOR # reorder: put REV before ANCHOR
|
||||
```
|
||||
|
||||
Moving `-r` vs `-b`:
|
||||
- `-r REV` — rebase only REV; its descendants follow because jj automatically rebases them on top
|
||||
- `-b REV` — rebase the entire branch (REV and all its descendants) to a new location. Equivalent to `-s roots(dest..REV)`
|
||||
|
||||
Note: jj automatically rebases descendants so you don't need to manually restack after a rebase. However, this can create duplicate commits if the destination already has commits with the same change IDs. `--keep-divergent` controls this behavior.
|
||||
|
||||
## jj squash
|
||||
|
||||
Move changes from one revision into another. The most common pattern is moving `@`'s changes into its parent (the jj equivalent of amending).
|
||||
|
||||
```
|
||||
jj squash # squash @ into its parent
|
||||
jj squash -f SOURCE -t DEST # move SOURCE's changes into DEST
|
||||
```
|
||||
|
||||
- Without flags: squash `@` into `@-` (the parent). After this, `@` becomes empty and `@-` now includes the changes.
|
||||
- `-f` / `--from`: which revision to take changes from (default: `@`)
|
||||
- `-t` / `--into`: which revision to put changes into (default: `@`)
|
||||
- `-i` / `--interactive`: choose which parts of the diff to squash
|
||||
- `-k` / `--keep-emptied`: don't abandon the source revision after squashing
|
||||
- `-m "msg"`: set description on the result
|
||||
|
||||
The `-o` (experimental), `--insert-after`, and `--insert-before` flags control where the resulting revision goes in the graph, similar to `jj rebase`.
|
||||
|
||||
## jj split
|
||||
|
||||
Split one revision into two. Changes in the original revision are partitioned into two new revisions.
|
||||
|
||||
```
|
||||
jj split -r REV # interactively choose which files go into the first split
|
||||
jj split FILE... # put specified files into the new first revision
|
||||
```
|
||||
|
||||
- `-r REV`: the revision to split (default: `@`)
|
||||
- `-i`: force interactive mode (choose which hunks go where)
|
||||
- `-m "msg"`: description for the new (first) revision
|
||||
- `--parallel`: split into two parallel revisions (same parent) instead of parent-child
|
||||
- `--insert-after` / `--insert-before` / `-o`: control where the new revision goes
|
||||
|
||||
## jj abandon
|
||||
|
||||
Drop a revision. The revision is removed from the graph and its descendants are rebased onto its parent(s).
|
||||
|
||||
```
|
||||
jj abandon -r REV # abandon a specific revision
|
||||
jj abandon # abandon @ (only works if @ is empty)
|
||||
```
|
||||
|
||||
Common use: clean up empty revisions after squash/restructuring. `jj abandon -r empty()` is a batch cleanup pattern.
|
||||
|
||||
## jj absorb
|
||||
|
||||
Automatically moves changes from child revisions into the parent revisions they logically belong to. It detects which changes should have been made in which parent by analyzing the diff.
|
||||
|
||||
```
|
||||
jj absorb
|
||||
```
|
||||
|
||||
Runs on `@` by default. Useful when you make a fix that should belong to a lower commit in your stack — instead of manually squashing, `jj absorb` figures out where each hunk belongs.
|
||||
|
||||
## jj parallelize
|
||||
|
||||
Make sibling revisions into a linear chain or vice versa.
|
||||
|
||||
```
|
||||
jj parallelize -r REVS...
|
||||
```
|
||||
|
||||
Takes a set of revisions and makes them siblings (all children of the same parent), rebasing their descendants as needed.
|
||||
|
||||
## jj arrange
|
||||
|
||||
Interactive graph rearrangement. Opens a diff editor where you can drag and drop revisions to reorder them. More visual than command-line rebase operations.
|
||||
|
||||
```
|
||||
jj arrange
|
||||
```
|
||||
|
||||
## jj diffedit
|
||||
|
||||
Touch up the content changes in a revision. Opens an editor showing the revision's diff and lets you modify it directly.
|
||||
|
||||
```
|
||||
jj diffedit -r REV
|
||||
```
|
||||
|
||||
Use this when you need to change what a specific revision does, rather than adding a fix on top.
|
||||
|
||||
## jj metaedit
|
||||
|
||||
Modify a revision's metadata (author, author date, committer, description) without changing its content.
|
||||
|
||||
```
|
||||
jj metaedit -r REV
|
||||
```
|
||||
|
||||
## jj restack
|
||||
|
||||
This is not a real command — jj restacks automatically. You should never need to manually restack after rebase, squash, etc. If a rebase leaves empty commits, `jj abandon` them.
|
||||
|
||||
## jj squash/absorb vs jj squash
|
||||
|
||||
- Use `jj squash` when you want to explicitly move changes between revisions
|
||||
- Use `jj absorb` when you want jj to figure out where changes belong automatically
|
||||
|
||||
## jj squash vs git commit --amend
|
||||
|
||||
- `jj squash` without arguments is jj's equivalent of `git commit --amend`: it takes `@`'s changes and merges them into `@-`, leaving `@` empty
|
||||
- Unlike git, the old `@`'s change ID still exists (as an empty revision) — you can `jj abandon` it afterwards
|
||||
|
||||
## jj split + jj rebase
|
||||
|
||||
A common pattern: split a large revision into two, then rebase one of them to a different parent:
|
||||
1. `jj split -r BIG_COMMIT` — split into two
|
||||
2. `jj rebase -r NEW_REV -o DIFFERENT_PARENT` — move the new revision elsewhere
|
||||
@@ -0,0 +1,119 @@
|
||||
# Recovery
|
||||
|
||||
Commands for undoing mistakes, resolving conflicts, and restoring lost work.
|
||||
|
||||
## jj undo
|
||||
|
||||
Undoes the most recent operation. This is the first recovery command to reach for.
|
||||
|
||||
```
|
||||
jj undo # undo last operation
|
||||
jj undo --undo # undo the undo (same as jj redo)
|
||||
```
|
||||
|
||||
Any operation can be undone — commit, rebase, push, etc. The undo itself creates a new operation, so it can also be undone.
|
||||
|
||||
## jj redo
|
||||
|
||||
Redo the most recently undone operation.
|
||||
|
||||
```
|
||||
jj redo # redo last undo
|
||||
```
|
||||
|
||||
## jj op log / jj operation
|
||||
|
||||
View the operation log — the history of all jj commands run in this repo. This is jj's equivalent of shell history but tied to repo state.
|
||||
|
||||
```
|
||||
jj op log # show all operations
|
||||
jj op log -n 20 # show last 20 operations
|
||||
```
|
||||
|
||||
Each operation has an ID (hash). The most recent operation is shown at the top with `@`. The snapshot of the working copy is also an operation.
|
||||
|
||||
## jj op restore
|
||||
|
||||
Restore the repo to a previous state by operation. Unlike `jj undo` (which only undoes the last operation), this can jump to any point in the operation log.
|
||||
|
||||
```
|
||||
jj op restore OP_ID # restore repo to state after OP_ID
|
||||
jj op restore --what undo # restore just the undo history (not working copy)
|
||||
```
|
||||
|
||||
This is *not* a revert — it moves the entire repo state backward (or forward). Changes made after that operation will appear as divergent changes. Use `jj --at-op` for read-only inspection first.
|
||||
|
||||
## jj restore (content restore)
|
||||
|
||||
Restore file contents within a revision. This is NOT the same as `jj op restore`.
|
||||
|
||||
```
|
||||
jj restore # restore all files in @ from its parent
|
||||
jj restore PATH # restore specific files in @ from its parent
|
||||
jj restore --from SOURCE # restore from a specific source revision
|
||||
jj restore --changes-in REV # undo the changes introduced by REV (creates reverse diff on @)
|
||||
```
|
||||
|
||||
- Without `--from`: restores from the parent of the target revision
|
||||
- Without `--into`: restores into `@`
|
||||
- `--changes-in REV` is the closest equivalent to `git revert REV` — it applies the reverse of REV's diff to `@`
|
||||
- `--restore-descendants`: when rebasing descendants, preserve their content (not their diff)
|
||||
|
||||
To "unstage" files (there's no real staging area in jj, but for git users who ask): use `jj restore PATH` to undo changes to specific files in `@`.
|
||||
|
||||
## jj resolve
|
||||
|
||||
Resolve merge conflicts. jj tracks conflicts natively (unlike git, which leaves conflict markers in files and lets you handle them).
|
||||
|
||||
```
|
||||
jj resolve PATH... # resolve conflicts in specific files
|
||||
jj resolve --list # list all unresolved conflicts
|
||||
```
|
||||
|
||||
When you run `jj resolve`, jj opens the external merge tool (configured in `merge-tools`). If no tool is configured, it falls back to leaving conflict markers in the file, which you can edit manually.
|
||||
|
||||
After resolving conflicts manually (by editing the file), mark them as resolved with `jj resolve PATH`.
|
||||
|
||||
## jj --at-op (read-only inspection)
|
||||
|
||||
Run any jj command as if the repo were at a past operation. Read-only — useful for inspecting old state before deciding whether to restore.
|
||||
|
||||
```
|
||||
jj --at-op OP_ID log # log from past state
|
||||
jj --at-op OP_ID status # status from past state
|
||||
jj --at-op OP_ID diff -r REV # diff from past state
|
||||
```
|
||||
|
||||
## Divergent changes
|
||||
|
||||
When the operation log has diverged (e.g., two concurrent operations), `jj status` will warn about divergent operations. This happens when you run jj commands from different terminals or after `jj op restore`.
|
||||
|
||||
To resolve divergence:
|
||||
1. `jj --at-op OP_ID status` for each divergent operation to understand the state
|
||||
2. `jj op restore` to pick one side
|
||||
3. Or use `jj new` to create a merge of the divergent states
|
||||
|
||||
## Common recovery scenarios
|
||||
|
||||
**"I rebased and lost changes"**
|
||||
- `jj undo` — undoes the rebase
|
||||
- If `jj undo` isn't enough: `jj op log` to find the pre-rebase operation, then `jj op restore OP_ID`
|
||||
|
||||
**"I pushed the wrong thing"**
|
||||
- You can't unpush (remote doesn't support it), but you can:
|
||||
1. Fix the local revision
|
||||
2. `jj bookmark move --to=FIXED BOOKMARK`
|
||||
3. `jj git push --force` or `jj git push` with a new commit
|
||||
|
||||
**"I accidentally squashed the wrong files"**
|
||||
- `jj undo` immediately
|
||||
- If too late: use the operation log to find the pre-squash state
|
||||
|
||||
**"I want to get old version of a file back"**
|
||||
- `jj restore --from OLD_REV PATH` — restore PATH from OLD_REV into `@`
|
||||
- Or: `jj file show -r OLD_REV PATH > PATH` to extract it as a file
|
||||
|
||||
**"jj status shows conflicts"**
|
||||
- `jj resolve --list` to see which files have conflicts
|
||||
- Resolve them individually: `jj resolve PATH`
|
||||
- After resolving all, `jj status` will clear
|
||||
Reference in new issue
Block a user