Jujutsu workshop
A Git-compatible version control system
At 39C3, I gave a workshop about Jujutsu, a new-ish version control system that I fell in love with last year! :)
Here’s the script that I used in the workshop:
___ _ _
|_ | (_) | |
| |_ _ _ _ _| |_ ___ _ _
| | | | | | | | | __/ __| | | |
/\__/ / |_| | | |_| | |_\__ \ |_| |
\____/ \__,_| |\__,_|\__|___/\__,_|
_/ |
|__/ A Git-compatible VCS
blinry
# Getting to know you!
Who is using Git in any way?
Who is familiar with the command line?
Who has tried Jujutsu?
# Workshop in 3 parts
Please interrupt me and ask questions!
# Motivation
Git is kinda hard
https://git-man-page-generator.lokaltog.net
https://spderosso.github.io/onward13.pdf
Multiple friends told me about a new VCS
https://github.com/jj-vcs/jj
Tried it last year
Has entirely replaced Git for me! 😮
# What I like about Jujutsu
Both simple and powerful
Some workflows that are hard with Git are easy with jj!
Trivial to modify commit history
Simpler mental model
No index, working directory *is* the commit
Deal with conflicts when you're ready
Possible to undo mistakes (finally!)
GIT-COMPATIBLE! ✨
Anyone remember git-svn?
# History
Started in 2019
Hobby project of Martin von Zweigbergk
Initially called "Jujube" :D
https://commons.wikimedia.org/wiki/Category:Ziziphus_jujuba_(fruit)
Renamed to "Jujutsu" in 2021
# 6 basic commands
jj git init
Until v0.32, use --colocate.
jj log
jj show
jj describe
jj new
jj commit
Things to note
Working directory is "snapshotted" every time you run a jj command!
Git: Edit files, add files, commit
jj: Edit files, commit
Uncommited changes are recorded in the current commit!
Questions so far?
Self-help: jj <subcommand> -h / --help
~~~ Install jj & try the 6 commands for 10 minutes! ~~~
# Manipulating history
jj edit
Automatic rebasing!
No stashing required!
jj squash (-r <revision>)
jj split (-r <revision>)
Alternative to Git's index and interactive adding
jj abandon
Creating and resolving conflicts
# More things `jj new` can do
jj new <revision>
jj new <revision 1> <revision 2>
jj new -A/-B <revision>
# Rebasing
jj rebase --branch <revision> --onto <revision>
~~~ Try manipulating history for 15 minutes! ~~~
# Git interop
`jj log` also shows commit ids
Changes vs commits
jj evolog
# Working with Git remotes
Branches don't *need* names!
jj git remote add origin <url>
jj bookmark
create
move
delete
track origin@main
jj git push
(jj git push --named <bookmark name>=<revision>)
jj git fetch
Common alias: jj tug
tug = ["bookmark", "move", "--from", "heads(::@- & bookmarks())", "--to", "heads(::@ & (~empty()))"]
# Common starting problems
I don't see the full log!
jj log -r ..
My files are added by default!
jj config set --user snapshot.auto-track "none()"
jj file track <file>
I made a mistake!
jj undo
Working with the operations log
jj op log
jj op revert <operation id>
jj op restore <operation id>
I wanna go back to Git!
Always possible to switch between jj & git!
rm -rf .jj
Probably in a detached HEAD state, so:
git switch <branch>
# More juicy things!
Revset language
inspired by Mercurial!
https://docs.jj-vcs.dev/latest/revsets/#operators
author(blinry)
comitter_date(after:"10 minutes ago")
heads(::)
Templates
https://docs.jj-vcs.dev/latest/templates/
"format_short_id(id)" = "id.shortest(4)"
jj absorb
# Now what?
You can use jj *right now*!
It might make your life easier?
# Cheat sheets
https://justinpombrio.net/src/jj-cheat-sheet.pdf
https://jj-vcs.github.io/jj/latest/git-command-table/
# Suggestion
1. Make a local copy of one of your projects
2. Delete all remotes (to make the commits mutable)
3. `jj git init`
4. Play around, try some of the jj commands again
(edit, describe, new, commit, split, ...)
5. Find three places where you can improve the history!
# My graph-drawing command:
bash -c 'while true; do OUT="$(jj log --ignore-working-copy --color=always -r ::)"; clear; echo "$OUT"; sleep 0.1; done'
# Find me on the Internet!
Mastodon
https://chaos.social/@blinry
Projects & contact
https://blinry.org
Slides
https://blinry.org/jj-workshop/
~~~ Try jj on your own project (until we get kicked out) ~~~
Several people have asked for my config file, here it is! It also includes some experiments I’ve commented out:
[ui]
default-command = "log"
pager = "less -FX"
movement.edit = true
#diff-editor = ["nvim", "-c", "DiffEditor $left $right $output"]
diff-formatter = ["difft", "--color=always", "$left", "$right"]
[snapshot]
max-new-file-size = 100000000
#auto-track = "none()"
[aliases]
tug = ["bookmark", "move", "--from", "heads(::@- & bookmarks())", "--to", "heads(::@ & (~empty()))"]
[revset-aliases]
'2weeks' = 'committer_date(after:"2 weeks ago")'
[template-aliases]
#"format_timestamp(timestamp)" = "timestamp.ago()"
#"format_timestamp(timestamp)" = 'timestamp.format("%Y-%m-%d")'
#"format_timestamp(timestamp)" = ''
"format_short_id(id)" = "id.shortest(4)"
#"format_short_commit_id(id)" = ""
#"format_short_signature(signature)" = "signature.email().local()"
"format_short_signature(signature)" = ''
#"format_short_signature_oneline(signature)" = ''
"format_short_signature_oneline(signature)" = 'signature.name()'
[templates]
log = 'builtin_log_oneline'
draft_commit_description ='''
concat(
coalesce(description, default_commit_description, "\n"),
surround(
"\nJJ: This commit contains the following changes:\n", "",
indent("JJ: ", diff.stat(72)),
),
"\nJJ: ignore-rest\n",
diff.git(),
)
'''
[git]
colocate=true
Comments?
Send a message to @blinry@chaos.social or drop me a mail at mail@blinry.org. Also, you can support me on Patreon or subscribe to my newsletter!