Preserve meaningful per-file mtimes for Git-derived sources

Summary

For Fedora packages whose source content is derived from a Git repository, preserve meaningful and reproducible per-file modification timestamps based on Git history rather than giving files the timestamp of the source snapshot, archive generation, package preparation, or build.

For each tracked file, the proposed timestamp is the time of the most recent Git commit in which that file’s contents actually changed, following renames where possible. Pure renames and metadata-only changes such as executable-bit changes do not change the file timestamp.

A reference implementation is available at:

The initial implementation is intended as a proof of concept. This proposal does not require Fedora to adopt that particular script if the same semantics can be implemented more appropriately in existing Fedora packaging or source-generation infrastructure.

Motivation

Git stores detailed history about when the contents of individual files changed, but this information is normally lost when a repository is converted into a source archive.

For example, a Git-derived project may contain:

  • firmware-a.bin, last changed in 2026;

  • firmware-b.bin, last changed in 2024;

  • firmware-c.bin, last changed in 2021.

After creating a source snapshot or preparing an RPM build, those three files can instead receive the same or similarly recent modification timestamp. Looking at the installed filesystem therefore gives no useful indication of which files actually changed upstream.

This is particularly noticeable in packages such as linux-firmware, which contain a large collection of independently updated binary firmware files. When upgrading between versions, preserving meaningful per-file mtimes would make it possible to inspect the installed tree with ordinary Unix tools and immediately obtain useful historical information about individual files.

The same property can be useful for other packages containing large collections of independently maintained data files.

Proposed semantics

For a file derived directly from a Git working tree, set its modification time to the timestamp of the newest commit in its followed Git history that introduced new file contents.

More specifically:

  • a commit that changes the file contents updates the timestamp;

  • creation of the file establishes its initial timestamp;

  • a pure rename does not update the timestamp;

  • a mode-only change does not update the timestamp;

  • a rename combined with a content change does update the timestamp;

  • where Git can follow a rename, history before the rename is considered;

  • merge commits are handled according to whether they introduce contents not present in the relevant parent history.

The timestamp must be derived exclusively from repository history and must therefore be deterministic.

The reference implementation currently uses the Git committer timestamp by default. Whether Fedora should standardize on committer or author timestamps is explicitly open for discussion.

Benefit to Fedora

More informative installed filesystems

File mtimes once again convey useful information.

For collections such as linux-firmware, users and developers can inspect:

ls -l
find ... -newermt ...
stat ...

and obtain an approximation of when individual files were actually last changed upstream instead of when the package snapshot happened to be generated.

Easier comparison between package versions

When a package containing thousands of files is updated, unchanged files retain their historical timestamps while newly changed files naturally receive newer timestamps.

This provides a simple additional way to identify recently changed files without requiring access to the previous RPM or manually comparing package contents.

Deterministic metadata

Unlike timestamps derived from the time a build or source-generation command happened to run, timestamps derived from Git history are deterministic.

Given the same Git commit and history, independent source preparation should produce the same timestamps.

This is compatible in principle with Fedora’s reproducible-build goals.

Reproducible-build considerations

Fedora currently clamps RPM file mtimes to SOURCE_DATE_EPOCH where necessary to avoid build-time-dependent metadata.

This proposal does not suggest replacing that mechanism.

Per-file Git-derived timestamps are deterministic inputs. They would normally be earlier than or equal to the Git snapshot from which the package is produced and therefore can coexist with timestamp clamping.

The exact interaction with Fedora’s existing SOURCE_DATE_EPOCH, add-determinism, RPM macros, and source-generation tooling should be evaluated as part of this proposal.

A major requirement of any final implementation is that two builds from identical source and packaging inputs continue to produce identical timestamps.

Scope

The proposal is intended for packages whose distributed source is generated from Git history and where preserving per-file history is practical.

It should not require guessing timestamps for:

  • upstream release tarballs that do not contain Git history;

  • generated files;

  • files created during the package build;

  • patched files whose packaged contents differ from the corresponding upstream Git blob.

The appropriate integration point is open for discussion.

Possible implementations include:

  • applying the transformation while Fedora generates Git source snapshots;

  • extending Fedora source-generation tooling;

  • providing an RPM macro for packages using Git-derived sources;

  • implementing equivalent functionality in an existing packaging helper.

The reference git-file-dates utility demonstrates the proposed behavior but is not intended to predetermine the final Fedora implementation.

linux-firmware

linux-firmware is a useful example and candidate for an initial trial.

The upstream repository consists largely of firmware blobs that are updated independently over a long period of time. Preserving their individual Git-derived timestamps would make the installed /usr/lib/firmware hierarchy substantially more informative.

A trial could compare two consecutive linux-firmware builds and verify that:

  1. unchanged firmware blobs retain their historical mtimes;

  2. modified or newly added blobs receive appropriate newer mtimes;

  3. package contents remain reproducible;

  4. RPM’s existing mtime-clamping behavior does not unexpectedly destroy the useful timestamps.

Upgrade/compatibility impact

The contents and paths of packaged files would not change solely because of this proposal.

The observable change would be file modification timestamps.

Software that incorrectly depends on Git-derived package files all having the snapshot or package timestamp could observe different values. Such cases should be identified during testing.

How to test

A prototype implementation should first be applied to selected Git-derived packages, particularly linux-firmware.

Testing should include:

  • two independent builds from identical inputs produce identical RPM metadata;

  • pure file renames preserve the previous content timestamp;

  • mode-only changes preserve the previous content timestamp;

  • actual content modifications update the timestamp;

  • symlinks are handled without modifying their targets;

  • unusual valid Git filenames are handled safely;

  • merge histories behave according to the documented semantics;

  • RPM mtime clamping does not replace valid historical timestamps unnecessarily.

For linux-firmware, compare the installed file mtimes before and after consecutive upstream snapshots and verify that the files identified as recently modified correspond to actual upstream Git changes.

Contingency plan

If no sufficiently general integration point can be found, no system-wide behavior needs to change.

The reference implementation can still be used experimentally by individual packages, and linux-firmware could be considered separately if its maintainers find the behavior useful.

Open questions

  1. Should the standardized timestamp be the Git author date or committer date?

  2. At what point in Fedora’s source/package pipeline should timestamps be restored?

  3. Should this initially be opt-in through an RPM macro or source-generation option?

  4. Should only files installed unchanged from an upstream Git blob be eligible?

  5. How should histories unavailable because of shallow source snapshots be handled?

  6. Is linux-firmware suitable as an initial package for evaluating the approach?

You may want to talk to the packaging comitte about this if you wish to have a new guideline to do this enacted. Making sure you're not a bot!

For linux-firmware you might file a bug (or better a PR that does this) and see what they think. I don’t think there’s anything standing in the way of them implementing this if they choose to.

Why not?


How does this idea handle files that are patched downstream?