A Claude Code skill that enforces a disciplined Gitflow-based development workflow with conventional commits, semantic versioning, and issue-driven branching.
Installation · Usage · What It Enforces · Contributing · Onboarding
Clone the repo and run the install script for your platform. The script creates a symlink, so the skill stays in sync with the repo automatically.
git clone https://github.com/qubernetic-org/git-workflow-agent-skill.git
cd git-workflow-agent-skill
./scripts/install_linux.shgit clone https://github.com/qubernetic-org/git-workflow-agent-skill.git
cd git-workflow-agent-skill
./scripts/install_macos.shgit clone https://github.com/qubernetic-org/git-workflow-agent-skill.git
cd git-workflow-agent-skill
.\scripts\install_windows.ps1Note: Windows symlinks require Developer Mode enabled or an elevated terminal. The script falls back to a file copy if symlinks are unavailable.
# Linux
./scripts/install_linux.sh --uninstall
# macOS
./scripts/install_macos.sh --uninstall# Windows
.\scripts\install_windows.ps1 -UninstallIf you prefer not to use the scripts:
mkdir -p ~/.claude/skills/git-workflow
ln -s "$(pwd)/SKILL.md" ~/.claude/skills/git-workflow/SKILL.mdThe skill will be automatically discovered on the next Claude Code session.
The skill activates automatically when you ask Claude Code to perform any git operation:
> Commit my changes
> Create a branch for this feature
> Prepare a release for version 1.2.0
> I need to hotfix a production bug
Or invoke directly:
/git-workflow
| Rule | Description |
|---|---|
| Gitflow branching | main, develop, feature/*, fix/*, hotfix/*, release/* |
| Conventional Commits | Structured messages — feat:, fix:, docs:, chore:, etc. |
| Atomic commits | One logical change per commit, no mixed concerns |
--no-ff merges |
All merges into protected branches preserve branch topology |
| No AI signatures | No "Co-Authored-By" or "Generated by" lines |
| Semantic Versioning | MAJOR.MINOR.PATCH with proper bump rules |
| Issue-driven workflow | Every branch starts from an issue and closes it via PR |
| PR-only merges | main and develop are never committed to directly |
| Conventional PR titles | PR titles follow Conventional Commits format |
%%{init: { 'theme': 'base', 'themeVariables': { 'git0': '#0969da', 'git1': '#e8590c', 'git2': '#7c3aed', 'git3': '#2da44e', 'git4': '#fe5196', 'git5': '#2da44e', 'git6': '#cf222e', 'gitBranchLabel0': '#ffffff', 'gitBranchLabel1': '#ffffff', 'gitBranchLabel2': '#ffffff', 'gitBranchLabel3': '#ffffff', 'gitBranchLabel4': '#ffffff', 'gitBranchLabel5': '#ffffff', 'gitBranchLabel6': '#ffffff', 'commitLabelFontSize': '11px', 'tagLabelFontSize': '12px' }, 'gitGraph': { 'mainBranchName': 'main', 'rotateCommitLabel': true, 'showCommitLabel': true } } }%%
gitGraph
commit id: "init"
commit id: " " tag: "v0.1.0"
branch develop order: 1
commit id: "setup"
branch "feature/1-auth" order: 2
commit id: "login"
commit id: "logout"
checkout develop
merge "feature/1-auth" id: " merge-1"
branch "feature/2-search" order: 3
commit id: "index"
commit id: "query"
checkout develop
branch "fix/3-typo" order: 4
commit id: "typo"
checkout develop
merge "fix/3-typo" id: " merge-3"
merge "feature/2-search" id: " merge-2"
branch "release/1.0" order: 1
commit id: "bump"
commit id: "changelog"
checkout main
merge "release/1.0" id: " " tag: "v1.0.0"
checkout develop
merge main id: " back-merge"
checkout main
branch "hotfix/4-crash" order: 2
commit id: "crash-fix"
commit id: "patch"
checkout main
merge "hotfix/4-crash" id: " " tag: "v1.0.1"
checkout develop
merge main id: " hotfix-sync"
commit id: "next"
| Pattern | Base | Merges into | Purpose |
|---|---|---|---|
feature/<issue>-<slug> |
develop |
develop |
New features |
fix/<issue>-<slug> |
develop |
develop |
Bug fixes |
hotfix/<issue>-<slug> |
main |
main + develop |
Urgent production fixes |
release/<version> |
develop |
main + develop |
Release preparation |
<type>(<optional scope>): <description>
feat(auth): add OAuth2 login flow
fix: resolve race condition in websocket reconnect
chore(release): prepare 1.2.0
feat!: drop support for Node 16
See SKILL.md for the full specification including commit types, breaking change conventions, versioning rules, release processes, and the complete forbidden operations list.
| Aspect | This Skill (Gitflow) | GitHub Flow | Trunk-Based |
|---|---|---|---|
| Branches | main + develop + typed branches |
main + feature branches |
main only |
| Releases | Explicit release branches with version bump | Deploy from main on merge | Continuous deploy from main |
| Commit style | Conventional Commits (enforced) | Free-form | Free-form |
| Merge strategy | --no-ff merge commits (preserves topology) |
Squash merge (flat history) | Squash or rebase |
| Traceability | Issue → branch → PR → changelog | PR-based | Commit-based |
| Best for | Versioned releases, libraries, skills, APIs | SaaS with continuous deploy | Small teams, rapid iteration |
- You ship discrete versions (v1.0, v1.1, v2.0) rather than continuous deploys
- You need a clear audit trail from issue to release
- Multiple features develop in parallel with different release timelines
- You want hotfix capability without disrupting in-progress work
- You deploy to production on every merge (GitHub Flow is simpler)
- You have a single developer with no parallel work streams
- Your project doesn't use semantic versioning
The skill enforces workflow rules through Claude Code, but you can add mechanical enforcement for your team with these tools:
npm install --save-dev @commitlint/{cli,config-conventional}// commitlint.config.js
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [2, 'always', [
'feat', 'fix', 'docs', 'chore', 'refactor',
'test', 'style', 'perf', 'ci', 'build', 'revert'
]],
'subject-case': [2, 'always', 'lower-case'],
'subject-full-stop': [2, 'never', '.'],
'header-max-length': [2, 'always', 72],
},
};npm install --save-dev husky
npx husky init
echo "npx --no -- commitlint --edit \$1" > .husky/commit-msgAdd to your GitHub Actions workflow:
- name: Validate branch name
if: github.event_name == 'pull_request'
run: |
BRANCH="${{ github.head_ref }}"
PATTERN="^(feature|fix|docs|hotfix|release)/[a-z0-9-]+$"
if [[ ! "$BRANCH" =~ $PATTERN ]]; then
echo "::error::Branch '$BRANCH' doesn't match pattern: $PATTERN"
exit 1
fiNote: These tools complement the skill — they catch mechanical errors (typos in commit types, wrong branch names) while Claude Code handles the higher-level workflow logic (correct base branch, issue traceability, release process).
See CONTRIBUTING.md for guidelines and ONBOARDING.md for a new contributor guide.