콘텐츠로 건너뛰기
Codex

.gitignore에 적었는데 하위 폴더 파일이 계속 잡힐 때

TECH NOTE · AUTOMATION OPS

gitignore에 적은 규칙이 하위 폴더에서 안 먹는 이유는 슬래시 위치 때문입니다. 패턴 중간에 슬래시가 있으면 저장소 루트 기준이 되고, git은 아무 경고도 하지 않습니다.

분명히 적었는데 계속 잡힌다

예제 저장소에 커밋하려는데 빌드 산출물이 딸려 왔다. .gitignore에 적었는데도 그랬다.

gen/schemas/

이 한 줄을 적고 git add -A를 했는데 overlay-window/gen/schemas/ 아래 파일 네 개가 그대로 스테이징됐다. git reset으로 풀고 다시 해도 똑같았다.

오타도 아니고 문법 오류도 아니다. git이 아무 말도 안 해 준다. 스테이징된 줄 수가 5,011줄로 찍히는 걸 보고서야 뭔가 이상하다는 걸 알았다.

원인은 슬래시의 위치다.

슬래시가 중간에 있으면 루트 기준이 된다

.gitignore 패턴에는 규칙이 하나 있다. 패턴 안에 슬래시가 있으면 — 맨 끝에 붙은 것은 빼고 — 그 패턴은 저장소 루트에서 시작하는 경로로 읽힌다.

gen/schemas/     →  /gen/schemas/ 만 가리킨다

즉 저장소 최상위에 gen 폴더가 있을 때만 걸린다. app/gen/schemas/overlay-window/gen/schemas/는 대상이 아니다.

반면 슬래시가 끝에만 있거나 아예 없으면 어느 깊이에서든 걸린다.

target/          →  모든 하위 폴더의 target/ 을 잡는다
node_modules/    →  마찬가지
.DS_Store        →  마찬가지

.gitignore를 처음 쓸 때 적는 것들이 대부분 후자라, 이 차이를 모르고 지나가기 쉽다. target/이 잘 되니까 gen/schemas/도 될 거라고 생각한다.

직접 재현해 보면

빈 저장소로 확인할 수 있다.

git init -q .
mkdir -p app/gen/schemas src
echo x > app/gen/schemas/a.json
echo x > src/main.rs

먼저 문제가 되는 패턴이다.

printf 'gen/schemas/\n' > .gitignore
git add -A && git status --short
A  .gitignore
A  app/gen/schemas/a.json      ← 잡혔다
A  src/main.rs

**를 붙이면 달라진다.

git reset -q
printf '**/gen/schemas/\n' > .gitignore
git add -A && git status --short
A  .gitignore
A  src/main.rs

app/gen/schemas/a.json이 목록에서 빠졌다.

어느 규칙이 걸렸는지 물어보는 명령

이 문제를 빨리 찾는 방법이 있다. git check-ignore-v를 붙이면 어느 파일의 몇 번째 줄이 그 경로를 잡았는지 알려준다.

고치기 전에는 아무것도 안 나온다.

git check-ignore -v app/gen/schemas/a.json
# (출력 없음, 종료 코드 1)

고친 뒤에는 이렇게 나온다.

.gitignore:1:**/gen/schemas/	app/gen/schemas/a.json

파일:줄번호:패턴 순서다. 규칙이 여러 파일에 흩어져 있을 때 특히 쓸모 있다 — 전역 .gitignore.git/info/exclude에 있는 규칙도 여기서 잡힌다.

출력이 없다는 것이 곧 답이다. 그 경로는 어떤 규칙에도 안 걸리고 있다는 뜻이다.

이미 추적 중이면 규칙을 고쳐도 안 빠진다

여기서 두 번째 함정이 있다. .gitignore아직 추적하지 않는 파일에만 적용된다. 한 번 커밋된 파일은 규칙을 나중에 추가해도 계속 따라온다.

git rm -r --cached gen/schemas

--cached가 중요하다. 이게 없으면 디스크의 파일까지 지운다. 빌드 산출물이면 다시 만들면 그만이지만, 설정 파일이었다면 곤란해진다.

헷갈리는 패턴 정리

실제로 자주 쓰는 것만 모으면 이렇다.

패턴 걸리는 것
build/ 모든 깊이의 build 폴더
/build/ 저장소 최상위의 build 폴더만
doc/build/ 최상위 doc 안의 build
**/doc/build/ 어느 깊이든 doc/build
*.log 모든 깊이의 .log 파일
logs/*.log 최상위 logs 안의 것만

규칙은 하나다. 패턴 중간에 슬래시가 있으면 경로가 고정된다. 그게 싫으면 **/를 앞에 붙인다.

정리

  • 패턴 중간에 슬래시가 있으면 저장소 루트 기준이 된다
  • 하위 폴더까지 잡으려면 **/를 앞에 붙인다
  • git check-ignore -v <경로>로 어느 규칙이 걸렸는지 확인한다. 출력이 없으면 안 걸린 것이다
  • 이미 추적 중인 파일은 git rm -r --cached로 빼야 한다
  • git은 패턴이 아무것도 안 잡아도 경고하지 않는다. 스스로 확인해야 한다

target/처럼 슬래시가 끝에만 있는 패턴이 잘 동작해서, 슬래시가 중간에 들어간 순간 규칙이 달라진다는 걸 모르고 지나가기 쉽다. 한 번 겪으면 안 잊는 종류의 문제다.

이 블로그 더 보기

이 블로그는 실제 프로젝트를 AI와 함께 굴리면서 남긴 기록입니다.

  • 새 글은 RSS로 받아볼 수 있습니다.
  • 시리즈 전체는 여기에 정리해 두었습니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다