1

git ls-files在脚本中使用来收集 git 跟踪的所有文件。不幸的是,如果您rm的文件(而不是git rm)它不再存在于文件系统中,但它仍将由git ls-files

所以问题是:是否有一种简单而有效的方法可以git ls-files输出本身或通过事后过滤(使用例如bash)排除文件系统上不再存在的文件?就像是

git ls-files --existing-only

背景:我想创建一个 CMake 虚拟目标,它包含项目目录中的所有文件(即由 git 跟踪)。我使用类似的东西

execute_process(
    COMMAND bash -c "cd ${CMAKE_SOURCE_DIR}; git ls-files"
    OUTPUT_VARIABLE ADDITIONAL_PROJECT_FILES
)

生成文件列表。但不幸rm的是 ing 一个文件并且尚未暂存更改将导致错误,因为 CMake 无法再找到该文件..

更新:在我的编辑之前,我正在谈论git rming 一个文件 - 这将由git ls-files. 但问题仍然存在:如果有人删除了一个文件(不使用 git)git ls-files将列出它(我遇到了麻烦)。

4

1 回答 1

1

我不认为你可以自己做到这一点git ls-files(有点遗憾,因为它对这类事情非常方便)。

最终,对于 Git,工作树中不存在文件这一事实对于下一次提交并不重要。提交使用索引/暂存区域中的任何内容。的主要焦点git ls-files是索引内容,因此有 和 之类的--stage选项--debug。但是,该--others选项的存在证明git ls-files 可以扫描工作树。扫描工作树后,它可以显示哪些文件在工作树中但从索引中丢失:--others. 该列表可以进一步减去、使用--exclude-standard等。

您的特殊情况是,您不想获取工作树文件列表并减去那些index中的文件,而是要获取索引文件列表并减去那些不在工作树中的文件. 也就是说,如果我们将I定义为索引文件的集合,将W定义为工作树文件的集合,我们可以看到git ls-files可以轻松计算W\I。我们想让它计算I \ W,即在索引中但从工作树中丢失的文件集,以便我们可以从git ls-files的输出中删除它们。

唉,没有这样的选择。剩下的就是git diff-files,它可以轻松地计算这组文件:为git diff-files --name-only --diff-filter=D HEAD您获取索引中但从工作树中丢失的文件。使用列表从git ls-files输出中删除文件名,您就拥有了所需的内容。

重要的侧边栏

通常,工作树中丢失但存在于索引中的文件错误地处于这种状态,正确的做法是将它们从索引中提取到工作树中。此外,任何时候您打算立即对索引中的文件集执行某些操作时,您都应该考虑到工作树中这些文件的副本可能索引中的副本不同的事实。例如,Git 预提交挂钩可能旨在确保文件针对某些源语言正确格式化:例如,运行它们clang-formatblack保持它们不变。

通过检查工作树文件对此进行测试从根本上是错误的,因为 Git 不会从工作树构建提交。这意味着这些工具应该将整个索引提取到文件系统中其他位置的临时(新的和空的)工作树中,然后在该临时工作树上运行格式化程序或要使用的任何工具. 这个过程的结果告诉你提交是否应该继续。然后,您删除临时工作树(即,自己清理)并提供适当的“可以提交”/“不,不提交”退出状态。

于 2019-06-27T16:05:47.727 回答