Cc-skills conventional-git
Conventional Commits v1.0.0 branch naming and commit message standards for GitHub and GitLab projects. Use when creating branches, writing commits, generating commit messages, reviewing branch conventions, or setting up changelog automation. Apply when your project needs consistent git history, SemVer-driven releases, parseable changelog generation, or automatic issue closing.
git clone https://github.com/samber/cc-skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/samber/cc-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/conventional-git" ~/.claude/skills/samber-cc-skills-conventional-git && rm -rf "$T"
skills/conventional-git/SKILL.mdConventional Commits & Branch Naming
Follow Conventional Commits v1.0.0 for both branch names and commit messages — consistent naming lets tools auto-generate changelogs, enforce SemVer bumps, and filter history by concern.
Branch Naming
Format:
<type>/[issue-]<description> — lowercase, hyphens only, no special chars except /.
feat/user-authentication feat/42-user-authentication fix/login-race-condition fix/87-login-race-condition docs/api-reference-update refactor/payment-module
Prefix with the issue number when one exists — GitHub and GitLab auto-link it and it makes
git log immediately traceable to the tracker. Keep the description under 50 characters — most git UIs truncate branch names in lists around that length. Match the type to the work you're doing — this is the contract readers use to understand the branch purpose at a glance.
NEVER include
worktree in a branch name — git worktrees are a local checkout mechanism, not a branch concept; the name would leak implementation details into the remote and confuse other contributors.
Commit Message Format
<type>[optional scope]: <description> [optional body] [optional footer(s)]
Types:
| Type | SemVer | When |
|---|---|---|
| MINOR | New feature |
| PATCH | Bug fix |
| — | Docs only |
| — | Formatting, no logic change |
| — | Restructure, no feature/fix |
| — | Performance improvement |
| — | Add/fix tests |
| — | Build system, deps |
| — | CI config |
| — | Anything else (not src/test) |
| — | Reverts a previous commit |
Rules:
- Subject line ≤ 72 characters — git log and GitHub/GitLab UIs silently truncate longer subjects
- Imperative mood: "add" not "added" — reads as an instruction, not a history log
- No capital letter, no trailing period — enforces uniform parsing by changelog tools
- Body separated by blank line — parsers split header/body at the first blank line
- Breaking changes: use
after type/scope, or add!
footer (triggers MAJOR bump) — body-only descriptions are invisible to changelog toolsBREAKING CHANGE:
commits SHOULD includerevert
in the body —This reverts commit <hash>.
generates this automatically; don't strip itgit revert- NEVER add a Claude signature, AI agent attribution, or
trailer for Claude or any other AI agent to commitsCo-authored-by
Examples:
feat(auth): add JWT token refresh
fix: prevent race condition on concurrent requests Introduce request ID and reference to latest request. Dismiss responses from stale requests.
refactor!: drop support for Go 1.18 BREAKING CHANGE: Go 1.18 no longer supported; uses stdlib APIs from 1.21+
Closing Issues via Commit Messages
Both GitHub and GitLab detect keywords in commit messages and automatically close the referenced issue when the commit lands on the default branch. Place the reference in the footer (preferred — keeps the subject line clean).
Keywords:
close, closes, closed, fix, fixes, fixed, resolve, resolves, resolved — case-insensitive.
GitHub:
fix(auth): prevent token expiry race condition Closes #42 Closes owner/repo#99
- Triggers when merged into the default branch (usually
)main - Cross-repo:
Closes owner/repo#42 - Close multiple:
Closes #42, closes #43 - Works in PR descriptions too
GitLab:
feat: add dark mode support Resolves #101 Closes group/project#42
- Triggers when merged into the default branch (configurable per project)
- Cross-project:
Closes group/project#42 - Close multiple:
Closes #101, closes #102 - Works in MR descriptions too
Tip: Pair with the commit type —
fix: closing a bug issue, feat: closing a feature request — keeps the changelog semantically coherent.
Common Mistakes
| Mistake | Fix |
|---|---|
| — imperative, no capital |
| — no trailing period |
| Subject over 72 chars | Shorten; move detail to body |
| Breaking change only in body | Add or footer — tools won't detect body-only |
| — scope is a noun, not a verb |
| Closes #42 in subject line | Move to footer — keeps subject clean and parseable |
Best Practices
- Align branch type and commit type —
branch →feat/auth-*
commitsfeat(auth): - One concern per branch — mixing fixes into feature branches obscures the changelog
- Use scope consistently within a branch —
throughout, notfeat(auth):
mid-wayfeat(user): - Squash merge: when squash-merging a PR/MR, the branch commits are collapsed into one — the PR/MR title becomes the commit message. If the title doesn't follow conventional commits format, changelog generation breaks silently. Always set the PR title before squashing.