Skip to content
Connect an agent
Other diagram kinds

Git graphs

A git graph draws a repository history as lanes: one lane for each branch, with the commits along the lanes and the merges, tags, and cherry-picks marked on them. It is for anyone who explains a branching strategy, a release process, or the story of a hotfix, in a README, a pull request, or a handbook. You write the history, so the picture shows the history you mean and not whatever a repository happens to hold.

TL;DR

QuestionAnswer
What is it for?Showing how branches, commits, merges, tags, and cherry-picks fit together, such as a release flow or a trunk-based workflow.
What does the header look like?git "Title", with the optional direction=, main=, and desc=.
How is time read?The order the statements are written is the order in time. There are no dates.
Which way does it run?direction=auto (the default) draws left to right when that fits a Markdown column and top to bottom when it does not. right and down are taken as written.
What are the limits?At most 300 commits and 24 branches (error E140). Warnings start at 40 commits and 7 branches (W200).
How is it colored?Each branch takes a tone from the theme, in the order the branches are made. No color is written in the source.
Does Mermaid convert?Yes: gitGraph becomes a git graph. See From Mermaid.

Ask your agent

text
Use Plotwork to draw a git graph of our release process. Features branch from develop and merge back into it. Develop is merged into main for release 1.0 and tagged v1.0. A hotfix branches from main, is merged back and tagged v1.0.1, and its fix is cherry-picked onto develop.
text
Use Plotwork to draw a git graph of trunk-based development. Main is the only long-lived branch. Three short branches each get two or three commits and are merged back into main. Draw it top to bottom, and tag the last merge v2.0.

Example

A feature is merged into develop, develop is released as v1.0, and a hotfix is tagged and picked back.

Release and hotfix: 10 commits on 4 branches, 3 merges, 1 cherry-pick, 2 tags. A feature is merged into develop, develop is released as v1.0, and a hotfix is tagged and picked back.

The language

Everything is key=value, text is in double quotes, and a # starts a comment. Statements work like the commands they are named after: commit adds to the branch you are on, branch makes a branch at the newest commit and switches to it, and checkout switches to another.

The header

PartMeaning
git "Title"The first line. The title becomes the accessible name of the picture.
direction=auto (the default), right, or down.
main=The name of the default branch, which is main unless you rename it.
desc="Summary"A one- or two-sentence summary. It is the alt text of the picture, so write what the history shows.
Plotwork
git "Release flow" direction=down main=trunk

Statements

StatementMeaningCopyable example
commit "message" id=c1 tag="v1.0" type=highlightA commit on the current branch. Every part is optional: with no message it is a bare dot. id is a name for cherry-pick and from=. tag may repeat, or list names with commas, up to 3. type is normal, highlight, or reverse.commit "Add search" id=c2 tag="v0.2"
branch name from=x order=n tone=tMakes a branch at the newest commit of the current branch, or of from= (a branch, or a commit id), and switches to it.branch "feature/search" from=develop order=2
checkout name or switch nameNew commits go on that branch.checkout develop
merge name "message" id=m1 tag="v1" type=tA merge commit on the current branch that brings in the newest commit of name.merge develop "Release 1.0" tag="v1.0"
cherry-pick id "message" tag="v1" type=tA copy of one commit, made on the current branch. With no message it keeps the message of the commit it copies.cherry-pick c3
desc "text"The plain-language summary, written as a statement instead of on the header.desc "Hotfix 1.0.1 is picked back onto main."

A branch name that holds a slash goes in double quotes, because a bare word cannot hold one. Writing it bare is error E100, and the hint gives the line to write.

Plotwork
branch "feature/search" from=develop

Names and ids

Branch names and commit ids share one set of names, so from=x, merge x, and cherry-pick x mean one thing. Using a name twice is error E130. An id is letters, digits, _ and -, starting with a letter. The message is what the picture shows, so put words there and keep the id short.

Lane order

