【问题标题】:How do we show all the unignored files in a Git repository?我们如何显示 Git 存储库中所有未被忽略的文件?
【发布时间】:2020-10-13 22:20:44
【问题描述】:

用 Git 术语来表达这个问题的另一种方法是:我们如何显示磁盘上存在的所有文件,无论它们是否在索引中,并且不会被忽略?

似乎没有与git check-ignore 直接相反的方法,它允许处理带有换行符、制表符等的不寻常(但可能的)文件名。

一些 Git 命令会生成可用于此任务的空分隔输出(带有-z),但涉及解析。

通过一些 Git 命令,我们可以获得一些以空值分隔的文件名列表,我们可以通过交叉/差异来获得相同的效果,但这需要相当复杂的解析,这并不容易(也许不可能做到?)以便携式方式使用 Shell、AWK 或 SED。

【问题讨论】:

  • 我了解您的实际问题在标题中,但您的问题主体讨论了有关您找到的特定实现的一些技术点。您能否在帖子正文中说出您的完整问题?
  • 更准确地说:您是否正在寻找一种“列出所有未忽略的文件”的方法?还是您在解析您选择的命令的输出时寻求帮助?如果我阅读了您的问题的标题、问题的主体以及您作为插图发布的代码,我会看到三种不同的意图...... :)
  • 您看到的三种不同意图是什么?
  • title : 你想列出不被忽略的文件;正文:您寻找 awk 或 sed 的特定标志来解析以\0 分隔的多行字段,并可能暗示您的文件名中包含非常奇怪的字符('\n' ?);代码:不知何故,您还需要不列出列为--deleted的文件
  • 问题正文提供了背景信息。问题的标题就是问题。当然,这是一个密集的问题。在问题主体中,讨论了两种可能的解决方案——但都需要解析带有\0 的内容。解析困难与需要文件列表有关。 Sed 或 Awk 没有可移植的标志来解析 \0

标签: javascript git shell


【解决方案1】:

这是 JavaScript 的尝试:

#!/usr/bin/env node
/// Run this script in the Git repository. Pass `-z` as the first and
/// only argument in order to process and output null-separated lists.

const execFileSync = require("child_process").execFileSync
const writeSync = require("fs").writeSync
const process = require("process")

const z = process.argv[2] == "-z"
const lsFiles = z ? ["ls-files", "-z"] : ["ls-files"]

const execToArray = (cmd, args) => {
    const data = execFileSync(cmd, args).toString().split(z ? "\0" : "\n")
    data.pop()
    return data
}

const inIndex = execToArray("git", lsFiles)
const notInIndexAndNotIgnored = execToArray("git", [
    ...lsFiles,
    "-o",
    "--exclude-standard",
])

const merged = inIndex.concat(notInIndexAndNotIgnored).sort()
const deleted = new Set(execToArray("git", [...lsFiles, "--deleted"]))

for (let i = 0; i < merged.length; i++) {
    const s = merged[i]
    if (deleted.has(s)) continue
    writeSync(1, s)
    writeSync(1, z ? "\0" : "\n")
}

【讨论】:

    【解决方案2】:

    git ls-files --exclude-standard -co 将列出所有未忽略的文件(缓存 + 未跟踪),但仍会列出索引中存在并从磁盘中删除的文件。

    您可以使用xargs ls 查看列出的文件是否存在于磁盘上:

    git ls-files --exclude-standard -co | xargs ls -1 2> /dev/null
    

    您似乎必须处理奇怪的字符:以下选项组合导致输出文件名,每行一个:

    git ls-files --exclude-standard -co -z | xargs -0 -L1 ls 2> /dev/null
    

    例如,上面的内容可以成功地被 bash 本身使用:

    ... | while read name; do
        echo "===== processing file '$name' :"
        head -10 "$name"   # quote the variable if you pass it as an argument
    done
    

    【讨论】:

    • 重新测试git ls-files:我忘了它默认不考虑.gitignore规则,你必须添加--exclude-standard选项。更新了我的答案。
    • 这个答案没有为管道中的进一步步骤提供处理异常文件名的方法,因此是不正确的。
    • 您能解释一下您打算对输出做什么吗?你似乎想以某种方式处理它,你需要一个批量的完整列表吗?或者您可以一次处理一个文件吗?
    • 有一种方法可以进行读取循环,它 (a) 处理所有文件名而不解释转义码和 (b) 在 \0 而不是换行符上拆分:read -r -d'' name
    猜你喜欢
    • 2013-03-09
    • 2017-01-01
    • 1970-01-01
    • 2020-04-25
    • 1970-01-01
    • 1970-01-01
    • 2011-11-06
    • 1970-01-01
    • 2013-10-26
    相关资源
    最近更新 更多