/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
$ npx -y skills add marcus/sidecar --skill merge-strategy --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/merge-strategy
Context preview
The summary Claude sees to decide when to auto-load this skill.
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
SKILL.md
merge-strategy.SKILL.mdname: merge-strategy
description: >
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.
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:** 1. Push branch to remote 2. Create PR via `gh pr create` 3. Wait for PR merge (polling) 4. 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
1. **No configurable defaults** -- users must select strategy every time 2. **Limited merge strategies** -- direct merge hardcoded to `--no-ff`, missing `--ff`, `--ff-only`, `--squash`, rebase-based integration 3. **No squash merge support** -- no clean-history option for main branch 4. **Hardcoded commit messages** -- `fmt.Sprintf("Merge branch '%s'", branch)`, no templates 5. **Missing safety options** -- no GPG signing, no `--verify-signatures`, no `--force-with-lease` 6. **Autostash inconsistency** -- available for pull-rebase but not post-merge pull or divergence resolution 7. **No upstream tracking config** -- remote always `origin`, no configurable tracking 8. **Limited conflict recovery** -- only abort or dismiss, no continue/skip rebase 9. **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 `defaultPullStrategy` is 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'", bRead more
name: merge-strategy description: > 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.
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:** 1. Push branch to remote 2. Create PR via `gh pr create` 3. Wait for PR merge (polling) 4. 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
1. **No configurable defaults** -- users must select strategy every time 2. **Limited merge strategies** -- direct merge hardcoded to `--no-ff`, missing `--ff`, `--ff-only`, `--squash`, rebase-based integration 3. **No squash merge support** -- no clean-history option for main branch 4. **Hardcoded commit messages** -- `fmt.Sprintf("Merge branch '%s'", branch)`, no templates 5. **Missing safety options** -- no GPG signing, no `--verify-signatures`, no `--force-with-lease` 6. **Autostash inconsistency** -- available for pull-rebase but not post-merge pull or divergence resolution 7. **No upstream tracking config** -- remote always `origin`, no configurable tracking 8. **Limited conflict recovery** -- only abort or dismiss, no continue/skip rebase 9. **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 `defaultPullStrategy` is 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'", bYou might never open your editor again. Status: Ready for daily use. Please report any issues you encounter.
Other skills on sidecar.
- /create-adapter
Create conversation adapters for importing AI chat history from different tools (Claude Code, Cursor, Warp, Codex, etc.). Covers the adapter.Adapter interface, caching strategies, incremental parsing, watch/FD management, and performance standards. Use when creating a new
Open skill - /create-modal
Create declarative modals using the modal library API. Covers modal types (confirm, input, select, form), sections (Text, Buttons, Input, Textarea, Checkbox, List, When, Custom), rendering with OverlayModal, and keyboard/mouse handling. Use when adding modals or dialogs to the
Open skill - /create-plugin
Create new sidecar plugins implementing the plugin.Plugin interface, rendering views with Bubble Tea, handling keyboard input via keymap contexts, and integrating with the app shell (footer hints, event bus, adapters). Use when creating a new plugin, modifying plugin
Open skill - /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.
Open skill - /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
Open skill - /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,
Open skill

