|
| 1 | +# Git Skill |
| 2 | + |
| 3 | +## When to use this skill |
| 4 | +Use this skill when asked to: |
| 5 | +- Summarize the difference between a feature branch and the default branch |
| 6 | +- Write a commit message for a branch or set of changes |
| 7 | +- Describe what a branch does, what it changes, or what it's for |
| 8 | +- Review a diff or changelog in plain language |
| 9 | + |
| 10 | +--- |
| 11 | + |
| 12 | +## Core Workflow |
| 13 | + |
| 14 | +### 1. Identify the default branch |
| 15 | +```bash |
| 16 | +git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@' \ |
| 17 | + || git remote show origin 2>/dev/null | grep 'HEAD branch' | awk '{print $NF}' \ |
| 18 | + || echo "main" |
| 19 | +``` |
| 20 | +Fall back to `main`, then `master` if the above fails. |
| 21 | + |
| 22 | +### 2. Identify the current feature branch |
| 23 | +```bash |
| 24 | +git rev-parse --abbrev-ref HEAD |
| 25 | +``` |
| 26 | + |
| 27 | +### 3. Get the merge base (branch point) |
| 28 | +```bash |
| 29 | +git merge-base HEAD <default_branch> |
| 30 | +``` |
| 31 | +Always diff from the **merge base**, not the tip of the default branch. This isolates only the commits introduced by the feature branch, excluding any upstream changes merged in. |
| 32 | + |
| 33 | +### 4. Collect the diff and log |
| 34 | +```bash |
| 35 | +# Stat summary (files changed, insertions, deletions) |
| 36 | +git diff --stat $(git merge-base HEAD <default_branch>) |
| 37 | + |
| 38 | +# Full diff (use sparingly for large repos — prefer --stat first) |
| 39 | +git diff $(git merge-base HEAD <default_branch>) |
| 40 | + |
| 41 | +# Commit log on this branch only |
| 42 | +git log --oneline $(git merge-base HEAD <default_branch>)..HEAD |
| 43 | +``` |
| 44 | + |
| 45 | +--- |
| 46 | + |
| 47 | +## Summarizing the Branch |
| 48 | + |
| 49 | +Produce a short, plain-English summary covering: |
| 50 | + |
| 51 | +1. **What changed** — files, modules, or systems affected |
| 52 | +2. **Why it changed** — the purpose or problem being solved (infer from code and commit messages if not stated) |
| 53 | +3. **Scope** — number of commits, files touched, rough size of the change |
| 54 | + |
| 55 | +Keep the summary to 3–6 sentences. Avoid restating the diff line-by-line. Focus on intent and impact, not mechanics. |
| 56 | + |
| 57 | +### Example summary format |
| 58 | +> This branch adds rate-limit handling to the API client. It introduces a retry loop with exponential backoff in `client.py` and updates `config.py` to expose a `MAX_RETRIES` setting. Three commits touch two files. No tests were changed. |
| 59 | +
|
| 60 | +--- |
| 61 | + |
| 62 | +## Writing a Commit Message |
| 63 | + |
| 64 | +Use the **imperative mood**, present tense, and keep it direct. Do not over-explain. |
| 65 | + |
| 66 | +### Format |
| 67 | +``` |
| 68 | +<Short subject line — 50 chars or fewer> |
| 69 | +
|
| 70 | +<Optional body — wrap at 72 chars. Explain WHAT and WHY, not HOW. |
| 71 | + Omit if the subject line is self-sufficient.> |
| 72 | +``` |
| 73 | + |
| 74 | +### Rules |
| 75 | +- **Subject line**: imperative mood ("Add", "Fix", "Remove", "Update") — not "Added" or "Adding" |
| 76 | +- **No period** at the end of the subject line |
| 77 | +- **Body** (optional): explain *why* the change was made if it isn't obvious; omit implementation details that are visible in the diff |
| 78 | +- **No fluff**: avoid "This commit...", "As per discussion...", "Various improvements" |
| 79 | +- If the branch has multiple unrelated concerns, note them with bullet points in the body |
| 80 | + |
| 81 | +### Example commit messages |
| 82 | + |
| 83 | +Single-concern branch: |
| 84 | +``` |
| 85 | +Add exponential backoff to API client retries |
| 86 | +``` |
| 87 | + |
| 88 | +Multi-concern or non-obvious branch: |
| 89 | +``` |
| 90 | +Refactor auth middleware to support token refresh |
| 91 | +
|
| 92 | +The previous implementation rejected expired tokens immediately. |
| 93 | +This change adds a refresh attempt before returning 401, matching |
| 94 | +the behavior expected by the mobile clients. |
| 95 | +``` |
| 96 | + |
| 97 | +--- |
| 98 | + |
| 99 | +## Quick Reference Commands |
| 100 | + |
| 101 | +| Goal | Command | |
| 102 | +|---|---| |
| 103 | +| Default branch | `git symbolic-ref refs/remotes/origin/HEAD \| sed 's@.*/@@'` | |
| 104 | +| Current branch | `git rev-parse --abbrev-ref HEAD` | |
| 105 | +| Merge base | `git merge-base HEAD <default>` | |
| 106 | +| Files changed | `git diff --name-only $(git merge-base HEAD <default>)` | |
| 107 | +| Stat summary | `git diff --stat $(git merge-base HEAD <default>)` | |
| 108 | +| Commit log | `git log --oneline $(git merge-base HEAD <default>)..HEAD` | |
| 109 | +| Full diff | `git diff $(git merge-base HEAD <default>)` | |
| 110 | + |
| 111 | +--- |
| 112 | + |
| 113 | +## Notes & Edge Cases |
| 114 | + |
| 115 | +- **Detached HEAD**: if `git rev-parse --abbrev-ref HEAD` returns `HEAD`, ask the user which branch they're working on. |
| 116 | +- **Large diffs**: for repos with thousands of changed lines, use `--stat` and `--name-only` first. Only fetch the full diff for files relevant to the summary. |
| 117 | +- **Merge commits on the branch**: use `git log --no-merges` to exclude them from the commit list when writing the message. |
| 118 | +- **Monorepos**: scope the diff to the relevant subdirectory with `git diff <merge-base> -- <path/to/dir>` if the branch touches only one package. |
| 119 | +- **No remote**: if there's no remote, fall back to comparing against `main` or `master` locally. |
0 commit comments