Expandera RCS nyckelord i Git

Ursprungligen publicerad i min blogg 2009-08-11. Uppdaterad 2024-02-25. Observera att informationen kan vara föråldrad.
Tillbaka till översikten.


Ett vanligt migreringsproblemen med Git är att Git inte har stöd för expandering av RCS-liknande nyckelord. Flera andra system har stöd för att till exempel sätta in den senaste incheckningstiden i ett dokument genom att man lägger in en platshållare på formen $Date$. Git gör det inte, och man anser inte heller att man skall göra det.

Jag förstår argumenten de framför och i de allra flesta fall kan jag leva utan den här funktionen. Men just när det gäller att ha min vävplats i Git så vill jag gärna ha den. De allra flesta av mina sidor har en datumstämpling nederst på sidan som beskriver när sidan sist uppdaterades och jag är allt för glömsk för att komma ihåg att uppdatera den manuellt. Jag försökte mig först på en metod som använde sig av filter, men det fungerade inte så bra. Efter en del testande så har jag dock löst det genom att använda mig av en så kallad pre-commit-krok:

#!/bin/bash -e

# Find base commit
if git-rev-parse --verify HEAD >/dev/null 2>&1
then
  against=HEAD
else
  # Initial commit: diff against an empty tree object
  against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi

# Run Perl in non-UTF-8 mode
unset PERL5OPTS
unset PERL_UNICODE

# Set up Date substitution
export NOW=$(date +"%Y-%m-%d %H:%M:%S")
for file in $(git diff-index --cached --diff-filter=AM --name-only $against); do
  if git check-attr datereplace -- "$file" | grep 'datereplace: true' > /dev/null; then
    if test -f "$file"; then
      perl -w -i -e 'my $now = $ENV{"NOW"};
$now =~ s/[^-:0-9 ]//g;
while (<>)
{
 if (/\$Date:?[^\$]*\$/)
 {
   s/\$Date:?[^\$]*\$/\$Date: ${now} \$/;
 }
 print
}' "$file"
      git update-index --add "$file"
    fi
  fi
done

exit 0

Det kan helt säkert göras snyggare, men det här fungerar tillfredsställande för det jag vill använda det till, så jag är nöjd med det och har använt det sedan 2009. Det huvudsakliga problemet med den här lösningen är att det inte går att checka in delar av filer, eftersom skriptet alltid skriver över filer i sin helhet. Det har dock inte varit något problem för min webbplats.