Remix.run Logo
andrepd 12 hours ago

Is there a concise introduction / overview of jj? I've read 8 pages of this link and the author is still in preambles and considerations... Not my favourite style of article!

SAI_Peregrinus 8 hours ago | parent | next [-]

You have a DAG of "changes" to the repo state. Each change has a stable ID, you can modify its contents or description without changing the ID. There's always a "current" change checked out, JJ automatically snapshots your edits to files into this change. JJ provides tools to edit changes, describe them, group them into named branches (bookmarks), reorder them, split them apart, etc.

JJ defaults to being backed by git. Each change has a corresponding git commit. When you edit the contents of a change, jj makes a new git commit & points the change at that new git commit. JJ is never actually amending or editing git commits, it's using git as a content-addressed data store.

That's the mental model. It's like git with a lot of accidental complexity (staging area, stashes, commit ID instability) removed.

There are a few ways you can work with this model. I like the following:

When I want to start new work, I fetch any changes from upstream `jj git fetch`, then make a new change after the current `main` or `master` bookmark: `jj new main`. Then I start writing code. When I want to commit it, I type `jj commit` and write a description. If I find I want to make an edit to a previous change, I edit my working copy and interactively squash to that change ID with `jj squash -i -r <change_id>`. When I'm ready to push those changes, I name the branch HEAD with `jj bookmark create`, then push it with `jj git push -b <bookmark_name>`. If there are review comments I squash edits into the appropriate changes or add new changes, and move the bookmark to the new head with `jj bookmark move`. If I want to merge two (or more) branches, I use `jj new <branch_1_name> <branch_2_name> <...>` to make a new commit with those branch names as parents. If I want to rebase some changes I use `jj rebase`. JJ doesn't care about conflicts, I fix them after a rebase has completed, instead of in the middle.

jampekka 7 hours ago | parent [-]

That sounds a bit faffy. In solo or small team work git is often git pull, edit code, git commit -a, git push.

With jj you have to fetch, start new space off a bookmark, edit code, commit it, update the bookmark and finally push?

SAI_Peregrinus 13 minutes ago | parent [-]

Git pull equivalent is `jj git fetch`

Git `checkout -b` equivalent is `jj bookmark create`

`git commit -a` equivalent is `jj commit`

Git push equivalent is `jj git push`

No more faff than git, I just prefer to do things in a slightly different order. I don't usually name the branch (`git checkout -b` equivalent) until after I'm done making changes & ready for a PR. I prefer to make changes, try things out, get it working, and then rearrange the commits to have a clean history to make my reviewer's lives easier. With `git` that's an interactive rebase, which tends to require a lot of faffing about.

JJ doesn't require branches to have names. By default it just leaves bookmarks (names of branches, roughly) where they are when new changes are made, but that's easily configured. You can even have it automatically create names when you push.

marcuskaz 12 hours ago | parent | prev | next [-]

I wrote a brief intro to Jujutsu here: https://mkaz.blog/code/jujutsu-vcs

steveklabnik 7 hours ago | parent | prev [-]

I can be a bit verbose, it's true :)

You've got some decent replies, but if you give me some background, like how comfortable you are with git, how much you care about certain details, I'd be happy to respond here with something more concise.