Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/src/content/docs/hook.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ All hooks share the same perspective — `{{ branch | hash_port }}` produces the

- `pre-switch`: hook runs in the source worktree; `worktree_path` is the destination when that worktree already exists — a switch that creates one has no destination directory yet, so `worktree_path` stays on the source (use `pre-start` to work in the new worktree)
- `post-remove`: the active worktree is gone, so the hook runs in the primary worktree
- `post-merge` with removal: the active worktree is gone, so the hook runs in the target worktree
- `post-merge`: the hook runs in the target branch's worktree (the primary worktree if the target has none), including under `--no-remove`, where the merged worktree `worktree_path` names is still on disk

Undefined variables error — use conditionals or defaults for optional behavior:

Expand Down
2 changes: 1 addition & 1 deletion plugins/worktrunk/skills/worktrunk/reference/hook.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion skills/worktrunk/reference/hook.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1762,7 +1762,7 @@ All hooks share the same perspective — `{{ branch | hash_port }}` produces the

- `pre-switch`: hook runs in the source worktree; `worktree_path` is the destination when that worktree already exists — a switch that creates one has no destination directory yet, so `worktree_path` stays on the source (use `pre-start` to work in the new worktree)
- `post-remove`: the active worktree is gone, so the hook runs in the primary worktree
- `post-merge` with removal: the active worktree is gone, so the hook runs in the target worktree
- `post-merge`: the hook runs in the target branch's worktree (the primary worktree if the target has none), including under `--no-remove`, where the merged worktree `worktree_path` names is still on disk

Undefined variables error — use conditionals or defaults for optional behavior:

Expand Down
39 changes: 39 additions & 0 deletions tests/integration_tests/merge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,45 @@ fn test_merge_post_merge_runs_with_nothing_to_merge(mut repo: TestRepo) {
wait_for_file(&marker_file);
}

#[rstest]
fn test_merge_post_merge_runs_in_destination_with_no_remove(mut repo: TestRepo) {
// `--no-remove` keeps the feature worktree, but `post-merge` is anchored on
// the merge destination either way: the hook's cwd is the target worktree,
// not the preserved feature worktree its `worktree_path` names.
let config_dir = repo.root_path().join(".config");
fs::create_dir_all(&config_dir).unwrap();
fs::write(
config_dir.join("wt.toml"),
r#"post-merge = "echo ran > post-merge-cwd.txt""#,
)
.unwrap();
repo.commit("Add config");

let feature_wt = repo.add_worktree("feature");
fs::write(feature_wt.join("feature.txt"), "feature content").unwrap();

let output = repo
.wt_command()
.args(["merge", "main", "--no-remove", "--yes"])
.current_dir(&feature_wt)
.output()
.unwrap();
assert!(
output.status.success(),
"merge failed:\n{}",
String::from_utf8_lossy(&output.stderr)
);

// The hook wrote its marker relative to its cwd: the destination worktree.
wait_for_file(&repo.root_path().join("post-merge-cwd.txt"));
let feature_marker = feature_wt.join("post-merge-cwd.txt");
assert!(
!feature_marker.exists(),
"post-merge ran in the preserved feature worktree: {}",
feature_marker.display()
);
}

#[rstest]
fn test_merge_post_merge_runs_from_main_branch(repo: TestRepo) {
// Verify post-merge hooks run when merging from main to main (nothing to do)
Expand Down
Loading