简体   繁体   English

列出当前 git 分支历史记录中任意位置的子目录中的文件

[英]List the files in a sub-directory present at any point in the current git branch's history

To list all the files present in a sub-directory at a particualr commit I can check-out that commit and look at the files.要在特定提交中列出子目录中存在的所有文件,我可以签出该提交并查看文件。 Is there a way to list all the files that have been present in a sub-directory at any point (ie in any commit in the current commit's ancestors)?有没有办法列出在任何时候(即在当前提交的祖先中的任何提交中)存在于子目录中的所有文件?

Yes: git ls-tree accepts both the so-called "tree-ish" and an optional path (which defaults to repository root, if not specified).是: git ls-tree接受所谓的“tree-ish”和可选路径(如果未指定,则默认为存储库根目录)。

A tree-ish is anything which can be resolved to a tree—an object which stores the information about a single "directory" in a recorded commit.树形是可以解析为树的任何东西——一个 object,它将有关单个“目录”的信息存储在记录的提交中。

A commit always refers to exactly a single tree object, and a tree object may refer to zero or more other tree objects—representing "subdirectories".提交总是指精确的单个树 object,而树 object 可能引用零个或多个其他树对象 - 表示“子目录”。

Hence, a commit is always a vaid "tree-ish".因此,提交始终是一个空洞的“树状”。

TL;DR TL;博士

To get the listing of the files under the /foo/bar prefix three commits back call要获取/foo/bar前缀下的文件列表,三个提交回调调用

git ls-tree HEAD~2 foo/bar

Updated to reflect on the clarification of the original question更新以反映对原始问题的澄清

But I want the files in all commits, ie HEAD, HEAD~, HEAD~2, HEAD~3, HEAD~4, … right back through the entire history.但我想要所有提交中的文件,即 HEAD、HEAD~、HEAD~2、HEAD~3、HEAD~4,…… 回到整个历史记录。 Perhaps my question is not clear?也许我的问题不清楚?

One could roll with a bit of shell scripting:可以使用一点 shell 脚本来滚动:

git rev-list HEAD | while read sha; do
  git ls-tree -r "$sha" prefix/of/interest;
done

…which basically walks all the commits in the DAG reachable from HEAD , and for each of them calls git ls-tree with the name of the commit and the prefix (directory name) of interest. …它基本上遍历从HEAD可访问的 DAG 中的所有提交,并为每个提交调用git ls-tree并带有提交的名称和感兴趣的前缀(目录名称)。

Note that if a tree object for the prefix does not exist in a particular commit, git ls-tree exits with a non-zero exit code, so if this code is to be run under set -e , this should be acknowledged and compensated for.请注意,如果特定提交中不存在前缀树 object ,则git ls-tree以非零退出代码退出,因此如果要在set -e下运行此代码,则应确认并补偿.

This approach might be upgraded in a number of interesting ways.这种方法可能会以许多有趣的方式进行升级。
For instance, one might not just get the list of files or call something like git show --name-status $sha and so on.例如,可能不只是获取文件列表或调用诸如git show --name-status $sha之类的东西。

Ionică Bizău's answer to another question ("How to get ONLY filename with path using git log?") gave me something to work with. Ionică Bizău 对另一个问题的回答(“如何使用 git 日志仅获取带有路径的文件名?”)给了我一些可以使用的东西。 This seems to work to get all the files that ever existed under the /foo/bar directory in all of the commits leading to the current state:这似乎可以在导致当前 state 的所有提交中获取/foo/bar目录下曾经存在的所有文件:

git log --name-status -- /foo/bar | grep -E '^[A-Z]\b' | sed -e 's/^\w\t*\ *//' | sort | uniq
  • git log --name-status gives the names and status of all files changed in all the commits ( docs ). git log --name-status给出了所有提交中更改的所有文件的名称和状态( 文档)。
  • -- /foo/bar restricts the log to the directory of interest ( here ) -- /foo/bar将日志限制到感兴趣的目录(这里
  • | bash pipeline ( docs ) bash 管道( 文档
  • grep -E '^[AZ]\b' Gets the lines that start with ( ^ ) a capital letter ( [AZ] ) followed by a word break ( \b ), ie the lines starting M, D, A, .... ( grep docs & diff-filter docs ) grep -E '^[AZ]\b'获取以 ( ^ ) 大写字母 ( [AZ] ) 后跟分词符 ( \b ) 开头的行,即以 M、D、A、.. 开头的行..( grep 文档差异过滤器文档
  • sed -e 's/^\w\t*\ *//' run the stream editor on s/regexp/replacement/ In this case ^\w\t*\ * looks for lines starting ( ^ ) with a word ( \w ) followed by zero or more tabs ( \t* ) and then zero or more spaces ( \ * ) and replaces those matches with the empty string ( sed docs ) sed -e 's/^\w\t*\ *//'s/regexp/replacement/上运行 stream 编辑器/ 在这种情况下^\w\t*\ *查找以 ( ^ ) 开头的带有单词 ( \w )后跟零个或多个制表符( \t* ),然后是零个或多个空格( \ * )并将这些匹配项替换为空字符串( sed 文档
  • sort ( docs ) sort文档
  • uniq ( docs ) uniq ( 文档)

(NB This solution will not include files added to the working tree or the stage but not yet comitted, so add and commit first.) (注意此解决方案不包括添加到工作树或阶段但尚未提交的文件,因此请先添加并提交。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM