klauserc 2 days ago

Been using jj at work for months now. In colocated mode, JetBrains IDEs even retain some if their VCS integration.

The ability to easily work on top of an octopus merge and then push changes "down" into the contributing branches has been a live saver when my team had to do a big refactoring in a mono repo and split the changes into small PRs for individual teams (code owners).

The auto committing behavior is a bit weird at first, but now I don't want to go back to git. It feels a bit like the step from SVN to git back in the the day. ("this feels weird" -> "how did people ever tolerate the old way?")

  • stouset 16 hours ago

    100% agreement on that transition. I feel like I had to unlearn a lot of git’s subtly-broken model and now things feel so much simpler and easier.

    One of those for me was branch names that don’t automatically “follow” new commits. At first it felt weird but it unlocks the ability to do consecutive work as one linear set of changes, even when those changes need to be merged in discrete chunks. The git approach for this (stacking branches) is so painful, particularly when you need to edit an earlier change or add a new commit between earlier ones. This went from being so frustratingly difficult I wouldn’t even consider it to being utterly trivial.

    Also rebase conflicts. Not being unceremoniously dropped into a half-broken “fix this NOW state” with no ability to inspect and poke at other commits in the chain and not being able to fix things incrementally in any order is something I couldn’t have imagined. And like you said now it’s insane to me that people continue to put up with it.

  • steveklabnik 2 days ago

    Full agreement on both “it feels weird” -> “how do people ever tolerate the old way” as well as the auto commit behavior being one of those things. In fact I probably over-index on that specifically when talking about jj. I thought I’d hate this because I love git’s index. Turns out that by getting rid of the index, jj has a better index than git does, but that sounds insane at first!

    • stouset 15 hours ago

      Same about the index! I initially skipped over jj thinking the lack of an index was a huge step backwards but commit-splitting is a massive improvement.

      I do wish there was a better front end for it though.

  • conaclos 2 days ago

    > The auto committing behavior is a bit weird at first

    I am a bit skeptical about this, because this requires a jj daemon?

    • aseipp 2 days ago

      It's a bit of a magic trick. A "snapshot" is taken any time a command is run, and it happens implicitly before any actual algorithms or code for a given command is run (massively simplifying the internal design), so for all intents and purposes it's "automatic" from the user interface e.g. even checking repo status or otherwise small operations will cause a snapshot.

      But you can integrate with https://github.com/facebook/watchman/ in order to have a truly daemon-ified option where any filesystem write will cause a snapshot to be taken.

      • stouset 15 hours ago

        What’s also amazing is this means you’re no longer completely on your own when fixing things up.

        I can’t tell you how many times I got midway through a git rebase, realize I’d fucked up earlier, and had to abort and redo everything from scratch. With jj not only is this not a problem (thanks to conflict markers being first class citizens) but also any intermediate changes are being snapshotted without me having to do anything. So I can always go back to an earlier change if need be.

        The first time I had to do this I’d royally fucked up a complicated commit reordering sequence while screen sharing during a meeting. I’d never needed to use the op log before and had no idea how to use it. It took maybe a minute or two to fix things completely.

swiftcoder 2 days ago

> I also heard friends rave about "stacked diffs" but struggled to understand what exactly was going on there. Nothing I read or conversations I had have clicked.

I wonder what it is about descriptions of stacked diffs that doesn't land - it's literally just a rebase-centric workflow instead of the merge-centric workflow popularised by GitHub et al.

  • steveklabnik 2 days ago

    For me, my git brain is very low level. And none of them ever explains what actually happens under the hood, or how that was different than branching…

    With some respect, I think “rebase centric workflow” doesn’t really cover it: I use rebasing heavily with GitHub. A “trunk based development where all branches are rebased before merge so there’s never merge commits, please add to commits and rebase the branches in response to review comments” development style is still very rebase centric, but not stacked.

    You also have to remember (though there’s no reason you should know this) that GitHub came out of the community I was heavily involved in at the time of its birth. I’ve been using GitHub for longer than most people, and so the PR-style workflow has been the air I’ve breathed for so long, it can be hard to understand other things at first. I had used subversion before git, but didn’t really understand much about it.

    Anyway, that’s just a roundabout way of saying that I think this space is super interesting because these tools are so flexible that they can be used in so many different ways, and it’s easy to assume that “how you use git” is some sort of shared experience when that’s not really true.

    • 3np a day ago

      What I find confusing with people raving about it as something different is the considering the following scenario:

          refactor/a  # should be merged as independent PR
          feature/a-b # depends on a; should be merged independently, after
          fix/c       # independent
      
      Then I will probably have some local `dev` branch checked out with a combination of all of the above and maybe some.

      How else than "stacked diffs" would you submit all of this for review concurrently while still working on all of them? It sounds like a new word for what we were always expected to do? What's an alternative which doesn't rely on compromising merge-strategy?

      At this point I'm suspecting "stacked diffs" is just a crotch for people still barely coping with DVCS but I could be missing something.

      • viraptor a day ago

        GH did not really support automated base change (after merging) not that long ago, so doing this as stacked diffs/prs there was quite annoying. I guess that's why people tried to avoid it for a long time? I know I did some weird PRs in the past just to keep them independent. It could still be improved today (why is main the base when the branch contains an existing PR? adjust it automatically, please!), but it's not a big issue anymore.

        • stouset 15 hours ago

          Also this workflow is excruciatingly painful if you need to make a change or add a commit to an earlier part of the “stack”. Now you have to manually rebase everything after it one by one by one.

      • ykonstant a day ago

        A crutch, I think. Or a crotch; I don't judge.

    • Kinrany 2 days ago

      The holy grail of a stacked diff workflow would be making multiple Github PRs each made against the previous branch instead of trunk, and then updating the branch that's closest to trunk and rebasing all of the children PRs without having to force push into any of them.

      Git and Github do not support this workflow directly, and this creates space for all the other tools.

      Jujutsu comes close to supporting this workflow directly, without having to provide any specialized utilities that mention "stacked diffs" at all.

      https://github.com/spacedentist/spr (not to be confused with ejoffe/spr) is a utility that maps a local change to a remote branch, updating the branch (without force pushes) when the local change is updated. (Changes work the same as they do in JJ, but the implementation is different.) And this works even when you have a stack of changes and update one in the middle of the stack.

    • swiftcoder 2 days ago

      Yeah, and I think it's also worth noting that by far the largest set of folks advocating for stacked diffs are not actually using git.

      Meta runs a custom mercurial-compatible monorepo that was scaled up to handle thousands of commits per hour, and they have a culture of constant codebase-wide refactoring commits (i.e. the ongoing live migration of PHP -> Hack) - that rate of change causes problems that most GitHub projects have no reason to solve.

  • arccy 2 days ago

    because it's a name that describes the technical implementation, not the end user experience

    • swiftcoder 2 days ago

      Maybe the problem here is that there aren't any open tools implementing the user experience, because I'd say it's exactly the opposite - that it is implemented using rebase under the hood is entirely secondary to the user experience of "stacking" changes on top of one another.

      • steveklabnik 2 days ago

        This is a major issue for sure. Like a big enough one that if I was still doing major open source work, I’d be working on that.

jFriedensreich 2 days ago

I am torn between sapling and jj. Both make good progress in git/github integration which seems to have been the major road block in adoption before. One other major roadblock seems to be the limits of review tools supporting stacks: github PRs are too limited, gerrits ux is horrible, graphite does not work and is not open enough, saplings review tool is just a very slow performing POC (though with a really good UI concept as starting point)

  • sheremetyev 2 days ago

    for me important argument in favour of JJ over Sapling was "first-class conflicts" - JJ stores conflicts in the history and allows you to resolve them later, while Sapling forces you to resolve conflicts at the point when they happen

    https://martinvonz.github.io/jj/latest/sapling-comparison/

    • hinkley 9 hours ago

      If first class resolution is done right, then instead of project generators we can just create sample projects that people fork, and when you make breaking changes or add new startup config to the project, you update the sample project(s) and people can pull the updates. Once you resolve the conflicts you’re done until the next change, at which point your repo remembers how the last conflict was resolved, and doesn’t ask you to redo it.

      This is why jj is on my todo list. I’m not calling it jujutsu no matter how much someone pays me though.

  • aseipp 2 days ago

    Gerrit, as I like to say, has a user interface that only a mother could love. But ultimately it's a very productive tool, so I just got over it. I even wrote some integration between jj and gerrit, making submitting stacks very easy and smooth.

    IMO, Gerrit is the best currently available option by a large margin, notwithstanding its quirks.

  • forks 17 hours ago

    Could you say more about how/why "graphite does not work"?

  • steveklabnik 2 days ago

    I think it’s great that there is more than one project in this space. Sapling is pretty cool too, though I haven’t used it as much.

    And yeah, the lack of good review tooling is certainly a big issue.

