The project is in a healthy, maintained state
Gives access to a file's most recent commit date, message, sha, and author/committer information.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Runtime

>= 3.7, < 5.0
~> 1.1
 Project Readme

jekyll-last-commit

Jekyll generator plugin and liquid tag to access the last commit information for a file.

Provides performant access to page.last_modified_at for Jekyll sites with very large page counts (100s+).

Use cases for a site page, document, static file, or data file:

  • accessing the last commit date
  • accessing the last committer name, email, and other metadata

Inspired by the work done at gjtorikian/jekyll-last-modified-at and aimed at improved performance. Seeks to be drop-in replacement. Uses libgit2/rugged rather than spawning a process.

Important:

  • ignores commits where a file has been renamed without content changes
  • has not been tested on Windows
  • if your git repo uses SHA-256: the version of libgit2 that rugged uses must also support SHA-256

Example Usage

The following is the last (most recent) commit from a repo:

main 5fde57927efdb2f440dd40c802687b60384e5d9d
Author:     Kip Landergren <klandergren@users.noreply.github.com>
AuthorDate: Fri Dec 16 18:30:53 2022 -0800
Commit:     Kip Landergren <klandergren@users.noreply.github.com>
CommitDate: Fri Dec 16 18:30:53 2022 -0800

add new pages to the site

Every page that was created or modified by this commit will get access to the commit’s information:

usage rendered
{{ page.last_commit.sha }} 5fde57927efdb2f440dd40c802687b60384e5d9d
{{ page.last_commit.author.name }} Kip Landergren
{{ page.last_commit.author.email }} klandergren@users.noreply.github.com
{{ page.last_commit.author.time }} 2022-12-16 18:30:53 -0800
{{ page.last_commit.committer.name }} Kip Landergren
{{ page.last_commit.committer.email }} klandergren@users.noreply.github.com
{{ page.last_commit.committer.time }} 2022-12-16 18:30:53 -0800
{{ page.last_commit.message }} add new pages to the site
{{ page.last_commit.time }} 2022-12-16 18:30:53 -0800
{{ page.last_commit.time_epoch }} 1671244253
{{ page.last_modified_at }} 2022-12-16 18:30:53 -0800
{{ page.last_modified_at | date: '%F' }} 2022-12-16
{{ page.last_modified_at_formatted }} December 16, 2022
{% last_modified_at %} December 16, 2022
{% last_modified_at %F %} 2022-12-16

Additionally, last commit info is accessible for any data file via site.data.meta[data_file] with the same API:

usage rendered
{{ site.data.meta[data_file].last_commit.sha }} 5fde57927efdb2f440dd40c802687b60384e5d9d
{{ site.data.meta[data_file].last_commit.author.name }} Kip Landergren
{{ site.data.meta[data_file].last_commit.author.email }} klandergren@users.noreply.github.com
{{ site.data.meta[data_file].last_commit.author.time }} 2022-12-16 18:30:53 -0800
{{ site.data.meta[data_file].last_commit.committer.name }} Kip Landergren
{{ site.data.meta[data_file].last_commit.committer.email }} klandergren@users.noreply.github.com
{{ site.data.meta[data_file].last_commit.committer.time }} 2022-12-16 18:30:53 -0800
{{ site.data.meta[data_file].last_commit.message }} add new pages to the site
{{ site.data.meta[data_file].last_commit.time }} 2022-12-16 18:30:53 -0800
{{ site.data.meta[data_file].last_commit.time_epoch }} 1671244253
{{ site.data.meta[data_file].last_modified_at }} 2022-12-16 18:30:53 -0800
{{ site.data.meta[data_file].last_modified_at | date: '%F' }} 2022-12-16
{{ site.data.meta[data_file].last_modified_at_formatted }} December 16, 2022

Every page has their own last commit info computed during rebuild.

Installation

Add to your Gemfile:

group :jekyll_plugins do
  gem "jekyll-last-commit"
end

and run bundle install.

Configuration

All of the following are optional:

jekyll-last-commit:
  date_format: '%F'                # default: `%B %d, %Y`
  # if a commit is not found `File.mtime` is used
  should_fall_back_to_mtime: false # default: `true`
  # enable processing of data and static files
  index_data_files: true           # default: false
  index_static_files: true         # default: false
  # information about data files is stored in a separate site.data hash
  data_files_key: 'meta'           # default: meta

The use case for should_fall_back_to_mtime is so that rendering of a file that is not yet tracked by git looks correct (e.g. a new, uncommitted blog post).

Date Format Directives

See Time#strftime documentation for available date format directives.

Examples

