Mastodon

Jujutsu is a distributed version control system (think git alternative). I consider myself a git power user and it’s interesting to challenge myself and work with a system that promotes a bit different workflow.

The main difference in philosophy seems to be that jujutsu encourages “rewriting the history” and editing older revisions, with changes seamlessly propagated to the descendant commits. I saw it described as “always being in an interactive rebase, and it’s actually good!“. As someone who uses git rebase -i quite a lot - I was curious!

For the full sales pitch and tutorials I’d like to refer to the official docs or a tutorial by Steve Klabnik. Here you will find my notes on the pros, cons and “good to know” as I’m learning to work with jj.

Materials

Useful reference materials

Cheat sheet

Useful config

The jj config is stored in ~/.config/jj/config.toml. So far, I liked the following options:

# display full commit messages in `jj log` rather than the one-line titles
jj config set --user templates.log "builtin_log_compact_full_description"
 
# limit the log length when executing `jj`
jj config set --user ui.default-command '["log", "-n", "15"]'
 
# prevent secret or temporary commits from being pushed to remotes
[revset-aliases]
private = "description(regex:'^(wip:|local:|secret:|private:)')"
 
[git]
private-commits = "private"

jj log by default displays the following set of revisions: present(@) | ancestors(immutable_heads().., 2) | present(trunk()). This can be changed with the setting revsets.log.

The good

  • jj operation log is impressive - all operations in the repository are recorded and can be reverted with a simple jj undo
  • all files in the repository are tracked by default. This increases the risk of accidentally committing secrets but much more often I made the mistake of forgetting to add the right files in git.
  • jj coexists with git, making it possible to adopt it without converting the rest of your team
  • it’s possible to configure a regex for identifying local-only commits (see config docs) and jj will protect you from pushing those to the remote

Complaints

Some of the difficulties and downsides I’ve encountered. Surely at least some of them will be resolved as tooling around jj matures, for example improving shell completion.

  • the language for selecting revisions is quite verbose. That’s a win for readability (compared to git’s magical incantations) but quite a lot to type.
  • I miss the commit.verbose setting from Git config which showed a preview of the whole diff when editing the commit messages. It made it easier to ensure I’m committing the right thing and writing an accurate message and. On the other hand, in jj it’s trivial to undo any operation with jj undo so I shouldn’t worry so much about making a mistake.
  • the diff capable of showing per -word difference is nice but I miss the git.colorMoved setting which would differentiate moved lines from truly deleted.
  • I’m yet to find a quick way to show a diff of all changes made on a given branch. In git that would be git diff main...some-long-branch-name. Here the equivalent seems to be jj diff -f 'fork_point(main | some-long-branch-name)' -t some-long-branch-name which is quite a lot more to type. Perhaps I need to set up an alias that will make it easier to call this command.
    • This is exacerbated by fish shell completions not working while in the middle of a more complex expression. After jj diff -f 'fork_point(main | tab completion will not help me with some-long-branch-anme