Google Backs Jujutsu VCS to Replace Mercurial Across Monorepo

Jujutsu: A Git-Compatible VCS - Git Merge 2022 — GitHub

GitHub

By storing unresolved conflicts inside commit metadata and treating the working copy as an automatic commit, Jujutsu eliminates rebase aborts while preparing Google to unify engineering workflows into a single cloud-hosted commit graph.

AI-assisted summary of Jujutsu: A Git-Compatible VCS - Git Merge 2022 — original source. Check the original for full context.

Source published:

Key ideas

  • Google is transitioning internal source control from Fig (a Mercurial wrapper) to Jujutsu (jj), an open-source, Git-compatible DVCS written in Rust and led full-time by Martin von Zweigbergk. (4:21)
  • Jujutsu eliminates dirty working copies and the Git staging area by modeling the working copy as an ordinary commit that automatically amends on every CLI invocation. (6:11)
  • Merge and rebase operations in Jujutsu never fail on conflicts; instead, conflicts are stored as structured metadata inside commits, enabling delayed resolution and automatic rebasing of descendant commits. (9:43)
  • An Operation Log records whole-repository snapshots on every command, enabling repository-wide undo, time-travel inspection, and crash-resilient multi-device synchronization. (15:31)
  • Google's internal deployment roadmap aims to store developer commits in a single centralized cloud graph using lazy indexing (inspired by Meta's segmented changelog) and virtual file system mounts. (29:35)

Detailed notes

## Background Published on YouTube by GitHub on October 18, 2022, this video captures a presentation from Git Merge 2022 delivered by Google engineer Martin von Zweigbergk on Jujutsu (jj), a Git-compatible version control system. According to the description, the session explores Jujutsu's design and features—including anonymous branches, first-class conflicts, automatic descendant rebasing, and treating the working copy as an automatic commit—alongside Google's long-term deployment plans.

## TL;DR Martin von Zweigbergk outlines the evolution of source control at Google and how the performance and consistency limitations of Fig (a Mercurial wrapper) led to the development of Jujutsu (jj). He highlights core UX innovations, such as treating the working copy as an auto-amending commit, handling conflicts as first-class metadata rather than workflow-stopping failures, and recording whole-repository state transitions in an Operation Log for effortless inspection and undo. Implemented as a modular Rust library, Jujutsu delivers Git compatibility while enabling automatic rebasing of descendant stacks. Finally, von Zweigbergk discusses missing features like copy tracking and blame, alongside Google's roadmap to deploy Jujutsu on top of its monorepo using lazy commit indexing and cloud storage backends.

## Atmosphere & style The presentation has the calm, deliberate atmosphere of a seasoned infrastructure engineer sharing a passion project that organically evolved into a core corporate initiative. Von Zweigbergk speaks with understated humor and technical modesty, opening with a dry clarification about the name's non-relation to anime and openly dissecting early architectural missteps. It feels deeply practical and grounded, giving version control practitioners an authentic look behind the curtain of developer tooling and large-scale repository engineering.

## Bulletin - [04:21](https://www.youtube.com/watch?v=bx_LGilOuE4&t=261s) Google is transitioning internal source control from Fig (a Mercurial wrapper) to Jujutsu (jj), an open-source, Git-compatible DVCS written in Rust and led full-time by Martin von Zweigbergk. - [06:11](https://www.youtube.com/watch?v=bx_LGilOuE4&t=371s) Jujutsu eliminates dirty working copies and the Git staging area by modeling the working copy as an ordinary commit that automatically amends on every CLI invocation. - [09:43](https://www.youtube.com/watch?v=bx_LGilOuE4&t=583s) Merge and rebase operations in Jujutsu never fail on conflicts; instead, conflicts are stored as structured metadata inside commits, enabling delayed resolution and automatic rebasing of descendant commits. - [15:31](https://www.youtube.com/watch?v=bx_LGilOuE4&t=931s) An Operation Log records whole-repository snapshots on every command, enabling repository-wide undo, time-travel inspection, and crash-resilient multi-device synchronization. - [29:35](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1775s) Google's internal deployment roadmap aims to store developer commits in a single centralized cloud graph using lazy indexing (inspired by Meta's segmented changelog) and virtual file system mounts.

## Key takeaways - [01:20](https://www.youtube.com/watch?v=bx_LGilOuE4&t=80s) Google's prior DVCS tooling, Fig, suffered from Python performance bottlenecks, lack of distributed file system consistency, and brittle CLI output parsing. - [04:21](https://www.youtube.com/watch?v=bx_LGilOuE4&t=261s) Jujutsu was developed as an independent VCS rather than upstream Git patches to freely explore radical UX changes and avoid ecosystem incompatibilities with internal Google tools. - [06:11](https://www.youtube.com/watch?v=bx_LGilOuE4&t=371s) Anonymous branches track all commits by default without requiring explicit branch names, hiding obsolete revisions automatically when rewritten. - [07:30](https://www.youtube.com/watch?v=bx_LGilOuE4&t=450s) Treating the working copy as a regular commit (@) renders commands like git stash and git commit obsolete while keeping the CLI uniform. - [09:43](https://www.youtube.com/watch?v=bx_LGilOuE4&t=583s) First-class conflicts are recorded directly inside commit objects as metadata rather than raw file markers, eliminating rebase abort/continue states and enabling asynchronous team resolution. - [12:45](https://www.youtube.com/watch?v=bx_LGilOuE4&t=765s) Because rebasing never fails due to conflicts, Jujutsu automatically rebases entire stacks of descendant commits whenever an ancestor commit is updated or amended. - [13:46](https://www.youtube.com/watch?v=bx_LGilOuE4&t=826s) The jj move command allows arbitrary transfer of diffs between commits, such as moving a conflict resolution directly into the originating commit. - [14:35](https://www.youtube.com/watch?v=bx_LGilOuE4&t=875s) Rebasing merge commits recalculates the resolution diff against auto-merged parents, preserving conflict resolutions cleanly across history rewrites. - [15:31](https://www.youtube.com/watch?v=bx_LGilOuE4&t=931s) The Operation Log snapshots the entire repository state—including branches, commits, and working copy locations—allowing point-in-time inspection (--at-op) and surgical operation undos. - [18:32](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1112s) Jujutsu's strict transaction model commits state append-only to the Operation Log, preventing repository corruption during crashes or across cloud-synced folders like Dropbox. - [19:53](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1193s) Implemented as a modular Rust library rather than a monolithic CLI, Jujutsu features pluggable commit storage and working copy backends designed for lazy evaluation at scale. - [22:29](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1349s) Operations are executed repository-first in the object database before mutating files on disk, significantly cutting disk I/O and network latency. - [24:10](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1450s) Full Git interoperability allows developers to adopt Jujutsu inside existing Git projects and collaborate seamlessly with peers using standard Git. - [25:35](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1535s) Jujutsu incorporates Mercurial's revset functional revision syntax and advanced history manipulation tools like split, fold, and non-linear rebases. - [27:45](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1665s) Key missing features currently include explicit rename/copy tracking (versus Git's heuristic detection), git blame equivalent tooling, and network sync for the native backend. - [29:35](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1775s) Google's internal enterprise plan integrates Jujutsu with a custom VFS and cloud storage to connect developer workspaces and cloud IDEs into a single shared commit graph.

## Detailed walkthrough ### [00:08](https://www.youtube.com/watch?v=bx_LGilOuE4&t=8s) Introduction to Jujutsu (jj)

Martin von Zweigbergk introduces himself at Git Merge 2022, briefly searching for his speaker notes before diving in. He explains that he works on source control at Google and has spent nearly three years developing Jujutsu (abbreviated as `jj`), a Git-compatible version control system (VCS). Addressing an obvious pop-culture question with a dry chuckle, he clarifies that the project has no relation to the anime *Jujutsu Kaisen*. Instead, the name comes from the CLI command `jj`, which was chosen simply because it is easy to type.

```mermaid flowchart TD accTitle: History of Source Control at Google accDescr: Evolution of internal version control tooling at Google leading to the creation of Jujutsu. subgraph Monorepo Evolution CVS["CVS (early days)"] --> P4["Perforce"] P4 --> Piper["Piper (in-house VCS)"] Piper --> CitC["CitC (Cloud Storage FUSE)"] end subgraph DVCS & Next-Gen CitC --> Fig["Fig (Mercurial wrapper)"] Fig --> JJ["Jujutsu / jj (Next-Gen VCS)"] end ```

Martin presents an agenda for the talk covering his background, the history of source control at Google, the core workflows and architecture of Jujutsu, and the upcoming plans for both the open-source project and its integration within Google.

