티스토리 뷰
.gitignore에 분명히 추가했는데도 파일이 계속 변경 목록에 뜨는 경우가 있다. 오타를 의심하고 경로를 몇 번씩 확인하게 되는데, 열에 아홉은 문법 문제가 아니다.
원인: gitignore는 "이미 추적 중인 파일"에는 안 먹는다
이게 핵심이다. .gitignore는 아직 Git이 모르는 파일을 무시하라는 규칙이다. 한 번이라도 git add 된 파일은 이미 인덱스(스테이징 영역)에 등록돼 있고, 그 뒤에 gitignore에 추가해봐야 Git은 계속 추적한다.
그래서 순서가 이렇게 꼬인 경우에 문제가 생긴다.
- 프로젝트를 만들고
git add .로 전부 커밋 - 나중에
.env나node_modules가 들어간 걸 발견 .gitignore에 추가- 여전히 변경 목록에 뜸
해결: 인덱스에서 캐시를 걷어낸다
git rm -r --cached .
git add .
git commit -m "fix: apply gitignore"
--cached 옵션이 중요하다. 이건 인덱스에서만 제거하고 실제 파일은 건드리지 않는다. 이 옵션을 빼면 디스크에서 파일이 진짜 지워지니 절대 빠뜨리면 안 된다.
세 줄을 실행하면 Git이 추적 목록을 전부 비웠다가 다시 채우는데, 이때 .gitignore 규칙이 적용되면서 무시 대상이 빠진다.
전체가 아니라 특정 파일만 빼고 싶다면
위 명령은 전체를 다시 스테이징하기 때문에 작업 중이던 변경사항까지 같이 올라간다. 대상이 명확하면 그 파일만 지정하는 게 안전하다.
# 파일 하나
git rm --cached .env
# 디렉터리
git rm -r --cached node_modules
# 패턴
git rm --cached "*.log"
그래도 안 되면: 어느 규칙이 걸리는지 확인
규칙 자체가 잘못됐을 수도 있다. Git에는 이걸 알려주는 명령이 있다.
git check-ignore -v config/database.php
무시되고 있다면 어느 파일 몇 번째 줄의 어떤 규칙 때문인지 출력된다. 아무것도 안 나오면 그 파일은 무시 대상이 아니라는 뜻이니, gitignore 패턴을 다시 봐야 한다.
자주 걸리는 gitignore 문법 함정
1. 디렉터리를 통째로 무시하면 안쪽 예외가 안 먹는다
# 이렇게 하면 !storage/logs/.gitkeep 이 무시된다
storage/
!storage/logs/.gitkeep
# 이렇게 해야 예외가 동작한다
storage/*
!storage/logs
storage/logs/*
!storage/logs/.gitkeep
Git은 디렉터리 자체를 제외하면 그 안을 아예 들여다보지 않는다. 그래서 하위 항목을 !로 되살릴 수 없다. 상위 디렉터리를 /* 로 열어두고 단계별로 내려가야 한다.
2. 슬래시 위치에 따라 의미가 다르다
build: 어느 depth에 있든 이름이 build인 파일·디렉터리 전부/build: 저장소 루트의 build만build/: 디렉터리만 (같은 이름의 파일은 무시 안 함)
3. 빈 디렉터리는 Git이 추적하지 않는다
로그 디렉터리 구조만 유지하고 싶으면 안에 .gitkeep 같은 빈 파일을 하나 넣고 그것만 예외 처리해야 한다.
이미 push된 민감 정보라면 이야기가 다르다
.env나 API 키가 이미 원격 저장소에 올라갔다면, git rm --cached 로는 부족하다. 그건 "앞으로 추적하지 않겠다"는 뜻일 뿐, 과거 커밋 히스토리에는 그대로 남아 있다. 누구든 이전 커밋을 체크아웃하면 볼 수 있다.
이 경우 해야 할 일은 두 가지다.
- 키를 즉시 폐기하고 재발급한다. 이게 1순위다. 히스토리 정리보다 먼저다.
- 히스토리에서 제거하려면
git filter-repo또는 BFG Repo-Cleaner를 쓴다. 다만 커밋 해시가 전부 바뀌므로 협업 중인 저장소라면 팀원 전체가 다시 클론해야 한다.
공개 저장소에 올라간 키는 봇이 몇 분 안에 수집해간다고 보는 게 안전하다. 히스토리를 아무리 깔끔하게 지워도 이미 긁혔을 가능성이 있으니 재발급이 먼저다.
예방: 전역 gitignore 설정
.DS_Store, Thumbs.db, IDE 설정 폴더처럼 프로젝트와 무관하게 매번 걸리는 것들은 전역으로 빼두면 편하다.
git config --global core.excludesfile ~/.gitignore_global
# ~/.gitignore_global
.DS_Store
Thumbs.db
.idea/
.vscode/
*.swp
프로젝트 .gitignore에 .idea/ 같은 개인 환경 설정을 넣는 건 사실 다른 팀원 입장에서 불필요한 항목이다. 전역으로 빼두는 쪽이 협업할 때 깔끔하다.
정리
- 적용 안 되는 이유 대부분은 이미 추적 중인 파일이기 때문이다
git rm -r --cached .후 다시 add·commit (--cached빠뜨리면 파일이 삭제된다)- 규칙이 의심되면
git check-ignore -v로 확인 - 디렉터리 전체 제외 시 하위 예외(
!)는 안 먹는다./*로 단계별 처리 - 이미 push된 비밀키는 재발급이 먼저, 히스토리 정리는 그다음
'기타 개발' 카테고리의 다른 글
| 구형 세탁기를 IOT 세탁기로 만들기 (0) | 2023.04.22 |
|---|---|
| 티스토리에 구글애드센스 광고 정말 빠르고 쉽게 달기 feat. 블로그 (0) | 2018.10.23 |
| docker 로 PHP 개발환경 만들기 (0) | 2018.09.20 |
| 설치 없이 웹으로 ERD 그리기, 도구 비교와 선택 기준 (0) | 2018.08.31 |
| HTTP/응답코드 (0) | 2018.08.29 |
