git rm * 不会一次性删除所有文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19363795/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 17:08:40  来源:igfitidea点击:

git rm * doesn't remove all files in one go

git

提问by u1860929

I was trying out some sample instructions of git and came across this peculiar case that when we do a git rm *, it doesn't delete the .*files in the first attempt. Why is it so?

我正在尝试 git 的一些示例指令并遇到这种特殊情况,即当我们执行 a 时git rm *,它不会.*在第一次尝试中删除文件。为什么会这样?

mkdir -p test_repo1/folder && cd test_repo1
touch .testfile1 .testfile2 testfile3 folder/testfile4 folder/.testfile5
git init && git add . && git commit -m "test commit"

If now I do a git rmas follows, I have to do it a second time to remove all the files

如果现在我执行git rm如下操作,我必须再次执行以删除所有文件

$ git rm -r *
rm 'folder/.testfile5'
rm 'folder/testfile4'
rm 'testfile3'

$ git rm -r *
rm '.testfile1'
rm '.testfile2'

Why doesn't git remove all files in the first attempt itself? Also, why is this happening for files withing the repo root only?

为什么 git 在第一次尝试中不删除所有文件?另外,为什么只有 repo root 的文件会发生这种情况?

Interestingly, if all I have are those .testfiles, then git removes them in the first attempt itself.

有趣的是,如果我只有那些.testfiles,那么 git 会在第一次尝试中删除它们。

I am using git version 1.7.9.5

我正在使用 git 版本 1.7.9.5

回答by tripleee

The wildcard gets expanded by your shell, and the expansion does not include dot files, by default, in most shells.

通配符由您的 shell 扩展,并且默认情况下,在大多数 shell 中扩展不包括点文件。

So by the time gitexecutes, the first command has become

所以到git执行的时候,第一个命令已经变成

git rm -r folder testfile3

and the second probably a literal

第二个可能是字面意思

git rm -r *

which gitthen expands by itself.

git然后通过自身扩张。

As remarked by Keith,to remove everything in one go, prevent the shell from expanding the wildcard so that gitdoes the expansion the first time already. This can be done with double or single quotes, or with a backslash before the asterisk. I tend to prefer single quotes:

正如Keith 所说,要一次性删除所有内容,请防止 shell 扩展通配符,以便git第一次进行扩展。这可以使用双引号或单引号完成,或者在星号前使用反斜杠。我倾向于喜欢单引号:

git rm -r '*'

回答by Todd A. Jacobs

Shell Globbing

壳流

When you run git rm *you are actually using the shell's globbing rules to pass arguments to git-rm(1). Many shells don't include hidden files (e.g. files with leading dots) by default. In Bash, you can change the globbing rules with dotgloband GLOBIGNORE. For example:

当您运行时,git rm *您实际上是在使用 shell 的通配规则将参数传递给git-rm(1)。默认情况下,许多 shell 不包含隐藏文件(例如带有前导点的文件)。在 Bash 中,您可以使用dotglobGLOBIGNORE更改通配规则。例如:

  • Using the shoptbuiltin:

    # set dotglob
    shopt -s dotglob
    
    git rm *
    
    # unset dotglob
    shopt -u dotglob
    
  • Using the GLOBIGNOREvariable (which also sets dotglob):

    # Run git within a modified environment that includes GLOBIGNORE.
    GLOBIGNORE='.git' git rm *
    
  • 使用shopt内置:

    # set dotglob
    shopt -s dotglob
    
    git rm *
    
    # unset dotglob
    shopt -u dotglob
    
  • 使用GLOBIGNORE变量(也设置dotglob):

    # Run git within a modified environment that includes GLOBIGNORE.
    GLOBIGNORE='.git' git rm *
    

回答by torek

As user1281385 noted in a comment, the shell expands *the first time around.

正如 user1281385 在评论中指出的那样,外壳*第一次扩展。

The reason the secondtime removes the dot-files is that once there are no files to match, the shell leaves the literal asterisk as an argument (depending on your shell anyway, at least one variant errors out instead) and git then does its own matching.

究其原因,第二个时间删除点文件是,一旦没有文件匹配,壳叶字面星号作为参数(这取决于你的shell,无论如何,至少一种变体出现了错误,而不是),然后混帐做自己的匹配。

回答by VonC

Note that the right syntax should be git rm -r .('dot')

请注意,正确的语法应该是git rm -r .('dot')

More worrying is git rm -r(empty pathspec string) which does the same until Git 2.11!

更令人担忧的是git rm -r(空路径规范字符串)在 Git 2.11 之前也是如此!

See commit d426430(22 Jun 2016) by Emily Xie (emilyxxie).
(Merged by Junio C Hamano -- gitster--in commit 3b1e135, 26 Oct 2016)

请参阅Emily Xie ( ) 的commit d426430(2016 年 6 月 22 日(由Junio C Hamano合并-- --提交 3b1e135 中,2016 年 10 月 26 日)emilyxxie
gitster

pathspec: warn on empty strings as pathspec

An empty string as a pathspec element matches all paths.
A buggy script, however, could accidentally assign an empty string to a variable that then gets passed to a Git command invocation, e.g.:

pathspec: 警告空字符串作为路径规范

作为 pathspec 元素的空字符串匹配所有路径。
然而,一个有问题的脚本可能会意外地将一个空字符串分配给一个变量,然后该变量被传递给 Git 命令调用,例如:

path=... compute a path to be removed in $path ...
git rm -r "$paht"

which would unintentionally remove all paths in the current directory.

The fix for this issue requires a two-step approach.

  • As there may be existing scripts that knowingly use empty strings in this manner, the first step simply gives a warning that (1) tells that an empty string will become an invalid pathspec element and (2) asks the user to use "." if they mean to match all.

  • For step two, a follow-up patch several release cycles later will remove the warning and throw an error instead.

这会无意中删除当前目录中的所有路径。

此问题的修复需要两步法。

  • 由于可能存在以这种方式故意使用空字符串的现有脚本,第一步只是给出警告:(1) 告诉空字符串将成为无效的 pathspec 元素,(2) 要求用户使用“ .”,如果他们意思是匹配所有。

  • 对于第二步,几个发布周期后的后续补丁将删除警告并抛出错误。



Update for Git 2.15.x/2.16 (Q1 2018):

Git 2.15.x/2.16 更新(2018 年第一季度):

The message "will be made invalid in upcoming releases" disappear, and becomes:

消息“将在即将发布的版本中失效”消失,变成:

empty string is not a valid pathspec.
please use . instead if you meant to match all paths

See commit 9e4e8a6(07 Jun 2017) by Emily Xie (emilyxxie).
See commit 229a95a(23 Jun 2017) by Junio C Hamano (gitster).
(Merged by Junio C Hamano -- gitster--in commit 728c573, 06 Nov 2017)

请参阅Emily Xie ( ) 的commit 9e4e8a6(07 Jun 2017 )。 请参阅Junio C Hamano( ) 的commit 229a95a(2017 年 6 月 23 日(由Junio C Hamano合并-- --提交 728c573 中,2017 年 11 月 6 日)emilyxxie
gitster
gitster

An empty string as a pathspec element matches all paths.
A buggy script, however, could accidentally assign an empty string to a variable that then gets passed to a Git command invocation, e.g.:

作为 pathspec 元素的空字符串匹配所有路径。
然而,一个有问题的脚本可能会意外地将一个空字符串分配给一个变量,然后该变量被传递给 Git 命令调用,例如:

path=... compute a path to be removed in $path ...
git rm -r "$path"

which would unintentionally remove all paths in the current directory.

这会无意中删除当前目录中的所有路径。