git-flow-master
SkillDev toolsEnd-to-end Git operator for any branching strategy. Auto-detects the project's strategy (solo-main, main+integration, enterprise multi-branch, trunk-based, GitFlow, GitHub Flow, GitLab Flow, SDET integration-trunk for chained test-automation suites) from .git config, branches, and the `git_strategy:` block in `.agents/project.yaml`, then adapts every commit, branch, push, PR, conflict-fix, and chained-PR action to that strategy. Use this skill whenever the user wants to: create a branch (`crear branch`, `new feature branch`, `start work on UPEX-123`), commit changes (`commit this`, `commitear esto`, `make a commit`, `commit and push`), push code (`push`, `push to main`, `push to staging`, `subir cambios`), open a pull request (`create PR`, `open PR`, `abrir PR`, `crear pull request`, `gh pr create`), fix merge conflicts (`fix conflict`, `resolver conflicto`, `merge conflict`, `rebase conflict`, `push rejected`), plan stacked or chained PRs (`stack of PRs`, `chained PRs`, `split this PR`, `PR demasiado grande`), set up an isolated git worktree (`worktree`, `work in a worktree`, `isolate this work`, `parallel session`, `aislar el trabajo`, `trabajar aislado`), set up or bootstrap a branching strategy on a fresh repo (`set up our git strategy`, `bootstrap branching`, `configura el flujo de git`, `git strategy setup`, `materialize the git flow`, `create the staging branch and write the runbook`), or pick / change / set up a branching strategy (`git flow`, `git strategy`, `branching strategy`, `which git flow do we use`, `set up our git strategy`, `bootstrap branching`, `configura el flujo de git`). Trigger even when the user does not say `git-flow-master` literally, if the work is git-or-PR-shaped, this is the right tool. Do NOT use for: testing tickets (use /sprint-testing), authoring test cases in TMS (use /test-documentation), writing automated tests (use /test-automation), running regression suites (use /regression-testing), or general code editing, git-flow-master operates strictly on the version-control layer.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the git-flow-master skill
What this skill tells your AI
The instructions your AI receives, as published by upex-galaxy/agentic-qa-boilerplate in .agents/skills/git-flow-master/SKILL.md and read by ahel’s review.
Git Flow Master — One Skill for Branches, Commits, Pushes, PRs, and Conflicts
This skill is the project's single entry point for everything that happens on the version-control layer: creating branches, writing commits, pushing safely, opening pull requests, resolving conflicts, and planning chained / stacked PRs when a change outgrows the review budget.
It does not assume one branching model. The project may run on main only, on main + staging, on a multi-branch enterprise layout, or on any of the well-known flows (trunk-based, GitFlow, GitHub Flow, GitLab Flow). The skill detects which one is active and adapts every command accordingly. The detection is sticky: once resolved, the strategy is recorded in the git_strategy: block of .agents/project.yaml so future invocations skip the prompt.
Compact Rules
- DO: read the repo state (status, branches, diff, log, fetch, upstream, remotes) at the start of EVERY invocation and report it before acting. Never assume repo state.
- DO: resolve the branching strategy from the
git_strategy:block in.agents/project.yamlfirst, then layout heuristics, then by asking — never pick one silently. Persist the resolution back into that block, never into a separate file and never as policy prose inAGENTS.md. - WHEN
git_strategy.strategyis set butproject.project_nameis null, ormeta.strategy_sourceis stillinheritedon a named project: the strategy was INHERITED from the template, not chosen. Treat it as unconfirmed and OFFER Strategy Setup once per session — never auto-run it, and proceed under the inherited strategy on a "no". - DO: consult
git_strategy.policy.direct_push_to_protectedbefore any direct push to a protected branch —allowedis standing authorization (asking anyway collapses it intoconfirm),confirmasks every time,forbiddenrefuses and routes through a PR. A missing or null block behaves asconfirm. - DO NOT: force-push,
--force-with-lease,--no-verify, amend or rebase a pushed commit, or otherwise rewrite pushed history, unless the user explicitly authorizes it AND the branch is unshared. - DO NOT: run a repo-wide discard (
git restore .,git checkout -- .,git reset --hard, untargetedgit stash,git clean -f) — concurrent sessions may share this working tree. Discard only explicit paths this session modified; unclear ownership means stop and ask. - DO NOT:
git add -Aorgit add .. List explicit paths, so a secret or another session's work cannot ride along. - DO: keep one commit to one responsibility, in conventional format (
{type}({ISSUE-KEY}): {description}). Commit messages, branch names and PR bodies are English and carry NO AI attribution. - WHEN a pre-commit hook rejects a commit: stop, fix the underlying issue, and create a NEW commit. Never
--amendthe rejected one. - DO: propose every branch name, commit set, and PR body and wait for an explicit OK before executing.
- DO: stop at PR creation — merging is the user's next step, never automatic. If the
ghtransport is missing or unauthenticated, surface the blocker instead of implying a PR was opened. - WHEN reconciling declared policy against the host: run the policy-verify tool once at the first push / PR / merge intent, never hand-query protection endpoints. A
404on the classic protection endpoint does not mean unprotected, and a push that succeeded may have been a documented bypass, not permission. Report drift; never auto-correct it. - WHEN a planned change exceeds ~400 changed lines: run the chained-PR decision (single-pr / stacked-to-main / feature-branch-chain / size-exception) before coding, and re-run it if the real diff outgrows the estimate rather than silently up-budgeting.
- WHEN a conflict fires: diagnose and classify it first, present options ranked by safety, and prefer a safe abort over a guess. Never pick a destructive option silently.
Read full SKILL.md when: running Strategy Setup, resolving a specific conflict type, picking a base branch or branch prefix for an unfamiliar strategy, or setting up an isolated worktree.
When to use
Trigger on any of these intents — even without literal keywords:
- "I want to start work on UPEX-123" → branch creation
- "commit and push", "subir cambios", "push to main" → commit + push flow
- "abrí un PR contra staging" → PR creation
- "tengo conflictos al hacer pull" → conflict resolution
- "este PR va a quedar enorme" → chained-PR planning hand-off
- "qué estrategia de git usamos en este repo" → strategy detection / persistence
- "el push fue rechazado" → diagnostic + recovery flow
If the user is asking about testing a ticket, authoring test cases, writing automated tests, or running regression suites — that is not this skill. Hand back to /sprint-testing, /test-documentation, /test-automation, or /regression-testing.
The six operations
Every git-flow-master invocation maps to one (or a sequence) of these six operations. Operation choice is driven by the user's request; strategy resolution shapes how each operation runs.
| Op | Trigger phrases (examples) | Skill behaviour |
|---|---|---|
| Branch | "create branch", "new feature branch", "start UPEX-123" | Resolve strategy → propose name with prefix + issue key → wait for OK → checkout |
| Commit | "commit this", "commit and push", "make atomic commits" | Group by responsibility → propose conventional commits → wait for OK → execute one-by-one |
| Push | "push", "push to main", "subir cambios" | Diagnose upstream → confirm if pushing to a protected branch → never --force without explicit user opt-in |
| PR | "create PR", "abrir PR", "gh pr create" | Pick base branch from strategy → render body inline → ask labels/reviewers → call gh pr create |
| Conflict | "fix conflict", "rebase failed", "push rejected" | Diagnose first (see references/conflict-resolution.md) → present options → guide resolution → verify clean state |
| Strategy Setup | "set up our git strategy", "bootstrap branching", "configura el flujo de git", "materialize the flow" | Resolve strategy → run decision questionnaire (Q1-Q4) → conditionally create/ff-sync long-lived branches (never force) → write the git_strategy: block in .agents/project.yaml. Skips questions already answered by non-n/a git_strategy.decisions.* fields. See references/strategy-setup.md. |
When the operation is ambiguous (user just says "git-flow-master" or "let's do the git stuff"), report the current repo state (Step 1 below) and ask what they need.
Step 1 — Always: read the repo state
Run these silently every invocation. Do not act until the picture is clear:
git status
git branch --show-current
git branch -a
git diff --stat
git log --oneline -5
git fetch origin
git status -sb
git remote -v
Summarise to the user:
- Current branch.
- Dirty / clean working tree (staged / unstaged / untracked counts).
- Unpushed / unpulled commits (ahead / behind upstream).
- Upstream status (no upstream, up-to-date, diverged).
- Remote name(s) — most repos have one (
origin); some have a fork + upstream.
This summary is cheap, prevents 90% of mistakes, and is the input to every subsequent decision.
Step 1b — Reconcile the declared policy against the host (once per session)
git_strategy.policy.* in .agents/project.yaml records what the team DECIDED. The hosting platform records what is actually ENFORCED. These drift, and the drift only surfaces at the worst moment: a merge that stalls on an approval nobody expected, or a "protected" branch that was never protected.
Run this ONCE per session, at the first push / PR / merge intent (not on read-only operations), and cache the result for the rest of the session.
Run the tool; do not perform the queries by hand:
bun run git:policy verify # read-only; exit 1 on drift
bun run git:policy verify --stamp # same, and records the reconciliation when clean
It queries BOTH GitHub protection mechanisms for every branch in git_strategy.branches / protected, compares the union against the declared policy, and prints each divergence as declared vs enforced. The strategy-to-ruleset mapping and what the tool deliberately does not manage: references/ruleset-parity.md.
Why a tool rather than a checklist. This reconciliation existed only as prose in the sibling boilerplate and kept not happening — that repo shipped require_pr_reviews: 0 against a host demanding one approval plus a code-owner review, and it surfaced months later as a refused merge. This repo had the identical divergence. A script performs every query on every run; a procedure performs the ones the reader remembered.
Facts that still bind you when reading its output:
- A
404frombranches/{b}/protectiondoes NOT mean the branch is unprotected. A repo governed by rulesets returns404there while enforcing PR requirements, approvals, signed commits and non-fast-forward bans throughrules/branches/{b}. Stopping at the classic endpoint produces a confident "unprotected" reading on a branch that requires a reviewed pull request. - A push that succeeds is not evidence of an absent rule. Org owners and anyone on the ruleset bypass list push through while the rule still binds everyone else. When a push prints
Changes must be made through a pull request, that was a BYPASS: report it as one, never as permission. Withgit_strategy.policy.admin_bypass: true(or the divergence listed ingit_strategy.policy.accepted_divergences), theBypassed rule violationsremote line is the DOCUMENTED norm — mention it in the report as expected, do NOT treat it as an anomaly, do NOT stall asking for confirmation, and NEVER open a PR to "satisfy" the rule. require_code_owner_review: truewith noCODEOWNERSfile is unsatisfiable, not strict. Nobody outside the bypass list can clear it, so every merge becomes a bypass.
On drift, report — never auto-correct. Three legitimate resolutions: update .agents/project.yaml to match the host, change the host (bun run git:policy apply, dry run until --yes), or accept the divergence and record WHY in this project's own AGENTS.md. Editing either side needs the user's choice.
Step 2 — Resolve the branching strategy
The skill supports eight strategies (see references/branching-strategies.md for the full catalogue, detection signals, and trade-offs):
| Strategy | One-line description |
|---|---|
solo-main | Single long-lived branch (main). All work lands directly. Best for solo projects, scratch repos, prototypes. |
main-integration | main (production) + a single integration branch (staging / dev / develop). Features merge to integration, release-promote to main. |
enterprise | main + integration + many short-lived feature/*, fix/*, release/*, hotfix/* branches. Adds environment branches when needed. |
trunk-based | Trunk (main) is the only long-lived branch. Short-lived feature branches (<1 day) merge fast, behind feature flags. CI gate is non-negotiable. |
gitflow | Vincent Driessen's classic. main (releases) + develop (integration) + feature/* + release/* + hotfix/*. Heavyweight; mostly legacy. |
github-flow | main always deployable. feature/* branches → PR → merge → deploy. No staging/develop branch. |
gitlab-flow | GitHub Flow + environment branches (pre-production, production) to model deployment promotion. |
sdet | SDET Gitflow. main (confirmed tests) + ephemeral per-suite integration trunk test/<module>-suite. Test tickets chain through the trunk (--no-ff); one final PR → main. For chained test-automation suites. Opt-in; see references/sdet-integration-trunk.md. |
Detection algorithm
Apply in order; stop at the first definitive answer:
git_strategy:block in.agents/project.yaml— read it. Ifgit_strategy.strategyis non-null (one of the eight slugs), it +git_strategy.branches(production / integration / ephemeral_pattern) +git_strategy.decisions(promote_method / feature_merge / hotfix_policy) ARE the persisted decision — use them. Eachgit_strategy.decisions.*field whose value is NOTn/a/empty means Strategy Setup SKIPS that question on re-run (idempotent — idempotency is keyed off thegit_strategy.decisions.*fields, not markers). Inherited-template guard: the boilerplate ships the block FILLED (strategy: solo-main) and a scaffolded project INHERITS it verbatim (the scaffolder only patchesproject.project_name/project.project_key). So a non-nullgit_strategy.strategyis only authoritative when the project is actually onboarded. Readproject.project_namein the SAME file: ifgit_strategy.strategyis non-null BUTproject.project_nameisnull, the block was INHERITED from the template (not chosen for THIS project) — treat the strategy as UNCONFIRMED and route to the Bootstrap trigger's inherited case (it still operates under the inherited strategy if the offer is declined). Ifproject.project_nameis set, the block is confirmed → use it normally, no nudge.- Single-branch heuristic —
git branch -ashows onlymain(ormaster) and no integration branch in the remote →solo-main. - Two-branch heuristic — exactly
main(ormaster) + one of{staging, dev, develop, integration}exists upstream →main-integration(record the integration branch name). - Multi-branch heuristic —
main+ integration + activefeature/*orrelease/*branches ingit branch -a→enterprise. - Project hints — look for
.gitlab-ci.yml(suggestsgitlab-flow),release/*andhotfix/*long-lived branches (suggestsgitflow). - Fallback — ask the user. Show the options with one-line descriptions; mirror their language. Do NOT pick silently. On a test-automation repo (KATA / Playwright /
/test-automation), surfacesdetas the recommended option.sdetis opt-in only — never inferred silently from layout; a livetest/<module>-suitetrunk withtest/{KEY}-*PRs targeting it confirms an already-activesdetsuite.
Persist the decision
Once resolved (whether by detection or by asking), write/update the git_strategy: block in place inside .agents/project.yaml (preserve the rest of the file — it holds project identity, env config, etc.; create the block if it is missing). NEVER write a separate file. It is the single source of truth. At minimum the first five operations need git_strategy.strategy + git_strategy.branches; the full schema (with git_strategy.decisions, git_strategy.protected, git_strategy.policy, git_strategy.branch_prefixes, git_strategy.meta) is populated by Strategy Setup (3.6).
# .agents/project.yaml — git_strategy block (only the fields that apply shown)
git_strategy:
strategy: main-integration
branches:
production: main
integration: staging
ephemeral_pattern: null
The block is the source of truth; its git_strategy.description field is the one-paragraph human summary. The user can edit it; the next invocation re-reads it.
AGENTS.md's ## Git Strategy section is just a pointer to .agents/project.yaml (git_strategy: block) — NEVER write strategy policy or branch decisions into AGENTS.md.
If the strategy uses an integration branch with a non-default name (anything other than staging), record it under git_strategy.branches.integration so commits don't have to re-detect.
Block fields and idempotent setup. git_strategy.strategy + git_strategy.branches are the minimum the first five operations need. Strategy Setup (3.6) additionally populates the three git_strategy.decisions.* fields (promote_method, feature_merge, hotfix_policy) plus the git_strategy.policy.* fields (Q4); these gate questionnaire skips. On any later invocation, detection reads the block and treats each git_strategy.decisions.* field that is NOT n/a/empty as an already-answered questionnaire question — Strategy Setup re-run only asks the questions whose git_strategy.decisions.* fields are still n/a, and never recreates a branch that already exists.
Bootstrap trigger — offer setup on a fresh repo (never auto-run)
At the top of any git intent, after Step 1 (repo state) and Step 2 detection have run, evaluate the gate — it fires on EITHER of two conditions:
(a) Unset —
git_strategy.strategyin.agents/project.yamlis null (or thegit_strategy:block is absent) AND the repo looks fresh — any of: onlymain/masterexists locally and on the remote; fewer than ~3 commits; or a boilerplate sentinel file is present (e.g..agents/project.yaml).(b) Inherited —
git_strategy.strategyis non-null BUTproject.project_name(same file) isnull. The block was INHERITED from the boilerplate template (this project has not been onboarded yet) — it was NOT chosen for THIS project. Treat it as UNCONFIRMED.
If EITHER condition is true, OFFER (do not auto-execute, do not silently pick a strategy), using the matching prompt:
(unset case (a)) "No git strategy is set up yet. Want me to run Strategy Setup — pick the flow, create the branches it needs, and write the
git_strategy:block in.agents/project.yaml? (Y/N)"
(inherited case (b)) "This project's
git_strategylooks inherited from the boilerplate (project not onboarded yet —project.project_nameis null). Want to run Strategy Setup to define this project's own flow? (Y/N)"
Rules:
- Offer once per session, then cache the answer. Do not re-prompt every git intent in the same session.
- Never auto-run. A
Noproceeds with the requested operation under the detected (case a) or inherited (case b) strategy without writing the block. - A
Yesenters Strategy Setup (3.6) before continuing with the original git intent. - The boilerplate ships
.agents/project.yamlwith thegit_strategy:block FILLED (strategy: solo-main); a scaffolded project INHERITS it verbatim (the scaffolder patches onlyproject.project_name/project.project_key, and the updater freezes the file viabootstrapOnlyPaths). So the unset case (a) and the inherited case (b) are the two ways a project reaches a real git intent without having confirmed its own flow → the offer fires on first real use — by design (template-trap guard). Ifproject.project_nameis set, the strategy is confirmed and NEITHER case fires.
Step 3 — Operation-specific runbooks
3.1 Branch creation
Decide the prefix from the dominant change. Use this fixed vocabulary (mixed-changes precedence: feat > fix > refactor > test > docs > chore):
| Prefix | When the dominant change is… |
|---|---|
feat/ | new feature or capability |
fix/ | bug fix |
test/ | adding or updating automated tests (no product code) |
docs/ | docs only |
refactor/ | code change without behaviour change |
chore/ | tooling, deps, housekeeping |
For enterprise and gitflow strategies, also consider release/X.Y.Z and hotfix/X.Y.Z when appropriate.
In a QA repo most work lands as test/, fix/, or chore/ branches. Feature branches (feat/) are rare here — a feat/ in this repo usually means a change to the test framework itself (new fixture, new Page component layer, new reporter).
Issue key extraction (in order):
- Current branch name regex:
(?:feat|feature|fix|test|docs|refactor|chore)/([A-Z]+-\d+)-. $ARGUMENTSfor[A-Z]+-\d+.- Ask the user once: "Is there an issue key for this work?" — accept "no" gracefully.
Branch name format — read git_strategy.branch_prefixes in .agents/project.yaml (naming_with_key / naming_without_key / precedence); the patterns below are the shipped defaults, used verbatim when the block is absent:
- With key:
{prefix}/{ISSUE-KEY}-{kebab-slug}(e.g.test/UPEX-123-bulk-assign-coverage). - Without key:
{prefix}/{kebab-slug}(e.g.refactor/split-kata-fixtures). - Keep slugs lowercase, hyphen-separated, ≤50 chars.
Strategy-specific source branch:
solo-main,github-flow,trunk-based→ branch offmain.main-integration,gitlab-flow→ branch off the integration branch (staging/dev/ equivalent).enterprise→ branch off the integration branch unless it is ahotfix/*, which branches offmain.gitflow→feature/*branches offdevelop;hotfix/*offmain;release/*offdevelop.sdet→test/{KEY}-*ticket branches + Plus Branches (docs/*/chore/*/fix/*) branch off the ephemeral integration trunktest/<module>-suite; the trunk itself is cut frommainon demand when a suite begins. Never stack a ticket on the previous ticket branch. Seereferences/sdet-integration-trunk.md.
Always propose the name and ask for OK before git checkout -b. Never create silently.
3.2 Commits
Group changes by responsibility, not by file type:
| Group | Typical paths |
|---|---|
| Test code | tests/, tests/components/, tests/e2e/, tests/integration/ |
| API schemas | api/schemas/, codegen output, OpenAPI types |
| Test data | tests/data/ |
| Skills/Docs | .agents/skills/, .agents/, AGENTS.md, docs/, README.md |
| Config | package.json, tsconfig.json, playwright.config.ts, lint/format configs |
Test data and fixtures stay with the tests they support. If a test commit ships its own fixture, they belong in the same commit, not in a separate chore: commit.
Conventional commit format:
- With issue key:
{type}({ISSUE-KEY}): {description}(e.g.test(UPEX-123): cover bulk-assign empty states). - Without key:
{type}: {description}. - Breaking changes: append
!after type/scope and addBREAKING CHANGE:footer.
Vocabulary: feat, fix, docs, style, refactor, perf, test, chore, build, ci, revert (full list in references/conventional-commits.md).
Hard rules (apply on every commit):
Shortened here. Read the whole file on GitHub.
Signals
- GitHub stars
- 22
- Forks
- 13
- Last commit
- Sep 2026
ahel review
K4binfo
destructive-scoped (in references/conflict-resolution.md)
Automated review, not a security audit. Ruleset v1+k2.
Advanced
- Catalog kind
- skill
- Gateway key
git-flow-master- Source
- github.com/upex-galaxy/agentic-qa-boilerplate