---
title: "Commit Message rules for TYPO3 CMS"
manual: "TYPO3 Core Contribution Guide"
version: "main"
permalink: "https://docs.typo3.org/permalink/t3contribute:commitmessage"
source: "Appendix/CommitMessage.rst"
rendered: "2026-09-26T04:50:59+00:00"
---

# Commit Message rules for TYPO3 CMS {#commitmessage}

In TYPO3 we try to automate the contribution/coding process as much as possible
and the commit message plays an important role in that.

Git and related tools work best when following strict guidelines for commit
messages. The [introduction to git revision log conventions](http://tbaggery.com/2008/04/19/a-note-about-git-commit- messages.html) explains the guidelines in more detail.

Here is an example of a final commit message. The `Change-Id` will be generated
by the commit-hook. Do not set the `Change-Id` on your first commit!

```none
[BUGFIX] Introduce some serious fixing

Most importantly, describe what is changed with the commit
and not what is has not been working
(that is part of the bug report already).

More detailed explanatory text, if necessary. Wrap it to 72 characters.
The first line is treated as the subject of the commit message and
the rest of the text as the body.  The blank line separating the
subject from the body is critical (unless you omit the body entirely);
tools like git rebase can get confused if you run the two together.

Write your commit message in the '''imperative present tense'''
("Fix bug", not "Fixed bug"). This convention matches up with generated
commit messages by commands like git merge and git revert.

Help others to understand what you did (Motivation for the change?
Whats the difference to the previous version?), but keep it simple.

Problem description as well as testing and/or reproduction instructions
shall be part of the Forge ticket referenced below.
The commit message solely describes '''what is changed'''.

* Bullet points are okay, too
* An asterisk (`*`) is used for the bullet, it can be followed by a
  single space. This format is rendered correctly by Forge (redmine)
* Use a hanging indent

Resolves: #12346
Related: #12340
Releases: main, 13.4
Change-Id: I<some string generated by the git commit-msg hook>
```

You can see that a commit message consists of several parts, let's go over them step by step:

## Summary line (first line) {#summary-line-first-line}

A summary line starts with a **keyword** and a **brief summary** of what the
change does. Make sure to describe how the behavior is **now**, not how it used
to be - in the end, telling someone what was broken doesn't help anyone, you
want to tell what is working now :)

-   Prefix the line with a keyword:  *\[BUGFIX\]*,  *\[FEATURE\]*,  *\[TASK\]* or  *\[DOCS\]*.

Possible keywords are:

-   **`[BUGFIX]`**

    A fix for a bug.

