6 ms·
I've been waiting for the server-side of things to be open-sourced ever since this announcement. In the meantime, I've been enjoying jj/jujutsu (https://github
by Yasuraka 2y ago
I've been waiting for the server-side of things to be open-sourced ever since this announcement.
In the meantime, I've been enjoying jj/jujutsu (https://github.com/martinvonz/jj https://github.com/martinvonz/jj), which started as a 20% project and has been out (and developed) in the open ever since.
An introduction by Chris Krycho for those familiar with some form of vcs: https://v5.chriskrycho.com/essays/jj-init/ https://v5.chriskrycho.com/essays/jj-init/
"Jujutsu brings to the table a few key concepts — none of which are themselves novel, but the combination of which is really nice to use in practice:
Changes are distinct from revisions: an idea borrowed from Mercurial, but quite different from Git’s model.
Conflicts are first-class items: an idea borrowed from Pijul and Darcs.
The user interface is not only reasonable but actually really good: an idea borrowed from… literally every VCS other than Git."
- riedel 2y agoThanks, looks great. Found this comparison: https://martinvonz.github.io/jj/latest/sapling-comparison/ https://martinvonz.github.io/jj/latest/sapling-comparison/ Will try it for sure.
- eterps 2y agoAlso check out lazyjj: https://github.com/Cretezy/lazyjj https://github.com/Cretezy/lazyjj
- 0cf8612b2e1e 2y agoThe readme did not make it clear: does this have a TUI workflow for moving line chunks around? That is my one reluctance towards jj is that my (bad practices?) frequently have me touch a few different unrelated bits simultaneously (eg editing foo, but fix a typo in bar) which I use stage to iteratively commit. From the jj stuff I have read thus far, my workflow would be a bit clunky to adapt.
- steveklabnik 2y ago> frequently have me touch a few different unrelated bits simultaneously (eg editing foo, but fix a typo in bar) which I use stage to iteratively commit. From the jj stuff I have read thus far, my workflow would be a bit clunky to adapt. I do this too! I find it easier in jj than in git. I wrote out a lengthy thing about the "oh I found a typo" use case here: https://lobste.rs/s/yjqd6d/against_names#c_7yfw7g https://lobste.rs/s/yjqd6d/against_names#c_7yfw7g
- 0cf8612b2e1e 2y agoThanks for the write up, but that’s a bit more care and thought than I usually have. The outlined workflow is more, “I see a second change I need to do how should I prep for it”. Whereas I am more likely to do a bunch of work and try to separate it later. Again, not defending my workflow, just what I end up doing. The other response with the ‘jj split’ example is exactly the kind of workflow I envisioned where you can supposedly move the chunks between commits.
- steveklabnik 2y agoAhh yeah, if you want to take things apart after the fact, split is what you want. No need to be defensive about workflows! The fact that you don’t need to plan ahead is a strength of a tool, in my mind, not a weakness. Nobody would claim that someone is a bad engineer for saving a file when their work is in progress, and the same is true for version control as far as I’m concerned.
- aseipp 2y ago`jj split --interactive` is built in, and will handle that exact case for you. It also comes with a built in TUI so you can select lines right from the terminal immediately. You can even do `jj split --parallel` which will not only split the changes into two commits, but then make the commits siblings (instead of child/parent), so you can immediately push things if they're easy fixes. I have a base of B with my commit @ that contains a bunch of changes. B --> @ `jj split` will give me this graph, where `X` contains the changes I selected, and `@` contains all the changes I didn't select: B --> X --> @ Instead, if I did `jj split --parallel`, I would get this: B --> @ \ --> X Let's say `X` is a typofix and @ contains your feature you're not done with yet. OK, just run `jj git push -c X` and jj will create a branch name for you, and push it to the remote for code review. Done. You don't have to switch branches or do anything. You basically can just stop thinking about X since it will probably get merged.
- 0cf8612b2e1e 2y agoGreat visual and I will definitely have to check it out now.
- aseipp 2y agoThe server-side IS open source -- it's basically been in the source tree since day 1, but "inert" due to facebook-only dependencies that made the code unusable, but most of the stuff was actually there if you were willing to dig deep. And actually, they just recently said it became "usable for unsupported experimentation"[1], so it's been on my TODO list to give Mononoke a run and see how it operates. Unfortunately the builds for Mononoke are not actually uploaded on GitHub due to a bug in the GHA setup[2] that I reported :') [1] https://github.com/facebook/sapling?tab=readme-ov-file#mononoke https://github.com/facebook/sapling?tab=readme-ov-file#monon... [2] https://github.com/facebook/sapling/issues/922 https://github.com/facebook/sapling/issues/922
- smaudet 2y ago> Conflicts are first-class items I have less experience working in large (heavily tracked active, e.g. 1k+ committers) repos, however we try to keep conflicts to a minimum - of course you can't get rid of them completely, normally merge/rebase I have close to zero conflicts on the regular, or those that I have are automatically (non-ai) merged (correctly). I suppose I find the idea of conflicts as first class entities as somewhat intriguing, do they function as a sort of super-feature? If e.g. you have 10 features all touching the same area of code, then do you get maybe 3 combined conflict(ing) features? At any rate, I think while it might be a useful metric, there should be an aim to keep conflicts to an absolute minimum....
- steveklabnik 2y agoOne thing that "conflicts as first class items" implies is that commits can exist in a conflicted state. This implies that you don't have to deal with conflicts right away. Let me explain. jj's rebase works just like git's rebase conceptually: take these commits and move them on top of some different commits. But unlike git, `jj rebase` will aways succeed, and succeed immediately. The resulting rebased commits/changes will just be in a conflicted state if a conflict happens. This decouples the "do the rebase" from "fix the conflicts" in time, meaning I can choose if I want to handle them right away or later. This ends up being very powerful in a few ways: for one, because it will always succeed, and succeed quickly, we can start automatically rebasing. Let's say you have a branch with three changes on it. You go back and edit the first change, because you forgot to do something. jj will then automatically rebase the two children, and you immediately see if you've introduced a conflict. You can then fix it right now, or you can continue working on change #1, until you're ready to address the conflict. Let's say you decide to do that, and the conflict originates in change #2: when you fix that conflict, #3 gets rebased again, and in this hypothetical story, the conflict goes away. It's also nice if you have a bunch of outstanding work, and you want to rebase it all on top of your latest trunk/main/master branch: run the command to do so, and it'll all get rebased right away, and you can immediately see what has a conflict and what doesn't, and fix them when you feel like it, rather than doing it right now just so that the command completes. There are secondary advantages, like the fact that this means rebases can happen in-memory, rather than through materializing files. This means it's super fast, and doesn't interrupt what you're doing. But I think those kinds of things are harder to grok than the workflow improvements.
- dsissitka 2y agoHow does https://martinvonz.github.io/jj/latest/FAQ/#can-i-prevent-jujutsu-from-recording-my-unfinished-work-im-not-ready-to-commit-it https://martinvonz.github.io/jj/latest/FAQ/#can-i-prevent-ju... work in practice? It feels like you'd end up with a bunch of junk in your repo.
- steveklabnik 2y agoIn practice, for more "modern" projects, it works fine: they tend to have good hygiene anyway. For Rust projects, for example, you .gitignore the target directory, and you're good for 99% of projects (and cargo new already generates said ignore.) For older projects that leave temporary files everywhere, or for workflows that may generate intermediate files (like coredumps are often generated in the cwd and not somewhere easily ignored), it can be a pain. However, in the next release, a feature related to this has landed: you can add a configuration, `snapshot.auto-track="none()"`, to turn off automatically tracking files, and then `jj track` individual paths (with globs, of course), if you prefer that workflow.
- aseipp 2y agoIt basically works fine, but there are some annoying edge cases that even I, a jj developer, have run into. Probably the most "common" one (and it's not that common, just moreso than the rest) when you switch branches with different `.gitignore` files, you may stop ignoring some junk from the other branch when you switch. Kind of annoying. But it's overall pretty marginal in projects with good ignore hygiene, and there are solutions to that problem too (to varying degrees of ease.)