jj/latest/contributing/index.html

2452 lines
70 KiB
HTML

<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="canonical" href="https://jj-vcs.github.io/jj/latest/contributing/">
<link rel="prev" href="../technical/conflicts/">
<link rel="next" href="../code-of-conduct/">
<link rel="icon" href="../images/favicon-96x96.png">
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.6.4">
<title>Guidelines and "How to...?" - Jujutsu docs</title>
<link rel="stylesheet" href="../assets/stylesheets/main.8608ea7d.min.css">
<link rel="stylesheet" href="../assets/stylesheets/palette.06af60db.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
<script>__md_scope=new URL("..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
</head>
<body dir="ltr" data-md-color-scheme="default" data-md-color-primary="indigo" data-md-color-accent="indigo">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#how-to-contribute" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<div data-md-color-scheme="default" data-md-component="outdated" hidden>
</div>
<header class="md-header md-header--shadow" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href=".." title="Jujutsu docs" class="md-header__button md-logo" aria-label="Jujutsu docs" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
Jujutsu docs
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Guidelines and "How to...?"
</span>
</div>
</div>
</div>
<form class="md-header__option" data-md-component="palette">
<input class="md-option" data-md-color-media="(prefers-color-scheme)" data-md-color-scheme="default" data-md-color-primary="indigo" data-md-color-accent="indigo" aria-label="Switch to system preference" type="radio" name="__palette" id="__palette_0">
<label class="md-header__button md-icon" title="Switch to system preference" for="__palette_1" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m14.3 16-.7-2h-3.2l-.7 2H7.8L11 7h2l3.2 9zM20 8.69V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12zm-9.15 3.96h2.3L12 9z"/></svg>
</label>
<input class="md-option" data-md-color-media="(prefers-color-scheme: light)" data-md-color-scheme="default" data-md-color-primary="indigo" data-md-color-accent="indigo" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_1">
<label class="md-header__button md-icon" title="Switch to light mode" for="__palette_2" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 10a6 6 0 0 1-6-6 6 6 0 0 1 6-6 6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg>
</label>
<input class="md-option" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-scheme="slate" data-md-color-primary="indigo" data-md-color-accent="indigo" aria-label="Switch to dark mode" type="radio" name="__palette" id="__palette_2">
<label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_0" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12s-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6a6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg>
</label>
</form>
<script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
<label class="md-header__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
</label>
<nav class="md-search__options" aria-label="Search">
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
</button>
</nav>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href=".." title="Jujutsu docs" class="md-nav__button md-logo" aria-label="Jujutsu docs" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
</a>
Jujutsu docs
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href=".." class="md-nav__link">
<span class="md-ellipsis">
Home
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2" >
<label class="md-nav__link" for="__nav_2" id="__nav_2_label" tabindex="0">
<span class="md-ellipsis">
Getting started
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2">
<span class="md-nav__icon md-icon"></span>
Getting started
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../install-and-setup/" class="md-nav__link">
<span class="md-ellipsis">
Installation and setup
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../tutorial/" class="md-nav__link">
<span class="md-ellipsis">
Tutorial and bird's eye view
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../github/" class="md-nav__link">
<span class="md-ellipsis">
Working with GitHub
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../windows/" class="md-nav__link">
<span class="md-ellipsis">
Working on Windows
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../FAQ/" class="md-nav__link">
<span class="md-ellipsis">
FAQ
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cli-reference/" class="md-nav__link">
<span class="md-ellipsis">
CLI reference
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../testimonials/" class="md-nav__link">
<span class="md-ellipsis">
Testimonials
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../community_tools/" class="md-nav__link">
<span class="md-ellipsis">
Community-built tools
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_7" >
<label class="md-nav__link" for="__nav_7" id="__nav_7_label" tabindex="0">
<span class="md-ellipsis">
Concepts
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_7">
<span class="md-nav__icon md-icon"></span>
Concepts
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../working-copy/" class="md-nav__link">
<span class="md-ellipsis">
Working copy
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../bookmarks/" class="md-nav__link">
<span class="md-ellipsis">
Bookmarks
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../conflicts/" class="md-nav__link">
<span class="md-ellipsis">
Conflicts
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../operation-log/" class="md-nav__link">
<span class="md-ellipsis">
Operation log
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../glossary/" class="md-nav__link">
<span class="md-ellipsis">
Glossary
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_8" >
<label class="md-nav__link" for="__nav_8" id="__nav_8_label" tabindex="0">
<span class="md-ellipsis">
Configuration
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_8_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_8">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../config/" class="md-nav__link">
<span class="md-ellipsis">
Settings
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../filesets/" class="md-nav__link">
<span class="md-ellipsis">
Fileset language
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../revsets/" class="md-nav__link">
<span class="md-ellipsis">
Revset language
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../templates/" class="md-nav__link">
<span class="md-ellipsis">
Templating language
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_9" >
<label class="md-nav__link" for="__nav_9" id="__nav_9_label" tabindex="0">
<span class="md-ellipsis">
Comparisons
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_9_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_9">
<span class="md-nav__icon md-icon"></span>
Comparisons
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../git-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Git comparison
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../git-command-table/" class="md-nav__link">
<span class="md-ellipsis">
Git command table
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../git-compatibility/" class="md-nav__link">
<span class="md-ellipsis">
Git compatibility
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../sapling-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Sapling comparison
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../related-work/" class="md-nav__link">
<span class="md-ellipsis">
Other related work
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_10" >
<label class="md-nav__link" for="__nav_10" id="__nav_10_label" tabindex="0">
<span class="md-ellipsis">
Technical details
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_10_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_10">
<span class="md-nav__icon md-icon"></span>
Technical details
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../technical/architecture/" class="md-nav__link">
<span class="md-ellipsis">
Architecture
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../technical/concurrency/" class="md-nav__link">
<span class="md-ellipsis">
Concurrency
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../technical/conflicts/" class="md-nav__link">
<span class="md-ellipsis">
Conflicts
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_11" checked>
<label class="md-nav__link" for="__nav_11" id="__nav_11_label" tabindex="0">
<span class="md-ellipsis">
Contributing
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_11_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_11">
<span class="md-nav__icon md-icon"></span>
Contributing
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<span class="md-ellipsis">
Guidelines and "How to...?"
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
Guidelines and "How to...?"
</span>
</a>
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#policies" class="md-nav__link">
<span class="md-ellipsis">
Policies
</span>
</a>
<nav class="md-nav" aria-label="Policies">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#contributor-license-agreement" class="md-nav__link">
<span class="md-ellipsis">
Contributor License Agreement
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#commit-guidelines" class="md-nav__link">
<span class="md-ellipsis">
Commit guidelines
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#code-reviews" class="md-nav__link">
<span class="md-ellipsis">
Code reviews
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#community-guidelines" class="md-nav__link">
<span class="md-ellipsis">
Community Guidelines
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#contributing-large-patches" class="md-nav__link">
<span class="md-ellipsis">
Contributing large patches
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#contributing-to-the-documentation" class="md-nav__link">
<span class="md-ellipsis">
Contributing to the documentation
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#learning-rust" class="md-nav__link">
<span class="md-ellipsis">
Learning Rust
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#setting-up-a-development-environment" class="md-nav__link">
<span class="md-ellipsis">
Setting up a development environment
</span>
</a>
<nav class="md-nav" aria-label="Setting up a development environment">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#summary" class="md-nav__link">
<span class="md-ellipsis">
Summary
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#explanation" class="md-nav__link">
<span class="md-ellipsis">
Explanation
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#configuring-jj-fix-to-run-rustfmt" class="md-nav__link">
<span class="md-ellipsis">
Configuring jj fix to run rustfmt
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#using-mold-for-faster-tests-on-linux" class="md-nav__link">
<span class="md-ellipsis">
Using mold for faster tests on Linux
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#editor-setup" class="md-nav__link">
<span class="md-ellipsis">
Editor setup
</span>
</a>
<nav class="md-nav" aria-label="Editor setup">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#visual-studio-code" class="md-nav__link">
<span class="md-ellipsis">
Visual Studio Code
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#zed" class="md-nav__link">
<span class="md-ellipsis">
Zed
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#previewing-the-html-documentation" class="md-nav__link">
<span class="md-ellipsis">
Previewing the HTML documentation
</span>
</a>
<nav class="md-nav" aria-label="Previewing the HTML documentation">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#install-uv" class="md-nav__link">
<span class="md-ellipsis">
Install uv
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#build-the-docs" class="md-nav__link">
<span class="md-ellipsis">
Build the docs
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#building-the-entire-website" class="md-nav__link">
<span class="md-ellipsis">
Building the entire website
</span>
</a>
<nav class="md-nav" aria-label="Building the entire website">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#explanation-of-the-docs-build-deploy-script" class="md-nav__link">
<span class="md-ellipsis">
Explanation of the docs-build-deploy script
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#modifying-protobuffers-this-is-not-common" class="md-nav__link">
<span class="md-ellipsis">
Modifying protobuffers (this is not common)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#logging" class="md-nav__link">
<span class="md-ellipsis">
Logging
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#profiling" class="md-nav__link">
<span class="md-ellipsis">
Profiling
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../code-of-conduct/" class="md-nav__link">
<span class="md-ellipsis">
Code of conduct
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../design_docs/" class="md-nav__link">
<span class="md-ellipsis">
Design docs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../design_doc_blueprint/" class="md-nav__link">
<span class="md-ellipsis">
Design doc blueprint
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../releasing/" class="md-nav__link">
<span class="md-ellipsis">
Releasing
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../governance/temporary-voting/" class="md-nav__link">
<span class="md-ellipsis">
Temporary voting for governance
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../governance/GOVERNANCE/" class="md-nav__link">
<span class="md-ellipsis">
Governance
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_12" >
<label class="md-nav__link" for="__nav_12" id="__nav_12_label" tabindex="0">
<span class="md-ellipsis">
Design docs
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_12_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_12">
<span class="md-nav__icon md-icon"></span>
Design docs
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../design/git-submodules/" class="md-nav__link">
<span class="md-ellipsis">
git-submodules
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../design/git-submodule-storage/" class="md-nav__link">
<span class="md-ellipsis">
git-submodule-storage
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../design/run/" class="md-nav__link">
<span class="md-ellipsis">
JJ run
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../design/sparse-v2/" class="md-nav__link">
<span class="md-ellipsis">
Sparse patterns v2
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../design/tracking-branches/" class="md-nav__link">
<span class="md-ellipsis">
Tracking branches
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../design/copy-tracking/" class="md-nav__link">
<span class="md-ellipsis">
Copy tracking and tracing
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../roadmap/" class="md-nav__link">
<span class="md-ellipsis">
Development roadmap
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#policies" class="md-nav__link">
<span class="md-ellipsis">
Policies
</span>
</a>
<nav class="md-nav" aria-label="Policies">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#contributor-license-agreement" class="md-nav__link">
<span class="md-ellipsis">
Contributor License Agreement
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#commit-guidelines" class="md-nav__link">
<span class="md-ellipsis">
Commit guidelines
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#code-reviews" class="md-nav__link">
<span class="md-ellipsis">
Code reviews
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#community-guidelines" class="md-nav__link">
<span class="md-ellipsis">
Community Guidelines
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#contributing-large-patches" class="md-nav__link">
<span class="md-ellipsis">
Contributing large patches
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#contributing-to-the-documentation" class="md-nav__link">
<span class="md-ellipsis">
Contributing to the documentation
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#learning-rust" class="md-nav__link">
<span class="md-ellipsis">
Learning Rust
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#setting-up-a-development-environment" class="md-nav__link">
<span class="md-ellipsis">
Setting up a development environment
</span>
</a>
<nav class="md-nav" aria-label="Setting up a development environment">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#summary" class="md-nav__link">
<span class="md-ellipsis">
Summary
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#explanation" class="md-nav__link">
<span class="md-ellipsis">
Explanation
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#configuring-jj-fix-to-run-rustfmt" class="md-nav__link">
<span class="md-ellipsis">
Configuring jj fix to run rustfmt
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#using-mold-for-faster-tests-on-linux" class="md-nav__link">
<span class="md-ellipsis">
Using mold for faster tests on Linux
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#editor-setup" class="md-nav__link">
<span class="md-ellipsis">
Editor setup
</span>
</a>
<nav class="md-nav" aria-label="Editor setup">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#visual-studio-code" class="md-nav__link">
<span class="md-ellipsis">
Visual Studio Code
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#zed" class="md-nav__link">
<span class="md-ellipsis">
Zed
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#previewing-the-html-documentation" class="md-nav__link">
<span class="md-ellipsis">
Previewing the HTML documentation
</span>
</a>
<nav class="md-nav" aria-label="Previewing the HTML documentation">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#install-uv" class="md-nav__link">
<span class="md-ellipsis">
Install uv
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#build-the-docs" class="md-nav__link">
<span class="md-ellipsis">
Build the docs
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#building-the-entire-website" class="md-nav__link">
<span class="md-ellipsis">
Building the entire website
</span>
</a>
<nav class="md-nav" aria-label="Building the entire website">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#explanation-of-the-docs-build-deploy-script" class="md-nav__link">
<span class="md-ellipsis">
Explanation of the docs-build-deploy script
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#modifying-protobuffers-this-is-not-common" class="md-nav__link">
<span class="md-ellipsis">
Modifying protobuffers (this is not common)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#logging" class="md-nav__link">
<span class="md-ellipsis">
Logging
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#profiling" class="md-nav__link">
<span class="md-ellipsis">
Profiling
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<h1 id="how-to-contribute">How to Contribute<a class="headerlink" href="#how-to-contribute" title="Permanent link">&para;</a></h1>
<h2 id="policies">Policies<a class="headerlink" href="#policies" title="Permanent link">&para;</a></h2>
<p>We'd love to accept your patches and contributions to this project. There are
just a few small guidelines you need to follow.</p>
<h3 id="contributor-license-agreement">Contributor License Agreement<a class="headerlink" href="#contributor-license-agreement" title="Permanent link">&para;</a></h3>
<p>Contributions to this project must be accompanied by a Contributor License
Agreement. You (or your employer) retain the copyright to your contribution;
this simply gives us permission to use and redistribute your contributions as
part of the project. Head over to <a href="https://cla.developers.google.com/">https://cla.developers.google.com/</a> to see
your current agreements on file or to sign a new one.</p>
<p>You generally only need to submit a CLA once, so if you've already submitted one
(even if it was for a different project), you probably don't need to do it
again.</p>
<h3 id="commit-guidelines">Commit guidelines<a class="headerlink" href="#commit-guidelines" title="Permanent link">&para;</a></h3>
<p>Unlike many GitHub projects (but like many VCS projects), we care more about the
contents of commits than about the contents of PRs. We review each commit
separately, and we don't squash-merge the PR (so please manually squash any
fixup commits before sending for review).</p>
<p>Each commit should ideally do one thing. For example, if you need to refactor a
function in order to add a new feature cleanly, put the refactoring in one
commit and the new feature in a different commit. If the refactoring itself
consists of many parts, try to separate out those into separate commits. You can
use <code>jj split</code> to do it if you didn't realize ahead of time how it should be
split up. Include tests and documentation in the same commit as the code they
test and document.</p>
<p>The commit message should describe the changes in the commit;
the PR description can even be empty, but feel free to include a personal
message. We start the commit message with <code>&lt;topic&gt;:</code> and don't use
<a href="https://www.conventionalcommits.org/en/v1.0.0/">conventional commits</a>. This means if
you modified a command in the CLI, use its name as the topic, e.g.
<code>next/prev: &lt;your-modification&gt;</code> or <code>conflicts: &lt;your-modification&gt;</code>. We don't
currently have a specific guidelines on what to write in the topic field, but
the reviewers will help you provide a topic if you have difficulties choosing
it. <a href="https://cbea.ms/git-commit/">How to Write a Git Commit Message</a> is a good
guide if you're new to writing good commit messages. We are not particularly
strict about the style, but please do explain the reason for the change unless
it's obvious.</p>
<h3 id="code-reviews">Code reviews<a class="headerlink" href="#code-reviews" title="Permanent link">&para;</a></h3>
<p>All submissions, including submissions by project members, require review. We
use GitHub pull requests for this purpose. Consult
<a href="https://help.github.com/articles/about-pull-requests/">GitHub Help</a> for more
information on using pull requests.</p>
<p>When you address comments on a PR, don't make the changes in a commit on top (as
is typical on GitHub). Instead, please make the changes in the appropriate
commit. You can do that by creating a new commit on top of the initial commit
(<code>jj new &lt;commit&gt;</code>) and then squash in the changes when you're done (<code>jj squash</code>).
<code>jj git push</code>
will automatically force-push the bookmark.</p>
<p>When your first PR has been approved, we typically invite you to the
<code>jj-vcs/contributors</code> team to give you contributor access,
so you can address any remaining minor comments and then merge the PR yourself
when you're ready. If you realize that some comments require non-trivial
changes, please ask your reviewer to take another look.</p>
<p>If your employer pays anyone (not necessarily you) to contribute to Jujutsu,
please make sure your GitHub username is <a href="../paid_contributors/">recorded</a>.
To avoid conflicts of interest, please don't merge a PR that has only been
approved by someone from the same organization. Similarly, as a reviewer, there
is no need to approve your coworkers' PRs, since the author should await an
approval from someone else anyway. It is of course still appreciated if you
review and comment on their PRs. Also, if the PR seems completely unrelated to
your company's interests, do feel free to approve it.</p>
<h3 id="community-guidelines">Community Guidelines<a class="headerlink" href="#community-guidelines" title="Permanent link">&para;</a></h3>
<p>This project follows <a href="https://opensource.google/conduct/">Google's Open Source Community
Guidelines</a>.</p>
<h2 id="contributing-large-patches">Contributing large patches<a class="headerlink" href="#contributing-large-patches" title="Permanent link">&para;</a></h2>
<p>Before sending a PR for a large change which designs/redesigns or reworks an
existing component, we require an architecture review from multiple
stakeholders, which we do with <a href="../design_docs/">Design Docs</a>, see the
<a href="../design_docs/#process">process here</a>.</p>
<h2 id="contributing-to-the-documentation">Contributing to the documentation<a class="headerlink" href="#contributing-to-the-documentation" title="Permanent link">&para;</a></h2>
<p>We appreciate <a href="https://github.com/jj-vcs/jj/issues/new?template=bug_report.md">bug
reports</a>
about any problems, however small, lurking in <a href="https://jj-vcs.github.io/jj/prerelease">our documentation
website</a> or in the <code>jj help
&lt;command&gt;</code> docs. If a part of the bug report template does not apply, you can
just delete it.</p>
<p>Before reporting a problem with the documentation website, we'd appreciate it if
you could check that the problem still exists in the "prerelease" version of the
documentation (as opposed to the docs for one of the released versions of <code>jj</code>).
You can use the version switcher in the top-left of the website to do so.</p>
<p>If you are willing to make a PR fixing a documentation problem, even better!</p>
<p>The documentation website sources are Markdown files located in the <a href="https://github.com/jj-vcs/jj/tree/main/docs"><code>docs/</code>
directory</a>. You do not need to
know Rust to work with them. See below for <a href="#previewing-the-html-documentation">instructions on how to preview the
HTML docs</a> as you edit the Markdown files.
Doing so is optional, but recommended.</p>
<p>The <code>jj help</code> docs are sourced from the "docstring" comments inside the Rust
sources, currently from the <a href="https://github.com/jj-vcs/jj/tree/main/cli/src/commands"><code>cli/src/commands</code>
directory</a>. Working
on them requires setting up a Rust development environment, as described
below, and may occasionally require adjusting a test.</p>
<h2 id="learning-rust">Learning Rust<a class="headerlink" href="#learning-rust" title="Permanent link">&para;</a></h2>
<p>In addition to the <a href="https://doc.rust-lang.org/book/">Rust Book</a> and the other
excellent resources at <a href="https://www.rust-lang.org/learn">https://www.rust-lang.org/learn</a>, we recommend the
<a href="https://google.github.io/comprehensive-rust/">"Comprehensive Rust" mini-course</a>
for an overview, especially if you are familiar with C++.</p>
<h2 id="setting-up-a-development-environment">Setting up a development environment<a class="headerlink" href="#setting-up-a-development-environment" title="Permanent link">&para;</a></h2>
<p>To develop <code>jj</code>, the mandatory steps are simply
to <a href="https://www.rust-lang.org/tools/install">install Rust</a> (the default
installer options are fine), clone the repository, and use <code>cargo build</code>
, <code>cargo fmt</code>,
<code>cargo clippy --workspace --all-targets</code>, and
<code>cargo test --workspace</code>. If you are preparing a PR, there are some additional
recommended steps.</p>
<h3 id="summary">Summary<a class="headerlink" href="#summary" title="Permanent link">&para;</a></h3>
<p>One-time setup:</p>
<div class="codehilite"><pre><span></span><code>rustup toolchain add nightly # wanted for &#39;rustfmt&#39;
rustup toolchain add 1.84 # also specified in Cargo.toml
cargo install --locked bacon
cargo install --locked cargo-insta
cargo install --locked cargo-nextest
</code></pre></div>
<p>During development (adapt according to your preference):</p>
<div class="codehilite"><pre><span></span><code>bacon clippy-all
cargo +nightly fmt # Occasionally
cargo nextest run --workspace # Occasionally
cargo insta test --workspace --test-runner nextest # Occasionally
</code></pre></div>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>Build artifacts from debug builds and especially from repeated
invocations of <code>cargo test</code> can quickly take up 10s of GB of disk space.
Cargo will happily use up your entire hard drive. If this happens, run
<code>cargo clean</code>.</p>
</div>
<h3 id="explanation">Explanation<a class="headerlink" href="#explanation" title="Permanent link">&para;</a></h3>
<p>These are listed roughly in order of decreasing importance.</p>
<ol>
<li>
<p>Nearly any change to <code>jj</code>'s CLI will require writing or updating snapshot
tests that use the <a href="https://insta.rs/"><code>insta</code></a> crate. To make this
convenient, install the <code>cargo-insta</code> binary.
Use <code>cargo insta test --workspace</code> to run tests,
and <code>cargo insta review --workspace</code> to update the snapshot tests.
The <code>--workspace</code> flag is needed to run the tests on all crates; by default,
only the crate in the current directory is tested.</p>
</li>
<li>
<p>GitHub CI checks require that the code is formatted with the <em>nightly</em>
version of <code>rustfmt</code>. To do this on your computer, install the nightly
toolchain and use <code>cargo +nightly fmt</code>.</p>
</li>
<li>
<p>Your code will be rejected if it cannot be compiled with the minimal
supported version of Rust ("MSRV"). Currently, <code>jj</code> follows a rather
casual MSRV policy: "The current <code>rustc</code> stable version, minus one."
As of this writing, that version is <strong>1.84.0</strong>.</p>
</li>
<li>
<p>Your code needs to pass <code>cargo clippy</code>. You can also
use <code>cargo +nightly clippy</code> if you wish to see more warnings.</p>
</li>
<li>
<p>You may also want to install and use <a href="https://dystroy.org/bacon/"><code>bacon</code></a>,
to automatically build, check, and / or run tests.</p>
</li>
<li>
<p>To run tests more quickly, use <code>cargo nextest run --workspace</code>. To
use <code>nextest</code> with <code>insta</code>, use <code>cargo insta test --workspace
--test-runner nextest</code>.</p>
<p>On Linux, you may be able to speed up <code>nextest</code> even further by using
the <code>mold</code> linker, as explained below.</p>
</li>
</ol>
<h3 id="configuring-jj-fix-to-run-rustfmt">Configuring <code>jj fix</code> to run <code>rustfmt</code><a class="headerlink" href="#configuring-jj-fix-to-run-rustfmt" title="Permanent link">&para;</a></h3>
<p>Run this in the jj repo:</p>
<div class="highlight"><pre><span></span><code>jj<span class="w"> </span>config<span class="w"> </span><span class="nb">set</span><span class="w"> </span>--repo<span class="w"> </span>fix.tools.rustfmt<span class="w"> </span><span class="s1">&#39;{ command = [&quot;rustfmt&quot;, &quot;+nightly&quot;], patterns = [&quot;glob:**/*.rs&quot;] }&#39;</span>
</code></pre></div>
<h3 id="using-mold-for-faster-tests-on-linux">Using <code>mold</code> for faster tests on Linux<a class="headerlink" href="#using-mold-for-faster-tests-on-linux" title="Permanent link">&para;</a></h3>
<p>On a machine with a multi-core CPU, one way to speed up
<code>cargo nextest</code> on Linux is to use the multi-threaded <a href="https://github.com/rui314/mold"><code>mold</code>
linker</a>. This linker may help
if, currently, your CPU is underused while Rust is linking test
binaries. Before proceeding with <code>mold</code>, you can check whether this is
an issue worth solving using a system monitoring tool such as <code>htop</code>.</p>
<p><code>mold</code> is packaged for many distributions. On Debian, for example,
<code>sudo apt install mold</code> should just work.</p>
<p>A simple way to use <code>mold</code> is via the <code>-run</code> option, e.g.:</p>
<div class="highlight"><pre><span></span><code>mold<span class="w"> </span>-run<span class="w"> </span>cargo<span class="w"> </span>insta<span class="w"> </span><span class="nb">test</span><span class="w"> </span>--workspace<span class="w"> </span>--test-runner<span class="w"> </span>nextest
</code></pre></div>
<p>There will be no indication that a different linker is used, except for
higher CPU usage while linking and, hopefully, faster completion. You
can verify that <code>mold</code> was indeed used by running
<code>readelf -p .comment target/debug/jj</code>.</p>
<p>There are also ways of having Rust use <code>mold</code> by default, see the <a href="https://github.com/rui314/mold#how-to-use">"How
to use" instructions</a>.</p>
<p>On recent versions of MacOS, the default linker Rust uses is already
multi-threaded. It should use all the CPU cores without any configuration.</p>
<h3 id="editor-setup">Editor setup<a class="headerlink" href="#editor-setup" title="Permanent link">&para;</a></h3>
<h4 id="visual-studio-code">Visual Studio Code<a class="headerlink" href="#visual-studio-code" title="Permanent link">&para;</a></h4>
<p>We recommend at least these settings:</p>
<div class="highlight"><pre><span></span><code><span class="p">{</span>
<span class="w"> </span><span class="s2">&quot;files.insertFinalNewline&quot;</span><span class="o">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;files.trimTrailingWhitespace&quot;</span><span class="o">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;[rust]&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="s2">&quot;files.trimTrailingWhitespace&quot;</span><span class="o">:</span><span class="w"> </span><span class="kc">false</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
<h4 id="zed">Zed<a class="headerlink" href="#zed" title="Permanent link">&para;</a></h4>
<div class="highlight"><pre><span></span><code><span class="c1">// .zed/settings.json</span>
<span class="p">{</span>
<span class="w"> </span><span class="s2">&quot;ensure_final_newline_on_save&quot;</span><span class="o">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;remove_trailing_whitespace_on_save&quot;</span><span class="o">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span>
<span class="w"> </span><span class="s2">&quot;languages&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// We don&#39;t use a formatter for Markdown files, so format_on_save would just</span>
<span class="w"> </span><span class="c1">// mess with others&#39; docs</span>
<span class="w"> </span><span class="s2">&quot;Markdown&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="s2">&quot;format_on_save&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;off&quot;</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="s2">&quot;Rust&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="s2">&quot;format_on_save&quot;</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;on&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="c1">// Avoid removing trailing spaces within multi-line string literals</span>
<span class="w"> </span><span class="s2">&quot;remove_trailing_whitespace_on_save&quot;</span><span class="o">:</span><span class="w"> </span><span class="kc">false</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="s2">&quot;lsp&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="s2">&quot;rust-analyzer&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="s2">&quot;initialization_options&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// If you are working on docs and don&#39;t need `cargo check`, uncomment</span>
<span class="w"> </span><span class="c1">// this option:</span>
<span class="w"> </span><span class="c1">//</span>
<span class="w"> </span><span class="c1">// &quot;checkOnSave&quot;: false,</span>
<span class="w"> </span><span class="c1">// Use nightly `rustfmt`, equivalent to `cargo +nightly fmt`</span>
<span class="w"> </span><span class="s2">&quot;rustfmt&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="s2">&quot;extraArgs&quot;</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;+nightly&quot;</span><span class="p">]</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</code></pre></div>
<h2 id="previewing-the-html-documentation">Previewing the HTML documentation<a class="headerlink" href="#previewing-the-html-documentation" title="Permanent link">&para;</a></h2>
<p>The documentation for <code>jj</code> is automatically published online at
<a href="https://jj-vcs.github.io/jj/">https://jj-vcs.github.io/jj/</a>.</p>
<p>When editing documentation, you should check your changes locally — especially
if you are adding a new page, or doing a major rewrite.</p>
<h3 id="install-uv">Install <code>uv</code><a class="headerlink" href="#install-uv" title="Permanent link">&para;</a></h3>
<p>The only thing you need is <a href="https://docs.astral.sh/uv/"><code>uv</code></a> (version 0.5.1 or newer).</p>
<p><code>uv</code> is a Python project manager written in Rust. It will fetch the right Python
version and the dependencies needed to build the docs. Install it like so:</p>
<div class="tabbed-set tabbed-alternate" data-tabs="1:5"><input checked="checked" id="__tabbed_1_1" name="__tabbed_1" type="radio" /><input id="__tabbed_1_2" name="__tabbed_1" type="radio" /><input id="__tabbed_1_3" name="__tabbed_1" type="radio" /><input id="__tabbed_1_4" name="__tabbed_1" type="radio" /><input id="__tabbed_1_5" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="__tabbed_1_1">macOS/Linux</label><label for="__tabbed_1_2">Windows</label><label for="__tabbed_1_3">Homebrew</label><label for="__tabbed_1_4">Cargo</label><label for="__tabbed_1_5">Other options</label></div>
<div class="tabbed-content">
<div class="tabbed-block">
<div class="copy highlight"><pre><span></span><code>curl<span class="w"> </span>-LsSf<span class="w"> </span>https://astral.sh/uv/install.sh<span class="w"> </span><span class="p">|</span><span class="w"> </span>sh
</code></pre></div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>If you don't have <code>~/.local/bin</code> in your <code>PATH</code>, the installer will
modify your shell profile. To avoid it:</p>
<div class="copy highlight"><pre><span></span><code>curl<span class="w"> </span>-LsSf<span class="w"> </span>https://astral.sh/uv/install.sh<span class="w"> </span><span class="p">|</span><span class="w"> </span>env<span class="w"> </span><span class="nv">INSTALLER_NO_MODIFY_PATH</span><span class="o">=</span><span class="m">1</span><span class="w"> </span>sh
</code></pre></div>
</div>
</div>
<div class="tabbed-block">
<div class="copy highlight"><pre><span></span><code>powershell<span class="w"> </span>-ExecutionPolicy<span class="w"> </span>ByPass<span class="w"> </span>-c<span class="w"> </span><span class="s2">&quot;irm https://astral.sh/uv/install.ps1 | iex&quot;</span>
</code></pre></div>
</div>
<div class="tabbed-block">
<div class="copy highlight"><pre><span></span><code>brew<span class="w"> </span>install<span class="w"> </span>uv
</code></pre></div>
</div>
<div class="tabbed-block">
<div class="copy highlight"><pre><span></span><code><span class="c1"># This might take a while</span>
cargo<span class="w"> </span>install<span class="w"> </span>--git<span class="w"> </span>https://github.com/astral-sh/uv<span class="w"> </span>uv
</code></pre></div>
</div>
<div class="tabbed-block">
<ul>
<li>Directly download the binaries from GitHub: <a href="https://github.com/astral-sh/uv/releases">uv releases</a>.</li>
<li>Even more options: <a href="https://docs.astral.sh/uv/getting-started/installation/">Installing uv</a>.</li>
</ul>
</div>
</div>
</div>
<h3 id="build-the-docs">Build the docs<a class="headerlink" href="#build-the-docs" title="Permanent link">&para;</a></h3>
<p>To build the docs, run from the root of the <code>jj</code> repository:</p>
<div class="copy highlight"><pre><span></span><code>uv<span class="w"> </span>run<span class="w"> </span>mkdocs<span class="w"> </span>serve
</code></pre></div>
<p>Open <a href="http://127.0.0.1:8000">http://127.0.0.1:8000</a> in your browser to see the docs.</p>
<p>As you edit the <code>.md</code> files in <code>docs/</code>, the website should be rebuilt and
reloaded in your browser automatically.</p>
<div class="admonition note">
<p class="admonition-title">If the docs are not updating</p>
<p>Check the terminal from which you ran <code>uv run mkdocs serve</code> for any build
errors or warnings. Warnings about <code>"GET /versions.json HTTP/1.1" code 404</code>
are expected and harmless.</p>
</div>
<h2 id="building-the-entire-website">Building the entire website<a class="headerlink" href="#building-the-entire-website" title="Permanent link">&para;</a></h2>
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p>Building the entire website is not usually necessary. If you are editing
documentation, the previous section is enough.</p>
<p>These instructions are relevant if you are working on the versioning of the
documentation that we currently do with <code>mike</code>.</p>
</div>
<p>The full <code>jj</code> website includes the documentation for several <code>jj</code> versions
(<code>prerelease</code>, latest release, and the older releases). The top-level
URL <a href="https://jj-vcs.github.io/jj">https://jj-vcs.github.io/jj</a> redirects to
<a href="https://jj-vcs.github.io/jj/latest">https://jj-vcs.github.io/jj/latest</a>, which in turn redirects to
the docs for the last stable version.</p>
<p>The different versions of documentation are managed and deployed with
<a href="https://github.com/jimporter/mike"><code>mike</code></a>, which can be run with
<code>uv run mike</code>.</p>
<p>On a POSIX system or WSL, one way to build the entire website is as follows (on
Windows, you'll need to understand and adapt the shell script):</p>
<ol>
<li>
<p>Check out <code>jj</code> as a co-located <code>jj + git</code> repository (<code>jj clone --colocate</code>),
cloned from your fork of <code>jj</code> (e.g. <code>github.com/jjfan/jj</code>). You can also use a
pure Git repo if you prefer.</p>
</li>
<li>
<p>Make sure <code>github.com/jjfan/jj</code> includes the <code>gh-pages</code> bookmark of the jj repo
and run <code>git fetch origin gh-pages</code>.</p>
</li>
<li>
<p>Go to the GitHub repository settings, enable GitHub Pages, and configure them
to use the <code>gh-pages</code> bookmark (this is usually the default).</p>
</li>
<li>
<p>Install <code>uv</code> as explained in <a href="#previewing-the-html-documentation">Previewing the HTML
documentation</a>, and run the same <code>sh</code> script
that is used in GitHub CI (details below):</p>
<div class="highlight"><pre><span></span><code>.github/scripts/docs-build-deploy<span class="w"> </span>prerelease<span class="w"> </span>main<span class="w"> </span>--push
</code></pre></div>
<p>This should build the version of the docs from the current commit,
deploy it as a new commit to the <code>gh-pages</code> bookmark,
and push the <code>gh-pages</code> bookmark to the origin.</p>
</li>
<li>
<p>Now, you should be able to see the full website, including your latest changes
to the <code>prerelease</code> version, at <code>https://jjfan.github.io/jj/prerelease/</code>.</p>
</li>
<li>
<p>(Optional) The previous steps actually only rebuild
<code>https://jjfan.github.io/jj/prerelease/</code> and its alias
<code>https://jjfan.github.io/jj/main/</code>. If you'd like to test out version switching
back and forth, you can also rebuild the docs for the latest release as follows.</p>
<div class="highlight"><pre><span></span><code>jj<span class="w"> </span>new<span class="w"> </span>v1.33.1<span class="w"> </span><span class="c1"># Let&#39;s say `jj 1.33.1` is the currently the latest release</span>
.github/scripts/docs-build-deploy<span class="w"> </span>v1.33.1<span class="w"> </span>latest<span class="w"> </span>--push
</code></pre></div>
</li>
<li>
<p>(Optional) When you are done, you may want to reset the <code>gh-pages</code> bookmark to the
same spot as it is upstream. If you configured the "upstream" remote,
this can be done with:</p>
<div class="highlight"><pre><span></span><code><span class="c1"># This will LOSE any changes you made to `gh-pages`</span>
jj<span class="w"> </span>git<span class="w"> </span>fetch<span class="w"> </span>--remote<span class="w"> </span>upstream
jj<span class="w"> </span>bookmark<span class="w"> </span><span class="nb">set</span><span class="w"> </span>gh-pages<span class="w"> </span>-r<span class="w"> </span>gh-pages@upstream
jj<span class="w"> </span>git<span class="w"> </span>push<span class="w"> </span>--remote<span class="w"> </span>origin<span class="w"> </span>--bookmark<span class="w"> </span>gh-pages
</code></pre></div>
<p>If you want to preserve some of the changes you made, you can do <code>jj bookmark
set my-changes -r gh-pages</code> BEFORE running the above commands.</p>
</li>
</ol>
<h3 id="explanation-of-the-docs-build-deploy-script">Explanation of the <code>docs-build-deploy</code> script<a class="headerlink" href="#explanation-of-the-docs-build-deploy-script" title="Permanent link">&para;</a></h3>
<p>The script sets up a few environment variables and invokes <code>uv run mike deploy</code>
with some default arguments and whatever arguments were passed to
<code>docs-build-deploy</code>. Run <code>uv run mike help deploy</code> to find out what the
arguments do.</p>
<p>If you need to do something more complicated, you can use <code>uv run mike
...</code> commands. You can also edit the <code>gh-pages</code> bookmark directly, but take care
to avoid files that will be overwritten by future invocations of <code>mike</code>. Then,
you can submit a PR based on the <code>gh-pages</code> bookmark of
<a href="https://jj-vcs.github.com/jj">https://jj-vcs.github.com/jj</a> (instead of the usual <code>main</code> bookmark).</p>
<p>Previously, the version switcher would not work unless the value of the
<code>site_url</code> config in <code>mkdocs.yml</code> matched the actual URL the site is being
served from. This bug should now be fixed, but if you are not serving the site
from https://jj-vcs.github.com/jj and something does not work weirdly, you might
want to adjust the <code>site_url</code> to something like <code>https://jjfan.github.io/jj</code>.</p>
<h2 id="modifying-protobuffers-this-is-not-common">Modifying protobuffers (this is not common)<a class="headerlink" href="#modifying-protobuffers-this-is-not-common" title="Permanent link">&para;</a></h2>
<p>Occasionally, you may need to change the <code>.proto</code> files that define jj's data
storage format. In this case, you will need to add a few steps to the above
workflow.</p>
<ul>
<li>Install the <code>protoc</code> compiler. This usually means either <code>apt-get install
protobuf-compiler</code> or downloading <a href="https://github.com/protocolbuffers/protobuf/releases">an official release</a>. The
<code>prost</code> <a href="https://docs.rs/prost-build/latest/prost_build/#sourcing-protoc">library docs</a> have additional advice.</li>
<li>Run <code>cargo run -p gen-protos</code> regularly (or after every edit to a <code>.proto</code>
file). This is the same as running <code>cargo run</code> from <code>lib/gen-protos</code>. The
<code>gen-protos</code> binary will use the <code>prost-build</code> library to compile the
<code>.proto</code> files into <code>.rs</code> files.</li>
<li>If you are adding a new <code>.proto</code> file, you will need to edit the list of
these files in <code>lib/gen-protos/src/main.rs</code>.</li>
</ul>
<p>The <code>.rs</code> files generated from <code>.proto</code> files are included in the repository,
and there is a GitHub CI check that will complain if they do not match.</p>
<h2 id="logging">Logging<a class="headerlink" href="#logging" title="Permanent link">&para;</a></h2>
<p>You can print internal jj logs using <code>JJ_LOG</code>. It acts like the <code>RUST_LOG</code>
environment variable, frequent in Rust codebases, and accepts one or more
<a href="https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html#directives">directives</a>. You can also run <code>JJ_LOG=debug jj</code> to get <code>debug</code> level logs
enabled for all targets. You can also use the <code>--debug</code> global option, which
turns on <code>debug</code> log level for <code>jj-lib</code> and <code>jj-cli</code> only.</p>
<h2 id="profiling">Profiling<a class="headerlink" href="#profiling" title="Permanent link">&para;</a></h2>
<p>One easy-to-use sampling profiler
is <a href="https://github.com/mstange/samply">samply</a>. For example:
<div class="highlight"><pre><span></span><code>cargo<span class="w"> </span>install<span class="w"> </span>samply
samply<span class="w"> </span>record<span class="w"> </span>jj<span class="w"> </span>diff
</code></pre></div>
Then just open the link it prints.</p>
<p>Another option is to use the instrumentation we've added manually (using
<code>tracing::instrument</code>) in various places. For example:
<div class="highlight"><pre><span></span><code><span class="nv">JJ_TRACE</span><span class="o">=</span>/tmp/trace.json<span class="w"> </span>jj<span class="w"> </span>diff
</code></pre></div>
Then go to <code>https://ui.perfetto.dev/</code> in Chrome and load <code>/tmp/trace.json</code> from
there.</p>
</article>
</div>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"base": "..", "features": [], "search": "../assets/javascripts/workers/search.f8cc74c7.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": {"alias": true, "provider": "mike"}}</script>
<script src="../assets/javascripts/bundle.f1b6f286.min.js"></script>
</body>
</html>