jj notes
A brief on working with jj based on steve
klabnik's guide
jj workflows
Squash workflow
Create an empty change on top with the changes that you want to create:
jj new
N (empty) (no description set)
|
...
Describe the change you want in this one
jj describe
Editor opens, add your change description
N (empty) My fancy description
|
...
Now, this change is empty. Let it be empty. Create a new blank change.
S (empty) (no description set)
|
N (empty) My fancy description
|
...
Now you have an empty, undescribed change on top of an empty, described change.
Do the deed and make changes here.
S (no description set)
|
N (empty) My fancy description
|
...
Move the contents down to the parent change using
jj squash
Takes the file path, can stage hunks using
--interactive, to move changes from a particular commit
that's not @, use --from option and to
move to something that's not the parent commit, use the
--into/--to option. So squashing is pretty powerful in
general. If you totally destroy a change in between, then you can
still keep the emptied change with --keep-emptied
Edit workflow
Create an empty change on top of a fully populated change, and proceed to add stuff and such like regular
A - My awesome description
|
B - My awesome parent change
|
C - Moar boosters
|
...
now, we want to make a change to somewhere in between. So, we do it
jj new --before B or
jj new --after C
Can also chain them to create funky graphs, but please don't
Make changes, and then go to top again with either repeated
jj next --edit or
jj edit <change ID>
rebasing
jj rebase does what you think it does. It takes a
commit, and puts them on top of other commits. We can specify a
source using the -s/--source. This would move all the
revision and the children. This is practically the only thing that
matters.
We can specify where to rebase in three ways:
--onto/-o rebases on top of the specified change and
create a new chain/anonymous branch.
jj rebase -s M -o O
P
|
O N'
| | P
| N M'/
| | |/
| M O
| | => |
| | L | L
| |/ | |
| K | K
|/ |/
J J
--insert-after/-A inserts it after the given change
and then the children of that change are moved to the top of the
chain. --insert-before/-B inserts it before the given
change and then that change are moved to the top of the chain.
jj rebase -s M -A O (alternately)
jj rebase -s M -B P
P P
| |
O N'
| |
| N M'
| | |
| M O
| | => |
| | L | L
| |/ | |
| K | K
|/ |/
J J
conflict resolution
This is fairly straightforward. If the rebase/merge/whatever fails, that change will be marked as conflicted. Just open the editor and remove the conflicts. Often, jj will remove the conflicts above as well. If there are no further conflicts on the higher level.
jj concepts
revision sets
Describe a set of changes in the history of the repo.
@ is the current revision. You can go up and down with
@+ and @- respectively
anonymous branches
They are nothing but a particular change that have more than two children. From that point on the changes are said to diverge or branch off.
named branches
Create using jj bookmark create <name>. A
bookmark is nothing but a specially marked change. To update it, you
need to run jj bookmark set <name> whenever you
want to set it to a new change revision.