Comprehensive guide for git commit workflow covering feature branch development, main branch releases, commit message conventions, repository-specific requirements, and branch naming patterns.
Owner: agent-auditor
Applies when: a git commit message's subject line starts with a non-imperative verb form — past tense (added, fixed, updated), gerund (adding, fixing), or 3rd-person singular (adds, fixes, updates) — instead of the bare imperative form (add, fix, update).
Enforcement: judgment (PR/commit-message check; the agent reads commit subjects via git log --format=%s and flags non-imperative verbs against the prose Common Imperative Verbs table below)
Trigger: @commits
Why: Imperative mood matches Git's own convention (every internal git command produces an imperative message: "Merge branch X", "Revert commit Y") so the project history reads as one consistent voice. Past-tense and gerund forms also make git log --grep "^add" lossy — searching for added features finds 30% of them. The bare-imperative form is one fewer keystroke, one shorter subject line, and grep-friendly.
Added user authentication endpoint
Fixing the payment processor crash
Updates README with installation steps
add user authentication endpoint
fix payment processor crash
update README with installation steps
No-AI-attribution rule lives in git-workflow.md as git-workflow/no-ai-attribution-in-commits (canonical). This guide intentionally does not duplicate it — both would produce double-findings at PR review time, same owner (agent-auditor), same trigger surface. Treat the git-workflow rule as the single source of truth for AI-attribution enforcement on commits.
Owner: agent-auditor
Applies when: a git commit subject line exceeds 50 characters. Body lines may be longer (wrap at 72 per the broader convention) but the subject is the single line that has to fit GitHub's PR list view, git log --oneline, and 80-column terminals without wrapping.
Enforcement: scripts/rule-checks.sh (git log --format=%s HEAD~10..HEAD | awk over recent commits when .git present)
Why: GitHub truncates PR subject lines around 70 characters; terminals at 80 columns wrap awkwardly around 60+ char subjects after the SHA prefix; git log --oneline becomes hard to scan when every line wraps to 2-3 rows. The 50-char convention is a soft cap with operational payoff: every history-reading surface stays one line per commit.
add comprehensive user authentication endpoint with OAuth2 PKCE flow support
add OAuth2 PKCE auth endpoint
Owner: agent-auditor
Applies when: a git tag vX.Y.Z command runs on a feature branch (any branch that is not master / main). Tags landing on a feature branch attach to a non-canonical commit; after PR merge the master-branch merge commit lacks the tag, and git describe returns a misleading version.
Enforcement: judgment (PR/CI check; git for-each-ref --contains <feature-branch-tip> 'refs/tags/*' returning any tag = violation. The agent verifies the tagged commit is reachable from master, not just from the feature branch)
Trigger: @commits
Why: Tags represent released versions that users consume via git checkout vX.Y.Z or claude plugin install pkg@vX.Y.Z. A tag on a feature branch points at a commit that may differ from what landed on master (rebase, squash, amendment during review), so users who fetch the tag get pre-merge code that nobody actually reviewed. Only master-branch commits — the merge commits CI tested and reviewers approved — should carry release tags. The release procedure: merge first, tag second. See releasing-coding.md for the canonical autoRelease workflow when .maintainer.yaml has release.autoRelease: true.
# On branch feature/oauth-endpoint
git add . && git commit -m "release v1.5.0" && git tag v1.5.0 && git push --tags # WRONG: tag lives on feature commit; master will lack v1.5.0 after merge# On feature branch: just push, no tag
git push -u origin feature/oauth-endpoint
gh pr create
# After merge to master, on master:
git checkout master && git pull && git tag v1.5.0 && git push origin v1.5.0
# Or use autoRelease bot per .maintainer.yaml (preferred for bborbe repos)Structure:
<imperative verb> <description under 50 chars>
[Optional body with details]
[Reference issues: #123]
Rules:
- Use imperative mood: "Add feature" not "Added feature" or "Adds feature"
- Keep first line under 50 characters: Subject line should be concise
- Separate subject from body: Use blank line between subject and body
- Reference issues/PRs when relevant: Link to tracking issues
- NEVER add AI attribution: No "Generated with Claude" or similar
Examples:
# ✅ Good
git commit -m "add user authentication endpoint"
git commit -m "fix null pointer in payment processor"
git commit -m "update README with installation steps"
# ❌ Bad
git commit -m "Added user authentication endpoint" # Not imperative
git commit -m "fixes" # Not descriptive
git commit -m "Generated with Claude: add authentication" # AI attributionCommon Imperative Verbs:
add- New feature or filefix- Bug fixupdate- Modification to existing featureremove- Delete feature or filerefactor- Code restructuring without behavior changedocs- Documentation only changestest- Test additions or modifications
For commits in feature branches (non-main branches):
- Run pre-commit checks:
make precommit- ALWAYS run this first - Update changelog: Add changes to
CHANGELOG.mdwith new version number - REQUIRED for all commits - Stage and commit:
git add . && git commit -m "commit message" - NO TAGGING: Do not tag commits in feature branches
Critical Notes for Feature Branches:
- Never commit without first updating the changelog
- Update CHANGELOG.md with the planned version number for tracking
- DO NOT TAG feature branch commits - tags should only point to main branch commits
- Version numbers in CHANGELOG.md represent planned releases, not actual releases
For commits merged to main branch (actual releases):
- After PR merge: Ensure the commit is in the main or master branch
- Verify changelog: Confirm CHANGELOG.md has the correct version for this release
- Tag the release:
git tag v1.x.x(use exact version from CHANGELOG.md) - Push tag:
git push origin v1.x.x
Critical Notes for Main Branch:
- Only tag commits that are in the main or master branch
- Tags represent actual releases available to users
- The tag version MUST match the version in CHANGELOG.md exactly
- Tags should point to merge commits or squashed commits in main
# 1. Create feature branch
git checkout -b feature/my-feature
# 2. Make changes and follow feature branch workflow
make precommit
# Update CHANGELOG.md with planned version
git add .
git commit -m "implement feature X"
# NO TAGGING
# 3. Push and create PR
git push origin feature/my-feature
gh pr create# 1. After PR is merged, checkout main
git checkout main
git pull origin main
# 2. Tag the release (only if you're the maintainer)
git tag v1.x.x # Use version from CHANGELOG.md
git push origin v1.x.xConfiguration (email, GPG key, branch naming) varies by repository context to ensure proper attribution and signing.
Detection Patterns:
- Internal git hosting:
git.company.com - Organization GitHub:
github.com/company-name - Enterprise Bitbucket:
bitbucket.company.com
Required Configuration:
git config user.email your.name@company.com
git config user.signingkey YOUR_GPG_KEY_ID
git config commit.gpgsign trueBranch Naming Pattern: PROJECT-12345-description
PROJECT: Issue tracker project key (e.g.,API,WEB,DB)12345: Issue numberdescription: Short descriptive name (lowercase, hyphens)
Examples:
API-1234-add-authenticationWEB-5678-user-dashboardDB-9012-migration-script
Branch Ancestry Requirement:
- Feature branches MUST be created from
origin/master, not localmaster - Ensures branch is based on latest remote state
- Prevents merge conflicts and outdated base branches
Correct workflow:
git fetch
git checkout -b API-1234-new-feature origin/masterWrong workflow:
# ❌ DON'T DO THIS
git checkout master
git checkout -b API-1234-new-feature # based on local masterProtected Branches (skip branch naming/ancestry validation):
mastermainstagingdev
Detection Pattern:
- Personal GitHub:
github.com/username - Personal GitLab:
gitlab.com/username
Required Configuration:
git config user.email your.email@example.com
git config user.signingkey YOUR_GPG_KEY_ID
git config commit.gpgsign trueBranch Naming:
- No specific requirements
- Use descriptive names (e.g.,
feature/user-auth,fix/null-pointer)
Branch Ancestry:
- No specific requirements
- Can branch from local
mainororigin/main
Warning:
⚠️ Email: personal@gmail.com (should end with @company.com)
Fix:
git config user.email your.name@company.comWarning:
⚠️ Missing or incorrect GPG signing key
Current: PERSONAL_KEY_ID
Expected: COMPANY_KEY_ID
Fix:
git config user.signingkey COMPANY_KEY_IDWarning:
⚠️ GPG signing not enabled
Fix:
git config commit.gpgsign trueWarning:
⚠️ Branch: fix-typo (should be PROJECT-12345-description)
Example: API-1234-fix-authentication
Fix:
- Rename branch:
git branch -m API-1234-description - Or create new branch with correct name:
git checkout -b API-1234-fix-typo origin/master
Warning:
⚠️ origin/master not in branch history
Fix: git fetch && git rebase origin/master
Fix Option 1 - Rebase:
git fetch && git rebase origin/masterFix Option 2 - Create new branch:
git fetch && \
git checkout -b API-1234-new-branch origin/master && \
git cherry-pick <commit-range>Problem:
git commit -m "add authentication \n\nGenerated with Claude"Fix:
# Amend the last commit (if not pushed)
git commit --amend -m "add authentication"
# Or create new commit with correct message
git reset --soft HEAD~1
git commit -m "add authentication"Prevention: Always follow commit message format without any AI attribution.
Feature Branch Workflow:
# Company/organization repos
git fetch && \
git checkout -b API-1234-feature origin/master && \
make precommit && \
git add . && \
git commit -m "add new feature" && \
git push origin API-1234-feature && \
gh pr create
# Personal/open source repos
git checkout -b feature/new-feature && \
make precommit && \
git add . && \
git commit -m "add new feature" && \
git push origin feature/new-feature && \
gh pr createMain Branch Release:
git checkout main && \
git pull origin main && \
git tag v1.x.x && \
git push origin v1.x.xCommit Message Template:
<verb> <description under 50 chars>
[Optional detailed explanation]
[References: #123]