递归应用git rm -f,未指定'-r'

9gm1akwq  于 2023-02-20  发布在  Git
关注(0)|答案(1)|浏览(161)

我移动了一些文件后,添加/暂存他们。文件结构看起来像:

parent/dir1/script0.py
parent/dir1/script1.py
parent/script0_delete_me.py
parent/script1_delete_me.py

dir1内部运行git rm -f ../*.py时(注意,我没有指定-r),我期望的结果是:

parent/dir1/script0.py
parent/dir1/script1.py
parent/
parent/

但事实是

parent/dir1/
parent/dir1/
parent/
parent/

取回我需要的文件没有问题。但是为什么git rm -f ../*.py要递归搜索,即使-r从来没有被给定过?快速浏览git rm -f的文档表明递归搜索需要-r选项。
常规bash的行为不是这样的:

~/test/dir1$ ls ../
dir1  d.py
~/test/dir1$ rm -f ../*.py
~/test/dir1$ ls
d.py

编辑:复制:

~$ git init t
Initialized empty Git repository in ~/t/.git/
~$ cd t
~/t$ touch d.py
~/t$ git add d.py
~/t$ git commit -m "init"
[master (root-commit) f59e049] init
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 d.py
~/t$ mkdir u
~/t$ git mv d.py u/d.py
~/t$ cd u
~/t/u$ ls
d.py
~/t/u$ ls ../
u
~/t/u$ git rm -f ../*.py
rm 'u/d.py'
~/t/u$ ls
~/t/u$

我想可能是我没有正确地看待这个问题/试图用错误的方式做一些事情。但这种行为仍然看起来很奇怪。

ercv8c1e

ercv8c1e1#

Git的命令行路径规范有它的怪癖,shell globbing也有它的怪癖。
简短的形式是,您希望使用git rm -f ':(glob)../*.py',或者在脚本或shell启动(可能是~/.bashrc)中设置nullglobfailglob来运行,以避免这种情况,嗯,可能过于急切,在不必显式警告shell关闭的情况下输入模糊的命令参数。
Git命令行路径规范不会特别处理目录分隔符,而shell glob则会,许多shell会将不匹配的glob沿着给命令,以防它实际上不是文件名,命令会以其他方式理解字符串。
因此,由于父目录中没有以.py结尾的路径,Git将rm-f*.py视为args,而Git的rm将其解释为Git路径规范。
无论是在shell还是在Git中,改变这些行为的痛苦/收益比都是无法忍受的。说git help glossary,然后搜索pathspec,看看你可以用它做的很多有时候非常方便的事情。
怀疑地盯着这个,然后试试看:

sh -x <<\EOD; rm -rf test
git init test; cd $_
mkdir inner; cd $_; touch a.file; git add .
ls ../*.file
git ls-files ../*.file
shopt -s failglob
ls ../*.file
git ls-files ../*.file
shopt -u failglob
shopt -s nullglob
ls ../*.file
git ls-files ../*.file
git ls-files ':(glob)../*.file'
EOD

这里还有几个怪癖在起作用,这就是它的工作方式,每一个选择都迎合了工作流的特定部分,有些人经常点击,而有些人几乎从来没有。

相关问题