Applied Intelligence
Module 6: Version Control with Agents

Exercise: Parallel Feature Development with Worktrees

This exercise practices the complete worktree workflow: setting up isolated development environments, running parallel agent sessions, and resolving the merge conflicts that result when branches converge.

Overview

The huh library is a Go package for building interactive terminal forms. It provides field types (text input, select, multiselect, confirm) that developers compose into forms for CLI applications. The codebase is small enough to understand quickly while having clear module boundaries that enable parallel work.

The exercise creates two worktrees, assigns independent features to each, runs agent sessions in parallel, and then merges the results. The merge will produce conflicts because both features touch shared infrastructure. Resolving those conflicts practices the techniques from this module.

The task

Add two independent features to the huh library:

Feature A: Add a FilePicker field type

A new field that presents a file browser interface, allowing users to navigate directories and select files. This requires creating a new field type following the patterns established by existing fields like field_input.go and field_select.go.

Feature B: Add a HighContrast theme

A new theme optimized for accessibility, using bold colors and maximum contrast. This requires adding a new theme to theme.go and ensuring it works with all existing field types.

Both features are independent in concept but share infrastructure:

  • Both modify the form's field registration or theming system
  • Both likely update shared test files or examples
  • Both may add to the same import blocks or interface definitions

This shared infrastructure creates merge conflicts when the branches combine.

Setup

Clone the repository:

git clone https://github.com/charmbracelet/huh.git
cd huh

Verify the project builds and tests pass:

go build ./...
go test ./...

Explore the project structure:

ls -la
ls field*.go
cat theme.go | head -50

Understand the existing patterns before parallelizing:

  • field_input.go, field_select.go show how field types are structured
  • theme.go shows how themes are defined
  • huh.go shows how fields are registered and orchestrated

Phase 1: Create worktrees

Create two worktrees for parallel development:

# Create worktree for Feature A (FilePicker)
git worktree add -b feature/filepicker ../huh-filepicker main

# Create worktree for Feature B (HighContrast theme)
git worktree add -b feature/high-contrast ../huh-highcontrast main

# Verify worktree setup
git worktree list

The directory structure now looks like:

~/projects/
├── huh/                    # main worktree (stay on main)
├── huh-filepicker/         # Feature A worktree
└── huh-highcontrast/       # Feature B worktree

Each worktree has its own branch. Changes in one worktree do not affect the others until branches merge.

Phase 2: Parallel agent sessions

Open two terminal windows (or tmux panes, or IDE splits). Launch separate Claude Code sessions in each worktree.

Terminal 1 - Feature A:

cd ../huh-filepicker
claude

Terminal 2 - Feature B:

cd ../huh-highcontrast
claude

Prompt for Feature A (FilePicker)

Add a new FilePicker field type to this forms library.

The FilePicker should:
- Display a file browser interface in the terminal
- Allow navigating up/down through files and into directories
- Support filtering by file extension (e.g., only show .go files)
- Return the selected file path as a string
- Follow the same patterns as existing fields (field_input.go, field_select.go)

Create field_filepicker.go with the implementation.
Add a simple example showing how to use it.
Make sure existing tests still pass.

Prompt for Feature B (HighContrast theme)

Add a new HighContrast theme to this forms library.

The theme should:
- Use maximum contrast colors (black/white with bold accents)
- Be optimized for users with visual impairments
- Follow the same structure as existing themes in theme.go
- Work with all existing field types

Add the theme to theme.go and create an example demonstrating it.
Make sure existing tests still pass.

Run both agent sessions simultaneously. Switch between terminals to monitor progress. Let each agent work independently without cross-coordination.

What to observe during parallel execution

  • Do the agents ask about the same files?
  • How long does each feature take independently?
  • Does either agent modify files you expected the other to touch?
  • Do agents maintain focus on their assigned feature?

Take notes. These observations inform future parallelization decisions.

Phase 3: Commit and prepare to merge

Once both agents complete their work, commit changes in each worktree.

In Terminal 1 (huh-filepicker):

git add .
git commit -m "Add FilePicker field type for file/directory selection"

In Terminal 2 (huh-highcontrast):

git add .
git commit -m "Add HighContrast theme for accessibility"

Return to the main worktree:

cd ../huh

Phase 4: Merge and resolve conflicts

Merge both feature branches into main. The first merge should succeed without conflicts. The second merge will likely produce conflicts.

# Merge Feature A first
git merge feature/filepicker -m "Merge FilePicker field type"

# Merge Feature B (expect conflicts here)
git merge feature/high-contrast

When conflicts occur, Git reports which files have problems:

Auto-merging huh.go
CONFLICT (content): Merge conflict in huh.go
Auto-merging theme.go
CONFLICT (content): Merge conflict in theme.go
Automatic merge failed; fix conflicts and then commit the result.

Resolution workflow

For each conflicted file, the workflow is:

  1. Examine the conflict
  2. Understand what both branches intended
  3. Resolve to preserve both changes
  4. Verify the resolution compiles
  5. Run tests
  6. Stage the resolution

Examine conflicts:

git status
git diff --name-only --diff-filter=U

Open a conflicted file and find the markers:

<<<<<<< HEAD
// Code from Feature A (already merged)
=======
// Code from Feature B (being merged)
>>>>>>> feature/high-contrast

Resolution options:

Manual resolution: Edit the file directly. Keep both additions, ensuring they do not conflict logically. For import blocks, combine the imports. For registration code, add both registrations. For test files, include tests for both features.

AI-assisted resolution: In Claude Code, request help:

Resolve the merge conflicts in huh.go.
Both features (FilePicker and HighContrast theme) need to be preserved.
The conflicts are in the import block and the field registration section.

Always review AI-generated resolutions. The 46% unacceptable rate from research applies here. Verify that both features remain functional after resolution.

Verify each resolution

After resolving each file:

# Check it compiles
go build ./...

# Run tests
go test ./...

Only proceed to the next conflicted file if the build and tests pass. Errors compound when multiple resolutions are made without verification.

Complete the merge

Once all conflicts are resolved and tests pass:

git add .
git commit -m "Merge HighContrast theme, resolving conflicts with FilePicker"

Phase 5: Cleanup

Remove the worktrees now that features are merged:

git worktree remove ../huh-filepicker
git worktree remove ../huh-highcontrast

# Verify cleanup
git worktree list

Delete the feature branches if they are no longer needed:

git branch -d feature/filepicker
git branch -d feature/high-contrast

Analysis

Record your observations from the exercise:

MetricValue
Time to set up worktrees
Time for Feature A (FilePicker)
Time for Feature B (HighContrast)
Total parallel time
Number of conflicted files
Time to resolve conflicts
Total exercise time

Compare parallel vs sequential:

If you had done these features sequentially, the time would be Feature A + Feature B. Parallel time is max(Feature A, Feature B) + merge/conflict time. Did parallelization save time overall?

Conflict analysis:

  • Which files had conflicts?
  • Were the conflicts predictable from the task descriptions?
  • Could task boundaries have been drawn differently to avoid conflicts?
  • How did AI-assisted resolution compare to manual resolution (if you tried both)?

Reflection questions

Task independence: Were these features as independent as they seemed? What shared infrastructure did both touch? How would you assess task independence before parallelizing in the future?

Prevention vs resolution: Could the conflicts have been prevented? What if Feature A had been scoped to avoid touching huh.go? What if both features used separate example files instead of modifying shared ones?

Parallel efficiency: At what point does conflict resolution overhead exceed sequential execution time? For this exercise, was the overhead worth it?

Worktree overhead: Was worktree setup and cleanup time significant? For a smaller feature (15 minutes of agent work), would worktrees still be worthwhile?

Success criteria

  • Two worktrees created successfully
  • Both agent sessions ran in parallel
  • Both features implemented and committed
  • First merge completed without conflicts
  • Second merge produced conflicts (as expected)
  • All conflicts resolved correctly
  • Final build succeeds (go build ./...)
  • All tests pass (go test ./...)
  • Worktrees cleaned up properly
  • Analysis section completed

Variations

Variation A: Three-way parallel

Add a third feature (e.g., a DatePicker field type) in a third worktree. Observe how conflict complexity scales with parallelism. Three branches merging produce more conflict combinations than two.

Variation B: Conflict prevention

Before creating worktrees, analyze the features and identify likely conflict points. Scope the tasks explicitly to avoid shared files:

  • Feature A works only in field_filepicker.go and filepicker_example.go
  • Feature B works only in theme.go and theme_example.go

Run the exercise with these boundaries. Do conflicts still occur? Was the scoping effort worth the prevention?

Variation C: Different languages

Repeat the exercise with a TypeScript or Python repository. The tiged/tiged scaffolding tool or wbolster/jsonlines library work well. Do worktree workflows differ between language ecosystems? How do dependency installation times affect the overhead calculation?

Variation D: Sequential baseline

Do the features sequentially in a single worktree without branching. Measure the total time. Compare directly to your parallel time. For these specific features, which approach was faster?

What this exercise teaches

Worktrees enable parallel agent work by providing isolation. Without them, two agents modifying the same repository create file conflicts, context pollution, and build state interference. With them, each agent operates independently until merge time.

Merge conflicts are the cost of parallelization. They are not failures they are expected outcomes when multiple streams of work converge. The question is whether parallel development time saved exceeds conflict resolution time spent.

Prevention beats resolution. Clear task boundaries, explicit file ownership, and careful scoping reduce conflicts before they occur. When parallelizing, the analysis phase (determining what each agent will touch) matters as much as the execution phase.

AI tools assist but do not replace judgment. AI-assisted merge resolution accelerates the mechanical parts of conflict resolution but requires human review. The 46% unacceptable rate from research is not a failure of AI it reflects the inherent difficulty of merging code with conflicting intentions.

The workflow compounds. Worktree creation, parallel execution, and conflict resolution become faster with practice. The exercise simulates what becomes routine in ASD work: spinning up parallel sessions for independent tasks and integrating the results.

On this page