6.9 KiB
6.9 KiB
Git to jj Command Comparison
This reference maps common Git commands and workflows to their jj equivalents.
Quick Reference Table
| Git Command | jj Equivalent | Notes |
|---|---|---|
git init |
jj git init |
Creates colocated repo by default |
git clone |
jj git clone |
Creates colocated repo by default |
git status |
jj status |
Alias: jj st |
git log |
jj log |
Shows graph by default |
git log --oneline |
jj log --no-graph |
Or customize template |
git show |
jj show |
|
git diff |
jj diff |
|
git diff --staged |
N/A | No staging area in jj |
git add |
N/A | Auto-tracked |
git add -p |
jj split -i |
Interactive commit splitting |
git commit |
jj commit or jj new |
Different workflow |
git commit --amend |
jj describe + changes |
Working copy is always amendable |
git commit --amend -m |
jj describe -m "msg" |
|
git reset HEAD~ |
jj squash |
Move changes to parent |
git reset --hard |
jj restore |
|
git checkout <file> |
jj restore <file> |
|
git checkout <branch> |
jj new <bookmark> |
Creates new working copy |
git switch |
jj new |
|
git branch |
jj bookmark |
Alias: jj b |
git branch -d |
jj bookmark delete |
|
git merge |
jj new <A> <B> |
Creates merge commit |
git rebase |
jj rebase |
More powerful |
git rebase -i |
jj squash -i, jj split |
Different approach |
git cherry-pick |
jj new <rev>; jj squash |
Or jj duplicate |
git revert |
jj revert |
|
git stash |
N/A | Not needed - use jj new |
git stash pop |
N/A | Use jj squash |
git fetch |
jj git fetch |
|
git pull |
jj git fetch + jj rebase |
No single command |
git push |
jj git push |
|
git blame |
jj file annotate |
|
git reflog |
jj op log |
More powerful |
git tag |
jj tag |
Workflow Comparisons
Creating a New Commit
Git:
git add .
git commit -m "message"
jj:
# Changes are auto-tracked
jj describe -m "message"
jj new # Start new work
# Or:
jj commit -m "message" # Same effect
Amending the Last Commit
Git:
git add .
git commit --amend
jj:
# Changes automatically amend current working copy
# Just edit files, done!
# To change message:
jj describe -m "new message"
Interactive Staging
Git:
git add -p
git commit
jj:
# Split current changes into separate commits
jj split -i
# Or squash parts into parent
jj squash -i
Undoing Last Commit (Keep Changes)
Git:
git reset HEAD~
jj:
jj squash # Moves changes to parent, abandons if empty
Discarding Changes
Git:
git checkout -- .
git reset --hard
jj:
jj restore # Restore from parent
Switching Branches
Git:
git checkout feature
# or
git switch feature
jj:
jj new feature # Create working copy on feature
# Or to edit feature directly:
jj edit feature
Creating a Branch
Git:
git checkout -b feature
# or
git switch -c feature
jj:
jj bookmark create feature
# Then work - changes go to working copy
Stashing Changes
Git:
git stash
# ... do other work ...
git stash pop
jj:
# Not needed! Working copy is already a commit.
# To work on something else:
jj new main # Start new work from main
# ... do other work ...
jj edit <original-change-id> # Go back
Rebasing a Branch
Git:
git checkout feature
git rebase main
jj:
jj rebase -b feature -d main
# Or if on feature:
jj rebase -d main
Interactive Rebase
Git:
git rebase -i HEAD~5
jj:
# Different approach - use individual commands:
jj squash # Combine commits
jj split # Split commits
jj rebase # Reorder
jj describe # Edit messages
jj abandon # Drop commits
Cherry-picking
Git:
git cherry-pick <commit>
jj:
jj new <commit> # Create child of commit
jj rebase -r @ -d main # Move to destination
# Or simpler:
jj duplicate <commit>
jj rebase -r <duplicated> -d main
Resolving Conflicts
Git:
git merge feature
# Conflicts occur
# Edit files
git add .
git commit
jj:
jj new main feature # Create merge (may have conflicts)
# Conflicts are recorded in commit
jj log # Shows conflict marker
# Edit files
# Changes auto-commit, conflict resolved
Undoing Operations
Git:
git reflog
git reset --hard HEAD@{2}
jj:
jj op log
jj op restore <op-id>
# Or simply:
jj undo
Viewing History at a Point
Git:
git log HEAD@{yesterday}
jj:
jj --at-op=<op-id> log
Conceptual Differences
No Staging Area
Git has a staging area (index) between working directory and commits. jj doesn't:
- Git: working directory → staging area → commit
- jj: working copy (IS a commit) → new commit
Working Copy is a Commit
In jj, the working copy is always a commit. Changes are automatically recorded:
- No "dirty" working directory
- No lost changes from checkout
- Can always undo
Change IDs vs Commit IDs
- Git: Only commit hashes (SHA), change when commit is amended
- jj: Change IDs (stable) + Commit IDs (change on rewrite)
Use change IDs (kntqzsqt) when referring to commits.
Conflicts as First-Class Citizens
- Git: Conflicts block operations, must resolve immediately
- jj: Conflicts are recorded in commits, resolve when convenient
Operations are Atomic
Every jj operation is recorded and reversible:
jj op log # See all operations
jj undo # Undo last operation
jj op restore # Go to any point
Bookmarks vs Branches
- Git branches: Automatically move with commits
- jj bookmarks: Named pointers, move explicitly
# Git: branch moves with HEAD
git commit # branch advances
# jj: bookmark stays unless moved
jj new # bookmark doesn't move
jj bookmark set <name> # explicit move
Common Patterns
"Pull and Rebase"
Git:
git pull --rebase
jj:
jj git fetch
jj rebase -d <remote>@origin # or main@origin
"Push New Branch"
Git:
git push -u origin feature
jj:
jj git push --bookmark feature
# Or create bookmark from change:
jj git push --change <change-id>
"Squash Last N Commits"
Git:
git rebase -i HEAD~3
# Mark commits as squash
jj:
# Squash into parent repeatedly:
jj squash -r <commit>
jj squash -r <commit>
# Or use revsets:
jj squash --from 'trunk()..@'
"Edit Old Commit"
Git:
git rebase -i <commit>^
# Mark commit as edit
# Make changes
git commit --amend
git rebase --continue
jj:
jj edit <commit>
# Make changes (auto-committed)
jj new # Continue with new work
# Descendants auto-rebased!