Jujutsu – A Git-compatible DVCS that is both simple and powerful

This page summarizes the projects mentioned and recommended in the original post on news.ycombinator.com

Our great sponsors
  • InfluxDB - Power Real-Time Data Analytics at Scale
  • WorkOS - The modern identity platform for B2B SaaS
  • SaaSHub - Software Alternatives and Reviews
  • jj

    A Git-compatible VCS that is both simple and powerful

  • > For example, "when the working copy is automatically committed," where does it go?

    It becomes a regular git commit with a git ref called something like `refs/jj/keep/9f1a0fb0-a0aa-4a4b-922f-d6d48687996a` pointing to it (to prevent GC). It won't get fetched or pushed by default, except with `--mirror`, I think.

    > If I'm hacking on an ffmpeg script and I (temporarily) copy a 4GB mp4 file into the working directory so I can easily run `./mycode video.mp4`

    Yes! You'll have to more diligent about keeping your .gitignore (or .git/info/exclude, etc) file updated. I plan to add commands for fixing such mistakes by forgetting the commit.

    > Do you have to use the jj backend to get all the feature?

    Nope, conflicts work with the git backend as well. https://github.com/martinvonz/jj/blob/main/docs/git-compatib... has some info.

    > To sum up my comment in a TL;DR: To really sell me on a project like this it has to work with git, and being able to quickly tell which features I can use with git, would make this substantially more interesting to me.

    Makes sense. Thanks for the suggestion! I'll put it on my TODO list.

  • pre-commit

    A framework for managing and maintaining multi-language pre-commit hooks.

  • > But that's what they've tested.

    https://pre-commit.com/ helps with that.

    > It would be quite fun if we could have hierarchical commits, so I could add bits to a commit without having to squash/amend.

    Yes! I've been saying this for years.

    Branch merge commits are already this, kind of. However their UI sucks and there's an idea gap which prevents them from being fully understood as such "supercommits" composed of subcommits.

    For one, the user should be forced to give meaningful, high level commit messages for merge commits and the tooling should fold commits made on a merge branch into the merge commit by default (effectively linearizing the merged history).

  • InfluxDB

    Power Real-Time Data Analytics at Scale. Get real-time insights from all types of time series data with InfluxDB. Ingest, query, and analyze billions of data points in real-time with unbounded cardinality.

    InfluxDB logo
  • Git

    Git Source Code Mirror - This is a publish-only repository but pull requests can be turned into patches to the mailing list via GitGitGadget (https://gitgitgadget.github.io/). Please follow Documentation/SubmittingPatches procedure for any of your improvements.

  • It's doing something weirder than that, but I think that "it applies a diff between a specified commit and its parent on top of your current work" is more accurate/intuitive than "it does a three-way merge with a common ancestor".

    The first hint that it's doing something interesting is that the implementation of cherry-pick is in revert.c, because it's implemented as a variant of revert: https://github.com/git/git/blob/v2.35.1/builtin/revert.c#L23...

    Both the "revert" and "cherry-pick" operations initialize a sequencer object with a single operation in the sequence. (This is the same mechanism underlying "git rebase -i").

    From there we can find the call to sequencer_pick_revisions, which leads us to the sequencer implementation, where there's a fast-path for ordinary cherry-picks leading us to a short function single_pick, which in turn calls do_pick_commit: https://github.com/git/git/blob/v2.35.1/sequencer.c#L2066

    This operation then does the following:

    - Determine what we're applying a diff on top of: https://github.com/git/git/blob/v2.35.1/sequencer.c#L2083-L2...

    - Find a parent commit. If the commit has more than one parent, it requires you to specify a "-m" option indicating which parent to diff against. https://github.com/git/git/blob/v2.35.1/sequencer.c#L2109-L2...

    - Set up the commit message and some other stuff.

    - Set the variable "base" to the parent it found and "next" to the commit being cherry-picked. https://github.com/git/git/blob/v2.35.1/sequencer.c#L2187-L2...

    - Assuming no merge strategy (or either of the standard strategies "ort" or "recursive") was specified on the command line, call do_recursive_merge. https://github.com/git/git/blob/v2.35.1/sequencer.c#L2237-L2...

    In turn, do_recursive_merge calculates a head_tree from the current HEAD (https://github.com/git/git/blob/v2.35.1/sequencer.c#L645), and then calls either merge_incore_nonrecursive (the current default, from the new "ort" merge strategy) or merge_trees (from the older "recursive" merge strategy) with three trees (i.e., with no further ancestry information): the base is the parent it found, and the two sides being merged are your current HEAD and the (tree of) the commit being cherry-picked.

    That is to say, at no point does it care whether the two commits even have a common ancestor! It's just doing an operation on trees. It is doing a three-way merge, yes, but the graph of the merge it's doing is one that potentially doesn't actually exist in reality.

    Or, in other words, it's trying to compute the tree that could be equally well described as the result of

    - applying the diff of the commit you're cherry-picking to your current HEAD

    - applying the diff between your current HEAD and the parent of the commit you're cherry-picking to the commit you're cherry-picking

    So this is more powerful than purely applying a diff with no information about the base of the diff, but it is very much like applying a diff.

    One way you can test this without drilling into source code is to make two independent commit histories (using either two git repos, or git checkout --orphan, or whatever) where a commit in one history has a diff that would apply to a file in the other history if applied with the "patch" command. Then try cherry-picking it into the second history. It should work.

  • git-imerge

    Incremental merge for git

  • That gist seems like a simplified version of https://github.com/mhagger/git-imerge, so check that out if you haven't. (I haven't looked at git-imerge in a long time, so I should read about it again myself.)

NOTE: The number of mentions on this list indicates mentions on common posts plus user suggested alternatives. Hence, a higher number means a more popular project.

Suggest a related project

Related posts