2

pathspecs で 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.どのように動作を変更するかに焦点を当てます。

ロジック

パス展開のほとんどはシェルによって行われます(したがって、私のコメントです)。必要なものがあれば、git によって実行されるものもあります。

いくつかのテスト

セットアップ

このプログラムを使用して問題を調査しました。

include <stdio.h>

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

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

私は知っています、それは非常に高度なプログラミングです。

テスト

何が起こっているのかを見て、シェルが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

Point 5, 6, 7 : 今回は Git で処理、動作はそれほど驚くことではありません (glob とリテラルの両方の比較を行います)

$ ./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 に答える