Fix sparse checkout leaking to main repo by using git sparse-checkout set
Replace manual git config + file write + read-tree with `git sparse-checkout set --no-cone` which correctly isolates sparse checkout config to the worktree without polluting the shared .git/config. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -160,56 +160,31 @@ fn create_worktree_sync(
|
|||||||
/// This prevents pipeline file moves (upcoming → current → qa → merge → archived)
|
/// This prevents pipeline file moves (upcoming → current → qa → merge → archived)
|
||||||
/// from being committed on feature branches, which avoids rename/delete merge
|
/// from being committed on feature branches, which avoids rename/delete merge
|
||||||
/// conflicts when merging back to master.
|
/// conflicts when merging back to master.
|
||||||
|
///
|
||||||
|
/// Uses `git sparse-checkout set --no-cone` which correctly isolates the
|
||||||
|
/// config to the worktree without polluting the main checkout's config.
|
||||||
fn configure_sparse_checkout(wt_path: &Path) -> Result<(), String> {
|
fn configure_sparse_checkout(wt_path: &Path) -> Result<(), String> {
|
||||||
// Enable worktree-specific config so sparse checkout settings don't leak
|
// `git sparse-checkout set --no-cone` handles everything:
|
||||||
// to the main checkout or other worktrees.
|
// - Enables core.sparseCheckout for this worktree only
|
||||||
let _ = Command::new("git")
|
// - Writes the pattern file to the correct worktree-specific git dir
|
||||||
.args(["config", "extensions.worktreeConfig", "true"])
|
// - Updates the working tree
|
||||||
.current_dir(wt_path)
|
//
|
||||||
.output();
|
// The '!' prefix excludes .story_kit/work/ while '/*' includes everything else.
|
||||||
|
|
||||||
// Enable sparse checkout for THIS worktree only (--worktree flag).
|
|
||||||
// Without --worktree, this writes to the shared .git/config and
|
|
||||||
// enables sparse checkout on the main checkout too.
|
|
||||||
let output = Command::new("git")
|
let output = Command::new("git")
|
||||||
.args(["config", "--worktree", "core.sparseCheckout", "true"])
|
.args([
|
||||||
|
"sparse-checkout",
|
||||||
|
"set",
|
||||||
|
"--no-cone",
|
||||||
|
"/*",
|
||||||
|
"!.story_kit/work/",
|
||||||
|
])
|
||||||
.current_dir(wt_path)
|
.current_dir(wt_path)
|
||||||
.output()
|
.output()
|
||||||
.map_err(|e| format!("sparse-checkout config: {e}"))?;
|
.map_err(|e| format!("git sparse-checkout set: {e}"))?;
|
||||||
|
|
||||||
if !output.status.success() {
|
if !output.status.success() {
|
||||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||||
return Err(format!("sparse-checkout config failed: {stderr}"));
|
return Err(format!("git sparse-checkout set failed: {stderr}"));
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve the actual git dir (worktrees use a .git file pointing elsewhere)
|
|
||||||
let git_dir_output = Command::new("git")
|
|
||||||
.args(["rev-parse", "--git-dir"])
|
|
||||||
.current_dir(wt_path)
|
|
||||||
.output()
|
|
||||||
.map_err(|e| format!("git rev-parse --git-dir: {e}"))?;
|
|
||||||
|
|
||||||
let git_dir = PathBuf::from(
|
|
||||||
String::from_utf8_lossy(&git_dir_output.stdout).trim().to_string(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Write sparse-checkout patterns: include everything, exclude .story_kit/work/
|
|
||||||
let info_dir = git_dir.join("info");
|
|
||||||
std::fs::create_dir_all(&info_dir)
|
|
||||||
.map_err(|e| format!("Create sparse-checkout dir: {e}"))?;
|
|
||||||
std::fs::write(info_dir.join("sparse-checkout"), "/*\n!.story_kit/work/\n")
|
|
||||||
.map_err(|e| format!("Write sparse-checkout: {e}"))?;
|
|
||||||
|
|
||||||
// Re-read the working tree to apply sparse checkout rules
|
|
||||||
let output = Command::new("git")
|
|
||||||
.args(["read-tree", "-mu", "HEAD"])
|
|
||||||
.current_dir(wt_path)
|
|
||||||
.output()
|
|
||||||
.map_err(|e| format!("git read-tree: {e}"))?;
|
|
||||||
|
|
||||||
if !output.status.success() {
|
|
||||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
||||||
return Err(format!("git read-tree failed: {stderr}"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
Reference in New Issue
Block a user