Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ func runStatus(gitClient git.GitClient, githubClient github.GitHubClient) error

// Don't offer to add the base branch to a stack - it can't have a parent
if currentBranch == baseBranch {
fmt.Printf("Branch '%s' is the base branch and cannot be part of a stack.\n", ui.Branch(currentBranch))
fmt.Printf("No stack found. You're on the base branch (%s).\n", ui.Branch(currentBranch))
fmt.Printf("\nUse '%s' to create a new stack branch.\n", ui.Command("stack new <branch-name>"))
return nil
}
Expand Down
10 changes: 10 additions & 0 deletions cmd/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,17 @@ func runSync(gitClient git.GitClient, githubClient github.GitHubClient) error {
if len(chain) == 0 {
// Wait for parallel operations before returning
wg.Wait()
if fetchErr != nil {
return fmt.Errorf("failed to fetch: %w", fetchErr)
}
fmt.Println("No stack branches found.")
if originalBranch == baseBranch {
fmt.Printf("Updating %s from origin...\n", ui.Branch(baseBranch))
if err := gitClient.FastForwardToRemote(baseBranch); err != nil {
return fmt.Errorf("failed to update %s: %w", baseBranch, err)
}
fmt.Println(ui.Success(fmt.Sprintf("Updated %s", ui.Branch(baseBranch))))
}
return nil
}

Expand Down
1 change: 1 addition & 0 deletions cmd/sync_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,7 @@ func TestRunSyncNoStackBranches(t *testing.T) {
// These are started but may not complete before early return
mockGit.On("Fetch").Return(nil).Maybe()
mockGH.On("GetAllPRs").Return(make(map[string]*github.PRInfo), nil).Maybe()
mockGit.On("FastForwardToRemote", "main").Return(nil).Maybe()

// These calls don't happen when there are no stack branches (early return)

Expand Down
11 changes: 11 additions & 0 deletions internal/git/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,17 @@ func (c *gitClient) Fetch() error {
return err
}

// FastForwardToRemote fast-forwards the current branch to match origin/<branch>
func (c *gitClient) FastForwardToRemote(branch string) error {
remoteBranch := "origin/" + branch
if DryRun {
fmt.Printf(" [DRY RUN] git merge --ff-only %s\n", remoteBranch)
return nil
}
_, err := c.runCmd("merge", "--ff-only", remoteBranch)
return err
}

// BranchExists checks if a branch exists locally
func (c *gitClient) BranchExists(name string) bool {
output := c.runCmdMayFail("rev-parse", "--verify", "refs/heads/"+name)
Expand Down
1 change: 1 addition & 0 deletions internal/git/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type GitClient interface {
ForcePush(branch string) error
IsWorkingTreeClean() (bool, error)
Fetch() error
FastForwardToRemote(branch string) error
BranchExists(name string) bool
RemoteBranchExists(name string) bool
GetRemoteBranchesSet() map[string]bool
Expand Down
5 changes: 5 additions & 0 deletions internal/testutil/mocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ func (m *MockGitClient) Fetch() error {
return args.Error(0)
}

func (m *MockGitClient) FastForwardToRemote(branch string) error {
args := m.Called(branch)
return args.Error(0)
}

func (m *MockGitClient) BranchExists(name string) bool {
args := m.Called(name)
return args.Bool(0)
Expand Down