Skip to content

Branch workflow UX issues: missing branch selection prompt and outdated base branch #331

@itdove

Description

@itdove

Overview

Two related UX issues in daf new branch creation workflow that can lead to users working on wrong/outdated branches.


Issue #1: Missing Branch Selection When Declining Branch Creation

Problem

When a user declines to create a new branch, the system continues with whatever branch is currently checked out, without asking which existing branch the user wants to work on.

Current Behavior

✓ Detected git repository

Would you like to create a new branch? [y/n] (y): n

No new branch will be created.
Would you like to sync current branch with origin/main? [y/n] (y): 

Pulling latest changes from origin/main...
✓ Successfully synced with origin/main

Problem: User might be on develop, feature/old-work, or any other branch - but was never asked!

Expected Behavior

After user declines branch creation, prompt for branch selection:

Would you like to create a new branch? [y/n] (y): n

Available local branches:
  1. main (current)
  2. develop
  3. release/1.0
  4. feature/ai-guardian-improvements

Which branch would you like to work on? (1): 4
✓ Switched to branch: feature/ai-guardian-improvements

Would you like to sync this branch with origin/main? [y/n] (y):

Code Location (Issue #1)

File: devflow/cli/commands/new_command.py
Function: _handle_branch_creation() (lines 1604-1991)
Problem area: Lines 1760-1803

When should_create = False:

  • Line 1763: Prints "No new branch will be created."
  • Lines 1765-1803: Offers to sync with upstream
  • MISSING: Branch selection prompt between these steps

Suggested Fix (Issue #1)

Add branch selection logic after line 1763:

# User declined - offer to switch to an existing branch
console_print("\n[dim]No new branch will be created.[/dim]")

# Get list of local branches
local_branches = GitUtils.list_local_branches(path)
current_branch = GitUtils.get_current_branch(path)

if local_branches and len(local_branches) > 1:
    console_print("\n[bold]Available local branches:[/bold]")
    for i, branch in enumerate(local_branches, 1):
        if branch == current_branch:
            console_print(f"  {i}. {branch} [cyan](current)[/cyan]")
        else:
            console_print(f"  {i}. {branch}")
    
    # Prompt for selection...
    # Checkout if different from current...

Issue #2: New Branch Created from Outdated Base Branch

Problem

When creating a new branch from a source branch the user is already on, the system skips pulling latest changes. This results in the new branch being based on an outdated commit.

Example Scenario

# User's local main is 8 commits behind origin/main
$ git status
On branch main
Your branch is behind 'origin/main' by 8 commits

$ daf new --name release-ai-guardian-1.1

✓ Detected git repository
Would you like to create a new branch? [y/n] (y): y
Creating branch from: main

Creating branch 'release-ai-guardian-1.1' from 'main'...
Fetching latest from remote...
✓ Created and switched to branch: release-ai-guardian-1.1

# New branch is 8 commits behind! Pull was skipped!

Root Cause

File: devflow/cli/commands/new_command.py
Lines: 1940-1967

The pull logic is inside a conditional block that only runs when switching branches:

# Line 1941-1942
current_branch = GitUtils.get_current_branch(path)
if current_branch != source_branch:  # ❌ Bug: only pulls when switching!
    # ... checkout source branch ...
    
    # Lines 1959-1964: Pull logic (only runs if switching)
    if '/' not in source_branch:  # Local branch
        console_print(f"[cyan]Pulling latest {source_branch}...[/cyan]")
        GitUtils.pull_current_branch(path)  # ❌ Also non-critical, ignores failures

# Line 1967: Create branch (from potentially outdated HEAD)
success, error_msg = GitUtils.create_branch(path, branch_name)

Flow when already on source branch:

  1. Line 1938: fetch_origin() - updates origin/main tracking branch ✓
  2. Line 1941: current_branch = "main"
  3. Line 1942: if "main" != "main":FALSE
  4. Lines 1943-1964: SKIPPED (no pull!) ❌
  5. Line 1967: Creates branch from current HEAD (8 commits behind)

Expected Behavior

Always pull latest changes from remote before creating new branch:

Creating branch 'release-ai-guardian-1.1' from 'main'...
Fetching latest from remote...
Pulling latest main...
✓ Synced with origin/main (8 new commits)
✓ Created and switched to branch: release-ai-guardian-1.1

Suggested Fix (Issue #2)

Move pull logic outside the if current_branch != source_branch: block:

# Line 1940: Checkout source branch first (if needed)
current_branch = GitUtils.get_current_branch(path)
if current_branch != source_branch:
    console_print(f"[cyan]Checking out {source_branch}...[/cyan]")
    success, error_msg = GitUtils.checkout_branch(path, source_branch)
    if not success:
        console_print(f"[red]✗[/red] Failed to checkout {source_branch}")
        return None

# ALWAYS pull latest if it's a local branch (regardless of whether we switched)
if '/' not in source_branch:  # Local branch
    console_print(f"[cyan]Pulling latest {source_branch}...[/cyan]")
    success, error_msg = GitUtils.pull_current_branch(path)
    
    if not success:
        # Don't ignore pull failures - warn user!
        console_print(f"[yellow]⚠[/yellow] Could not pull latest {source_branch}")
        console_print(f"[yellow]Your new branch may be based on an outdated commit[/yellow]")
        if not Confirm.ask("Continue anyway?", default=False):
            return None

# Create new branch
success, error_msg = GitUtils.create_branch(path, branch_name)

Key changes:

  1. Move pull outside the checkout conditional - pull even if already on branch
  2. Check pull return value - don't silently ignore failures
  3. Warn user if pull fails - let them decide whether to continue
  4. Show commit count if possible (optional enhancement)

Impact

Issue #1 Severity: Medium

  • User might work on wrong branch unintentionally
  • Confusing UX - assumes user knows current branch

Issue #2 Severity: High

  • New branches created from outdated commits
  • Can lead to missing critical updates from main branch
  • Causes merge conflicts and duplicate work

Related Files

  • devflow/cli/commands/new_command.py - main branch creation logic
  • devflow/git/utils.py - git utilities (list_local_branches, pull_current_branch)
  • devflow/cli/commands/open_command.py - similar logic for reopening sessions

Acceptance Criteria

Issue #1:

  • After declining branch creation, show list of local branches
  • Highlight current branch in the list
  • Allow selection by number, name, or Enter to keep current
  • Checkout selected branch before sync prompt
  • Non-interactive mode uses current branch (backward compatible)

Issue #2:

  • Always pull latest changes before creating new branch from local base
  • Pull happens even if already on source branch
  • Check pull return value and warn if it fails
  • Display number of new commits pulled (optional)
  • Don't create branch if pull fails and user declines to continue
  • Integration test: create branch when local main is behind origin

Testing Scenarios

Issue #1:

  1. User on develop, declines branch creation → prompted to select branch
  2. User selects different branch → checkout happens, then sync prompt
  3. User selects same branch (Enter) → no checkout, proceed to sync
  4. Only one branch exists → skip selection prompt

Issue #2:

  1. User on main (8 commits behind) → pull happens, new branch is up-to-date
  2. User on feature, creates from main → checkout + pull main, then create
  3. Pull fails (conflicts, network) → user warned, can abort or continue
  4. Source is origin/main (remote) → no pull attempt (correct behavior)

Metadata

Metadata

Assignees

Labels

2.1Issues targeted for version 2.1 releasebugSomething isn't workinggit-workflowux

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions