Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I have used jj for about one month on a project with a colocated git repo.

So far, I enjoy it a lot. Previously I would have a bunch of 'wip', 'fix typo' commits, but my commit history got much cleaner with jj. It's very easy to jump to old changes and apply fixes right in the place they belong. All changes + tests are now committed as one unit. I would never bother to do it in git, but because it's so easy now, I do it all the time.

Also, the possibility to add a description/message at any time, not only when you "commit" something at the end, is super useful. I use it as some kind of TODO list. Basically, I create a bunch of empty commits with a message and then just start from the first and work my way through all of them with `jj next --edit`.

If you have some extra time and would like to try out something new, I would very much recommend it.



Although it is currently undocumented, since v0.21.0 you can make `--edit` the default by adding the following to your configuration:

  [ui.movement]
  edit = true
Ref: https://github.com/jj-vcs/jj/pull/4283


The config file needs a lot of love. As does the help.

If you clone the repo there’s a bunch of documentation and example files, but if you install jj, those do not exist.


Each release comes with a file with all the help, for example:

https://github.com/jj-vcs/jj/releases/download/v0.25.0/jj-v0...

In theory, packagers could put these docs somewhere. I'm not sure what the best way is to make it convenient to use.

Also, I'm not sure about jj v0.25, but in the upcoming (probably tomorrow) 0.26, you can get a lot of docs by doing e.g. `jj help -k config`. Ironically, this fact is currently somewhat under-documented. `jj help` just says at the end:

`'jj help --help' lists available keywords. Use 'jj help -k' to show help for one of these keywords.`


Yeah I made it as far as planning out a change to the `jj config --help` output to at least link to the documentation and then realized that my copy didn't have the documentation. Oops. And then I got occupied by some other FOSS bug and forgot to circle back.

Unfortunately there was a gap between installing it and trying it for the clever merge resolution use case I had in mind, and I've forgotten how I installed it, so I need to reverse engineer that to figure out how I got here.


If your editor supports TOML schemas you can add the following to the config file to get autocomplete and in-editor documentation:

    "$schema" = "https://jj-vcs.github.io/jj/prerelease/config-schema.json"
More info here: https://jj-vcs.github.io/jj/prerelease/config/#json-schema-s... (I changed latest -> prerelease in the URL as this feature has been merged but not yet released).


> my commit history got much cleaner with jj

In my opinion the traditional git workflow is flawed, but wanting the commit history to be cleaner is fundamentally the wrong approach.

There are basically two main reasons to look at a chronological list of commits: reading it as a changelog, and bisecting to find a bug. As a changelog, you want the history to be clean, organized, and concise. Rebase-based workflows are good for this and it's what Jujutsu excels at. For bug hunting, every commit should build successfully and be a faithful representation of what was on the developer's machine at the time they made the commit. Merge-based workflows are good for this.

But these are conflicting requirements. If you optimize for readability, you lose reproducibility and vice-versa. To achieve both you need to stop trying to use commit histories as a changelog. It doesn't matter how messy it is if you never look at it.

But then you need some kind of history to look at. Personally I haven't seen any open source tools that solve this well enough to be a viable alternative. Stacked diffs are probably the closest.

I like Jujutsu but it feels more like an incremental improvement over Git as opposed to something that actually addresses the deeper issues of VCS.


> For bug hunting, every commit should build successfully and be a faithful representation of what was on the developer's machine at the time they made the commit. Merge-based workflows are good for this.

I'm not quite sure how that follows - I commit things all the time that cause either the main build or tests to fail. And a faithful representation of what was on my machine at a certain time in the past doesn't help me find bugs.

What helps is when each commit represents a single atomic change that I can easily understand, it has a clear commit message and it builds and the tests pass. To acheive this I often need to rewrite history, but doing so doesn't diminish my ability to find where I introduced bugs later on.

So I feel that rebase workflows are better for both readability _and_ bisection.


You can squash locally, that's fine, so long as you then locally run tests on the new squashed commit before pushing.

What I think is problematic is rebasing entire branches weeks after their commits have last been touched. The more you rely on manually looking through commit histories, the more you're encouraged to do this.

EDIT: something I forgot to mention in my original comment as well is that it rebasing makes collaboration harder. Basically, overall, we spend a lot of effort working around the drawbacks of rebasing, when we should be trying to eliminate the need to rebase in the first place.


How does this work with a shared remote branch? I know in git when you alter your history you can do a `git push --force-with-lease` as a safer `--force` - do you have to do this frequently with jj "rewriting history" (from a git perspective)?


Jj lets you edit:

- History you haven't pushed yet, or

- Bookmarks that you're tracking (meaning you're actively working on these branches), except "main"

History behind "main" or behind any untracked remote bookmark is immutable by default.

If you want to move "main" or any remote bookmark to a commit that isn't a descendant, you have to use `--allow-backwards`. If you want to edit one of these commits, you can use `--ignore-immutable`. Using either of these options is like a `push -f` in git terminology.


Yeah, `jj git push` acts as an equivalent (according to my experience and understanding) to `git push --force-with-lease`, always.

You don't have to pass an explicit --force, nor an explicit lease-related argument. As you say, rewriting the commits underlying changes happens frequently, so this would otherwise be pretty annoying.

There's also `jj git push --dry-run` to preview which branches would be updated in what way.


Thanks that makes sense - just feels weird to go from years of “be very careful rewriting history with git, especially at work” to jj rewriting everything all the time - can’t shake the feeling there’s a clash somewhere waiting to happen


You can customize the immutable commits option to specify which commits you want to be blocked from changing.

By default that’s only the main branch and untracked remote branches. For me that makes sense as I’m generally fine with constantly rewriting my feature branches.

However, if you want it to e.g. block you from rewriting anything that you’ve already pushed to the remote, you can set it to treat anything that’s pushed to the remote as immutable, too, as another commenter described [0].

[0]: https://news.ycombinator.com/item?id=42940329


As long as you don't use `--allow-backward` or `--ignore-immutable`, and as long as everyone sticks to their own feature branches, this shouldn't be possible.

The operation log makes jj quite safe. There's a command to restore the entire working copy + history to an earlier state in case you screw something up. Even this operation log is itself versioned, so you can undo the undo if you screwed the undo up, ad infinitum. :)


For every feature we usually have two developers working on it, one frontend and one backend, working on the same feature branch. Would Jujitsu cause a problem in this context?


I haven't used this workflow personally, but it should be fine.

`jj git push` does an equivalent to `--force-with-lease`, so if there are remote commits that are later than what your current bookmark points to, it won't overwrite them. You can `jj git fetch`, it'll update your bookmark, and you can choose to put your new commits onto the updated sequence of commits wherever they belong.


Just to be clear, as with git, you don’t have to rebase. It’s just that doing so is nicer in jj. But if rewriting commits on a shared branch becomes onerous, don’t do that!




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: