如何让Git提交时间采用文件最新mtime?求推荐工具及解惑
为什么Git不支持
--date=files功能? Git的核心设计逻辑里,提交时间(包括Author Date和Committer Date)记录的是「提交操作发生的时间」,而非文件实际修改的时间。这是因为提交是一个明确的版本控制节点,代表你正式将修改纳入版本历史的动作,和文件在本地编辑完成的时间是两个独立的概念——Git要保证提交历史的客观性,避免引入模糊的「修改完成时间」这类主观定义的时间点。
另外,Git的暂存区(index)并没有存储文件的修改时间(mtime)信息,它只记录文件的哈希值、权限等元数据。要获取文件的mtime,只能从本地工作区读取,但工作区的文件可能在git add之后被再次修改,这会导致获取到的mtime并非你当初完成修改的时间,这种不确定性是Git官方不愿意内置该功能的重要原因——官方不想提供一个可能产生不准确结果的原生参数。
实现该功能的方案
1. 自定义Shell脚本(最灵活可控)
你可以自己写一个脚本,自动提取暂存区文件的最新mtime,再传递给git commit命令。以下是适配Linux/macOS的脚本示例:
#!/bin/bash # 获取暂存区的所有文件路径 staged_files=$(git diff --cached --name-only) if [ -z "$staged_files" ]; then echo "Error: No files are staged for commit." exit 1 fi max_mtime=0 # 遍历暂存文件,找出最大的mtime时间戳 for file in $staged_files; do # Linux 系统使用 stat -c %Y,macOS 替换为 stat -f %m current_mtime=$(stat -c %Y "$file") if [ "$current_mtime" -gt "$max_mtime" ]; then max_mtime=$current_mtime fi done # 转换为Git可识别的日期格式 commit_date=$(date -d @$max_mtime "+%Y-%m-%d %H:%M:%S %z") # 执行提交,传递所有原命令参数(比如-m "提交信息") git commit --date="$commit_date" "$@"
使用方法:
- 将脚本保存为
git-commit-date-from-files - 执行
chmod +x git-commit-date-from-files赋予执行权限 - 将脚本所在目录加入系统
PATH,或者直接放在Git的命令目录(比如~/.local/bin) - 之后提交时用
git commit-date-from-files -m "modified a and b"替代原git commit命令
注意:
这个脚本读取的是当前工作区文件的mtime,如果git add后你又修改了文件,拿到的会是最新修改时间而非当初完成工作的时间。所以建议你修改完文件后立刻执行git add,且提交前不要改动已暂存的文件。
2. Git Hook 自动设置提交时间
如果你不想每次都用自定义命令,可以用pre-commit钩子自动处理:
- 在仓库的
.git/hooks目录下创建pre-commit文件 - 写入以下内容(逻辑和脚本类似):
#!/bin/bash staged_files=$(git diff --cached --name-only) if [ -z "$staged_files" ]; then exit 0 fi max_mtime=0 for file in $staged_files; do current_mtime=$(stat -c %Y "$file") [ "$current_mtime" -gt "$max_mtime" ] && max_mtime=$current_mtime done commit_date=$(date -d @$max_mtime "+%Y-%m-%d %H:%M:%S %z") # 设置Git的环境变量,覆盖默认提交时间 export GIT_AUTHOR_DATE="$commit_date" export GIT_COMMITTER_DATE="$commit_date"
- 执行
chmod +x .git/hooks/pre-commit
之后每次git commit都会自动用暂存文件的最新mtime作为提交时间。
内容的提问来源于stack exchange,提问作者Lutz Prechelt
相关产品推荐
相关产品推荐

