28P by GN⁺ 18시간전 | ★ favorite | 댓글 2개
  • Git은 저장소 내 특정 파일들을 통해 동작 방식을 제어하며, 이들은 .git/ 내부 설정이 아닌 커밋되어 코드와 함께 이동하는 파일
  • .gitignore, .gitattributes, .lfsconfig, .gitmodules, .mailmap 등은 각각 파일 추적 제외, 속성 정의, LFS 설정, 서브모듈 관리, 작성자 통합을 담당
  • .git-blame-ignore-revs.gitmessage코드 포맷팅 커밋 무시커밋 메시지 템플릿을 제공해 협업 품질을 높임
  • GitHub, GitLab, Gitea 등은 .github/, .gitlab/, .gitea/ 같은 포지별 설정 폴더를 통해 CI/CD, 리뷰어 지정 등 기능을 확장함
  • 이러한 구조는 Git을 넘어 EditorConfig, Docker, 언어 버전 관리 도구 등에서도 동일하게 적용되어, 도트파일 기반 자동 설정 생태계를 형성함

Git의 주요 매직 파일

  • Git은 .gitignore, .gitattributes, .lfsconfig, .gitmodules, .mailmap 등 여러 특수 파일을 인식해 저장소 동작을 제어함
    • 이 파일들은 .git/ 내부 설정이 아닌 커밋되어 공유되는 구성 요소로, 협업 시 일관된 동작을 보장함

.gitignore

  • Git이 추적하지 않아야 할 파일 패턴을 정의
    • 와일드카드(*.log), 디렉터리(dist/), 부정(!important.log) 등을 지원
    • .gitignore, .git/info/exclude, 전역 설정(~/.config/git/ignore) 순으로 적용
  • 이미 추적된 파일은 .gitignore 추가 후에도 계속 추적되며, git rm --cached로 제거 가능
  • GitHub, GitLab, Gitea 등은 무시된 패턴의 파일도 경고 없이 커밋 가능
  • GitHub는 언어별 .gitignore 템플릿을 공식 저장소에서 제공

.gitattributes

  • 파일별 필터, diff, merge, 줄바꿈, 언어 감지 등을 제어
    • 예: *.psd filter=lfs, *.png binary, *.sh text eol=lf
  • text는 줄바꿈 정규화, binary는 diff/merge 비활성화, merge=ours는 충돌 시 로컬 버전 유지
  • GitHub Linguist는 .gitattributes를 읽어 언어 통계 제외, 생성 코드 접기, 문서 제외 등을 수행
  • 각 디렉터리별 .gitattributes.git/info/attributes를 함께 인식

.lfsconfig

  • Git LFS 설정을 저장소와 함께 공유
  • .gitattributes에서 LFS 처리 파일을 지정하고, .lfsconfig는 서버 위치 등 세부 설정을 담당
  • 기존 커밋 파일을 LFS로 이동하려면 git lfs migrate 명령 필요

.gitmodules

  • 서브모듈 구성 정보를 저장
  • git submodule add 시 생성, git submodule update 시 참조
  • git clone 시 자동으로 서브모듈을 가져오지 않으며, --recurse-submodules 옵션 필요
  • 버전 범위 추적 불가, 중첩 .git 디렉터리 생성 등 단점 존재

.mailmap

  • 작성자 이름과 이메일을 통합 관리
    • 예:
      Jane Developer <[email protected]> <[email protected]>
      
  • git log, git shortlog, git blame 등에서 통합된 이름으로 표시
  • GitHub의 기여자 그래프는 mailmap을 반영하지 않음
  • .mailmap 또는 mailmap.file 설정으로 위치 지정 가능

.git-blame-ignore-revs

  • git blame에서 무시할 커밋 목록을 지정
    • 포맷터 실행, 린트 적용 등 의미 없는 변경을 제외
    • 예:
      # Ran prettier on entire codebase
      a1b2c3d4e5f6g7h8i9j0...
      
  • git config blame.ignoreRevsFile .git-blame-ignore-revs로 활성화
  • GitHub, GitLab(15.4+), Gitea는 자동 인식
  • 파일이 없을 경우 오류 발생 가능하므로 빈 파일 유지 권장

.gitmessage

  • 커밋 메시지 템플릿을 정의
    • 예:
      # <type>: <subject>
      #
      # Types: feat, fix, docs, style, refactor, test, chore
      
  • git config commit.template .gitmessage로 설정 필요
  • 클론 후 수동 설정이 필요하며, 일부 팀은 husky 등으로 자동화
  • 대안으로 commit-msg 훅이나 prepare-commit-msg 훅 사용 가능

포지별 확장 폴더

  • GitHub, GitLab, Gitea, Forgejo, Bitbucket 등은 자체 설정 폴더를 사용
    • .github/, .gitlab/, .gitea/, .forgejo/, .bitbucket/
  • CI/CD 워크플로, 이슈·PR 템플릿, CODEOWNERS 파일 등을 포함
  • Forgejo는 .forgejo/ → .gitea/ → .github/, Gitea는 .gitea/ → .github/ 순으로 폴백
  • SourceHut은 .build.yml 또는 .builds/*.yml을 사용

기타 관례적 파일

  • .gitkeep: Git이 빈 디렉터리를 추적하지 않기 때문에, 디렉터리 유지용 더미 파일로 사용
  • .gitconfig: 프로젝트별 Git 설정 예시를 제공하지만 자동 로드되지 않음
  • .gitsigners: GPG/SSH 서명 키 목록을 관리, gpg.ssh.allowedSignersFile로 지정 가능
  • .gitreview: Gerrit 코드 리뷰 서버 설정 파일
    • 예:
      [gerrit]
      host=review.opendev.org
      port=29418
      project=openstack/nova.git
      defaultbranch=master
      
  • .gitlint: 커밋 메시지 린팅 규칙 정의
    • 예:
      [general]
      ignore=body-is-missing
      [title-max-length]
      line-length=72
      
  • .jj/: Git 호환 VCS인 Jujutsu의 상태 디렉터리, .git/과 함께 존재 가능

Git을 넘어선 도트파일 생태계

  • .editorconfig: 에디터 간 일관된 코드 스타일 유지
    • 들여쓰기, 줄바꿈, 인코딩, 공백 제거 등을 정의
    • VS Code, Vim, Emacs 등 주요 에디터가 지원
  • .ruby-version, .node-version, .python-version: 언어 버전 관리 도구(rbenv, nodenv, pyenv 등)가 읽어 자동 전환
  • .tool-versions: asdf의 다언어 버전 관리 파일
  • .dockerignore: Docker 빌드 시 제외할 파일 목록 지정
    • .gitignore와 동일한 패턴 문법 사용, 빌드 속도 향상 및 비밀정보 제외

Git 연동 도구 개발 시 고려사항

  • Git 저장소를 다루는 도구는 다음 파일들을 반드시 인식해야 함
    • .gitignore: 파일 탐색 시 무시 패턴 적용
    • .gitattributes: 바이너리·생성 파일 구분
    • .mailmap: 작성자 정보 통합 표시
    • .gitmodules: 서브모듈 처리
  • Git 설정 파일 형식은 [section "subsection"] key = value 구조이며, git config 명령으로 읽기·쓰기 가능
  • 대부분의 언어용 Git 라이브러리는 이 형식을 파싱하는 기능을 제공

gitmessage는 몰랐던건데 써봐야겠어요

Hacker News 의견들
  • GitHub, GitLab, Gitea 모두 .gitignore를 존중해서 웹 UI에 무시된 파일을 안 보여준다고 했는데, 그건 잘못된 설명 같음
    실제로는 무시된 파일이 저장소에 포함되지 않기 때문에 안 보이는 것임. 이미 커밋된 파일이라면, 오히려 보여야 하는 게 맞다고 생각함
    • 그렇지 않음. 이미 푸시된 파일을 나중에 .gitignore에 추가해도 여전히 UI에 보임. 그 파일은 여전히 repo의 일부이기 때문임
      반대로, 처음부터 무시된 파일을 강제로 커밋하는 것도 가능하지만 약간의 트릭이 필요함
    • 맞음, 원 댓글이 틀림. .gitignore는 단지 untracked 파일을 숨길지 여부만 결정함. 원하면 무시된 파일도 커밋할 수 있음
    • showinwebui=(true|false) 같은 옵션이 있으면 좋겠다는 생각이 듦 😄
    • 이런 실수를 사람이 직접 썼을 리 없다고 느껴서, 그 부분에서 읽기를 멈췄음
  • .git/info/exclude를 강조하고 싶음. 이건 로컬 전용 gitignore로, 나만을 위한 설정임
    예를 들어 버그 조사 중에 임시 파일을 만들어 브랜치를 바꿔도 그대로 두고 싶을 때 유용함
    나는 아래처럼 셸 alias를 만들어 씀
    git-ignore-local () {
      echo "$1" >> .git/info/exclude
    }
    
    이렇게 하면 git-ignore-local myfile.ext로 간단히 추가 가능함
    • 루트 디렉터리에 있지 않아도 작동하도록 조금 더 마법 같은 버전을 만들어봤음
      MacOS에서는 readlink 부분만 수정하면 됨
      git-ignore-local () {
        root=$(git rev-parse --show-toplevel)
        path=$(readlink -f "$1")
        relpath=$(relpath -m --relative-to="$root" "$path")
        echo "$relpath" >> "${root}.git/info/exclude"
      }
      
      이 함수를 PATH에 git-ignore-local로 등록하면 git ignore-local처럼 쓸 수 있음
    • .git/info/exclude.gitignore 설명의 첫 부분에서도 언급되어 있음
    • 이런 기능은 처음 알았음. 내 프로젝트에서 이런 작은 임시 파일들 때문에 PR이 복잡해졌는데, 이걸로 해결될 것 같음
  • .gitattributes/test export-ignore를 추가하면, 프로덕션 서버로 배포 시 테스트 파일을 제외할 수 있음
    Capistrano 같은 배포 도구가 git export를 사용할 때 자동으로 적용되어, 테스트 파일이 서버에 올라가지 않음
    개발 중에는 영향을 주지 않으면서 디스크 공간도 절약됨
    • 좋은 기능이지만 대부분의 사람들은 git archive 자체를 잘 모르는 듯함
      기본적인 CI 도구들에서도 거의 안 쓰이는 걸 봤음. Capistrano가 이걸 활용하는 첫 사례로 알게 됨
      참고로 export-subst 옵션을 쓰면 git describe와 비슷한 정보를 파일 안에 직접 넣을 수도 있음
  • jj를 쓰면서 .jj 폴더를 repo와 모든 git 작업에서 완전히 제외하고 싶었음
    git clean -xdf에서도 지워지지 않게 말임. 지금은 임시로 git clean -e .jj alias로 해결 중임
    • .git/info/exclude를 쓰면 됨
  • GitHub의 contributor graph는 .mailmap을 지원하지 않음
    관련 논의는 GitHub Community Discussion에 있음
  • package-lock.json merge=ours 설정은 위험하다고 생각함
    merge나 rebase 시 ours/theirs의 의미가 불분명하기 때문임
    이런 설정은 자동화된 병합 도구(예: git-annex branch)에서만 의미가 있음
    참고: ours/theirs 의미 설명, git-annex 내부 구조
  • .git-blame-ignore-revs는 좋은 기능이지만, “기타 관례” 섹션에 속해야 함
    git 클라이언트에 설정하지 않으면, 해당 파일이 없는 저장소에서는 git blame이 실패
    • git 2.52부터는 (:optional) 옵션을 써서 파일이 없어도 오류가 나지 않게 할 수 있음
      관련 설명은 Stack Overflow 답변에 있음
  • 전체적으로 잘 정리된 리스트라고 생각함
    다만 모든 도구가 .mailmap을 지원하지 않는 점이 아쉬움. 예를 들어 IntelliJ는 아직 관련 기능이 버그/기능 요청 상태
    또한 .git-blame-ignore-revs는 단순한 관례일 뿐, 직접 설정을 해야 작동함
  • 약간 다른 이야기지만, VS Code가 .ignore 파일도 인식한다는 걸 최근에 알게 됨
    .gitignore만 적용되는 줄 알았는데, .ignore에서 ripgrep 설정을 바꿨더니 검색 결과가 달라졌음. 알고 보니 합리적인 동작이었음
  • 글 작성자가 forge-specific repository folders(일종의 “매직 폴더”)에 대한 후속 글도 올렸음
    링크: nesbitt.io 글