버전 관리 — Git으로 협업하기¶
왜 버전 관리가 필요한가?¶
혼자 개발할 때도, 팀으로 개발할 때도 이런 상황이 생깁니다.
"어제 코드로 돌아가고 싶어."
"누가 이 코드를 바꿨지?"
"A가 기능 추가하는 동안 B가 버그를 고치려면?"
"테스트 중에 실수로 파일을 지워버렸어."
Git은 이 모든 문제를 해결하는 버전 관리 시스템입니다.
Git 기본 개념¶
저장소 (Repository)¶
프로젝트의 전체 변경 이력을 담는 공간입니다.
로컬 저장소: 내 컴퓨터에 있는 저장소
원격 저장소: GitHub 같은 서버에 있는 저장소
커밋 (Commit)¶
특정 시점의 코드 상태를 저장하는 행위입니다.
커밋 1: "프로젝트 초기화"
커밋 2: "로그인 기능 추가"
커밋 3: "버그 수정: 빈 제목 허용 오류"
커밋 4: "테스트 코드 추가"
각 커밋에는 누가, 언제, 무엇을 바꿨는지 기록됩니다.
기본 명령어¶
저장소 설정¶
# 현재 디렉토리를 Git 저장소로 초기화
git init
# 원격 저장소(GitHub) 연결
git remote add origin https://github.com/username/repo.git
변경사항 저장¶
# 현재 상태 확인
git status
# 변경된 파일 확인
git diff
# 파일 스테이징 (커밋할 파일 선택)
git add main.py
git add . # 모든 변경 파일
# 커밋 (메시지와 함께 저장)
git commit -m "로그인 API 구현"
# 원격 저장소에 올리기
git push origin main
이력 확인¶
# 커밋 이력 보기
git log
git log --oneline # 한 줄로 요약
# 특정 파일의 변경 이력
git log main.py
# 누가 이 줄을 바꿨는지
git blame main.py
되돌리기¶
# 마지막 커밋 이후 변경사항 취소 (파일 복원)
git restore main.py
# 특정 커밋 시점으로 파일 복원
git checkout abc1234 -- main.py
# 커밋을 되돌리는 새 커밋 생성 (안전)
git revert abc1234
브랜치 (Branch) — 병렬 작업의 핵심¶
브랜치는 코드의 분기점입니다.
메인 코드를 건드리지 않고 새 기능을 개발할 수 있습니다.
main ──●──●──●──────────────●──
\ /
feature/login ●──●──●──●
# 브랜치 목록 확인
git branch
# 새 브랜치 생성 + 이동
git checkout -b feature/login
# 또는 (최신 방식)
git switch -c feature/login
# 브랜치 이동
git switch main
# 브랜치 삭제
git branch -d feature/login
팀 협업 워크플로우¶
GitHub Flow (가장 단순)¶
1. main 브랜치에서 새 브랜치 생성
git switch -c feature/my-feature
2. 변경사항 커밋
git add .
git commit -m "새 기능 추가"
3. 원격 저장소에 올리기
git push origin feature/my-feature
4. GitHub에서 Pull Request(PR) 생성
→ 팀원이 코드 리뷰
5. 승인 후 main에 병합 (Merge)
6. 로컬에서 최신 main 받기
git switch main
git pull origin main
Pull Request (PR) / Merge Request (MR)¶
PR은 "이 브랜치를 main에 합쳐도 되나요?" 하고 팀에 묻는 과정입니다.
PR에서 확인하는 것:
- 코드가 올바르게 동작하는가
- 코드 품질이 기준에 맞는가
- 테스트가 통과하는가
충돌 (Conflict) 해결¶
같은 파일의 같은 부분을 두 사람이 동시에 수정하면 충돌이 생깁니다.
# Git이 표시하는 충돌 내용
<<<<<<< HEAD
def greet(name):
return f"안녕, {name}"
=======
def greet(name):
return f"Hello, {name}!"
>>>>>>> feature/english
<<<<<<< HEAD : 내 브랜치의 내용
======= : 구분선
>>>>>>> feature/ : 합치려는 브랜치의 내용
해결 방법: 두 코드 중 원하는 버전을 선택하고 표시 기호를 제거합니다.
# 충돌 해결 후
def greet(name):
return f"안녕, {name}!" # 두 내용을 합치거나 하나를 선택
# 해결 후 커밋
git add main.py
git commit -m "merge conflict 해결"
.gitignore — 추적하지 않을 파일¶
# .gitignore
.env ← 환경 변수 (비밀 키 포함)
*.db ← 데이터베이스 파일
__pycache__/ ← Python 캐시
*.pyc
node_modules/ ← JavaScript 패키지
.DS_Store ← macOS 시스템 파일
.gitignore에 포함된 파일은 git status에 나타나지 않고, 커밋에 포함되지 않습니다.
좋은 커밋 메시지 작성법¶
나쁜 예:
fix
수정
asdfasdf
좋은 예:
feat: JWT 인증 기능 추가
fix: 빈 제목으로 todo 생성 시 500 오류 수정
refactor: get_db() 함수 중복 제거
docs: API 엔드포인트 목록 문서화
타입 접두사 (선택):
feat: 새 기능
fix: 버그 수정
refactor: 기능 변경 없는 코드 개선
docs: 문서만 수정
test: 테스트 관련
chore: 빌드, 설정 등 기타
자주 쓰는 명령어 한눈에 보기¶
git status # 현재 상태
git add . # 전체 스테이징
git commit -m "메시지" # 커밋
git push origin main # 올리기
git pull origin main # 받기
git switch -c feature/xxx # 새 브랜치
git switch main # 브랜치 이동
git log --oneline # 이력 보기
git diff # 변경사항 보기
실습 미션¶
미션 1: 기본 흐름¶
1. 새 디렉토리에 git init 하세요.
2. main.py 파일을 만들고 커밋하세요.
3. main.py를 수정하고 git diff로 차이를 확인하세요.
4. 두 번째 커밋을 만드세요.
5. git log --oneline으로 이력을 확인하세요.
미션 2: 브랜치 실습¶
1. feature/hello 브랜치를 만드세요.
2. 해당 브랜치에서 greet() 함수를 추가하고 커밋하세요.
3. main 브랜치로 돌아와 다른 수정을 커밋하세요.
4. feature/hello를 main에 병합(merge)하세요.
미션 3: GitHub 연동¶
1. GitHub에서 새 저장소를 만드세요.
2. 로컬 저장소와 연결하세요.
3. push해서 코드를 올리세요.
4. GitHub에서 커밋 이력을 확인하세요.
미션 4 (심화): 충돌 해결¶
같은 파일을 두 브랜치에서 동시에 수정하고
merge 시 충돌을 의도적으로 만들어 직접 해결해 보세요.
핵심 요약¶
| 개념 | 설명 |
|---|---|
| 저장소 | 프로젝트의 전체 변경 이력 |
| 커밋 | 특정 시점의 코드 스냅샷 |
| 브랜치 | 독립적인 작업 공간 |
| merge | 두 브랜치를 하나로 합치기 |
| PR | 코드 리뷰 후 main에 병합 요청 |
.gitignore |
Git이 추적하지 않을 파일 목록 |
| 충돌 | 같은 부분을 두 브랜치가 다르게 수정 |
코드보다 커밋을 먼저 생각하세요.
"이 변경이 왜 필요한가?"가 커밋 메시지에 담겨야 합니다.