Git에서 파일을 무시하는 방법은 .gitignore만이 아님
(nelson.cloud)- Git의 파일 무시 규칙은 공유 범위에 따라
.gitignore,.git/info/exclude,~/.config/git/ignore의 세 수준으로 나뉨 .gitignore는 저장소 코드와 함께 커밋되므로, 팀이나 프로젝트가 함께 적용해야 하는 공유 규칙을 두는 위치임- 개인 파일이나 로컬 작업용 파일처럼 저장소에는 필요하지만 팀 규칙으로 만들기 애매한 항목은
.git/info/exclude에 두는 편이 적합함 - macOS의
.DS_Store처럼 모든 저장소에서 반복적으로 제외할 파일은 머신 전역 ignore 파일인~/.config/git/ignore에 넣을 수 있음 git check-ignore -v <파일명>은 어떤 규칙이 파일을 무시하는지 추적할 때 유용하며, 매칭되는 규칙이 없으면 출력이 없음
Git ignore 규칙의 적용 위치
- Git은 파일 무시 규칙을 세 위치에서 처리할 수 있음
.gitignore.git/info/exclude~/.config/git/ignore
.gitignore: 저장소에 커밋되는 공유 규칙
.gitignore는 무시할 파일명을 작성하는 일반적인 파일임- 나머지 코드와 함께 Git에 체크인됨
.gitignore규칙에 매칭되는 파일은git명령 실행 시 고려되지 않음
.git/info/exclude: 저장소별 개인 규칙
exclude파일은 모든 Git 저장소의.git디렉터리 안에 있음- 이 파일의 변경 사항은 Git에 체크인되지 않음
- 새 Git 저장소에서는 보통 몇 줄의 주석이 들어 있음
- 저장소별로만 무시하고 싶지만
.gitignore에는 넣고 싶지 않은 파일에 적합함- 예: 개인 워크플로에만 필요한
notes.txt를 저장소에 커밋하지 않고, 프로젝트의.gitignore에도 추가하지 않으려면.git/info/exclude에notes.txt를 추가함
- 예: 개인 워크플로에만 필요한
~/.config/git/ignore: 머신 전역 규칙
- 전역
ignore파일은 홈 디렉터리의~/.config/git/ignore에 있음 - 여기에 추가한 파일명은 머신 수준에서 전역 무시됨
- Git에 체크인되지 않으며 특정 저장소와 연결되지 않음
- 컴퓨터의 모든 Git 저장소에서 무시하고 싶은 파일을 넣기 좋은 위치임
- 예: macOS에서는
.DS_Store를 여기에 추가하는 것이 적합함
- 예: macOS에서는
전역 ignore 파일 경로 바꾸기
- 전역 ignore 파일은 다른 파일로 지정할 수 있음
- 전역 Git ignore 파일을
.gitignore_global로 쓰려면 다음 명령을 실행함
git config --global core.excludesFile ~/.gitignore_global
- 기본 설정으로 되돌리려면 다음 명령을 실행함
git config --global --unset core.excludesFile
어떤 규칙이 파일을 무시하는지 확인하기
git check-ignore -v <파일명>으로 특정 파일이 어떤 규칙에 의해 무시되는지 확인할 수 있음.DS_Store가 어떻게 무시되는지 확인하려면 Git 저장소 안에서 다음 명령을 실행함
git check-ignore -v .DS_Store
- 저장소의
.gitignore가.DS_Store를 무시하는 경우 출력 예시는 다음과 같음
$ git check-ignore -v .DS_Store
.gitignore:1:.DS_Store .DS_Store
- 저장소의
.git/info/exclude가.DS_Store를 무시하는 경우 출력 예시는 다음과 같음
$ git check-ignore -v .DS_Store
.git/info/exclude:7:.DS_Store .DS_Store
- 전역
~/.config/git/ignore파일이.DS_Store를 무시하는 경우 출력 예시는 다음과 같음
$ git check-ignore -v .DS_Store
/Users/nelson/.config/git/ignore:2:.DS_Store .DS_Store
- 사용자 지정 전역 ignore 파일
.gitignore_global이.DS_Store를 무시하는 경우 출력 예시는 다음과 같음
$ git check-ignore -v .DS_Store
/Users/nelson/.gitignore_global:1:.DS_Store .DS_Store
- 특정 파일을 무시하는 규칙이 없으면
git check-ignore -v명령은 아무 출력도 내지 않음
댓글과 토론
저는 프로젝트를 벗어난 local global 설정을 싫어합니다. 혼자 일하면 상관없겠지만 대부분 다 협업이라서 이런 환경 맞추는 거 너무 번거로워요. 물론 대표적으로 ds_store 이파일이 진짜 짜치긴 하지만, 이것 역시 로컬 프로젝트에 다 gitignore 넣을건데 그렇게 관리할게 편한거 같습니다.
Hacker News 의견들
-
재미있는 글이지만, Git에서 제일 좋아하는 거의 무시하기 기능인
.gitattributes가 빠져 있음
이 파일로 특정 파일의 차이를 Git이 "무시"하게 지정할 수 있음. 예를 들어 Node 프로젝트의package-lock.json은 Git 관점에서는 순수한 잡음에 가까움. 라이브러리의 구체 버전이 들어간 거대한 차이만 나오고, 사람이 읽기 쉬운 실제 버전 정보는 별도package.json에 있음
프로젝트 루트의.gitattributes에package-lock.json -diff한 줄을 추가하면, 파일은 계속 스테이징/커밋되지만git diff에서는 의미 없는 거대한 차이가 보이지 않음package-lock.json이 잡음이어서는 안 됨. 의도적으로 갱신하려는 게 아니라면 업데이트하지 말아야 하고, 그렇지 않으면 이유 없이 공급망 위험에 노출됨
package-lock.json변경이 자주 예상치 않게 생긴다면 뭔가 잘못하고 있는 것임package-lock.json은 모든 전이 의존성을 보여주고,package.json은 직접 의존성만 보여줌. 후자가 "사람이 읽을 수 있는 진짜 버전"이라는 말은 사실이 아님
둘은 목적이 다르고, 잠금 파일의 차이를 항상 무시해도 된다고 말하는 건 위험함- 의존성 업그레이드와 버그 원인 추적을 하는 입장에서는
git diff가 잠금 파일 차이를 안 보여주면 정말 화날 것 같음
줄 단위 잡음처럼 보인다는 건 이해하지만, 필요할 때는 반드시 필요함
-
전역/사용자 단위 제외 설정은 더 널리 알려져야 하는 기능임. IDE/OS/AI 관련 파일을 모든 프로젝트의
.gitignore에 추가하려는 변경을 자주 받는데, 표준 설정에 넣으면 모든 곳에서 무시되고 각 프로젝트를 건드릴 필요도 없으며.gitignore를 갱신하지 않은 프로젝트에서 실수로 커밋할 위험도 없다고 알려주면 대부분 반가워함
개인적인 원칙은 저장소 안의.gitignore는 빌드 산출물, 의존성 폴더 같은 저장소 전용 항목에만 쓰고, 사용자 도구 대부분은 각자의 사용자 설정에 둬야 한다는 것임- 전역
.gitignore설정을 자주 알려줘야 하는 건, 저장소 안.gitignore를 저장소 전용 항목에만 쓰겠다는 원칙의 당연한 결과임
모두의 시간을 덜 쓰려면 그냥 모든 프로젝트에서 그런 파일들을.gitignore에 넣는 편이 낫다 - 무지해서 그런 파일을 프로젝트에 추가하는 일이 없게 하려고 항상 프로젝트의
.gitignore에 넣어왔음
결국 다시 Git에서 제거할 것이고 그 사람에게 고통이 생길 테니, 친절 차원에서 미리 막아둔 것임. 앞으로는 덜 친절하게 할지도 모르겠음 - 개발 컨테이너를 재빌드해도 살아남기 때문에
gitignore쪽을 선호함
gitignore를 피해야 한다면 생성 스크립트나 볼륨으로 설정을 복원/유지할 수는 있지만,.gitignore한 줄 대신 추가 스크립트나devcontainer마운트 설정이 필요해짐 - 같은 잘못된 행동을 계속 보면서도, 그 행동을 고치는 가장 쉬운 방법을 명시적으로 금지하는 엄격한 규칙을 두는 건 서로 충돌하지 않나
- 전역
-
전역 Git 설정과 무시 파일은
~/.gitignore_global을 만들고 설정을 바꾸는 것보다~/.config/git/ignore와~/.config/git/config에 두는 게 맞다고 봄
~/.config/를 여러 용도에 활용하면 루트 수준의 dotfiles가 훨씬 작아짐
Git exclude가 덜 쓰이는 이유는 저장소에 커밋되지 않아서, 쓰고 싶을 때마다 다시 만들어야 하기 때문임. 나쁘다는 뜻은 아니고 덜 쓰이는 이유가 그렇다는 것임- 덤으로
~/.config디렉터리를 버전 관리하면 나중의 수정과 공유가 가능해짐 - 같은 파일을 쓰는 다른 도구들을 위해
~/.cvsignore를 써도 됨
- 덤으로
-
어디서 배웠는지는 모르겠지만 전역 Git ignore에
attic을 추가해 둠
그러면 어떤 프로젝트에서든 절대 커밋하면 안 되는 잡다한 것을 보관할attic디렉터리를 만들 수 있음. 실제로 그런 디렉터리 검사를 하는 저장소는 아직 못 봤음- 약간 반대로도 할 수 있지만, 경우마다 따로 해야 함
attic같은 디렉터리가 있다면 그 안에attic/.gitignore를 만들고/**를 넣으면, 그 디렉터리와 내부 모든 것이 무시되며 ignore 파일 자체도 무시됨
보통 내 버전의 디렉터리 이름은 U+1F4A9 한 글자로 짓는데, HN이 댓글에 넣는 걸 허용하지 않음 - 내 경우는
aux를 씀
그 안에 별표 하나*만 들어 있는.gitignore를 넣어 숨기면, 자기 자신과 내부 모든 것을 무시함 - 나도 이렇게 함. 다만 이름은
.local로 둠 - 내 것은
scratch/임
아직은 발목 잡힌 적 없음
- 약간 반대로도 할 수 있지만, 경우마다 따로 해야 함
-
사용자별 무시에 대해, macOS라면
.DS_Store를 거기에 추가하는 게 이상적이라고 하지만 프로젝트의 모든 Mac 사용자가 그렇게 해야 함
둘 이상이라면 각자에게 맡기지 않는 편이 나을 수 있음- 어디서 생겼는지는 확실히 모르겠지만, 내 Mac 두 대(Ventura 한 대, Sequoia 한 대) 모두
~/.gitignore_global파일에.DS_Store항목이 있고, 전역 Git 설정에도 그 파일의 항목을 무시하게 하는 설정이 들어 있음
새 Mac의 이 파일 날짜는 주문하기 이틀 전이고, 직접 설정한 기억이 없어서 기본으로 온 것 같음. 오래된 Mac도 비슷했을 거라 보고, macOS 버전을 보면 꽤 오래전부터 기본 설정이 이랬을 수도 있음
그래서 이제.DS_Store/를.gitignore에 추가해야 하던 시절은 끝났을지도 모름 - 소수와 다수를 보는 방식이 꽤 특이함. macOS 사용자 한 명이 프로젝트 열 개에서 일한다면, 열 프로젝트 모두 그 줄을 추가해야 하나, 아니면 그 한 사용자의 손에서 처리하는 편이 나은가?
- 어디서 생겼는지는 확실히 모르겠지만, 내 Mac 두 대(Ventura 한 대, Sequoia 한 대) 모두
-
와, 이걸 어떻게 몰랐지? 20년 차 전문 소프트웨어 개발자인데
.gitignore만 써왔음
내게만 관련 있는 온갖 제외 항목으로.gitignore를 어지럽히는 것보다 더 나은 방법이 있을지 스스로 물어본 적도 없었다는 걸 깨달음. 그냥 보이는 세상을 그대로 받아들였던 것임
오늘 세상이 조금 더 나아졌음 -
.git/info/exclude를 정말 많이 씀. 로컬에서만 쓰고 협업자에게는 필요 없거나 쓸 수도 없는 스크립트/Makefile에 아주 잘 맞음- 다른 협업자가 쓸 수 없는 스크립트에는 어떤 예가 있는지 궁금함. 예를 들면 PR 작업 흐름용 스크립트 같은 것인가?
- 꽤 오래전부터
git status에 나온 추적되지 않은 파일 전부를.git/info/exclude로 밀어 넣는 셸 함수를 써왔음
보통 저장소에 넣고 싶은 것들을add와commit한 뒤 적용함
-
여러 저장소가 들어 있는 프로젝트 디렉터리에 프로젝트 단위 Git 설정을 다르게 적용하려고 excludes 파일을 이렇게 씀
https://laszlo.nu/blog/project-level-git-config.html -
관련해서 쓰고 있는 별칭들이 있음
assume = update-index --assume-unchanged
unassume = update-index --no-assume-unchanged
assumed = "!git ls-files -v | grep ^h | cut -c 3-"
unassumeall = "!git assumed | xargs git update-index --no-assume-unchanged"
assumeall = "!git st -s | awk {'print $2'} | xargs git assume" -
이미 추적 중인 파일에는
git update-index --[no]-skip-worktree도 있음
로컬 실험에 유용할 수 있지만, Git이 어디에 잘 드러내 주는 기능은 아니라 쓰기가 조금 귀찮음. 설정해 둔 걸 기억해야 하고, 잊으면 체크아웃 같은 다른 작업이 막힐 수 있음