[GH-ISSUE #143] Parallel mode: merge conflicts leave orphaned branches and unmerged work #55

Closed
opened 2026-02-27 10:21:58 +03:00 by kerem · 0 comments
Owner

Originally created by @DBULL7 on GitHub (Jan 31, 2026).
Original GitHub issue: https://github.com/mikeyobrien/ralph-orchestrator/issues/143

Summary

When running ralph parallel, merge conflicts during the squash-merge phase leave the orchestrator in a broken state with orphaned branches and unmerged work. This has been a recurring issue since parallel mode was introduced.

Environment

  • ralph-orchestrator (latest via uv)
  • macOS / git 2.x
  • Multiple nested parallel phases

Bugs Identified

1. Merge conflict handling marks phase as success despite failure

When there are local uncommitted changes that conflict with a phase's squash merge, the error occurs but the phase is still marked as success=True:

2026-01-31 14:13:50,714 - ralph.parallel - ERROR - Squash merge conflict for phase application_controller_cookie_auth: error: Your local changes to the following files would be overwritten by merge...
2026-01-31 14:13:50,715 - ralph.parallel - INFO - Received PHASE_COMPLETE for application_controller_cookie_auth (success=True)  # <-- BUG: should be False

This leaves valuable work stranded in worktree branches that never get merged.

2. Nested worktrees accumulate and don't get cleaned up

When phases spawn sub-phases (e.g., core_modelsplayer_coach_modelscoach_model), worktrees nest 3+ levels deep:

.agent/worktrees/core_models/.agent/worktrees/player_coach_models/.agent/worktrees/coach_model

When cleanup_on_failure=False, these never get cleaned and accumulate across runs.

3. Branch accumulation across multiple runs

Each failed run leaves behind all its _ralph-internal/* branches. After 3-4 failed runs, there can be 15+ orphaned branches making manual recovery difficult.

4. Unmerged work warning comes too late

The warning about unmerged branches appears in stderr after the phase is already marked failed:

WARNING - UNMERGED WORK DETECTED: 2 commits across 2 branches not merged...
WARNING - To recover this work, run: git checkout ... git merge ...

But by this point the orchestrator has already moved on or terminated.

Reproduction

  1. Start a ralph parallel run with nested phases
  2. While a phase is running, make local changes to a file that phase will also modify
  3. Phase completes its work but squash-merge fails
  4. Orchestrator marks phase as failed but leaves branches behind
  5. Repeat 2-3 times → branch explosion

Expected Behavior

  1. If squash-merge fails due to conflicts, phase should be marked success=False
  2. Orchestrator should offer automatic conflict resolution or at least a clean recovery command
  3. cleanup_on_failure=True should actually clean up nested worktrees
  4. ralph cleanup command (or similar) to nuke all _ralph-internal/* branches and worktrees in one go

Suggested Fixes

  1. Pre-merge check: Before marking phase complete, verify merge will succeed
  2. Atomic merge: Stash local changes → merge → pop stash (or fail cleanly)
  3. Cleanup command: ralph cleanup --all to remove all internal branches/worktrees
  4. Recovery mode: ralph recover to find unmerged branches and offer to cherry-pick them

Workaround

Manual recovery (what I had to do):

# 1. Identify valuable commits in orphaned branches
git log main..<branch> --oneline

# 2. Stash local changes, checkout main, create recovery branch
git stash && git checkout main && git checkout -b recovery

# 3. Cherry-pick valuable commits
git cherry-pick <commit>...

# 4. Clean up
rm -rf .agent/worktrees/*
git worktree prune
git branch | grep _ralph-internal | xargs git branch -D

This is tedious and error-prone. Would love a built-in solution.


Happy to provide more logs or help test fixes. This is blocking productive use of parallel mode.

Originally created by @DBULL7 on GitHub (Jan 31, 2026). Original GitHub issue: https://github.com/mikeyobrien/ralph-orchestrator/issues/143 ## Summary When running `ralph parallel`, merge conflicts during the squash-merge phase leave the orchestrator in a broken state with orphaned branches and unmerged work. This has been a recurring issue since parallel mode was introduced. ## Environment - ralph-orchestrator (latest via uv) - macOS / git 2.x - Multiple nested parallel phases ## Bugs Identified ### 1. Merge conflict handling marks phase as success despite failure When there are local uncommitted changes that conflict with a phase's squash merge, the error occurs but the phase is still marked as `success=True`: ``` 2026-01-31 14:13:50,714 - ralph.parallel - ERROR - Squash merge conflict for phase application_controller_cookie_auth: error: Your local changes to the following files would be overwritten by merge... 2026-01-31 14:13:50,715 - ralph.parallel - INFO - Received PHASE_COMPLETE for application_controller_cookie_auth (success=True) # <-- BUG: should be False ``` This leaves valuable work stranded in worktree branches that never get merged. ### 2. Nested worktrees accumulate and don't get cleaned up When phases spawn sub-phases (e.g., `core_models` → `player_coach_models` → `coach_model`), worktrees nest 3+ levels deep: ``` .agent/worktrees/core_models/.agent/worktrees/player_coach_models/.agent/worktrees/coach_model ``` When `cleanup_on_failure=False`, these never get cleaned and accumulate across runs. ### 3. Branch accumulation across multiple runs Each failed run leaves behind all its `_ralph-internal/*` branches. After 3-4 failed runs, there can be 15+ orphaned branches making manual recovery difficult. ### 4. Unmerged work warning comes too late The warning about unmerged branches appears in stderr after the phase is already marked failed: ``` WARNING - UNMERGED WORK DETECTED: 2 commits across 2 branches not merged... WARNING - To recover this work, run: git checkout ... git merge ... ``` But by this point the orchestrator has already moved on or terminated. ## Reproduction 1. Start a `ralph parallel` run with nested phases 2. While a phase is running, make local changes to a file that phase will also modify 3. Phase completes its work but squash-merge fails 4. Orchestrator marks phase as failed but leaves branches behind 5. Repeat 2-3 times → branch explosion ## Expected Behavior 1. If squash-merge fails due to conflicts, phase should be marked `success=False` 2. Orchestrator should offer automatic conflict resolution or at least a clean recovery command 3. `cleanup_on_failure=True` should actually clean up nested worktrees 4. `ralph cleanup` command (or similar) to nuke all `_ralph-internal/*` branches and worktrees in one go ## Suggested Fixes 1. **Pre-merge check**: Before marking phase complete, verify merge will succeed 2. **Atomic merge**: Stash local changes → merge → pop stash (or fail cleanly) 3. **Cleanup command**: `ralph cleanup --all` to remove all internal branches/worktrees 4. **Recovery mode**: `ralph recover` to find unmerged branches and offer to cherry-pick them ## Workaround Manual recovery (what I had to do): ```bash # 1. Identify valuable commits in orphaned branches git log main..<branch> --oneline # 2. Stash local changes, checkout main, create recovery branch git stash && git checkout main && git checkout -b recovery # 3. Cherry-pick valuable commits git cherry-pick <commit>... # 4. Clean up rm -rf .agent/worktrees/* git worktree prune git branch | grep _ralph-internal | xargs git branch -D ``` This is tedious and error-prone. Would love a built-in solution. --- Happy to provide more logs or help test fixes. This is blocking productive use of parallel mode.
kerem closed this issue 2026-02-27 10:21:59 +03:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/ralph-orchestrator#55
No description provided.