| 편집기 | 설정 명령어 |
|---|---|
| 크로스 플랫폼 | |
| VS Code | git config --global core.editor "code --wait" |
| Vim | git config --global core.editor "vim" |
| Emacs | git config --global core.editor "emacs" |
| Sublime Text | git config --global core.editor "subl -n -w" |
| 윈도우 | |
| Notepad++ | git config --global core.editor "'C:/Program Files/Notepad++/notepad++.exe' -multiInst -notabbar -nosession -noPlugin" |
| 맥/리눅스 | |
| nano | git config --global core.editor "nano -w" |
| Gedit | git config --global core.editor "gedit --wait --new-window" |
17 Git 시작하기
프로그래밍을 배우는 사람에게 Git은 낯선 존재다. 코드를 작성하는 방법, 알고리즘을 이해하는 과정에서 “왜 버전 관리까지 배워야 하는가?”라는 의문이 들 수 있다. 하지만 현대 소프트웨어 개발에서 Git은 선택이 아닌 필수다. 프로그래밍 언어를 익히는 것만큼이나 Git을 다루는 능력이 중요해진 이유가 있다.
첫째, 실수를 두려워하지 않아도 된다. 코드를 작성하다 보면 잘못된 방향으로 진행하거나, 이전 버전이 더 나았던 경우가 빈번하다. Git은 모든 변경 이력을 보존하므로 언제든 과거로 되돌아갈 수 있다. “어제 작성한 코드가 더 좋았는데…”라는 후회가 사라진다.
둘째, AI 시대에 Git 중요성은 더욱 커졌다. 챗GPT나 GitHub Copilot 같은 AI 도구가 코드를 생성해주지만, AI가 생성한 코드가 올바른지, 기존 코드와 어떻게 통합되는지 검증하는 것은 여전히 사람의 몫이다. AI가 제안한 코드를 실험하고, 문제가 생기면 되돌리고, 여러 접근 방식을 비교하는 과정에서 Git은 안전망 역할을 한다. AI와 협업하는 시대일수록 버전 관리 능력은 더욱 필수적이다.
셋째, 오픈소스 생태계 공용어가 Git이다. GitHub에는 수백만 개 프로젝트가 공개되어 있고, 거의 모든 프로그래밍 라이브러리와 프레임워크가 Git으로 관리된다. 다른 개발자 코드를 가져다 쓰거나, 버그를 수정해서 기여하거나, 동료와 협업하려면 Git을 알아야 한다. Git 없이 현대 프로그래밍 생태계에 참여하기는 사실상 불가능하다.
넷째, 재현가능한 연구 기반이다. 데이터 과학이나 연구 분야에서 “분석 결과를 어떻게 재현할 수 있는가?”는 핵심 질문이다. Git은 코드뿐 아니라 분석 전과정 모든 변경 이력을 기록한다. 논문에 사용한 정확한 코드 버전으로 언제든 돌아갈 수 있고, 다른 연구자도 동일한 결과를 재현할 수 있다.
그림 17.1 은 현대 프로그래밍을 구성하는 세 가지 핵심 요소를 보여준다. 왼쪽 “코드”는 프로그래밍 언어로 문제를 해결하는 능력이고, 오른쪽 “AI”는 챗GPT나 Copilot처럼 코드 생성을 지원하는 도구다. 가운데 위치한 “Git”은 두 영역을 연결하는 다리 역할을 한다. 사람이 작성한 코드든 AI가 생성한 코드든, 모든 변경 이력을 추적하고 협업을 가능하게 하는 기반이 Git이기 때문이다. 코드 작성 능력만으로는 절반만 갖춘 셈이고, Git을 통해 코드를 관리하고 공유할 줄 알아야 완전한 프로그래머라 할 수 있다.
Git은 프로그래밍 교육에서 한 부를 차지할 만큼 중요한 주제다. 코드를 “작성”하는 것과 코드를 “관리”하는 것은 다른 기술이며, 둘 다 능숙해야 진정한 프로그래머라 할 수 있다. 이제 버전 관리가 왜 필요한지, Git이 어떤 문제를 해결하는지 구체적으로 살펴보자.
17.1 버전 관리가 필요한 이유
코드를 작성하다 보면 자연스럽게 여러 버전이 생긴다. 처음에는 단순히 “백업”이라고 생각하며 파일을 복사해둔다. 그러다 수정을 거듭하면서 최종.py, 최종_수정.py, 최종_진짜최종.py 같은 파일명이 등장한다. 혼자 작업할 때도 이 정도인데, 여러 사람이 함께 작업하면 혼란은 기하급수적으로 커진다. 누가 무엇을 언제 고쳤는지 파악하기 어렵고, 어떤 버전이 최신인지조차 헷갈린다. 버전 관리 시스템은 바로 이러한 고질적인 문제를 해결하기 위해 탄생했다.
대학원생이라면 누구나 공감할 상황이 그림 17.2 에 나와 있다. 처음 “최종.hwp”라고 이름 붙인 파일이 수정을 거듭하면서 점점 괴상한 이름으로 변해간다. 최종_수정2, 최종_수정6_코멘트, 최종_수정18_코멘트7_교정9… 결국 어떤 파일이 진짜 최종인지 알 수 없게 되고, 작성자는 절망에 빠진다.
논문을 쓰다가 훌륭한 결론 문단을 작성했는데, 이후 수정 과정에서 망쳐버린 경험이 있을 것이다. 원래 버전을 되살리고 싶어도 방법이 없다. 공동 저자가 5명이라면 각자의 수정 사항과 코멘트를 어떻게 관리해야 할까? 워드프로세서의 “변경 내용 추적” 기능이나 구글 문서(Google Docs)의 버전 기록 기능이 어느 정도 도움이 되지만, 수십 차례 오간 수정 이력을 온전히 보존하기에는 역부족이다. Git은 바로 이런 문제를 근본적으로 해결한다.
버전 관리 시스템은 문서의 초기 상태에서 출발해 변경 사항을 순차적으로 기록한다. 카세트 테이프에 비유하면 이해하기 쉽다. 테이프를 처음으로 되감으면 원본 상태가 되고, 앞으로 재생하면서 변경 사항을 하나씩 적용하면 최신 버전에 도달한다.
그림 17.3 처럼 변경 사항을 문서 자체와 분리해서 생각하면, 원본에 서로 다른 변경 사항을 적용해볼 수 있다. 두 사람이 같은 문서를 각자 수정하는 상황을 떠올려 보자.
그림 17.4 에서 보듯, 원본에서 두 개의 다른 버전이 만들어질 수 있다. 두 변경 사항이 서로 충돌하지 않는다면, 그림 17.5 처럼 하나로 합칠 수도 있다.
버전 관리 시스템은 변경 이력 기록, 버전 생성, 파일 병합을 자동으로 처리한다. 특정 시점의 변경 사항을 저장하는 행위를 커밋(commit)이라 부른다. 커밋에는 변경 내용뿐 아니라 작성자, 시간, 설명 같은 메타 정보도 함께 기록된다. 프로젝트의 전체 커밋 이력은 저장소(repository)에 보관되며, 저장소는 여러 컴퓨터 간에 동기화할 수 있다.
17.1.1 버전 관리 시스템 진화
Git이 오늘날 표준이 되기까지 버전 관리 시스템은 50년 넘는 진화 과정을 거쳤다. 처음에는 한 컴퓨터에서만 작동하는 단순한 도구였지만, 네트워크 협업 기능이 추가되고, 마침내 분산형 시스템으로 발전했다. 각 세대마다 이전 세대의 한계를 극복하며 더 강력한 기능을 제공했고, 그 결과 오늘날 우리가 사용하는 Git이 탄생했다. 1세대 로컬 시스템에서 3세대 분산형 시스템까지 주요 도구들의 등장 시점이 그림 17.6 에 나와 있다.
1972년 벨 연구소(Bell Labs)에서 SCCS(Source Code Control System)가 등장했고, 1982년 퍼듀(Purdue) 대학 월터 티치(Walter Tichy)가 RCS(Revision Control System)를 개발했다. 1세대 시스템은 한 컴퓨터에서만 작동하는 로컬 도구였다.
1986년 딕 그루네(Dick Grune)가 CVS(Concurrent Versions System)를 만들면서 네트워크를 통한 협업이 가능해졌다. CVS는 1990년대를 지배했고, 2000년 아파치(Apache) 재단 서브버전(Subversion, SVN)이 “더 나은 CVS”를 표방하며 뒤를 이었다. 하지만 2세대 중앙집중식 시스템은 서버에 연결해야만 커밋할 수 있다는 한계가 있었다.
2005년 리누스 토르발스(Linus Torvalds)가 리눅스(Linux) 커널 개발을 위해 Git을 만들면서 3세대 분산형 시스템이 시작되었다. Git은 중앙 서버 없이도 각자의 컴퓨터에 완전한 저장소를 가질 수 있고, 오프라인에서도 커밋이 가능하다. 2008년 깃허브(GitHub)가 등장하면서 Git은 폭발적으로 성장했다. 스택 오버플로(Stack Overflow) 2015년 조사에서 개발자의 69%가 Git을 사용한다고 응답했으며, 2위인 서브버전 두 배에 달했다. 오늘날 Git은 버전 관리의 사실상 표준이 되었다.
17.2 Git 설정
새 컴퓨터에서 Git을 처음 사용하면 몇 가지 기본 설정이 필요하다. 가장 중요한 설정은 이름과 이메일 주소로, 커밋할 때마다 작성자 정보로 기록된다. 기본 텍스트 편집기도 지정해야 하는데, 커밋 메시지를 작성할 때 사용된다. --global 플래그를 붙이면 해당 컴퓨터의 모든 Git 프로젝트에 설정이 적용되므로, 처음 한 번만 실행하면 된다.
Git 명령어는 git verb options 형식을 따른다. verb는 수행할 작업이고, options는 추가 옵션이다. 드라큘라가 새 노트북에서 Git을 설정하는 과정을 따라가 보자.
$ git config --global user.name "Vlad Dracula"
$ git config --global user.email "vlad@tran.sylvan.ia"드라큘라 대신 본인의 이름과 이메일 주소를 입력한다. 커밋에 기록되는 작성자 정보이므로 실명과 실제 사용하는 이메일 주소를 권장한다. GitHub, BitBucket, GitLab 같은 Git 호스팅 서비스에 푸시할 때도 등록 정보가 함께 전송된다.
본 교재에서는 GitHub을 사용한다. Git에 설정한 이메일 주소는 GitHub 계정 이메일과 동일해야 커밋 이력이 프로필에 제대로 연결된다. 개인정보 보호가 필요하다면 GitHub 이메일 비공개 설정을 활용할 수 있는데, 이와 같은 경우 username@users.noreply.github.com 형식을 user.email에 설정한다.
Enter 키를 누르면 컴퓨터는 줄 바꿈 문자를 삽입하는데, 운영체제마다 줄 바꿈 문자가 다르다. 윈도우는 캐리지 리턴과 라인 피드(\r\n, CRLF)를 함께 사용하고, 맥과 리눅스는 라인 피드(\n, LF)만 사용한다. 윈도우에서 작성한 파일을 맥 사용자가 열면, 또는 그 반대의 경우, Git은 줄 바꿈 문자가 달라졌다고 판단해 실제 내용은 같아도 모든 줄이 “변경됨”으로 표시될 수 있다.
core.autocrlf 설정으로 Git이 자동 변환하도록 할 수 있다. true는 체크아웃 시 LF를 CRLF로, 커밋 시 CRLF를 LF로 변환한다. input은 커밋 시에만 CRLF를 LF로 변환하고 체크아웃 시에는 변환하지 않는다.
# 맥OS/리눅스: 커밋 시에만 LF로 정규화
$ git config --global core.autocrlf input
# 윈도우 (전통적 설정): 양방향 변환
$ git config --global core.autocrlf true그러나 현대적인 방법은 저장소 루트에 .gitattributes 파일을 두는 것이다. 개인 설정인 core.autocrlf와 달리 .gitattributes는 저장소에 포함되어 모든 팀원에게 동일하게 적용된다. VS Code 같은 현대 편집기는 윈도우에서도 LF를 완벽히 지원하므로, * text=auto만 설정해도 대부분의 경우 충분하다.
# .gitattributes 파일 생성
* text=auto자세한 내용은 GitHub 도움말을 참고한다.
17.2.1 기본 텍스트 편집기 설정
Git은 커밋 메시지를 작성하거나 병합 충돌을 해결할 때 텍스트 편집기를 실행한다. 기본 편집기를 지정하지 않으면 시스템에 따라 Vim이나 nano가 실행되는데, 익숙하지 않은 편집기가 갑자기 열리면 당황할 수 있다. 평소 사용하는 편집기를 core.editor로 설정해 두면 편리하다.
표 17.1 는 주요 편집기별 설정 명령어를 보여준다. VS Code처럼 크로스 플랫폼 편집기는 운영체제에 관계없이 동일한 명령어를 사용하고, Notepad++처럼 특정 운영체제 전용 편집기는 해당 운영체제에서만 사용할 수 있다. --wait 옵션은 편집기에서 파일을 닫을 때까지 Git이 대기하도록 한다.
편집기 설정은 언제든지 변경할 수 있다. VS Code를 처음 설치했다면, 명령 팔레트(Ctrl+Shift+P 또는 Cmd+Shift+P)에서 “Shell Command: Install ‘code’ command in PATH”를 실행해야 터미널에서 code 명령어를 사용할 수 있다.
Vim이 기본 편집기로 설정된 시스템이 많다. Vim이 처음이라면 당황할 수 있는데, Esc를 눌러 명령 모드로 전환한 뒤 :q!를 입력하고 Enter를 누르면 저장하지 않고 종료된다. 저장 후 종료하려면 :wq를 입력한다.
17.2.2 설정 확인과 변경
Git 설정이 제대로 되었는지 확인하거나, 나중에 설정을 변경해야 할 때가 있다. git config --list 명령어를 실행하면 현재 적용된 모든 설정을 한눈에 볼 수 있다. 출력 결과에는 사용자 이름, 이메일, 편집기, 줄바꿈 설정 등 지금까지 설정한 값들이 키=값 형식으로 나열된다.
$ git config --list
user.name=Vlad Dracula
user.email=vlad@tran.sylvan.ia
core.editor=code --wait
core.autocrlf=input전체 목록을 보지 않고 특정 설정만 확인하고 싶다면 설정 키를 직접 지정한다. 예를 들어 git config user.name을 실행하면 사용자 이름만 출력된다.
$ git config user.name
Vlad Dracula설정을 변경하려면 처음 설정할 때와 동일한 명령어를 새 값으로 다시 실행하면 된다. Git은 기존 값을 새 값으로 덮어씌우므로, 잘못 입력했거나 이메일 주소가 바뀌었을 때 언제든 수정할 수 있다. 명령어 사용법이 기억나지 않을 때는 -h 옵션으로 간단한 도움말을, --help 옵션으로 상세 매뉴얼을 볼 수 있다.
기업이나 학교 네트워크는 보안과 트래픽 관리를 위해 외부 인터넷 접속을 프록시 서버를 통해서만 허용하는 경우가 많다. 프록시 설정이 없으면 git push나 git pull 명령 실행 시 “Connection refused”, “Could not resolve host” 같은 네트워크 오류가 발생한다.
프록시를 올바르게 설정하면 방화벽 뒤에서도 GitHub, GitLab 등 원격 저장소에 정상적으로 접근할 수 있다. http.proxy와 https.proxy에 프록시 서버 주소를 지정하면 Git이 해당 프록시를 경유하여 외부와 통신한다. 프록시 주소는 네트워크 관리자에게 문의하거나, 웹 브라우저의 프록시 설정에서 확인할 수 있다.
# 프록시 설정 (예: http://proxy.company.com:8080)
$ git config --global http.proxy http://proxy.company.com:8080
$ git config --global https.proxy http://proxy.company.com:8080
# 인증이 필요한 프록시
$ git config --global http.proxy http://username:password@proxy.company.com:8080
# 프록시 해제 (외부 네트워크 사용 시)
$ git config --global --unset http.proxy
$ git config --global --unset https.proxy집이나 카페처럼 프록시가 없는 네트워크에서 작업할 때는 --unset 옵션으로 프록시 설정을 해제해야 정상적으로 연결된다.
17.3 GitHub 인증 설정
로컬 컴퓨터에서 GitHub 저장소에 코드를 올리거나(push) 내려받으려면(pull) 먼저 신원을 증명해야 한다. GitHub 입장에서는 요청을 보낸 사람이 저장소에 접근할 권한이 있는지 확인할 방법이 필요하고, 사용자 입장에서는 매번 아이디와 비밀번호를 입력하는 번거로움을 피하고 싶다. SSH 인증 설정은 보안 확인과 사용자 편의라는 두 가지 요구를 동시에 충족한다.
2021년 8월 이후 GitHub은 비밀번호만으로 Git 작업을 허용하지 않는다. 보안 강화 정책에 따라 반드시 토큰 기반 인증이나 SSH 키를 사용해야 한다. 처음에는 설정이 번거롭게 느껴질 수 있지만, 한 번 설정해 두면 이후에는 비밀번호 입력 없이 안전하게 작업할 수 있다.
17.3.1 GitHub 인증 방법
GitHub에서 사용할 수 있는 인증 방법은 크게 세 가지다. 전통적인 SSH 키 방식, 자동화에 적합한 개인 접근 토큰, 그리고 가장 간편한 GitHub CLI가 있다. 각 방법마다 장단점이 있으므로 상황에 맞게 선택하면 된다.
SSH 키는 공개 키 암호화 방식을 사용하는 전통적이고 안전한 방법이다. 내 컴퓨터에 비밀 키를 보관하고, 짝이 되는 공개 키를 GitHub에 등록한다. GitHub이 암호화된 질문을 보내면 비밀 키로만 답할 수 있으므로, 비밀 키를 가진 사람만 인증에 성공한다. 한 번 설정하면 해당 컴퓨터에서는 추가 인증 없이 모든 저장소에 접근할 수 있다. 여러 컴퓨터에서 작업한다면 각 컴퓨터마다 SSH 키를 생성하고 등록해야 한다.
개인 접근 토큰(Personal Access Token, PAT)은 비밀번호 대신 사용하는 일회성 문자열이다. GitHub 웹사이트에서 토큰을 생성하고, Git 작업 시 비밀번호 대신 토큰을 입력한다. 토큰에는 유효 기간과 권한 범위를 세밀하게 지정할 수 있어, 특정 저장소에만 접근하거나 읽기 전용으로 제한하는 것이 가능하다. 스크립트나 CI/CD 파이프라인처럼 자동화된 환경에서 주로 사용한다.
GitHub CLI(gh)는 GitHub이 공식 제공하는 명령줄 도구로, 가장 간편한 인증 방법이다. gh auth login 명령 하나로 웹 브라우저를 통해 인증하면, SSH 키 생성과 등록까지 자동으로 처리된다. Pull Request 생성, 이슈 관리 같은 GitHub 기능도 터미널에서 바로 사용할 수 있다. 2020년 출시 이후 빠르게 표준 도구로 자리 잡았으며, 초보자에게 특히 권장하는 방법이다.
처음 시작한다면 GitHub CLI를 권장한다. gh auth login 한 번으로 인증 설정이 끝나고, SSH 키도 자동 생성된다. 이미 SSH에 익숙하거나 GitHub CLI를 설치하기 어려운 환경이라면 직접 SSH 키를 생성해도 좋다. 개인 접근 토큰은 자동화 스크립트나 특수한 상황에서 사용한다.
17.3.2 SSH 공개 키 인증 원리
SSH 인증이 어떻게 작동하는지 이해하면 설정 과정이 훨씬 명확해진다. SSH 키 인증은 비대칭 암호화(asymmetric cryptography)라는 수학적 원리를 기반으로 한다. 비대칭 암호화에서는 암호화에 사용하는 키와 복호화에 사용하는 키가 서로 다르다.
핵심 아이디어는 간단하다. 비밀 키(private key)와 공개 키(public key)라는 두 개의 키를 쌍으로 생성하고, 공개 키로 암호화한 메시지는 오직 짝이 되는 비밀 키로만 복호화할 수 있다. 비밀 키는 내 컴퓨터에 안전하게 보관하고, 공개 키는 GitHub에 등록한다. 그림 17.7 은 인증 과정을 보여준다.
GitHub에 접속을 요청하면, GitHub은 등록된 공개 키로 암호화한 질문을 보낸다. 올바른 비밀 키를 가진 사람만 질문에 답할 수 있으므로, 비밀번호 없이도 신원이 증명된다. 비밀번호를 네트워크로 전송하지 않아 도청 위험이 없고, 매번 비밀번호를 입력하는 번거로움도 사라진다.
비밀 키는 절대 외부에 공유하면 안 된다. 비밀 키가 유출되면 누구나 내 계정으로 GitHub에 접근할 수 있다. 반면 공개 키는 이름 그대로 공개해도 안전하다. 공개 키만으로는 비밀 키를 역산할 수 없기 때문이다.
17.3.3 GitHub CLI로 인증하기
앞서 소개한 GitHub CLI를 사용해 인증을 설정해 보자. cli.github.com에서 직접 다운로드하거나, 운영체제별 패키지 관리자로 설치할 수 있다.
# macOS (Homebrew)
$ brew install gh
# Windows (winget)
$ winget install --id GitHub.cli
# Ubuntu/Debian
$ sudo apt install gh설치 후 gh auth login 명령을 실행한다.
$ gh auth login몇 가지 질문에 답하면 인증이 완료된다. GitHub.com을 선택하고, SSH 프로토콜을 선택한 뒤, SSH 키 생성 여부를 묻는 질문에 “Yes”를 선택한다. 웹 브라우저가 열리면 GitHub에 로그인하고 장치 코드를 입력한다.
? What account do you want to log into? GitHub.com
? What is your preferred protocol for Git operations? SSH
? Generate a new SSH key to add to your GitHub account? Yes
? Enter a passphrase for your new SSH key (Optional):
? Title for your SSH key: (GitHub CLI)
? How would you like to authenticate GitHub CLI? Login with a web browser
인증이 완료되면 SSH 키가 자동으로 생성되고 GitHub 계정에 등록된다. gh auth status 명령으로 인증 상태를 확인할 수 있다.
$ gh auth status
github.com
✓ Logged in to github.com account username (keyring)
- Active account: true
- Git operations protocol: ssh
- Token: gho_************************************
- Token scopes: 'gist', 'read:org', 'repo', 'workflow'17.3.4 SSH 키 직접 생성하기
GitHub CLI를 설치할 수 없는 환경이거나, SSH 키 생성 과정을 직접 제어하고 싶다면 ssh-keygen 명령을 사용한다. ssh-keygen은 OpenSSH에 포함된 표준 도구로, 맥OS와 리눅스에는 기본 설치되어 있고 윈도우 10 이상에서도 OpenSSH 클라이언트가 기본 제공된다. 키 생성 과정은 네 단계로 이루어진다: 명령 실행, 키 쌍 생성, 비밀 키 보관, 공개 키 등록. 그림 17.8 은 전체 과정을 보여준다.
키를 생성할 때는 암호화 알고리즘을 선택해야 하는데, 최신 알고리즘인 Ed25519를 권장한다. Ed25519는 RSA보다 키 길이가 짧으면서도 보안 강도가 높고 생성 속도도 빠르다. -C 옵션으로 이메일 주소를 지정하면 공개 키 끝에 주석으로 추가되어 여러 키를 구분하기 쉬워진다.
$ ssh-keygen -t ed25519 -C "your_email@example.com"키 저장 위치와 암호문(passphrase)을 묻는 질문이 나온다. 기본 위치(~/.ssh/id_ed25519)를 그대로 사용하려면 Enter를 누른다. 암호문은 비밀 키에 추가 보안을 제공하는데, 빈칸으로 두면 암호문 없이 키를 사용할 수 있다.
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/user/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/user/.ssh/id_ed25519
Your public key has been saved in /home/user/.ssh/id_ed25519.pub
생성된 공개 키를 GitHub에 등록한다. 먼저 공개 키 내용을 확인하고 복사한다.
$ cat ~/.ssh/id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... your_email@example.comGitHub 웹사이트에서 우측 상단 프로필 아이콘을 클릭하고 Settings로 이동한다. 좌측 메뉴에서 SSH and GPG keys를 선택하고 New SSH key 버튼을 클릭한다. Title에는 컴퓨터를 식별할 수 있는 이름(예: “MacBook Pro”)을 입력하고, Key 필드에 복사한 공개 키 전체를 붙여넣은 뒤 Add SSH key를 클릭한다.
연결을 테스트하려면 다음 명령을 실행한다.
$ ssh -T git@github.com
Hi username! You've successfully authenticated, but GitHub does
not provide shell access.“successfully authenticated” 메시지가 나오면 설정이 완료된 것이다.
ssh-keygen의 -t 옵션은 암호화 알고리즘을 지정한다. Ed25519는 2014년 도입된 최신 알고리즘으로, RSA보다 키 길이가 짧으면서도 보안 강도가 높고 성능도 빠르다. 오래된 시스템에서는 Ed25519를 지원하지 않을 수 있는데, 그 경우 RSA 4096비트를 사용한다.
# 오래된 시스템용 RSA 키 생성
$ ssh-keygen -t rsa -b 4096 -C "your_email@example.com"17.4 저장소 생성
설정이 끝났으니 실제로 Git을 사용해 보자. 본 장에서 다루는 예제는 전 세계 연구자들에게 프로그래밍과 데이터 과학을 가르치는 Software Carpentry 커뮤니티의 Git 교재를 바탕으로 한다. 원본 교재는 영문으로 작성되어 있으며, 한국 R 사용자회에서 한글로 번역한 Git 교재에 뿌리를 두고 있다.
프로젝트 주인공은 화성 탐사 프로젝트에 참여한 세 명의 연구원이다. 늑대인간(Wolfman)은 달의 영향을 연구하고, 드라큘라(Dracula)는 화성의 햇빛을 분석하며, 미라(Mummy)는 고대 화성 문명의 흔적을 추적한다. 서로 다른 배경을 가진 세 연구원이 하나의 프로젝트에서 협업하는 과정을 따라가며 Git의 핵심 기능을 익힌다. 팀원들이 각자의 연구 내용을 어떻게 기록하고, 변경 사항을 추적하며, 충돌을 해결하는지 살펴보자.
드라큘라가 화성 탐사 데이터를 정리할 프로젝트를 시작한다. 먼저 바탕화면에 planets라는 작업 디렉토리를 만들고 그 안으로 이동한다. 디렉토리 이름은 프로젝트 성격을 잘 드러내는 것이 좋다.
$ cd ~/Desktop
$ mkdir planets
$ cd planets디렉토리를 만들었다고 해서 Git이 자동으로 관리를 시작하는 것은 아니다. 일반 폴더를 Git 저장소(repository)로 바꾸려면 git init 명령을 실행해야 한다. 저장소란 Git이 파일의 모든 버전 정보를 보관하는 특별한 공간이다.
$ git init
Initialized empty Git repository in /Users/dracula/Desktop/planets/.git/“Initialized empty Git repository”라는 메시지가 나오면 저장소가 성공적으로 생성된 것이다. ls 명령으로 디렉토리 내용을 확인해 보면 아무것도 보이지 않는다.
$ ls겉보기에는 변화가 없지만, -a 옵션으로 숨김 파일까지 표시하면 .git이라는 디렉토리가 새로 생긴 것을 확인할 수 있다.
$ ls -a
. .. .gitGit은 프로젝트의 모든 버전 정보를 .git 디렉토리에 저장한다. 커밋 이력, 브랜치 정보, 설정 파일 등 Git이 동작하는 데 필요한 모든 데이터가 이곳에 보관된다. 프로젝트 폴더 안의 다른 파일들은 자유롭게 편집하고 삭제해도 되지만, .git 디렉토리를 건드리면 전체 이력이 사라지므로 절대 삭제하면 안 된다.
저장소가 제대로 작동하는지 확인하는 가장 좋은 방법은 git status 명령이다. Git을 사용하면서 가장 자주 실행하게 될 명령어이기도 하다.
$ git status
On branch master
No commits yet
nothing to commit (create/copy files and use "git add" to track)출력 결과는 현재 저장소 상태를 요약해서 보여준다. “On branch master”는 기본 브랜치에 있다는 뜻이고, “No commits yet”은 아직 아무것도 저장하지 않았다는 의미다. “nothing to commit”은 추적할 새 파일이 없다는 뜻인데, 아직 파일을 만들지 않았으니 당연한 결과다. Git 버전에 따라 출력 형식이 약간 다를 수 있지만 핵심 내용은 동일하다.
드라큘라가 planets 프로젝트에서 작업하다가 달(moons) 관련 데이터도 관리하고 싶어졌다. 늑대인간이 만류했지만, 드라큘라는 planets 안에 moons 하위 디렉토리를 만들고 그곳에서 git init을 실행하려 한다. 과연 좋은 생각일까?
정답은 “아니오”다. planets 저장소는 이미 모든 하위 디렉토리와 파일을 추적한다. moons 데이터가 필요하다면 단순히 하위 디렉토리로 만들면 충분하다. 저장소를 중첩하면 외부 저장소가 내부 저장소의 .git 디렉토리까지 추적하려 해서 예기치 않은 문제가 발생한다. 별도 프로젝트로 관리하고 싶다면 planets와 같은 수준의 독립된 디렉토리에 새 저장소를 만들어야 한다.
새 저장소를 만들기 전에 git status로 현재 위치가 기존 저장소 안인지 확인하는 습관을 들이자.
$ git status
fatal: Not a git repository (or any of the parent directories): .git위 메시지가 나오면 저장소 밖이므로 git init을 실행해도 안전하다. 만약 실수로 저장소 안에서 git init을 실행했다면 해당 디렉토리의 .git 폴더를 삭제하면 된다.
$ rm -rf moons/.git단, rm -rf는 복구가 불가능하므로 경로를 정확히 확인해야 한다. 잘못된 경로를 입력하면 의도치 않게 전체 프로젝트 이력이 사라질 수 있다.
💡 생각해볼 점
Git은 단순히 파일을 백업하는 도구가 아니다. 프로젝트의 모든 변경 이력을 체계적으로 기록하고, 언제든 과거 시점으로 돌아갈 수 있게 해주는 “타임머신”이다. 버전 관리 시스템이 50년에 걸쳐 진화해 온 이유는 협업과 실수 복구라는 두 가지 근본적인 필요 때문이다. Git이 3세대 분산형 시스템의 대표 주자로 자리 잡은 배경에는 오프라인 작업 지원, 빠른 성능, GitHub이라는 강력한 협업 생태계가 있다.
초기 설정에서 가장 중요한 것은 user.name과 user.email이다. 커밋할 때마다 작성자 정보로 기록되므로, 팀 프로젝트에서는 누가 어떤 변경을 했는지 명확히 추적할 수 있다. GitHub 인증 방식으로는 SSH 키를 권장하는데, 한 번 설정해 두면 비밀번호 입력 없이 안전하게 작업할 수 있기 때문이다. GitHub CLI를 사용하면 복잡한 SSH 키 생성 과정을 자동화할 수 있어 초보자에게 특히 유용하다.
저장소를 생성할 때 기억해야 할 핵심은 .git 디렉토리다. Git의 모든 마법은 숨겨진 .git 폴더 안에서 일어난다. 프로젝트 파일은 자유롭게 수정해도 되지만, .git을 건드리면 전체 이력이 사라진다. 또한 저장소를 중첩하면 예기치 않은 문제가 발생하므로, 새 저장소를 만들기 전에 git status로 현재 위치를 확인하는 습관을 들이자.
지금까지 Git 환경을 설정하고 빈 저장소를 만들었다. 다음 장에서는 실제로 파일을 만들고, 변경 사항을 추적하며, 커밋으로 저장하는 방법을 배운다. 드라큘라가 화성 탐사 데이터를 어떻게 기록하고 관리하는지 따라가 보자.