-   **`[FEATURE]`**

    A new feature (also small additions). Most likely it will be an added
    feature, but it could also be removed. Features may exclusively be targeted for
    the "main" branch of TYPO3 CMS, because no new features are allowed in older
    branches. Exceptions to this have to be discussed on a case-to-case basis with
    the designated release managers. Features have to be documented in the
    [changelog](https://docs.typo3.org/permalink/t3contribute:changelog).

-   **`[DOCS]`**

    This tag is used for changes regarding the documentation.

-   **`[TASK]`**

    Anything not covered by the above categories. E.g. Refactoring of a component

Additionally other flags  **should be added** under certain circumstances:

-   **`[!!!]`**

    Breaking change. After this patch, something works different than before
    and the user / admin / extension developer will have to change something. Has to
    be  **documented** accordingly and should only be targeted for the main branch.
    See [Editing the changelog](https://docs.typo3.org/permalink/t3contribute:changelog).

> [!IMPORTANT]
> Whenever your change introduces a breaking change, it is **mandatory** to
> put `[!!!]` in front of the keyword.

-   **`[SECURITY]`**

    Visualizes that a change fixes a security issue. This tag is used
    by the Security Team.

> [!IMPORTANT]
> In case you found a security issue, always get in touch with the [Security Team](https://typo3.org/community/teams/security/contact-us/) **first**! Never post information
> about security vulnerabilities in a public place such as Slack or push patches
> that disclose information about vulnerabilities.

-   Keep the whole line below 52 characters if possible, but below 72 in any case

**The seven rules of a great Git commit message**

[https://chris.beams.io/posts/git-commit/#seven-rules](https://chris.beams.io/posts/git-commit/#seven-rules) is an excellent guide
about how to write good subject lines.

-   It is *very important* that the message is written in **imperative mood**;
    that means that it must be written as if you are giving a command or an
    instruction, since a commit is a set of instructions for how to go from a
    previous state to the new state and the commit message should describe this
    process. This convention matches up with generated commit messages by
    commands like git merge and git revert. If in doubt, the *golden rule* to
    follow is very simple: Review your subject lines, and apply the following
    words in front of it:

`if applied, this commit will **"your subject line here"**`

For example (you will find some more examples later):

`If applied, this commit will **Invalid session token on creating content element in admin panel**` Does not make any sense.

`If applied, this commit will **"Fix backend edit URL in admin panel"**` Reads nicely and explains what happened

-   After the keyword, make sure to start the summary with a capital letter.
-   Avoid using `EXT:somesystemextension` in the commit subject: looks ugly
    and is redundant when you look at what code changed.
-   In case of reverting a previous commit, basically you should just prepend
    \[TASK\] to the message automatically generated by a git revert. For example,
    in case of reverting a feature you would
    use: `[TASK] Revert "[FEATURE] Transform Lead to Gold"`

### Deprecations {#deprecations}

-   [Deprecations](https://docs.typo3.org/permalink/t3contribute:deprecations) must **not** use the breaking Prefix \[!!!\]
-   [Deprecations](https://docs.typo3.org/permalink/t3contribute:deprecations) may **only** be of type **\[TASK\]** or **\[FEATURE\]**

### Some examples of topic descriptions {#some-examples-of-topic-descriptions}

`[BUGFIX] Throw HttpStatusExceptions in BackendController`

`[FEATURE] Add option to hide BE search box in list mod`

`[!!!][FEATURE] Implement new BE login form service`

`[!!!][TASK] Replace Foo API with new approach`

`[SECURITY] Escape record title in RecordsOverview`

*Note:* The \[!!!\] prefix is added at the *very beginning* of the line, so it doesn't get overlooked.

## Description (Message body) {#description-message-body}

Here you can go into detail about the how and why of the change. It should be
brief, but yet descriptive so people reviewing your change get an idea what they
need to look out for

-   Describe the fix/change introduced by the Change Request. (The problem is
    already described in the Forge ticket.)
-   Keep it simple and don't repeat information that is already part of
    the issue tracker. Especially avoid "How to reproduce" part. At most,
    try to explain the change itself, if it is not already clear by reading
    the diff. Do not repeat the code change itself in the body text.
-   Wrap the lines after 72 characters manually

### Inserting links / long lines {#commitmessage-links}

Sometimes you must insert long links that exceed the line length of 72 characters.

In that case, it is ok to have these long lines - because inserting linebreaks
would make the link invalid. You can ignore warnings of possible CGL checks,
or (temporarily) disable your GIT commit hook check for this specific warning.

It is best practice to use placeholders for links and then group used links
at the end in your commit message, like this:

```none
[BUGFIX] Link some long links

In [1] is is documented, that something is not wrong. But
in reality [2] properly indicates, this is indeed right.

So we follow the advice of [3][4] and make things better.

[1] https://example.com/a/very/very/long-link/because/it/is/really-needed-I-mean-it-its-long-but-okay
[2] https://example.com/this/is/short/but/also/nice
[3] https://example.com/snafu
[4] https://example.com/mostlyharmless

Resolves: #12346
Related: #12340
Releases: main, 12.4
Change-Id: I<some string generated by the git commit-msg hook>
```

This is no specifically parsed syntax, the `[number]` formatting is
just common plaintext formatting.

### Relationships {#relationships}

> [!IMPORTANT]
> 1.  The space after the colon (:) is mandatory. Otherwise the system will not
>     properly update forge.
> 1.  If you have multiple resolved or related issues, **use one line for each
>     issue number**. Do not separate them by comma or alike!
>
>     **commit message**
>
>     ```text
>     Resolves: #12345
>     Resolves: #67890
>     ```

1.  `Resolves:` **(REQUIRED)**
    You **must** reference an issue on [Forge](https://forge.typo3.org) by
    adding the #\[ISSUE_NUMBER\]. The commit-msg hook rejects commits that
    do not have at least one `Resolves:` line. For **feature** and **task** commits,
    the resolved issues are closed on merge:

    **commit message**

    ```text
    Resolves: #12345
    ```

    *Historical* : Some issues from the time since the introduction of GIT
    (March 1st 2011) and the migration of the bug tracker to Forge
    (March 29th 2011), still refer to Mantis bug tracker numbers, with a
    prefix the number with an  *M* , i.e.:

    **commit message**

    ```text
    Resolves: #M12345
    ```
1.  `Related:` **(OPTIONAL)**
    Other issues related to this change which are not resolved (for **all
    types** of commit, it only adds relations and the issues are not closed). This is optional and
    **cannot be used alone** \- you must have at least one `Resolves:` line
    as well. You reference the related issue on [Forge](https://forge.typo3.org) by adding the issue number:

    **commit message**

    ```text
    Related: #12345
    ```
1.  `Releases:`
    This is a comma separated list of the target versions you intend to apply
    this fix on. In general, we **always** fix things on **main** first and
    then backport a change if it goes along with our support rules for older
    versions. Example:

    **commit message**

    ```text
    Releases: main, 13.4, 12.4
    ```

    Always make sure the target version does indeed exist, when in doubt, as in the coredev channel on [Slack](https://slack.typo3.org).
1.  `Depends:`
    For TYPO3  **documentation patches**.
    Refer to the corresponding TYPO3 Core patch:

    **commit message**

    ```text
    Depends: ChangeIdOfCorePatch
    ```
1.  `Change-Id:`
    Do not write or change this line yourself. But keep the line once it exists.

    The change id is a randomly generated unique ID that identifies this change in
    [Gerrit](https://review.typo3.org).
    The `Change-Id` line is automatically added by [our pre-commit hook](https://docs.typo3.org/permalink/t3contribute:pre-commit-hook). The commit hook is executed when you have finished
    editing and save the commit message.

    *Attention:* Be sure to keep the existing Change-Id when adding a new patchset
    to an existing review. Use `git commit --amend` to do so.

## Reverting patches {#reverting-patches}

If there's the need to revert a patch, please add this information to
the commit message:

1.  Add a `Resolves`-line for the ticket that is giving the reason for the
    revert.
1.  Add a `Reverts`-line for the ticket that belongs to the original patch.

You will find  more information about the life cycle of a patch here [Revert patches](https://docs.typo3.org/permalink/t3contribute:lifeofapatch-reverting-patches).

## Commit Template {#commit-template}

You can use a custom template for automatically generating a commit message with the basics.

This is covered in the Git setup instructions, see [setting up a commit message template](https://docs.typo3.org/permalink/t3contribute:committemplate).

## Bad summary lines examples vs. good examples {#bad-summary-lines-examples-vs-good-examples}

Please note that the following examples are taken from *real commits*.

**Example 1**

```none
[FOLLOWUP][BUGFIX] Remove uglify of jquery-ui/sortable.js
```

should have been:

```none
[BUGFIX] Remove uglify of jquery-ui/sortable.js
```

**Example 2**

```none
[BUGFIX] EXT:filelist Cancelling the file exists already modal works now
```

should have been:

```none
[BUGFIX] Allow cancelling modal that appears when file exists
```

**Example 3**

```none
Revert "[FEATURE] EXT:form - introduce YAML "imports""
```

should have been:

```none
[TASK] Revert "[FEATURE] introduce YAML "imports""
```

> [!NOTE]
> Please note that in this case the subject of the commit to revert was
> poorly written, too! This required some additional adjustment..

**Example 4**

```none
[TASK] Revert "Add support for PSR-15 HTTP middlewares"
```

should have been:

```none
[TASK] Revert "[FEATURE] Add support for PSR-15 HTTP middlewares"
```

**Example 5**

```none
[TASK] use horizontal ellipsis instead of 3 dots
```

should have been:

```none
[TASK] Use horizontal ellipsis instead of 3 dots
```

**Example 6**

```none
[BUGFIX] Element Browser should only render default language pages
```

should have been:

```none
[BUGFIX] Limit element browser to only render default language pages
```

**Example 7**

```none
[BUGFIX] D3.js uses basic authentication credentials cached in browser
```

should have been:

```none
[BUGFIX] Use only basic authentication credentials cached in browser in D3.js
```

**Example 8**

```none
[DOCS] 1/1 9.1 Documentation
```

should have been:

```none
[DOCS] Add documentation for version 9.1 (1/1)
```

**Example 9**

```none
[FEATURE] Option to globally enable redirect hit count
```

should have been:

```none
[FEATURE] Add option to globally enable redirect hit count
```

**Example 10**

```none
[TASK] Improved extension configuration API
```

should have been:

```none
[TASK] Improve extension configuration API
```

**Example 11**

```none
[BUGFIX] NewContentElementWizardController to NewContentElementController
```

should have been:

```none
[BUGFIX] Remove recently introduced NewContentElementWizardController
```

**Example 12**

```none
[BUGFIX] Invalidate session token on creating content element in admin panel
```

Should have been:

```none
[BUGFIX] Fix backend edit URL in admin panel
```
