# How to Implement Merge-Only Copies Without Moving the Card in SwarmForge

> Learn to implement merge only copies in SwarmForge without moving cards. Keep your original card position while merging and processing branches efficiently.

- Repository: [Robert C. Martin/swarm-forge](https://github.com/unclebob/swarm-forge)
- Tags: how-to-guide
- Published: 2026-09-01

---

**Create a copy of a SwarmForge card branch, merge it into your target branch, and trigger processing—all while keeping the original card in its queue position by omitting queue-moving helpers.**

SwarmForge is a git-centric workflow system where every work item exists as a branch. The **merge-only copy** pattern lets you experiment with a card's content on a duplicate branch without disrupting the original card's lifecycle. This article covers the exact scripts, file paths, and command sequences needed to execute this pattern correctly.

## The Merge-Only Copy Pattern Explained

A **merge-only copy** duplicates a card branch for independent work while preserving the original in its queue. The key insight is architectural: SwarmForge separates **merge processing** from **queue management**. You exploit this separation by invoking only the merge-and-process pipeline, deliberately skipping the handoff commands that would advance or remove the source card.

The pattern relies on three core behaviors from `swarmforge/scripts/merge_and_process.bb`:

- Performs `git merge --no-ff` from source to target branch
- Triggers [`swarm_handoff.sh`](https://github.com/unclebob/swarm-forge/blob/main/swarm_handoff.sh) to process the merged commit
- Does **not** invoke [`ready_for_next.sh`](https://github.com/unclebob/swarm-forge/blob/main/ready_for_next.sh) or [`done_with_current.sh`](https://github.com/unclebob/swarm-forge/blob/main/done_with_current.sh)

Since these queue-advancing scripts are never called, the original card branch remains untouched in its workflow position.

## Creating a Copy Branch Manually

The simplest approach uses standard git commands. You create a copy branch from the remote tracking branch, then run the merge-and-process script.

```bash

# Step 1: Create copy branch from origin (avoids local checkout dependencies)

git checkout -b copy-card-123 origin/card-123

# Step 2: Merge copy into target branch and process

bb swarmforge/scripts/merge_and_process.bb copy-card-123 develop

```

The `merge_and_process.bb` script, located at `swarmforge/scripts/merge_and_process.bb` in the repository, executes:

1. `git merge --no-ff copy-card-123` onto the target
2. [`swarmforge/scripts/swarm_handoff.sh`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/scripts/swarm_handoff.sh) to hand off the result
3. Normal processing flow for the merged commit

Because the source argument (`copy-card-123`) is your manually created copy—not the original card identifier—no queue state changes affect `card-123`.

## Automating Copy Creation with pack_board.bb

For repeated operations, the `swarmforge/scripts/pack_board.bb` helper automates branch duplication. According to the SwarmForge source, this script creates a "board" (copy) of a card's branch in a single invocation.

```bash

# Single-command copy creation

bb swarmforge/scripts/pack_board.bb card-123 copy-card-123

# Follow with standard merge-and-process

bb swarmforge/scripts/merge_and_process.bb copy-card-123 develop

```

The `pack_board.bb` script handles the `git checkout -b` mechanics internally, ensuring consistent naming conventions and remote tracking setup.

## Critical: What to Omit for Merge-Only Behavior

The **merge-only** characteristic depends entirely on omission. Normal SwarmForge card processing includes queue-progression scripts that you must deliberately skip:

| Script | Normal Use | Merge-Only Copy Behavior |
|--------|-----------|--------------------------|
| [`ready_for_next.sh`](https://github.com/unclebob/swarm-forge/blob/main/ready_for_next.sh) | Advances card to next queue position | **Skip** |
| [`done_with_current.sh`](https://github.com/unclebob/swarm-forge/blob/main/done_with_current.sh) | Removes card from current queue | **Skip** |
| `merge_and_process.bb` | Merge + handoff only | **Use this** |

The [`handoff-protocol.md`](https://github.com/unclebob/swarm-forge/blob/main/handoff-protocol.md) specification in [`swarmforge/handoff-protocol.md`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/handoff-protocol.md) defines how `git_handoff` messages trigger queue movement. By using `merge_and_process.bb` directly rather than higher-level orchestration scripts, you avoid emitting these move-card messages entirely.

## Workflow Discipline and Safety

The SwarmForge **Constitution**, specifically `swarmforge/constitution/articles/workflow.prompt`, governs safe merge-only copy operations:

- **Worktree isolation**: Copy branches must use dedicated worktrees or temporary directories
- **Commit message conventions**: Merged commits should reference both source and copy for auditability
- **Temporary file cleanup**: Copy operations must not leave lock files or state artifacts that interfere with the original card's processing

Violating these rules can cause the handoff daemon (which monitors `git_handoff` messages per [`handoff-protocol.md`](https://github.com/unclebob/swarm-forge/blob/main/handoff-protocol.md)) to misidentify your copy operation as a card move.

## Complete Working Example

This sequence demonstrates a safe, complete merge-only copy workflow:

```bash
#!/bin/bash

# save as: merge_only_copy.sh

# usage: ./merge_only_copy.sh card-123 develop

CARD=$1
TARGET=$2
COPY="copy-${CARD}-$(date +%s)"

# 1. Create isolated worktree for copy operation

git worktree add "../${COPY}" origin/${CARD}

# 2. Create copy branch in main repository

pushd ..
git checkout -b ${COPY} origin/${CARD}
popd

# 3. Clean up worktree

git worktree remove "../${COPY}"

# 4. Merge and process (merge-only: no queue movement)

bb swarmforge/scripts/merge_and_process.bb ${COPY} ${TARGET}

# 5. Optional: push copy branch for remote backup

git push origin ${COPY}

```

The original `card-123` remains at its queue position, available for normal SwarmForge processing, while your merged changes enter the target branch pipeline.

## Summary

Key takeaways for implementing merge-only copies in SwarmForge:

- **Create manually or with `pack_board.bb`** — both approaches produce a branch copy without queue registration
- **Use `merge_and_process.bb` exclusively** — this script merges and hands off without moving cards
- **Never invoke [`ready_for_next.sh`](https://github.com/unclebob/swarm-forge/blob/main/ready_for_next.sh) or [`done_with_current.sh`](https://github.com/unclebob/swarm-forge/blob/main/done_with_current.sh)** — these scripts trigger the queue movement you want to avoid
- **Follow Constitution worktree rules** — isolation prevents accidental interference with original card state
- **Name copies explicitly** — timestamped or descriptive prefixes prevent branch namespace collisions

## Frequently Asked Questions

### What happens if I accidentally run ready_for_next.sh on a copy branch?

The [`ready_for_next.sh`](https://github.com/unclebob/swarm-forge/blob/main/ready_for_next.sh) script, located at [`swarmforge/scripts/ready_for_next.sh`](https://github.com/unclebob/swarm-forge/blob/main/swarmforge/scripts/ready_for_next.sh), emits a `git_handoff` message that advances whatever branch it identifies as the current card. If run against a copy branch, it may advance the copy to the next queue position or produce undefined behavior since copies lack full card metadata. Always verify your branch name before running queue scripts.

### Can I create multiple merge-only copies of the same card?

Yes. Each copy branch receives a distinct name (e.g., `copy-card-123-exp1`, `copy-card-123-exp2`), and each can be merged independently through `merge_and_process.bb`. The original `card-123` remains unaffected regardless of how many copies exist or how frequently they are merged.

### Does merge_and_process.bb support fast-forward merges?

The script defaults to `git merge --no-ff` to preserve history topology, but this is configurable in `swarmforge/scripts/merge_and_process.bb`. Fast-forward behavior may be desirable for linear history requirements; however, non-fast-forward merges provide clearer audit trails for copy operations.

### How do I clean up copy branches after merging?

Copy branches are standard git branches with no special SwarmForge state. Remove them with `git branch -D copy-card-123` locally and `git push origin --delete copy-card-123` remotely. Confirm deletion does not affect the original card by verifying `origin/card-123` remains in its expected queue position.