AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 401437
Accepted
Eric Bréchemier
Eric Bréchemier
Asked: 2012-06-23 11:41:19 +0800 CST2012-06-23 11:41:19 +0800 CST 2012-06-23 11:41:19 +0800 CST

如何检索 Git 存储库中所有文件的最后修改日期

  • 772

我知道如何检索 Git 存储库中单个文件的最后修改日期:

git log -1 --format="%ad" -- path/to/file

是否有一种简单有效的方法可以对存储库中当前存在的所有文件执行相同的操作?

git
  • 7 7 个回答
  • 70262 Views

7 个回答

  • Voted
  1. Best Answer
    Andrew M.
    2012-06-23T12:10:17+08:002012-06-23T12:10:17+08:00

    一个简单的答案是遍历每个文件并显示其修改时间,即:

    git ls-tree -r --name-only HEAD | while read filename; do
      echo "$(git log -1 --format="%ad" -- $filename) $filename"
    done
    

    这将产生如下输出:

    Fri Dec 23 19:01:01 2011 +0000 Config
    Fri Dec 23 19:01:01 2011 +0000 Makefile
    

    显然,您可以控制它,因为此时它只是一个 bash 脚本——所以请随意自定义您的内容!

    • 101
  2. William Entriken
    2016-05-04T07:35:34+08:002016-05-04T07:35:34+08:00

    这种方法也适用于包含空格的文件名:

    git ls-files -z | xargs -0 -n1 -I{} -- git log -1 --format="%ai {}" {}
    

    示例输出:

    2015-11-03 10:51:16 -0500 .gitignore
    2016-03-30 11:50:05 -0400 .htaccess
    2015-02-18 12:20:26 -0500 .travis.yml
    2016-04-29 09:19:24 +0800 2016-01-13-Atlanta.md
    2016-04-29 09:29:10 +0800 2016-03-03-Elmherst.md
    2016-04-29 09:41:20 +0800 2016-03-03-Milford.md
    2016-04-29 08:15:19 +0800 2016-03-06-Clayton.md
    2016-04-29 01:20:01 +0800 2016-03-14-Richmond.md
    2016-04-29 09:49:06 +0800 3/8/2016-Clayton.md
    2015-08-26 16:19:56 -0400 404.htm
    2016-03-31 11:54:19 -0400 _algorithms/acls-bradycardia-algorithm.htm
    2015-12-23 17:03:51 -0500 _algorithms/acls-pulseless-arrest-algorithm-asystole.htm
    2016-04-11 15:00:42 -0400 _algorithms/acls-pulseless-arrest-algorithm-pea.htm
    2016-03-31 11:54:19 -0400 _algorithms/acls-secondary-survey.htm
    2016-03-31 11:54:19 -0400 _algorithms/acls-suspected-stroke-algorithm.htm
    2016-03-31 11:54:19 -0400 _algorithms/acls-tachycardia-algorithm-stable.htm
    ...
    

    输出可以通过添加| sort到末尾按修改时间戳排序:

    git ls-files -z | xargs -0 -n1 -I{} -- git log -1 --format="%ai {}" {} | sort
    
    • 36
  3. Mikko Rantalainen
    2020-08-30T02:52:37+08:002020-08-30T02:52:37+08:00

    这是另一种方式:

    git ls-tree -r --name-only HEAD -z | TZ=UTC xargs -0n1 -I_ git --no-pager log -1 --date=iso-local --format="%ad _" -- _
    

    对先前给出的答案的更改:

    • 正确处理文件名中的空格。
    • uses ls-treeinstead of ls-filesand as such 可以与裸存储库一起使用。
    • 始终以类似 ISO 8601 的格式打印零偏移量 (UTC)。 | sort通过附加到命令,这也允许对接近夏令时更改(或来自不同时区的提交)的时间进行正确排序。
    • 不需要使用子外壳,因此性能应该尽可能好。

    请注意,这不能正确处理带有%字符的文件名。有关正确处理文件名中所有字符的更详尽的命令,请参见下文。

    请注意,此命令仍然非常慢,因为 Git 并未真正存储我们正在查找的信息。从技术上讲,这会遍历所有文件,过滤整个项目历史中对任何给定文件的所有更改,获取最新提交并打印其作者时间戳。结果,显示的时间与更改每个文件的最后一次提交相匹配。如果文件在进行原始提交时在磁盘上具有不同的时间戳,则它不会存储在 Git 存储库中的任何位置,因此如果没有外部数据源,它永远无法恢复。

    该脚本发出的时间戳只是一个与提交时间匹配的模拟版本,而不是文件的真实时间戳,因为 Git 不将文件时间戳视为数据。这是因为 Git 的这一部分是由 Linus Torvalds 设计的,他坚信磁盘上的文件时间戳应该匹配它在磁盘上被修改的时间,而不是文件在历史上被修改时在其他人磁盘上的时间戳. Git 只为已提交的提交存储一个时间戳,并为提交包含在 DAG 中的那一刻存储另一个时间戳。如果提交作者和将提交应用于版本历史记录的人是两个不同的人,这可能会有所不同,这在 Linux 内核开发中经常发生。

    如果你想将文件系统修改时间设置为每个文件的最后作者提交时间,你可以做这样的事情来处理文件名中的特殊字符(添加| bash自动执行所有发出的命令):

    git ls-tree -r --name-only HEAD -z | TZ=UTC xargs -0n1 git --no-pager log -1 --date=iso-local --name-only -z --format="format:%ad" | perl -npe "INIT {\$/ = \"\\0\"} s@^(.*? .*?) .*?\n(.*)\$@\$date=\$1; \$name=\$2; \$name =~ s/'/'\"'\"'/sg; \"TZ=UTC touch -m --date '\$date' '\$name';\n\"@se"
    

    尽管这比上面的命令复杂得多,但该命令的性能应该与第一个命令大致相同,因为性能受到搜索每个文件的最后修改时间而不是实际设置修改时间的限制。请注意,这会将时间转换为 UTC,使用空分隔文件并在设置时间时使用 UTC 时区为文件系统上的每个文件重置正确的时间戳。

    如果输出顺序不是很重要,您可以通过添加标志来提高此命令的性能,以将-P $(nproc)Gitxargs扩展到所有 CPU,使命令看起来像...TZ=UTC xargs -0n1 -P $(nproc) git...。

    如果您更喜欢提交者时间而不是作者日期,请在上面的命令行中使用%cdinstead of 。%ad

    • 11
  4. Kevin G.
    2016-06-22T10:15:19+08:002016-06-22T10:15:19+08:00

    这是Andrew M.'s answer的一个小调整。(我无法评论他的回答。)

    将第一个 $filename 括在双引号中,以支持带有嵌入空格的文件名。

    git ls-tree -r --name-only HEAD | while read filename; do
        echo "$(git log -1 --format="%ad" -- "$filename") $filename"
    done
    

    示例输出:

    Tue Jun 21 11:38:43 2016 -0600 subdir/this is a filename with spaces.txt
    

    我很欣赏 Andrew 的解决方案(基于ls-tree)适用于裸存储库!(使用ls-files的解决方案并非如此。)

    • 7
  5. Andrew Murphy
    2020-10-01T10:22:33+08:002020-10-01T10:22:33+08:00

    如果您尝试在大型存储库上设置文件修改时间,请查看Git 工具。已经是一个包了。

    sudo apt install git-restore-mtime
    cd repo
    git restore-mtime
    

    它使用git whatschangedrather than git log,这在大型存储库上要快得多。

    • 5
  6. James Skemp
    2019-10-18T07:39:57+08:002019-10-18T07:39:57+08:00

    对于我们这些使用 Windows 和 PowerShell 的人,Andrew M 的答案是计算机可读的调整:

    git ls-tree -r --name-only HEAD | ForEach-Object { "$(git log -1 --format="%ai" -- "$_")`t$_" }
    

    示例输出:

    2019-05-07 12:00:37 -0500   .editorconfig
    2016-07-13 14:03:49 -0500   .gitattributes
    2019-05-07 12:00:37 -0500   .gitignore
    2018-02-03 22:01:17 -0600   .mailmap
    
    • 3
  7. Kevin Cherepski
    2018-03-10T08:28:34+08:002018-03-10T08:28:34+08:00

    对于那些使用 Fish 的人,这是Andrew M 的答案的Fish shell 版本。

    git ls-tree -r --name-only HEAD | while read -l filename
        printf '%s %s\n' (git log -1 --format="%ai" -- $filename) $filename
    end
    

    我将其存储为 Fish 函数以便于访问。

    • 1

相关问题

  • 如何使用 Gitosis 删除 Git 存储库

  • Git 和 Mercurial

  • 如何修复 git 中第一次提交的元信息?

  • 如何编辑 git 的历史记录以更正不正确的电子邮件地址/名称 [关闭]

  • git如何控制访问权限

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    新安装后 postgres 的默认超级用户用户名/密码是什么?

    • 5 个回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve