Skip to content

feat: Implement idempotent branch operations to improve reliability #787

@Ray0907

Description

@Ray0907

Problem

When a GitHub Actions job fails and is retried, the current implementation creates a new branch because branch names include timestamps:

claude/issue-123-20250103-1430
claude/issue-123-20250103-1445  <- retry creates new branch
claude/issue-123-20250103-1500  <- another new branch

This causes:

  1. Branch sprawl - Accumulation of orphan branches
  2. Lost work - Previous progress not continued
  3. Confusion - Multiple branches for same issue/PR

Root Cause

The current approach uses unique timestamps to avoid conflicts rather than solving them. This is accidental complexity.

The fundamental question: Why does the same issue/PR need multiple branches?

In most cases, one issue = one Claude branch. Multiple triggers on the same issue should continue on the same branch, not create new ones.

Proposed Solution

1. Simplified Branch Naming

Before:

{prefix}{entity_type}-{entity_number}-{timestamp}
Example: claude/issue-123-20250103-1430

After:

{prefix}{entity_type}-{entity_number}
Example: claude/issue-123

2. Idempotent Branch Creation (check-before-create)

async function setupBranch(...): Promise<BranchInfo> {
  const branchName = `${branchPrefix}${entityType}-${entityNumber}`;

  const branchExists = await checkBranchExists(octokit, owner, repo, branchName);

  if (branchExists) {
    // Branch exists -> checkout and continue
    execGit(["fetch", "origin", branchName]);
    execGit(["checkout", branchName]);
  } else {
    // Branch doesn't exist -> create
    execGit(["fetch", "origin", sourceBranch, "--depth=1"]);
    execGit(["checkout", sourceBranch]);
    execGit(["checkout", "-b", branchName]);
  }

  return { baseBranch: sourceBranch, claudeBranch: branchName, currentBranch: branchName };
}

3. Documentation for Concurrency Control

Users should configure workflow-level concurrency to prevent simultaneous executions:

concurrency:
  group: claude-${{ github.event.issue.number || github.event.pull_request.number }}
  cancel-in-progress: false

Files to Modify

File Change
src/github/operations/branch.ts Remove timestamp, add check-before-create
src/mcp/github-file-ops-server.ts Idempotent handling for commit signing mode
README.md or docs/ Concurrency configuration docs
test/branch.test.ts Add idempotency tests

Benefits

  1. Reliability - Retries work correctly without creating duplicate branches
  2. Simplicity - One branch per issue/PR, easy to understand
  3. No sprawl - Eliminates accumulation of orphan branches

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestfeature-requestp2Non-showstopper bug or popular feature request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions