.gitignore 구문 : bin vs bin / vs. bin / * vs. bin / **


90

추가의 차이점은 무엇입니까 bin, bin/, bin/*bin/**내 .gitignore 파일에? 나는 .gitignore 파일을 사용 bin/하고 있지만 다른 .gitignore 파일을 보고 있습니다 ( 일식 파일 에서 이중 및 단일 별은 다음과 같이 함께 사용됩니다. tmp/**/*무슨 일입니까?) 처음 두 패턴도 널리 사용된다는 것을 알 수 있습니다. 누군가가 세 가지 차이점을 설명해 주시겠습니까?


4
@unutbu : 그 질문에 대한 대답은 분명히 논쟁의 여지가 있습니다. 상위 댓글 중 하나는 대답이 실제로 완전한 신화라고 주장합니다.
chandsie

동작은 맨 페이지에 완전히 지정되어 있으며 모든 정보를 포함하는 질문 / 답변이 여기 (또는 10 개)에있을 것이라고 확신합니다.
Cascabel

답변:


85

bin'bin'이라는 파일 또는 디렉토리 와 일치합니다 .

bin/'bin'이라는 이름의 디렉토리 와 일치합니다 . 이는 사실상 Git이 디렉토리 만 추적하지 않기 때문에 모든 내용을 의미합니다.

bin/*모든 파일 및 디렉토리를 bin/. 이렇게하면 Git이 하위 디렉터리에서 파일을 자동으로 찾지 못하지만 bin/foo하위 디렉터리가 생성 된 경우이 규칙은 의 콘텐츠 와 일치 하지 않습니다foo .

bin/**모든 bin/디렉토리 및 모든 하위 디렉토리의 모든 파일 및 디렉토리와 일치합니다 .

규칙은 저장소 루트와 관련이없고 파일 시스템 트리의 모든 위치 에 적용되므로 여기서 "임의"라는 단어가 중요합니다 . 의도 한 내용 만 일치 시키려면 시스템의 루트가 아닌 저장소의 루트를 의미하는 a /(또는 !/무시 해제)로 규칙을 시작해야합니다 .

경고 : 당신이해야 결코 같은 규칙을 사용하지 dir/*, /dir/**등 혼자 당신은 또한 디렉토리 내부에 존재하는 무엇인가를 취소 무시하지 않는 한 . 생략 별표는 또는 영구적으로 많은 양의 데이터를 잃을 수있는 특정의 호출로부터 git gc, git stash그리고 더.

나는 무엇을해야하는지 정말로 모른다 tmp/**/*. 처음에는 하위 디렉토리에있는 파일을 일치시키는 데 사용할 수 있다고 생각 tmp/했지만 tmp/그 자체로 직접 존재하는 파일 은 아닙니다 . 그러나 간단한 테스트는 이것이 tmp/.


