2

我在使用带有路径规范的 git-status 时观察到一种奇怪的行为。我希望您对它是预期行为还是 git 中的未定义行为提出意见。

初始设置

$ mkdir main && cd main
$ git init .
Initialized empty Git repository in d:/temp/main/.git/
$ touch test[1].txt
$ touch test[2].txt

以下几条可以理解

$ # 1. escaped square brackets
$ git status test\[1\].txt --short        
?? test[1].txt

$ # 2. escaped square brackets with range
$ git status test\[[1-9]\].txt --short    
?? test[1].txt
?? test[2].txt

$ # 3. unmatched range, with what looks like a fallback to literal comparison
$ git status test[1].txt --short          
?? test[1].txt

意外行为的附加设置

$ touch test1.txt

意外行为

$ # 4. matched range, so no fallback to literal comparison (this one looks OK)
$ git status test[1].txt --short
?? test1.txt

$ # 5. escaped square brackets => I would expect only test[1].txt to be returned
$ git status test\[1\].txt --short
?? test1.txt
?? test[1].txt

$ # 6. escaped square brackets with range => I would expect only test[1].txt 
$ # and test[2].txt to be returned
$ git status test\[[1-9]\].txt --short
?? test1.txt
?? test[1].txt
?? test[2].txt

$ # 7. only escaping the last square bracket
$ # result looks similar to the 5th case
$ git status test[1\].txt --short
?? test1.txt
?? test[1].txt

额外设置带来更多乐趣

$ git add test1.txt
$ rm test1.txt
$ touch test2.txt

更多意外行为

$ # 8. ???
$ git status test[1].txt --short
AD test1.txt
?? test[1].txt

$ # 9. We lost test1.txt ???
$ git status test[1-2].txt --short
?? test2.txt

$ # Woo... Should this really work?
$ git status test[*.txt --short
AD test1.txt
?? test2.txt
?? test[1].txt
?? test[2].txt

我在那里有点困惑。我已经阅读了与pathspec相关的 Git 文档,但并没有那么详细。

谁能帮我理解背后的逻辑?

4

1 回答 1

4

这里有很多事情要讨论,但我会尽量关注:1.这背后的逻辑,2.它如何修改行为。

逻辑

大多数路径扩展是由 shell 完成的(因此我的评论)。有些是由 git 完成的,当它有它需要的时候。

一些测试

设置

我用这个程序来调查这个问题:

include <stdio.h>

int
main(int argc, char **argv)
{
    int i;

    for (i = 1; i < argc; i++) {
            puts(argv[i]);
    }
}

我知道,这是非常高技能的编程。

测试

我们现在可以看看发生了什么,看看 shell 如何修改 git 接收的内容:

第 1、2、3、4 点:一切正常,运行小程序也会给你同样的结果。

$ ./a.out test\[1\].txt test\[[1-9]\].txt test[1].txt
test[1].txt
test[1].txt
test[2].txt
test[1].txt

第 5、6、7 点:这次由 Git 处理,行为并不令人惊讶(同时进行全局和文字比较)

$ ./a.out test\[1\].txt test\[[1-9]\].txt test[1\].txt
test[1].txt
test[1].txt
test[2].txt
test[1].txt

第 8、9、10 点:嗯,根据我们之前所见,这不再令人惊讶。对于9.,没有与 test1.txt 匹配的 bash 比较(已删除,因此,...已删除)

$ ./a.out test[1].txt                         
test[1].txt

$ ./a.out test[1-2].txt          
test2.txt

$ ./a.out test[*.txt
test[1].txt
test[2].txt

结论

如果你想测试 Git 处理 pathspec 的方式,你应该用双引号将你的路径括起来:

$ ./a.out "test[*.txt" "test[1\].txt"
test[*.txt
test[1\].txt

希望有帮助,

于 2012-07-03T18:03:08.637 回答