Markdown on GitHub and GitLab
Markdown where developers and operations teams use it most: READMEs, issues and pull requests, alerts, mentions and references, diagrams with Mermaid, and math.
Files and comments
On GitHub, Markdown appears in two kinds of places.
Markdown files (.md) in a repository,
such as the
README, runbooks and the docs/ folder, are rendered when you
open them. Text fields are everything you type into
the web interface: issue and pull request descriptions, comments,
review comments, Discussions and wiki pages. Both use
GitHub Flavored Markdown
with GitHub's extras, but they do not behave identically.
Every text field has a Preview tab next to Write. Use it before you post: a comment that notifies twenty people or a table that collapsed into one line of pipes is much easier to fix before it is sent.
For a rendered file, GitHub builds an outline (a table of contents)
from the headings automatically. For the README it looks in
.github/, then the repository root, then
docs/, and it truncates anything beyond 500 KiB.
Line breaks in comments
In CommonMark, a single newline inside a paragraph is a
soft break: the browser joins the lines. That is how
Markdown files on GitHub behave too. Here is a status update as a
.md file renders it:
Status: investigating
Impact: portal logins fail
Next update: 14:30
<p>Status: investigating Impact: portal logins fail Next update: 14:30</p>
In issues, pull requests and comments, GitHub renders a line break
for every newline. The renderer on this site can imitate that with
its breaks option, used in the next example:
Status: investigating
Impact: portal logins fail
Next update: 14:30
<p>Status: investigating<br> Impact: portal logins fail<br> Next update: 14:30</p>
So text that Tomasz Nowak pastes from an incident comment into the runbook file suddenly runs together. In files, end the line with a backslash for a hard break, use a list, or leave a blank line between paragraphs; see Headings, paragraphs and line breaks.
Relative links and images
Inside a repository, link to other files with a relative path, not
with a full https://github.com/… address. GitHub
rewrites relative links and image paths to the branch you are
currently viewing, so the README on a feature branch shows that
branch's diagram, and the links keep working in a fork, a clone and
an editor preview.
See the [restart runbook](docs/runbooks/restart-portal.md)
and the [contributing guide](CONTRIBUTING.md).