10
단지 명확하게, 차이 무엇 bin/bin/**?
chandsie

1
나는 bin/bin 디렉토리를 무시할 것이지만 bin 디렉토리 bin/**는 포함하지만 그 내용은 포함하지 않을 것입니다
Robin Winslow 2012 년

1
그것은 Siddhartha의 대답과 일치하지 않는 것 같습니다. 대답에서 그리기, bin/반면, (모든 하위 디렉토리와 파일 포함) 디렉토리 자체를 무시합니다 bin/**모든 bin 디렉토리에있는 파일과 하위 디렉토리,하지만 무시 하지 bin 디렉토리 자체를. 그것이 정확한지 아닌지 확실하지 않습니다.
Christopher Berman 2012

3
bin / 디렉토리의 모든 파일을 추적하고 하위 디렉토리의 모든 파일을 무시하려면 다음 줄에서 수행 할 수 있습니다 ( bin/** \n !bin/*미니 마크 다운에서 줄 바꿈 을 강제하는 방법을 볼 수 없기 때문에)
TomRoche

9
이 대답은 여러면에서 잘못되었습니다. 첫째, git은 디렉토리를 추적하지 않으므로 .gitignore 항목은 디렉토리 내용과 일치 할 수 있으며 디렉토리와는 일치하지 않습니다. 둘째, 이름이 지정된 파일 폴더 의 내용을 모두bin 일치 시킵니다 . 셋째, 하위 디렉토리의 모든 파일 과 일치합니까 ? 이거 시험해 봤어? bin binbin/*
ThomasR

46

binbin/차이가 아니라 후자는 디렉토리와 일치합니다.

bin/**/*bin/**@VonC의 답변에 따르면 1.8.2 이후 로 동일 합니다.

까다로운 하나, 난 그냥 시간을 보냈다 정도 이상 내 머리를 추출한다는 점이다 bin/bin/**아니다 확실히 같은! 앞의 것은 디렉토리 전체를 무시하고 후자는 그 안의 각 파일을 무시하고 거의 모든 경우에 git은 디렉토리를 신경 쓰지 않기 때문에 일반적으로 차이가 없습니다. !그러나을 사용 하여 하위 경로 무시를 해제 하려고 하면 부모 디렉토리를 무시하면 git (ahem)이 무시 한다는 것을 알 수 있습니다! (디렉토리 내용이 아니라 다시)

이것은 예제에서 가장 명확하므로 새로 초기화 된 저장소의 경우 다음과 같이 설정됩니다.

$ cat .gitignore
ignored-file
or-dir
dir-only/
!dir-only/cant-reinclude
dir-contents/**
!dir-contents/can-reinclude

$ mkdir or-dir dir-only dir-contents

$ touch file ignored-file or-dir/ignored-file dir-only/cant-reinclude dir-contents/can-reinclude

다음과 같은 추적되지 않은 파일이 있습니다.

$ git ls-files --other
.gitignore
dir-contents/can-reinclude
dir-only/cant-reinclude
file
ignored-file
or-dir/ignored-file

그러나 다음 파일이 무시되지 않음을 알 수 있습니다.

$ git ls-files --other --exclude-standard
.gitignore
dir-contents/can-reinclude
file

추가하려고하면 다음과 같은 결과가 나타납니다.

$ git add dir-only/cant-reinclude
The following paths are ignored by one of your .gitignore files:
dir-only/cant-reinclude
Use -f if you really want to add them.
fatal: no files added

나는이 행동을 버그라고 생각한다. (모두 켜짐 git version 1.8.4.msysgit.0)


1
실제로 +1. 이 동작이 예상치 못한 것처럼 보이므로 실제 버그 보고서를 제출하는 것을 고려해야합니다.
chandsie

1
내 사용 사례입니다. 감사!
Sebastian Graf 2014 년

3
dir/dir/**re 의 다른 동작 . 무시 해제 !는 "파일의 상위 디렉토리가 제외되면 파일을 다시 포함 할 수 없습니다 . " [source ] 때문에 발생합니다. 혼란 스럽지만 성능상의 이유로 수행됩니다. 관련 SO 질문을 참조하십시오 .
tanius 2015 년

23

엄밀히 말하면 git은 디렉토리가 아니라 파일 만 추적합니다. 따라서 디렉토리를 추가 할 수 없으며 해당 내용 만 추가 할 수 있습니다 .

.gitignore그러나 맥락 에서 git은 다음과 같은 유일한 이유로 디렉토리를 이해하는 척합니다.

해당 파일의 상위 디렉토리가 제외 된 경우 파일을 다시 포함 할 수 없습니다.
https://git-scm.com/docs/gitignore#_pattern_format

이것은 제외 패턴에 대해 무엇을 의미합니까? 자세히 살펴 보겠습니다.

bin

이것은 무시합니다

  • 이름이 bin.
  • 이름이 지정된 폴더의 내용 bin

bin후속 !항목 을 추가하여 무시 된 파일 및 폴더를 허용 할 수 있지만 이름이 지정된 폴더 의 내용 을 허용 할 수는 없습니다.bin

bin

!bin/file_in_bin # has no effect, since bin/ is blacklisted!
!bin/* # has no effect, since bin/ is blacklisted!
!file_in_bin # has no effect, since bin/ is blacklisted!

!bin # this works

bin/

위와 동일, 일치하지 않는 것을 제외하고 파일 이름을 bin. 후행을 추가하면 /git이 디렉토리 만 일치하도록 지시합니다.

bin/*

이것은 무시합니다

  • 이름이 지정된 폴더에 포함 된 파일bin
  • 이름이 지정된 폴더의 직접 하위 폴더 내용 bin
bin/*  # blacklists bin/file_in_bin and bin/subfolder/

!bin/subfolder/file_in_sub # has no effect, since bin/subfolder is blacklisted!
!bin # whitelists files named bin/bin, since bin/ itself is not blacklisted
!bin/ # has no effect, since bin/ itself is not blacklisted


!bin/file_in_bin # works since bin/ itself is not blacklisted
!file_in_bin # works too
!bin/subfolder # works (so implicitly whitelists bin/subfolder/file_in_sub)
!bin/subfolder/ # works just as well
!bin/* # works for file_in_bin and subfolder/

bin/**

이것은 무시합니다

  • 내용 bin
  • 하위 폴더의 내용 (모든 중첩 수준) bin
bin/**  # blacklists bin/file_in_bin and
        # bin/subfolder/ and bin/subfolder/file_in_sub and
        # bin/subfolder/2/ and bin/subfolder/2/file_in_sub_2

!bin/subfolder/file_in_sub # has no effect, since bin/subfolder is blacklisted
!bin/subfolder/2/ # has no effect, since bin/subfolder is blacklisted
!bin/subfolder/2/file_in_sub_2 # has no effect, since bin/subfolder is blacklisted

!bin/subfolder # works only in combinations with other whitelist entries,
               # since all contents of subfolder are blacklisted (1)

!bin/file_in_bin # works since bin itself is not blacklisted
!bin/* # works for file_in_bin and subfolder; see (1)

9

방금 새 저장소를 만들고 몇 가지 시도했습니다. 내 결과는 다음과 같습니다.

새로운 결과

git 버전 2.10.1.windows.1

  1. 거의 비어있는 저장소를 초기화합니다. README 파일 만
  2. bin디렉터리를 여러 레이어 깊이 채 웁니다.
    • bin.txt
    • Test.txt
    • bin/a/b/bin.txt
    • bin/a/b/Test.txt
    • bin/a/bin/bin.txt
    • bin/a/bin/Test.txt
    • bin/a/bin.txt
    • bin/a/Test.txt
    • bin/bin.txt
    • bin/Test.txt
  3. bingitignore에 추가 : 결과
    • bin이제 디렉토리 아래 (및 더 깊은) 아래의 모든 항목 이 무시됩니다.
    • 루트 수준은 무시되지 않습니다 (/bin.txt 및 /Test.txt는 계속 표시됨).
  4. 편집 binbin/gitignore의 : 결과
    • 변경 없음
  5. 편집 bin/bin/*
    • 변경 없음
  6. 편집 bin/*bin/**
    • 변경 없음
  7. 편집 bin/**bin/**/
    • bin/bin.txt그리고 bin/Test.txt더 이상 무시하지 않습니다
  8. 편집 bin/**/bin/**/*
    • bin/bin.txt그리고 bin/Test.txt무시로 돌아

오래된 결과

git 버전 : 2.7.0.windows.1

  1. 거의 비어있는 저장소를 초기화합니다. README 파일 만
  2. bin디렉터리를 여러 레이어 깊이 채 웁니다.
    • bin/a/b/Test.txt
    • bin/a/bin/Test.txt
    • bin/a/Test.txt
    • bin/Test.txt
  3. bingitignore에 추가 : 결과
    • bin이제 디렉토리 아래 (및 더 깊은) 아래의 모든 항목 이 무시됩니다.
  4. 편집 binbin/gitignore의 : 결과
    • bin디렉토리 아래 (및 더 깊은) 아래의 모든 항목 은 여전히 ​​무시됩니다 (변경 없음).
  5. 편집 bin/bin/*
    • bin디렉토리 아래 (및 더 깊은) 아래의 모든 항목 은 여전히 ​​무시됩니다 (변경 없음).
  6. 편집 bin/*bin/**
    • bin디렉토리 아래 (및 더 깊은) 아래의 모든 항목 은 여전히 ​​무시됩니다 (변경 없음).
  7. 편집 bin/**bin/**/
    • bin/Test.txt 더 이상 무시되지 않습니다
  8. 편집 bin/**/bin/**/*
    • bin디렉토리 아래 (및 더 깊은) 아래의 모든 항목 이 다시 무시됩니다.

