Agent skill
merge-strategy
Git merge strategies, conflict resolution approaches, merge vs rebase recommendations, and branch integration patterns in sidecar. Covers pull strategy menu, direct merge workflow, squash merge, commit message templates, configurable defaults, and protected branches. Use when working on git merge features or making decisions about merge strategies.
Install this agent skill to your Project
npx add-skill https://github.com/marcus/sidecar/tree/main/.claude/skills/merge-strategy
SKILL.md
Merge Strategy Configuration
This skill covers sidecar's git merge and pull operations, their current implementation, known gaps, and recommended configuration patterns.
Current Implementation
Git Status Plugin Pull Strategies
Location: internal/plugins/gitstatus/pull_menu.go, internal/plugins/gitstatus/remote.go
The git-status plugin offers four pull strategies via a modal menu:
| Strategy | Command | Use Case |
|---|---|---|
| Pull (merge) | git pull |
Creates merge commit, preserves branch topology |
| Pull (rebase) | git pull --rebase |
Replays local commits on top of upstream |
| Pull (fast-forward only) | git pull --ff-only |
Only pulls if fast-forward possible (safest) |
| Pull (rebase + autostash) | git pull --rebase --autostash |
Rebase with automatic stash/unstash |
Workspace Plugin Merge Workflows
Location: internal/plugins/workspace/merge.go
PR Workflow:
- Push branch to remote
- Create PR via
gh pr create - Wait for PR merge (polling)
- Cleanup: delete worktree, branches, pull base
Direct Merge (No PR) at merge.go:430-498:
1. git fetch origin <baseBranch>
2. git checkout <baseBranch>
3. git pull origin <baseBranch>
4. git merge <branch> --no-ff -m "Merge branch '<branch>'" // Hardcoded --no-ff
5. git push origin <baseBranch>
Post-Merge Pull at merge.go:500-551:
- When on base branch:
git pull --ff-only origin <branch>(hardcoded) - Otherwise:
git fetch+git update-ref
Divergence Resolution at merge.go:644-705:
- Rebase option:
git pull --rebase origin <branch> - Merge option:
git pull origin <branch>
Known Issues and Gaps
- No configurable defaults -- users must select strategy every time
- Limited merge strategies -- direct merge hardcoded to
--no-ff, missing--ff,--ff-only,--squash, rebase-based integration - No squash merge support -- no clean-history option for main branch
- Hardcoded commit messages --
fmt.Sprintf("Merge branch '%s'", branch), no templates - Missing safety options -- no GPG signing, no
--verify-signatures, no--force-with-lease - Autostash inconsistency -- available for pull-rebase but not post-merge pull or divergence resolution
- No upstream tracking config -- remote always
origin, no configurable tracking - Limited conflict recovery -- only abort or dismiss, no continue/skip rebase
- No interactive rebase -- no squash/reorder/edit before merge
Recommended Configuration Schema
Add to internal/config/config.go:
type GitConfig struct {
DefaultPullStrategy string `json:"defaultPullStrategy,omitempty"` // "merge", "rebase", "ff-only", "autostash"
DefaultMergeStrategy string `json:"defaultMergeStrategy,omitempty"` // "no-ff", "ff", "ff-only", "squash", "rebase"
MergeCommitTemplate string `json:"mergeCommitTemplate,omitempty"` // Go template: .Branch, .BaseBranch, .PRTitle, .PRNumber
SignCommits bool `json:"signCommits,omitempty"`
SignMerges bool `json:"signMerges,omitempty"`
AutostashOnPull bool `json:"autostashOnPull,omitempty"`
DefaultRemote string `json:"defaultRemote,omitempty"` // Default: "origin"
SetUpstreamOnPush bool `json:"setUpstreamOnPush,omitempty"`
ProtectedBranches []string `json:"protectedBranches,omitempty"` // e.g. ["main", "master", "release/*"]
PreMergeChecks []string `json:"preMergeChecks,omitempty"` // e.g. ["go test ./..."]
}
Add to PluginsConfig:
type PluginsConfig struct {
Git GitConfig `json:"git"`
GitStatus GitStatusPluginConfig `json:"git-status"`
// ... existing fields
}
Example user config (~/.config/sidecar/config.json):
{
"plugins": {
"git": {
"defaultPullStrategy": "rebase",
"defaultMergeStrategy": "squash",
"mergeCommitTemplate": "Merge {{.Branch}} into {{.BaseBranch}}",
"signCommits": true,
"autostashOnPull": true,
"protectedBranches": ["main", "production"]
}
}
}
Implementation Priorities
Priority 1: Default Pull Strategy
Files: internal/config/config.go, internal/plugins/gitstatus/pull_menu.go, internal/plugins/gitstatus/update_handlers.go
- If
defaultPullStrategyis set, execute directly (skip menu) - If unset, show menu as today
- Consider adding "Always use this" option to menu
Priority 2: Default Merge Strategy
File: internal/plugins/workspace/merge.go -- performDirectMerge()
func (p *Plugin) performDirectMerge(wt *Worktree) tea.Cmd {
strategy := p.ctx.Config.Plugins.Git.DefaultMergeStrategy
if strategy == "" {
strategy = "no-ff" // backward compatible default
}
var mergeArgs []string
switch strategy {
case "ff":
mergeArgs = []string{"merge", branch, "-m", mergeMsg}
case "ff-only":
mergeArgs = []string{"merge", branch, "--ff-only"}
case "squash":
mergeArgs = []string{"merge", branch, "--squash"}
case "rebase":
// 1. git rebase baseBranch branch
// 2. git checkout baseBranch
// 3. git merge branch --ff-only
default: // "no-ff"
mergeArgs = []string{"merge", branch, "--no-ff", "-m", mergeMsg}
}
}
Priority 3: Squash Merge Support
After git merge --squash, a separate commit is needed:
case "squash":
mergeCmd := exec.Command("git", "merge", branch, "--squash")
// execute...
commitMsg := fmt.Sprintf("Squash merge branch '%s'", branch)
commitCmd := exec.Command("git", "commit", "-m", commitMsg)
Priority 4: Merge Commit Templates
type MergeTemplateData struct {
Branch, BaseBranch, PRTitle, PRNumber string
}
func renderMergeMessage(tmpl string, data MergeTemplateData) (string, error) {
if tmpl == "" {
tmpl = "Merge branch '{{.Branch}}'"
}
t, err := template.New("merge").Parse(tmpl)
// ... execute template
}
Priority 5: Protected Branch Warnings
func isProtectedBranch(branch string, patterns []string) bool {
for _, pattern := range patterns {
if matched, _ := filepath.Match(pattern, branch); matched {
return true
}
}
return false
}
Show confirmation modal before direct merge to protected branches.
Strategy Comparison
| Strategy | History | Commit Count | Best For |
|---|---|---|---|
No Fast-Forward (--no-ff) |
Preserves branch topology | +1 merge commit | Feature branches, audit trails |
Fast-Forward (--ff) |
Linear when possible | No extra commits | Small changes, single commits |
Fast-Forward Only (--ff-only) |
Always linear | Fails if not possible | Strict linear history |
| Squash | Linear | Single commit | Clean history, large features |
| Rebase | Linear, preserves commits | No merge commit | Clean history with detail |
Team Recommendations
- Open source: default
squash, PR workflow recommended - Internal teams: default
no-ff, direct merge acceptable - Solo developers: default
rebaseorff, direct merge for speed
Related Files
| File | Purpose |
|---|---|
internal/config/config.go |
Config struct definitions |
internal/config/loader.go |
Config loading and defaults |
internal/plugins/gitstatus/remote.go |
Pull/fetch operations |
internal/plugins/gitstatus/pull_menu.go |
Pull strategy UI |
internal/plugins/workspace/merge.go |
Merge workflow |
internal/plugins/workspace/diff.go |
Base branch detection |
internal/plugins/workspace/worktree.go |
Branch operations |
Migration Notes
- Empty config = current behavior -- all new fields default to empty/false
- Config validation -- warn on invalid strategy names, do not fail
- Backward compatibility -- if changing defaults, provide migration warnings
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
create-prompt
Create prompts for sidecar workspaces. Covers prompt structure (name, ticketMode, body), template variables (ticket with fallbacks), config file locations (global vs project), and scope overrides. Use when creating or modifying prompts in sidecar config files.
keyboard-shortcuts
Reference for keyboard shortcut implementation, keybinding registration, shortcut parity with vim and other TUI tools, and the complete shortcut assignment table across all sidecar plugins. Use when adding or modifying keyboard shortcuts, checking shortcut assignments, resolving key conflicts, or assessing alignment with vim conventions.
profile-memory
Profile memory usage in sidecar using Go pprof, system tools, and heap analysis. Covers identifying memory leaks, goroutine leaks, file descriptor accumulation, and CPU profiling. Use when investigating memory issues, profiling performance, debugging memory leaks, or diagnosing unresponsive plugins.
create-theme
Create custom color themes for Sidecar, including base theme selection, color overrides, gradient borders, tab styles, per-project themes, community themes, and programmatic theme registration. Use when creating or modifying themes, adjusting UI appearance, or debugging color/style issues. See references/palette-reference.md for the full color palette with all keys and per-theme values.
feature-flags
Creating and using feature flags in sidecar for gating experimental functionality. Covers flag registration, checking flags in code, config file and CLI overrides, and priority resolution. Use when adding feature flags, toggling features, or gating new functionality behind flags.
drag-pane
Drag-and-drop pane resizing implementation for two-pane plugin layouts. Covers mouse event handling via the internal/mouse package, hit region registration, drag delta calculation, width clamping, state persistence, and pane layout management. Use when working on pane resizing, drag interactions, layout management, or adding drag-to-resize to a new plugin.
Didn't find tool you were looking for?