phildenhoff 2 days ago

Steve, I see you’re in this thread. I was using jj for a while before reading your tutorial and yet still found it quite insightful and helpful. Thanks for your contribution!

nixosbestos 3 days ago

One of my favorite people talking about my single favorite tool of the past 3+ years. Up there with (above, really) zellij and helix for changing my daily life.

  • emmanueloga_ 2 days ago

    Helix, the editor? How would you pitch it?

    Zellij looks powerful but also a bit too complex, following the "kitchen sink" school of design :-). No biggie but its name is too close to IntelliJ imho. What kind of workflow do you use with it?

    I used tmux a bit back in the day, but these days I feel like good old tabs and app windows cover my needs. When I want to multiplex processes in a single window, I reach for Overmind. [1]

    --

    1: https://github.com/DarthSim/overmind

    • stavros 2 days ago

      I don't know what you find complex about Zellij, as I haven't used it extensively, but the few times I've used it, the UI was eminently self-describing, I managed to do everything I've needed to do within a minute of first launching it.

      Is there more advanced stuff that's more complex that I just haven't seen?

      • emmanueloga_ 2 days ago

        > Is there more advanced stuff that's more complex that I just haven't seen?

        Yes? I mean, it even has a system to install plugins made with WASM, from what I saw in the docs. I guess you could just use the basics and be okay with it.

        For me, after years of tinkering with apps like Vim, Emacs, and AwesomeWM [1], I've developed a bit of PTSD over the amount of time these kinds of tools can take to configure and master [2]. Zellij feels like it belongs in this category of tools, and perhaps I'm overreacting or flinching. :-)

        --

        1: https://awesomewm.org/

        2: I've benefitted a lot from being able to use vim key bindings with extensions in apps like VS Code and emacs key bindings on places and I'm somewhat glad I spent the time, though.

        • stavros 2 days ago

          Those things are optional, though. You can just use the basics and ignore the rest.

    • Lyngbakr 2 days ago

          > Helix, the editor? How would you pitch it?
      
      Not the OP, but Helix is a minimal fuss modal editor with sensible defaults. My config is maybe five lines? I say "maybe" because I haven't looked at it I first wrote it. And I think I'd probably be just fine with no config.
      • imjonse 2 days ago

        Sensible defaults but also out of the box features you only get in vim by finding and configuring external plugins (fuzzy file picker, LSP integration, multi-cursor editing, inline keymapping help).

        Cons: no session save, good Helix keybindings not available in other tools so confusing to switch between vim/hx mental models when in colab/vscode, no AI-assistants since no plugin system yet.

  • rw_panic0_0 2 days ago

    nice to see zellij+helix combo users out there. Helix been my fav editor for like a year already, zellij is also a daily driver, and now i'm learning jj :P

thih9 2 days ago

Love it, read a couple of chapters already and planning to finish the rest. As a person completely new to jj and someone who also enjoys git CLI, this is an intuitive, very useful and enjoyable read.

I’m especially interested after learning about the git compatible backend:

> There's one other reason you should be interested in giving jj a try: it has a git compatible backend, and so you can use jj on your own, without anyone else you're working with to convert too.

stavros a day ago

This was informative, thanks Steve! The only problem I had was that the difference between changes and commits wasn't clarified enough in the beginning, and I got lost trying to distinguish between the two. I'm on chapter 4 and I'm still not sure what a change is and what a commit is.

From a tiny bit of previous jj experience, my mental model is "a commit is the snapshot, and a change is what happened between snapshots", but that might be wrong. It would be great if this could be clarified a bit more in the tutorial.

  • stouset 15 hours ago

    Changes are a stable ID for a single conceptual modification to the repo. They are backed by—at least right now—a regular git commit with a content hash.

    As you iterate on one change, new underlying git commits are made to snapshot the latest state of the current change being edited. The change ID remains stable though the backing commit ID varies as the change’s contents are modified.

    You can always revert a change back to a previous backing commit.

    This has a few cool implications.

    First, you never have uncommitted changes. You are always editing a “current” change with an ID that is regularly persisting your work (either every time you run a jj command or with a filesystem event monitor).

    Second, you’re never “on” a named branch: you’re only ever “on” a change and named branches are just mutable pointers to change IDs. This is awesome for a long-lived linear bit of work that needs to be merged in piecemeal. In git you’d need multiple branches based on one another and nothing tracks the relationship between them. Updating earlier work is painful. With jj, it’s all just one linear branch with some changes having names. If you need to edit an earlier change or insert new ones, you just… do that.

    • stavros 15 hours ago

      Thank you, this clarifies things. And the changes aren't shown to git clients/GitHub? They just see a bunch of commits?

      I should probably use jj at this stage and figure all this out for myself, rather than just read about it. Thank you!

      • stouset 15 hours ago

        They (and you, unless you go digging) only see the latest commit associated with each change.

        The older ones are there in your local repo but they’re invisible unless you need to look through the “obsolete log” to find earlier iterations of changes. This is similar to (and built on, essentially) git’s reflog that holds on to commits that are no longer in active use.

        There’s also an “operations log” that, instead of tracking history of individual changes, tracks history of the entire repo. So if you reorder or drop changes, you can always undo those operations.

  • steveklabnik a day ago

    Thanks for the feedback! I think these terms are used a bit loosely, even though I try to be precise about it.

    Your mental model sounds decent. I think there’s a few ways to describe things. I like to think of changes as a stable ID for something I want to accomplish, and a commit as the intermediate steps that make up a change. You can kind of think of a change as a branch… but I think that’s stretching it.

    • stavros a day ago

      OK, going through the tutorial again, I think the difference between commits and changes are definitely the thing to focus on. Before your comments, I felt like I was building on a small foundation, because I didn't understand how commits and changes relate, and didn't have a good mental model of them.

      After your comments, the entire tutorial is more solid, but still I feel like I have gaps. My feedback would be to really focus on commits vs changes and define their relationships, what affects them, etc before you go into anything else.

    • stavros a day ago

      Ahh, this really helps. I think you should definitely mention that a change consists of commits (unless it already is and I missed it). This helps because the two questions I had before were "if I change some text, will the change ID change too?" and "does a commit end a change?".

      Clarifying early on what exactly a change ID is, when it changes, and what the relationship between changes and commits is would really help, I think.

lawn 2 days ago

I really like Jujutsu but I went back to Git because there wasn't a Neovim plugin with features comparable to Neogit or Fugitive.

I even started writing one but that was a pretty big project and I lost the motivation for it.

  • steveklabnik 2 days ago

    I’ve heard people say similar things about magit. Tooling matters a lot, for sure.

aos 2 days ago

I’ve started to use jj much more often (and actually used this tutorial to get me started!). I do wish its interaction with Nix flakes is less annoying though, but that’s not the fault jj.

  • spott 12 hours ago

    How is it annoying?

chaostheory 2 days ago

