A flexible and interactive React component for visualising Git commit history. Displays a branching graph alongside commit, branch and tag metadata, with support for customised theming.
- 🌱 Responsive commit history graph
- 📝 Table with commit message and date
- 🔖 Branch and tagging information
- 🎨 Custom theming API
- 🌘 Dark and light modes
Pass a page size and number to render a window of the log. See the paging properties for more details.
This requires you to pass the entire git log history to the entries
prop of the GitLog
component.
You can pass in history from every branch in the repository to this variant of the component.
If you're managing page state yourself via something like server-side pagination from an API, then use the GitLogPaged
variant of the component.
This variant of the component only supports one branch (and any commits that merge into it from other branches).
import { GitLogPaged } from "@tomplum/react-git-log"
const { entries, currentBranch } = useYourPaginatedDataSource()
<GitLogPaged
entries={entries} // <-- Pass it a page of your git log entries
branchName='main' // <-- Pass the branch name that the entries belong to
headCommitHash='abcd1234' // <-- Tell it the SHA1 commit hash of your branches HEAD commit
/>
The implementation of the graph was designed with testing in mind.
The traditional way to draw such an image would with a HTML canvas
element. Which, while efficient (and probably easier to implement), is hard to programmatically assert its correctness.
This graph uses a grid system. Each row has N number of columns rendered in it, where N is equal to the maximum number of concurrent active branches in the given git log entry data. This means that each column is aware of its state and what needs to be drawn (A commit node, vertical line, curved merge line etc.).
Each column is responsive as its row is stretched vertically or horizontally.
-
Install the package using your preferred package manager.
Using npm
npm install @tomplum/react-git-log
Using yarn
yarn add @tomplum/react-git-log
Using pnpm
pnpm add @tomplum/react-git-log
-
Make sure that
react
andreact-dom
are installed in your project, as they are peer dependencies.npm install react react-dom
-
Render the component in your application.
The core
<GitLog />
component is using the compound component pattern and must be rendered around the subcomponents you wish to render.
Below is an example component,YourConsumer.tsx
, that is using<GitLog />
with all three available subcomponents and only the required props.
See the required component props to get started and the optional props for further configuration and theming.import { GitLog } from "@tomplum/react-git-log" const YourConsumer = () => { const { entries, currentBranch } = useYourDataSource() return ( <GitLog entries={entries} currentBranch={currentBranch}> <GitLog.Tags /> <GitLog.Graph /> <GitLog.Table /> </GitLog> ) }
Below is another example that is passing in optional props to configure the log. See the optional props for further configuration and theming.
import styles from './YourConsumer.module.scss' import { GitLog } from "@tomplum/react-git-log" const YourConsumer = () => { const { entries, currentBranch } = useYourDataSource() return ( <GitLog entries={entries} currentBranch={currentBranch}> <GitLog.Tags /> <GitLog.Graph enableResize nodeTheme='plain' showCommitNodeTooltips /> <GitLog.Table className={styles.table} timestampFormat='YYYY MM dd' /> </GitLog> ) }
The array of GitLogEntry
objects is the source of data used by the GitLog
component. It has the following properties:
Property | Type | Description |
---|---|---|
hash |
string |
The unique hash identifier of the commit. |
branch |
string |
The name of the branch this commit belongs to. |
parents |
string[] |
An array of parent commit hashes. If this is a merge commit, it will have multiple parents. If it's an initial commit, it will have none. |
message |
string |
The commit message describing the changes made in this commit. |
author |
CommitAuthor? |
Details of the user who authored the commit. |
committerDate |
string |
The date and time when the commit was applied by the committer. Typically the timestamp when the commit was finalized. |
authorDate |
string? |
(Optional) The date and time when the commit was originally authored. May differ from committerDate if the commit was rebased or amended. |
Tip
Usually you'd be sourcing this data from a backend service like a web-api, but you can extract it from the command line with the following command.
# For the entire Git log history across all branches
git log --all --pretty=format:'hash:%h,parents:%p,branch:%S,msg:%s,cdate:%cd,adate:%ad,author:%an,email:%ae' --date=iso >> git-log-all.txt
# For the entire Git log history on a given <branch-name>
git log <branch-name> --pretty=format:'hash:%h,parents:%p,branch:%S,msg:%s,cdate:%cd,adate:%ad,author:%an,email:%ae' --date=iso >> git-log.txt
This will write git-log.txt
or git-log-all.txt
in the directory where you ran the command. It can be passed to the parseGitLog.ts
function from the library to produce an array of GitLogEntry
.
Only the core parent components have required props.
Prop | Type | Description |
---|---|---|
entries |
GitLogEntry[] |
The git log entries to visualize on the graph. |
currentBranch |
string |
The name of the branch that is currently checked out. |
Prop | Type | Description |
---|---|---|
entries |
GitLogEntry[] |
The git log entries to visualize on the graph. |
branchName |
string |
The name of the branch whose entries are being rendered. |
headCommitHash |
string |
The SHA1 commit hash of the HEAD commit of the branch. |
All components have optional props to further configure the log.
Property | Type | Description |
---|---|---|
theme |
ThemeMode |
The variant of the default color theme to apply to the log. |
colours |
ThemeColours | string[] |
Array of colors used for graph elements. One per column, looping if insufficient colors are provided. |
showHeaders |
boolean |
Whether to show element names like "Graph" or "Commit message" at the top of the component. |
rowSpacing |
number |
The spacing between log rows, affecting branches, graph, and table. Default: 0 . |
urls |
GitLogUrlBuilder |
A function that returns built URLs to the remote Git provider. Enables links for commits, tags, and PRs. |
defaultGraphWidth |
number |
Default width of the graph in pixels. Can be changed dynamically if resizing is enabled. Default: 300 . |
onSelectCommit |
(commit?: Commit) => void |
Callback function when a commit is selected. commit is undefined if unselected. |
classes |
GitLogStylingProps |
CSS classes for various elements to enable custom styling. |
paging |
GitLogPaging |
Optional paging settings for displaying a subset of log entries. |
indexStatus |
GitLogIndexStatus |
Renders information about added, deleted and modified files to the index pseudo-commit entry. |
showGitIndex |
boolean |
Enables the Git index "pseudo-commit' entry above the HEAD commit. |
Property | Type | Description |
---|---|---|
theme |
ThemeMode |
The variant of the default color theme to apply to the log. |
colours |
ThemeColours | string[] |
Array of colors used for graph elements. One per column, looping if insufficient colors are provided. |
showHeaders |
boolean |
Whether to show element names like "Graph" or "Commit message" at the top of the component. |
rowSpacing |
number |
The spacing between log rows, affecting branches, graph, and table. Default: 0 . |
urls |
GitLogUrlBuilder |
A function that returns built URLs to the remote Git provider. Enables links for commits, tags, and PRs. |
defaultGraphWidth |
number |
Default width of the graph in pixels. Can be changed dynamically if resizing is enabled. Default: 300 . |
onSelectCommit |
(commit?: Commit) => void |
Callback function when a commit is selected. commit is undefined if unselected. |
classes |
GitLogStylingProps |
CSS classes for various elements to enable custom styling. |
indexStatus |
GitLogIndexStatus |
Renders information about added, deleted and modified files to the index pseudo-commit entry. |
showGitIndex |
boolean |
Enables the Git index "pseudo-commit' entry above the HEAD commit. |
Property | Type | Description |
---|---|---|
containerClass |
string |
Class name for the wrapping <div> containing branches, graph, and log table. |
containerStyles |
CSSProperties |
React CSS styling object for the wrapping container <div> . |
Prop | Type | Description |
---|---|---|
size |
number |
The number of rows to show per page. |
page |
number |
The page number to display (first page is 0 ). |
Prop | Type | Description |
---|---|---|
added |
number |
The number of added files in the git index for the checked-out branch. |
deleted |
number |
The number of deleted files in the git index for the checked-out branch. |
modified |
number |
The number of modified files in the git index for the checked-out branch. |
A function with the following signature
type GitLogUrlBuilder = (args: GitLogUrlBuilderArgs) => GitLogUrls
Returns an object of type GitLogUrls
with the following fields.
Prop | Type | Description |
---|---|---|
commit |
string |
A resolved URL to a particular commit hash on the external Git providers remote website. |
branch |
string |
A resolved URL to a branch on the external Git providers remote website. |
Property | Type | Description |
---|---|---|
showCommitNodeHashes |
boolean |
Whether to show the commit hash next to nodes in the graph. |
showCommitNodeTooltips |
boolean |
Whether to show tooltips when hovering over a commit node. |
nodeTheme |
NodeTheme |
Theme applied to commit node elements in the graph. |
nodeSize |
number |
The diameter, in pixels, of the commits nodes. Should be divisible by 2 and between 8 and 30 to render nicely. |
orientation |
normal | flipped |
The orientation of the graph. Normal renders the checked-out branch on the left, flipped on the right. |
enableResize |
boolean |
Enables horizontal resizing of the graph. Default: false . |
Prop | Type | Description |
---|---|---|
default |
string |
The default theme where nodes change their style based on their type. |
plain |
string |
All nodes look the same, except for their colours. |
Property | Type | Description |
---|---|---|
timestampFormat |
string |
A timestamp format string for DayJS to format commit timestamps. Default: ISO-8601 . |
className |
string |
A class name for the table's wrapping container. |
styles |
GitLogTableStylingProps |
A React CSS styling object for the table elements. |
Property | Type | Description |
---|---|---|
table |
CSSProperties |
Styles for the table container element. |
thead |
CSSProperties |
Styles for the table header wrapper. |
tr |
CSSProperties |
Styles for each table row. |
td |
CSSProperties |
Styles for each table cell. |
-
Clone the repository from GitHub
git clone [email protected]:TomPlum/react-git-log.git
-
Install NPM dependencies
npm install
-
Start the library TSC build watcher
npm run build:watch --workspace=@tomplum/react-git-log
-
Start the Storybook demo website dev server
npm run storybook --workspace=@tomplum/react-git-log-demo
- Many thanks to Pierre Vigier for his fantastic blog on Git algorithms and his Electron-based Git client gitamine for help and inspiration.
- This blog by Mark Lodato was useful for graph theory reference.
- And Iain Ballard for his experimental GUI SnivellingGit
- Show code in stories
- Expose custom theme object off the Theme type
- Can Zustand help us here to reduce re-renders with GitContext Provider?
- Expose component override props for things like CommitNode, CommitMessage etc.
- Straight line prop to turn curves into right angles?
- Line curve radius prop?
- Fix React docgen in Storybook controls as its not showing the JSDoc from the interface props
- Extract ThemeContext
- Mobile responsiveness for the demo site
- Add graph render strategy with a second option to use 2d rendering context (html canvas)
- Add eslint to pipeline
- Tags should be independent. Add a new optional field to the log entry / commit objects.
- Branch / Tags column is fixed. Dynamically floor it to match the max tag size currently being rendered?
- Is the SS paginated log gonna accept data from multiple branches? Because then we need the HEAD commits of each branch
- Make repository URL a function that generates the URL