Branches and pull requests
How SpecsGraph names proposal branches, opens pull requests or commits directly, writes commit messages, handles conflicts and works with branch protection.
One branch per proposal
Every proposal has a branch under spec/, named from its title, such as spec/checkout-reserve for "Checkout reserves stock before payment". The name shows on the proposal while it is still open, and you can shorten it before approval. If the name is taken, SpecsGraph adds a number.
Nothing is pushed to GitHub before a person approves. On approval, SpecsGraph creates the branch from the tip of the base branch, commits the change inside the spec folder and, by default, opens a pull request. Each branch holds one proposal, so each pull request can be reviewed and merged on its own.
Warning
Leave spec/ branches to SpecsGraph
SpecsGraph may rewrite a proposal branch when it rebases it, so commits pushed there by hand can be lost. Put code changes on your own branch and link the spec pull request from it.
Publish mode
Each project has a Publish mode setting that decides how approved changes reach the base branch. An Admin or Owner changes it in the project settings.
Direct commit fails on a protected base branch. The proposal then stays Approved with the error from GitHub, and you can switch the project back to Pull request and choose Retry publish.
What the pull request contains
The pull request is titled after the proposal. Its description lists the nodes it changes, grouped by context, and links back to the proposal in SpecsGraph with its review threads and approver. It changes files inside the spec folder only; for spec/checkout-reserve that is three requirement files, the decision file, the WS-3 workstream file, README.md and graph.json.
Commit message format
Each publish is one commit, authored by your GitHub App's bot account, such as specsgraph-northwind[bot]. The subject starts with spec: and the proposal title. The body lists what changed, and trailers name the proposal and the approver. The person whose token an agent used appears as a co-author, so GitHub credits them.
spec: Checkout reserves stock before payment
Orders
+ ORD-12 Reserve stock for every line item at checkout
+ ORD-13 Release reservations after 15 minutes idle
Billing
+ BIL-04 Capture payment only once stock is reserved
Decisions
+ 0007 Reserve stock before payment
Workstreams
~ WS-3 Reserve stock at checkout
Spec-Proposal: spec/checkout-reserve
Spec-Approved-By: Kofi <kofi@northwind.example>
Co-authored-by: Ana <ana@northwind.example>Lines start with + for an added node, ~ for a changed one and - for a retired one. Search for spec commits with git log --grep "Spec-Proposal:".
After the pull request
A proposal stays Approved while its pull request is open, and the pull request follows your repository's rules. Merging it marks the proposal Published, and from that moment the graph shows the change as the current revision, as described in How the spec workflow works.
- Merged. The proposal becomes Published and shows the merge commit. Squash, merge commit and rebase merges all work. With a squash merge the base branch keeps one commit per proposal.
- Closed without merging. The proposal stays Approved and shows a warning; the base branch and the current revision are unchanged. Reopen the pull request, or choose Retry publish to open a new one. To drop the change instead, an Editor or above withdraws the proposal.
- Branch cleanup. Delete merged spec branches as you would any other. GitHub's setting to delete head branches automatically works for them too.
Conflicts and rebasing
Spec branches only touch the spec folder, so they never conflict with code. They can conflict with each other, because every publish updates shared files such as the index and the graph data.
Two proposals are approved
spec/checkout-reserveand a Catalog proposal are both approved on the same morning. Both branches start from the same commit onmain, and both changeREADME.mdandgraph.json.One merges first
The Catalog pull request merges. GitHub sends a
pushevent formain.SpecsGraph rebases the other
SpecsGraph rebases
spec/checkout-reserveonto the newmain, writes the generated files again from the graph and updates the pull request. Nobody resolves the conflict by hand.
SpecsGraph stops instead of rebasing when a file it needs to write was changed on the base branch outside SpecsGraph. The proposal shows the files involved. Move the hand edit into a proposal, or revert it in Git, then choose Retry publish. The guard in Spec files in your repository keeps this from happening, and Troubleshooting lists other reasons a proposal stays Approved.
Branch protection and required checks
Spec pull requests follow the same rules as every other pull request. Required reviews and required status checks apply to them, and SpecsGraph does not bypass either.
- Required checks. Your CI runs on spec pull requests like any other. The App has no checks permission, so it adds no status checks of its own. Workflows that validate the spec folder are yours to add.
- Required reviews. SpecsGraph approval and GitHub review are separate. Some teams keep the GitHub review light, since the content was reviewed in SpecsGraph by an Editor or above. Others route spec changes to named reviewers with a code owners file.
- Up-to-date branches. If you require branches to be current with the base branch, the rebase described above keeps spec pull requests mergeable.
- Rulesets that restrict branch names. Allow
spec/*for the App, or proposal branches cannot be created.
# Every spec change goes to the architecture group
/specsgraph/ @northwind/architecture
# Orders spec changes go to the Checkout team as well
/specsgraph/contexts/orders/ @northwind/architecture @northwind/checkoutGitHub asks the owners of each changed file for a review, and with code owner review required in branch protection, one of them must approve. The last matching pattern wins, which is why the Orders line repeats the architecture group.
Next steps
- Connect GitHub: the App, its permissions and project settings.
- Proposals and reviews: the review that happens before any branch exists.
- History and versions: read spec commits and roll back a change.