为什么 `$(git branch)` 会输出文件夹内所有文件的名称(除了 git branch)?

为什么 `$(git branch)` 会输出文件夹内所有文件的名称(除了 git branch)?

我写了一个命令来删除所有 git 分支,而不需要手动全部写入,目前是这样的:

git branch -d $(git branch)

它按照我的要求进行操作,但还尝试删除当前目录中以文件命名的分支,因此输出如下:

error: branch 'angular.json' not found.
error: branch 'assembly.xml' not found.
error: branch 'ci-settings.xml' not found.
error: branch 'coverage' not found.
error: branch 'cypress.json' not found.
error: branch 'Dockerfile.angular' not found.
error: branch 'Dockerfile.spring' not found.
error: branch 'e2e' not found.
error: branch 'examples' not found.
error: branch 'mvnw' not found.
error: branch 'mvnw.cmd' not found.
error: branch 'nginx' not found.
error: branch 'node' not found.
error: branch 'node_modules' not found.
error: branch 'package.json' not found.
error: branch 'package-lock.json' not found.
error: branch 'pom.xml' not found.
error: branch 'README.md' not found.
error: branch 'scripts' not found.
error: branch 'serve-proxy.conf.json' not found.
error: branch 'src' not found.
error: branch 'target' not found.
error: branch 'to-do.txt' not found.
error: branch 'tsconfig.json' not found.
error: branch 'web.config' not found.
error: Cannot delete branch 'dev' checked out at 'D:/Documentos/oreons/Rise/archivekeeper-ui'
Deleted branch test (was 729628a).

如果我 echo $(git branch),输出如下:

$ echo $(git branch)
angular.json assembly.xml ci-settings.xml coverage cypress.json Dockerfile.angular Dockerfile.spring e2e examples mvnw mvnw.cmd nginx node node_modules package.json package-lock.json pom.xml README.md scripts serve-proxy.conf.json src target to-do.txt tsconfig.json web.config dev

这解释了命令的输出。但是为什么$(git branch)除了 git 分支之外还输出所有这些文件名?

答案1

作为@steeldriver上面提到评论,在其输出中git branch有一个星号(*),以标记当前签出的分支。

$ git branch
* main
  test

当以 方式运行时$(git branch),输出中的星号将扩展为当前所在目录中的所有非隐藏文件和目录。

要删除星号,您可以通过传递选项来格式化输出--format,仅显示引用名称的短格式。

$ git branch --format='%(refname:short)'
main
test

因此您要使用的命令如下。

git branch -d $(git branch --format='%(refname:short)')

答案2

不要git branch在脚本中使用。相反,请使用低级命令,例如git for-each-ref

git for-each-ref --shell --format='%(refname:short)' refs/heads | \
while read branch; do git branch -d "$branch"; done

或者

git for-each-ref --shell --format='%(refname:short)' refs/heads | \
xargs git branch -d

这避免了问题中的命令问题,因为它正确地引用了参数扩展。不引用参数扩展(或命令替换)将执行路径名扩展扩大价值。

由于git branch是面向用户的命令,它用 标记当前分支*。您可能知道,*作为通配符/通配符,可解析为任意 0 个或多个字符。执行 时echo *,您的 shell 首先扩展并替换*当前目录中的所有(非隐藏)文件,然后将此文件列表作为参数传递给echo

结论:总是引用“美元表达”(不是一个真正的术语,我说的是参数扩展命令替换)来防止字段拆分和路径名扩展——除非你有很好的理由不这样做(并且知道你在做什么)

答案3

我在 shell 函数中使用它,目的基本相同,尽管它保留了mainmaster和当​​前分支(用星号标记,如较早的答案和评论中所述)。您可能会发现它很有用。

git branch |
    grep -v '^\*' |
    grep -oE '[^ ]+' |
    grep -vE '^(master|main)$' |
    while read branch_name; do
        git branch -D $branch_name
    done

相关内容