不同分支的git ls-files

4

我想在指定分支的基本目录中找到所有Markdown文件。有人建议我使用git ls-files,但文档没有提到如何指定分支。我想在不检出该分支的情况下完成此操作。这个能做到吗?


2
https://git-scm.com/docs/git-ls-tree - matt
我没有看到根据文件扩展名过滤的方法。git ls-files *.md 显示当前分支中所有 markdown 文件,而 git ls-tree --name-only origin/master 则显示 origin/master 中的所有文件。我需要自己筛选吗,还是有一个标志可以用? - Pi Fisher
2个回答

5

git ls-files 命令用于检查 索引区(index) 或者 工作树(work-tree) 中的文件(或两者都检查)。由于当前的索引和工作树通常反映当前分支末尾提取的提交,因此这种方式将不起作用。但是有一个解决方法。

正如VonC指出的git ls-tree 命令检查存储在提交中的树对象(tree)。然而,git ls-tree 不接受像 **/*.md 这样的路径参数。

解决方法是将感兴趣的提交读入到一个临时的索引中。为了干净地执行此操作,请使用mktemp 命令创建一个临时文件,然后删除该临时文件,并使用git read-tree 命令重新创建文件,以创建包含您希望检查的提交镜像的有效临时索引,然后可以使用 git ls-files 命令进行查看。例如:

$ cd git
$ sh -c 'export GIT_INDEX_FILE=$(mktemp); rm $GIT_INDEX_FILE; git read-tree e83c5163316f89bfbde7d9ab23ca2e25604af290; git ls-files -- "*.h" "**/*.h"; rm $GIT_INDEX_FILE'
cache.h
$ sh -c 'export GIT_INDEX_FILE=$(mktemp); rm $GIT_INDEX_FILE; git read-tree origin/master; git ls-files -- "*.md"; rm $GIT_INDEX_FILE'
.github/CONTRIBUTING.md
.github/PULL_REQUEST_TEMPLATE.md
README.md
contrib/vscode/README.md

(注意:sh -c 'export ...; cmd1; cmd2; cmd3'是必需的,尽管如果您已经在使用POSIX兼容的shell,则可以用括号替换sh -c来创建子shell。 我们需要环境变量GIT_INDEX_FILE仅为那些命令设置。 如果您的mktemp带有-u选项,请考虑使用该选项代替第一个rm。 另请参见mktemp(1)有多可移植?

我不明白创建临时文件并立即删除的意义所在。然后,在git read-tree之后再次删除$GIT_INDEX_FILE,这应该会导致错误,因为您已经在第一次调用rm $GIT_INDEX_FILE中删除了该临时文件。您能否进一步解释一下这个问题? - EarthIsHome
1
@EarthIsHome:尝试不删除它并观察效果。(认真地,试试看。这是Git的一个bug吗?我认为这可能被视为一个bug。)请注意,如果您的mktemp-u,则可以使用此标志而不是单独的初始rm。另外,考虑回答问题:“git read-tree创建哪些文件”。 - torek
我尝试过了。它将我的索引更改为git read-tree的内容,而不会更改我的HEAD或工作树中的文件。我使用reset --hard回到了我的HEAD所指向的分支。 - EarthIsHome
我猜我不理解git是如何使用mktemp创建的临时文件。 - EarthIsHome
1
你可能忘记了添加 export 或者没有将其作为单独的子shell命令运行。环境变量 $GIT_INDEX_FILE 指定了Git应该使用的临时索引文件,但是这个文件必须要么不存在(在这种情况下,Git会创建一个有效的索引),要么包含一个有效的索引(在这种情况下,Git会将其作为read-tree等操作的起点)。一个空的(零字节)文件不是一个有效的索引,因为它缺少校验和。 - torek
啊,我没有理解 GIT_INDEX_FILE 是我的误解的根源。现在我明白了!谢谢你。而且,是的,你是对的,我不是在子 shell 中;我只是在我的主 shell 中玩耍。 - EarthIsHome

4
如果您正在使用git ls-tree,可能需要自己过滤输出以获取所需内容。
正如2012年的这个线程中提到的那样:

这里有两个“pattern”的用法,前者可能是可以的,但后者确实是误导性的。

当我们编写这个命令时,有两个不同的“pathspec”系列,ls-tree属于其中一个带有“diff”家族的系列,该系列除了“前导路径模式”外,不接受任何东西(另一个来自“ls-files”和“grep”家族允许通配符)。从未支持将通配符传递给“ls-tree”/diff家族的命令。

如果您更改ls-tree以使用其路径参数作为pathspec,则会破坏向后兼容性。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接