Visitar URL original
wt merge | WorktrunkSkip to content

wt merge

Merge a branch into the target branch. Squash & rebase, fast-forward the target branch, remove the worktree.

Unlike git merge, this merges a source branch into the target branch, not the target into the current branch. Similar to clicking “Merge pull request” on GitHub, but locally. The source defaults to the current branch (--branch names another); the target defaults to the default branch.

wt merge demo
Creating a worktree, committing in it, and merging it away

Merge to the default branch:

wt merge
◎ Running pre-merge project:test
cargo nextest run
Finished `test` profile [unoptimized + debuginfo] target(s) in 0.02s
Summary [ 0.002s] 2 tests run: 2 passed, 0 skipped
◎ Merging 1 commit to main @ a1b2c3d (no commit/squash/rebase needed)
* a1b2c3d feat: add hook registration
hook.rs | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
✓ Merged to main (1 commit, 1 file, +31)
◎ Removing hooks worktree & branch in background (same commit as main, _)
○ Switched to worktree for main @ ~/repo

Merge to a different branch:

wt merge develop

Merge another worktree’s branch without leaving the current worktree:

wt merge --branch feature/auth
wt merge develop --branch feature/auth

The source branch must have a checked-out worktree. Commit, squash, rebase, and hooks use that worktree and its project configuration. Cleanup removes the source worktree; the invoking worktree stays in place. A rebase conflict is left in the source worktree to resolve or abort.

Keep the worktree after merging:

wt merge --no-remove

Preserve commit history (no squash):

wt merge --no-squash

Create a merge commit — rebased semi-linear history by default:

wt merge --no-ff

Skip committing/squashing (rebase still runs unless —no-rebase):

wt merge --no-commit

Preserve the exact clean commit graph and tip:

wt merge --no-commit --no-rebase

wt merge runs these steps:

  1. Commit — Pre-commit hooks run, then uncommitted changes are committed. Post-commit hooks run in the background. This step is skipped when squashing (the default) — changes are staged during the squash step instead. With --no-squash, this is the only commit step.
  2. Squash — Combines all commits since target into one (like GitHub’s “Squash and merge”). Pre-commit hooks see the staged changes, and their edits are staged into the squash commit; post-commit hooks run in the background after committing. Use --stage to control what gets staged: all (default), tracked, or none. Working-tree changes swept into the squash are backed up first to refs/wt-backup/<branch>; see wt step squash for recovery. With --no-squash, individual commits are preserved.
  3. Rebase — Rebases onto target, skipping when nothing needs replaying (wt step rebase gives the conditions). A conflict stops the merge with the rebase left open in the worktree, to resolve or abort. With --no-rebase, the graph produced by earlier commit/squash steps is preserved and the target must be able to fast-forward to its tip.
  4. Pre-merge hooks — Hooks run after rebase, before merge. Failures abort. See wt hook.
  5. Merge — Fast-forward merge to the target branch (wt step push). With --no-ff, a merge commit is created instead — semi-linear history after the default rebase, while explicit --no-rebase preserves the graph produced by earlier steps before adding the merge commit. Non-fast-forward merges are rejected.
  6. Pre-remove hooks — Hooks run before removing worktree. Failures abort.
  7. Cleanup — Removes the worktree and branch. Use --no-remove to keep the worktree. When already on the target branch, in the primary worktree, locked, or containing another registered worktree, the worktree is preserved.
  8. Post-remove + post-merge hooks — Run in background after cleanup.

Use --no-commit to skip committing uncommitted changes and squashing; rebase still runs by default and can rewrite commits unless --no-rebase is passed. Combining both flags preserves the exact source graph and requires the target to be its ancestor. Useful after preparing commits manually with wt step commit. Requires a clean working tree.

wt merge merges into the local target branch and never fetches.

Pre-merge hooks run checks locally before merging. A failed check stops the merge:

.config/wt.toml
[[pre-merge]]
test = "cargo test"
lint = "cargo clippy"
  • wt step — Run individual operations (commit, squash, rebase, push)
  • wt remove — Remove worktrees without merging
  • wt switch — Navigate to other worktrees
wt merge - Merge a branch into the target branch
Squash & rebase, fast-forward the target branch, remove the worktree.
Usage: wt merge [OPTIONS] [TARGET]
Arguments:
[TARGET]
Target branch
Defaults to default branch.
Options:
-b, --branch <BRANCH>
Branch to merge (defaults to the current branch)
--no-squash
Skip commit squashing
--no-commit
Skip commit and squash
--no-rebase
Skip rebase; require the target to fast-forward to the resulting tip
--no-remove
Keep worktree after merge
--no-ff
Create a merge commit (no fast-forward)
--stage <STAGE>
What to stage before committing [default: all]
Possible values:
- all: Stage everything: untracked files + unstaged tracked changes
- tracked: Stage tracked changes only (like git add -u)
- none: Stage nothing, commit only what's already in the index
-h, --help
Print help (see a summary with '-h')
Automation:
--no-hooks
Skip hooks
--format <FORMAT>
Output format
JSON prints structured result to stdout after merge completes.
[default: text]
[possible values: text, json]
Global Options:
-C <path>
Working directory for this command
--config <path>
User config file path
--config-set <toml>
Override config with inline TOML, e.g. --config-set list.full=true (repeatable)
-v, --verbose...
Verbose output (-v: info logs + hook/alias template variables on stderr; -vv: also debug
logs and raw subprocess output written to .git/wt/logs/). Set WORKTRUNK_VERBOSE=0|1|2 to
apply the same level everywhere — including shell completion, which no flag can reach
-y, --yes
Skip approval prompts