<p>See the <a href="docs/runbooks/restart-portal.md">restart runbook</a> and the <a href="CONTRIBUTING.md">contributing guide</a>.</p> <p><img src="docs/images/portal-architecture.png" alt="Portal architecture: load balancer, two web servers, database"></p>
The Markdown only stores the paths; GitHub resolves them against the file's own folder and the current branch. If the image cannot be loaded, the reader sees the alternative text, which is also what a screen reader announces. More on paths and alt text in Links and images.
Heading anchors
A heading anchor is the
identifier that a renderer gives each heading, so that a link ending
in #name jumps straight to it. GitHub creates anchors
for every heading in rendered Markdown with these rules:
- letters become lower case;
- spaces become hyphens;
- other punctuation and whitespace are removed, except hyphens and underscores, and so is Markdown formatting;
-
a repeated heading gets
-1,-2and so on.
| Heading | Link to it |
|---|---|
## Rollback plan |
#rollback-plan |
## Restart the portal (v2)! |
#restart-the-portal-v2 |
## **Before** you start |
#before-you-start |
A second ## Rollback plan |
#rollback-plan-1 |
Anchors are not part of CommonMark. The renderer on this site, like
many plain renderers, does not add them, so the link is created but
the heading has no id to jump to:
If the restart fails, follow the [rollback plan](#rollback-plan).
## Rollback plan
<p>If the restart fails, follow the <a href="#rollback-plan">rollback plan</a>.</p> <h2>Rollback plan</h2>
On GitHub the same link works. Other tools (GitLab, documentation
generators, plugins such as markdown-it-anchor)
generate anchors with similar but not always identical rules,
especially for non-English letters, emoji and duplicates. A link
checker catches broken fragments; see
Linting and consistent style.
Alerts
A GitHub alert is a block quote
whose first line is a marker such as [!WARNING]. GitHub
shows it as a highlighted box with an icon and a colored title.
There are five types:
> [!NOTE]
> The portal runs on two web servers behind one load balancer.
> [!TIP]
> Run the health check script first; it saves you a restart.
> [!IMPORTANT]
> Every restart needs an approved change number.
> [!WARNING]
> Do not restart both web servers at the same time.
> [!CAUTION]
> Restoring the database overwrites all orders since the backup.
ⓘ Note The portal runs on two web servers behind one load balancer. … ⚠ Warning Do not restart both web servers at the same time. … (each type is a box with its own icon, title and color)
GitHub launched alerts in December 2023. Older tutorials show a beta
syntax with > **Note**; that is now just a quote
with bold text. GitHub's own advice: use alerts only when they are
crucial, at most one or two per document, and do not nest them
inside other elements such as lists.
Outside GitHub, an alert falls back to an ordinary block quote with
the marker as text. That is a graceful fallback, but the literal
[!WARNING] remains visible:
> [!WARNING]
> Do not restart the core switch during office hours.
<blockquote> <p>[!WARNING] Do not restart the core switch during office hours.</p> </blockquote>
Mentions, references and emoji
A mention is an
@ followed by a user name (@tomasz-nowak)
or an organization and team (@kestrel-energy/noc). The
person, or every member of the team, gets a notification and the
name becomes a link to the profile. Mentions are how you pull
someone into a conversation, so use them deliberately: a mention in
a long thread is a request for that person's attention.
Issue references
An issue reference is a short
code such as #482 that the platform turns into a link
to an issue or pull request. On GitHub, the timeline of the
referenced issue also records the mention, which builds a trail
between related work. GitHub also links commit hashes and longer
forms that point into other repositories; its documentation on
autolinked references lists them all.
@kestrel-energy/noc the portal outage in #482 looks related to
the certificate change in #479. @emeka-obi can you check the
load balancer logs? :eyes:
[@kestrel-energy/noc] the portal outage in [#482] looks related to the certificate change in [#479]. [@emeka-obi] can you check the load balancer logs? 👀 ([…] = link; the team and Emeka Obi are notified)
Emoji shortcodes such as :eyes: or
:white_check_mark: become emoji; typing
: in a GitHub text field opens a list of suggestions.
In plain Markdown elsewhere they stay as the literal text, so keep
them out of documents that are read outside GitHub, and do not let
an emoji carry information that the words do not.
Footnotes
A footnote is a numbered reference
in the text, [^1], that points to a note defined
elsewhere in the document with [^1]: text. GitHub
renders the reference as a small superscript link and collects all
notes at the bottom, each with a link back. The label can be a word
instead of a number; GitHub numbers the notes in order of appearance
anyway.
The failover took 41 seconds.[^timing]
[^timing]: Measured from the first failed health check to the first successful login.
The failover took 41 seconds.¹ ──────────── Footnotes 1. Measured from the first failed health check to the first successful login. ↩
Since September 2021, GitHub supports footnotes in Markdown files, issues, pull requests and comments, but not in wikis. Footnotes are not part of CommonMark or the GFM spec. A renderer without the extension shows the raw labels:
The failover took 41 seconds.[^timing]
[^timing]: Measured from the first failed health check.
<p>The failover took 41 seconds.[^timing]</p> <p>[^timing]: Measured from the first failed health check.</p>
Diagrams and math
Mermaid diagrams
Mermaid is a text-based diagram
language: you describe a flowchart, sequence diagram, timeline or
state diagram in lines of text, and a JavaScript library draws it.
GitHub renders a fenced code block with the info string
mermaid as a diagram in issues, pull requests,
Discussions, wikis and Markdown files (since February 2022; wikis
since August 2022). Because the diagram is text, it lives in the
repository next to the documentation, and a change to it shows up in
a diff like any other change.
```mermaid
flowchart LR
A[NOC detects outage] --> B[Incident opened]
B --> C[Service desk updates status page]
C --> D[Customers informed]
```
[NOC detects outage] → [Incident opened] → [Service desk updates status page] → [Customers informed] (drawn as four boxes with arrows, left to right)
Anywhere that does not run Mermaid, the block is simply a code block
with a language-mermaid class, which still reads
reasonably as text:
```mermaid
flowchart LR
A[NOC detects outage] --> B[Incident opened]
```
<pre><code class="language-mermaid">flowchart LR
A[NOC detects outage] --> B[Incident opened]
</code></pre>
GitHub also renders geojson and
topojson blocks as maps and stl blocks as
3D models. GitHub does not always run the newest Mermaid release
(12.1.0 as of October 2026), so check GitHub's documentation before
you use a brand-new diagram type. VS Code's built-in preview and
GitLab render Mermaid too.
Math
GitHub renders mathematical expressions with MathJax: inline between
dollar signs, $…$ (or $`…`$ when the
expression itself contains characters Markdown would otherwise
interpret), and as a block between $$ lines or in a
```math fence.
Power is voltage times current: $P = V \times I$.
$$
E = P \times t
$$
A dollar sign that should stay a dollar sign can be a problem in
text with prices. Escape it as \$ inside an expression,
or wrap it in <span>$</span> outside one,
as GitHub's documentation suggests.
GitLab Flavored Markdown
GitLab Flavored Markdown (GLFM) starts from the same base: CommonMark, then the GFM extensions, then GitLab's own. A README or runbook written in plain GFM renders almost identically on both platforms. The differences are in the extras:
| Feature | GitHub | GitLab |
|---|---|---|
| Issue reference | #123 |
#123; #123+ also shows the title
|
| Pull or merge request | #123 (same numbering as issues) |
!123 |
| Labels and milestones | Not in Markdown | ~label, %milestone |
| Alerts | Five types | The same five types |
| Diagrams | Mermaid, GeoJSON, TopoJSON, STL | Mermaid; PlantUML and Kroki where an administrator has enabled them |
| Table of contents | Automatic outline for files | [[_TOC_]] placed in the text |
| Multiline quote | Repeat > on every line |
Also >>> … >>>
|
| Front matter | YAML, shown as a table in rendered files | YAML, TOML or JSON (Front matter and metadata) |
GitLab also shows color chips for color codes in backticks (for
example `#1A7F37`), supports description lists and
math, and can include other files with include directives. When a
document has to work on both platforms, stay with the shared base
and the five alert types, and avoid platform-specific references in
files (they only make sense in that platform's issues and comments
anyway).