Skip to content

Commit

Docs: the Rules guide, and rulesets wherever branch protection was

- guides/rules.md: what a ruleset has, patterns, creating one, the rules that hold for a branch, who may bypass and how, every rule with its parameters and examples (the agent-first ones too), evaluate mode, Insights, where rules are checked with a refused push as git shows it, how branch protection became the "Default branch protection" ruleset, and the REST routes and MCP actions with an example. - Pull requests, other branches, git, CODEOWNERS, the merge queue, projects, actions and working with g1t point at rulesets; the MCP reference lists the new actions; llms.txt tells agents that rules hold for them as for people and where to read what is unmet. - The docs home links the guide.

syntaqxcommitted Parentfa14579Browse files
14 files+505−770/14 viewed
+1−0
128128 { label: 'Labels', slug: 'guides/labels' },
129129 { label: 'Milestones', slug: 'guides/milestones' },
130130 { label: 'The merge queue', slug: 'guides/merge-queue' },
131+ { label: 'Rules', slug: 'guides/rules' },
131132 { label: 'CODEOWNERS', slug: 'guides/codeowners' },
132133 { label: 'Sessions and why-blame', slug: 'guides/why-blame' },
133134 { label: 'Forks and branches', slug: 'concepts/forks' },
+3−3
209209 a workflow with `name: CI` reports `CI`, with the status context
210210 `CI / pull_request` (the workflow's name and the event).
211211
212−- **Which checks a merge needs** is up to the default branch's
213− [required status checks](/guides/pull-requests/#required-status-checks),
214− under **Settings → Branches and merging**. A required check that failed,
212+- **Which checks a merge needs** is up to the [rules](/guides/rules/) of the branch it merges into,
213+ their [required status checks](/guides/pull-requests/#required-status-checks),
214+ under **Settings → Rules**. A required check that failed,
215215 is still running or has not reported holds the merge. Checks that are not
216216 required are shown on the pull request and never hold it.
217217 - **In a repository that merges through the [merge queue](/guides/merge-queue/)**,
+10−8
3333
3434 ## What holds in another branch
3535
36+A pull request is held to the [rules](/guides/rules/) of the branch it
37+merges into: every ruleset, the repository's and its workspace's, whose
38+patterns cover that branch. A ruleset that targets `release/*` holds for
39+pull requests into `release/1.x` just as one that targets
40+`~DEFAULT_BRANCH` holds for those into the default branch.
41+
3642 | | Into the default branch | Into another branch |
3743 | --- | --- | --- |
38−| [Required status checks](/guides/pull-requests/#required-status-checks) | Must pass | Not required |
39−| Required approvals | As the repository asks | Not required |
40−| Must be up to date | As the repository asks | No |
41−| [Merge queue](/guides/merge-queue/) | Joins it, when it is on | Never; it merges directly |
44+| Required checks, approvals, being up to date | As the rules covering it ask | As the rules covering it ask; nothing when none cover it |
45+| [Merge queue](/guides/merge-queue/) | Joins it, when a rule requires it | Never; it merges directly |
4246 | Catching up | Merges the default branch in | Merges its base in |
4347 | Its issue | Closes when it merges | Stays open |
4448
45−The repository's protection settings guard the default branch, so they do
46−not hold for a pull request into another branch. Merging still needs the
47−Write role, and the default branch takes the work only through a pull
48−request into it, which is held to everything above.
49+Merging still needs the Write role. Under **Settings → Rules**, **What holds
50+for a branch** shows every rule that covers a branch.
4951
5052 ## g1t's agent and other branches
5153
+3−2
241241 ## Require review from code owners
242242
243243 Someone with the Maintain role or higher turns it on under the
244−repository's **Settings → Branches and merging**, in **Branch protection**:
245−**Require review from code owners**. It is off by default.
244+repository's **Settings → Rules**, in a ruleset's **Require a pull request before merging** rule:
245+**Require review from code owners**. It is off by default. From the API it
246+is the `pull_request` rule's `require_code_owner_review` (see [rules](/guides/rules/)).
246247
247248 With it on, a pull request merges only when every rule that owns a changed
248249 file has the approvals its section asks for, from its owners, and no code
+15−10
9191
9292 ## Protected branches
9393
94−A repository can protect its default branch under **Settings → Branches and
95−merging**. Pushing to it is then refused for everyone, whatever their role, and for agents, and
96−git says why:
94+A repository protects its branches and tags with [rulesets](/guides/rules/),
95+under **Settings → Rules**. A push that breaks a rule is refused for
96+everyone, whatever their role, and for agents, unless a ruleset lists them
97+as able to bypass it. Git prints which ruleset and rule refused it, and how
98+to fix it:
9799
98100 ```text
99− ! [remote rejected] main -> main (main is protected: push a branch and open a pull request)
101+remote: error: rules for refs/heads/main declined this push:
102+remote: - Changes to main must be made through a pull request. [ruleset "Protect main", pull_request]
103+remote: Push a branch, open a pull request into main, and merge it.
104+ ! [remote rejected] main -> main (declined by ruleset "Protect main" (pull_request))
100105 ```
101106
102−Changes reach a protected branch only by merging a pull request. The first
103−push to an empty repository is still allowed.
104−
105−The same page sets what a merge needs: the
106−[required status checks](/guides/pull-requests/#required-status-checks)
107−and approvals.
107+With **Require a pull request before merging**, changes reach a branch only
108+by merging a pull request. Creating the branch, such as the first push to
109+an empty repository, is still allowed. Rulesets also block force pushes and
110+deletions, restrict who creates branches and tags, check commit messages,
111+signatures and the files a push changes, and set what a merge needs. See
112+[rules](/guides/rules/).
108113
109114 ## Branches
110115
+11−7
1717
1818 ## Turn it on
1919
20−1. Open the project's **Settings → Branches and merging**. You need the Maintain
20+1. Open the project's **Settings → Rules**. You need the Maintain
2121 [role](/guides/access-and-roles/) or higher on its repository.
22−2. Turn on **Merge through a queue**.
23−3. Save.
24−4. Add `merge_group` to the `on:` of every workflow behind a
22+2. Open the ruleset that covers the default branch, or create one.
23+3. Choose **Add a rule**, then **Require the merge queue**. Set how many
24+ pull requests it tests at once, the smallest batch it starts with and
25+ how long it waits for one, and how long a batch's checks may take.
26+4. Save.
27+5. Add `merge_group` to the `on:` of every workflow behind a
2528 [required status check](/guides/pull-requests/#required-status-checks),
2629 so that it runs on the queue's states too
2730 ([below](#what-each-state-is-held-to)).
2831
2932 From the API, send `merge_queue` to `PATCH /repos/{owner}/{name}/settings`
30−(or `update_repo_settings`):
33+(or `update_repo_settings`), which adds the rule to the "Default branch
34+protection" [ruleset](/guides/rules/):
3135
3236 ```sh
3337 curl -X PATCH https://api.g1t.sh/repos/acme/web/settings \
5660
5761 ## How entries are tested
5862
59−g1t takes up to four entries from the front of the queue and tests them all
63+g1t takes up to four entries (the rule's `max_entries_to_build`) from the front of the queue and tests them all
6064 at once, speculatively, each in its own sandbox. Each sandbox builds `main`
6165 with that entry and every entry ahead of it merged in, in queue order:
6266
6973
7074 If every entry passes, the four can land one after another without being
7175 tested again. The next batch starts when nothing is being tested. A batch
72−that takes longer than 45 minutes is tested again.
76+that takes longer than 45 minutes (`check_response_timeout_minutes`) is tested again.
7377
7478 ### What each state is held to
7579
+3−2
166166 | **Guardrails** | What agents may reach, run and spend while they work here. See [guardrails](/guides/guardrails/). |
167167 | **Repository** | The repository's name, description, website, [topics](/guides/search/#what-is-indexed) and default branch, and its danger zone: visibility, archive, transfer and delete. See [Managing a repository](/guides/managing-repositories/). |
168168 | **Access** | Who has a [role](/guides/access-and-roles/) on the repository, and invitations. |
169−| **Branches and merging** | Branch protection, [required status checks](/guides/pull-requests/#required-status-checks), required approvals, the merge queue, auto-merge and how g1t's agents review. |
169+| **Branches and merging** | Auto-merge, how g1t's agents review and revise, the CODEOWNERS file's errors, and what the rules hold for the default branch. |
170+| **Rules** | [Rulesets](/guides/rules/): branch and tag protection, [required status checks](/guides/pull-requests/#required-status-checks), approvals, the merge queue, and rules for agents' changes, with Insights. |
170171 | **Secrets and variables** | The project's rows. See [Secrets and variables](/guides/secrets-and-variables/). |
171172 | **Runners** | The project's own [self-hosted runners](/guides/self-hosted-runners/), and where its agents' work runs. |
172173 | **Webhooks** | The repository's [webhooks](/guides/webhooks/). |
181182 | Tab | Needs |
182183 | --- | --- |
183184 | **General**, **Dependencies**, **Agents**, and on **Repository** its description, website and topics | Maintain |
184−| **Branches and merging**, **Guardrails** | Maintain |
185+| **Branches and merging**, **Rules**, **Guardrails** | Maintain |
185186 | **Access**: seeing who has a role; changing it | Write; Admin |
186187 | **Deployments**, **Domains**, **Secrets and variables**, **Runners**, **Webhooks** | Admin |
187188 | On **Repository**: its name, default branch, and the danger zone (visibility, archive) | Admin |
+28−25
6161
6262 ## Required status checks
6363
64−Rules for merging belong to the default branch, and hold for every pull
65−request into it; a pull request into another branch is not held to them
66−(see [pull requests into other branches](/guides/base-branches/)).
67−Someone with the Maintain [role](/guides/access-and-roles/)
68−or higher sets them under the repository's **Settings → Branches and
69−merging**, in **Branch protection**:
64+What a pull request needs before it merges is set by the
65+[rulesets](/guides/rules/) that cover the branch it merges into, the
66+repository's and its workspace's. They hold for every pull request into
67+that branch, a person's or an agent's. Someone with the Maintain
68+[role](/guides/access-and-roles/) or higher sets them under the
69+repository's **Settings → Rules**:
7070
71−| Setting | Default | What it does |
72−| --- | --- | --- |
73−| Require a pull request to change the default branch | Off | Refuses pushes to the default branch; changes reach it only by merging. See [protected branches](/guides/git/#protected-branches). |
74−| Required status checks | None | The checks that must pass on a pull request's head before it merges. |
75−| Required approvals | None | How many reviewers must approve before a merge, 0 to 3 on the page (up to 6 from the API). A reviewer who asked for changes blocks it. |
76−| g1t's approval counts | On | Off means approvals have to come from people. |
77−| Require review from code owners | Off | On means the owners of every file a pull request changes, as its [CODEOWNERS file](/guides/codeowners/) says, must approve before it merges. See [require review from code owners](/guides/codeowners/#require-review-from-code-owners). |
78−| Require branches to be up to date before merging | Off | On means a pull request behind the default branch has to catch up, and its checks run again, before it merges. |
79−| Merge through a queue | Off | See [merge queue](/guides/merge-queue/). |
80−| Allow bypassing required checks | On | Lets someone who may merge tick **bypass** when merging, to merge without the required checks passing. Off means nobody can. |
71+| Rule | What it does |
72+| --- | --- |
73+| Require a pull request before merging | Refuses pushes to the branch, so changes reach it only by merging. Sets the approvals a merge needs, whether an agent's approval counts, whether approvals before the latest push count, and whether [code owners](/guides/codeowners/#require-review-from-code-owners) must approve. |
74+| Require status checks to pass | The checks that must pass on a pull request's head before it merges, whether it must be up to date with the branch first, whether someone who may merge can bypass the checks, and optionally only when some paths change. |
75+| Require the merge queue | See [merge queue](/guides/merge-queue/). |
76+| Require deployments to succeed | A pull request's head must have deployed to these environments. |
8177
78+[Rules](/guides/rules/#rules) lists every rule, including those for
79+agents' changes, confidence, cost, sensitive paths and merge windows.
80+The merge box on a pull request lists each rule it does not meet yet, with
81+the ruleset it comes from and what to do about it.
82+
8283 ### Choosing the checks
8384
84−**Required status checks** offers the check names reported on the
85−repository's commits in the last 30 days, each with the events it was seen
86−for, such as `pull_request` and `merge_group`. Pick from the list, or type a
87−name that has not reported yet. A repository can require at most 20.
85+**Require status checks to pass** offers the check names reported on the
86+repository's commits in the last 30 days. Pick from them, or type a name
87+that has not reported yet. A check can be pinned to the integration that
88+must report it, such as workflows or deployments.
8889
8990 A required check is met by a status of that name on the pull request's head,
9091 whatever event reported it:
9293 | What reported it | What the merge does |
9394 | --- | --- |
9495 | A status that failed | Refused: "The required check CI failed." |
95−| A status still pending | Held: "The required check CI is still running." |
96−| Nothing yet | Held: "The required check CI has not reported on this commit yet." |
96+| A status still pending | Held: "The required check CI has not finished." |
97+| Nothing yet | Held: "The required check CI has not reported on its latest commit." |
9798 | Success | Allowed |
9899
99100 The same rule holds wherever a pull request merges: the merge button,
100101 [`merge_pull_request`](/reference/api/pull-requests/merge-pull-request/),
101102 a g1t agent's [automatic merge](/guides/working-with-g1t/#merging-automatically)
102−and the [merge queue](/guides/merge-queue/). With **Allow bypassing required
103−checks** on, the merge button has a **bypass** box, and the API takes
103+and the [merge queue](/guides/merge-queue/). Where the rule lets a merger bypass the
104+required checks, the merge button has a **bypass** box, and the API takes
104105 `ignore_checks: true`.
105106
106107 A check that only exists once a workflow has run, such as `CI` from a
131132 `merge_queue`, `allow_ignoring_checks` and `require_code_owner_review`;
132133 [`get_repo_settings`](/reference/api/repositories/get-repo-settings/)
133134 returns them. On the MCP server they are the `repository` tool's
134−`check_names`, `get_settings` and `update_settings` actions.
135+`check_names`, `get_settings` and `update_settings` actions. They read and
136+write the "Default branch protection" ruleset; [rulesets](/guides/rules/#from-the-api)
137+have routes of their own.
135138
136139 ## Reviewers
137140
+389−0
1+---
2+title: Rules
3+description: Rulesets decide what may happen to a repository's branches and tags, and what a pull request needs before it merges, for people and agents alike.
4+---
5+
6+A **ruleset** says what may happen to some of a repository's branches or
7+tags, and what a pull request into them needs before it merges. Every push,
8+every merge, and every branch renamed or commit made through g1t is checked
9+against the rulesets that cover it. Agents, g1t's own included, follow the
10+same rules as people. Only people, teams, tokens or g1t that a ruleset
11+lists as able to bypass it are let through.
12+
13+A ruleset belongs to a repository, or to a workspace. A workspace's ruleset
14+holds in every repository it selects. When several rulesets cover a branch,
15+all of their rules hold, so the strictest one wins.
16+
17+## What a ruleset has
18+
19+| Part | What it is |
20+| --- | --- |
21+| Name | What people call it, up to 100 characters. |
22+| Enforcement | `active`: its rules hold. `evaluate`: nothing is refused, and every push or merge it would have refused is recorded (see [Insights](#insights)). `disabled`: kept, but not checked. |
23+| Target | `branch` or `tag`. |
24+| Branches or tags | `include` and `exclude` patterns. A name is covered when it matches an include pattern and no exclude pattern. |
25+| Repositories | A workspace's ruleset only: which of its repositories it holds in. |
26+| Bypass list | Who these rules do not hold for. Nobody is on it unless listed. |
27+| Rules | What holds, each with its parameters, and whose changes it holds for. |
28+
29+### Patterns
30+
31+Branch, tag and repository names are matched with fnmatch patterns:
32+
33+| Pattern | Matches |
34+| --- | --- |
35+| `~DEFAULT_BRANCH` | The repository's default branch, whatever it is called now. |
36+| `~ALL` | Every branch, tag or repository. |
37+| `release/*` | `release/1.x`, but not `release/1.x/hotfix`: `*` stays within one segment. |
38+| `release/**` | Everything under `release/`. |
39+| `v[0-9]*` | `v1`, `v2.0.1`. `[...]` matches one character of a set; `[!...]` one not in it. |
40+
41+A pattern written as a full ref, such as `refs/heads/main`, works too. An
42+empty include list covers nothing.
43+
44+File path patterns in rules work the same way, with one addition: a
45+pattern without a `/`, such as `*.exe` or `CODEOWNERS`, matches a file of
46+that name in any directory. A pattern ending in `/` matches everything
47+under it.
48+
49+### Repositories a workspace ruleset holds in
50+
51+| Condition | What it does |
52+| --- | --- |
53+| `include`, `exclude` | Repository name patterns, ignoring case. `~ALL` is every repository. |
54+| `visibility` | `any`, `public` or `private`. |
55+| `topics` | Only repositories with at least one of these [topics](/guides/managing-repositories/). Empty means any. |
56+
57+## Create a ruleset
58+
59+You need the Maintain [role](/guides/access-and-roles/) or higher for a
60+repository's ruleset. For a workspace's, you need to be an owner.
61+
62+1. Open the repository's **Settings → Rules**, or the workspace's
63+ **Settings → Rules**.
64+2. Choose **New ruleset**.
65+3. Name it, choose **Branches** or **Tags**, and set which names it covers.
66+ **Default branch** and **All branches** are a click away.
67+4. Choose its enforcement. To try it without refusing anything, choose
68+ **Evaluate** and watch Insights.
69+5. Add people, teams, roles, tokens or g1t who may bypass it, if anyone.
70+6. Choose **Add a rule** for each rule. Set its parameters, and whether it
71+ holds for **Everyone**, **Agents' changes** or **People's changes**.
72+7. Choose **Create ruleset**.
73+
74+**Export JSON** downloads a ruleset. **Import JSON** fills the form from a
75+ruleset file, so one ruleset can be copied to other repositories or
76+workspaces. The file is the ruleset as the [API](#from-the-api) shows it.
77+
78+## The rules that hold for a branch
79+
80+Under **Settings → Rules**, **What holds for a branch** lists every rule of
81+every ruleset that covers a branch, the repository's and its workspace's,
82+active ones first. For each ruleset it also shows who may bypass it. To see
83+a tag's rules, put `?tag=v1.0` in the address.
84+
85+The **Rules** box on a pull request lists each rule of its base branch it
86+does not meet yet. For each one it shows which ruleset it comes from and
87+what to do about it.
88+
89+## Who may bypass
90+
91+| Kind | `value` | Who |
92+| --- | --- | --- |
93+| `role` | `write`, `maintain`, `admin` (that role or higher), or `owner` | People with that role on the repository, or the workspace's owners. |
94+| `team` | `team` or `workspace/team` | The team's people, child teams included. |
95+| `user` | A username | One person. |
96+| `token` | A token's id, or `workspace` | That access token, or any of the workspace's own tokens. |
97+| `g1t` | None | g1t's agents, and g1t acting on its own, such as the merge queue and security updates. |
98+
99+Each entry has a `mode`:
100+
101+- `always`: pushes and merges both go through.
102+- `pull_requests`: only merges go through. Their pushes follow the rules.
103+
104+An agent never gets its person's role. An agent acting for an admin still
105+follows a ruleset that lets admins bypass it. Only a `g1t` or `token` entry
106+lets an agent through.
107+
108+When a person who may bypass merges a pull request that does not meet the
109+rules, the merge box offers **Bypass the rules**. Through the API, pass
110+`bypass_rules`. A push from someone on the bypass list goes through by
111+itself, since git has no box to tick. Every bypass is recorded in
112+[Insights](#insights).
113+
114+## Rules
115+
116+Each rule has a `type` and `parameters`. A parameter you leave out takes its
117+default. `applies_to` is `everyone` (the default), `agents` or `people`.
118+
119+A change counts as an agent's when it is pushed with an agent's token, or
120+when its pull request was made by g1t or opened with an agent label through
121+the API or MCP. A pull request a person opens on the site is a person's.
122+
123+### Branches and tags
124+
125+| Rule | `type` | What it does | Parameters |
126+| --- | --- | --- | --- |
127+| Restrict creations | `creation` | Only people on the bypass list create matching branches or tags. | None |
128+| Restrict updates | `update` | Only people on the bypass list push to matching branches or tags. This covers merges too. | None |
129+| Restrict deletions | `deletion` | Only people on the bypass list delete them. | None |
130+| Block force pushes | `non_fast_forward` | A push must add to the branch's history, never rewrite it. | None |
131+| Branch name pattern | `branch_name_pattern` | New branches must be named as it says. | [Pattern](#pattern-rules) |
132+| Tag name pattern | `tag_name_pattern` | New tags must be named as it says. | [Pattern](#pattern-rules) |
133+
134+### Pull requests and checks
135+
136+| Rule | `type` | What it does |
137+| --- | --- | --- |
138+| Require a pull request before merging | `pull_request` | Pushes straight to the branch are refused. A pull request into it needs what the parameters say. |
139+| Require status checks to pass | `required_status_checks` | These checks must pass on a pull request's head before it merges. |
140+| Require the merge queue | `merge_queue` | Merging into the default branch adds the pull request to the [merge queue](/guides/merge-queue/), with these settings. On other branches it merges directly. |
141+| Require deployments to succeed | `required_deployments` | A pull request's head must have deployed successfully to these environments. |
142+
143+`pull_request` parameters:
144+
145+| Parameter | Default | What it does |
146+| --- | --- | --- |
147+| `required_approvals` | `0` | Approving reviews needed, 0 to 10. A reviewer who has since asked for changes blocks the merge. Nobody approves their own pull request, or one g1t made for them. |
148+| `count_agent_approvals` | `true` | Whether an agent's approval counts toward `required_approvals`. |
149+| `dismiss_stale_reviews_on_push` | `false` | Approvals given before the latest push no longer count. |
150+| `require_code_owner_review` | `false` | The [code owners](/guides/codeowners/) of every file it changes must approve. |
151+| `require_last_push_approval` | `false` | Someone other than whoever pushed last must approve after that push. |
152+| `allowed_merge_methods` | All | `merge`, `squash` or `rebase`. g1t merges by landing the branch as it is, which counts as `merge`. Squash and rebase merging are planned. |
153+| `allow_direct_pushes` | `false` | Pull requests need what this rule says, but pushes straight to the branch are still allowed. Only the ruleset made from branch protection that did not require pull requests has this on. |
154+
155+`required_status_checks` parameters:
156+
157+| Parameter | Default | What it does |
158+| --- | --- | --- |
159+| `checks` | None | Each check has a `context`, such as `CI` (a workflow's name) or `g1t / deploy`, and an optional `integration`: `actions`, `deployments`, `security` or `g1t`. A check with an `integration` counts only when that integration reported it, so a workflow cannot stand in for a deployment. |
160+| `strict` | `false` | The pull request must contain the branch's latest commits, so what merges is exactly what was checked. |
161+| `paths` | Always | The checks are required only when the pull request changes a file matching one of these patterns. |
162+| `allow_bypass_on_merge` | `false` | Someone who may merge can merge past checks that have not passed by ticking **Bypass the required checks**. |
163+
164+`merge_queue` parameters: `max_entries_to_build` (pull requests tested at
165+once, 1 to 20, default 4), `min_entries_to_merge` and
166+`min_entries_wait_minutes` (the smallest batch to start, and how long the
167+oldest entry waits for it to fill; default 1 and 0),
168+`check_response_timeout_minutes` (how long a batch's checks may take before
169+it is tested again, 5 to 360, default 45) and `merge_method`. When several
170+rulesets set a queue, the queue uses the smallest batch size and timeout
171+and the longest wait among them.
172+
173+`required_deployments` takes `environments`. `preview` is a pull request's
174+[preview deployment](/guides/deployments/). A project's slug is that
175+project's deployment, when a repository has several.
176+
177+### Commits
178+
179+| Rule | `type` | What it does |
180+| --- | --- | --- |
181+| Require linear history | `required_linear_history` | No merge commits. Rebase instead of merging the branch in. |
182+| Require signed commits | `required_signatures` | Every commit carries a signature g1t verifies. |
183+| Commit message pattern | `commit_message_pattern` | Every commit message must match, or must not. |
184+| Commit author email pattern | `commit_author_email_pattern` | Every author address must match, or must not. |
185+| Committer email pattern | `committer_email_pattern` | Every committer address must match, or must not. |
186+
187+These hold for the commits a push adds and for the commits a pull request
188+would land when it merges.
189+
190+**Signed commits.** g1t verifies SSH signatures made with an ed25519 key:
191+
192+```sh
193+git config gpg.format ssh
194+git config user.signingkey ~/.ssh/id_ed25519.pub
195+git commit -S -m "Add rules"
196+```
197+
198+A signature counts as verified when it is valid over the commit and the key
199+is one of the [SSH keys](/guides/authentication/) on the g1t account that
200+owns the committer's verified email address. GPG signatures, and SSH
201+signatures made with RSA or ECDSA keys, are reported as not verified yet.
202+Commits g1t makes itself, such as catching a pull request up and web edits,
203+are not signed. So with this rule on a branch, bring pull requests up to
204+date with a signed rebase of your own.
205+
206+### Pattern rules
207+
208+| Parameter | What it does |
209+| --- | --- |
210+| `operator` | `starts_with`, `ends_with`, `contains` or `regex`. |
211+| `pattern` | The text, or the regular expression. |
212+| `negate` | The text must not match. |
213+| `name` | What the rule is called in refusals, such as `Conventional commits`. |
214+
215+Regular expressions run on a linear-time engine. A pattern can never make a
216+push slow, and look-around and back-references are not supported. For
217+example, conventional commits:
218+
219+```json
220+{ "type": "commit_message_pattern", "parameters": { "name": "Conventional commits", "operator": "regex", "pattern": "^(feat|fix|docs|chore)(\\(.+\\))?: " } }
221+```
222+
223+### Files
224+
225+| Rule | `type` | What it does | Parameters |
226+| --- | --- | --- | --- |
227+| Restrict file paths | `file_path_restriction` | Changes to matching paths are refused, deletions included. | `restricted_file_paths` |
228+| Restrict file extensions | `file_extension_restriction` | Files with these extensions may not be added or changed. | `restricted_file_extensions`, such as `.exe` |
229+| Restrict file size | `max_file_size` | No file larger than this. | `max_file_size_mb`, 1 to 100 |
230+| Restrict file path length | `max_file_path_length` | No path longer than this. | `max_file_path_length` |
231+| Restrict files changed | `max_files_changed` | A commit may change at most this many files. | `max_files` |
232+| Block pushes that add secrets | `secret_scanning` | Every push to the branch is scanned by [push protection](/guides/security/secret-protection/). A push too large to scan is refused rather than let through unscanned. | None |
233+
234+### Agents, review and timing
235+
236+These rules exist for teams where agents write much of the code.
237+
238+| Rule | `type` | What it does | Parameters |
239+| --- | --- | --- | --- |
240+| Confidence threshold | `confidence_threshold` | An agent's change that g1t [rates](/guides/working-with-g1t/#how-sure-the-agent-is) below `minimum` needs approvals from people before it merges. A change not rated yet counts as below. | `minimum` (`low`, `medium`, `high`), `required_approvals` |
241+| Cost cap | `cost_cap` | Once agents have spent more than `max_usd` on a pull request, it does not merge, and its agent is not sent back to revise, until a person approves it. | `max_usd` |
242+| Review for sensitive paths | `path_review` | A pull request that changes a matching file needs approvals from people since its latest push, from `team` when one is named. | `paths`, `required_approvals`, `team` |
243+| Merge window | `merge_window` | When pull requests may merge into the branch. | See below |
244+| Agent auto-merge | `agent_auto_merge` | Whether g1t lands an agent's ready pull request into the branch without a person, and how sure g1t must be first. The repository's **Merge automatically when ready** setting must be on too. | `allowed`, `minimum_confidence` |
245+
246+Rules that hold only for agents' changes cover the rest of what an
247+agent-first team needs. For example:
248+
249+- Agents' pull requests need one approval from a person: `pull_request`
250+ with `required_approvals` `1`, `count_agent_approvals` `false`, and
251+ `applies_to` `agents`.
252+- Agents may not change workflows or code owners: `file_path_restriction`
253+ with `.g1t/workflows/**` and `CODEOWNERS`, and `applies_to` `agents`.
254+
255+`merge_window` parameters:
256+
257+| Parameter | What it does |
258+| --- | --- |
259+| `time_zone` | A fixed offset from UTC, such as `+02:00` or `-05:00`, or `UTC`. Daylight saving time is not applied. |
260+| `windows` | Weekly hours when merging is open: each has `days` (`mon` to `sun`), `start` and `end` as `HH:MM`. An `end` before its `start` runs past midnight. With none, merging is open whenever no freeze covers the moment. |
261+| `freezes` | Periods when merging waits, each with `start`, `end` (RFC 3339) and a `reason`. A freeze without an `end` lasts until you remove it. Use one during an incident. **Freeze now, until lifted** adds one. |
262+| `exceptions` | Periods when merging is open whatever the windows and freezes say, such as a hotfix. |
263+
264+A refusal outside the window says when it next opens.
265+
266+## Evaluate mode
267+
268+A ruleset in `evaluate` refuses nothing. Every push and merge it would have
269+refused is recorded as **Would block** in Insights. On a pull request, the
270+merge box lists what it would refuse under **Rulesets in evaluate would
271+refuse it**. Turn a ruleset to **Active** once Insights shows it refusing
272+only what it should.
273+
274+## Insights
275+
276+**Settings → Rules → Insights** lists how the rules judged each push, merge,
277+branch creation, deletion, rename and commit made on the site, newest first.
278+Each entry shows the ruleset, the ref, who made the change, whether they are
279+a person or an agent, and every rule broken with the reason. Totals cover
280+the last 30 days: **Passed**, **Blocked** (refused by an active ruleset),
281+**Would block** and **Bypassed**, with the rules broken most. A workspace's
282+Insights covers all of its repositories. Evaluations are kept for 90 days.
283+
284+Changing a ruleset is recorded in the workspace's
285+[audit log](/guides/audit-log/) and sent to webhooks as `ruleset.created`,
286+`ruleset.updated` or `ruleset.deleted`. A workspace's ruleset events go to
287+the workspace's webhooks.
288+
289+## Where rules are checked
290+
291+| Change | What happens |
292+| --- | --- |
293+| `git push` | The rules of every branch and tag the push changes are checked before anything is stored. A refused push changes nothing, and git prints why. |
294+| Merging a pull request | The merge button, the API, MCP, auto-merge, g1t's own merges and the merge queue all check the same rules. |
295+| Renaming a branch | Covered as deleting the old name and creating the new one. |
296+| A file committed on the site | Covered as a push of that commit to its new branch. |
297+| Bringing a pull request up to date | Covered as a push of the merge commit to its branch. |
298+
299+A refused push looks like this:
300+
301+```text
302+remote:
303+remote: error: rules for refs/heads/main declined this push:
304+remote: - Changes to main must be made through a pull request. [ruleset "Protect main", pull_request]
305+remote: Push a branch, open a pull request into main, and merge it.
306+remote: See the rules that hold for it: https://g1t.sh/acme/web/settings/rules?branch=main
307+remote:
308+ ! [remote rejected] main -> main (declined by ruleset "Protect main" (pull_request))
309+```
310+
311+A pull request's fork, where g1t's agents work, has no rules of its own.
312+What it brings is checked against the base branch's rules when it merges.
313+
314+## Rulesets and branch protection
315+
316+Before rulesets, a repository had one set of protection settings for its
317+default branch. Each repository's settings became a ruleset named
318+**Default branch protection**, targeting `~DEFAULT_BRANCH` and holding
319+exactly what they held:
320+
321+| Setting | Becomes |
322+| --- | --- |
323+| Require a pull request to change the default branch | `pull_request` |
324+| Required approvals, g1t's approval counts, require review from code owners | `pull_request`'s `required_approvals`, `count_agent_approvals`, `require_code_owner_review` |
325+| Required status checks, require branches to be up to date, allow bypassing required checks | `required_status_checks`'s `checks`, `strict`, `allow_bypass_on_merge` |
326+| Merge through a queue | `merge_queue` |
327+
328+Where approvals or code owners were required but pushes were not refused,
329+the `pull_request` rule has `allow_direct_pushes` on, so pushes still go
330+through as before.
331+
332+Pull requests into other branches used to need nothing. Now they need what
333+the rulesets covering their base ask for. With only the migrated ruleset,
334+that is still nothing.
335+
336+[`update_repo_settings`](/reference/api/repositories/update-repo-settings/)
337+still takes the old fields and writes them to the **Default branch
338+protection** ruleset, creating it when needed. Rules only rulesets have
339+stay as they are. [`get_repo_settings`](/reference/api/repositories/get-repo-settings/)
340+returns the default branch's protection as all of its rulesets stack. The
341+`protected` field of [`update_repo`](/reference/api/repositories/update-repo/)
342+turns the ruleset's pull request requirement on or off.
343+
344+## From the API
345+
346+| Route | MCP | What it does |
347+| --- | --- | --- |
348+| `GET /repos/{owner}/{name}/rulesets` | `repository` `list_rulesets` | A repository's rulesets; `include_parents` adds the workspace's that hold in it. |
349+| `POST /repos/{owner}/{name}/rulesets` | `repository` `create_ruleset` | Create one. |
350+| `GET /repos/{owner}/{name}/rulesets/{id}` | `repository` `get_ruleset` | One ruleset. |
351+| `PUT /repos/{owner}/{name}/rulesets/{id}` | `repository` `update_ruleset` | Change one. Fields you leave out stay as they are. |
352+| `DELETE /repos/{owner}/{name}/rulesets/{id}` | `repository` `delete_ruleset` | Delete one. |
353+| `GET /repos/{owner}/{name}/rules/branches/{branch}` | `repository` `branch_rules` | Every rule that holds for a branch (`?target=tag` for a tag). Encode slashes: `release%2F1.x`. |
354+| `GET /repos/{owner}/{name}/rules/evaluations` | `repository` `rule_evaluations` | Evaluations and insights; `ruleset_id`, `verdict`, `problems_only`, `before`, `limit`. |
355+| `/workspaces/{workspace}/rulesets` and `/workspaces/{workspace}/rules/evaluations` | `workspace` `list_rulesets` and the rest | The same for a workspace. |
356+
357+The body of a create or update is the ruleset. Under a repository's
358+address, `name` already names the repository, so the ruleset's name is
359+`ruleset_name`. A file exported from the site, which says `name`, is read as
360+it is.
361+
362+```sh
363+curl -X POST https://api.g1t.sh/repos/acme/web/rulesets \
364+ -H "Authorization: Bearer $G1T_TOKEN" \
365+ -H "Content-Type: application/json" \
366+ -d '{
367+ "ruleset_name": "Protect main",
368+ "conditions": { "ref_name": { "include": ["~DEFAULT_BRANCH"] } },
369+ "bypass_actors": [{ "kind": "role", "value": "admin", "mode": "pull_requests" }],
370+ "rules": [
371+ { "type": "deletion" },
372+ { "type": "non_fast_forward" },
373+ { "type": "pull_request", "parameters": { "required_approvals": 1, "dismiss_stale_reviews_on_push": true } },
374+ { "type": "required_status_checks", "parameters": { "checks": [{ "context": "CI", "integration": "actions" }], "strict": true } },
375+ { "type": "pull_request", "parameters": { "required_approvals": 1, "count_agent_approvals": false }, "applies_to": "agents" },
376+ { "type": "file_path_restriction", "parameters": { "restricted_file_paths": [".g1t/workflows/**"] }, "applies_to": "agents" }
377+ ]
378+ }'
379+```
380+
381+Reading rulesets takes the `repo:read` or `workspace:read`
382+[scope](/guides/authentication/). Changing them takes `repo:admin` or
383+`workspace:admin`, since it changes what everyone, agents included, may do.
384+[`merge_pull_request`](/reference/api/pull-requests/merge-pull-request/)
385+takes `bypass_rules`. [`get_pull_request`](/reference/api/pull-requests/get-pull-request/)
386+returns `rules`: what is `unmet`, what you may bypass (`bypassable`),
387+and what rulesets in evaluate would refuse (`evaluate`).
388+
389+Every operation is in the [API reference](/reference/api/rules/list-repo-rulesets/).
+15−15
230230
231231 ### What a repository can ask for
232232
233−Under a project's **Settings → Branches and merging**, someone with the
234−Maintain [role](/guides/access-and-roles/) or higher sets the rules its pull
235−requests follow. **Branch protection** holds the rules for every pull
236−request, a person's or an agent's; they are described in
237−[required status checks](/guides/pull-requests/#required-status-checks):
233+A project's [rulesets](/guides/rules/), under **Settings → Rules**, set
234+what every pull request needs before it merges, a person's or an agent's:
235+required checks, approvals, being up to date, the merge queue and the rest.
236+Agents, g1t's included, follow them as people do. They are let through only
237+when a ruleset lists g1t, or their token, as able to bypass it. Some rules
238+are written for agents' changes:
238239
239−| Setting | Default | What it does |
240−| --- | --- | --- |
241−| Require a pull request to change the default branch | Off | Refuses pushes to the default branch. |
242−| Required status checks | None | The checks that must pass on a pull request's head before it merges. |
243−| Required approvals | None | How many reviewers must approve before a merge. A reviewer who asked for changes blocks it. |
244−| g1t's approval counts | On | Off means approvals have to come from people. |
245−| Require branches to be up to date before merging | Off | On means catching up is a step of its own and the checks run again. |
246−| Merge through a queue | Off | Merging tests a pull request together with those ahead of it; the default branch only moves to a combination that passed. See [merge queue](/guides/merge-queue/). |
247−| Allow bypassing required checks | On | Lets someone who may merge merge without the required checks passing. Off means nobody can. |
240+| Rule | What it does for an agent's change |
241+| --- | --- |
242+| A rule that holds for agents only | For example, one approval from a person, or no changes to `.g1t/workflows/**` and `CODEOWNERS`. A push that breaks it is refused, and git says which rule refused it. |
243+| Confidence threshold | A change g1t [rates](#how-sure-the-agent-is) below the minimum waits for people's approval. |
244+| Cost cap | Past the cap, the pull request neither merges nor goes back to its agent until a person approves it. It shows **Needs you**. |
245+| Agent auto-merge | Whether g1t merges the agent's change into this branch by itself, and at what confidence. |
246+| Merge window | Merges, g1t's included, wait outside the window and during a freeze. |
248247
249−In the **g1t** section, you set what g1t does with its own pull requests:
248+Under **Settings → Branches and merging**, in the **g1t** section, you set
249+what g1t does with its own pull requests:
250250
251251 | Setting | Default | What it does |
252252 | --- | --- | --- |
+5−0
111111 href="/guides/teams/"
112112 />
113113 <LinkCard
114+ title="Rules"
115+ description="Protect branches and tags with rulesets: pull requests, checks, signed commits, merge windows, and rules for agents' changes."
116+ href="/guides/rules/"
117+ />
118+ <LinkCard
114119 title="CODEOWNERS"
115120 description="Say who owns which paths, ask them to review the changes to their files, and require their approval before a merge."
116121 href="/guides/codeowners/"
+15−2
237237 | [`get`](/reference/api/repositories/get-repo/) | One repository's details. | `repo` | `repo:read` |
238238 | [`create`](/reference/api/repositories/create-repo/) | Create a repository in one of your workspaces, empty or as a copy of a public git repository (`import_url`). `workspace` may be left out if you belong to exactly one. | `name` | `repo:write` |
239239 | [`update`](/reference/api/repositories/update-repo/) | Change its `description`, `website`, `topics` and `default_branch`, whether its default branch is `protected`, and whether it is `private`. Maintain role; `private` and `default_branch` need Admin. | `repo` | `repo:write` |
240−| [`get_settings`](/reference/api/repositories/get-repo-settings/) | How it handles pull requests: the default branch's required checks, approvals, bypassing checks, being up to date, the merge queue, and how g1t's agents are reviewed, revised and merged. | `repo` | `repo:read` |
240+| [`get_settings`](/reference/api/repositories/get-repo-settings/) | How it handles pull requests: how g1t's agents are reviewed, revised and merged, and the default branch's required checks, approvals, bypassing checks, being up to date and merge queue as its [rulesets](/guides/rules/) stack. | `repo` | `repo:read` |
241241 | [`update_settings`](/reference/api/repositories/update-repo-settings/) | Change those settings, including `hold_low_confidence`, which holds g1t's [low-confidence](/guides/working-with-g1t/#how-sure-the-agent-is) change for a person. Only the fields given change; `required_checks` replaces the whole list. Maintain role. | `repo` | `repo:write` |
242242 | [`check_names`](/reference/api/repositories/list-check-names/) | The check names reported on its commits in the last 30 days, most recent first, each with `name`, `events` and `last_seen`: the names `required_checks` takes. | `repo` | `repo:read` |
243+| [`list_rulesets`](/reference/api/rules/list-repo-rulesets/) | Its [rulesets](/guides/rules/); `include_parents` adds the workspace's that hold in it. | `repo` | `repo:read` |
244+| [`get_ruleset`](/reference/api/rules/get-repo-ruleset/) | One ruleset by `id`. | `repo`, `id` | `repo:read` |
245+| [`create_ruleset`](/reference/api/rules/create-repo-ruleset/) | Create one: `ruleset_name`, `enforcement`, `target`, `conditions`, `bypass_actors`, `rules`. Maintain role. | `repo` | `repo:admin` |
246+| [`update_ruleset`](/reference/api/rules/update-repo-ruleset/) | Change one; fields left out stay. Maintain role. | `repo`, `id` | `repo:admin` |
247+| [`delete_ruleset`](/reference/api/rules/delete-repo-ruleset/) | Delete one. Maintain role. | `repo`, `id` | `repo:admin` |
248+| [`branch_rules`](/reference/api/rules/get-branch-rules/) | Every rule that holds for a `branch` (or, with `target` `tag`, a tag), with the ruleset each comes from. | `repo`, `branch` | `repo:read` |
249+| [`rule_evaluations`](/reference/api/rules/list-rule-evaluations/) | How its rules judged pushes and merges, newest first, with 30 days of insights. Write role. | `repo` | `repo:read` |
243250 | [`codeowners`](/reference/api/repositories/get-codeowners-errors/) | Its [CODEOWNERS file](/guides/codeowners/) checked as a linter would, on `ref` (the default branch unless you say): its `path`, `rules`, `sections`, and `errors`, each with `line`, `kind`, `token` and `message`. Read role. | `repo` | `repo:read` |
244251 | [`list_labels`](/reference/api/labels-and-milestones/list-labels/) | Its labels by name, each with `color`, `description`, and how many `issues` and `pulls` carry it. | `repo` | `repo:read` |
245252 | [`create_label`](/reference/api/labels-and-milestones/create-label/) | Create a label named `label`, with `color` (six hex digits; chosen from the name when left out) and `description`. Triage role. | `repo`, `label` | `issues:write` |
324331 | [`remove_requested_reviewers`](/reference/api/pull-requests/remove-requested-reviewers/) | Stop asking them. Reviews they gave stay. | `repo`, `number` | `pull_requests:write` |
325332 | [`review`](/reference/api/pull-requests/review-pull-request/) | `approve`, or `request_changes` with a `body`. Not on your own pull request, nor one g1t made for you. | `repo`, `number`, `verdict` | `pull_requests:write` |
326333 | [`close`](/reference/api/pull-requests/close-pull-request/) | Close it without merging. | `repo`, `number` | `pull_requests:write` |
327−| [`merge`](/reference/api/pull-requests/merge-pull-request/) | Land it on its [base](/guides/base-branches/), or add it to the [merge queue](/guides/merge-queue/), once every [required check](/guides/pull-requests/#required-status-checks) has passed on its head. Into the default branch, it resolves its issue. `ignore_checks` bypasses required checks where the repository allows it. Write role. | `repo`, `number` | `pull_requests:write` |
334+| [`merge`](/reference/api/pull-requests/merge-pull-request/) | Land it on its [base](/guides/base-branches/), or add it to the [merge queue](/guides/merge-queue/), once it meets every [rule](/guides/rules/) of its base, required checks included; `bypass_rules` merges past rules a ruleset lets you bypass. Into the default branch, it resolves its issue. `ignore_checks` bypasses required checks where the repository allows it. Write role. | `repo`, `number` | `pull_requests:write` |
328335 | [`merge_queue`](/reference/api/pull-requests/get-merge-queue/) | The pull requests waiting to land, in order, each with the state it is tested in and how that went; then those that recently landed or left. | `repo` | `pull_requests:read` |
329336
330337 `record_session` takes a list of `entries`, each with a `kind` (`prompt`,
548555 | [`pin_project`](/reference/api/pinned-projects/pin-project/) | Pin a project you can see, at `position` (0 first) or at the end; at most 8 a workspace. Returns your pins. | `workspace`, `project` | `account:write` |
549556 | [`unpin_project`](/reference/api/pinned-projects/unpin-project/) | Unpin it. Returns your pins. | `workspace`, `project` | `account:write` |
550557 | [`reorder_pinned_projects`](/reference/api/pinned-projects/reorder-pinned-projects/) | Put your pins in a new order: `projects` names each pinned project's slug once. | `workspace`, `projects` | `account:write` |
558+| [`list_rulesets`](/reference/api/rules/list-workspace-rulesets/) | The workspace's own [rulesets](/guides/rules/). Members only. | `workspace` | `workspace:read` |
559+| [`get_ruleset`](/reference/api/rules/get-workspace-ruleset/) | One of them by `id`. Members only. | `workspace`, `id` | `workspace:read` |
560+| [`create_ruleset`](/reference/api/rules/create-workspace-ruleset/) | Create one, with `conditions.repository` choosing its repositories. Owners only. | `workspace` | `workspace:admin` |
561+| [`update_ruleset`](/reference/api/rules/update-workspace-ruleset/) | Change one. Owners only. | `workspace`, `id` | `workspace:admin` |
562+| [`delete_ruleset`](/reference/api/rules/delete-workspace-ruleset/) | Delete one. Owners only. | `workspace`, `id` | `workspace:admin` |
563+| [`rule_evaluations`](/reference/api/rules/list-workspace-rule-evaluations/) | How rules judged changes across its repositories, with insights. Members only. | `workspace` | `workspace:read` |
551564
552565 ## `billing`
553566
+1−1
910910 about={
911911 <>
912912 Names it holds for: fnmatch patterns, <code>*</code> within a segment and <code>**</code> across them.
913− {repositoryLabel ? ` ${repositoryLabel}'s default branch is matched by name too.` : ""}
913+ {repositoryLabel ? ` Default branch follows ${repositoryLabel}'s default branch if it is renamed.` : ""}
914914 </>
915915 }
916916 >
+6−2
170170 syntax) run on every pull request's head, and each reports a check named
171171 after the workflow, such as `CI`. Before you push, run the same tests and
172172 linters those workflows run. `GET {repo}/pulls/{number}` returns
173− `statuses` and `required_checks`: each check the default branch
173+ `statuses`, `required_checks` and `rules`: each check the branch it merges into
174174 requires, as `success`, `failure`, `pending` or `expected` (not reported
175175 yet). If one failed, read why with `GET {repo}/actions/runs/{id}` and
176176 `GET {repo}/actions/jobs/{job}/logs`, push a fix, and the workflows run
177177 again. `GET {repo}/check-names` lists the check names seen in the last
178− 30 days; `required_checks` on `PATCH {repo}/settings` sets which ones a
178+ 30 days. `rules.unmet` lists every rule of that branch not met yet, with
179+ what to do; `GET {repo}/rules/branches/{branch}` lists every rule. Rules
180+ hold for agents exactly as for people: a push that breaks one is refused
181+ with the ruleset and rule named, so read the `remote:` lines and fix the
182+ commits. `required_checks` on `PATCH {repo}/settings` sets which ones a
179183 merge needs.
180184 - **Comment** on an issue or a pull request:
181185 `POST {repo}/issues/{number}/comments` with `body`. On a pull request, add