```skill --- name: merge-branch description: Git branch merging workflow — merges current feature branch into the default branch (main/master) with conflict detection, working tree validation, and safety checks. --- # Merge Branch ## Overview This skill merges the current feature branch into the detected default branch (main or master). **Prerequisites:** - Working in a git repository - On a feature branch (not already on default branch) - Have commits ready to merge **Outcome:** - Feature branch merged into default branch - Default branch updated with latest changes - Ready to push merged changes to remote ## Default Branch Detection Detect the default branch name: ```sh git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@' ``` Fallback: check if `master` exists, else `main`. Store as `{default_branch}`. ## Pre-Merge Validation Run these checks BEFORE merging: ### 1. Get Current Branch ```sh CURRENT_BRANCH=$(git branch --show-current) ``` ### 2. Verify Not on Default Branch ```sh if [ "$CURRENT_BRANCH" = "{default_branch}" ]; then echo "ERROR: Already on default branch. Cannot merge into self." exit 1 fi ``` ### 3. Check Working Tree State ```sh IS_DIRTY=$(git status --porcelain) ``` If `IS_DIRTY` is not empty, working tree is dirty. Handle before merging. ## Dirty Working Tree Options When dirty, present these options to the user (use `ask_questions` tool): - **Commit changes first**: `git add -A && git commit -m "message"` — commits all changes before merging - **Stash changes**: `git stash push -m "WIP: auto-stash before merge"` — saves changes for later - **Discard changes**: `git checkout -- . && git clean -fd` — permanently removes uncommitted changes - **Abort**: Stop the workflow — user handles git state manually After committing, stashing, or discarding, working tree is clean. Proceed with merge. ## Merge Execution After working tree is clean: ### 1. Switch to Default Branch ```sh git checkout {default_branch} ``` ### 2. Pull Latest Changes ```sh git pull ``` ### 3. Execute Merge ```sh git merge $CURRENT_BRANCH ``` ### 4. Handle Merge Result Check exit code: - **Exit 0** (success): Merge completed successfully ``` ✓ Merged $CURRENT_BRANCH into {default_branch} Next steps: - Review merged changes: git log - Push to remote: git push - Delete feature branch if done: git branch -d $CURRENT_BRANCH ``` - **Non-zero exit** (conflict): Merge conflict detected ```sh git merge --abort echo "ERROR: Merge conflict detected. Merge aborted." echo "Resolve conflicts manually and retry merge." exit 1 ``` ## Error Handling | Scenario | Error Message | Exit Code | |----------|---------------|-----------| | Already on default branch | `ERROR: Already on default branch. Cannot merge into self.` | 1 | | Dirty working tree (user aborts) | `ERROR: Working tree is dirty. Merge aborted.` | 1 | | Merge conflict | `ERROR: Merge conflict detected. Merge aborted.` | 1 | | Default branch detection fails | `ERROR: Could not detect default branch.` | 1 | All errors exit with non-zero status to prevent downstream issues. ## Usage Example Complete workflow demonstrating all steps: ```sh #!/bin/bash set -e # Step 1: Detect default branch DEFAULT_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@') if [ -z "$DEFAULT_BRANCH" ]; then if git show-ref --verify --quiet refs/heads/master; then DEFAULT_BRANCH="master" else DEFAULT_BRANCH="main" fi fi # Step 2: Get current branch CURRENT_BRANCH=$(git branch --show-current) # Step 3: Verify not on default branch if [ "$CURRENT_BRANCH" = "$DEFAULT_BRANCH" ]; then echo "ERROR: Already on default branch. Cannot merge into self." exit 1 fi # Step 4: Check working tree state IS_DIRTY=$(git status --porcelain) if [ -n "$IS_DIRTY" ]; then echo "WARNING: Working tree is dirty." echo "Options: (c)ommit, (s)tash, (d)iscard, (a)bort" read -p "Choose: " choice case $choice in c) git add -A && git commit -m "Changes before merge" ;; s) git stash push -m "WIP: auto-stash before merge" ;; d) git checkout -- . && git clean -fd ;; a) echo "Merge aborted."; exit 1 ;; *) echo "Invalid choice. Aborting."; exit 1 ;; esac fi # Step 5: Switch to default branch git checkout $DEFAULT_BRANCH # Step 6: Pull latest changes git pull # Step 7: Execute merge if git merge $CURRENT_BRANCH; then echo "✓ Merged $CURRENT_BRANCH into $DEFAULT_BRANCH" echo "Next steps:" echo "- Review merged changes: git log" echo "- Push to remote: git push" echo "- Delete feature branch if done: git branch -d $CURRENT_BRANCH" else echo "ERROR: Merge conflict detected. Aborting merge." git merge --abort exit 1 fi ```