November 10, 2024
EDIT, 2025-12-25: I've gone back to straight git. I think jj will probably be a passing fad that will never have the full functionality as git, nor the documentation/support/community.
This is probably going to be something of an evergreen post, updated as necessary. Unless I forget it exists.
I heard about jujutsu sometime within the last year. I have to admit my initial thought was something along the lines of "why make something else when there's git?" but then I saw that Steve Klabnik (co-author of the Rust book) is writing a tutorial on it. So, as I said on Mastodon, I guess I'm going to have to check it out. (EDIT, 2025-07-23: "Jujustsu for busy devs" is a good intro.)
And so I've been using it on personal projects for the last couple weeks and I quite like it.
Anyway, I wanted to note some things I'm getting used to/figuring out.
Workflow:
- I'm mostly using the "edit" workflow Steve describes, but not quite as he describes it.
- The happy path: When I'm done with some set of changes, I'll update the description if necessary. I'm finding that writing the description before doing any work is helpful in thinking about it before doing it, so that's why I say "if necessary". But half the time it is, and if so it's done with
jj describe(to open an editor to write the subject and optionally body of the message) or withjj describe -m <message>to write it on the command line. Push to remote, possibly. Then runjj newto start a new revision. I don't often use the-m <message>option withjj new, as I'm just trying to finish up the one I've been working on and leave things in a fresh state, but you can do that. (There's also one command that will replacedescribeand thennew:jj commit, orjj cifor short.) - Aw fuck I forgot something:
- if I've already started a new revision with
jj new, just make whatever changes are necessary and then runjj squash. This will push the changes in the working copy into the previous revision, and the working copy will be empty. If you already added a description, an editor will pop up allow you to edit the commit, very much like in rebasing ingit. - if not, run
jj newand thenjj squash. If you just runjj squashwithout starting a new revision, you'll be pushing all your changes both now and what you previously did into the the revision before the one you're attempting to add to. - if you already pushed to a remote, you can do it again, just specify the revision:
jj git push -r <rev> --remote <remote-name>. There's no need (or option) for--force. Just push it. - it's also easy to do this with only some of the changes. I'll add that later.
- if I've already started a new revision with
Pushing to remote: If finished with a revision and want to push it somewhere, don't start a new one (because you can just work on the working copy without having to specify a revision). Update the bookmark with jj bookmark set main to move the main bookmark/branch to the working copy. Then do jj git push --remote <remote-name> to push it there. Then a new revision, to start further work, can be started with jj new.
Various things:
@is the working copy and@-is used for the revision before the working copy. You can pass in the revision on most commands --r <rev>. So-r @-is the one before the working. I'm not sure how far out it goes, but tacking on additional-will go one further.jj showwill show commit description (the full one, not just the subject likejj logdoes) and revision changes. Handy asjj show @-to see previous one from working copy.jj undois pretty great. I fucked up some things and it made them go away.jj abandonis both useful and good naming. Wrote some code that's actually not worth saving?jj abandon.- to use jujutsu out of the gate with a new Rust project (rather than "colocate" it with git), pass
--vcs=nonetocargo newand then runjj git initin the project's directory. - the "builtin_log_compact_full_description" template is the one that feels most like what I expect from
git log. So I've added an alias for it, to "v", which means it can be called withjj v. The new part of my ~/.config/jj/config.toml file looks like this:[aliases] v = ["log", "-T", "builtin_log_compact_full_description"] # v for verbose - Start a branch awhile ago and then just kind of forget about it? And then you're like 30 commits from where you diverged but you want to pick up the old branch again? I'd have to probably read several blog posts and forum threads for git, but for jujutsu it took me just
jj helpand a couple minutes to figure out that the answer is justjj rebase -r [revision] -d @and everything seems ... like I wanted it to be? (-bor-smay be a better choice than-r.jj help rebaseprovides clear explanation and graphs to make the decision easy.)