Harness-engineering harness-git-workflow

Harness Git Workflow

install
source · Clone the upstream repo
git clone https://github.com/Intense-Visions/harness-engineering
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/skills/claude-code/harness-git-workflow" ~/.claude/skills/intense-visions-harness-engineering-harness-git-workflow && rm -rf "$T"
manifest: agents/skills/claude-code/harness-git-workflow/SKILL.md
source content

Harness Git Workflow

Worktree setup, dependency installation, baseline verification, and branch finishing. Clean isolation for every workstream.

When to Use

  • When starting work that should be isolated from the main branch (new feature, experiment, multi-task plan)
  • When finishing a branch and deciding how to land it (merge, PR, keep, discard)
  • When
    on_pr
    or
    on_commit
    triggers fire and worktree management is needed
  • When the human asks to "set up a branch" or "start a new workstream"
  • NOT for simple single-file changes that do not need branch isolation
  • NOT when work is already in progress on the correct branch

Process

Part A: Worktree Creation

Step 1: Choose Worktree Location

  1. Check for

    .worktrees/
    directory in the project root. If it exists, use it — this is the preferred location.

  2. Check CLAUDE.md or AGENTS.md for worktree preferences. Some projects specify a custom worktree directory or naming convention. Follow those instructions.

  3. If neither exists, ask the user: "Where should I create the worktree? Options: (A)

    .worktrees/<branch-name>
    in the project root, (B) a sibling directory alongside the project, (C) a custom path."

  4. If placing worktrees in the project directory, verify that the worktree directory is gitignored. Check

    .gitignore
    for
    .worktrees/
    or the chosen directory name. If not gitignored, add it before creating the worktree.

Step 2: Check for Existing Worktrees

  1. Run

    git worktree list
    to see active worktrees.

  2. If a worktree already exists for the target branch, do not create a duplicate. Ask: "A worktree for branch

    <name>
    already exists at
    <path>
    . Should I use it, or create a new branch?"

  3. If the target directory already exists (but is not a worktree), do not overwrite. Ask the user how to proceed.

Step 3: Create Branch and Worktree

  1. Create the branch from the current HEAD (or from the specified base):

    git branch <branch-name> <base>
    
  2. Create the worktree:

    git worktree add <path> <branch-name>
    
  3. Verify the worktree was created. Check that the directory exists and contains a

    .git
    file (not a
    .git
    directory — worktrees use a file pointing to the main repo).

Step 4: Auto-Detect and Run Setup

Inspect the worktree for project files and run the appropriate setup:

File FoundAction
package.json
npm install
(or
yarn install
/
pnpm install
if lockfile indicates)
Cargo.toml
cargo build
go.mod
go mod download
requirements.txt
pip install -r requirements.txt
pyproject.toml
pip install -e .
or
poetry install
Gemfile
bundle install
Makefile
(with
install
target)
make install

If multiple project files exist (monorepo), install at the root level. Do not guess which subpackages to install — follow the project's documented setup or ask.

Step 5: Verify Clean Baseline

Before any work begins, verify the worktree is in a clean, working state:

  1. Run the test suite. All tests must pass on the fresh branch before any changes.

  2. Run

    harness validate
    . Project health must be green before starting work.

  3. If tests fail or validation fails on the fresh branch, stop. The base branch has issues. Report: "Baseline verification failed on fresh branch: [failure details]. The base branch needs to be fixed first."

  4. Record the baseline. Note the test count and validation result. This is the comparison point for the branch finishing phase.


Part B: Branch Finishing

When work on the branch is complete, follow this protocol to land the changes.

Step 1: Pre-Finish Verification

  1. Run the full test suite. All tests must pass.

  2. Run

    harness validate
    . Project health must be green.

  3. Check for uncommitted changes. Run

    git status
    . All changes must be committed. If there are uncommitted changes, commit or stash them before finishing.

  4. Check the branch is up to date. If the base branch has advanced since the worktree was created:

    git fetch origin
    git log HEAD..origin/main --oneline
    

    If there are new commits on the base, rebase or merge before finishing:

    git rebase origin/main
    

    Re-run tests after rebasing.

