How to Change the Default Commit Message on GitHub
In the world of software development, every line of code is like a brushstroke on a canvas, collectively creating a masterpiece of functionality. And just as artists meticulously select their colors and strokes, developers carefully craft their commit messages to maintain a clean and linear Git history.
A clean and linear Git history is a developer's equivalent of a well-organized library or a neatly arranged toolkit. It's not just a matter of aesthetics; it has profound implications for project maintainability, collaboration, and debugging.
Let's explore how developers effectively craft commit messages when merging pull requests on GitHub, enhancing their project's version control and collaboration.
When Merging Manually
GitHub introduced some great repository settings in August 2022 concerning commit messages. You can now change the default commit message for squash and merge commits.
Before that, GitHub used to set the commit message to something like:
Merge pull request #1234 from organization/branch/name
Well, that's not very useful when browsing the Git history…
Now, you can set the default commit message from the repository settings on the "General" settings page in the section marked "Pull Requests”.
The default commit message is presented to users on the pull request page when merging a pull request. For example, assume Default to pull request title and description
is selected, and a user clicks to merge a pull request with this description:
The default commit message will include the pull request's title and description:
The user can then accept this commit message or make changes before merging. Developers can now have a clean and useful Git history where each commit message describes exactly what changes have been made.
Available Options
For merge commit merging:
- Default message: pull request number and head branch on the first line; pull request title on the third line;
- Default to pull request title: pull request title and number on the first line;
- Default to pull request title and description: pull request title and number on the first line; pull request description starting on the third line.
For squash merging:
- Default message: commit title and commit message (if the pull request contains a single commit), or pull request title and number and list of commits (if the pull request contains multiple commits);
- Default to pull request title: pull request title and number on the first line;
- Default to pull request title and commit details: pull request title and number on the first line; commit message (if a single commit) or list of commits (if multiple commits);
- Default to pull request title and description: pull request title and number on the first line; pull request description starting on the third line.
Configuring Via API
Finally, the default message format can be managed using the following parameters on the Create a Repository or Update a Repository REST APIs, allowing finer control over it.
merge_commit_title
: default value for a merge commit title
PR_TITLE
: default to the pull request's titleMERGE_MESSAGE
: default to the classic title for a merge message (e.g.,Merge pull request #123 from branch-name
)
merge_commit_message
: default value for a merge commit message
PR_TITLE
: default to the pull request's titlePR_BODY
: default to the pull request's bodyBLANK
: default to a blank commit message
squash_merge_commit_title
: default value for a squash merge commit title
PR_TITLE
: default to the pull request's titleCOMMIT_OR_PR_TITLE
: default to the commit's title (if only one commit) or the pull request's title (when more than one commit)
squash_merge_commit_message
: default value for a squash merge commit message
PR_BODY
: default to the pull request's bodyCOMMIT_MESSAGES
: default to the branch's commit messageBLANK
: default to a blank commit message.
When Merging With a Merge Queue
Using GitHub’s Merge Queue
GitHub’s merge queue has been generally available since July 2023. This feature allows you to queue a pull request for merge when it’s ready. Each pull request in the queue is then tested with the latest version of the base branch and merged when the CI passes, thus avoiding the introduction of nasty bugs on the main branch due to outdated pull requests.
But you can't set the commit message when clicking on the “Merge when ready” button. GitHub uses the default commit message configured in the repository settings. So, you have only a few configuration choices when merging with GitHub’s merge queue.
This prevents some organizations from adopting this merge queue, as you can see in this discussion.
The best thing you can do is use the pull request title and description as commit message and check the pull request with your CI, using this GitHub Action for example.
Using Mergify’s Merge Queue
Mergify allows you to define a template for commit messages, whether you want to automatically merge a pull request or merge a pull request using a merge queue.
You can do this using Mergify’s configuration file with the commit_message_template
attribute, so all the pull requests that Mergify merges will have the same commit message template.
For example, to reproduce GitHub’s default commit message composed of the title and the description of the pull request, you could set the following configuration:
queue_rules:
- name: default
commit_message_template: |
{{ title }} (#{{ number }})
{{ body }}
Then when you add a pull request to the merge queue and Mergify merges it, the commit message will look like this:
Fix some bug (#123)
This fixes some bugs I found while testing the app.
Templating Using Pull Request’s Attributes
The template is rendered using the Jinja2 template language. This means you can render any attribute of the pull request, even list attributes.
Warning! When using templates, you must replace the -
character with _
from the pull request attribute names. The -
is not a valid character for variable names in a Jinja2 template.
Say that you want to include reviewers of a pull request in the commit message, you could set the following template:
queue_rules:
- name: default
commit_message_template: |
{{ title }} (#{{ number }})
{{ body }}
{% for user in approved_reviews_by %}
Approved-By: {{user}}
{% endfor %}
Resulting in:
Fix some bugs (#123)
This fixes some bugs I found while testing the app.
Approved-By: jd
Approved-By: sileht
You could also include the co-authors of the pull request in the commit message. For example:
queue_rules:
- name: default
commit_message_template: |
{{ title }} (#{{ number }})
{{ body }}
{% for co_author in co_authors %}
Co-Authored-By: {{ co_author.name }} <{{ co_author.email }}>
{% endfor %}
The result would be:
Fix some bugs (#123)
This fixes some bugs I found while testing the app.
Co-Authored-By: jd <jd@mergify.com>
Co-Authored-By: sileht <sileht@mergify.com>
The co_authors
attribute is the list of users who contributed to the pull request. It excludes the pull request’s author, bots, and merge commits’ authors.
Jinja2 Advanced Features
The Jinja2 template language is a powerful feature that allows you to craft complex commit messages. Most of the language features are supported, like Jinja2 filters.
You can build a string from list attributes. For example:
Approved by: @{{ approved_reviews_by | join(', @') }}
This template will be rendered like this:
Approved by: @jd, @sileht
Other operations are supported, like Python operations. Most of a pull request’s attributes are strings, so you can change them in many ways and combine these operations with filters.
The following template capitalizes the first letter of the pull request’s title and strips leading and trailing whitespaces.
{{ title.capitalize() | trim }}
Mergify also provides custom Jinja2 filters, like markdownify
that convert HTML to Markdown.
{{ body | markdownify }}
You could also extract a Markdown section using the custom filter get_section(<section>, <default>)
. For example, the following template extracts the “Description” section from the pull request’s body.
{{ body | get_section("## Description") }}
By default, the HTML comments are stripped from body
. To get the full body, you can use the body_raw
attribute.
Tools like Mergify provide a powerful canvas for developers to paint a clean and useful commit history. It could even serve as the foundation for automatically generating a project changelog based on your Git commit messages.