1
이것은 좋은 테스트이며 text.txt의 이름을 bin.txt로 바꾸면 몇 가지 주요 차이점을 더 잘 보여줄 수 있다고 생각합니다. 당신이 이것을했다면 나는이 대답에 투표 할 것입니다.
Matt Johnson

@MattJohnson True ... 불행히도 나는 현재 새로운 자식 버전을 사용하고 있습니다
Joe Phillips

@MattJohnson 나는 마침내 이것에 주위에
Joe Phillips

8

참고 그 ' **' 하위 디렉토리와 결합 할 때 ( **/bar)이 있기 때문에, 기본 동작 변경해야합니다 git1.8.2에 대한 릴리스 노트가 지금 언급 :

의 패턴 .gitignore.gitattributes파일을 가질 수 **/하위 디렉토리의 0 또는 그 이상의 수준을 일치하는 패턴으로,.

예를 들어 " foo/**/bar" bar는 " foo"자체 또는 " "의 하위 디렉토리 에서 " "와 일치 foo합니다.


기억해야 할 규칙 (그리고 해당 구문 뒤에있는 의도의 차이를 이해하는 데 도움이 됨)는 다음과 같습니다.

해당 파일의 상위 디렉토리가 제외 된 경우 파일을 다시 포함 할 수 없습니다.


일반적으로 무시 폴더 f의 하위 폴더에서 파일을 제외하려면 다음을 수행합니다.

f/**
!f/**/
!f/a/sub/folder/someFile.txt

그건:

  • 첫 번째 규칙이 f/이면 폴더 f/가 무시되고 관련 아래 규칙 f은 중요하지 않습니다.
  • f/**와 동일 f/하지만 모든 하위 요소 (파일 및 하위 폴더)를 무시합니다 .
    그러면 하위 폴더를 허용 목록 (gitignore에서 제외) 할 수 !f/**/있습니다..
  • 모든 f하위 폴더가 무시 되지 않으므로 파일 ( !f/a/sub/folder/someFile.txt) 을 제외하는 규칙을 추가 할 수 있습니다.

이것은 질문에 어떻게 대답합니까?
ThomasR

0

bin/*와 사이에는 또 다른 차이점이 있습니다 bin/.

bin/foo/bin/test.txt(예상대로) 일치 하지만 bin/*그렇지 않습니다. 이상하게 보이지만 문서화되었습니다 : https://git-scm.com/docs/gitignore

"Documentation / *. html"은 "Documentation / git.html"과 일치하지만 "Documentation / ppc / ppc.html"또는 "tools / perf / Documentation / perf.html"과는 일치하지 않습니다.

그 이유는 다음과 같은 규칙으로 보입니다.

  • 패턴이 슬래시로 끝나는 경우 다음 설명을 위해 제거됩니다.

  • 패턴에 슬래시 /가 포함되어 있지 않으면 Git은이를 쉘 glob 패턴으로 취급하고 .gitignore 파일의 위치에 상대적인 경로 이름과 일치하는지 확인합니다.

  • 그렇지 않으면 Git은 패턴을 FNM_PATHNAME 플래그를 사용하여 fnmatch (3)에서 사용하기에 적합한 쉘 glob으로 취급합니다.

따라서 패턴이 슬래시로 끝나면 슬래시가 제거되고 쉘 glob 패턴으로 처리되며이 경우 bin일치 foo/bin/test.txt합니다. 로 끝나는 경우 /*슬래시가 제거되지 않고 하위 디렉터리에서 일치하지 않는 fnmatch로 전달됩니다.

그러나 에서 후행 슬래시를 제거한 후에도 여전히 슬래시가 포함되어있어 glob이 아닌 fnmatch 패턴으로 처리 되기 때문에 foo/bin/및의 foo/bin/*경우도 마찬가지 foo/bin/입니다. 즉 일치하지 않습니다bar/foo/bin/test.txt

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.