I get that naming is one of the hardest problems in computer science, but naming software after a martial art is just lazy and will lead to problems with things like searches

  • red_admiral 2 days ago

    Like naming your language after a common two-letter verb. At least we can search for 'golang'.

  • riwsky 2 days ago

    If it helps, they actually named it after their desired CLI abbreviation:

    > The command-line tool is called jj for now because it's easy to type and easy to replace (rare in English). The project is called "Jujutsu" because it matches "jj".

    • gcarvalho 2 days ago

      And the martial art is jiu-jitsu, not jujutsu. Similar sounding but definitely not “named after”.

  • stavros 2 days ago

    I guess it's lucky they misspelled it, so there's no conflict.

    • martinvonz a day ago

      I would have spelled it "jiu-jitsu" if I had not looked up the spelling first and found that Wikipedia decided to spell it "jujutsu" (https://en.wikipedia.org/wiki/Jujutsu). Maybe I trusted Wikipedia too much; I have never practiced jujutsu/jiu-jitsu myself.

      • stavros a day ago

        Oh wow, I had no idea, thanks.

ZoomZoomZoom 2 days ago

Would be great if it was Pijul that got Steve's attention. Sometimes it's all you need to achieve a lot.

  • steveklabnik 2 days ago

    I’ll just be honest with you: Pijul never really caught my interest, but I always felt pretty neutral about it until I started noticing the project authors acting very snide and aggressive on here. That is not something I want to be around these days, and so I doubt I’ll ever try Pijul.

    • ZoomZoomZoom 2 days ago

      It's a little surprising to hear, from what I've seen here there's not much besides the usual whiff of academical loftiness, but nothing that I'd qualify as aggression.

      What caught my interest:

      * Separate operations and data

      * Partial repos = no big repo issues, no need for shallow clones and such

      * Proper and easy merging with no shuffled lines

      * Patch-based model is much more intuitive (e.g. rebase and merge are the same operation)

      * Conflict resolutions are stored and can be reapplied!

  • cinntaile 2 days ago

    No updates since March 2024?

drudru 3 days ago

Steve wrote this in a very approachable style. It is the first time I really understood what 'jj' is about. I'm actually kind of excited to start using this tool with my git repos.

  • steveklabnik 3 days ago

    Thanks so much!

    Just want to point out that this hasn’t been updated in a minute, and in particular, you’ll get some messages about branches being bookmarks now: https://github.com/steveklabnik/jujutsu-tutorial/pull/34

    I have started on a second iteration of the tutorial in private, and am gonna see if I can get it in shape this weekend.

    Happy to answer questions about jj!

    • emmelaich 2 days ago

      Does "in a minute" mean "not for a long time"? Because that's how my kids use that phrase.

      English is so great and so confusing!

      • stackghost 2 days ago

        It means both "in a long time" and "in a short time", depending on context and intonation.

    • nchmy 2 days ago

      I've been meaning to figure out JJ for a few months now. Part of why I havent was that your tutorial is a bit out of date. I can't wait for a revamp!

    • drudru 3 days ago

      Thank you Steve! Really enjoying this tutorial. No questions so far.

  • miguelxpn 3 days ago

    No surprises there. Steve has always been a great writer.

leighleighleigh 2 days ago

It's my first time encountering your writing Steve, loved it! Time to give JJ another crack...

cyanf 2 days ago

thank you steve, i’ve been excited for this!

forrestthewoods 2 days ago

I’d love a Sapling vs JJ comparison post. I use Sapling at the day job and… it’s pretty dang good! Although I don’t see how I’d recommend it outside of Meta.

I swear the modern programmer doesn’t realize how extremely bad Git is. It does do a lot of things better than SVN. But it’s a long, long ways from “good” imho.

I blame GitHub. Git didn’t win because it’s good. Git won because GitHub won. If only HgHub had won instead, alas.

My dream VCS system would have a virtual file system, copy-on-write storage, and a system wide blob cache. The goal being to allow open source repos to commit *ALL* their dependencies, up to and including toolchains in many cases.

  • aseipp 2 days ago

    I used Sapling for many months before switching to JJ. In my mind -- and I'm insanely biased as I am a JJ developer at this point -- they are both leagues ahead of Git, but I think JJ's Git interop, conflict handling, and general UX make it much more powerful and general than Sapling. Conflict handling alone is leagues better. (Martin worked on version control for a long time, and JJ is a tool that can only be created by someone with deep expertise in the domain, which I think shows itself over and over again in its use.)

    If you are already using Sapling then at least trying it should be fairly easy and familiar. You could also write a JJ backend for Mononoke and EdenFS if you wanted and then use it at work ;) You wouldn't be the first JJ user from Meta, actually...

    We do have plans to explore server-side designs with virtual filesystems, chunked storage, etc. There's nothing concrete yet.

    (Another benefit is that JJ is much easier to write patches and contribute to due to being a relatively new, small Rust project, whereas Sapling is much more developed but much bigger and harder to get into, I think.)

    • forrestthewoods 2 days ago

      JJ's conflict handling seems nice. Can't say that it's a big enough problem for me to qualify as a "major feature", but a seemingly nice improvement.

      I'm not sure how I feel about JJ's "working copy commit". One of the great things about Meta VCS is that all commits are automatically backed up into the cloud. Which seems incompatible with the JJ model? Not sure. I think the D in DVCS is *wildly* overrated. 99.999% of projects are defacto centralized.

      I'm #TeamMonoRepo 100% of the way. My background is gamedev and perforce. An industry which still uses Perforce because Git is poopy poop poop. The Git integration I want to see is the ability to easily sync a monorepo subfolder with an external GitHub repo. Syncing commits for internal projects that are open sourced requires a big ugly custom set of tooling. And I'd kind of like a way to do an "inner fork" within a monorepo if that makes sense.

      If you're interested here's a pair of blog posts I wrote that have at least some of my thoughts on source control.

      https://www.forrestthewoods.com/blog/dependencies-belong-in-... https://www.forrestthewoods.com/blog/using-zig-to-commit-too...

      • martinvonz 2 days ago

        > JJ's conflict handling seems nice. Can't say that it's a big enough problem for me to qualify as a "major feature", but a seemingly nice improvement.

        The advantages people first think of when they hear about jj's conflict handling are usually that you can collaborate on conflicts and that you can leave conflicts for later. What's less obvious [1] is that being able to store conflicts in commits means that we can always rebase descendants, so there are states like what Mercurial (and Sapling, I think) call "obsolete" and "orphan". There is also no "interrupted rebase" state when you're resolving conflicts.

        These things simplify for the user. They also simplify a lot for developers. An example is how I spent about 2 weeks on a `hg amend --into` command for amending the changes in the working copy into an ancestor. I then implemented that in under an hour in jj. Much of the complexity in hg stemmed from dealing with the interrupted states while dealing with conflicts. (Other complexity in hg that jj doesn't have is dealing with a dirty working copy, dealing with concurrent operations, and simply complexity in the APIs for creating new commits in memory.)

        [1] IIRC, it took me about a year after I added support for "first-class conflicts" until I figured out that it meant that we should simply always rebase descendants. Jujutsu had a orphans and a `jj evolve` command before then.

      • aseipp 2 days ago

        Conflict handling is much more useful whenever you actually have conflicts arising regularly. :) For working on JJ itself, this is super useful because it's still actively having tons of code written by 2-3 people, continuously. In other words, the velocity for newly written code is still very high, internal APIs change breaking PRs, etc. I think how often you handle conflicts in a project has a big number of factors. But JJ really does make conflict handling not 1 but like 3-5 times easier, IMO. So you only really need to do it once to be wow-ed, in my opinion. (One of my previous coworkers said something like, and I quote, "This is fucking awesome.")

        JJ has an abstract notion of a working copy and even an abstract notion of a backend that stores commits. It is a set of Rust crates, and these are interfaces, so you can just implement the interfaces with whatever backend you want. For example, the working copy can be described in terms of the filesystem (POSIX copy/rename/move files around) or in terms of a virtual filesystem (RPC to a server that tells you to make path x/y/z look like it did at version 123.)

        You can absolutely have "cloud commits" like Mononoke/Sapling does, and that is a central feature desired at Google too, where Martin works. Skip to the end of this talk from Git Merge 2024 a few weeks ago, and you can see Martin talk about their version of `jj` used at Google, that interacts with Piper/CitC: https://www.youtube.com/watch?v=LV0JzI8IcCY

        My understanding is that the design works something like this (no promises but we may approximate something like this in JJ itself): A central server (Piper) stores all the data. A local pair of daemons runs on your machine: a proxy daemon that talks with the server on your behalf (is used to reduce RPC latency for e.g. commits and writes, and does asynchronous upload) and a virtual filesystem daemon (CitC). The virtual filesystem daemon manages your working copy. It "mounts" the repository at version 123 (the "baseline version") onto a filesystem directory, by talking to the server. Then it tracks changes to the directory as you update files; sort of like OverlayFS does for Docker.

        When you make a commit, tell the VFS layer to snapshot the changes between your working copy and the baseline, uploading them to the server. Then tell the backend that you've created version 14 out of those files/blobs. The new version 124 is now your new baseline. Rinse and repeat to create version 125, 126, etc...

        The TL;DR on that is the VFS layer manages the working copy. The server/proxy manage interaction with a backend.

        OK, monorepo export of subprojects. For the purposes of exporting monorepo subfolders, I'm actively exploring and thinking about "filtering" tools that can be applied to a commit graph to produce a new commit graph. Mononoke at Meta can do something like this. Check out this tool Josh that does it for native Git repositories: https://josh-project.github.io/josh/reference/filters.html

        The idea is let's say you have commits A -> B -> C and you want to export a repository that only contains a project you want to export, located under paths path/to/oss/thing. You basically sweep the commit graph and only retain commits that touch path/to/oss/thing. If a commit does not touch this path, remove it from the graph and "stitch" the graph back together. If a commit does touch this path, then keep it.

        If a commit touches that path and other paths that don't match, then create a new commit that only touches files under that path. In other words, you might derive a new commit graph A' -> C' where B was thrown away because it touched private code, and A' and C' are "filtered" versions of the originals that retain a subset of their changes. The secret is that this algorithm can be fully deterministic, assuming the input commit graph is "immutable" and cannot be changed.

        This idea actually is kind of like applying a MATERIALIZED VIEW to a database. In fact it could actually be a kind of continuous materialized view where a new derived graph is computed incrementally and automatically. But how do you express the filters? The underlying filter is really a way of expressing a functional map between graphs. So should filters only be bijective? What if they're injective? Etc. I haven't fully figured this out.

        So anyway, I've never really worked in gamedev or huge monorepo orgs before, but these are all problems I've acutely felt, and Git never really solved. So, I can say that yes, we are at least thinking about these things and more.

        • forrestthewoods 2 days ago

          > whenever you actually have conflicts arising regularly.

          I mean I work at Meta. We have lots of people working on stuff at the same time. :) AraxisMerge auto-merges quite nicely. Text conflicts have just never been a meaningful issue for me in my 15+ year career.

          Now binary conflicts are a source of pain! Unfortunately require Perforce style file-locking once you hit a team size.

          > I've never really worked in gamedev or huge monorepo orgs before, but these are all problems I've acutely felt, and Git never really solved. So, I can say that yes, we are at least thinking about these things and more.

          Good to hear! Yeah the workflow for subproject syncing it's super obvious. It definitely can be done but will require a lot of thinking and a few iterations.

