After my previous attempt to get published date and the edited date of the post that lives entirely in the git somehow reached the dead end because I could not reliably find out how to handle renames, I have finally found a working way.

  • Start by preparing a file with a git history, containing a rename
git log --follow --name-status renamed-blog-post.md

Note the follow parameter, which helps producing output that might look like this

commit 48831b93a453f7c88838620509ccae6f9feaf851 (HEAD -> master)
Author: Peter Babič <peter@peterbabic.dev>
Date:   Thu Dec 3 22:07:31 2020 +0100

    add additional sentence to to blog post

M       renamed-blog-post.md

commit f6732cbfb7d787f62190b983f73901dd05f749e5
Author: Peter Babič <peter@peterbabic.dev>
Date:   Thu Dec 3 21:51:19 2020 +0100

    insert a chapter into post

M       renamed-blog-post.md

commit 70955f7c2ecdec469226f8226a10ad313497972e
Author: Peter Babič <peter@peterbabic.dev>
Date:   Thu Dec 3 21:49:27 2020 +0100

    rename blog post

R100    blog-post.md    renamed-blog-post.md

commit 86b45b4a5a7aee4726834e70f0ede60ac961abc5
Author: Peter Babič <peter@peterbabic.dev>
Date:   Thu Dec 3 20:54:27 2020 +0100

    insert blog post file to track

A       blog-post.md

The goal is to have the Dates accessible in the Typescript

  • Install required packages
npm install gitlog date-fns
  • Install required dev packages
npm install -D typescript ts-node-dev
  • The minimal tsconfig.json that worked for me
{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "lib": ["ES2017", "DOM"]
  }
}
  • The minimal code for server.ts looks like this
import gitlog, { GitlogOptions } from "gitlog"

const options: GitlogOptions = {
  repo: ".",
  fields: ["subject", "authorName", "authorDate"] as const,
  branch: "--follow",
  file: "renamed-blog-post.md",
}

gitlog(options).forEach(entry => console.log(entry))

The branch: "--follow" is a hack unfortunately - as a time of writing, the gitlog is version 4.0.3 and does not support follow parameter directly. Infecting the code however reveals that branch allows to sneak in any text, not just branch names, because there are no sanitization there.

  • Running the script
npx ts-node-dev server.ts

Produces desired results, the authorDate property is easy to parse

{
  status: [ 'M' ],
  files: [ 'renamed-blog-post.md' ],
  subject: 'add additional sentence to to blog post',
  authorName: 'Peter Babič',
  authorDate: '2020-12-03 22:07:31 +0100'
}
{
  status: [ 'M' ],
  files: [ 'renamed-blog-post.md' ],
  subject: 'insert a chapter into post',
  authorName: 'Peter Babič',
  authorDate: '2020-12-03 21:51:19 +0100'
}
{
  status: [ 'R100', 'D' ],
  files: [ 'renamed-blog-post.md', 'blog-post.md' ],
  subject: 'rename blog post',
  authorName: 'Peter Babič',
  authorDate: '2020-12-03 21:49:27 +0100'
}
{
  status: [ 'A' ],
  files: [ 'blog-post.md' ],
  subject: 'insert blog post file to track',
  authorName: 'Peter Babič',
  authorDate: '2020-12-03 20:54:27 +0100'
}

The parsing steps could then include

  1. Reverse the entries
  2. Entry with the A status hold date when the file was created (post was published)
  3. The last entry with the M status holds the date of the last edit
  4. If the last entry holds the R status and its score is lower than 100, this means that file was renamed and edited, now loading the last edit date

The details about the score from the git diff documentation

Status letters C and R are always followed by a score (denoting the percentage of similarity between the source and target of the move or copy). Status letter M may be followed by a score (denoting the percentage of dissimilarity) for file rewrites.

Done!

Sources are available in the repository