개발노트

.gitignore에 넣었는데 .env가 계속 올라간다면

설정 파일을 무시 목록에 넣는 것과 이미 시작한 추적을 해제하는 것은 다릅니다. 가짜 값으로 재현하고 실제 키가 노출됐을 때의 우선순위도 구분합니다.

서버 설정을 .env에 넣고, 깃허브에 올리기 전에 .gitignore에도 파일 이름을 적었습니다. 그런데 변경 목록에 계속 나타납니다. 분명 무시하라고 했는데 왜 그럴까요?

이때 먼저 확인할 것은 무시 규칙의 문법보다 이 파일을 이미 Git에 추가한 적이 있는지입니다. 한 번 추적을 시작한 파일은 나중에 무시 목록에 넣어도 자동으로 빠지지 않습니다. 이번 글에서는 가짜 설정 파일로 이 차이를 재현했습니다. 운영 중인 이 사이트의 키나 저장소 이력을 시험에 사용하지 않았습니다.

먼저, 실제 키를 올린 상황이라면

이미 비밀번호나 API 키를 원격 저장소에 올렸다면 실습부터 따라 하지 마세요. 해당 서비스에서 노출된 키를 폐기하거나 교체하는 일이 먼저입니다. 파일을 지우거나 저장소를 비공개로 바꾸는 것만으로 이미 복사된 값까지 없앨 수는 없습니다.

GitHub의 민감한 데이터 제거 안내도 비밀 값의 폐기·교체를 첫 단계로 설명합니다. 이력 정리는 별도의 문제이며 협업자와 조율해야 합니다. 이 글은 이력을 재작성하거나 외부에 남은 사본을 제거하는 절차까지 다루지는 않습니다.

무시 목록과 추적 목록은 다릅니다

Git에는 다음 커밋에 넣을 상태를 준비하는 인덱스가 있습니다. 여기에서 관리하고 있는 파일을 흔히 ‘추적 중’이라고 부릅니다. 반면 .gitignore는 아직 추적하지 않는 파일을 일반적인 추가 대상에서 제외하는 규칙입니다. ‘이미 들어간 파일을 빼는 명령’은 아닙니다. 이 구분은 Git 공식 문서에서도 확인할 수 있습니다.

상황/.env 규칙을 추가한 뒤
한 번도 추가하지 않은 루트 .env일반적인 git add 대상에서 제외됩니다.
이미 추가하거나 커밋한 루트 .env추적이 계속됩니다. 따로 해제해야 합니다.
예전 커밋에 들어 있는 .env현재 파일의 추적을 해제해도 과거 내용은 남습니다.

위 표의 규칙은 저장소 최상위에 있는 .gitignore에 /.env를 적었을 때를 기준으로 합니다. 하위 폴더의 설정 파일이나 .env.production까지 전부 처리하는 규칙은 아닙니다. 자신의 실제 파일 이름과 위치를 따로 확인해야 합니다.

임시 저장소에서 네 가지를 확인했습니다

실행에 쓴 코드는 Git 환경 파일 추적 실습 파일로 내려받을 수 있습니다. Python 3과 Git이 설치된 환경에서 다음처럼 실행합니다. 표준 라이브러리만 사용하며 패키지를 추가로 설치하지 않습니다.

python3 git-env-ignore-demo.py

실습은 임시 폴더에 새 저장소를 만들고 DEMO_TOKEN=NOT_A_REAL_SECRET이라는 가짜 값만 넣습니다. 원격 저장소를 연결하거나 push하지 않습니다. 기존 프로젝트 파일과 전역 Git 설정도 수정하지 않으며, 끝나면 만든 임시 폴더를 삭제합니다.

1. After .gitignore: tracked=.env
2. After rm --cached: local_exists=True, tracked=False
3. Earlier commit: dummy value still exists
4. Template tracked=.env.example; working tree clean
Temporary repository removed. No remote or real credentials used.

2026년 10월 26일 로컬 실행에서 위 결과를 확인했습니다. 첫 줄은 무시 규칙을 추가해도 기존 추적이 이어진다는 뜻입니다. 둘째 줄에서는 파일을 컴퓨터에 남긴 채 추적만 해제했습니다. 셋째 줄은 가장 중요한 한계입니다. 예전 커밋을 열면 가짜 값이 여전히 나옵니다. 마지막에는 값이 비어 있는 예제 파일만 추적하도록 바꿨습니다.

내 프로젝트에서는 내용 대신 파일 이름부터 확인합니다