Step 2: Choose Finishing Strategy

Present 4 options to the user:

  1. Merge locally. Merge the branch into the base branch on the local machine.

    • Best for: small changes, solo work, when CI is not required
    • Command:
      git checkout main && git merge <branch>
  2. Push and create PR. Push the branch to the remote and open a pull request.

    • Best for: team work, changes that need review, when CI must pass
    • Command:
      git push -u origin <branch>
      then create PR via
      gh pr create
  3. Keep as-is. Leave the branch and worktree in place for continued work later.

    • Best for: work-in-progress, experiments, paused projects
  4. Discard. Delete the branch and worktree. All changes are lost.

    • Best for: failed experiments, abandoned approaches
    • Safety: Confirm with the user before discarding. List the commits that will be lost.

Step 3: Execute Chosen Strategy

If merge locally:

cd <main-repo-path>
git merge <branch-name>
# Run tests on main after merge
# Run harness validate after merge
git worktree remove <worktree-path>
git branch -d <branch-name>

If push and create PR:

cd <worktree-path>
git push -u origin <branch-name>
gh pr create --title "<title>" --body "$(cat <<'EOF'
## Summary
<PR body with real newlines — never use \n escape sequences>

## Test plan
<checklist>
EOF
)"
# Report the PR URL to the user
# Leave worktree in place until PR is merged

If keep as-is:

No action needed. Report the worktree path and branch name for future reference.

If discard:

# Confirm with user first — list commits that will be lost
git worktree remove <worktree-path>
git branch -D <branch-name>

Step 3.5: Cross-Reference Conventions for Commit Messages and PR Bodies

GitHub auto-links any

#N
token in commit messages, PR titles, and PR bodies to the issue or PR with that number. Treat
#N
as a reserved sigil — never use it for non-issue references.

  • Do not use
    #N
    for proposal success criteria, list ordinals, footnote refs, table rows, or any other in-document numbering. Write "criterion 9", "item 9", "step 3" instead. Using
    #9
    to mean "criterion 9" will silently cross-reference issue #9 — which is almost certainly an unrelated issue — and add a misleading back-reference to that issue's timeline.
  • Do reference the actual roadmap/tracker issue when finishing work tied to one. Use
    Refs #<issue>
    for context-only links and
    Closes #<issue>
    /
    Fixes #<issue>
    only when the merge should auto-close that issue.
  • Before pushing or opening the PR, scan the commit messages and PR body for stray
    #N
    tokens. For each one, confirm it points to the intended issue/PR — or rewrite it as plain text.

Step 4: Clean Up

  1. Remove the worktree (unless keeping as-is or waiting for PR merge):

    git worktree remove <worktree-path>
    
  2. Prune stale worktree references:

    git worktree prune
    
  3. Verify cleanup. Run

    git worktree list
    and confirm the removed worktree is no longer listed.

Harness Integration

  • harness validate
    — Run during baseline verification (Step 5 of Part A) and pre-finish verification (Step 1 of Part B). Ensures project health is green at both boundaries.
  • Test runner — Run fresh in the worktree, not in the main repo. Tests must pass both at baseline (before work) and at finish (after work).
  • .gitignore
    — Verify worktree directory is gitignored if it lives inside the project tree.

Success Criteria

  • Worktree was created in the correct location (
    .worktrees/
    preferred, or per project convention)
  • Dependencies were auto-detected and installed
  • Baseline verification passed (tests green, harness validates) before any work began
  • Branch finishing strategy was chosen by the user (not assumed)
  • Chosen strategy was executed correctly (merge, PR, keep, or discard)
  • Worktree was cleaned up after finishing (unless keeping for continued work)
  • No stale worktree references remain after cleanup