itohihiyt 2 days ago

Came here for a martial arts tutorial, which I thought was a bit weird to see front page on HN, and now I see an alternative to git.

I don't particularly like git and for personal projects use fossil instead.

Without going through the whole tutorial, and doing a lot more reading, why should I consider using this over fossil?

  • abc123abc123 2 days ago

    Interesting. I'm not a professional developer and also love fossil for toy/hobby projects. I find it fascinating that this well crafted, solid piece of software is so forgotten, and that git has just rolled over everything.

    • otherme123 2 days ago

      Same here, the fact that it includes bug tracker, web UI and wiki/docs is a huge plus.

    • thiht 2 days ago

      Honestly you could sell me the best alternative to Git that exists and I still wouldn’t switch, or even try it. I don’t care enough about my versioning system to use something else than what everybody uses. Ubiquity beats convenience.

      What I care about is the tooling around it: GitHub and its ecosystem mainly. I also want my open source projects to be on GitHub specifically, and I don’t want to ask contributors to use something other than Git.

      • steveklabnik 2 days ago

        Totally respect you wanting to not care about tools, but for the latter part, I do agree with you, which is why I like jj: it uses a git repo as its backing store, so your projects can live on GitHub and all the rest of your collaborators can use git. Nobody else needs to know or care.

        • thiht 2 days ago

          Wow I’ve heard about jj multiple times before but didn’t realize it was compatible with Git. You got me interested in just 1 sentence, nicely done!

          Well, guess I’m on my way to read the tutorial.

          • steveklabnik 2 days ago

            Glad to hear it! It’s a killer feature, for sure.

  • tmtvl 2 days ago

    Yeah, I was also wondering 'Traditional JJ or BJJ?'

    I've never really messed around with VCSes other than git and Subversion, there's people who really like Mercurial though, so I wonder how jj compares to that.

  • kettleballroll 2 days ago

    Same. I miss the old times when people tried naming their projects sensibly. I mean, we're constantly telling ourselves how variable and function names should speak for themselves, but then we name our projects using random, completely non-descript names. It's a annoying.

    • chronial 2 days ago

      Which old times are you referring to / what are "sensible" names?

      I thought about it and I don't know what a better name would be. Off the top of my Head, I know Perforce, BitWarden, Subversion, fossil and git. And then the abbreviations CVS, RCS and SVN.

      Do any of these qualify as a descriptive name?

      • itohihiyt 2 days ago

        As a British national I like to think git is a very descriptive name, because git is a git to use and understand.

        • batch12 2 days ago

          For a US southerner it works too. We can use the tool to 'git' our code.

      • phrenq 2 days ago

        At one point in my career, I used Microsoft SourceSafe, which is a pretty descriptive name. Seems like the exception here, though.

      • kettleballroll 2 days ago

        I don't just mean version control systems, but since you mentioned them: CVS (concurrent version system), rcs (revision control system) and subversion all seem fairly descriptive to me?

