Git 추적 막는 방법 총정리
Git을 쓰다 보면 “이 파일은 추적하지 마!” 하고 싶을 때가 참 많습니다.
.env 파일에 담긴 비밀 키, node_modules처럼 덩치 큰 의존성 폴더, IDE가 만들어내는 .idea나 .vscode 디렉토리까지.
대부분은 .gitignore에 한 줄 추가하면 끝이지만 실제로는 그것만으로 해결되지 않는 상황이 꽤 있습니다.
“팀 전체가 아니라 나만 무시하고 싶은 파일이 있는데?”, “이미 커밋된 파일인데 이제 와서 무시하려면?”, “설정 파일을 로컬에서만 살짝 바꿔 쓰고 싶은데?”
이번 글에서는 Git에서 파일 추적을 막는 모든 방법을 하나씩 살펴보겠습니다. 상황별로 어떤 방법을 써야 하는지 감이 잡힐 거예요.
.gitignore — 팀과 함께 무시할 파일 정하기
가장 기본이 되는 방법은 프로젝트 루트에 .gitignore 파일을 만드는 것입니다.
node_modules/
dist/
.env
*.log
.gitignore 파일 자체가 Git에 커밋되기 때문에 여기에 적은 규칙은 팀원 모두가 공유하게 됩니다.
“우리 프로젝트에서는 이 파일들은 추적하지 말자”고 합의하는 공식적인 장소라고 보면 돼요.
하위 디렉토리에도 .gitignore를 놓을 수 있는데 이때 패턴은 그 디렉토리 기준으로 적용됩니다.
예를 들어 docs/.gitignore에 *.pdf를 적으면 docs/ 폴더 안의 PDF만 무시됩니다.
.gitignore파일의 패턴 문법과 기본 사용법은 .gitignore 파일 사용법에서 자세히 다루고 있습니다.
.git/info/exclude — 나만 무시하고 싶을 때
팀 전체가 아니라 나 혼자만 무시하고 싶은 파일이 있을 수 있습니다. 예를 들어 개인적인 메모 파일, 테스트용 스크립트, 혹은 본인만 쓰는 도구가 생성하는 파일 같은 것들이요.
이런 파일을 .gitignore에 넣으면 팀원들에게 “이게 뭐야?” 하는 의문만 남기게 되죠.
이럴 때 쓰는 것이 .git/info/exclude 파일입니다.
# 나만 쓰는 메모
notes.txt
# 개인 테스트 스크립트
test-local.sh
# 특정 IDE 설정
.my-editor-config
.git/ 디렉토리 안에 있기 때문에 원격 저장소에 올라가지 않습니다.
오직 내 로컬 환경에서만 동작하는 개인 전용 .gitignore인 셈이죠.
패턴 문법은 .gitignore와 완전히 동일하니 사용법을 따로 익힐 필요가 없습니다.
글로벌 ignore — 모든 프로젝트에 걸쳐서 무시하기
macOS를 쓴다면 .DS_Store, IntelliJ를 쓴다면 .idea/, Vim 사용자라면 *.swp 파일이 모든 프로젝트에서 거슬릴 겁니다.
이런 파일을 매번 프로젝트마다 .gitignore에 추가하는 건 번거롭기도 하고 다른 OS나 에디터를 쓰는 팀원에게는 불필요한 규칙이 됩니다.
글로벌 ignore 파일을 세팅해두면 한 방에 해결됩니다.
기본 위치는 ~/.config/git/ignore이고 여기에 규칙을 적어두면 끝이에요.
# macOS
.DS_Store
# IDE
.idea/
.vscode/
*.iml
# Editor swap files
*.swp
*.swo
*~
# Thumbnails
Thumbs.db
이렇게 해두면 어떤 프로젝트에서든 별도 설정 없이 이 파일들이 자동으로 무시됩니다.
재밌는 사실 하나 알려드리면, Claude Code(AI 코딩 도구)는 설치할 때 이 글로벌 ignore 파일에 **/.claude/settings.local.json을 자동으로 추가해둡니다 🤫
프로젝트마다 생기는 로컬 설정 파일이 실수로 커밋되는 걸 방지하려는 거죠.
글로벌 ignore를 이런 식으로 쓰면 개인 도구들의 부산물을 깔끔하게 관리할 수 있습니다.
기본 경로 대신 다른 위치를 사용하고 싶다면 core.excludesFile로 경로를 지정할 수 있습니다.
git config --global core.excludesFile ~/.gitignore_global
git config명령어의 범위(local, global, system)에 대해서는 git config 명령어 사용법에서 자세히 다루고 있습니다.
세 가지 ignore의 우선순위
.gitignore, .git/info/exclude, 글로벌 ignore를 모두 사용할 수 있다면, 서로 충돌하면 어떻게 될까 궁금해질 텐데요.
Git은 다음 순서로 규칙을 평가하며 나중에 평가되는 것이 우선합니다.
core.excludesFile에 지정된 글로벌 ignore 파일.git/info/exclude- 프로젝트 루트의
.gitignore - 하위 디렉토리의
.gitignore(파일에 가까울수록 우선)
같은 파일 안에서는 나중에 나오는 규칙이 우선이에요.
그래서 ! 부정 패턴이 동작하는 겁니다.
# 모든 로그 무시
*.log
# 하지만 error.log는 추적
!error.log
어떤 규칙 때문에 파일이 무시되는지 헷갈릴 때는 git check-ignore 명령어가 유용합니다.
$ git check-ignore -v debug.log
.gitignore:3:*.log debug.log
어느 파일의 몇 번째 줄에 있는 어떤 패턴 때문에 무시되는지 한눈에 보여줘요.
git rm —cached — 이미 추적 중인 파일 무시하기
여기서부터가 사실 많은 분들이 헤매는 구간입니다.
.gitignore는 아직 추적되지 않은 파일에만 효력이 있습니다.
한 번이라도 git add로 스테이징하고 커밋한 파일은 .gitignore에 추가해도 Git이 계속 추적합니다.
예를 들어 .env 파일을 실수로 커밋했다고 해볼게요.
$ echo "SECRET_KEY=abc123" > .env
$ git add .env && git commit -m "add env"
뒤늦게 .gitignore에 .env를 추가해봤자 Git은 이미 추적 중인 .env의 변경 사항을 계속 감지합니다.
여기서 git rm --cached를 꺼내야 합니다.
$ echo ".env" >> .gitignore
$ git rm --cached .env
rm '.env'
$ git commit -m "stop tracking .env"
--cached 옵션이 핵심인데요. 이 옵션 없이 git rm .env를 실행하면 파일이 디스크에서 실제로 삭제돼 버립니다.
--cached를 붙이면 Git의 인덱스(추적 목록)에서만 제거하고 로컬 파일은 그대로 남겨둡니다.
디렉토리 전체를 제거할 때는 -r 옵션을 함께 써야 합니다.
$ git rm --cached -r .idea/
한 가지 주의할 점이 있는데, 이렇게 커밋하고 팀원이 git pull을 받으면 팀원의 로컬에서는 그 파일이 삭제됩니다.
민감한 파일이라면 팀원에게 미리 알려주는 게 좋겠죠.
assume-unchanged — 변경 감지 잠깐 끄기
가끔 추적 중인 파일을 로컬에서 수정했는데 그 변경 사항을 Git에 알리고 싶지 않을 때가 있습니다. 예를 들어 데이터베이스 접속 정보가 담긴 설정 파일을 로컬 환경에 맞게 바꿔 쓰는 경우가 대표적이죠.
$ git update-index --assume-unchanged config/database.yml
이렇게 하면 Git이 이 파일의 변경을 감지하지 않습니다.
git status에도 나타나지 않고 git diff에서도 보이지 않아요.
되돌리려면 --no-assume-unchanged를 쓰면 됩니다.
$ git update-index --no-assume-unchanged config/database.yml
현재 어떤 파일에 플래그가 설정되어 있는지 확인하려면 git ls-files -v를 사용합니다.
소문자 h로 시작하는 파일이 assume-unchanged가 걸린 파일이에요.
$ git ls-files -v | grep ^h
h config/database.yml
다만 이 방법에는 중요한 제약이 있습니다.
원래 느린 파일 시스템에서 성능을 올리려고 만든 기능이라 파일 변경을 숨기는 용도로는 맞지 않아요.
git pull이나 git merge할 때 원격에서 그 파일이 변경되면 충돌이 발생하고 병합에 실패할 수 있습니다.
skip-worktree — 로컬 설정 파일 보호하기
assume-unchanged와 비슷하지만 좀 더 강력한 방법이 skip-worktree입니다.
$ git update-index --skip-worktree config/database.yml
되돌리려면 마찬가지로 --no-skip-worktree를 쓰면 됩니다.
$ git update-index --no-skip-worktree config/database.yml
assume-unchanged와 뭐가 다른 건지 궁금하실 텐데요. 핵심적인 차이가 있습니다.
assume-unchanged는 Git에게 “이 파일은 변경되지 않았다고 가정해”라고 말하는 겁니다.
성능 최적화용이라 Git이 필요하면 언제든 이 가정을 무시할 수 있어요.
반면 skip-worktree는 “이 파일의 워킹 트리 버전을 쓰지 마”라고 말하는 겁니다.
원래 sparse checkout(부분 체크아웃)을 위해 설계된 것이라 좀 더 의도가 명확하고 안정적이에요.
둘 다 로컬 설정 파일을 보호하는 용도로 흔히 쓰이지만 용도에 더 맞는 건 skip-worktree입니다.
그래도 Git 공식 문서에서는 두 방법 모두 추적 중인 파일의 변경을 숨기는 용도로 쓰는 걸 권장하지 않습니다. 대신 다음과 같은 패턴을 추천해요.
- 저장소에는 템플릿 파일을 커밋한다 (예:
.env.example) - 실제 설정 파일명을
.gitignore에 추가한다 (예:.env) - 개발자가 템플릿을 복사해서 로컬 설정을 만든다
$ cp .env.example .env
# .env를 로컬 환경에 맞게 수정
이렇게 하면 assume-unchanged나 skip-worktree 같은 트릭 없이도 깔끔하게 관리됩니다.
한눈에 비교하기
지금까지 살펴본 방법들을 정리해볼게요.
| 방법 | 범위 | 팀 공유 | 이미 추적 중인 파일 | 언제 쓰나 |
|---|---|---|---|---|
.gitignore | 프로젝트 | O (커밋됨) | X | 팀 전체가 무시할 파일 |
.git/info/exclude | 프로젝트 | X (로컬) | X | 나만 무시할 파일 |
~/.config/git/ignore | 전체 | X (사용자) | X | OS/에디터 관련 파일 |
git rm --cached | 프로젝트 | O (커밋됨) | O | 이미 추적 중인 파일 제거 |
--assume-unchanged | 프로젝트 | X (로컬) | O | 임시로 변경 감지 끄기 |
--skip-worktree | 프로젝트 | X (로컬) | O | 로컬 설정 파일 보호 |
자주 하는 실수와 해결법
Git ignore 쓸 때 자주 하는 실수 몇 가지를 짚어볼게요.
.gitignore에 추가했는데 파일이 여전히 추적되는 경우부터 볼게요.
위에서 설명한 것처럼 이미 커밋된 파일은 .gitignore가 효력이 없습니다.
git rm --cached로 인덱스에서 제거한 후 다시 커밋해야 합니다.
디렉토리 무시가 안 된다고요?
끝에 /를 붙여야 디렉토리만 매칭됩니다.
# 이렇게 쓰면 build라는 이름의 파일도 무시됨
build
# 이렇게 쓰면 build 디렉토리만 무시됨
build/
부정 패턴(!)을 썼는데 왜 안 먹히지? 싶을 때도 있습니다. 부모 디렉토리가 이미 무시된 상태라면 그 안의 파일을 !로 되살릴 수 없어요.
# 이렇게 하면 안 됩니다
logs/
!logs/important.log
# 이렇게 해야 합니다
logs/*
!logs/important.log
logs/는 디렉토리 자체를 무시하므로 Git이 아예 안을 들여다보지 않습니다.
logs/*는 디렉토리 안의 파일들을 무시하는 것이라 !로 예외를 둘 수 있어요.
마치며
Git에서 파일 추적을 막는 방법은 하나가 아닙니다. 상황에 따라 적절한 도구를 골라 써야 깔끔한 저장소를 유지할 수 있어요.
팀과 공유할 규칙은 .gitignore에, 개인적인 규칙은 .git/info/exclude에, OS나 에디터 관련 파일은 글로벌 ignore에 넣는 것이 기본 원칙입니다.
이미 추적 중인 파일을 제거해야 할 때는 git rm --cached를 쓰고, 로컬에서만 변경 사항을 숨기고 싶다면 skip-worktree를 검토해보세요.
.gitignore의 패턴 문법에 대해 더 알고 싶다면 .gitignore 파일 사용법을, Git 설정의 범위 체계가 궁금하다면 git config 명령어 사용법을 참고해보세요.
Git 공식 문서의 gitignore와 git-update-index 페이지도 도움이 될 겁니다. GitHub에서는 여러 언어와 프레임워크에 맞는 .gitignore 템플릿도 제공하고 있으니 새 프로젝트를 시작할 때 참고하면 좋겠습니다.
This work is licensed under
CC BY 4.0