131 lines
5.0 KiB
Markdown
131 lines
5.0 KiB
Markdown
# 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
|