release: v2.2.0 - change @Last modified by only when the file's content… - #129
Merged
Merged
Conversation
@last modified by now records whoever last edited the file's content (everything outside the header), not whoever last ran fix-headers. The content counts as edited when the file's body, with the header taken out, differs from its body at git HEAD, or when HEAD does not have the file (new, untracked or ignored). Header rewrites fix-headers makes on its own (date format, epoch repair, fixCreatedDate, time zone conversion, frame, spacing, margin, @Project/@Filename/@copyright) still restamp @last modified time but keep the recorded editor. Outside a git work tree content edits cannot be detected and the recorded editor is kept. A content edit by the editor already recorded is restamped once when the recorded time is older than the file's last commit, so repeat edits move the time without making re-runs churn. @Author/@Email stay the original author unless forceAuthorUpdate is set. forceLastModifiedAuthorUpdate keeps its previous meaning (write the run identity on every file) and is documented as not needed for normal use. Closes #127
Contributor
Author
🔒 Dependency Review
|
Contributor
Author
📦 Bundle size unchanged
📊 Generated by |
Shinrai
approved these changes
Oct 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
@cldmv/fix-headers v2.2.0 Changelog
Release Date: October 2026
Release Type: Minor
Branch:
release/2.2.0Overview
Version 2.2.0 changes what
@Last modified bymeans. It now names whoever last edited the file's content, the part of the file outside the header, instead of whoever last ran fix-headers. A run that only rewrites a header (a date format conversion, a corrected@Project, new spacing or margin) keeps the recorded editor, so running the tool never claims other people's files.@Authorwas already the original author and stays that way unlessforceAuthorUpdateis set.No option was removed, the
fixHeadersAPI and the header format are unchanged, and@Last modified timeis still restamped whenever a header is rewritten. See the upgrade notes for the one behaviour change that can show up in an existing setup.✨ Features
@Last modified byfollows content edits, not header rewrites (#128, closes #127)Before, any run that changed a header could write the identity detected for that run into
@Last modified by, and withforceLastModifiedAuthorUpdateit did so on every file. With a shared config that forces the author fields, whoever ran the tool became the last editor of every file it touched, including files they never opened.fix-headers now decides whether a file's content was edited by comparing it with the file at git
HEAD. The header is taken out of both versions, along with the blank lines after it, and what is left is compared:@Author@Last modified by@Last modified timeHEAD, header rewrittenHEADHEAD(new, untracked or ignored, or no commits yet)normalizeDateFormat), an epoch repair,@Date(fixCreatedDate), a time zone conversion, the frame,spacingandmargin, and the@Project,@Filenameand@Copyrightvalues all rewrite the header without changing who last edited the file.@Last modified timestill moves, because the header did.authorName/authorEmail, or git as described underuseGpgSignerAuthor). A missing field is filled with it in every case, and a file with no header gets it in both fields. Adding a header to a committed file is not a content edit, so a later header-only run by someone else keeps whoever was recorded then.HEADand the recorded time is older than the file's last commit, the edit has not been stamped yet, so@Last modified timeis restamped even though the editor is unchanged. Once stamped, the time is newer than the last commit and running fix-headers again changes nothing until the next commit.forceLastModifiedAuthorUpdatekeeps its meaning (write the run identity as@Last modified byon every file, edited or not), andforceAuthorUpdatestill replaces an existing@Author/@Email. With content-edit detection,forceLastModifiedAuthorUpdateis no longer needed for normal use, and the README says so. The--helptext for both force flags is reworded to match what they do.issuesresult follows the same rule. ThelastModifiedByName/lastModifiedByEmailentries appear only when the value that would be written really differs from the existing header, which now depends on whether the content was edited.The check compares the working tree with
HEAD, so run fix-headers before committing (a pre-commit hook, ornpm run fix:headersbeforegit commit). Content committed without a run is not detected later, because by then the body matchesHEAD. The README gains an Author and last modified section with the same table and rules.🧪 Tests
tests/last-modified-content-edit.test.vitest.mjscovers header-only rewrites that keep the editor, body edits that take the run identity,@Authorpreserved for a different runner,forceAuthorUpdatestill replacing it, untracked and new files, files outside a git work tree, and the one-time restamp of a repeat edit.tests/core-edge.test.vitest.mjsandtests/sample-output.test.vitest.mjsare updated for the newissuesoutput. Coverage stays at 100%.📚 Documentation
--force-author-update/--force-last-modified-author-updateCLI and API entries (#128).🔧 Dependencies
No dependency updates.
ignore, the only runtime dependency, is unchanged.Upgrade notes
@Last modified bycan differ from before after a run. A header-only rewrite no longer writes the run's identity into it, and a content edit now does. A config that setsforceLastModifiedAuthorUpdatekeeps the old behaviour (the run identity on every file) and can drop that option once its files carry the right editor.HEAD, so a hook or script that runs fix-headers after the commit will see an unchanged body and keep the recorded editor.@Last modified timemoves when a header is rewritten.--dry-run --diff --verbose.👥 Contributors
Avg: 100.0% ·
e643b86· Node lts/*Co-authored-by: Shinrai Shinrai@users.noreply.github.com