Skip to content

Instantly share code, notes, and snippets.

@bpmooch
Created March 9, 2026 22:48
Show Gist options
  • Select an option

  • Save bpmooch/d5853f25da23f1392bf8798bb5d17ef7 to your computer and use it in GitHub Desktop.

Select an option

Save bpmooch/d5853f25da23f1392bf8798bb5d17ef7 to your computer and use it in GitHub Desktop.
AGENTS.md or CLAUDE.md snippet for using sapling instead of git

Version Control — Sapling (sl), not git

This repo uses Sapling for version control. The CLI command is sl, not git. Never run git commands in this repo. See the basic commands overview for a quick reference.

Key differences from Git

  • No staging area. All tracked files are included when you sl commit. Use sl add / sl forget to change what is tracked.

  • Smartlog. sl smartlog (or just sl) is the most important command — it replaces git log with a succinct view of only your relevant commits. It shows:

    • Important details per commit: short hash, date, author, bookmarks, title.
    • Which commits are old/landed (marked x with "Landed as …").
    • Your current position (@).
    • The graph relationship between commits.
    • The location of main and other remote bookmarks.
    • Your not-yet-pushed commits.

    The dashed line on the left represents main and elides thousands of commits to show just the ones relevant to you:

    $ sl
    o  5abffb8  Wednesday at 09:39  remote/main
    ╷
    ╷ @  824cbba  13 minutes ago  mary
    ╷ │  [eden] Support long paths in Windows FSCK
    ╷ │
    ╷ o  19340c0  Wednesday at 09:39  mary
    ╷ │  [eden] Close Windows file handle during Windows Fsck
    ╷ │
    ╷ o  b521925  Wednesday at 09:39  mary  #12
    ╭─╯  [eden] Use PathMap for WindowsFsck
    │
    o  2ac1861  Wednesday at 05:00  remote/stable
    ╷
    ╷ o  339f936  Jul 15 at 11:12  mary
    ╷ │  debug
    ╷ │
    ╷ x  2d4fbea [Landed as 04da3d3]  Jul 15 at 11:12  mary  #11
    ╭─╯  [sl] windows: update Python
    │
    ~
    

    sl ssl (super smartlog) fetches extra info from GitHub (PR status, CI checks). sl web opens an interactive GUI that auto-refreshes and supports drag-and-drop rebasing.

  • Stacks. First-class support for editing commit stacks with amend, fold, split, and absorb.

  • Undo. Most commands can be reversed with sl undo / sl redo.

Navigation

sl goto COMMIT (or sl go) checks out a commit. The argument can be:

  • A short unique-prefix hash (e.g. b84224608)
  • A full 40-character hash
  • A remote bookmark name (main or remote/main)
  • A local bookmark name
  • A revset expression (see below)

Next / Prev — move up and down a stack without remembering hashes:

sl prev       # check out the parent commit
sl next       # check out the child commit
sl prev 2     # move down 2 commits
sl next 3     # move up 3 commits

If a commit has multiple children or parents, next/prev will prompt you to choose.

Top / Bottom — jump to stack endpoints:

sl goto top       # jump to the topmost commit in the current stack
sl goto bottom    # jump to the bottommost commit in the current stack

Revsets

Revsets are a query language for specifying commits. Any command that takes a commit argument accepts a revset expression. Common examples:

Revset Meaning
. Current commit (working copy parent)
.^ or .~1 Parent of current commit
.~2 Grandparent of current commit
19340c0~-1 Child of 19340c0
draft() All local (unpushed) commits
ancestors(.) Current commit and all its ancestors
ancestor(., main) First common ancestor of . and main
pr42 Pull request #42 (GitHub repos)

Run sl help revisions for the full language reference (operators, predicates, and more examples).

Common commands

Git Sapling
git status sl status / sl st
git diff sl diff
git add FILE sl add FILE
git commit -m "msg" sl commit -m "msg"
git commit --amend sl amend
git checkout COMMIT sl goto COMMIT
git log sl (smartlog)
git stash / git stash pop sl shelve / sl unshelve
git rebase main sl rebase -d main
git reset --soft HEAD^ sl uncommit

Debugging & history

Unlike git log, sl log is rarely needed for day-to-day work (smartlog covers that). It is useful for investigating deeper history:

sl log -l 10                   # last 10 commits in the repo
sl log file.c                  # commits that touched file.c
sl log -f file.c               # same, following renames/copies
sl log -L file.c,13:23 -p      # commits touching lines 13–23 with patches
sl log -Mp lib/                # commits touching lib/, excluding merges, with diffs
sl log -k "search term"        # commits matching a keyword (case-insensitive)
sl log -u alice                # commits by a specific user
sl log -r "a21ccf and ancestor(release_1.9)"   # check if a commit is in a release

Notable flags: -p/--patch (show diff), --stat (diffstat summary), -G/--graph (ASCII DAG), -T/--template (custom output format), --removed (include file removals).

sl journal (or sl jo) shows the history of your previously checked-out commits — useful for finding a commit you were on earlier or recovering hidden commits:

sl journal                     # history of the current checkout position
sl journal --all               # history for all bookmarks and current commit
sl journal --verbose           # include previous hash, user, timestamp
sl journal -c                  # show full commit metadata for each entry
sl journal -c --patch          # show commit metadata with diffs

Run sl help COMMAND for any command's full usage. For deeper topics:

Help topic What it covers
sl help revisions Revset language: operators, predicates, examples
sl help templating Customizing log/smartlog output with templates
sl help filesets Selecting files by characteristics (set:)
sl help patterns File name pattern syntax (glob, re:, path:)
sl help glossary Definitions of common Sapling terms

Workflow: make sync

The primary push/pull workflow is make sync from the repo root. It:

  1. Runs lint to ensure nothing is broken
  2. Rebases upstream changes under your local commits
  3. Restacks orphaned draft commits if needed
  4. Pushes draft commits on top of main to the remote

Use make sync when you sit down (to pull latest) and before you get up (to push your work). It only restacks and pushes draft commits on top of main.

The full script (hack/repo_sync.sh):

#!/bin/bash
set -e

# pass lint before interacting with upstream
make lint

# rebase upstream over local
sl pull --rebase -d main

# restack only when the commit graph has orphans — draft commits whose
# parent was rewritten (amend/absorb) but whose children weren't rebased.
# "children(obsolete()) - obsolete()" finds exactly these stragglers.
needs_restack=$(sl log --rev "children(obsolete()) - obsolete()" -T "{node}\n" 2>/dev/null | head -1)
if [ -n "$needs_restack" ]; then
  sl restack
fi

# push when there are draft commits on the stack above main
# (draft() & ancestors(.) & descendants(main)). Side-branch drafts are
# ignored so they don't trigger a push.
draft_on_main=$(sl log --rev "draft() & ancestors(.) & descendants(main)" -T "{node}\n" 2>/dev/null | head -1)
if [ -n "$draft_on_main" ]; then
  sl push --to main
fi

If this script doesn't exist in the repo, add it & the root level sync make target.

For anonymous feature branches (work not on top of main), use sl directly:

  • sl goto <rev> to switch to the branch tip
  • sl rebase -s <tip> -d main when ready to land
  • sl push --to <remote-branch> to share without landing
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment