Using named branches in jj
Named branches (or, starting with jj 0.22
, "bookmarks") are mostly an interoperability feature in jj
; other than some
sort of "main branch" that indicates where shared history lives, other branches
aren't necessary to get work done. However, if you use a tool like GitHub, which
bases a lot of its functionality around git
branches, then you'll end up using
more than one named branch.
To create a named branch (bookmark) in jj
, we can use jj bookmark create
:
$ jj bookmark create trunk
$ jj log --limit 2
@ povouosx steve@steveklabnik.com 2024-03-01 18:12:43.000 -06:00 trunk f68d1623
│ remove goodbye message
◉ vvmrvwuz steve@steveklabnik.com 2024-03-01 17:49:07.000 -06:00 d41c079b
│ refactor printing
I like the name trunk
here, but you can use main
if you prefer, whatever you
like really. But if we look on the right hand side of the first log line above,
we can see trunk
as an identifier here. We can use the name trunk
as a
revision or use it in a revset if we'd like:
> jj log -r 'ancestors(trunk, 2)'
@ povouosx steve@steveklabnik.com 2024-03-01 18:12:43.000 -06:00 trunk f68d1623
│ remove goodbye message
◉ vvmrvwuz steve@steveklabnik.com 2024-03-01 17:49:07.000 -06:00 d41c079b
│ refactor printing
~
One interesting thing about branches in jj
that's different than branches
in git
is that branches do not automatically move. For example, let's make a
new change:
> jj new
Working copy now at: moxnkoxx 3f14c03f (empty) (no description set)
Parent commit : ytkvxlpy 7ec11c41 trunk | remove goodbye message
> jj log
@ moxnkoxx steve@steveklabnik.com 2024-03-17 17:10:57.000 -05:00 3f14c03f
│ (empty) (no description set)
│ ◉ qtlkpytx steve@steveklabnik.com 2024-03-17 17:09:25.000 -05:00 e6667f9e
├─╯ (empty) (no description set)
◉ ytkvxlpy steve@steveklabnik.com 2024-03-17 17:09:25.000 -05:00 trunk 7ec11c41
│ remove goodbye message
Oh look, we have an extra empty commit lying around. That happens sometimes, let's forget about it:
> jj abandon qt
Abandoned commit qtlkpytx e6667f9e (empty) (no description set)
> jj log --limit 3
@ moxnkoxx steve@steveklabnik.com 2024-03-17 17:10:57.000 -05:00 3f14c03f
│ (empty) (no description set)
◉ ytkvxlpy steve@steveklabnik.com 2024-03-17 17:09:25.000 -05:00 trunk 7ec11c41
│ remove goodbye message
◉ krmulszn steve@steveklabnik.com 2024-03-17 17:06:59.000 -05:00 e98c1626
│ refactor printing
Even though @
has moved to moxnkoxx
, trunk
is still at ytkvxlpy
. This
behavior is a bit surprising for folks coming from git
, though it fits in with
jj
more nicely, I think.
Regardless, let's update trunk
to point at @
:
$ jj bookmark set trunk
Moved 1 bookmarks to pzkrzopz fcf669c5 trunk | (empty) (no description set)
$ jj log --limit 2
@ pzkrzopz steve@steveklabnik.com 2024-03-01 22:41:37.000 -06:00 trunk fcf669c5
│ (empty) (no description set)
◉ povouosx steve@steveklabnik.com 2024-03-01 18:12:43.000 -06:00 f68d1623
│ remove goodbye message
If you want to replicate git
's behavior, typing an additional command after
each change is done feels like overkill. But I would argue this is not the right
way to use jj
; as you'll see, we'll be either re-writing commits at the tip of
branches, or doing multiple steps of work before updating where a branch points.
In practice, it means I check the branch status before pushing code, rather
than as I work. That is, the branch name tends to sit at the same change as the
remote server, and when it's time to update the remote, that's when I update
things locally.
Speaking of remotes, let's talk about that next.