1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
|
---
stage: Create
group: Source Code
info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
type: reference, howto
---
# Push Rules **(STARTER)**
Gain additional control over what can and can't be pushed to your repository by using
regular expressions to reject pushes based on commit contents, branch names or file details.
## Overview
GitLab already offers [protected branches](../user/project/protected_branches.md), but there are
cases when you need some specific rules like preventing Git tag removal or
enforcing a special format for commit messages.
Push rules are essentially [pre-receive Git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) that are easy to
enable in a user-friendly interface. They are defined globally if you are an
admin or per project so you can have different rules applied to different
projects depending on your needs.
## Use cases
Every push rule could have its own use case, but let's consider some examples.
### Commit messages with a specific reference
Let's assume you have the following requirements for your workflow:
- every commit should reference a Jira issue, for example: `Refactored css. Fixes JIRA-123.`
- users should not be able to remove Git tags with `git push`
All you need to do is write a simple regular expression that requires the mention
of a Jira issue in the commit message, like `JIRA\-\d+`.
Now when a user tries to push a commit with a message `Bugfix`, their push will
be declined. Only pushing commits with messages like `Bugfix according to JIRA-123`
will be accepted.
### Restrict branch names
Let's assume there's a strict policy for branch names in your company, and
you want the branches to start with a certain name because you have different
GitLab CI/CD jobs (`feature`, `hotfix`, `docker`, `android`, etc.) that rely on the
branch name.
Your developers, however, don't always remember that policy, so they might push to
various branches, and CI pipelines might not work as expected. By restricting the
branch names globally in Push Rules, such mistakes are prevented.
Any branch name that doesn't match your push rule will get rejected.
Note that the name of your default branch is always allowed, regardless of the branch naming
regular expression (regex) specified. GitLab is configured this way
because merges typically have the default branch as their target.
If you have other target branches, include them in your regex. (See [Enabling push rules](#enabling-push-rules)).
The default branch also defaults to being a [protected branch](../user/project/protected_branches.md),
which already limits users from pushing directly.
#### Default restricted branch names
> Introduced in GitLab 12.10.
By default, GitLab restricts certain formats of branch names for security purposes.
Currently 40-character hexadecimal names, similar to Git commit hashes, are prohibited.
### Custom Push Rules **(CORE ONLY)**
It's possible to create custom push rules rather than the push rules available in
**Admin Area > Push Rules** by using more advanced server hooks.
See [server hooks](../administration/server_hooks.md) for more information.
## Enabling push rules
NOTE:
GitLab administrators can set push rules globally under
**Admin Area > Push Rules** that all new projects will inherit. You can later
override them in a project's settings. They can be also set on a [group level](../user/group/index.md#group-push-rules).
1. Navigate to your project's **Settings > Repository** and expand **Push Rules**
1. Set the rule you want
1. Click **Save Push Rules** for the changes to take effect
The following options are available.
| Push rule | GitLab version | Description |
| --------- | :------------: | ----------- |
| Removal of tags with `git push` | **Starter** 7.10 | Forbid users to remove Git tags with `git push`. Tags will still be able to be deleted through the web UI. |
| Check whether author is a GitLab user | **Starter** 7.10 | Restrict commits by author (email) to existing GitLab users. |
| Committer restriction | **Premium** 10.2 | GitLab will reject any commit that was not committed by the current authenticated user |
| Check whether commit is signed through GPG | **Premium** 10.1 | Reject commit when it is not signed through GPG. Read [signing commits with GPG](../user/project/repository/gpg_signed_commits/index.md). |
| Prevent committing secrets to Git | **Starter** 8.12 | GitLab will reject any files that are likely to contain secrets. Read [what files are forbidden](#prevent-pushing-secrets-to-the-repository). |
| Restrict by commit message | **Starter** 7.10 | Only commit messages that match this regular expression are allowed to be pushed. Leave empty to allow any commit message. Uses multiline mode, which can be disabled using `(?-m)`. |
| Restrict by commit message (negative match)| **Starter** 11.1 | Only commit messages that do not match this regular expression are allowed to be pushed. Leave empty to allow any commit message. Uses multiline mode, which can be disabled using `(?-m)`. |
| Restrict by branch name | **Starter** 9.3 | Only branch names that match this regular expression are allowed to be pushed. Leave empty to allow any branch name. |
| Restrict by commit author's email | **Starter** 7.10 | Only commit author's email that match this regular expression are allowed to be pushed. Leave empty to allow any email. |
| Prohibited file names | **Starter** 7.10 | Any committed filenames that match this regular expression and do not already exist in the repository are not allowed to be pushed. Leave empty to allow any filenames. See [common examples](#prohibited-file-names). |
| Maximum file size | **Starter** 7.12 | Pushes that contain added or updated files that exceed this file size (in MB) are rejected. Set to 0 to allow files of any size. Files tracked by Git LFS are exempted. |
TIP: **Tip:**
GitLab uses [RE2 syntax](https://github.com/google/re2/wiki/Syntax) for regular expressions in push rules, and you can test them at the [regex101 regex tester](https://regex101.com/).
## Prevent pushing secrets to the repository
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/385) in [GitLab Starter](https://about.gitlab.com/pricing/) 8.12.
Secrets such as credential files, SSH private keys, and other files containing secrets should never be committed to source control.
GitLab allows you to turn on a predefined denylist of files which won't be allowed to be
pushed to a repository, stopping those commits from reaching the remote repository.
By selecting the checkbox *Prevent committing secrets to Git*, GitLab prevents
pushes to the repository when a file matches a regular expression as read from
[`files_denylist.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/gitlab/checks/files_denylist.yml) (make sure you are at the right branch
as your GitLab version when viewing this file).
NOTE:
Files already committed won't get restricted by this push rule.
Below is an example list of what will be rejected by these regular expressions:
```shell
#####################
# AWS CLI credential blobs
#####################
.aws/credentials
aws/credentials
homefolder/aws/credentials
#####################
# Private RSA SSH keys
#####################
/ssh/id_rsa
/.ssh/personal_rsa
/config/server_rsa
id_rsa
.id_rsa
#####################
# Private DSA SSH keys
#####################
/ssh/id_dsa
/.ssh/personal_dsa
/config/server_dsa
id_dsa
.id_dsa
#####################
# Private ed25519 SSH keys
#####################
/ssh/id_ed25519
/.ssh/personal_ed25519
/config/server_ed25519
id_ed25519
.id_ed25519
#####################
# Private ECDSA SSH keys
#####################
/ssh/id_ecdsa
/.ssh/personal_ecdsa
/config/server_ecdsa
id_ecdsa
.id_ecdsa
#####################
# Any file with .pem or .key extensions
#####################
*.pem
*.key
#####################
# Any file ending with _history or .history extension
#####################
pry.history
bash_history
```
## Prohibited file names
> Introduced in [GitLab Starter](https://about.gitlab.com/pricing/) 7.10.
Each file name contained in a Git push is compared to the regular expression in this field. Filenames in Git consist of both the file's name and any directory that may precede it. A singular regular expression can contain multiple independent matches used as exclusions. File names can be broadly matched to any location in the repository, or restricted to specific locations. Filenames can also be partial matches used to exclude file types by extension.
The following examples make use of regex string boundary characters which match the beginning of a string (`^`), and the end (`$`). They also include instances where either the directory path or the filename can include `.` or `/`. Both of these special regex characters have to be escaped with a backslash `\\` to be used as normal characters in a match condition.
Example: prevent pushing any `.exe` files to any location in the repository. This is an example of a partial match, which can match any filename that contains `.exe` at the end:
```plaintext
\.exe$
```
Example: prevent a specific configuration file in the repository root from being pushed:
```plaintext
^config\.yml$
```
Example: prevent a specific configuration file in a known directory from being pushed:
```plaintext
^directory-name\/config\.yml$
```
Example: prevent the specific file named `install.exe` from being pushed to any location in the repository. Note that the parenthesized expression `(^|\/)` will match either a file following a directory separator or a file in the root directory of the repository:
```plaintext
(^|\/)install\.exe$
```
Example: combining all of the above in a single expression. Note that all of the preceding expressions rely on the end of string character `$`, so we can move that part of each expression to the end of the grouped collection of match conditions where it will be appended to all matches:
```plaintext
(\.exe|^config\.yml|^directory-name\/config\.yml|(^|\/)install\.exe)$
```
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
one might have when setting this up, or when something is changed, or on upgrading, it's
important to describe those, too. Think of things that may go wrong and include them here.
This is important to minimize requests for support, and to avoid doc comments with
questions that you know someone might ask.
Each scenario can be a third-level heading, e.g. `### Getting error message X`.
If you have none to add when creating a doc, leave this section in place
but commented out to help encourage others to add to it in the future. -->
|