아래 명령은 실습용 저장소가 아니라 자신의 프로젝트에서 확인할 때 쓰는 예시입니다. 먼저 올바른 폴더인지 확인하세요. 설정 값이 들어 있는 파일 전체를 터미널에 출력하거나 상담 화면에 붙여 넣을 필요는 없습니다.

git rev-parse --show-toplevel
git status --short
git ls-files -- .env

마지막 명령에서 .env가 나오면 현재 인덱스가 해당 경로를 추적하고 있다는 뜻입니다. 아무것도 나오지 않아도 ‘과거에 유출된 적이 없다’는 뜻은 아닙니다. 현재 추적 상태와 과거 이력은 서로 다른 질문입니다.

최상위 .env만 추적에서 뺄 계획이라면, 최상위 .gitignore에 아래 규칙을 추가합니다. 기존 규칙을 통째로 덮어쓰지 말고 필요한 줄을 보태면 됩니다.

/.env

그다음 git rm 문서의 --cached 옵션으로 인덱스에서만 뺍니다. 아래 명령에서 --cached를 생략하지 마세요. 생략하면 작업 폴더의 파일도 삭제 대상이 됩니다.

git rm --cached -- .env
git add -- .gitignore
git diff --cached --name-status
git ls-files -- .env

추적 해제 직후에는 준비된 변경 목록에 D .env가 나타납니다. 저장소의 다음 스냅샷에서 빠진다는 뜻이지, --cached로 처리한 로컬 파일까지 지웠다는 뜻은 아닙니다. 파일 탐색기에서도 실제 파일이 남았는지 확인하세요. 마지막 명령에서는 해당 경로가 나오지 않아야 합니다.

명령이 변경 충돌 등을 이유로 거부되면 멈추고 상태부터 확인하세요. 이 예제를 맞추려고 -f를 추가하거나 저장소 전체를 한꺼번에 추적 해제할 필요는 없습니다. 준비된 변경에 다른 작업이 섞여 있다면 그것도 함께 검토한 뒤 커밋해야 합니다.

빈 값의 예제 파일은 남겨둡니다

실제 설정 파일을 빼고 나면 새로 받은 프로젝트가 어떤 설정을 요구하는지 알기 어려워집니다. 그래서 변수 이름과 설명만 담은 .env.example을 별도로 두는 편이 좋습니다. 다음은 이 글을 위한 가상 예제입니다.

HOST=127.0.0.1
PORT=3001
DEMO_TOKEN=

실제 파일을 그대로 복사한 뒤 몇 군데만 지우는 것보다 필요한 항목을 빈 값으로 새로 작성하면 빠뜨릴 위험을 줄일 수 있습니다. 예제 파일에는 운영 비밀번호, 실제 토큰, 개인정보를 넣지 않습니다. 공개해도 되는 기본값인지도 항목별로 확인합니다.

.env.example을 쓰려면 프로그램이나 실행 도구가 어느 파일을 읽는지도 문서에 적어두세요. 이름이 .env라고 해서 모든 프로그램이 자동으로 읽어주는 것은 아닙니다. 설정 로딩은 Git이 아니라 애플리케이션의 역할입니다.

커밋하기 전에는 세 질문만 확인합니다

  • 실제 설정 파일은 내 컴퓨터에 남아 있고, 현재 Git 추적 목록에서는 빠졌나요?
  • 공개할 예제 파일에 실제 비밀 값이나 개인정보가 없는지 확인했나요?
  • 예전에 키를 올렸다면 파일 삭제와 별개로 그 키를 폐기하거나 교체했나요?

이 변경이 포함된 커밋을 동료나 배포 서버가 받으면, 그쪽에서 이전에 추적하던 파일도 삭제될 수 있습니다. 반영 전에 각 환경의 설정을 안전하게 별도 보관하고, 업데이트 뒤 필요한 설정이 있는지 확인하세요. 보관본도 비밀 정보이므로 공유 폴더나 저장소에 두지 않습니다.

여기까지 하면 ‘앞으로 해당 파일을 일반적인 커밋에 넣지 않기 위한 정리’가 된 것입니다. 과거 이력과 이미 퍼진 값까지 정리됐다고 보지는 마세요. 특히 저장소 이력을 바꾸는 작업은 배포와 다른 사람의 작업에 영향을 줄 수 있으니, 위의 GitHub 안내를 읽고 별도로 계획하는 편이 낫습니다.

실전노트 목록 문의하기

댓글

0개

아직 표시된 댓글이 없습니다.

Google 계정으로 댓글 작성

이메일은 일부를 가린 아이디로 표시됩니다.