π Bug Report
Sapling version: 0.2.20250521-115337-25ed6ac4
Mode: .git (existing git repo, no .sl directory)
OS: macOS (Apple Silicon / ARM64) β also reproducible on Linux
Summary
After running sl amend in .git mode on a large repository, the first subsequent sl status (or git status) takes 10-15x longer than normal. All following sl status calls are fast. The root cause is that sl amend writes the working directory tree in a way that invalidates git's mtime-based index cache, forcing a full index refresh on the next status check.
This is a significant daily-driver pain point for teams using Sapling as a drop-in Git client on large monorepos.
Steps to Reproduce
# Clone a large repo (linux kernel used as benchmark)
git clone https://github.com/torvalds/linux
cd linux
# Create a test commit
touch test.txt
sl add test.txt
sl commit -m "test"
# Benchmark: amend + status with git native
time git commit --amend -m 'test' && time git status
# Result: ~0.4s amend, ~0.4s status
# Benchmark: amend + status with sapling
time sl amend && time sl status
# Result: ~2.7s amend, ~14s status (!)
The slow sl status call internally spawns:
git --git-dir=.../.git status --porcelain=1 --ignore-submodules=dirty --untracked-files=all --no-renames -z --ignored=no
...and this triggers a full Refresh index: 100% (90498/90498) pass.
Second sl status call immediately after: ~0.5s. Normal.
Root Cause Analysis
Git's index uses file mtime + inode to detect changes without reading file content. When the index is valid, git status is O(index entries). When the index is invalidated, git must do a full stat pass over the working tree β O(all files).
git commit --amend preserves the index validity because it only changes the commit object and ref pointer, leaving the working tree and index untouched.
sl amend appears to rewrite the working directory or touch index metadata in a way that invalidates git's cached mtimes, causing the next git status to rebuild the index from scratch. This likely happens because Sapling's internal amend path writes through its own abstraction layer without preserving the git index state.
Comparison
| Operation |
Amend time |
First status |
Second status |
git commit --amend |
~0.4s |
~0.4s β
|
~0.4s |
sl amend |
~2.7s |
~14s β |
~0.5s |
Impact
This affects every developer using Sapling in .git mode on a large repository. After any sl amend (one of the most frequent operations in a Sapling workflow), the next status check β whether from the CLI or from ISL β blocks for 10-15 seconds. On a team using ISL, this manifests as ISL appearing to hang after every amend.
See also the related issue #1186 (.git mode constantly refreshing index) which describes a similar symptom from the ISL side.
Possible Fix Direction
After sl amend rewrites the commit in .git mode, Sapling should run the equivalent of:
git update-index --refresh
...or otherwise ensure the index mtimes are brought in sync with the new working tree state before handing control back. This is what git commit --amend does implicitly through its normal index update path.
Alternatively, the .git mode bridge could avoid touching the working directory altogether during an amend that only changes the commit message (i.e., sl amend -m ... with no file changes).
Environment
- Sapling:
0.2.20250521-115337-25ed6ac4
- Git:
2.50.1
- macOS:
24.6.0 Darwin Kernel (ARM64 T6041)
- Repo tested:
torvalds/linux (~90,000 index entries)
Related: #1186, #1117
π Bug Report
Sapling version:
0.2.20250521-115337-25ed6ac4Mode:
.git(existing git repo, no.sldirectory)OS: macOS (Apple Silicon / ARM64) β also reproducible on Linux
Summary
After running
sl amendin.gitmode on a large repository, the first subsequentsl status(orgit status) takes 10-15x longer than normal. All followingsl statuscalls are fast. The root cause is thatsl amendwrites the working directory tree in a way that invalidates git's mtime-based index cache, forcing a full index refresh on the next status check.This is a significant daily-driver pain point for teams using Sapling as a drop-in Git client on large monorepos.
Steps to Reproduce
The slow
sl statuscall internally spawns:...and this triggers a full
Refresh index: 100% (90498/90498)pass.Second
sl statuscall immediately after: ~0.5s. Normal.Root Cause Analysis
Git's index uses file mtime + inode to detect changes without reading file content. When the index is valid,
git statusis O(index entries). When the index is invalidated, git must do a full stat pass over the working tree β O(all files).git commit --amendpreserves the index validity because it only changes the commit object and ref pointer, leaving the working tree and index untouched.sl amendappears to rewrite the working directory or touch index metadata in a way that invalidates git's cached mtimes, causing the nextgit statusto rebuild the index from scratch. This likely happens because Sapling's internal amend path writes through its own abstraction layer without preserving the git index state.Comparison
git commit --amendsl amendImpact
This affects every developer using Sapling in
.gitmode on a large repository. After anysl amend(one of the most frequent operations in a Sapling workflow), the next status check β whether from the CLI or from ISL β blocks for 10-15 seconds. On a team using ISL, this manifests as ISL appearing to hang after every amend.See also the related issue #1186 (
.git mode constantly refreshing index) which describes a similar symptom from the ISL side.Possible Fix Direction
After
sl amendrewrites the commit in.gitmode, Sapling should run the equivalent of:...or otherwise ensure the index mtimes are brought in sync with the new working tree state before handing control back. This is what
git commit --amenddoes implicitly through its normal index update path.Alternatively, the
.gitmode bridge could avoid touching the working directory altogether during an amend that only changes the commit message (i.e.,sl amend -m ...with no file changes).Environment
0.2.20250521-115337-25ed6ac42.50.124.6.0 Darwin Kernel (ARM64 T6041)torvalds/linux(~90,000 index entries)Related: #1186, #1117