Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Adding more bookmarks

Let's switch back to Alice:

cd ~/jj-tutorial

She heard rumors that next week's assignment is going to be about writing loops in Python. In an attempt to stay ahead of the game, she extends the hello-world program with iteration:

echo "
for (i = 0; i < 10; i = i + 1):
    print('Hello, world!')" >> hello.py

Unfortunately, she seems to have made a mistake. Running python hello.py prints an error:

  File "/home/remo/jj-tutorial/hello.py", line 3
    for (i = 0; i < 10; i = i + 1):
         ^^^^^
SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?

Alice doesn't have time to figure out the problem. She decides it's best to wait for the teacher to explain how to do it correctly in next week's lecture. She doesn't just want to throw her changes away though, she wants to keep the experiment around so she can compare it to the correct version later. As usual, she describes her changes and makes a new commit before pushing:

jj describe -m "WIP add for loop (need to fix syntax)"
jj new

Pushing work-in-progress (WIP) changes like this directly to the main bookmark would be a bad idea. Imagine if Bob later created a submission tarball and it accidentally included Alice's incomplete, incorrect code! That would be no good. To avoid that, Alice decides to push her commit to a new bookmark.

What should be the name of that bookmark? Having a main bookmark is a strong convention, but for additional ones, anything goes. A simple approach is to just use a super short description of your changes, like add-for-loop. Some people like to prefix their bookmark names with their own name or username, allowing everyone to easily identify who's working on what: alice/add-for-loop. Still others include a ticket number from the bug-tracker software in the bookmark name. These are all fine options, but sometimes you just don't care. Jujutsu has a handy way to push changes by generating a generic bookmark name for you:

jj git push --change @-

The name of the generated bookmark is push-, followed by a prefix of the change ID. It's not very informative, but that's kind of the point. The content of the commit is always more important than the bookmark.

Note that the --change flag can be abbreviated as -c. You might be noticing a pattern here, many commonly-used flags have these short versions. From now on, I won't mention them anymore. You can explore the available flags of any Jujutsu command by calling it with the --help flag.

Alice just got a text from Bob telling here he pushed another commit. She decides to fetch the new changes and start a new commit on top of them, to make sure she has the latest and greatest of Bob's documentation at her disposal.

jj git fetch
jj new main
jj log
@  xtkuwvsy alice@local 2025-07-22 21:36:48 2ebd8e39(empty) (no description set)
  smswwyok bob@local 2025-07-22 21:31:05 main git_head() ee59c1b1
│  Add submission instructions
│ ○  kxxnntsl alice@local 2025-07-22 21:36:36 push-kxxnntslrpwq 07380950
├─╯  WIP add for loop (need to fix syntax)
  twywpklt alice@local 2025-07-22 21:27:24 606959ce(empty) Combine code and documentation for hello-world
~

Wonderful. Alice has the latest changes from Bob and can continue to do other work. Her experiment with Python loops is safely stored on the remote with a bookmark. She can always come back to it later, finish the work and then combine it with the main branch. The WIP commit and its bookmark can also be deleted if they're not needed anymore, but that's a topic for another day.

You've completed Level 1 ! 🎉

Now you have the basic skills to collaborate on projects with other people. Let's summarize what we've learned:

  • A branching history is normal when multiple people work together.
  • You can combine changes from a branched history by creating a merge commit or by rebasing one branch of commits on another.
  • Files which do not belong in version control can be excluded with .gitignore and
    jj file untrack.
  • Work-in-progress changes can be stored on the remote with additional bookmarks, avoiding chaos on the main branch.

It's time to take a break and practice what you've learned. I still recommend to come back for level 2 relatively soon. It will teach you how to solve everyday problems like conflict resolution.