Git은 현재 가장 널리 사용되는 버전 관리 시스템입니다. 초기 설정부터 시작해 브랜치, 머지, 리베이스, 변경 취소, 스태시, 팀 협업 워크플로우 등 일상 개발에서 사용하는 대부분의 작업을 다룹니다.
초기 설정
처음 Git을 사용하기 전에 전역 설정을 합니다:
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
기본 브랜치 이름 설정 (main 권장):
git config --global init.defaultBranch main
기본 편집기 설정 (VS Code 예시):
git config --global core.editor "code --wait"
모든 설정 확인:
git config --list
저장소 만들기
처음부터 시작:
mkdir my-project && cd my-project
git init
기존 저장소 클론:
# HTTPS (사용자명/비밀번호 또는 토큰 필요)
git clone https://github.com/user/repo.git
# SSH (SSH 키 설정 필요)
git clone git@github.com:user/repo.git
# 특정 폴더 이름으로 클론
git clone git@github.com:user/repo.git my-folder
기본 워크플로우
Git의 로컬 구조는 3단계입니다: 작업 디렉토리 → 스테이징 영역 → 로컬 저장소
# 현재 상태 확인
git status
# 파일을 스테이징에 추가
git add file.txt
git add . # 모든 변경사항 스테이지
git add -p # 변경사항 일부를 대화형으로 선택 (매우 유용)
# 커밋
git commit -m "feat: add user login"
# 스테이징 건너뛰고 추적된 파일 직접 커밋
git commit -am "fix: correct typo"
커밋 메시지 규약 (Conventional Commits)
좋은 커밋 메시지는 히스토리를 읽기 쉽게 하고 CHANGELOG 자동 생성을 가능하게 합니다:
type(scope): subject
feat 새 기능
fix 버그 수정
docs 문서 변경
style 포맷 조정 (로직 변경 없음)
refactor 리팩토링
test 테스트 추가 또는 수정
chore 빌드 프로세스, 도구 설정 등
히스토리 확인
# 커밋 히스토리 확인
git log
# 간결한 한 줄 형식
git log --oneline
# 그래픽 브랜치 뷰
git log --oneline --graph --all
# 특정 파일의 히스토리 확인
git log --follow -- path/to/file
# 특정 커밋의 변경사항 확인
git show <commit-hash>
브랜치 관리
브랜치는 Git의 가장 강력한 기능 중 하나로, 생성 및 전환 비용이 거의 없습니다.
# 모든 브랜치 목록
git branch
git branch -a # 원격 브랜치 포함
# 새 브랜치 생성
git branch feature/login
# 브랜치 전환
git switch feature/login
# 생성과 전환을 한 번에 (자주 쓰는 단축 명령)
git switch -c feature/login
# 브랜치 삭제
git branch -d feature/login # 안전 삭제 (미머지 시 경고)
git branch -D feature/login # 강제 삭제
# 현재 브랜치 이름 변경
git branch -m new-name
머지
# 대상 브랜치로 전환 (보통 main)
git switch main
# feature 브랜치 머지
git merge feature/login
Fast-forward 머지: 대상 브랜치에 새 커밋이 없으면 포인터를 앞으로 이동하기만 합니다 — 히스토리가 직선으로 유지됩니다.
Non-fast-forward 머지: 대상에 새 커밋이 있으면 머지 커밋이 생성되고 히스토리에 분기 구조가 남습니다.
항상 머지 커밋을 생성하려면 --no-ff:
git merge --no-ff feature/login
충돌 해결
머지 충돌이 발생하면 파일에 마커가 표시됩니다:
<<<<<<< HEAD
로컬 내용
=======
머지되는 내용
>>>>>>> feature/login
올바른 내용이 되도록 수동으로 편집한 후:
git add .
git commit # Git이 머지 커밋 메시지를 자동 입력
리베이스
리베이스는 현재 브랜치의 커밋을 다른 브랜치 끝에 "이식"하여 히스토리를 선형으로 유지합니다.
# feature 브랜치에서 최신 main 위에 이식
git switch feature/login
git rebase main
대화형 리베이스 (커밋 히스토리 정리에 매우 유용):
# 최근 3개의 커밋 편집
git rebase -i HEAD~3
편집기에서 사용할 수 있는 명령:
| 명령 | 효과 |
|---|---|
pick | 커밋을 그대로 유지 |
reword | 유지하지만 메시지 수정 |
squash | 이전 커밋에 합치기 |
fixup | squash와 같고 메시지 버림 |
drop | 커밋 삭제 |
주의: 이미 원격 공개 브랜치에 push된 커밋은 절대 리베이스하지 마세요 — 다른 사람의 히스토리와 충돌을 일으킵니다.
원격 저장소
# 원격 확인
git remote -v
# 원격 추가
git remote add origin git@github.com:user/repo.git
# 원격 URL 변경
git remote set-url origin git@github.com:user/new-repo.git
# 푸시 (처음에는 -u로 업스트림 설정)
git push -u origin main
# 이후에는
git push
# 풀 (fetch + merge)
git pull
# fetch만, 머지 없이
git fetch origin
# 원격 브랜치 삭제
git push origin --delete feature/login
스태시
브랜치를 전환해야 하는데 커밋할 준비가 안 된 변경사항이 있을 때:
# 현재 변경사항 스태시
git stash
# 설명과 함께 스태시
git stash push -m "wip: half-done login form"
# 스태시 목록 확인
git stash list
# 가장 최근 스태시 복원 (목록에 유지)
git stash apply
# 복원하고 목록에서 제거
git stash pop
# 특정 스태시 복원
git stash apply stash@{2}
# 특정 스태시 삭제
git stash drop stash@{0}
# 모든 스태시 삭제
git stash clear
변경 취소
Git에는 여러 취소 명령이 있습니다. 상황별로 이해하세요:
작업 디렉토리 변경 취소 (add 전)
# 파일을 마지막 커밋 상태로 복원
git restore file.txt
# 모든 파일 복원
git restore .
스테이징 취소 (add 후, commit 전)
git restore --staged file.txt
마지막 커밋 수정
# 커밋 메시지 편집 또는 빠진 파일 추가
git add forgotten-file.txt
git commit --amend
커밋 안전하게 취소 (역방향 커밋 생성)
git revert <commit-hash>
특정 버전으로 롤백 (reset)
# 소프트 리셋: 커밋 취소, 변경사항은 스테이징에 유지
git reset --soft HEAD~1
# 믹스드 리셋 (기본값): 커밋 취소, 변경사항을 작업 디렉토리로 이동
git reset HEAD~1
# 하드 리셋: 커밋과 변경사항 모두 폐기 (위험, 신중하게)
git reset --hard HEAD~1
revertvsreset:
revert는 변경사항을 되돌리는 새 커밋을 추가합니다. 히스토리 보존 — 공개 브랜치에 안전reset은 히스토리를 직접 수정합니다 — push하지 않은 로컬 커밋에만 사용
태그
보통 릴리스 버전 표시에 사용합니다:
# 경량 태그
git tag v1.0.0
# 주석이 있는 태그 (메시지 포함)
git tag -a v1.0.0 -m "Release version 1.0.0"
# 모든 태그 목록
git tag
# 원격에 태그 푸시
git push origin v1.0.0
git push origin --tags # 모든 태그 푸시
# 태그 삭제
git tag -d v1.0.0
git push origin --delete v1.0.0 # 원격 태그 삭제
.gitignore
.gitignore는 Git에 추적하지 않을 파일을 알려줍니다:
# 의존성
node_modules/
vendor/
# 빌드 출력
dist/
build/
*.min.js
# 환경 변수
.env
.env.local
# OS 파일
.DS_Store
Thumbs.db
# IDE 설정
.vscode/
.idea/
이미 Git이 추적하는 파일은 .gitignore에 추가해도 자동으로 무시되지 않습니다 — 먼저 추적을 해제해야 합니다:
git rm --cached file.txt # 단일 파일 추적 해제
git rm --cached -r node_modules/ # 디렉토리 추적 해제
협업 시나리오
Fork + Pull Request 워크플로우
- 대상 저장소를 자신의 계정으로 Fork
- 자신의 Fork 클론
- feature 브랜치 생성
- 개발 및 커밋
- 자신의 Fork에 푸시
- GitHub / GitLab에서 Pull Request / Merge Request 생성
Fork를 업스트림과 동기화:
# 업스트림 원격 추가
git remote add upstream git@github.com:original/repo.git
# 업스트림 최신 가져오기
git fetch upstream
# 로컬 main에 머지
git switch main
git merge upstream/main
팀 협업 주요 원칙
main/master는 보통 보호되어 직접 push 불가- 기능마다 feature 브랜치를 하나씩 생성
- 머지 전에 최신 main으로 리베이스하여 충돌 최소화
- PR에서 코드 리뷰 후 머지
유용한 명령어
# 두 브랜치의 차이 확인
git diff main feature/login
# 파일의 각 줄을 누가 변경했는지 확인
git blame file.txt
# 버그를 도입한 커밋을 이진 탐색으로 찾기
git bisect start
git bisect bad # 현재 버전에 버그 있음
git bisect good v1.0.0 # 이 버전은 정상
# Git이 중간 지점을 체크아웃 — 테스트 후 good/bad 표시
git bisect reset # 종료
# 특정 커밋을 현재 브랜치에 적용
git cherry-pick <commit-hash>
# 추적되지 않는 파일과 디렉토리 정리
git clean -fd
자주 발생하는 문제
push 거부됨 (rejected)
보통 원격에 다른 사람의 새 커밋이 있는 경우:
git pull --rebase # 가져온 후 리베이스, 선형 히스토리 유지
git push
실수로 삭제한 브랜치 복원
커밋은 즉시 사라지지 않습니다. reflog로 찾을 수 있습니다:
git reflog # 모든 작업 히스토리 확인
git switch -c recovered-branch <commit-hash>
큰 파일을 실수로 커밋했을 때
큰 파일은 Git 저장소에 넣으면 안 됩니다 (저장소가 영구적으로 커집니다).
아직 push하지 않은 경우:
git rm --cached bigfile.zip
git commit --amend
이미 push한 경우 git filter-repo(폐기된 filter-branch의 대체)로 히스토리에서 완전히 제거해야 합니다. 작업이 복잡하므로 처음부터 .gitignore로 방지하는 것이 최선입니다.
Fonnpo