我理解default Git behaviour of updating the modification time every time it changes a file,但有时我想恢复文件的原始修改时间。
有没有办法告诉Git这样做?
(例如,在处理大型项目时,我对configure.ac
进行了一些更改,发现autotools不能在我的系统上运行,并希望将configure.ac
恢复为其原始内容和修改时间,以便make
不会尝试使用我的自动工具更新configure
。)
答案 0 :(得分:17)
使用
将文件列表的修改时间恢复到上次提交的作者日期gitmtim(){ local f;for f;do touch -d @0`git log --pretty=%at -n1 -- "$f"` "$f"; done;}; gitmtim configure.ac
但它不会递归地更改目录。
如果您想要更改整个工作树,例如在新的克隆或结帐后,您可以尝试
git log --pretty=%at --name-status --reverse | perl -ane '($x,$f)=@F;next if !$x;$t=$x,next if !defined($f)||$s{$f};$s{$f}=utime($t,$t,$f),next if $x=~/[AM]/;'
注意:我在builtin / clone.c中使用了utime并没有匹配。
答案 1 :(得分:16)
Git没有这样做。就像链接的常见问题解答说的那样,它会破坏使用基于时间戳的依赖性分析工具,如 make 。
想想如果将旧时间戳应用于从“旧”提交中检出的文件会发生什么:
但是,如果你真的想要它,所有信息都在那里。您可以编写自己的工具来完成它。
在您的情况下,只需使用touch -r configure configure.ac
之类的内容重置仅configure.ac
的修改时间,(或使用touch configure
及时配置前提。)
如果你想练习阅读C代码,这实际上是一个简单的“读者练习”。更改时间戳的功能是utime
或utimes
。搜索代码以获取这些函数的使用(提示:git.git clone中的git grep utime
)。如果有一些用途,请分析代码路径以找出更新时间戳的时间。
答案 2 :(得分:6)
我认为'正确'修复是实际比较每个输入文件的SHA1,看它是否从上一次构建中更改。
这是很多工作,但是我已经开始尝试创建一个概念证明(仍处于早期阶段)。除了确定正确的构建步骤之外,它还旨在为以后的取证创建输入文件的审核列表。
请参阅http://github.com/alecthegeek/gitbuilding - 这是基于我几年前与SVN所做的类似的事情
答案 3 :(得分:6)
以下shell脚本应该适用于任何POSIX兼容系统,以设置所有跟踪文件(和目录)的修改和访问时间戳。我可以确定的唯一缺点是它很慢但是对我的用例来说很好(在生成发布档案时设置正确的日期)。
rev=HEAD
for f in $(git ls-tree -r -t --full-name --name-only "$rev") ; do
touch -d $(git log --pretty=format:%cI -1 "$rev" -- "$f") "$f";
done
答案 4 :(得分:2)
这个工具应该可以解决问题。它将mtimes更新为作者时间和atimes到提交者时间。它可以作为结账钩子。
使用DEBUG = 1运行,让它准确地告诉你它正在做什么。
另请注意,它不使用任何模块,只使用基本的perl,因此应该在任何地方运行。
str_extract(as.character(dt), "(?<=\\s)(\\d{1,2})(?=:)")
# [1] "11" "9"
答案 5 :(得分:1)
我们在工作中遇到了同样的问题,并成功使用了Danny Lin的git-store-meta perl脚本。
它肯定解决了你问题中指出的问题。
答案 6 :(得分:1)
https://github.com/MestreLion/git-tools
sudo apt install git-restore-mtime
cd [repo]
git restore-mtime
答案 7 :(得分:1)
在这里给我两分钱。
它需要@stefanct提出的大部分内容,但是在实现类似脚本时,我只是添加了并行功能。
对于我的情况(1000个文件),我从60秒缩短到15秒来并行执行操作。
#!/bin/bash
change_date() {
local dd=`git log -1 HEAD --pretty="%ci" -- $1`
if [ -z "$dd" ];
then echo "$1 is not versionned";
else touch -d "$dd" $1;
fi
}
#list_of_files = find .
list_of_files=`git ls-tree -r -t --full-name --name-only HEAD`
for f in $list_of_files;do
if test "$(jobs | wc -l)" -ge 16; then
wait
fi
{
change_date $f;
} &
done
wait
您可以通过更改此行来调整允许的并行作业数
test "$(jobs | wc -l)" -ge 16
答案 8 :(得分:-1)
我写了一个小工具,允许你在使用Git进行合并或结账后恢复目录中文件的修改时间。
https://bitbucket.org/chabernac/metadatarestore/wiki/Home
在执行提交,签出或合并时,将该工具用作Git中的钩子。有关Git挂钩的信息,请参阅 8.3 Customizing Git - Git Hooks 。您可以在项目的.git/hooks
目录中找到Git挂钩的示例。