Repository navigation
fix(core): resolve git rerun paths so worktree builds stay fresh - #4947
Merged
Merged
Conversation
In a git worktree .git is a file, so the hard-coded ../../.git/* rerun-if-changed paths never exist and cargo rebuilds openshell-core and every dependent crate on each invocation. Resolve HEAD and logs/HEAD from the git dir and tag refs, packed-refs, and the checked-out branch ref from the common git dir, and only emit paths that exist. Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
matthewgrossman
approved these changes
Oct 30, 2026
This was referenced Oct 31, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Every cargo command in a git worktree rebuilt
openshell-coreand everything that depends on it, even with no changes.mise run rust:lintre-clippied the whole workspace on each run, which made the pre-commit hook take minutes.The cause is in
openshell-core/build.rs. It tells cargo to watch../../.git/HEADand a few other files under../../.git/. In a worktree.gitis a small file, not a directory, so those paths don't exist. Cargo treats a missing watched path as changed and reruns the build script every time. The fingerprint log shows it asMissingFile { path: ".../crates/openshell-core/../../.git/HEAD" }.This PR asks git where those files really are.
Background
The build script bakes a version like
0.1.6-dev.51+g5aea12245into the binaries. It derives it from git: the last release tag, the number of commits since, and the short SHA. The watched paths make cargo recompute it after a commit or a new tag. Without them the version would go stale.History of the watched paths:
.git/HEADand.git/refs/tagsalong with the git-derived version.openshell-coreand its dependents on every commit. Revert "perf(build): speed up local CLI rebuilds" #1395 reverted it the same day..git/logs/HEADand.git/packed-refs.All of them assume
.gitis a directory at the repo root. That's only true for the main checkout. Linked worktrees (including ones made from a bare repo), submodules, and--separate-git-dirclones all have a.gitfile like this one:That directory holds the worktree's own
HEADandlogs/HEAD. Branches, tags andpacked-refsstay in the main.git, which git calls the common dir.git rev-parse --git-dirandgit rev-parse --git-common-dirreturn the right directory in every layout. In a normal clone both return the same.gitas before, so rebuild behavior there doesn't change.Related Issue
No issue required. This is a small build-script fix.
Changes
HEADandlogs/HEADin the directory fromgit rev-parse --git-dir.refs/tags,packed-refsand the checked-out branch ref in the directory fromgit rev-parse --git-common-dir.logs/HEADuntil its first commit, and theHEADfile doesn't change when you commit on a branch.Testing
mise run pre-commitpassesI ran
cargo clippy -p openshell-core --all-targets -- -D warningsin a worktree:openshell-core.0.1.6-dev.50+gc4688aa87to0.1.6-dev.51+g5aea12245.I also timed
mise run rust:lintin a worktree, with a shared sccache dir. Each run touched one file first, or none for the first row. Each build.rs version got one warm-up run.openshell-cli/src/main.rsopenshell-server/src/lib.rsopenshell-policy/src/lib.rsopenshell-core/src/lib.rsThe last column is summed over the 7 clippy commands in
rust:lint. Before the fix every run re-checked the whole workspace, whatever changed. After it, only the touched crate and the crates that depend on it are re-checked. sccache doesn't help here because it doesn't cache clippy: every run reported 0 cache hits.The main checkout was never affected, since the old
../../.gitpaths exist there.In the main checkout I confirmed both git commands point at the same
.gitpaths the old code used. I didn't build there.Checklist