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

Goal

You learn to resolve those cases when 2 developers try to move the same remote Bookmark in 2 different, incompatible positions.

Bookmark Conflicts

In general, as long as updating a Bookmark's position means moving it forward along the history tree, everything goes smoothly.

It's less natural for a Bookmark to go backwards in history, or even to jump to a parallel branch. If you try to do that with Git, it won't complain, but your next git push will likely be rejected, with an error such as:

! [rejected]        feature/my_feature_branch -> feature/my_feature_branch (non-fast-forward)
error: failed to push some refs to 'ssh://git@yourrepo.com/repo/my -project.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

Jujutsu tries to anticipate the problem and shows an error even before the push, already when you attempt to move the Bookmark.
In the theirs repository, try moving the foo Bookmark from k to o:

@  sz   (empty)
│ ○  k    foo Hello, world
│ ○  st
├─╯
│ ○  o    bar
├─╯
◆  u    main
│
~
$ jj bookmark move foo --to o
Error: Refusing to move bookmark backwards or sideways: foo
Hint: Use --allow-backwards to allow it.

Your Coworker Forces Their Way

If you really want to win this fight, you can always use the --allow-backwards parameter. Let's suppose that's the path your coworker decides to take:

jj bookmark move foo --to o --allow-backwards
@  sz   (empty)
│ ○  k    foo@origin Hello, world
│ ○  st
├─╯
│ ○  o    bar foo*
├─╯
◆  u    main
│
~

2 things to notice:

  • Since now foo and foo@origin are on different Changes, Jujutsu thinks it's appropriate to display both of them.
  • The asterisk in foo* invites your coworker to align. Which they do with a push:
jj git push -b foo
@  sz   (empty)
│ ○  k    Hello, world
│ ○  st
├─╯
│ ○  o    bar foo
├─╯
◆  u    main
│
~

What Happens in Your Repository

Go back to ours repository. Unaware of the Bookmark's move, you keep working on foo, adding another change:

jj new -m "Hola, mundo"
echo "Hola, mundo" > hello.txt
@  ol   Hola, mundo
○  k    foo Hello, world
○  s
│ ○  os   bar
├─╯
◆  u    main
│
~

You even reckon it's a good moment to advance foo from k to ol:

jj bookmark advance
@  ol   foo* Hola, mundo
○  k    foo@origin Hello, world
○  s
│ ○  os   bar
├─╯
◆  u    main
│
~

Right, Jujutsu marks foo with a * inviting you to align foo@origin with a push:

$ jj git push -b foo
Changes to push to origin:
  bookmark: foo [move forward from 938fe989965e to 0952644707a7]
Warning: The following references unexpectedly moved on the remote:
  refs/heads/foo (reason: stale info)
Hint: Try fetching from the remote, then make the bookmark point to where you want it to be, and push again.
Error: Failed to push some bookmarks

Rejected.

Conflicts

Here's the log:

@  ol   foo?? foo@git Hola, mundo
○  k    Hello, world
○  s
│ ○  os   bar foo?? foo@origin
├─╯
◆  u    main
│
~

It also helps to list the bookmarks:

$ jj bookmark list foo
foo (conflicted):
  - ksvskswq 938fe989 Hello, world
  + olnvmuqu 09526447 Hola, mundo
  + ossuomlo fa22ec04 (no description set)
  @git (behind by 1 commits): olnvmuqu 09526447 Hola, mundo
  @origin (behind by 3 commits): ossuomlo fa22ec04 (no description set)
Hint: Some bookmarks have conflicts. Use `jj bookmark set <name> -r  <rev>` to resolve.

OK, calm down: there are 4 instances of foo now. How should you interpret the situation?

  • There are 2 foo??, one on ol and one on os. Jujutsu is telling you that your local branch foo points to both.
    • On one hand, it wanted to keep foo on ol, where you moved it with jj bookmark advance.
    • On the other, the information coming from origin says that foo should point to os.

What to do? Undecided, Jujutsu lets foo target both. That's why it displays a ??.

  • foo@git reminds you that in the underlying Git repository the foo branch is still pointing to ol.
  • Finally, foo@origin shows you the last known position of foo on origin, after the fetch.

Apparerently the situation can't be reconciled automatically. You'd better talk to your coworker and clarify what they had in mind.

Resolve a Bookmark Conflict

One possible solution for having in foo both the changes in ol and those in os is to create a merge Change:

jj new -r ol -r os -m "Merge"
@    p    (empty) Merge
├─╮
│ ○  os   bar foo?? foo@origin
○ │  ol   foo?? foo@git Hola, mundo
○ │  k    Hello, world
○ │  s
├─╯
◆  u    main
│
~

The new Change p looks like a good place to put the foo Bookmark:

jj bookmark move foo -t p
@    p    (empty) foo* Merge
├─╮
│ ○  os   bar foo@origin
○ │  ol   Hola, mundo
○ │  k    Hello, world
○ │  s
├─╯
◆  u    main
│
~

Lovely! There are no more conflicts, only the invitation to push:

jj git push -b foo
@    p    (empty) foo Merge
├─╮
│ ○  os   bar
○ │  ol   Hola, mundo
○ │  k    Hello, world
○ │  s
├─╯
◆  u    main
│
~

All clear. Your coworker is forgiven.