[01:20](https://www.youtube.com/watch?v=bx_LGilOuE4&t=80s) Source Control History at Google and Fig’s Limitations

Martin recounts his career path: after graduating, he worked at Ericsson for roughly seven years. While there, he spearheaded their migration from ClearCase to Git and spent his personal time cleaning up Git rebase scripts. After joining Google, he worked briefly on a compensation app before spending the next eight years working on Fig, an internal client that wraps Mercurial to interface with Google's massive monorepo.

To give context, Martin summarizes Google’s source control journey. In the early days, the company supposedly started with CVS, later migrating to Perforce. When the Perforce server could no longer scale to Google's massive codebase, Google engineered its own centralized VCS called Piper. Because the repository was far too vast for a developer's physical disk, they created CitC (Clients in the Cloud), a virtual file system mounted on top of Piper that nearly every Googler uses. However, engineers coming from outside Google deeply missed the distributed version control (DVCS) workflows they were accustomed to, which led to the creation of Fig to bring Mercurial workflows on top of CitC. Those curious about the monorepo's sheer scale can refer to the *@Scale* presentation by Rachel Potvin and Josh Levenberg.

While engineers generally like Fig, Martin highlights three severe pain points: - **Performance:** Python is slow, and eager data structures fail to scale to the size of Google's monorepo. - **Consistency:** Mercurial was never designed for distributed file systems, leading to write races and repository corruption when stored across Google's distributed infrastructure. - **Integration complexity:** Fig relies on shelling out to the Mercurial CLI and parsing its text output, which Martin describes as decidedly “not fun.”

[04:21](https://www.youtube.com/watch?v=bx_LGilOuE4&t=261s) The Genesis of Jujutsu and Why Not Just Git

A few years ago, the team began brainstorming requirements for a next-generation version control system. One idea that surfaced was automatically creating a commit on every single editor save. Martin was captivated by the concept: “I got really excited by that idea and started jj to experiment with it.” He worked on Jujutsu as a 20% project for about two years. By spring 2022, Google decided to invest more heavily, making it Martin's full-time (100%) project.

Martin explains why he chose to create a new VCS rather than submitting these features to upstream Git. His primary goal was to experiment with a fundamentally different user experience: “I think that would end up being a completely separate set of commands inside of Git and that would be really ugly and wouldn't and shouldn't get accepted upstream.” Furthermore, Git integration was historically ruled out for Fig because of deep ecosystem incompatibilities at Google. Multiple internal tools reimplement Git by reading directly from the file system, which meant any novel feature added to Git would have to be duplicated across two or three separate internal implementations.

[06:11](https://www.youtube.com/watch?v=bx_LGilOuE4&t=371s) Anonymous Branches and the Automatic Working Copy Commit

Turning to user-facing workflows, Martin highlights the first major feature borrowed from Mercurial: anonymous branches. Instead of throwing developers into Git's notoriously intimidating detached `HEAD` state, Jujutsu tracks all commits without forcing the user to name them with branches. Commits appear cleanly in the log output and are never garbage collected accidentally. To prevent the log from becoming an unreadable mess, Jujutsu automatically hides the old versions of commits whenever they are rewritten (via amend or rebase). Developers can also manually hide commits using `jj abandon`.

```mermaid flowchart LR accTitle: Working Copy as a Commit accDescr: Comparison of Jujutsu automatic commit model versus Git staging workflows. subgraph JJ Model WC["Working Copy (@)"] -->|"auto-amends on edit"| WC WC -->|"jj checkout"| NewC["New Commit (@)"] OldC["Existing Commit"] -->|"jj edit"| OldC end ```

The second core realization when using Jujutsu is that the working copy is itself an actual commit, displayed in `jj log` with an `@` symbol. Every file modification in the working copy is automatically amended into this `@` commit whenever any `jj` command is executed. - Running `jj checkout <commit>` creates a brand new working copy commit on top of the target commit. - Running `jj edit <commit>` switches the working copy commit directly to an existing commit so the user can continue amending it in place.

This fundamental architectural choice eliminates several major Git pain points: - **No dirty working copies:** “The working copy will never be dirty, so if you check out a different commit or rebase or something, it will never tell you that you have unstaged changes.” - **Automatic backup:** Every invocation of a `jj` command creates an automatic backup commit of your current state. - **`git stash` is obsolete:** The working copy commit already acts as an ongoing, persistent stash. - **`git commit` is unnecessary:** Changes are already committed; setting or modifying a commit message is handled whenever convenient via `jj describe`. - **A uniform CLI:** The `@` commit is a standard commit, eliminating arbitrary flags needed to target unstaged files. For instance, `jj restore` defaults to restoring files from `@`'s parent into `@` (matching `git restore`), but can take any arbitrary pair of commits. - **Changes stay put:** Uncommitted edits do not inadvertently travel with the user across branches during checkouts.

[09:43](https://www.youtube.com/watch?v=bx_LGilOuE4&t=583s) First-Class Conflicts and Automatic Descendant Rebasing

Another defining architectural pillar of Jujutsu is first-class conflicts. In Jujutsu, operations like `jj merge` or `jj rebase` never fail when a conflict occurs. If a merge encounters conflicting changes, the operation succeeds completely, creating a merge commit that stores the conflicts as structured metadata directly in the commit object itself—rather than injecting raw conflict markers into files and halting the world.

Martin details the major advantages of this design: - **Delayed conflict resolution:** Developers are free to ignore a conflict immediately after a merge or rebase, check out another commit, and resolve the conflicts hours or days later. - **Collaborative resolutions:** Because conflicts are committed, developers can push them to a remote branch, resolve a subset of files, and let a teammate resolve the rest. - **No interrupted state commands:** “A rebase never fails... which makes continue and abort and for rebase and cherry-pick and all those similar commands unnecessary.” - **Unified conflict flow:** Users do not need to memorize whether a conflict was caused by a cherry-pick, merge, or rebase. They simply edit the conflicted commit, fix the files in their working copy, and the conflict indicators disappear automatically from the log.

Martin notes that it took him a year of experimentation to realize the ultimate payoff of non-failing operations: because rebasing never fails, Jujutsu can automatically rebase all descendant commits whenever an ancestor in a stack is amended or edited. Users no longer need to manually orchestrate complex interactive rebases to propagate changes through a stack of dependent patches; `jj` handles the whole cascade, sliding branches along automatically. Furthermore, Jujutsu can even rebase existing conflicts and their recorded resolutions onto new bases, preserving work in progress across evolving branches.

[13:46](https://www.youtube.com/watch?v=bx_LGilOuE4&t=826s) Moving Changes and Rebasing Merges Correctly

When conflict resolution happens in the working copy (which behaves like an automatic commit), that resolution is carried along when the commit is rebased, preventing conflicts from polluting the working copy. Jujutsu offers a dedicated command to manipulate where these diffs live: `jj move` (or `jj move --to`). Martin von Zweigbergk compares it to the squash workflows discussed earlier at the conference, “but much more generic you can can move a change from any commit into any other commit.” By default, without a `--from` flag, it pulls the changes directly from the working copy into the specified target. In his demo walkthrough, moving the resolution into the initial conflicting commit clears the conflict across the entire stack, leaving the working copy clean and empty.

Von Zweigbergk also explains how Jujutsu handles merges during history rewrites. Instead of breaking merge resolutions during a rebase, `jj` rebases merges cleanly by computing the diff between the merge commit and its auto-merged parents, and then applying that diff onto the new auto-merged parents. This principle is not reserved solely for rebasing; Jujutsu treats all diffs and inspection commands on merge commits this way, auto-merging the parents just like the merge-diff concepts discussed by Elijah Newren earlier in the day.

```mermaid flowchart LR accTitle: Rebase Merge Architecture accDescr: Diagram showing how Jujutsu rebases a merge commit by calculating the resolution diff against auto-merged parents and applying it onto new auto-merged parents.

subgraph OriginalState["Original State"] P1["Parent 1"] & P2["Parent 2"] --> AutoMerge["Auto-merged Parents"] AutoMerge -->|"Diff (Conflict Resolution)"| MergeCommit["Merge Commit"] end

subgraph NewState["Rebased State"] NewP1["New Parent 1"] & NewP2["New Parent 2"] --> NewAutoMerge["New Auto-merged Parents"] NewAutoMerge -->|"Apply Same Diff"| RebasedMerge["Clean Rebased Merge"] end

OriginalState -.->|"Rebase diff onto new parents"| NewState ```

[15:31](https://www.youtube.com/watch?v=bx_LGilOuE4&t=931s) The Operation Log: Repository State as Version Control

The final major feature highlighted is the Operation Log (op log). Von Zweigbergk suggests that “you can think of it as the entire repo being under Source control.” Unlike Git's reflogs, which track individual branch pointers independently, Jujutsu's Operation Log tracks the entire state of the repository at once—including all references, anonymous heads, and the exact position of the working copy across every worktree. Each operation snapshot records operational metadata, such as the timestamp, username, and hostname where the action was executed.

Because the repository is captured at distinct points in time, users can inspect prior states at will. Passing `--at-op` to commands like `jj status`, `jj log`, or `jj diff` displays the repository exactly as it existed before a given change occurred—for instance, showing a modified file right before its commit description was written. Entire repositories can be rolled back to any previous state, such as when the repo was freshly initialized before any files were added. Even more powerfully, `jj undo` can invert a single past operation without wiping out intermediate work:

- **Whole-repo snapshots**: Captures branches, anonymous commits, working copy pointers, timestamps, user IDs, and machine hostnames together. - **Time-travel inspection**: Read-only evaluation via `jj status --at-op <op_id>`, `jj log`, or `jj diff` to reconstruct how an unfamiliar repository reached its current state. - **Surgical undo**: Functions like a metadata-level `git revert`, reversing the ref mutations of a specific operation (e.g., restoring an accidentally abandoned commit) while leaving subsequent work intact.

[18:32](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1112s) Concurrency, Crash Resilience, and the Transaction Model

Beyond user-facing recovery, the Operation Log serves as an architectural safety mechanism. It enables safe multi-device concurrency: a repository synced across multiple machines via a file sync service like Dropbox will never suffer data corruption or lost commits. While conflicting operations can occur, Jujutsu handles them gracefully by creating a merge node directly within the Operation Log itself.

Under the hood, Jujutsu enforces a strict transaction model. When any command starts, it loads the repository at the latest recorded operation. Concurrent modifications made by other processes remain invisible to that command. Once the operation finishes, it commits its modifications as a new operation entry in the log. Because appending an operation record cannot fail—mirroring the guarantee that writing a Git commit object cannot fail—the internal programming model avoids catastrophic transaction aborts. Reflecting on this design choice, Von Zweigbergk admits: “and this is actually why I developed the the Operation Log for the simpler programming model and then uh the undo and trying travel stuff is just an accident.”

[19:53](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1193s) Architectural Decisions: Rust Library and Laziness at Scale

Turning to the codebase architecture, Jujutsu is implemented in Rust as a reusable core library rather than a monolithic command-line tool. While the CLI is its primary consumer, the library design is meant to support IDE integrations, graphical interfaces, and server deployments, while avoiding the rewrite cycles common in the Git ecosystem. To fit Google-scale monorepos and diverse developer setups, Jujutsu makes its subsystems pluggable:

1. **Commit Storage Backends**: Ships with a Git backend (storing commits inside a backing `.git` repository) and a simple custom backend, with the option to implement cloud-backed storage. 2. **Working Copy Backends**: Supports local disk writes or smart Virtual File Systems (VFS) that prevent unnecessary file checkouts. 3. **Scalability Through Laziness**: Tailored for massive repositories by eliminating any operations that require loading all ancestors of a commit or traversing entire tree hierarchies unless strictly required.

```mermaid flowchart TD accTitle: Jujutsu Modular Architecture accDescr: Architectural block diagram showing Jujutsu's core library interfacing with consumers on top, and pluggable storage backends on the bottom.

subgraph Interfaces["Consumers"] CLI["jj CLI"] IDE["IDE / GUI (Future)"] Server["Server Services"] end

subgraph Core["jj-lib (Rust Core Library)"] Engine["Transaction & Operation Engine"] Algorithms["Lazy Graph Algorithms"] end

subgraph PluggableBackends["Modular Backends"] GitStore["Git Backend (.git)"] CloudStore["Custom / Cloud Backend"] DiskVFS["Disk Working Copy"] SmartVFS["Virtual File System (VFS)"] end

Interfaces --> Core Core --> PluggableBackends ```

[22:29](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1349s) Repository-First Operations and Git Compatibility

A core design principle of Jujutsu is to execute operations in the repository first before touching the working copy on disk. Commands build new commit objects and update references in the object store; only after the transaction is safely committed is the local working copy touched, and only if the command actually altered it. Treating the working copy as an ordinary commit drastically simplifies internal mechanics, eliminating concerns over dirty working copies—much like Elijah Newren’s `merge-ort` engine in Git. Avoiding superfluous disk writes yields massive speed improvements and prevents unnecessary network round-trips to remote backends.

Jujutsu retains full compatibility with existing Git workflows, allowing individual developers to adopt `jj` in an existing team without forcing teammates to switch. At the storage layer, the Git backend reads commits directly from Git's object database and translates them into Jujutsu’s in-memory structures. The tool provides commands to import refs from Git, export refs back to Git, and communicate directly with remote Git repositories, provided the Git backend is active.

[25:35](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1535s) Mercurial Heritage and Future Project Roadmap

Von Zweigbergk's background as a long-time Mercurial contributor heavily shaped Jujutsu's developer experience. He deliberately ported Mercurial's best ideas into `jj`, including: - A clean, staging-area-free workflow. - A functional revision selection syntax inspired by Mercurial revsets. - Powerful history-rewriting tools akin to `hg split`, `hg fold` (squashing), and `hg rebase` (which rebases non-linear commit DAGs rather than just single linear branches).

While Mercurial achieved extreme customizability through Python monkey patching—which cannot be replicated in a compiled Rust tool—Jujutsu relies on modular abstractions to bridge the gap, though Von Zweigbergk notes there is still a long way to go to match that level of extensibility.

Looking forward, Jujutsu has transitioned from an informal personal venture into an officially backed project. As Von Zweigbergk observes, “this is has probably has been my 20 project for most of its lifetime so there's a lot of features and functionality missing.” Key priorities for the open-source project and Google's internal integration include implementing garbage collection and repacking for both commits and Operation Log entries, alongside batch prefetching and caching mechanisms to ensure acceptable performance when lazily pulling objects over high-latency networks.

[27:45](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1665s) Missing Features, Extensibility, and Community Collaboration

Martin von Zweigbergk outlines the current gaps and missing functionality in Jujutsu (jj), starting with handling file history across moves. At present, the tool lacks support for copies and renames, leaving an open architectural design choice. Jujutsu needs to determine whether it will explicitly track renames and copies in metadata—the approach used by systems like Mercurial and BitKeeper—or detect them dynamically via heuristics after the fact, as Git does. He invites feedback and suggestions from the audience on which direction to pursue. In addition, standard commands such as `git blame` are still missing, although he notes that community momentum is picking up, mentioning he had just received a pull request addressing some missing functionality a few days prior.

```mermaid flowchart TD accTitle: Jujutsu Extensibility and Backend Architecture accDescr: Diagram illustrating Jujutsu's core API connecting CLI, language bindings, and interchangeable backends.

subgraph ClientLayer["Clients & Integrations"] CLI["jj CLI / Custom Commands"] Bindings["Language Bindings"] end

subgraph CoreEngine["Jujutsu Core Engine"] API["jj Public Rust API"] end

subgraph BackendLayer["Storage Backends"] GitBE["Git Backend (Recommended)"] NativeBE["Native Backend (Experimental)"] CloudBE["Cloud Storage Backend (Google Monorepo)"] end

CLI --> API Bindings --> API API --> GitBE API --> NativeBE API --> CloudBE ```

Beyond core version-control features, significant architectural work is required around extensibility and language bindings. The goal is to make Jujutsu modular so developers can plug in custom CLI commands or write third-party backends using the API directly without needing to maintain source patches. To prevent fragmentation, von Zweigbergk emphasizes providing multi-language bindings so other tooling ecosystems can leverage the native engine: “Language bindings again want to avoid rewrites so hope people can use the API instead.” Security hardening is another priority. Regarding backend options, the non-Git native backend remains experimental and lacks basic network primitives like push and pull. For the foreseeable future, von Zweigbergk strongly advises users to stick with the default Git backend: “The Git backend is just what I would recommend to everyone for many, many years ahead anyway.” He highlights the GitHub project repository, underscoring that external contributors are welcomed and essential: “We don't want this to be just Google running the project.”

- **Rename/copy strategies under consideration**: Explicit tracking (Mercurial / BitKeeper style) versus dynamic detection (Git style). - **Missing CLI tooling**: Functionality equivalent to `git blame` remains unimplemented. - **Extensibility roadmap**: Supporting out-of-tree custom commands and backends via the API without source-code patching. - **Native storage maturity**: The non-Git backend lacks push/pull network capabilities, making the Git backend the recommended choice for years to come.

---

[29:35](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1775s) Google's Roadmap: Monorepo Scale, Cloud Storage, and VFS Integration

Jujutsu has become Martin von Zweigbergk’s full-time engineering project at Google, where the primary objective is overhauling and modernizing the company's internal developer ecosystem. The internal rollout consists of two primary pillars: replacing Google's existing Mercurial client with Jujutsu (`jj`), and decoupling repository and commit storage from individual developer workstations by migrating it into the cloud. The ambition is to unify developer activity under a single, centralized system: “We're hoping to create a single huge commit graph with all the commits from all Google developers in just one graph.” Storing repos in the cloud will allow remote development environments, cloud IDEs, and code-review tools to directly inspect and mutate a developer's repository state from anywhere.

```mermaid flowchart TD accTitle: Google Jujutsu Cloud Integration Architecture accDescr: Architecture of Google's Jujutsu deployment connecting cloud services, lazy index, VFS, and cloud storage.

subgraph GoogleCloud["Cloud Services"] CloudIDE["Cloud IDE"] ReviewTool["Internal Review Tool"] JjServer["jj Server Service"] end

subgraph JujutsuGoogle["Jujutsu Custom Core"] LazyIndex["Lazy Commit Index (Segmented Changelog)"] CustomVFS["Custom Virtual File System (VFS)"] InternalCmds["Internal Commands (Reviews / Land to Mainline)"] end

subgraph StorageLayer["Distributed Storage"] CloudStorage["Cloud Commit Storage & Op Logs"] end

CloudIDE --> JjServer ReviewTool --> JjServer JjServer --> LazyIndex JjServer --> CustomVFS InternalCmds --> LazyIndex LazyIndex --> CloudStorage CustomVFS --> CloudStorage ```

Scaling Jujutsu to Google's massive monorepo requires replacing foundational data structures. The existing commit graph indexing assumes all ancestral commits are locally present on disk, which fails at monorepo scale. Von Zweigbergk explains that this index must be re-engineered to be lazy, likely adopting the "segmented changelog" design developed by Meta for their Mercurial infrastructure. On the storage front, Google will implement custom backends for distributed cloud storage of commits and operation logs (which serve as repository state tracking). On developer workstations, rather than relying on sparse checkouts, Jujutsu will interface with Google's virtual file system (VFS), allowing developers to mount specific commits directly with local file overrides on top. Finally, custom commands will handle internal review workflows and landing changes to the mainline branch, with a dedicated Jujutsu server sitting on top to service cloud IDEs and code review interfaces.

- **Internal transition goal**: Deprecate internal Mercurial usage and deploy Jujutsu across Google. - **Unified graph**: Consolidating all engineers' working commits into a single cloud-backed commit graph. - **Commit index refactoring**: Transitioning to a lazy commit index inspired by Meta's segmented changelog to handle the monorepo's vast history. - **Filesystem strategy**: Using an internal VFS instead of sparse checkouts by instructing the filesystem driver to materialize target commits directly. - **Service layer**: Introducing a central server daemon enabling cloud IDEs and internal web review platforms to programmatically interact with repos. - **Contact & Community**: Community discussions are held on Discord (linked via the project's GitHub repository), and inquiries can be sent directly to `martinvonz@google.com`.

## Notable quotes > [06:11](https://www.youtube.com/watch?v=bx_LGilOuE4&t=371s) The working copy will never be dirty, so if you check out a different commit or rebase or something, it will never tell you that you have unstaged changes. — Martin von Zweigbergk

> [27:45](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1665s) The Git backend is just what I would recommend to everyone for many, many years ahead anyway. — Martin von Zweigbergk

> [29:35](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1775s) We're hoping to create a single huge commit graph with all the commits from all Google developers in just one graph. — Martin von Zweigbergk

## Mentioned Martin von Zweigbergk, Jujutsu, jj, Git, Mercurial, Google, Ericsson, ClearCase, CVS, Perforce, Piper, CitC, Fig, Rachel Potvin, Josh Levenberg, Elijah Newren, Rust, Dropbox, BitKeeper, Meta, GitHub, Discord

## Video description Presented by Martin von Zweigbergk

Jujutsu (jj) can be used as an alternative CLI for Git repos, but it's much more than just a different CLI. It adds many new features, such as undo, anonymous branches, first-class conflicts (stored in commits), and automatic rebasing of descendants on rewrite. It also makes the working copy an actual commit (created automatically), leading to a simpler and more powerful UX than the staging area. The session is going to cover jj's design and features, and our plans for the project at Google.

About Git Merge: Git Merge is dedicated to amplifying new voices in the Git community and showcasing the most thought-provoking projects from developers, maintainers, and teams around the world. Git Merge 2022 took place at Morgan Manufacturing in Chicago, IL on September 14th and 15th.

[Source](https://www.youtube.com/watch?v=bx_LGilOuE4)

中文简报

谷歌支持 Jujutsu 版本控制系统以替代单体仓库中的 Mercurial 通过将未解决的冲突存储在提交元数据中,并将工作副本视为自动提交,Jujutsu 消除了变基中止的问题,同时让谷歌能够将工程工作流统一到单个云端托管的提交图中。 Martin von Zweigbergk 概述了谷歌源代码控制的发展历程,以及 Fig(Mercurial 的封装工具)在性能和一致性方面的局限性如何催生了 Jujutsu (jj) 的开发。他重点介绍了核心用户体验创新,例如将工作副本视为自动追加修改的提交、将冲突作为一等元数据处理而非阻断工作流的错误,以及在操作日志中记录全仓库状态转换以便轻松检查与撤销。Jujutsu 基于模块化 Rust 库实现,在提供 Git 兼容性的同时,还能自动变基后续提交栈。最后,von Zweigbergk 讨论了文件复制追踪和 blame 等暂缺功能,并介绍了谷歌利用惰性提交索引和云存储后端在其单体仓库上部署 Jujutsu 的路线图。 谷歌正将内部源代码控制从 Fig(Mercurial 的封装工具)迁移至 Jujutsu (jj),这是一款由 Martin von Zweigbergk 全职主导、使用 Rust 编写且兼容 Git 的开源分布式版本控制系统。 (4:21) Jujutsu 通过将工作副本建模为在每次执行 CLI 命令时自动追加修改的普通提交,彻底消除了未提交的修改和 Git 暂存区。 (6:11) Jujutsu 中的合并和变基操作绝不会因冲突而失败;相反,冲突会作为结构化元数据存储在提交中,从而支持延迟解决冲突以及自动变基后续提交。 (9:43) 操作日志会在每次执行命令时记录整个仓库的快照,从而实现全仓库级别的撤销、时间旅行式检查以及抗崩溃的多设备同步。 (15:31) 谷歌的内部部署路线图旨在借助惰性索引(灵感来自 Meta 的分段变更日志)和虚拟文件系统挂载,将开发者的提交存储在单一的集中式云端图中。 (29:35)

Reading summary

Martin von Zweigbergk presents Jujutsu (jj), an open-source, Git-compatible version control system developed at Google that replaces conventional staging and branching mechanics with automatic working-copy commits, conflict-resilient graph operations, and whole-repository operation logging. Working Copy Commits and Anonymous Branching (6:11) Jujutsu eliminates the traditional divide between a working directory and committed history by treating the working copy as an ordinary commit, represented in the log as '@'. Any file modification in the working copy is automatically amended into this commit whenever a jj command runs, rendering git stash obsolete and preventing dirty working copy errors during checkouts or branch switches. Running 'jj checkout' creates a new working copy commit atop a specified target, while 'jj edit' switches to an existing commit for in-place modifications. In addition, Jujutsu adopts Mercurial's anonymous branching paradigm. Commits are tracked within the revision graph without requiring user-assigned branch names, preventing detached HEAD states. When commits are modified via rebasing or amending, older iterations are automatically hidden from the log to avoid visual clutter, and unneeded revisions can be manually hidden using 'jj abandon'. Non-Failing Operations and First-Class Conflicts (9:43) Rather than aborting execution and inserting conflict markers directly into working files, Jujutsu treats merge conflicts as structured metadata recorded directly within commit objects. Operations like 'jj merge' and 'jj rebase' complete unconditionally regardless of conflicting changes. This structure allows developers to defer conflict resolution, switch branches without immediate fixes, or share conflicted commits across a team for collaborative resolution, eliminating the need for operational pause commands such as rebase continue or abort. Because rebasing cannot fail, Jujutsu automates descendant rebasing across patch stacks. Amending or editing an ancestor commit automatically cascades updates through all downstream commits without requiring manual interactive rebases. When rebasing merge commits, Jujutsu computes the diff between the original merge and its auto-merged parents, then reapplies that resolution diff onto the newly auto-merged parents to preserve history cleanly. Repository State Tracking via the Operation Log (15:31) Unlike Git's reflogs, which monitor individual branch references independently, Jujutsu's Operation Log captures transactional snapshots of the entire repository state. Each operation log entry records branch positions, anonymous heads, working copy locations across worktrees, timestamps, user identities, and hostnames. Users can inspect historical repository states using commands like 'jj status --at-op' or selectively revert actions via 'jj undo' without destroying intervening work. Architecturally, the Operation Log provides concurrency control and crash safety. Commands evaluate repository state as of the latest recorded operation and commit updates within an append-only transaction. If concurrent processes diverge—such as across devices synced via cloud storage like Dropbox—Jujutsu reconciles the repository state by creating merge nodes directly inside the Operation Log to prevent repository corruption. Modular Architecture, Git Interoperability, and Scalability (19:53) Jujutsu is written in Rust as a reusable core library (jj-lib) rather than a monolithic CLI application, isolating the graph engine from client interfaces and storage layers. Commands execute operations in the repository before updating disk files, minimizing redundant filesystem input/output. Jujutsu natively interfaces with standard Git object stores, allowing individual developers to adopt jj within existing Git codebases by reading and writing directly to the backing '.git' directory. While an experimental native backend exists, von Zweigbergk advises using the Git backend until native networking capabilities mature. At Google, Jujutsu is slated to replace the internal Mercurial-based client (Fig) and manage a centralized, cloud-backed commit graph shared across all developers. Adapting Jujutsu to Google's monorepo involves transitioning commit indexing to a lazy model inspired by Meta's segmented changelog design, interfacing with Google's virtual file system instead of sparse checkouts, and routing interactions through dedicated server daemons. While Jujutsu offers a functional, Git-compatible alternative to standard distributed workflows, open architectural questions remain, including whether to handle file moves via explicit metadata tracking or post-hoc heuristic detection, implementing missing tools such as git blame, and developing garbage collection mechanisms for commit and operation logs.

精炼阅读摘要

Google 工程师 Martin von Zweigbergk 介绍了兼顾 Git 兼容性的新一代版本控制系统 Jujutsu(简称 jj),阐述了其通过重构工作副本、一等公民冲突及全局操作日志等核心机制,来解决传统 VCS 在易用性、并发一致性与大规模单体仓库扩展性上的系统性缺陷。 工作副本即提交与匿名分支机制 (6:11) 针对 Git 繁琐的暂存区以及容易令人困惑的游离头指针(detached HEAD)状态,Jujutsu 借鉴了 Mercurial 的匿名分支概念,并对本地修改的存储模型进行了重构。在 jj 中,系统能够完整追踪所有提交而无需强制要求分支命名,提交不会因未命名而被垃圾回收机制意外清除;在历史被重写时旧提交会自动隐藏,用户也可以使用 jj abandon 手动隐藏无用历史。更为关键的设计在于,Jujutsu 将工作副本直接视作一个常规的提交对象(在日志中以 @ 标识),文件修改会在用户执行任何 jj 命令时,被自动合并(amend)进该工作副本提交中。 这一架构彻底消除了传统版本控制中的“脏工作副本”与“未暂存状态”。开发者执行 jj checkout 即可在目标提交上方开辟新的工作副本提交,执行 jj edit 则能切换至已有提交进行原位修改。由于当前工作进度每时每刻都在自动生成备份提交,开发者不再需要使用 git stash 暂存修改,也不需要频繁执行 git commit,只需在需要时通过 jj describe 补充或修改提交说明即可。此外,检出操作时未完成的修改不会跨分支漂移,显著精简了常用命令的交互认知负担。 一等公民冲突与提交链自动级联变基 (9:43) 传统的版本控制工具在遭遇合并或变基冲突时往往会直接中断命令,并在工作区代码中硬编码冲突标记以强制用户停下排查。Jujutsu 则提出了“一等公民冲突”(First-Class Conflicts)理念,将冲突本身作为结构化元数据直接存储在提交对象内部。这意味着 jj merge 或 jj rebase 操作永远不会报错中断,即使产生冲突也会正常生成一个包含冲突记录的有效提交。由此,开发者可以延后处理冲突,随意切换去推进其他任务,甚至能够直接将包含冲突的提交推送到远端与同事协作排查,诸如 --continue 或 --abort 等状态控制参数因此变得不再必要。 由于变基操作永不失败,Jujutsu 进一步解锁了全自动衍生变基能力:当开发者修改提交链中的某个祖先提交时,系统会自动将其后续的所有子孙提交向后级联变基,完全消除了手动编排交互式变基的繁琐过程。针对解决冲突产生的代码变动,开发者只需在工作副本修复代码,冲突状态即可自动消除,并可通过通用的 jj move 命令将变更移动至指定提交。对于合并提交的历史重写,系统会计算合并提交与其自动合并父节点之间的差异,并将该差异重新应用到新的自动合并父节点上,确保重写历史时保留已有的冲突解决成果。 全仓库操作日志与无锁事务并发保障 (15:31) 不同于 Git 仅追踪单个分支指针移动的 reflog,Jujutsu 引入了全仓库级别的“操作日志”(Operation Log)。该日志将整个仓库的全局状态(包括所有引用、匿名提交以及所有工作树中工作副本的精确位置)作为一个统一快照予以记录,并附带时间戳、执行用户及机器主机名等元数据。借助 --at-op 参数,用户可使用 jj status、jj log 或 jj diff 穿梭回任意历史操作节点,以只读视角检查当时的仓库全貌;而 jj undo 命令则能精确逆转某次特定操作对元数据的更改(例如找回误废弃的提交),同时保留后续操作产生的工作成果。 在底层架构上,操作日志充当了并发控制与崩溃防护机制。Jujutsu 采用了严格的追加式事务模型:任意命令启动时都会读取最新的操作快照,与并发执行的其他进程相互隔离,命令完成后再以追加操作节点的方式提交事务。由于写入操作日志记录具有不失败的特性,内部编程模型避免了复杂的事务回滚逻辑。Martin von Zweigbergk 指出,最初设计操作日志是为了简化底层编程并保证并发安全,支持时光机式的历史检查与撤销功能反而是该设计带来的附带产物;即使用户将仓库放在 Dropbox 等同步网盘上多端并发修改,系统也能通过在操作日志中生成合并节点来保证数据不损坏、不丢失。 Rust 模块化架构设计与 Git 生态完全兼容 (19:53) 在代码实现上,Jujutsu 摒弃了基于 CLI 工具二次封装的传统思路,采用 Rust 将底层功能封装为独立的共享核心库(jj-lib),以便同时服务于命令行界面、IDE 插件、GUI 以及服务端系统。为了适应超大规模代码仓库与复杂的企业基础设施,系统在存储层推行高度可插拔的设计:同时提供 Git 后端(直接基于 .git 目录存储)和原生自定义存储后端,并在工作副本层支持常规本地磁盘写入与虚拟文件系统(VFS)。在核心算法层面,Jujutsu 严格贯彻惰性计算(laziness),避免任何需要遍历全量提交图或深层目录树的贪婪操作,以此控制资源消耗。 Jujutsu 确立了“仓库优先操作”原则,所有变更先在对象库与元数据中完成提交,确认事务提交后才在必要时触碰本地磁盘上的工作副本,这一流程大幅提升了运行速度并避免了脏文件导致的 I/O 冲突。在生态整合方面,Jujutsu 维持对 Git 的完全双向兼容:其 Git 后端可直接读写 Git 的对象数据库,支持双向导入导出引用,并能与远端 Git 仓库正常通信。这允许单个工程师在无需团队其他成员协同切换工具的前提下,在现有工作流中单独采用 jj 作为日常客户端。 谷歌单体仓库迁移规划与当前功能局限 (27:45) 随着 Jujutsu 成为 Google 的正式研发项目,其内部的首要任务是替代现有的 Mercurial 客户端 Fig,并将所有工程师的工作提交解耦并汇聚到云端存储中。Google 计划构建一个包含全体内部工程师提交的超大规模统一提交图,允许远程 IDE 与代码评审工具直接在云端检查并修改仓库状态;本地开发则结合虚拟文件系统(VFS)按需挂载目标提交,摆脱物理克隆的限制。为应对单体仓库庞大历史对提交图索引造成的性能压力,Jujutsu 正计划引入类似 Meta 在 Mercurial 中研发的“分段变更日志”(segmented changelog)架构,实现提交索引的惰性加载。 但从开源项目现状来看,Martin von Zweigbergk 指出该工具仍处于演进阶段且存在不少功能缺口。系统尚未最终确定文件复制与重命名的底层方案——是在元数据中显式记录(类似 Mercurial/BitKeeper),还是依赖后置的启发式动态检测(类似 Git),目前仍处于开放讨论阶段;类似 git blame 的代码溯源工具也尚未实现。此外,原生非 Git 存储后端目前仍属实验性质且欠缺网络同步能力,演讲者明确建议大众用户在未来多年内继续以成熟的 Git 后端为核心;垃圾回收、操作日志压缩打包以及高延迟网络下的批量预取机制,也是后续开发必须补齐的关键环节。 Jujutsu 通过重构工作副本的提交属性与非阻塞的冲突元数据机制,证明了在保留 Git 生态兼容性的同时颠覆版本控制体验的可行性。然而,该项目目前在文件重命名追踪模型、溯源命令及独立网络原生存储等能力上仍有待补全,其在大规模分布式企业架构中的最终表现,仍取决于 Google 云端单体仓库与惰性索引落地的后续检验。

Detailed notes — zh

## Background 该视频由 GitHub 于 2022 年 10 月 18 日发布在 YouTube 频道上,内容为在芝加哥举办的 Git Merge 2022 大会演讲。Google 源码控制团队的 Martin von Zweigbergk 介绍了兼具 Git 兼容性与全新设计理念的版本控制系统 Jujutsu(jj),重点讲解其系统设计、创新特性以及 Google 内部对其未来的应用规划。 ## TL;DR Martin 首先回顾了 Google 从 CVS、Perforce 到 Piper 及基于 Mercurial 的 Fig 的版本控制演进历程,解释了为何没有选择直接修改 Git,而是另起炉灶打造 Jujutsu(jj)。接着他深入解析了 jj 的颠覆性设计:将工作副本直接视为真实提交以彻底淘汰暂存区、引入一等公民冲突机制与全自动后代变基、依托全局操作日志(Operation Log)实现无锁并发与全仓库时光机回滚。最后,他阐述了采用 Rust 构建的模块化库架构,并分享了 Google 计划在内部用 jj 取代 Mercurial、将全员提交拓扑图及元数据迁移至云端与虚拟文件系统的宏大愿景。 ## Atmosphere & style 整场演讲呈现出浓厚而严谨的硬核系统工程气质,开场澄清名字与动漫《咒术回战》无关的小插曲让现场氛围迅速放松。Martin 的表达平实、谦逊且极具逻辑说服力,在谈及推导出“自动变基所有后代”的顿悟时刻时流露出纯粹的技术热情。面对台下 Git 专家听众,他毫不避讳项目的早期短板与取舍难题,整场分享宛如一场高水平的分布式系统与版本控制心智模型深度思辨。 ## Bulletin - [00:08](https://www.youtube.com/watch?v=bx_LGilOuE4&t=8s) Google 工程师 Martin von Zweigbergk 推出了基于 Rust 开发的 Git 兼容版本控制系统 Jujutsu(jj),将工作副本直接建模为常规提交,彻底移除了 Git 繁琐的暂存区和 stash 操作。 - [09:43](https://www.youtube.com/watch?v=bx_LGilOuE4&t=583s) Jujutsu 将合并冲突作为一等公民直接存储在提交对象中,使 merge 与 rebase 等历史重写操作永远不会失败,并能全自动完成子孙节点变基与冲突重放。 - [15:31](https://www.youtube.com/watch?v=bx_LGilOuE4&t=931s) 系统通过全仓库级别的操作日志(Operation Log)实现事务性无锁并发安全,支持任意历史状态的时光旅行查看与单步精准撤销,在通过 Dropbox 等云同步时也不会发生数据损坏。 - [29:35](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1775s) Jujutsu 已升级为 Google 内部全职推进项目,长远目标是在内部全面替换基于 Mercurial 的 Fig,并将全体工程师的提交与操作日志汇入统一的云端 Commit Graph。 ## Key takeaways - [00:08](https://www.youtube.com/watch?v=bx_LGilOuE4&t=8s) Jujutsu(jj)的名字纯粹源于二进制文件名在键盘上易于键入,与动漫《咒术回战》无关;项目旨在解决 Google 基于 Mercurial 的 Fig 客户端在性能、并发一致性与工具集成上的痛点。 - [04:21](https://www.youtube.com/watch?v=bx_LGilOuE4&t=261s) 团队未将新特性直接合入 Git 上游,是因为这套新 UX 会引入完全割裂的命令集合,且 Google 内部存在多种直接读取文件系统的底层 Git 实现,改动成本过高。 - [06:11](https://www.youtube.com/watch?v=bx_LGilOuE4&t=371s) jj 引入匿名分支机制,所有提交均被系统天然追踪而无需命名,消除了 Git 中令人生畏的 detached HEAD 状态,且在改写时自动隐藏旧版本而不是垃圾回收。 - [06:11](https://www.youtube.com/watch?v=bx_LGilOuE4&t=371s) 工作副本(@)本身就是一个真实的提交,文件修改会被自动 amend 进去,工作区永远不会处于“脏”状态,彻底消除了 git stash 与切换分支时的改动漂移。 - [09:43](https://www.youtube.com/watch?v=bx_LGilOuE4&t=583s) 冲突是一等公民并以结构化格式直接记录在提交内,这使得变基、合并与拣选操作永不中断,开发者可将冲突延迟解决或推送至远端协作修复。 - [09:43](https://www.youtube.com/watch?v=bx_LGilOuE4&t=583s) 基于变基永不失败的特性,jj 实现了后代节点的全自动变基(Descendant Rebasing),修改历史栈中的某个提交后,其后续子孙节点与分支引用会自动更新。 - [13:46](https://www.youtube.com/watch?v=bx_LGilOuE4&t=826s) 命令 jj move 允许在任意提交之间自由转移代码变更,可将工作区中的冲突解决方案精准抽离并合并进历史提交,一举消除整条链上的冲突。 - [15:31](https://www.youtube.com/watch?v=bx_LGilOuE4&t=931s) 全局操作日志(Operation Log)记录仓库所有引用与工作副本的实时快照,支持针对任意历史操作状态运行 status、diff 或 log,并提供类似 git revert 的引用级单步撤销。 - [18:32](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1112s) 命令执行被封装为隔离的快照事务,确保并发修改不会引发数据损坏,即使通过网盘(如 Dropbox)同步多机数据,并发操作也会被安全记录为合并。 - [19:53](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1193s) Jujutsu 以 Rust 编写,架构上首先是一个可嵌入的代码库而非单纯的 CLI,且提交存储与工作副本均支持可插拔后端,以适配 Git、云端及虚拟文件系统(VFS)。 - [22:29](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1349s) 系统坚持“仓库先行”哲学,所有操作优先在内存与提交图模型中生效并完成事务,最后才按需更新物理磁盘,避免了大规模 Monorepo 下不必要的 I/O 阻塞。 - [22:29](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1349s) jj 在深度兼容 Git 对象模型与网络协议的同时,全面继承了 Mercurial 的精髓,包括免暂存区流、Revsets 查询语言以及强大的子树级历史重写工具。 - [27:45](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1665s) 项目当前仍处于演进阶段,尚缺乏成熟的垃圾回收机制,对重命名/拷贝追踪的设计方案仍在评估中,日常用户在相当长时期内仍建议优先使用 Git 后端。 - [30:45](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1845s) Google 计划在内部通过引入类似 Meta 的 Segmented Changelog 惰性索引技术与自研 VFS,摆脱稀疏检出(Sparse Checkout),构建覆盖全员的云端单一提交图系统。 ## Detailed walkthrough ### [00:08](https://www.youtube.com/watch?v=bx_LGilOuE4&t=8s) 名字起源与 Google 的版本控制历史背景 演讲者 Martin von Zweigbergk 走上讲台时遇到了一点小插曲——演讲备注一开始没有显示出来。他自我介绍在 Google 负责源码控制(Source Control)工作,今天介绍的是他开发了近三年的 Git 兼容版本控制系统 Jujutsu(简称 `jj`)。针对许多人的第一反应,Martin 特别澄清:“以防你们好奇,这个名字跟动漫《咒术回战》(Jujutsu Kaisen)没有任何关系。”项目之所以叫 Jujutsu,单纯是因为其二进制可执行文件名为 `jj`,而叫 `jj` 是因为在键盘上特别好敲。 ```mermaid flowchart TD accTitle: Google 内部版本控制演进历程 accDescr: 展示 Google 源码控制系统从 CVS、Perforce、Piper+CitC 到 Fig 的演变步骤 subgraph Centralized["集中式演进"] CVS["CVS"] --> P4["Perforce<br/>(规模过大无法承载)"] P4 --> Piper["Piper (自研单体仓库)"] Piper --> CitC["CitC (虚拟文件系统)"] end subgraph Distributed["分布式体验需求"] CitC --> Fig["Fig<br/>(基于 Mercurial 的客户端)"] Fig -.->|"性能/一致性痛点"| JJ["Jujutsu (jj) 构想"] end ``` Martin 回顾了个人经历与 Google 内部版本控制系统的演进。毕业后,他在爱立信(Ericsson)工作了大约 7 年,推动了公司从 ClearCase 迁移到 Git 的过程,并在业余时间清理过一些 Git rebase 脚本;随后他加入 Google,最初做一款薪酬应用(Compensation app),过去 8 年则全力投入到 Fig 项目中——Fig 是为适配 Google 庞大的内部 Monorepo(单体代码仓库)而构建的 Mercurial 客户端。关于 Google 的版本控制发展史,传闻最早使用 CVS,之后切换到 Perforce;后来代码库急剧膨胀,Perforce 无法支撑,Google 便自研了 Piper,并针对工作副本过大的问题开发了名为 CitC 的虚拟文件系统。然而,习惯了分布式版本控制(DVCS)的工程师们十分想念外部的工作流,于是团队在 CitC/Piper 之上构建了包装层 Mercurial(即 Fig)。 - 推荐参考资料:Rachel Potvin 与 Josh Levenberg 在 @Scale 大会上关于 Google 超大规模 Monorepo 的分享。 - Fig 虽然广受内部工程师喜爱,但在长期实践中暴露了三大核心技术痛点: - **性能问题(Performance)**:部分原因是 Python 语言本身的执行开销,更根本的在于使用了许多无法横向扩展至 Monorepo 规模的“急切求值(eager)”数据结构。 - **一致性问题(Consistency)**:Mercurial 的架构最初并非为分布式存储设计,在 Google 的分布式文件系统上频繁遭遇并发写入竞争(Write races),从而导致数据损坏(Corruption)。 - **集成痛苦(Integration pain)**:其他工具与内部系统不得不通过调用 Mercurial CLI 并解析命令行文本输出来交互,“这绝不是什么好玩的差事(which is not fun)”。 --- ### [04:21](https://www.youtube.com/watch?v=bx_LGilOuE4&t=261s) 从 20% 项目到全新设计:为何不直接修改 Git 几年前,团队开始探讨下一代版本控制系统(Next-gen VCS)的蓝图。在讨论中,有人提出一个很大胆的构想:“把编辑器里的每一次保存,都自动变成一次提交。”Martin 被这个理念深深吸引,并在业余时间开启了 Jujutsu(`jj`)项目来验证这种全新工作流。这个项目最初作为他长达两年的“20% 时间个人项目”推进;直到 2022 年春季,团队决定加大投入,`jj` 正式升级为他的“100% 全职项目”。 面对台下 Git Merge 听众最普遍的困惑——“为什么不直接把这些功能提交合并到 Git 官方上?”——Martin 给出了深思熟虑的解释。他想要探索的是一种截然不同的用户体验(UX),如果强行塞进 Git 体系: > “我认为这最终会变成 Git 内部一套完全独立的命令集合,那将会非常难看,而且 upstream(Git 上游社区)也绝不应该接受这种代码。” 此外,该系统必须融入 Google 的工程生态体系。在早年做 Fig 时,团队就已经否决了直接采用 Git 的方案,原因在于生态内存在多种不同的 Git 底层实现(它们直接读取文件系统),任何新引入的特性都必须在两到三个不同的实现库中重复重写。 --- ### [06:11](https://www.youtube.com/watch?v=bx_LGilOuE4&t=371s) 匿名分支与“工作副本即提交”哲学 进入具体的工作流,Martin 展示的第一项特性是直接借鉴自 Mercurial 的**匿名分支(Anonymous Branches)**。在传统的 Git 中,用户一旦离开具体分支名就会落入令人困惑且恐惧的 `detached HEAD` 状态;而 `jj` 能够天然追踪每一个提交,用户完全不需要预先给它们起名。这意味着这些提交不会丢失,也不会被垃圾回收机制(Garbage collection)随意清理。为了防止 commit 日志迅速变得杂乱无章,当提交被改写(例如通过 amend 或 rebase)时,旧版本会被自动隐藏,用户也可以随时使用 `jj abandon` 手动隐藏废弃的提交。 ```mermaid flowchart LR accTitle: jj 工作副本自动提交模型 accDescr: 说明工作副本修改后自动作为 @ 提交被捕获,不需要传统暂存区的流程 A["父提交 (Commit A)"] --> B["@ 提交<br/>(工作副本状态 / 自动提交)"] B -.->|"编辑文件并运行任何 jj 命令"| B B -->|"jj describe"| C["写入 Commit Message"] B -->|"jj checkout"| D["基于 @ 创建全新空提交"] ``` 使用 `jj` 最颠覆的直观感受在于:**工作副本(Working Copy)本身就是一个货真价实的 Commit**。在 CLI 日志中,当前工作副本用 `@` 符号标识。任何时候只要用户在磁盘上修改了文件,并在终端运行任意 `jj` 命令,那些修改就会被自动追加(amend)进这个 `@` 提交中。若要切换开发上下文,使用 `jj checkout` 会在指定提交之上开辟一个新的空提交来承载后续工作;若要继续修改历史上的某个既有提交,只需运行 `jj edit`。 这种“工作副本即提交”的设计打破了 Git 长久以来的诸多操作定式: - **工作副本永远不会处于“脏(Dirty)”状态**:切换提交或执行变基时,工具绝不会弹出令人头疼的“有未暂存改动(unstaged changes)无法切换”的报错。 - **天然的每一次操作自动备份(Automatic Backup)**:用户输入的每条命令都会自动固化当前的本地变更。 - **完全淘汰了 `git stash`**:工作副本提交本身就是事实上的 stash。 - **淘汰了传统的独立 `commit` 动作**:代码时刻都在提交中。若需要补充提交说明,随时运行 `jj describe` 编辑描述即可。 - **更加统一、正交的命令行体验(Consistent CLI)**:`@` 提交与普通历史提交在地位上完全对等,无需任何专门针对工作副本的特殊参数标记。以 `jj restore` 为例,它可以在任意两个提交之间恢复文件,默认是将工作副本父提交恢复至工作副本。 - **未提交改动不会“尾随”漂移**:在 Git 中未暂存的修改经常在切换分支时跟着到处移动,而在 `jj` 中,所有的改动都牢牢锚定在它们所属的特定提交节点上。 --- ### [09:43](https://www.youtube.com/watch?v=bx_LGilOuE4&t=583s) 一等公民冲突与全自动后代变基(Descendant Rebasing) `jj` 的另一大杀手级特性是**一等公民冲突(First-Class Conflicts)**。在现场展示的截图中,将工作副本 `@` 与另一个分支的提交进行合并(merge),即使产生严重的代码冲突,该合并命令也会直接成功退出。随后在 log 输出中可以看到,工作副本提交被清晰地标记包含 conflict。 Martin 强调,`jj` 记录冲突的方式并非简单地往源文件里塞入 `<<<<<<<` 这类冲突标记文本,而是以一种结构化的数据模型直接存储在 Commit 对象本身内部。这一架构突破带来了一系列颠覆性的操作体验: - **冲突解决可以无压力延后(Delaying conflict resolution)**:工程师完全可以把冲突搁在一旁,先 `checkout` 去处理其他紧急需求,稍后再回来解决。 - **冲突能够团队协同处理(Collaborative conflict resolution)**:冲突状态被提交并推送后,开发者可以先解决部分文件冲突,剩下的推给同事协作解决。 - **变基永不失败(Rebase never fails)**:不仅 merge 不会失败,rebase、cherry-pick 等操作也永远成功执行到底。这彻底消灭了 Git 中繁琐的 `--continue` 和 `--abort` 命令交互死循环。 - **统一的解决冲突心智模型**:无需记忆是哪个变基或合并指令引发了冲突,只需检出冲突提交,在本地修复内容,然后将其 squash 吸收进冲突提交即可。 ```mermaid flowchart TD accTitle: 自动变基后代提交示意图 accDescr: 说明修改历史栈中的某个节点时,jj 自动将其所有子孙节点变基上去的过程 subgraph Before["修改前"] A1["Commit A"] --> B1["Commit B (检出并修改)"] B1 --> C1["Commit C"] C1 --> D1["Commit D (栈顶)"] end subgraph After["jj 自动处理后"] A2["Commit A"] --> B2["Commit B' (amend 完成)"] B2 ==>|"自动无缝重放"| C2["Commit C'"] C2 ==>|"自动无缝重放"| D2["Commit D'"] end ``` 在演讲推进到更深层应用时,Martin 分享了他花了整整一年时间才顿悟的一个推论:“既然 rebase 永远成功、绝不因冲突中断,那么我们就可以始终**全自动变基所有的后代节点(Automatic rebasing of descendants)**。”在由一系列提交叠起来的代码栈(Commit stack)中,如果你检出中间的一个提交并 amend 了一些修改,`jj` 会自动把后续所有依赖它的子孙提交逐个自动 rebase 上去,分支引用也会一并同步向前迁移,开发者完全无需手动干预。更精妙的是,`jj` 甚至支持对冲突本身及其冲突解决方案进行变基与重放,使得复杂的分支交互历史迁移变得稳健而平滑。 ### [13:46](https://www.youtube.com/watch?v=bx_LGilOuE4&t=826s) 精准的变基与跨提交变更移动(jj move) Martin von Zweigbergk 详细演示了 Jujutsu 如何优雅地解决历史重写中的冲突。在此前的场景中,工作副本(Working Copy)本身作为一个合并提交,承载了冲突的解决方案。当整个提交栈发生变基时,该解决方案会被自动变基并保留在工作副本中,因此开发者在工作副本里完全不会看到冲突遗留。 紧接着,他展示了第二个操作截图——运行 `jj move --to <commit>` 命令。Martin 指出,这个命令的底层逻辑与当天早些时候有人提到的 Git “自动压制”(autosquash)颇为相似,但 `jj move` 要通用得多:“你可以把改动从任意一个提交移动到任意另一个提交中。”(“you can can move a change from any commit into any other commit”)。在默认缺省参数下(无需加 `--from`),它会直接把工作副本中的改动精准抽离并合并进首个发生冲突的提交中。这么做之后,整条提交链上的冲突被一次性彻底消除,而工作副本则随之恢复为一个干净的空提交。 此外,Jujutsu 对合并提交(Merge Commit)的变基处理也极具独创性。不同于传统工具的生硬重放,jj 是通过计算该合并提交相对于其“父节点自动合并结果”(auto-merged parents)的差异(Diff),再将这段差异重新应用到变基后“新的父节点自动合并结果”之上去完成的。Martin 强调,这实际上是 jj 处理提交中所有 Diff 的通用法则:无论何时对一个合并提交执行 `diff` 操作,jj 都会先自动合并父节点并以此为基准进行比对,这与 Elijah 早前探讨过的“三方合并差异”(three-way merge diff)思路不谋而合。 --- ### [15:31](https://www.youtube.com/watch?v=bx_LGilOuE4&t=931s) 操作日志(Operation Log):全仓库维度的“时光机”与撤销机制 ```mermaid flowchart TD accTitle: jj Operation Log Snapshot Model accDescr: 架构图展示了每一步操作如何生成包含元数据的全局快照,并支持分支回滚与单独撤销。 subgraph OperationLog["Operation Log 全局操作流水"] Op1["操作 N-2: 仓库初始化\n(工作副本为空)"] --> Op2["操作 N-1: 放弃某提交\n(abandoned commit)"] Op2 --> Op3["操作 N: 设置提交描述\n(describe)"] end subgraph Operations["操作日志提供的核心能力"] View["时光旅行式查看\njj status --at-op / diff / log"] Restore["全仓库全局恢复\njj undo / restore 全量回滚"] Revert["单步细粒度撤销\n类似针对引用的 git revert"] end Op3 -.->|"支持回溯状态"| View Op1 -.->|"可瞬间恢复至"| Restore Op2 -.->|"精准逆向撤回"| Revert ``` Martin 重点介绍了 Jujutsu 最具突破性的特性之一——操作日志(Operation Log)。在 jj 的设计哲学中,开发者可以把整座仓库都理解为处于版本控制系统之下。这里的“整座仓库”,不仅包含所有显式引用(Refs),还涵盖了匿名分支头指针(Anonymous Heads)以及每个工作区树(Worktree)中工作副本的精确位置。它在感官上类似于 Git 的 `reflog`,但有着根本性的升维:git reflog 针对单个引用,而 jj 的 Operation Log 是对整个仓库的所有引用在同一时刻进行全局快照,并附带执行者的用户名、主机名以及操作时间戳等完备元数据。 这一机制赋予了仓库真正的“时光旅行”能力: - **任意维度的历史查看**:开发者可以在任意命令后添加操作标识(如针对某个历史操作运行 `jj status`、`jj log` 或 `jj diff`),从而观察仓库在当时究竟处于何种状态。演示截图中展示了在设置提交描述之前的一个操作快照,输出直接反映出当时的提交尚无描述信息、但已有修改过的文件。Martin 评价道,当你接手一个不属于自己的代码仓库,急需弄清它到底是如何变成现在这副模样时,该功能具有无与伦比的排错价值。 - **全量回退与精准单步撤销**:除了直接将整个仓库还原到早期的空白状态,jj 还支持跳过中间步骤、仅撤销其中某一次独立操作。Martin 解释道:“它的运作方式有点像 git revert,但它作用的对象不是提交中的文件,而是操作中的引用。”(“so that works kind of like git reverted us but instead of acting on on the files in the committed acts on the refs in an operation”)。截图中展示了通过撤销一次先前放弃(abandon)提交的操作,那个原本丢失的提交瞬间重新显形并恢复可用。 --- ### [18:32](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1112s) 无锁并发安全与事务编程模型 除了直观的用户功能,Operation Log 还带来了强大的底层安全性与极简的架构契约: - **极端环境下的无损并发同步**:即便两台不同的机器同时在本地修改各自的代码仓库,并仅仅通过类似 Dropbox 这类同步网盘来直接传输底层数据,jj 也能提供并发安全保障。尽管业务逻辑上仍可能产生冲突,但底层绝对不会遭遇数据损坏或静默丢失;当两个通过 Dropbox 同步的操作相遇时,jj 的操作日志会清晰地将它们记录并展示为一次合并(Merge)。 - **事务永远不会失败的编程模型**:Martin 坦言,这其实是他最初发明 Operation Log 的真正初衷,而随之诞生的“撤销”与“时光旅行”反而只是顺带捡到的副产物。在 jj 的运行机制中,一条 CLI 命令启动时,仓库会立刻锚定并加载在当前最新的操作快照上,命令执行过程中外部发生的任何并发修改均被完全隔离、对当前命令不可见;当命令完成时,它只需将本次修改打包成一次全新的操作事务提交落盘即可。如同写入一个普通提交不会中途失败一样,这一步事务提交也绝不会失败。 --- ### [19:53](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1193s) 系统架构:以 Rust 编写的高内聚库与模块化解耦 Martin 开始转入 Jujutsu 的软件架构剖析。Jujutsu 采用 Rust 语言编写,并且在定位上首先是一个核心代码库(Library),其次才是 CLI 界面。尽管当前的 CLI 是该库唯一的消费者,但将其构建为库的设计初衷,是方便未来能毫无摩擦地嵌入到服务端、图形界面(GUI)或 IDE 插件中。同时,这种库化设计也意在避免重走 Git 早期命令混乱、后续不得不耗费巨资重写底层驱动的历史弯路。 为了能平滑融入 Google 内部独特的基础设施生态,jj 极度强调模块化与可替换性: | 模块类别 | 默认与备选实现 | 设计目的与潜在场景 | |:--- |:--- |:--- | | **提交存储后端 (Commit Storage Backend)** | 1. **Git 后端**(默认将提交存为标准 Git 对象)<br>2. **简单自定义后端** | 预留接口规范,使得未来可以直接编写出将提交透明存放于云端后端的插件。 | | **工作副本后端 (Working Copy Backend)** | 1. **本地磁盘文件系统**<br>2. **虚拟文件系统集成 (VFS)** | 适配超大规模代码库;通过对接更智能的 VFS,避免向物理磁盘真实写入巨量不必要的文件。 | 针对 Google 超大规模单体仓库(Monorepo)的伸缩性挑战,jj 在算法设计上贯彻了极端的“惰性”(Laziness)原则。系统内严禁出现任何必须遍历某次提交全部祖先节点的全局操作;在设计遍历与比对算法时,严格限制算法复杂度不随整个仓库的总规模或单棵树的总容量无端膨胀,从源头上做到不加载任何非必需的对象。 --- ### [22:29](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1349s) 仓库先行原则与 Git / Mercurial 基因继承 jj 架构中另一项至关重要的决定是:**所有操作一律在仓库模型内首先发生,而不是在工作副本中执行**。 当任何 jj 命令触发改动时,它会首先在底层写入提交对象,并更新内部引用指向这些提交;只有当整个事务成功提交后,系统才会根据最终结果去按需更新本地工作副本的文件。由于工作副本在 jj 内部本身就是一个真实的提交,即使是专门修改工作副本的指令,也不过是提交一个包含了改动的新事务,随后再去同步物理磁盘。这种设计消除了开发者对“当前工作区到底处于什么状态”的顾虑,极大提升了执行速度,并完美配合了惰性加载——系统无需为了中间计算而去远端服务器反复拉取对象再写回工作副本。 在生态兼容与灵感汲取方面,Martin 阐述了 jj 兼收并蓄的设计脉络: - **原生双向兼容 Git**:在最低层级,jj 的 Git 存储后端能直接读取外部 Git 仓库的对象存储区,将其转换为内存中的内部表达;同时原生支持导入导出 Git 引用(Refs)并直接与 Git 远端进行网络交互。 - **复刻 Mercurial 的优秀体验**:作为拥有多年 Mercurial(Hg)开发背景的核心开发者,Martin 毫不掩饰地将 Mercurial 中广受好评的精髓全盘引入: - 彻底抛弃烦琐的暂存区(Staging Area),追求干净易用的单层工作流。 - 引入了类似 Hg 的 **Revsets** 修订集查询语言,用于精准且具表现力地筛选指定提交。 - 继承了 Hg 卓越的历史重写哲学:如类似 `hg split` 的交互式提交拆分、`hg fold` 的提交折叠,以及 `hg rebase` 直接变基整棵提交子树(而非仅仅单条线性分支)的高阶能力。 - 针对定制性差异,Martin 指出 Mercurial 依靠 Python 动态特性广泛使用 Monkey Patching(运行时打补丁),而 Rust 无法照搬这种做法,因此 jj 试图通过更严谨清晰的模块化架构来逐步追平其可扩展性。 --- ### [27:00](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1620s) Google 内部演进路线与开源规划 演讲的最后一部分转向了 Jujutsu 的后续开发路线图。Martin 坦率地向观众披露,该项目在过往绝大多数生命周期里,都只是他个人在 Google 的“20% 自由时间项目”(20% project),因此系统中仍有很多基础功能有待补全: - **垃圾回收(GC)与对象重包(Repacking)**:当前提交对象和操作流水均未实现完备的 GC 机制,这一块必须补齐以防止数据无限膨胀。 - **网络拉取批处理与缓存优化**:对于那些依赖网络按需延迟获取对象的云端后端,为了保证日常交互性能处于可接受的水平,团队必须尽快引入批量预取(Batch Prefetching)和智能本地缓存机制。 ### [27:45](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1665s) 功能短板、架构扩展性与开源路线图 Martin von Zweigbergk 坦诚地介绍了 Jujutsu 当前仍处于早期阶段,许多特性尚不完备。其中一个核心设计难题是对文件拷贝与重命名的处理。目前 Jujutsu 尚未支持拷贝或重命名跟踪,团队正面临设计抉择:是像 Mercurial 或 BitKeeper 那样显式显式记录跟踪元数据,还是像 Git 那样在差异比较时通过启发式算法事后检测。Martin 现场向社区征集意见:“Happy to hear suggestions.” 除了重命名机制外,许多日常版本控制功能也在逐步补齐。例如类似 `git blame` 的功能当时仍未内置,不过 Martin 提到几天前刚刚收到了社区贡献者提交的相关 Pull Request。在架构层面,Jujutsu 迫切需要提升组件的可插拔性,让开发者无需修改或修补(patch)源代码,就能直接通过 API 添加自定义命令或定制存储后端。同时,为了避免其他语言社区重新用其他语言去重写一套版本控制系统,项目组正在发力多语言绑定(Language bindings),希望大家能直接复用底层核心。至于内置的原生非 Git 后端(Custom native backend),目前其完善度远落后于 Git 后端,甚至尚未实现网络推送与拉取(`push` 与 `pull`)功能。对此 Martin 直言,对于绝大多数日常用户而言,Git 后端依然是当下乃至未来很长一段时间内的绝对首选: > “The Git backend is just what I would recommend to everyone for many many years ahead anyway.” 此外,在安全性加固与社区建设方面,Martin 强调 Jujutsu 属于整个开源社区,热烈欢迎外部开发者参与共建。他明确表示:“We don't want this to be just Google running the project.” - **重命名与拷贝追踪**:正在评估 Mercurial/BitKeeper 式的显式存储方案与 Git 式的内容启发式检测方案。 - **缺失功能与 PR**:缺失诸如代码追溯(blame)等常见命令,正在快速接受社区 PR。 - **组件可替换性与 API**:目标是不碰源码即可接入自定义子命令与自定义 Storage 后端,并提供丰富的语言绑定以防止生态碎片化重写。 - **非 Git 后端现状**:原生存储后端暂无网络传输(push/pull)能力,仅建议将 Git 后端作为生产环境首选。 --- ### [29:35](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1775s) Google 内部愿景:替代 Mercurial 与仓库上云 Martin 宣布 Jujutsu 目前已成为他在 Google 的全职工作项目,其终极目标是彻底升级和改善 Google 内部的大规模开发生态系统。在 Google 内部,该项目主要围绕两个宏大目标展开:其一是在公司内部全面用 Jujutsu 替换 Mercurial;其二是彻底打破本地文件系统的束缚,将提交存储(Commit storage)和仓库元数据存储整体迁移至云端。 这项云端战略最具雄心之处在于构筑一个全局统一的统一拓扑图。Google 计划将全体开发者的所有提交汇聚到同一个超大规模的单一 Commit Graph 之中。一旦版本库驻留于云端,工程师无论身处何地,无论是通过本地终端、云端 IDE(Cloud IDE)还是内部代码审查工具(Review Tool),都可以直接访问、检视乃至修改同一个仓库。这不仅消除了本地同步海量历史记录的沉重负担,也让跨工具链协同变得前所未有的顺畅。 > “So we're hoping to create a single huge commit graph with all the commits from all Google Developers in just one graph.” ```mermaid flowchart TD accTitle: Google 内部基于 Jujutsu 的云端 VCS 架构 accDescr: 展示 Jujutsu 如何通过云端存储、虚拟文件系统与各类 IDE、代码审查工具进行集成 subgraph UserSurfaces["用户使用场景与工具"] CLI["本地终端 CLI"] CloudIDE["云端开发环境 (Cloud IDE)"] ReviewTool["代码审查工具 (Code Review)"] end subgraph ServiceLayer["服务端接口"] JJServer["Jujutsu Cloud Server"] end subgraph CoreEngine["Jujutsu 核心层改造"] LazyGraph["惰性提交图索引 (Segmented Changelog)"] CustomVFS["Google 内部虚拟文件系统 (VFS Working Copy)"] end subgraph CloudStorage["内部云存储设施"] GlobalGraph[("全公司统一提交图 (Single Huge Graph)")] OpLogs[("云端操作日志与仓库存储 (Operation Logs)")] end CLI --> CoreEngine CloudIDE --> JJServer ReviewTool --> JJServer JJServer --> CoreEngine CoreEngine --> LazyGraph CoreEngine --> CustomVFS LazyGraph --> GlobalGraph CoreEngine --> OpLogs ``` --- ### [30:45](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1845s) 架构落地细节:惰性索引、虚拟文件系统与告别稀疏检出 为了在 Google 独一无二的超大单体代码库(Monorepo)中实现上述设想,Martin 详细展示了需要引入的新系统与底层改造(在幻灯片中用红色标出)。首要难题是现有的提交图索引(Commit Indexer)假设所有祖先提交在本地全部可用,这在 Google 的单体仓库规模下根本无法加载,会导致系统彻底崩溃。为此,团队必须对其进行重写以实现“惰性加载”(Lazy Loading)。在技术选型上,Martin 透露他们很可能会借鉴同行 Meta(原 Facebook)为其基于 Mercurial 的版本控制系统所研发的“分段更新日志”(Segmented Changelog)技术。 其次,针对底层提交数据与操作日志(Operation Logs)的持久化,Google 团队正在编写适配内部分布式云存储系统的全新后端。而在工作区(Working copy)层面,Google 计划深度整合内部自研的虚拟文件系统(VFS),从而彻底告别传统耗时且容易出错的稀疏检出(Sparse Checkout)。开发者甚至不需要拉取树状目录,只要直接通知 VFS 挂载检出指定的 Commit,并在其之上加载所需的少量编辑文件即可。此外,系统还会接入内部代码审查工作流,提供自动发起 Review 及向主线(Mainline)合并的专用命令,并在上层架设专用服务器接口供各种云端协作工具调用。 在演讲尾声,Martin 感谢了全场听众并留下了联系方式。他欢迎所有对 Jujutsu 演进感兴趣的开发者加入其官方 Discord 交流群(链接托管于项目的 GitHub 仓库主页),也可以通过邮件 `martinvonz@google.com` 与他直接探讨,整场分享在热烈的掌声中圆满落幕。 > “One of the first things we're going to have to do is to replace the commit graph or which is called commit indexer in the in the diagram, because it currently assumes that all ancestors are are available, which of course doesn't scale to the size of our monorepo.” - **惰性提交图(Lazy Commit Graph)**:重构 Commit Indexer,拟引入 Meta 的 Segmented Changelog 算法,化解全量祖先遍历的规模瓶颈。 - **虚拟文件系统工作区(VFS Working Copy)**:依托 Google 内部 VFS,按需动态呈现文件,弃用传统的 Sparse Checkout 机制。 - **云端服务与集成服务**:构建 Server 接口,无缝打通云端 IDE、内部 Review 系统及主干合入链路。 - **联系与社区渠道**:可通过 GitHub 页面加入 Discord 讨论群,或通过 Martin 的工作邮箱直接沟通。 ## Notable quotes > [27:45](https://www.youtube.com/watch?v=bx_LGilOuE4&t=1665s) The Git backend is just what I would recommend to everyone for many many years ahead anyway. — Martin von Zweigbergk ## Mentioned Martin von Zweigbergk, Jujutsu (jj), Git, Mercurial, Google, Ericsson, ClearCase, CVS, Perforce, Piper, CitC, Fig, Rachel Potvin, Josh Levenberg, Elijah Newren, Meta, BitKeeper, Dropbox, Rust, Python, Git Merge 2022 ## Video description Presented by Martin von Zweigbergk Jujutsu (jj) can be used as an alternative CLI for Git repos, but it's much more than just a different CLI. It adds many new features, such as undo, anonymous branches, first-class conflicts (stored in commits), and automatic rebasing of descendants on rewrite. It also makes the working copy an actual commit (created automatically), leading to a simpler and more powerful UX than the staging area. The session is going to cover jj's design and features, and our plans for the project at Google. About Git Merge: Git Merge is dedicated to amplifying new voices in the Git community and showcasing the most thought-provoking projects from developers, maintainers, and teams around the world. Git Merge 2022 took place at Morgan Manufacturing in Chicago, IL on September 14th and 15th. [Source](https://www.youtube.com/watch?v=bx_LGilOuE4)

Source quotes

[27:45] Martin von Zweigbergk: The Git backend is just what I would recommend to everyone for many many years ahead anyway.

Source quotes

[6:11] Martin von Zweigbergk: The working copy will never be dirty, so if you check out a different commit or rebase or something, it will never tell you that you have unstaged changes. [27:45] Martin von Zweigbergk: The Git backend is just what I would recommend to everyone for many, many years ahead anyway. [29:35] Martin von Zweigbergk: We're hoping to create a single huge commit graph with all the commits from all Google developers in just one graph.

Original transcript

[0:08] um yeah so my name is Martin Von [0:11] schweigberg [0:14] I [0:15] expected my speaker notes to be here [0:18] somewhere [0:19] um but yeah [0:21] um I work for uh on Source control at [0:23] Google [0:24] and I'm going to talk about uh a project [0:26] I've been working on for almost three [0:28] years it's a git compatible VCS called [0:32] Jiu Jitsu and in case you're wondering [0:34] the name has nothing to do with [0:36] jiu-jitsu kaisen the anime [0:39] um it's called Jujitsu just because the [0:41] binary is called JJ and the binary is [0:43] called JD because it's easy to type [0:47] um [0:49] oh okay now there it is [0:52] um so here's an overview of the [0:54] presentation [0:55] um [0:56] first I'm going to give you some [0:57] background about me and about the [1:00] history of source control at Google [1:03] and I'm going to go through the [1:04] workflows and architecture of JJ [1:08] um and then at the end I'll explain [1:11] what's what's next for the open source [1:14] project and uh and um our the [1:17] integration at Google [1:20] so background about me I after [1:24] graduating I worked for Eric's son for [1:28] about 70 years [1:30] and while there I think it was it's fair [1:32] to say I drove the immigration to get [1:35] there from from clear case [1:37] and I cleaned up some get three base [1:39] scripts in my spare time [1:42] then I joined Google and worked on [1:45] a compensation app [1:48] and for the last eight years I've worked [1:52] on fig which is a which is a project to [1:54] integrate material as a client for our [1:57] in-house monorepo [2:03] um so for for context uh let me tell you [2:06] a bit about the history our Version [2:08] Control at Google [2:09] so long time ago we supposedly started [2:12] with CVS [2:15] um [2:16] and uh then we switched to the perforce [2:19] and after a while proforce uh wasn't [2:22] able to handle the repository anymore [2:25] because it got too large so we wrote Our [2:28] Own VCS called Piper [2:31] um but the working copy was still too [2:33] big so we created a virtual flight [2:37] system called City [2:39] on top of Piper [2:41] and that's what almost every user go at [2:45] Google uses now [2:48] um [2:49] people who are still missing the dbcs [2:51] workflows that they were used to from [2:53] outside Google so we added Mercury on [2:56] top of that and as I said that's what [2:58] I've been working on for the last eight [3:00] years [3:03] um and also in case you you didn't know [3:05] um this our monoree but Google is [3:07] extremely large and has like all the [3:10] source code [3:11] um at Google [3:14] and you can you can watch this uh uh [3:17] talk by Rachel plattwood and potvin [3:20] um from at scale that if you're curious [3:25] so generally people really like fig but [3:27] there's still some major problems uh [3:29] we're having [3:31] the probably the biggest one is [3:33] performance [3:35] um and and that's partly because of [3:37] python python is slow [3:40] uh and partly because of [3:42] um eager data structures that don't [3:45] scale to the size of the repo [3:48] another problem is uh with uh [3:52] consistency we're seeing right races [3:55] because Mercurial is not designed for [3:58] distributed storage so we get corruption [4:01] when when we store it on top of our [4:04] distributed file system [4:07] um and another pain has been [4:09] integration because we're calling [4:12] Mercurial the Mercurial CLI and parsing [4:16] the outputs which is not fun [4:19] so [4:21] a few years ago we started talking about [4:23] what we would want from a next-gen VCS [4:27] and one of the ideas that came up there [4:30] was to automatically commit or to to [4:34] make the [4:35] make to make a make a commit from every [4:39] save from from your editor [4:42] and I got really excited by that idea [4:44] and started JD to experiment with it [4:50] um [4:51] and then I worked on it as my 20 product [4:54] for about two years [4:57] and this spring we decided to invest [4:59] more so now it's my 100 project [5:04] um [5:07] next [5:09] so you may be wondering why we're why I [5:12] didn't decide to to just add these [5:15] features to to git but as I said I want [5:18] I was want to experiment with a [5:20] different ux so I I think that would end [5:24] up being a completely separate [5:27] set of commands inside of git and that [5:30] would be [5:31] really ugly and wouldn't and shouldn't [5:33] get up accepted Upstream [5:37] and also I wanted to be able to [5:39] integrate into Google's ecosystem and we [5:44] had already decided what fig that [5:47] against using git there because because [5:49] of the problems with integrating it with [5:52] um our ecosystem at Google [5:55] and one of the problems is that there [5:58] are multiple implementations I'll get [6:01] that read from the file system so we [6:04] would have to add any new features in in [6:06] at least two or three places [6:11] okay so let's take a look at the [6:13] workflows [6:16] so the first the first teacher [6:21] um is anonymous branches which is [6:22] something I copied from mercurial [6:26] so instead of this [6:28] gets scary uh detached head workflow or [6:33] state [6:35] um JJ keeps track of all your commits [6:38] without you having to name them [6:41] so that means they didn't show up in log [6:44] outputs and they will not be garbage [6:46] collected [6:48] um so it may seem like you would get a [6:50] very cluttered log output very quickly [6:52] but [6:53] um whenever you rewrite the commit so if [6:55] you amend it or rebate it for example [6:57] the the old version gets gets hidden and [6:59] you can also manually hide commits with [7:02] JG abandon [7:06] and um so one of the first things you'll [7:09] notice if you start using JJ is that the [7:13] working copy is is an actual commit that [7:16] gets automatically committed [7:18] and it shows up in the log output at [7:21] with an at symbol [7:24] and whenever you make any changes in the [7:26] working copy [7:28] and run the run any JJ command after [7:30] that it will get automatically amended [7:33] into that that commit [7:36] um so and you can use the JD checkout [7:40] command and that actually creates [7:42] a new commit on top of the [7:45] committee specify to keep to store your [7:49] working working copy changes and and if [7:52] you instead wanted to resume [7:54] um editing an existing commit you can [7:56] use JJ edits [7:58] so this is some very interesting [8:00] consequences like the one important one [8:04] is the the working copy would never be [8:07] dirty [8:08] so if you check out the different commit [8:11] or rebase or something it will never [8:13] tell you that you have unstaged changes [8:19] you get automatic backup because every [8:22] command you run trace is another [8:24] automatic backup for you [8:26] it makes stash unnecessary because your [8:30] working copy commits is effectively a [8:32] stash [8:34] it also makes commit unnecessary [8:38] because the well it's already committed [8:41] whenever you run a command you your [8:43] working copy is committed so [8:45] and you can [8:47] um if you if you want to set the [8:49] description commit message you can run [8:51] jda describe to do that at any time [8:56] we get more consistent CLI because the [9:00] um the the ads commit the working copy [9:03] commits behaves just like any other [9:05] commit so there are no special Flags to [9:08] to work um to act on the working copy [9:12] um and for example JD restore can [9:15] restore files between any two commits [9:19] it defaults to to restoring from the [9:22] parent of the working copy and into the [9:24] working copy just like gets restored as [9:25] I think [9:27] um but you can pass any two commits [9:31] and also uncommitted changes stay in [9:34] place so they don't move around with you [9:36] like like they do with Git checkouts [9:41] so um [9:43] another one of of JD's distinguishing [9:45] features is a first-class conflicts [9:50] um [9:51] so if you if you look at the screenshot [9:53] there we merge the working copy at with [9:56] some other commits from another branch [9:59] and that succeeds [10:03] even though there are conflicts and we [10:05] can see in the log output afterwards [10:06] that there are conflicts in the working [10:08] copy [10:09] and that's so as you see the the working [10:12] copy commit there with the ad is is a [10:15] merge commits with conflicts [10:18] so these conflicts are recorded in the [10:20] commit as in a structured way so they're [10:23] not they're not just conflict markers [10:26] stored in a file [10:30] um [10:31] and and this like design leads to even [10:34] more magic like um maybe obvious one is [10:37] that you can [10:39] you can delay [10:41] resolving conflicts until you're ready [10:44] ready until you feel like it so if in [10:46] this case [10:47] when we had this conflict we can just [10:49] check out any another commit and deal [10:51] with the conflicts later who want to [10:54] and you can collaborate on on conflict [10:57] resolutions [10:58] you can resolve some some of the [11:00] conflicts in in these files and and [11:03] leave the rest for your co-worker for [11:05] example [11:08] um maybe less obvious is that a rebase [11:11] never fails so [11:14] um and same I mean we saw that here that [11:16] merge doesn't fail the same thing is [11:18] true for rebates and or all the other [11:20] similar commands [11:23] um which makes continue and abort and [11:27] for rebase and and cherubick and all [11:30] those similar commands unnecessary [11:33] we we also get a more consistent [11:35] conflict resolution flow you don't need [11:38] to remember which command [11:40] um [11:41] creative your conflicts you just check [11:43] out the command commit with conflict [11:47] and resolve the conflicts in the working [11:50] copy and then squash the that conflict [11:53] resolution into into the parent that [11:56] that conflict or as in in the screenshot [11:59] here we we were already [12:01] editing that commit so we just resolve [12:04] the conflict in The Working copy and and [12:06] it's it's gone from the log output [12:12] um so [12:13] um [12:14] yeah I remember so so now in the working [12:16] copy here in the second screenshot [12:19] the conflict has been resolved so in the [12:22] working copy [12:23] uh sorry in in the merge commit there in [12:25] the working copy [12:27] um that that working copy resolves the [12:29] conflict right [12:31] so we're going to come back to that in [12:33] the next slide [12:35] um and and and and a very important [12:37] feature that took me a year to to [12:39] realize it was possible is that um [12:42] because uh rebase always succeeds we can [12:45] we can always uh rebase all descendants [12:48] so if you [12:50] um check out the commit in the middle of [12:52] a stack and amend in some changes uh JD [12:55] will always rebase all The Descendants [12:57] on top so you will not have to do that [12:59] yourself and it moves the branches over [13:01] and so on [13:05] um [13:08] yes so so you can uh we can actually [13:11] even rebase [13:14] conflicts and conflict resolutions I [13:16] don't have time to explain how that [13:18] works but it does [13:20] um so in the top screenshots here [13:24] this is continuation from from the [13:26] previous slide [13:27] we re-based one side of the of the merge [13:31] from conflicts conflicting change to [13:34] there and it's and it's descendants onto [13:38] conflict and change one and of course we [13:40] get the same same conflict as we had in [13:42] the the merge commit before [13:44] and that stays in the non-conflicting [13:46] change but then in the the working copy [13:48] because we we had the conflict [13:50] resolution in the working copy which was [13:52] a merge commit before [13:54] um that resolution gets rebased over and [13:58] it stays in the working copy so we don't [14:00] have a conflict in the word copy here [14:04] um then the the second screenshot [14:08] um we were on JJ move 2 that commits [14:12] with the the first commit with the [14:14] conflict and that command [14:16] is a bit like the uh all the squash that [14:19] someone talked about earlier earlier [14:20] today [14:21] but much more generic you can can move [14:26] a change from any commit into any other [14:29] commit [14:31] so in this case we're moving the changes [14:34] from the working cup it does the default [14:35] as well there's no dash from [14:38] Move It from The Working copy and into [14:41] the conflict the first quit with the [14:43] conflict [14:44] and then the conflict is gone from the [14:47] entire stack and the working copy is in [14:50] this case becomes empty [14:53] we can also rebase merges correctly [14:57] by [14:58] rebasing the diff compared to the auto [15:01] merged parents [15:04] onto the new auto merge parents [15:08] and and that's actually how JD treats [15:11] all diffs or changes in in commits not [15:16] just not just on rebasing Souls when you [15:18] when you diff a merge commit it's come [15:20] to Auto merge the parents just like the [15:23] uh [15:24] three merged if I think Elijah talked [15:26] about before [15:31] um and the the last feature I was going [15:32] to talk about is the what I call the [15:35] Operation Log [15:36] so you can think of it as the entire [15:39] repo being under Source control [15:42] um and by the entire repo I mean refs [15:45] and on Anonymous heads and the working [15:48] copies position in in each work tree [15:53] so the [15:54] um [15:55] it's it's kind of like it gets ref Vlogs [15:59] but they're [16:01] um [16:02] across all the refs at once [16:06] and there's some extra metadata as well [16:08] so in the top screenshot there you can [16:11] see the [16:12] um [16:13] their username and hostname and time of [16:17] the operation [16:21] um and as as you can can imagine having [16:23] these snapshots of the repository at a [16:27] different points in time lets us go back [16:29] and look at the repository from a [16:32] previous snapshot [16:33] so in the in the middle uh [16:36] snapshot screenshot there [16:39] we run JD status at a particular [16:42] operation and that shows like just [16:44] before we had set set the description on [16:48] the commit [16:49] so we see that the working copy commit [16:52] has no description but it has a modified [16:54] font because it was from that point in [16:56] time [16:57] yeah you can run this with any command [17:00] not just status you can do run log or [17:02] div for anything [17:05] and of course this is very useful when [17:07] for when you're trying to figure out how [17:10] um aeropostory got into a certain [17:12] certain State especially if it's not [17:14] your own repositories you don't remember [17:16] what what happened [17:20] um [17:23] and like the last screenshot there shows [17:25] how we restored the entire repo to an [17:28] earlier State before before the file was [17:31] even added in this case [17:33] so that's the second operation from the [17:35] bottom when when we're just created the [17:37] repository so the working copy is empty [17:40] and and there's no description [17:44] um and and restoring back to [17:47] an earlier State like that is is very [17:50] useful when you have made a mistake but [17:52] uh JD actually even lets you undo [17:56] just a single operation without undoing [17:58] all the later operations [18:01] so that works kind of like git reverted [18:04] us but instead of acting on [18:07] on the files in the committed acts on [18:10] the refs in an operation [18:14] so the screenshots here show how we [18:17] undo and and [18:20] an operation the second to last [18:21] operation there that abandoned the [18:23] commit so we undo that operation and it [18:27] becomes visible again [18:32] um and the Operation Log also gives us [18:36] safe concurrency even if you have run [18:39] commands on [18:41] a repositories in on different machines [18:44] and sync them via Dropbox for example [18:47] you can get conflicts of course but you [18:50] will not [18:51] lose data or or get corruption [18:56] and then in those cases if you sync two [19:00] operations via Dropbox you'll see a [19:02] merge in this Operation Log output [19:08] um we also got a simpler simpler [19:10] programming model because transactions [19:13] never fail when you started a command [19:17] um the repository is loaded at the [19:20] current the latest operation and any any [19:24] changes that happen [19:26] um concurrently will not be seen by that [19:28] by that command [19:29] and then when the command is is done it [19:32] commits that transaction as a new [19:34] operation which gets recorded recorded [19:38] and can't fail just like write me in [19:40] commit can't fail [19:42] uh and and this is actually why I [19:44] developed the the Operation Log for the [19:47] simpler programming model and then uh [19:49] the undo and trying travel stuff is just [19:51] an accident [19:53] okay so um that's all about features and [19:57] workflows and take a look let's take a [19:59] look at the architecture [20:02] uh so JD is written as rest [20:06] um [20:07] it's written as a library to be to be [20:10] easy to to reuse [20:13] uh in the CLI is the only the current [20:16] only current user of that library but [20:19] the goal is to to be able to use it in [20:21] in a in a server or a CLI or or uh GUI [20:26] or or an idea for example [20:30] um and and I hope also by making it the [20:33] library we reduce the temptation to to [20:36] rewrite and have the same problem as [20:37] kids [20:43] um and and because I wanted JD to be [20:45] able to [20:46] um integrate with the ecosystem at [20:48] Google [20:49] I try to make it easy to replace [20:51] different modules a bit [20:56] um [20:57] and so for example it comes with two [21:01] different [21:02] commit storage backends by default [21:06] one is the the kids back end the source [21:09] commits as git commits [21:12] and the other one is just a very simple [21:15] custom one but it should be possible to [21:18] write one that stores commits in the [21:21] cloud for example [21:23] and same thing with the working copy [21:26] it's [21:26] of course stored on local disk normally [21:29] but the goal is to be able to to write [21:32] to replace that with an implementation [21:34] that writes [21:36] um writes the work in copy to a VFS for [21:38] example [21:39] integrates with a smarter vs VFS by not [21:43] actually writing all the files [21:48] and also to be able to use that at [21:50] Google [21:51] it needs to be scalable to very very [21:54] large repositories [21:56] which means we can't have any operations [21:59] that need all the ancestors for example [22:02] of the commits [22:04] so to achieve that we achieved that [22:07] mostly by by laziness not fetching [22:10] objects that we don't need so [22:13] try to be careful when designing [22:15] algorithms to [22:17] like not scale to the size of the [22:19] repository or the size of a tree unless [22:21] necessary [22:29] so another important design decision was [22:32] to [22:34] um [22:34] perform operations in the repository [22:37] first not in the working copy so [22:40] when all operations are at like right [22:44] commits and update references to point [22:46] to those commits and then only [22:48] afterwards after transaction commits [22:51] actually [22:52] um is that it's the working copy updated [22:55] to to match that that states the new [22:58] state if if they're working copy even [23:00] Changed by the operation [23:04] um and it helps here that the [23:07] um the working copy is to commit because [23:10] then you even when you're running a [23:12] command that updates the working copy [23:14] that's to say the same thing you just [23:16] commit that transaction that modifies [23:18] the working copy commit and then update [23:20] to working copy afterwards [23:23] um and we get a simpler programming [23:26] model because we don't have to we always [23:28] create commits [23:31] whatever commit we need and we don't [23:33] need to worry about what's in the [23:34] working copy at that [23:37] so same same thing as Elijah was talking [23:40] about I think with merge award [23:44] um and this makes it much much faster [23:47] by not touching the working copy [23:49] unnecessarily [23:51] um [23:52] and it also helps with the laziness by [23:54] because you don't need to [23:57] fetch objects from the back end right [23:59] which might be from a server [24:01] um just in order to update the working [24:04] copy [24:05] and then update it back later for [24:07] example [24:11] and as I said JD is a is git compatible [24:14] and [24:17] um you can you can start using it on on [24:19] the same independently of others who use [24:22] the same [24:24] um git project so [24:28] um [24:29] and this this compatibility happens at a [24:32] few different levels at the lowest level [24:34] there's the the commit storage [24:38] so there is as I said there's one back [24:40] and you commit storage back in the [24:42] stores commits in in back in git [24:45] Repository [24:49] um [24:50] and uh so so that that reads commits [24:53] from the get back the backing git [24:55] repository the the object store uh and [24:59] converts it into the in-memory in memory [25:02] uh representation that JJ expects [25:06] um and there's also a functionality for [25:08] uh importing gitreps uh into jda and [25:12] exporting refs to get [25:17] um and and for like interacting with Git [25:20] remotes [25:22] and of course these commands only work [25:24] in when you're when the back end is the [25:27] get back end [25:30] not with the custom backend [25:35] um and of course since I I worked on [25:38] Mercurial for many many years [25:40] um there are many good things I want to [25:43] replicate [25:44] such as the the simple clean ux with for [25:49] example [25:51] um its rev sets language for selecting [25:54] revisions [25:56] and uh the simpler workflows without the [25:59] staging area so [26:01] I copied those [26:04] mercurial's history rewriting sport is [26:06] also pretty good with HD split and phone [26:09] for example for for splitting and uh and [26:12] uh squash squashing commits [26:15] and uh HD rebase which rebases a whole [26:19] three up commits not just a linear [26:21] Branch or a single Branch at least [26:25] um so I copy those things as well [26:28] and then Mercurial has is very [26:32] customizable [26:34] mostly thanks to being written in Python [26:36] so that since JJ has written in Rust we [26:39] can't just copy that but we can you [26:42] can't use monkey patching [26:44] in the same way [26:46] um but I hope the the modular design I [26:48] talked about earlier at least helps [26:50] there but it still have a long way to go [26:52] if [26:53] to be as customizable as as material [26:58] okay so [27:00] um let's take a look at our plans for [27:04] the projects the open source project and [27:07] and our Integrations at Google [27:11] um so remember this is has probably has [27:13] been my 20 project for most of its [27:16] lifetime so there's a lot of features [27:18] and functionality missing [27:21] um like for example GC and repacking is [27:24] not implemented [27:25] so we need to implement that for both [27:28] commits and and operations [27:32] for backings that lately fetch objects [27:36] over the network to make to make that [27:38] perform okay we need to do [27:40] some batch prefetching and caching [27:45] there is no support for [27:47] copies or renames [27:50] so we have to [27:51] decide if we want to do to track them [27:54] like Mercurial or bitkeeper does for [27:57] example or if you want to detect them [28:00] like like it does [28:02] happy to hear suggestions [28:07] and just lots of other features are [28:10] missing on this particular one I [28:12] actually got a pull request from for a [28:14] few days ago so but still like get blame [28:17] for example is not there [28:22] um we need to make it easier to replace [28:25] different components like for example [28:27] adding a custom command or adding a [28:31] custom backend without like using while [28:33] using the API or not having to to patch [28:36] the source code [28:40] um [28:40] and yeah language bindings again want to [28:44] avoid rewrites so hope people can use [28:47] the API instead [28:49] so we want to make that as easy as [28:50] possible in different languages [28:52] security hardening and [28:57] the the custom back end uh the [29:00] non-get-back and uh is has very little [29:04] support like there is no support for [29:06] push and pull for example [29:09] um so [29:10] that would need to be done at some point [29:12] but the the get back is just [29:15] um [29:15] what I would recommend to everyone for [29:17] many many years ahead anyway so [29:20] and of course [29:22] contributions are very welcome the URL [29:25] is for the project is there [29:28] we don't want this to be just Google [29:30] running the product [29:35] um and yes I said my this is now my [29:38] full-time project at Google [29:40] uh and and the the goal of that project [29:42] is to [29:44] um to improve the internal development [29:46] ecosystem [29:48] there are [29:51] two big main parts of this this project [29:55] one is to [29:56] replace Mercurial by JJ internally [30:00] the other part is to move the [30:04] commit storage and [30:07] repository storage out of the file [30:09] system and into the cloud [30:11] so we're hoping to create a single huge [30:15] commit graph with all the commits from [30:17] all Google Developers [30:19] in in just one graph [30:23] and and by having the [30:26] repository is available in the cloud we [30:29] you should be able to [30:30] access them from anywhere and and from [30:33] like a cloudy Audi for example or review [30:35] tool should be able to access your [30:38] repository and modify it [30:44] so [30:45] um and this diagram here shows how we're [30:49] planning to accomplish that [30:52] so most of this is [30:55] the same as on on a previous slide [30:59] I've added some new systems and [31:02] Integrations with in red [31:07] one of the first things we're going to [31:09] have to do is to replace the commit [31:13] graph or which is called commit inductor [31:16] in the in the diagram [31:18] uh because it currently assumes that all [31:20] ancestors are are available which of [31:23] course doesn't scale to the size of our [31:25] monorail [31:27] so that's uh we're going to have to [31:29] rewrite to make that lazy [31:32] um [31:33] I'm probably going to to use something [31:35] called segmented change log that our [31:38] friends at meta developed for their [31:40] mercurial-based VCS [31:44] um then we're going to add [31:47] new new backends for the internal [31:50] cloud-based storage of commits and [31:52] operation logs well operation logs are [31:54] basically repositories [31:58] um and we will add a custom working copy [32:01] implementation for our [32:04] VFS [32:06] so we we we're hoping to not use sparse [32:11] checkouts so instead this [32:14] our VFS is we can just tell the the BFS [32:19] which commit to check out basically and [32:21] and like a few files on top [32:26] um [32:27] and we'll add some we'll add a bunch of [32:31] commands probably for [32:32] integrating with our internal [32:35] integration with our existing review [32:38] reviews and and like starting to reuse [32:42] or merging into Mainline and stuff like [32:43] that [32:45] and then um we're going to add a server [32:47] on top of this that will be used by the [32:51] cloud ID and review tool [32:56] um yeah that was all I had so thanks for [32:59] listening if you have any questions you [33:00] can find a link to [33:03] to Discord chat for example on on from [33:06] their poster repository page GitHub page [33:09] um and feel free to email me at [33:11] martinvancy google.com [33:13] thank you [33:15] [Applause]