The lowest order= is the first lane: the top lane when the graph is drawn left to right, and the left one when it is drawn top to bottom. A branch with no order= takes the number of branches made before it, so the default is the order they were made in. Where two branches share a number, the one that asked for it goes first, so order=1 is the second lane and order=0 goes above the default branch. A branch keeps its tone when its lane moves.

Put the lanes that exchange commits next to each other. Warning W303 appears when a fork or a merge passes two or more other lanes, and its hint suggests the order= to write.

Plotwork
branch develop order=2branch hotfix order=1

Tones

tone= on a branch takes one of the tones of the language: neutral, blue, violet, aqua, orange, green, amber, or red. Leave it out and the branch takes the next tone in order. A name that is not one is error E121.

What the picture shows

ElementHow it is drawn
BranchA pill at the start of its lane with the branch icon and the name, in the lane's tone, and a faint dotted guide along the lane.
CommitA dot in the lane's tone. Its message hangs below it, or in a column to the right of the lanes when the graph runs top to bottom.
type=highlightThe dot inside a halo tinted with the lane's color.
type=reverseA hollow ring with a cross.
ForkA line that leaves the commit a branch was made from and turns into the new lane, in the new branch's tone.
MergeA ring around the merge commit in the tone of the merged branch, and a line from the merged branch's newest commit into it.
Cherry-pickA dashed ring in the tone of the lane the commit came from, and a muted line under the message, cherry-pick of c3. The copied commit shows its id so the pick can be matched to its source.
TagA small pill with a tag glyph.
Branch with no commitA short stub ending in a small ring where its first commit would be, and warning W301.

A second example

Three short branches leave the trunk and are merged back, and a release branch starts from an old commit by its id. It shows main= renaming the default branch, direction=down, from= with a commit id, order=0 for a lane before the default branch, and a tag on a highlighted merge.

Trunk-based development: 9 commits on 4 branches, 2 merges, 1 tag. Three short branches leave the trunk and are merged back within a few commits. The last merge is tagged as the 2.0 release, and a release branch starts from an old commit.

Limits and warnings

A history may hold at most 300 commits and 24 branches. Past either, the diagram is refused with error E140 before any layout work. Warnings never stop the picture. They point at things a reader will notice. Text is cut only past a hard limit: a message after two lines, a tag, or a branch name that is longer than its pill can hold.

Errors

CodeWhen it firesFix
E100A syntax error, such as a branch name with a slash that is not in quotes.Write what the hint gives, such as branch "feature/x".
E101A string with no closing quote.Close the quote.
E110A statement the language does not have.Use commit, branch, checkout, switch, merge, cherry-pick, or desc.
E121A tone that is not one of the eight.Use one the hint lists.
E123A direction that is not auto, right, or down.Use one of the three.
E130A name used twice. Branch names and commit ids share one set.Pick a different id.
E131A checkout, merge, from=, or cherry-pick that names a branch or a commit that does not exist.Make it first with branch, or fix the spelling.
E135An option the statement does not take.Use one the hint lists.
E136A bad value for an option, such as a commit type= that is not normal, highlight, or reverse.Use a value the hint lists.
E140More than 300 commits or 24 branches.Split the history into several graphs.
E300A branch merged into itself.Check out the branch that should receive the changes first.
E301A branch made before any commit, or from a branch with no commit.Write a commit first.
E302A cherry-pick of a commit the current branch already has.Cherry-pick a commit from another branch.
E303More than 3 tags on one commit.Keep the tags a reader needs, or tag a later commit with the rest.
E304A history with no commit.Add commits.

Warnings

