Logo

.gitignore 파일 사용법

이번 포스팅에서는 .gitignore 파일을 이용하여 Git으로 프로젝트의 버전 관리를 할 때 특정 파일이나 디렉토리를 제외시키는 방법에 대해서 알아보겠습니다.

버전 관리를 하지 않는 파일과 디렉토리

어떤 프로그래밍 언어로 프로젝트를 하든 버전 관리를 할 필요가 없거나 하지 말아야하는 파일이나 디렉토리가 생기기 마련입니다.

대표적인 예로, 자바스크립트(JavaScript) 프로젝트에서는 의존성을 설치하고 나면, 프로젝트에 node_modules 디텍토리가 생성되고 그 안에 npm 저장소로 부터 내려받은 라이브러리 코드가 저장됩니다. 오픈 소스 라이브러리 기반으로 개발되는 프로젝트의 경우 node_modules 디텍토리의 용량은 개발자가 다운로드 받기에는 부담스럽게 크며 npm install 명령어로 언제든지 다시 생성할 수 있기 때문에 일반적으로 node_modules 디텍토리는 버전 관리를 하지 않습니다.

또 다른 예로, 자바(Java) 프로젝트에서는 컴파일(compile) 결과로 생성되는 확장자가 .class인 파일과 패키징(packaging) 결과로 확장자가 .jar 또는 .war 파일도 일반적으로 버전 관리에서 제외를 시킵니다. 이렇게 빌드(build) 과정에서 생성되는 부산물은 개발자가 육안으로 이해하기 어려우며 따라서 코드 리뷰도 어렵기 때문에 굳이 번거롭게 버전 관리를 할 이유가 없습니다.

이 밖에도 보안상 민감한 데이터를 담고 있는 파일이 원격 코드 저장소에 업로드하면, 특히 GitHub와 같은 서비스를 사용할 경우, 외부에 유출이 되어 크게 곤란한 일이 겪을 수도 있습니다.

따라서 이렇게 버전 관리를 할 필요가 없는 파일이나 디렉토리는 Git에게 무시하라고 알려줘야하는데요. 이 때 사용하는 것이 바로 .gitignore 파일입니다.

실습 프로젝트 구성

간단한 실습을 위해서 디렉토리를 하나 생성해보겠습니다.

$ mkdir our-project
$ cd our-project

생성한 디렉토리에서 Git으로 버전 관리를 시작하겠습니다.

$ git init
Initialized empty Git repository in /Users/daleseo/temp/our-project/.git/

실습 프로젝트에 텍스트 파일 3개 a.txt, b.txt, c.txt를 생성해보겠습니다.

$ touch a.txt b.txt c.txt
$ ls
a.txt b.txt c.txt

Git에게 현재 상태를 물어보니 예상대로 3개의 파일을 추적해야 한다고 나옵니다.

$ git status
On branch main

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	a.txt
	b.txt
	c.txt

nothing added to commit but untracked files present (use "git add" to track)

.gitignore 파일 생성

이제 실습 프로젝트 안에 .gitignore 파일을 생성해보겠습니다.

$ touch .gitignore

자연스럽게 .gitignore 파일 자체도 일반 파일처럼 Git이 추적해야하는 파일로 나옵니다.

$ git status
On branch main

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	.gitignore
	a.txt
	b.txt
	c.txt

nothing added to commit but untracked files present (use "git add" to track)

특정 파일을 버전 관리에서 제외

실습 프로젝트의 3개의 텍스트 파일 중에서 b.txt 파일을 버전 관리에서 제외시키려면 어떻게 해야할까요?

.gitignore 파일에 b.txt를 추가해줍니다.

$ echo "b.txt" >> .gitignore
$ cat .gitignore
b.txt

이제 다시 Git에게 현재 상태를 물어보면 b.txt는 추적할 파일에서 빠져있는 것을 볼 수 있죠?

$ git status
On branch main

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	.gitignore
	a.txt
	c.txt

nothing added to commit but untracked files present (use "git add" to track)

현재 변경 사항을 스테이징(staging) 영역에 추가하고 커밋(commit)해보겠습니다.

$ git add . && git commit -m "ignore b.txt"
[main (root-commit) be4069a] ignore b.txt
 3 files changed, 2 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 a.txt
 create mode 100644 c.txt

무시된 파일 수정

무시된 b.txt 파일에 한 번 내용을 추가해보겠습니다.

$ echo "BBB" >> b.txt
$ cat b.txt
BBB

Git은 b.txt의 변경 사항을 신경쓰지 않는 것을 알 수 있습니다.

$ git status
On branch main
nothing to commit, working tree clean

주의 사항

