使用git status列出文件清单

7

背景

我很清楚git status的工作原理,甚至了解git ls-files。通常情况下,我只需要和想要git status,它完美地回答了这个问题:“我的状态是什么,哪些文件需要我关注?”

然而,我一直找不到一个快速的命令来回答以下问题:“我有哪些文件,它们各自的状态是什么?”因此,我需要一个完整的目录列表(像ls -la),其中包含一个显示每个文件/目录状态的列。


我尝试过的方法

git status -s --ignored非常接近我想要的输出格式,但它只会列出在HEAD、索引和工作目录之间未更改的文件。此外,它还会递归进入目录。

git ls-files似乎能够以可脚本化的形式提供所有所需的信息,但我无法阻止它递归列出所有目录的内容。

显然,我可以编写一些代码来处理这两个命令的输出,并提供我想要的视图。但如果已经有可用的命令,我会讨厌重新发明轮子。


问题

有没有一种方法可以列出目录中的所有文件及其各自的git状态?
我想要一个完整的列表,显示ls将显示的完全相同的文件。


注释

这个问题不能回答我的问题,因为我绝对想要一个等同于ls的命令。包括未修改、被忽略和未跟踪的文件,但排除目录内容。


1
考虑使用另一个脚本,但在 git status 选项中添加 -uall。我不太清楚您所说的“排除目录内容”的意思,因为 ls 查看的是目录内容... 您还可以查看 git ls-files --other 输出,并/或者考虑自己读取目录,特别是如果您编写一个简单的Python程序或类似程序。 (重新阅读您的问题,我发现您真正的意思是“不要递归”。 因此,我认为将 os.listdirgit status --short 组合成您想要的任何输出格式的Python程序会很好。) - torek
git ls-files有几个选项可能适合您的需求。例如,git ls-files --directory <path/to/dir/>将输出限制为给定目录中的文件(即在<path/to/dir/>部分定义的路径)- 如果这是您所说的“停止递归列表”的意思?要列出文件状态,可以使用--[cached|deleted|others|ignored|stage|unmerged|killed|modified]选项。例如,运行git ls-files --modified <path/to/dir/>将在给定的<path/to/dir/>部分列出具有“修改”状态的文件。 - RobC
谢谢 @cmaster 提供的非常详细的解释。我知道什么是“递归列表”,但我没有意识到 Git 命令处理方式不同 - 所以我学到了新东西。也许我应该在 SO 上写更多事实不正确的评论,作为学习的一种方法,而不是发布实际问题 ;) 那么 Git 运行类似于 ls foo/** 的东西吗? - RobC
当然,我理解你的观点并再次感谢。我开玩笑说“应该写更多不准确的评论”,但我知道故意这样做(或故意提供错误答案)是没有用的。无论如何,希望你能得到一个合适的回答/解决方案 - 我会关注的!</chat> - RobC
这似乎与https://stackoverflow.com/questions/34352494/one-git-command-to-show-status-of-all-files-in-a-directory非常相似,尽管那里也没有一个好的答案。此外,我不明白这个问题与https://dev59.com/BGoy5IYBdhLWcg3wKrCs之间的区别是什么。看起来两者都在寻求一个git命令(或其他命令)来显示目录中所有文件的状态。您能澄清一下区别吗? - David Z
显示剩余4条评论
2个回答

1
因为git status -s的输出已经足够了,让我们只是围绕这个函数创建一个Bash例程!对于未更改的文件,我们可以手动“回声”适当的信号。根据规范,我们可以使用两个空格符“ ”或其他符号来达到这个目的。例如,对于Git无法跟踪的目录,我们选择用符号“_”作为状态代码:
for FILE in *
do
  if [[ -f $FILE ]]
  then
    if ! [[ $(git status -s $FILE) ]]
    then
      # first two simbols below is a two-letter status code 
      echo "   $FILE"
    else 
      git status -s "$FILE"
    fi
  fi
  if [[ -d $FILE ]]
  then
    # first two symbols just selected as status code for directories
    echo "__ $FILE"
  fi
done

这个脚本的工作方式与 ls 相同。它也可以使用 ; 写成一行。


这确实是一个可以建立在其上的东西。但我认为,如果没有目录,列表还不够完整。不过,这很容易添加。谢谢。 - cmaster - reinstate monica
@cmaster-reinstatemonica 我已将目录添加到列表中,并使用虚拟状态代码对其进行了标记。 - Dmitry Kravtsov

1

要将Git检查的路径限制为当前目录,可以使用其Unix glob pathspecs。由于git status会对索引和HEAD进行大量检查,因此请使用它,并使用ls填充其余文件,ls会向您显示,只需操纵其输出以具有与git status相同的格式,并仅获取git status未列出的那些文件。

( git status -s -- ':(glob)*'; ls -A --file-type | awk '{print "   "$0}' ) \
| sort -t$'\n' -usk1.4
:(glob)告诉Git剩下的路径规范是Unix glob,即*应该只匹配一个级别,就像(启用了dotglob的)shell通配符¹一样。 -t$'\n'告诉sort字段分隔符是换行符,即它是一个大字段,并且-usk1.4表示uniquify,仅取一次运行中的第一个,stable,保留输入顺序,不违反排序键顺序(这会慢一些,所以必须特别要求),k1.4表示键从第一个字段开始,在该字段的第四个字符处开始,没有给出结束点,因此从那里到结尾。
¹为什么他们决定默认情况下既不像shell规范也不像gitignore规范匹配路径规范,我可能永远不会学习,因为我更喜欢无知地不赞成他们烦人的选择。

不错。我认为这将成为被接受的答案,因为 ':(glob)*' 提示非常有用。知道如何告诉命令该做什么,而不是默认地绕过它所做的事情,总是很好的。我只是再等一两天,看看新的行动是否会激发其他人发布更好的答案。 - cmaster - reinstate monica

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