CodeWhen it firesFix
W200More than 40 commits, or more than 7 branches.Split along a branch or a period.
W202The graph is wider than a Markdown column and its text would shrink.Use direction=down, shorten messages, or split it.
W203Text was cut with an ellipsis: a message, a tag, or a branch name.Shorten the text.
W300A merge that brings in nothing new. No line is drawn for it.Remove the merge, or commit on the merged branch first.
W301A branch with no commit of its own, drawn as an empty stub.Commit on it, or leave the branch out.
W302The same tag on two commits.A tag names one commit. Rename one, for example with a patch number.
W303A fork or a merge passes two or more other lanes.Move the lanes that exchange commits next to each other with order=.

From Mermaid

A gitGraph converts to a git graph. The converter replays the history as Mermaid would, so a statement that Mermaid itself would refuse is reported instead of guessed at. Header words LR, TB, and BT, and a trailing colon, are read.

Mermaid
gitGraph  commit id: "Initial commit"  branch develop  checkout develop  commit id: "Set up CI"  checkout main  merge develop tag: "v1.0"
MermaidPlotwork
commit id: "A"commit "A". What Mermaid draws on a commit is its id, so the id becomes the message.
commit "text" and commit msg: "text"commit "text".
commit with no id or messageA bare dot, reported once for all of them with M220.
commit id: "A" msg: "B"commit "A", with M222, because Mermaid draws only the id.
tag: and type: NORMAL, REVERSE, HIGHLIGHTtag= and type=normal, reverse, highlight. Any case is read. An unknown type is a normal commit, with M204.
branch name order: 2branch name order=2. A name with a slash or a space is quoted. An order that is not a whole number from 0 to 99 is dropped, with M203.
checkout name and switch namecheckout name. A checkout of the branch you are already on is not kept.
merge name id: "M" tag: "v" type: Tmerge name "M" tag="v" type=t.
cherry-pick id: "A"cherry-pick A, and the copied commit gets id=A. An id that is not valid, or that is a branch name, is renamed, with M206.
cherry-pick id: "A" parent: "B"The parent is dropped, with M221, because a cherry-pick copies one commit.
gitGraph LR:, TB:, or nothingdirection=right, down, or left to auto.
gitGraph BT:direction=down, with M204, because Plotwork draws time downward.
%%{init}%% and front matter config:Dropped, with M200. A front matter title: and accTitle become the title, and accDescr becomes the description.

What stops the conversion or changes it:

CodeWhat happenedWhat to do
M120The history cannot be replayed: a statement names a branch or commit that does not exist, makes a branch that already exists, merges a branch into itself, branches before the first commit, repeats an id, or cherry-picks a commit the branch already has. Nothing is converted.Fix the line the diagnostic points at, or convert with lenient to skip the statements that cannot be replayed.
M218With lenient, a statement was skipped and the rest was converted.Fix the Mermaid line, or add the commit by hand.
M110A line is not a gitGraph statement, or has text after its attributes.Fix the line the diagnostic points at.
M102More than 300 commits or 24 branches.Split the history into several graphs.
M220Commits with no id or message are drawn as bare dots.Give the commit an id: if the picture should say something next to it.
M221A cherry-pick named a parent:, which Plotwork has no choice of.Nothing, unless the picked commit is a merge and the parent mattered. Say which side in the commit message.
M222A commit had both an id: and a msg:, and only the id was kept.Put the text the picture should show in the id:, or in the message of the Plotwork commit.

When a directive renamed the main branch with mainBranchName, the directive is dropped, and a later checkout master is then reported as M120. The hint says so. Set main= on the header to keep the name.

See also

DocWhy
Writing diagramsThe language kind by kind, for flow, sequence, and schema diagrams
Examples to copyFinished diagrams with the prompt that gets an agent to write each
Migrating from MermaidHow a whole document converts, and every conversion code
Gantt chartsPlans over time, with tasks, dependencies, and milestones
Class diagramsClasses, their members, and the relations between them
State diagramsStates and the transitions between them
TimelinesEvents in order, grouped by period
User journeysThe steps of a person, each scored
Mind mapsA topic and the branches that grow from it
Language referenceEvery word of the language, one page for each topic
Diagram kindsThe kinds Plotwork draws and their headers