.gitignore 파일을 사용할 때 많은 분들이 실수하는 부분이 있는데요. 바로 Git이 일단 한 번 추적하기 시작한 파일은 .gitignore 파일에 추가해도 제외되지 않는다는 것입니다.

예를 들어, 방금 커밋을 했던 c.txt 파일을 .gitignore 파일에 추가해보겠습니다.

$ echo "c.txt" >> .gitignore
$ cat .gitignore
b.txt
c.txt

그리고 변경 사항을 커밋합니다.

$ git commit -am "ignore c.txt"
[main 94ce86d] ignore c.txt
 1 file changed, 1 insertion(+)

이제 c.txt 파일을 수정해보겠습니다.

$ echo "CCC" >> c.txt
$ cat c.txt
CCC

그리고 Git에게 상태를 물어보면 .gitignore 파일에 c.txt를 추가했음에도 불구하고, c.txt의 변경 내역이 잡히는 것을 볼 수 있습니다.

$ git status
On branch main
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   c.txt

no changes added to commit (use "git add" and/or "git commit -a")

정리하면 .gitignore 파일의 목적은 Git이 애초부터 파일이나 디렉토리가 추적되지 못하도록 예방하는 것입니다. 일단 Git이 추적을 시작한 파일은 .gitignore 파일로 추척을 막기에는 늦었다는 점 명심하세요.

이미 추적이 시작한 파일은 어떻게?

이미 Git이 추적을 시작한 파일을 추적을 멈추도록 하고 싶다면 어떻게 해야할까요?

일단 명시적으로 해당 파일을 삭제를 하고, Git에 커밋을 합니다.

$ rm c.txt
$ git add . && git commit "delete c.txt"

다시 c.txt 파일을 생성해보면, 이 번에는 .gitignore 파일에 추가했던 c.txt가 효력이 발휘하여 Git은 이 파일이 생성되었는지 인식조차 못하게 됩니다. 이제부터는 아무리 c.txt 파일을 변경해도 Git은 알아차리지 못할 것입니다.

$ touch c.txt
$ git status
On branch main
nothing to commit, working tree clean

이처럼 한 번 Git이 추적을 시작한 파일은 반드시 명시적으로 삭제한 후 커밋을 해줘야지만 .gitignore 파일이 의도했던데로 작동하게 됩니다.

.gitignore 자동 생성

.gitignore 파일에 일일이 버전 관리를 하지 않을 파일이나 디렉토리를 추가하는 것은 번거로울 뿐만 아니라 누락할 위험까지 있습니다. 그래서 실제 프로젝트에서는 프로그래밍 언어나 개발 도구에 따라서 커뮤니티에서 미리 정리해놓은 관행을 따르는 것이 일반적인데요. 대표적으로 웹사이트로 https://www.gitignore.io/를 들 수 있습니다.

이 사이트를 방문해서 프로젝트에서 사용하는 프로그래밍 언어나 개발 도구의 이름을 입력하면 최적화된 .gitignore 파일을 자동으로 생성해줍니다. 대부분의 프로젝트에서는 이렇게 자동 생성된 .gitignore 파일에 해당 프로젝트에서만 특별하게 버전 관리를 하지 않을 파일이나 디렉토리만 추가해주면 됩니다.

[추가 팁] git ignore 커맨드

저는 개인적으로 새로운 Git의 별칭(alias) 기능을 활용해서 브라우저에서 위 사이트를 방문하지 않고 터미널에서 커맨드로 .gitignore 파일을 자동 생성합니다.

먼저 터미널에서 Git에 ignore라는 별칭 커맨드를 등록합니다.

$ git config --global alias.ignore '!gi() { curl -L -s https://www.gitignore.io/api/$@ ;}; gi'

그리고 나서 git ignore 명령어를 뒤에 프로그래밍 언어나 개발 도구의 이름을 붙여서 실행해봅니다. 버전 관리에서 제외될 파일과 디렉토리를 콘솔에서 미리 확인해볼 수 있습니다.

$ git ignore java

# Created by https://www.toptal.com/developers/gitignore/api/java
# Edit at https://www.toptal.com/developers/gitignore?templates=java

### Java ###
# Compiled class file
*.class

# Log file
*.log

# BlueJ files
*.ctxt

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

# End of https://www.toptal.com/developers/gitignore/api/java

이제 해당 내용을 콘솔에 출력하는 대신에 .gitignore 파일에 쓰기만 하면 되겠죠?

$ git ignore java >> .gitignore

마치면서

이상으로 Git이 특정 파일이나 디렉토리를 추적하지 못하게 하기 위해서 사용하는 .gitignore 파일에 대해서 알아보았습니다.