red_admiral 2 days ago

I expected actual Jujutsu :)

I recommend looking up Bartitsu (that Conan Doyle spelled Baritsu), a short-lived but very interesting martial art.

38 2 days ago

Jujutsu is terrible in my opinion. people hate the index, but I think they just dont get it. to me a commit is something that is ready to push, and the index is for stuff that is done but not ready to push. just because I wrote one line that I am happy with, doesn't mean I am ready to commit and push that. I prefer to add stuff thats done, then when enough is done I can commit and push. if you remove the index it makes it too easy to push half done stuff

  • steveklabnik 2 days ago

    I like jj because I like git's index so much. JJ lets me do what git's index does, but in a much more powerful way.

    What you do is, you treat @ like the index, and you work on @-. This is the "squash workflow" https://steveklabnik.github.io/jujutsu-tutorial/real-world-w...

    • 38 2 days ago

      OK but again thats awful, because @ IS A COMMIT, so you are only a "git push" away from accidentally pushing arbitrary garbage instead of proper changes

      • nasso_dev 2 days ago

        Actually, `jj git push` will only push named branches, which are now called "bookmarks".

        You simply don't attach a bookmark to @, and `jj git push` will NEVER push it (to what branch would it push?)

        The branch you're working on is instead on @-. So when you squash, it updates the branch.

      • abhinavk 2 days ago

        You need to think commits as of a non-depleting commodity. And named-branches (bookmarks) as something that is explicitly set to newer commits/changes.

      • aseipp 2 days ago

        You are simply misinformed. `git push` always pushes the HEAD by default without question, but jj does not. @ is not special in any way, so it does not get special treatment from push. It will only push branches you tell it to or that have been amended/updated and are not immutable. jj also does not update any branch pointers (or "bookmarks" as we call them) unless you explicitly ask it to. You have to explicitly run `jj branch set ...` and then run `jj git push` to get the behavior you are describing, which is much more explicit.

    • 38 2 days ago

      [flagged]

      • steveklabnik 2 days ago

        https://steveklabnik.github.io/jujutsu-tutorial/hello-world/...

        > The very first character at the top left is an @. @ is a special name for "whichever commit the working copy reflects." At first I kind of thought about it like HEAD in git, but that's not correct: HEAD is the most recent commit, but @ represents the working copy, which may be "dirty" from git's point of view. This is our first glimpse into the power of the index-less workflow, though we'll explore that fully in the next chapter. For this moment, just realize that we have one less concept, but haven't actually lost any of its power.

        • 38 2 days ago

          OK but again thats awful, because @ IS A COMMIT, so you are only a "git push" away from accidentally pushing arbitrary garbage instead of proper changes

          • phildenhoff 2 days ago

            Bookmarks in JJ are closer to tags than branches. They aren’t updated whenever you add new commits on top of the bookmark.

            If you assign your bookmark to the current commit, yes, and I have done that before. But it’s very easy to not do that, and if you push the wrong commit (a WIP commit, let’s say) you can reassign the bookmark and then push again. It’s not a big deal to push arbitrary garbage to the remote if you do, and it’s not common that I do.

            On the flip side, jj has been remarkably useful at ensuring I never ever, ever lose any of my work. Ever. It’s not an issue that often, but when it is, oh thank god

          • jolux 2 days ago

            No, because `jj git push` only pushes bookmarks. If you `jj git push -c @` or create a bookmark, yeah, you will push the current commit, but then you're asking for that pretty explicitly.