Branching 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 branch
cd ~/jj-tutorial/repo
So far, we've worked solo. Let's simulate a collaboration to see how Jujutsu handles branching.
Two developers, Alice and Bob, are working on a project.
- Alice will add a
hello.pyscript. - Bob will update
README.md.
First, Alice creates hello.py:
echo 'print("Hello, world!")' > hello.py
And makes a commit:
jj commit -m "Add Python script for greeting the world
Printing the text \"Hello, world!\" is a classic exercise in introductory
programming courses. It's easy to complete in basically any language and
makes students feel accomplished and curious for more at the same time."
Run jj log:
@ svplvpro alice@local 2025-07-22 21:17:41 4db2d0d0 │ (empty) (no description set) ○ zzywylnt alice@local 2025-07-22 21:17:31 git_head() f8e44920 │ Add Python script for greeting the world ◆ kxqyrwux alice@local 2025-07-22 21:14:46 main ffdf52d0 │ Add project description to readme ~
Meanwhile, Bob works on a separate clone of the repository, unaware of Alice's new commit. We'll simulate this by cloning the remote again and configuring it for Bob.
jj git clone ~/jj-tutorial/remote ~/jj-tutorial/repo-bob
cd ~/jj-tutorial/repo-bob
jj config set --repo user.name Bob
jj config set --repo user.email bob@local
jj metaedit --update-author
jj log
@ quolxwkk bob@local 2025-07-22 21:19:11 3ffac111 │ (empty) (no description set) ◆ kxqyrwux alice@local 2025-07-22 21:14:46 main git_head() ffdf52d0 │ Add project description to readme ~
Bob updates the README.md, commits his changes, and pushes to main first:
echo "# jj-tutorial
The file hello.py contains a script that greets the world.
It can be executed with the command 'python hello.py'.
Programming is fun!" > README.md
jj commit -m "Document hello.py in README.md
The file hello.py doesn't exist yet, because Alice is working on that.
Once our changes are combined, this documentation will be accurate."
jj bookmark move main --to @-
jj git push
A little later, Alice finishes her work and tries to push, but it fails because the remote main bookmark has moved.
cd ~/jj-tutorial/repo
jj bookmark move main --to @-
jj git push
Changes to push to origin: Move forward bookmark main from cd5f3fff9c7b to e90b597ed78e Error: Failed to push some bookmarks Hint: The following references unexpectedly moved on the remote: refs/heads/main (reason: stale info) Hint: Try fetching from the remote, then make the bookmark point to where ↪ you want it to be, and push again.
Following the error's hint, Alice fetches the latest changes. jj git fetch downloads new commits and bookmarks from the remote.
jj git fetch
After fetching, her log shows that the history has diverged into two branches:
@ svplvpro alice@local 2025-07-22 21:17:41 4db2d0d0 │ (empty) (no description set) ○ zzywylnt alice@local 2025-07-22 21:17:31 main?? main@git git_head() f8e44920 │ Add Python script for greeting the world │ ◆ quolxwkk bob@local 2025-07-22 21:22:22 main?? main@origin 8d538390 ├─╯ Document hello.py in README.md ◆ kxqyrwux alice@local 2025-07-22 21:14:46 ffdf52d0 │ Add project description to readme ~
This happened because Alice and Bob both created new commits based on the same parent. Jujutsu prevented Alice's push to stop her from accidentally overwriting Bob's work.
Notice the main bookmark appears twice with question marks (??). This conflict means Jujutsu doesn't know where main should point: to Alice's local commit or Bob's commit from the remote.
- A bookmark is a named pointer to a single commit.
- A branch is specified by its tip, which is also a single commit. However, a branch refers to the set of commits that includes the tip and all of its ancestors.
A bookmark often names the tip of a branch. For example, the main bookmark points to the tip of what we call "the main branch". People who primarily use Git often use the word "branch" for both concepts.
To proceed, Alice and Bob need to combine their changes into a single version. We'll cover how in the next chapter.