format example output
default (%B %d, %Y), via {{ page.last_modified_at_formatted }} December 11, 2022
{{ page.last_modified_at | date: '%c' }} Fri Dec 16 18:30:53 2022
{{ page.last_modified_at | date: '%F' }} 2022-12-16
{{ page.last_modified_at | date: '%D' }} 12/16/22
{{ page.last_modified_at | date: '%v' }} 16-DEC-2022
{{ page.last_modified_at | date: '%r' }} 06:30:53 PM
{{ page.last_modified_at | date: '%R' }} 18:30
{{ page.last_modified_at | date: '%T' }} 18:30:53

Documentation

  • page.last_commit
    • page.last_commit.author
      • page.last_commit.author.email
      • page.last_commit.author.name
      • page.last_commit.author.time
    • page.last_commit.committer
      • page.last_commit.committer.email
      • page.last_commit.committer.name
      • page.last_commit.committer.time
    • page.last_commit.message
    • page.last_commit.sha
    • page.last_commit.time
    • page.last_commit.time_epoch
  • page.last_modified_at
  • page.last_modified_at_formatted
  • site.data.meta[data_file].last_commit
  • site.data.meta[data_file].last_modified_at
  • site.data.meta[data_file].last_modified_at_formatted
  • last_modified_at

page.last_commit

Gives access to the underlying rugged commit object information.

Important: ignores commits where a file has been renamed without content changes

field type usage
author Hash object see page.last_commit.author
committer Hash object see page.last_commit.committer
message String {{ page.last_commit.message }}
sha String {{ page.last_commit.sha }}
time Time object {{ page.last_commit.time }}
time_epoch Integer {{ page.last_commit.time_epoch }}

page.last_commit.author

Information about the author of the last commit for this file.

field type usage
email String {{ page.last_commit.author.email }}
name String {{ page.last_commit.author.name }}
time Time object {{ page.last_commit.author.time }}

page.last_commit.committer

Information about the committer of the last commit for this file.

field type usage
email String {{ page.last_commit.committer.email }}
name String {{ page.last_commit.committer.name }}
time Time object {{ page.last_commit.committer.time }}

page.last_modified_at

The Time object associated with the last commit for this file.

Example default output: 2022-12-11 19:54:26 -0800

Can be formatted using a liquid date filter:

{{ page.last_modified_at | date: '%B' }}

output:

December

page.last_modified_at_formatted

The formatted string of the Time object associated with the last commit for this file. Format controlled via _config.yml.

Default format: %B %d, %Y

Example default output: December 11, 2022

Override in _config.yml via:

jekyll-last-commit:
  date_format: '%F'

If you need a per-page date format, use {{ page.last_modified_at | date: '%F }}' with whatever format string you want.

site.data.meta[data_file].last_commit

  • data_file is the name of the file within _data/, e.g. foo.json
  • .yml, .yaml, .json, .tsv, and .csv supported

See page.last_commit for further information.

site.data.meta[data_file].last_modified_at

  • data_file is the name of the file within _data/, e.g. foo.json
  • .yml, .yaml, .json, .tsv, and .csv supported

See page.last_modified_at for further information.

site.data.meta[data_file].last_modified_at_formatted

  • data_file is the name of the file within _data/, e.g. foo.json
  • .yml, .yaml, .json, .tsv, and .csv supported

See page.last_modified_at_formatted for further information.

last_modified_at

A liquid tag that renders the formatted date using either the passed date format string, what was specified in _config.yml, or the default %B %d, %Y:

<p>{% last_modified_at %}</p>
<p>{% last_modified_at %F %D %}</p>

Added solely to be drop-in replacement with gjtorikian/jekyll-last-modified-at.

Performance

Comparison made to gjtorikian/jekyll-last-modified-at on a 2017 MacBook Pro running a 3.1 GHz Quad-Core Intel Core i7

site with ~1400 pages and ~2500 commits

generation command (note: no use of ---incremental):

$ JEKYLL_ENV=development bundle exec --gemfile=./static-site/Gemfile jekyll serve --port 4001 --source ./static-site --destination /tmp/_site_development
case baseline jekyll-last-modified-at jekyll-last-commit improvement
initial generation 16.480 s 79.601 s 22.447 s ~71% improvement
subsequent generation 15.727 s 78.200 s 20.739 s ~73% improvement

How It Works

Walks the commit history until all documents and pages are matched to a commit. Falls back to File.mtime when no commit found. Runs fresh on each site generation.

FAQ

Why not just improve gjtorikian/jekyll-last-modified-at ?

See improving render performance via PATH_CACHE usage and bulk git log ... call #85 which includes two PRs more in line with that repository’s architecture and conventions.

Why not fork gjtorikian/jekyll-last-modified-at ?

Grabbing data via libgit2/rugged would be too big of a rewrite for what is a very popular plugin. If folks have performance issues getting page.last_modified_at they can safely compare their options using this!

Will this work with GitHub Pages?

I don’t think so: my understanding is that GitHub Pages performs a shallow clone. I have not tried!