jj/docs/git-comparison.md

8.9 KiB

Comparison with Git

TODO: Describe the differences compared to Git here

The index

Git's "index" has multiple roles. One role is as a cache of file system information. Jujutsu has something similar. Unfortunately, Git exposes the index to the user, which makes the CLI unnecessarily complicated (learning what the different flavors of git reset do, especially when combined with commits and/or paths, usually takes a while). Jujutsu, like Mercurial, doesn't make that mistake.

As a Git power-user, you may think that you need the power of the index to commit only part of the working copy. However, Jujutsu provides commands for more directly achieving most use cases you're used to using Git's index for. For example, to create a commit from part of the changes in the working copy, you might be used to using git add -p; git commit. With Jujutsu, you'd instead use jj split to split the working copy commit into two commits. To add more changes into the parent commit, which you might normally use git add -p; git commit --amend for, you can instead use jj squash -i to choose which changes to move into the parent commit.

Command equivalence table

Note that all jj commands can be run on any commit (not just the working copy commit), but that's left out of the table to keep it simple. For example, jj squash/amend -r <revision> will move the diff from that revision into its parent.

Use case Jujutsu command Git command
Create a new repo jj init --git (without --git, you get a native Jujutsu repo, which is slow and whose format will change) git init
Clone an existing repo jj git clone <source> <destination> (there is no support for cloning non-Git repos yet) git clone <source> <destination>
Update the local repo with all branches from a remote jj git fetch [--remote <remote>] (there is no support for fetching into non-Git repos yet) git fetch [<remote>]
Update a remote repo with all branches from the local repo jj git push [--remote <remote>] (there is no support for pushing from non-Git repos yet) git push --all [<remote>]
Update a remote repo with a single branch from the local repo jj git push --branch <branch name> [--remote <remote>] (there is no support for pushing from non-Git repos yet) git push <remote> <branch name>
Show summary of current work and repo status jj st git status
Show diff of the current change jj diff git diff HEAD
Show diff of another change jj diff -r <revision> git diff <revision>^ <revision>
Show description and diff of a change jj show <revision> git show <revision>
Add a file to the current change touch filename touch filename; git add filename
Remove a file from the current change rm filename rm filename
Modify a file in the current change echo stuff >> filename echo stuff >> filename
Finish work on the current change and start a new change jj close/commit git commit -a
See log of commits jj log git log --oneline --graph --decorate
Abandon the current change and start a new change jj abandon git reset --hard (cannot be undone)
Make the current change empty jj restore git reset --hard (same as abandoning a change since Git has no concept of a "change")
Edit description (commit message) of the current change jj describe Not supported
Edit description (commit message) of the previous change jj describe @- git commit --amend (first make sure that nothing is staged)
Temporarily put away the current change Not needed git stash
Start working on a new change based on the <main> branch jj co main git checkout -b topic main (may need to stash or commit first)
Move branch A onto branch B Not supported yet (can be emulated with jj rebase -s) git rebase B A (may need to rebase other descendant branches separately)
Move change A and its descendants onto change B jj rebase -s A -d B git rebase --onto B A^ <some descendant branch> (may need to rebase other descendant branches separately)
Reorder changes from A-B-C-D to A-C-B-D jj rebase -r C -d A; rebase -s B -d C (pass change IDs, not commit IDs, to not have to look up commit ID of rewritten C) git rebase -i A
Move the diff in the current change into the parent change jj squash/amend git commit --amend -a
Interactively move part of the diff in the current change into the parent change jj squash/amend -i git add -p; git commit --amend
Interactively split a change in two jj split -r <revision> Not supported (can be emulated with the "edit" action in git rebase -i)
Interactively edit the diff in a given change jj edit -r <revision> Not supported (can be emulated with the "edit" action in git rebase -i)
Resolve conflicts and continue interrupted operation echo resolved > filename; jj squash/amend (operations don't get interrupted, so no need to continue) echo resolved > filename; git add filename; git rebase/merge/cherry-pick --continue
List branches jj branches git branch
Create a branch jj branch <name> -r <revision> git branch <name> <revision>
Move a branch forward jj branch <name> -r <revision> git branch -f <name> <revision>
Move a branch backward or sideways jj branch <name> -r <revision> --allow-backwards git branch -f <name> <revision>
Delete a branch jj branch --delete <name> git branch --delete <name>
See log of operations performed on the repo jj op log Not supported
Undo an earlier operation jj [op] undo -o <operation ID> (jj undo is an alias for jj op undo) Not supported