Navigating the history
Reset your progress
Reset your progress
To reset your progress to the start of this chapter, run the following command:
curl https://s2p2.github.io/jj-for-everyone/reset.sh | bash -s navigate
cd ~/jj-tutorial/repo
After Bob pushes a commit, Alice fetches the changes:
jj git fetch
@ qrtwnykn alice@local 2025-07-25 20:37:05 c2f4e43e │ (empty) (no description set) ○ rvpkroku alice@local 2025-07-25 20:37:05 push-rvpkrokuqrxt git_head() b9d02faf │ WIP: Add for loop (need to fix syntax) │ ◆ ttqlsyyr bob@local 2025-07-25 20:37:05 main 207a18a9 ├─╯ Add submission instructions ◆ stlxrmun alice@local 2025-07-25 20:37:05 530ad636 │ (empty) Merge code and documentation for hello-world ~
Bob's changes are on a different branch. Instead of merging or rebasing, we want to view his work while leaving Alice's changes on a separate branch for later.
The solution is to create a new, empty commit on top of Bob's main branch.
jj new main
@ uumounxy alice@local 2025-07-25 20:52:32 e1bcff24 │ (empty) (no description set) ◆ ttqlsyyr bob@local 2025-07-25 20:37:05 main git_head() 207a18a9 │ Add submission instructions │ ○ rvpkroku alice@local 2025-07-25 20:37:05 push-rvpkrokuqrxt b9d02faf ├─╯ WIP: Add for loop (need to fix syntax) ◆ stlxrmun alice@local 2025-07-25 20:37:05 530ad636 │ (empty) Merge code and documentation for hello-world ~
jj automatically deletes empty commits (no changes, no description), which keeps the log tidy. This makes jj new perfect for navigating the history. Running jj new <revision> checks out the project state at that revision by creating a new, temporary empty commit.
For example, let's view an older commit. Here's the full log for reference:
@ uumounxy alice@local 2025-07-25 20:52:32 e1bcff24 │ (empty) (no description set) ◆ ttqlsyyr bob@local 2025-07-25 20:37:05 main git_head() 207a18a9 │ Add submission instructions │ ○ rvpkroku alice@local 2025-07-25 20:37:05 push-rvpkrokuqrxt b9d02faf ├─╯ WIP: Add for loop (need to fix syntax) ◆ stlxrmun alice@local 2025-07-25 20:37:05 530ad636 ├─╮ (empty) Merge code and documentation for hello-world │ ◆ uxvvmtos alice@local 2025-07-25 20:37:05 a9946efd │ │ Add Python script for greeting the world ◆ │ qxkprvsu bob@local 2025-07-25 20:37:05 9e05718a ├─╯ Document hello.py in README.md ◆ xsswkrsu alice@local 2025-07-25 20:37:05 695f460b │ Add project description to readme ◆ pxvxmtks alice@local 2025-07-25 20:36:59 20c6a3b1 │ Add readme with project title ◆ zzzzzzzz root() 00000000
You can identify it using the description() function, which selects a commit by its description string.
jj new 'description("Document hello.py in README.md")'
Note the outer single quotes, which prevent your shell from interpreting the inner double quotes.
To check, run jj log:
@ uxuqnppz alice@local 2025-07-25 21:16:00 abba4830 │ (empty) (no description set) │ ◆ ttqlsyyr bob@local 2025-07-25 20:37:05 main 207a18a9 │ │ Add submission instructions │ │ ○ rvpkroku alice@local 2025-07-25 20:37:05 push-rvpkrokuqrxt b9d02faf │ ├─╯ WIP: Add for loop (need to fix syntax) │ ◆ stlxrmun alice@local 2025-07-25 20:37:05 530ad636 ╭─┤ (empty) Merge code and documentation for hello-world │ │ │ ~ │ ◆ qxkprvsu bob@local 2025-07-25 20:37:05 git_head() 9e05718a │ Document hello.py in README.md ~
The working directory is now at that older state. To return to main for the next chapter, run:
jj new main
Alice now has Bob's latest changes. She can always return to her loop experiment later with jj new.
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
.gitignoreand
jj file untrack. - Work-in-progress changes can be stored on the remote with additional bookmarks, avoiding chaos on the main branch.
- You can navigate to any branch or past version of your repository with
jj new.
It's time to take a break from this tutorial and practice what you've learned on a real project. Level 3 will teach you how to solve everyday problems like merge conflicts, so I recommend you come back for it relatively soon.