# Manage Git Branches

> Create, track, switch, sync, and clean up Git branches. Covers naming conventions, safe branch switching with stash, upstream synchronization, and pruning merged branches. Use when starting work on a new feature or bug fix, switching between tasks on different branches, keeping a feature branch up to date with main, or cleaning up branches after merging pull requests.

- Skill: `pjt222/manage-git-branches` (Agent Skill)
- Install (CLI): `npx skillmds@latest add pjt222/manage-git-branches`
- Raw SKILL.md: https://api.skillmd.com/api/skills/pjt222/manage-git-branches/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: MIT
- Author: pjt222 (https://skillmd.com/u/pjt222)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/pjt222/manage-git-branches

---


# Manage Git Branches

Create, switch, sync, and clean up branches following consistent naming conventions.

## When to Use

- Starting work on a new feature or bug fix
- Switching between tasks on different branches
- Keeping a feature branch up to date with main
- Cleaning up branches after merging pull requests
- Listing and inspecting branches

## Inputs

- **Required**: Repository with at least one commit
- **Optional**: Branch naming convention (default: `type/description`)
- **Optional**: Base branch for new branches (default: `main`)
- **Optional**: Remote name (default: `origin`)

## Procedure

### Step 1: Create a Feature Branch

Use a consistent naming convention:

| Prefix | Purpose | Example |
|---|---|---|
| `feature/` | New functionality | `feature/add-weighted-mean` |
| `fix/` | Bug fix | `fix/null-pointer-in-parser` |
| `docs/` | Documentation | `docs/update-api-reference` |
| `refactor/` | Code restructuring | `refactor/extract-validation` |
| `chore/` | Maintenance | `chore/update-dependencies` |
| `test/` | Test additions | `test/add-edge-case-coverage` |

```bash
# Create and switch to a new branch from main
git checkout -b feature/add-weighted-mean main

# Or using the newer switch command
git switch -c feature/add-weighted-mean main
```

**Expected:** New branch created and checked out. `git branch` shows the new branch with an asterisk.

**On failure:** If the base branch doesn't exist locally, fetch first: `git fetch origin main && git checkout -b feature/name origin/main`.

### Step 2: Track Remote Branches

Set up tracking when pushing a new branch for the first time:

```bash
# Push and set upstream tracking
git push -u origin feature/add-weighted-mean

# Check tracking relationship
git branch -vv
```

To check out a remote branch that someone else created:

```bash
git fetch origin
git checkout feature/their-branch
# Git auto-creates a local tracking branch
```

**Expected:** Local branch tracks the corresponding remote branch. `git branch -vv` shows the upstream.

**On failure:** If auto-tracking fails, set it manually: `git branch --set-upstream-to=origin/feature/name feature/name`.

### Step 3: Switch Branches Safely

Before switching, ensure the working tree is clean:

```bash
# Check for uncommitted changes
git status
```

**If changes exist**, either commit or stash them:

```bash
# Option 1: Commit work in progress
git add <files>
git commit -m "wip: save progress on validation logic"

# Option 2: Stash changes temporarily
git stash push -m "validation work in progress"

# Switch branches
git checkout main

# Later, restore stashed changes
git checkout feature/add-weighted-mean
git stash pop
```

List and manage stashes:

```bash
# List all stashes
git stash list

# Apply a specific stash (without removing it)
git stash apply stash@{1}

# Drop a stash
git stash drop stash@{0}
```

**Expected:** Branch switch succeeds. Working tree reflects the target branch's state. Stashed changes are recoverable.

**On failure:** If switch is blocked by uncommitted changes that would be overwritten, stash or commit first. `git stash` cannot stash untracked files unless you use `git stash push -u`.

### Step 4: Sync with Upstream

Keep your feature branch up to date with the base branch:

```bash
# Fetch latest changes
git fetch origin

# Rebase onto latest main (preferred — keeps linear history)
git rebase origin/main

# Or merge main into your branch (creates merge commit)
git merge origin/main
```

**Expected:** Branch now includes the latest changes from main. No conflicts, or conflicts resolved (see `resolve-git-conflicts`).

**On failure:** If rebase causes conflicts, resolve each one and `git rebase --continue`. If the conflicts are too complex, abort with `git rebase --abort` and try `git merge origin/main` instead.

### Step 5: Clean Up Merged Branches

After pull requests are merged, remove stale branches:

```bash
# Delete a local branch that has been merged
git branch -d feature/add-weighted-mean

# Delete a local branch (force, even if not merged)
git branch -D feature/abandoned-experiment

# Delete a remote branch
git push origin --delete feature/add-weighted-mean

# Prune remote-tracking references for deleted remote branches
git fetch --prune
```

**Expected:** Merged branches are removed locally and remotely. `git branch` shows only active branches.

**On failure:** `git branch -d` refuses to delete unmerged branches. If the branch was merged via squash merge on GitHub, Git may not recognize it as merged. Use `git branch -D` if you are certain the work is preserved.

### Step 6: List and Inspect Branches

```bash
# List local branches
git branch

# List all branches (local and remote)
git branch -a

# List branches with last commit info
git branch -v

# List branches merged into main
git branch --merged main

# List branches NOT yet merged
git branch --no-merged main

# See which remote branch each local branch tracks
git branch -vv
```

**Expected:** Clear view of all branches, their status, and tracking relationships.

**On failure:** If remote branches appear stale, run `git fetch --prune` to clean up references to deleted remote branches.

## Validation

- [ ] Branch names follow the agreed naming convention
- [ ] Feature branches are created from the correct base branch
- [ ] Local branches track their remote counterparts
- [ ] Merged branches are cleaned up (local and remote)
- [ ] Working tree is clean before branch switches
- [ ] Stashed changes are not left orphaned

## Common Pitfalls

- **Working on main directly**: Always create a feature branch. Committing directly to main makes it difficult to create PRs and collaborate.
- **Forgetting to fetch before branching**: Creating a branch from a stale local main means you start behind. Always `git fetch origin` first.
- **Long-lived branches**: Feature branches that live for weeks accumulate merge conflicts. Sync frequently and keep branches short-lived.
- **Orphaned stashes**: `git stash` is temporary storage. Don't rely on it for long-term work. Commit or branch instead.
- **Deleting unmerged work**: `git branch -D` is destructive. Double-check with `git log branch-name` before force-deleting.
- **Not pruning**: Remote branches deleted on GitHub still appear locally until you `git fetch --prune`.

## Related Skills

- `commit-changes` - committing work on branches
- `create-pull-request` - opening PRs from feature branches
- `resolve-git-conflicts` - handling conflicts during sync
- `configure-git-repository` - repository setup and branch strategy

