使用原始创build/修改的时间戳签出旧文件
有什么方法可以知道或获取原始创build/修改的时间戳吗? 谢谢。
我相信在Git数据库中logging的唯一时间戳是作者和提交时间戳。 我没有看到Git修改文件的时间戳以匹配最近的提交的选项,这是合理的,这不会是默认行为(因为如果它是,Makefiles将无法正常工作)。
您可以编写一个脚本来将文件的修改date设置为最近一次提交的时间。 它可能看起来像这样:
IFS=" " for FILE in $(git ls-files) do TIME=$(git log --pretty=format:%cd -n 1 --date=iso -- "$FILE") TIME=$(date -j -f '%Y-%m-%d %H:%M:%S %z' "$TIME" +%Y%m%d%H%M.%S) touch -m -t "$TIME" "$FILE" done
YES ,metastore或git-cache-meta 可以存储这样的(元)信息! Git本身,没有第三方工具,不能。 Metastore或git-cache-meta可以存储文件的任何文件元数据。
这是devise的,因为metastore或git-cache-meta是为了这个目的而devise的,同时也支持备份工具和同步工具。
(对不起,Jakub的答案只是一个有趣的旋转)
不 ,Git根本不存储这样的(元)信息 ,除非你使用像Metastore或git-cache-meta这样的第三方工具。 唯一存储的时间戳是创build时间补丁/更改(作者时间),创build时间提交(提交时间)。
这是devise,因为Git是版本控制系统,而不是备份工具或同步工具。
这个python脚本可能会有所帮助:对于每个文件,应用文件被修改的最近提交的时间戳:
- 核心function ,使用–help,debugging消息。 可以在工作树内的任何地方运行
- 全面的野兽 ,有很多select。 支持任何存储库布局。
下面是一个真正的脚本版本。 对于实际使用,我强烈build议使用上面更强大的版本之一:
#!/usr/bin/env python # Bare-bones version. Current dir must be top-level of work tree. # Usage: git-restore-mtime-bare [pathspecs...] # By default update all files # Example: to only update only the README and files in ./doc: # git-restore-mtime-bare README doc import subprocess, shlex import sys, os.path filelist = set() for path in (sys.argv[1:] or [os.path.curdir]): if os.path.isfile(path) or os.path.islink(path): filelist.add(os.path.relpath(path)) elif os.path.isdir(path): for root, subdirs, files in os.walk(path): if '.git' in subdirs: subdirs.remove('.git') for file in files: filelist.add(os.path.relpath(os.path.join(root, file))) mtime = 0 gitobj = subprocess.Popen(shlex.split('git whatchanged --pretty=%at'), stdout=subprocess.PIPE) for line in gitobj.stdout: line = line.strip() if not line: continue if line.startswith(':'): file = line.split('\t')[-1] if file in filelist: filelist.remove(file) #print mtime, file os.utime(file, (mtime, mtime)) else: mtime = long(line) # All files done? if not filelist: break
所有版本parsing由单个git whatchanged
命令生成的完整日志,比每个文件更快的跳跃数百倍。 对于git(24000提交,2,500个文件)和linux内核(40,000个文件,30万个提交)不到1分钟,
这是他在Ubuntu上(我的date(1)没有OSX的“-j”标志)欺骗我
for FILE in $(git ls-files) do TIME=$(git log --pretty=format:%cd -n 1 --date=iso $FILE) TIME2=`echo $TIME | sed 's/-//g;s/ //;s/://;s/:/\./;s/ .*//'` touch -m -t $TIME2 $FILE done
请参阅https://github.com/przemoc/metastore
它包含在debain repo中,只是apt-get install metastore
。
我一直在用git和文件时间戳冲突已经有一段时间了。
testing了你的一些想法,并制作了我自己非常庞大的前辈/内存繁重的脚本,直到我发现(在一些git wiki上)一个Perl脚本,几乎是我想要的。 https://git.wiki.kernel.org/index.php/ExampleScripts
而我想要的是能够保留基于提交date的文件的最后修改。
所以经过一些调整后,脚本可以在2-3分钟左右的时间内改变200k文件的创build和修改date。
#!/usr/bin/perl my %attributions; my $remaining = 0; open IN, "git ls-tree -r --full-name HEAD |" or die; while (<IN>) { if (/^\S+\s+blob \S+\s+(\S+)$/) { $attributions{$1} = -1; } } close IN; $remaining = (keys %attributions) + 1; print "Number of files: $remaining\n"; open IN, "git log -r --root --raw --no-abbrev --date=raw --pretty=format:%h~%cd~ |" or die; while (<IN>) { if (/^([^:~]+)~([^~]+)~$/) { ($commit, $date) = ($1, $2); } elsif (/^:\S+\s+1\S+\s+\S+\s+\S+\s+\S\s+(.*)$/) { if ($attributions{$1} == -1) { $attributions{$1} = "$date"; $remaining--; utime $date, $date, $1; if ($remaining % 1000 == 0) { print "$remaining\n"; } if ($remaining <= 0) { break; } } } } close IN;
假设你的存储库不会有10k +文件,这应该需要几秒钟的时间来执行,所以你可以把它钩到checkout,pull或者其他的git基本钩子上。
这是我的解决scheme,考虑到包含空格的path:
#! /bin/bash IFS=$'\n' list_of_files=($(git ls-files | sort)) unset IFS for file in "${list_of_files[@]}"; do file_name=$(echo $file) ## When you collect the timestamps: TIME=$(date -r "$file_name" -Ins) ## When you want to recover back the timestamps: touch -m -d $TIME "$file_name" done
请注意,这不需要git log
报告的时间,这是系统报告的时间。 如果你想要自提交文件以来的时间,使用git log
解决scheme,而不是date -r
原生git没有这个function,但是可以通过钩子脚本或第三方工具来实现。
我已经尝试了metastore
。 这是非常快的,但我不喜欢需要安装,元数据不以纯文本格式存储。 git-cache-meta
是我尝试过的一个简单的工具,但是对于大型回购(对于数以万计的文件进行回购,更新元数据文件需要花费几分钟的时间),速度非常慢,并且可能具有跨平台兼容性问题。 setgitperms
和其他方法也有自己的缺点,我不喜欢。
最后我为这个工作做了一个钩子脚本: git-store-meta 。 它具有非常轻的依赖性 (* nix shell, sort
和perl
,这是git所需要的,可选的是chown
, chgrp
和touch
),这样就不需要为可以运行git的平台安装任何额外的function具有成千上万个文件的repo,更新元数据文件需要10秒钟,虽然创build时间更长),以纯文本格式保存数据,以及“保存”或“加载”的元数据是可定制的 。
它对我来说工作得很好。 如果你对Metastore,git-cache-meta和其他方法不满意,试试这个。
对于Windows环境,我在Delphi 10.1柏林中编写了一个小的(快速且肮脏的)EXE,它将源树中的所有文件date收集到文件.gitfilattr中,并且可以将它们再次应用于检查我们的源代码树。
当然,我在GitHub中分享代码:
https://github.com/michaschumann/gitfiledates/blob/master/gitFileDates.dpr
我在基于GitLab跑步者的构build系统中使用它。
使用GNU工具。
s=$(git ls-files | wc -l); git ls-files -z | xargs -0 -I{} -n1 bash -c \ "git log --date=format:%Y%m%d%H%M.%S '--pretty=format:touch -m -t %cd \"{}\"%n' -n1 -- {}"| pv -l -s$s | parallel -n1 -j8 967 0:00:05 [ 171 /s] [=====================================> ] 16%
。
$ git --version ; xargs --version | sed 1q ; ls --version | sed 1q; parallel --version | sed 1q; pv --version | sed 1q; sh --version | sed 1q git version 2.13.0 xargs (GNU findutils) 4.6.0 ls (GNU coreutils) 8.25 GNU parallel 20150522 pv 1.6.0 - Copyright 2015 Andrew Wood <andrew.wood@ivarch.com> GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)