Rationalizations to Reject

RationalizationReality
"The tests are probably fine on the fresh branch — they were passing on main when I last checked. I'll skip baseline verification and start working."Baseline verification is the condition that makes branch work trustworthy. A test failure discovered at finish time is ambiguous — it could be pre-existing or introduced by the work. Skipping baseline removes the only clean comparison point.
"The user said 'just merge it' — I'll merge without checking if the base branch has advanced since the worktree was created."The pre-finish check for base branch divergence is mandatory before any finishing strategy. Merging without rebasing first can produce a merge that silently breaks tests that were passing on the branch but conflict with new commits on main.
"The worktree directory isn't gitignored, but it's inside a nested folder that's unlikely to be committed accidentally."The
.gitignore
check is not about likelihood — it is about preventing accidental commits of worktree state that would corrupt the repository. If the worktree directory is not gitignored, add it before creating the worktree. No exceptions.
"The user chose to discard — I'll delete the branch and worktree immediately without showing the commits that will be lost."The discard path requires showing the commit list from
git log main..HEAD --oneline
and receiving explicit confirmation before running
git worktree remove
and
git branch -D
. Work is being permanently deleted; the user must see what they are losing.
"There's already a worktree for this branch at a different path — I'll create a second one since the user asked for a fresh setup."Git does not allow two worktrees checked out to the same branch. Attempting to create a duplicate will fail. Instead, ask the user whether to use the existing worktree or create a new branch. Never assume a second worktree is the right answer.
"I'll use
#9
in the commit message to refer to 'success criterion 9' in the proposal — it's obviously an in-document reference."
#N
is GitHub's reserved syntax for issue/PR links in commits and PR bodies. It will auto-link to issue/PR #9 regardless of intent and post a misleading back-reference on that unrelated issue. Write "criterion 9" (no
#
) and cite the real roadmap issue separately with
Refs #<n>
.

Examples

Example: Setting Up a Worktree for a New Feature

# Check for preferred location
ls .worktrees/    # exists — use it

# Check gitignore
grep '.worktrees' .gitignore    # found — good, already gitignored

# Check existing worktrees
git worktree list
# /Users/dev/project  abc1234 [main]
# No existing worktree for this feature

# Create branch and worktree
git branch feat/notifications main
git worktree add .worktrees/notifications feat/notifications

# Auto-detect setup (found package.json)
cd .worktrees/notifications && npm install

# Verify baseline
npm test                # 142 tests, all pass
harness validate        # passes

# Ready to work. Report:
# "Worktree created at .worktrees/notifications on branch feat/notifications.
#  142 tests passing. harness validate green. Ready to start."

Example: Finishing a Branch with PR

# Pre-finish verification
cd .worktrees/notifications
npm test                # 158 tests, all pass (16 new)
harness validate        # passes
git status              # clean — all committed

# Check if base has advanced
git fetch origin
git log HEAD..origin/main --oneline
# 3 new commits on main — rebase

git rebase origin/main
npm test                # still passes after rebase

# User chooses: Push and create PR
git push -u origin feat/notifications
gh pr create --title "feat(notifications): email and in-app notifications" --body "$(cat <<'EOF'
## Summary
Implements notification service with create, list, and expiry.

## Test plan
- [x] 16 new tests, all passing
EOF
)"

# Report: "PR created: https://github.com/org/repo/pull/42
#  Worktree at .worktrees/notifications kept until PR merges."

Example: Discarding a Failed Experiment

# User says: "That approach didn't work, let's scrap it."

# Show what will be lost
git log main..HEAD --oneline
# a1b2c3d try websocket approach
# d4e5f6g add socket.io dependency
# "These 2 commits will be lost. Discard? (yes/no)"
# Human: "yes"

git worktree remove .worktrees/ws-experiment
git branch -D feat/ws-experiment
git worktree prune
git worktree list    # ws-experiment no longer listed