안녕하세요, 자바파커입니다.
"git 명령어, 매번 검색하고 계신가요?"
결론부터 말씀드리면 — Git의 핵심 개념은 10년 전과 달라지지 않았지만, 현대적 명령어(git switch, git restore)로 정리하면 훨씬 직관적입니다. 이 글 하나만 북마크해두면 일상 작업의 95%는 커버됩니다.
이 글에서는 Git 2.45+ 기준으로 기본 개념, 필수 명령어, 실전 시나리오, 커밋 컨벤션까지 한 번에 정리합니다.
형상관리란 무엇인가
형상관리(SCM, Source Code Management)는 소스 코드의 변경 이력을 체계적으로 관리하는 것입니다. 누가, 언제, 왜, 무엇을 바꿨는지를 기록합니다.
형상관리 없이 개발하면
프로젝트_최종.zip,프로젝트_최종_진짜최종.zip,프로젝트_최종_v3_수정.zip- "어제 고친 코드가 뭐였지?" — 기억에 의존
- "이 버그, 언제부터 있었지?" — 추적 불가
- 컴퓨터 포맷하면 모든 히스토리 소실
2026년 현재, Git은 사실상 유일한 선택지
| 도구 | 방식 | 상태 |
|---|---|---|
| Git | 분산형 | 업계 표준, 압도적 1위 |
| Subversion (SVN) | 중앙집중형 | 레거시 유지보수 모드 |
| Mercurial | 분산형 | 거의 사용 안 함 |
GitHub, GitLab, Bitbucket 모두 Git 기반입니다. 다른 도구를 익힐 이유가 없습니다.
Git의 4가지 영역 — 이것만 이해하면 끝
Git을 이해하는 가장 빠른 길은 4가지 영역을 머리에 그리는 것입니다.
┌─────────────────┐ git add ┌──────────────┐ git commit ┌───────────────┐ git push ┌───────────────┐
│ Working Directory│ ───────────> │ Staging │ ───────────> │ Local Repo │ ────────> │ Remote Repo │
│ (작업 디렉토리) │ │ (스테이지) │ │ (로컬 저장소) │ │ (원격 저장소) │
└─────────────────┘ └──────────────┘ └───────────────┘ └───────────────┘
▲ │
└──────────────────────────────── git pull / git fetch ◀───────────────────────────────────────┘| 영역 | 설명 | 대표 명령어 |
|---|---|---|
| Working Directory | 실제 편집 중인 파일 | git status, git diff |
| Staging Area | 다음 커밋에 포함할 변경 사항 | git add, git restore --staged |
| Local Repository | 내 컴퓨터의 커밋 히스토리 | git commit, git log |
| Remote Repository | GitHub 등 원격 저장소 | git push, git pull, git fetch |
이 흐름만 머리에 있으면 대부분의 명령어가 자연스럽게 이해됩니다.
필수 명령어 레퍼런스 (2026 현대 명령어 기준)
2019년 Git 2.23에서 도입된 git switch와 git restore가 현재 완전히 정착했습니다. git checkout은 여전히 동작하지만, 브랜치 이동과 파일 복원을 한 명령어가 같이 처리해서 혼란스러워 권장되지 않습니다. 새로 시작하시는 분은 switch/restore로 익히세요.
초기화 · 복제
| 명령어 | 설명 |
|---|---|
git init |
현재 디렉토리를 Git 저장소로 초기화 |
git clone <url> |
원격 저장소를 로컬로 복제 |
git clone --depth=1 <url> |
최신 커밋 1개만 가져오기 (얕은 복제) |
상태 확인
| 명령어 | 설명 |
|---|---|
git status |
변경/스테이징 상태 확인 |
git status -s |
짧은 형식으로 출력 |
git diff |
Working ↔ Staging 차이 |
git diff --staged |
Staging ↔ Local Repo 차이 |
git log --oneline --graph --all |
그래프 형태로 전체 히스토리 |
git log -p <파일> |
특정 파일의 변경 이력 |
git blame <파일> |
각 줄의 마지막 수정자 확인 |
변경 추적 · 커밋
| 명령어 | 설명 |
|---|---|
git add <파일> |
특정 파일을 스테이징 |
git add . |
현재 디렉토리 변경 전체 스테이징 |
git add -p |
변경 단위(hunk)별로 선택 스테이징 |
git commit -m "메시지" |
스테이지된 변경을 커밋 |
git commit --amend |
마지막 커밋 수정 |
브랜치 — git switch (현대 명령어)
| 명령어 | 설명 | 과거 방식 |
|---|---|---|
git branch |
로컬 브랜치 목록 | — |
git branch -a |
원격 포함 전체 브랜치 | — |
git switch <브랜치> |
브랜치 이동 | git checkout <브랜치> |
git switch -c <브랜치> |
브랜치 생성 + 이동 | git checkout -b <브랜치> |
git switch - |
직전 브랜치로 이동 | git checkout - |
git branch -d <브랜치> |
브랜치 삭제 (병합된 것만) | — |
git branch -D <브랜치> |
강제 삭제 | — |
git branch -m <새이름> |
현재 브랜치 이름 변경 | — |
파일 복원 — git restore (현대 명령어)
| 명령어 | 설명 | 과거 방식 |
|---|---|---|
git restore <파일> |
Working Directory 변경 취소 | git checkout -- <파일> |
git restore --staged <파일> |
스테이징 취소 (변경은 유지) | git reset HEAD <파일> |
git restore --source=HEAD~2 <파일> |
특정 커밋 시점으로 파일 복원 | git checkout HEAD~2 -- <파일> |
원격 저장소
| 명령어 | 설명 |
|---|---|
git remote -v |
원격 저장소 목록 |
git remote add origin <url> |
원격 연결 추가 |
git fetch |
원격 변경 가져오기 (병합 안 함) |
git pull |
fetch + merge |
git pull --rebase |
fetch + rebase (히스토리 깔끔) |
git push |
원격에 푸시 |
git push -u origin <브랜치> |
업스트림 설정하며 푸시 |
병합 · 리베이스
| 명령어 | 설명 |
|---|---|
git merge <브랜치> |
현재 브랜치로 병합 |
git merge --no-ff <브랜치> |
Fast-forward 방지 (머지 커밋 생성) |
git rebase <브랜치> |
현재 브랜치를 다른 브랜치 위로 재배치 |
git rebase -i HEAD~3 |
최근 3개 커밋 대화형 정리 |
git cherry-pick <커밋해시> |
특정 커밋만 가져오기 |
태그 · Stash
| 명령어 | 설명 |
|---|---|
git tag v1.0.0 |
현재 커밋에 태그 |
git tag -a v1.0.0 -m "릴리즈" |
주석 포함 태그 |
git push origin v1.0.0 |
태그 푸시 |
git stash |
작업 중 변경 임시 저장 |
git stash pop |
가장 최근 stash 복원 후 삭제 |
git stash list |
stash 목록 |
git stash drop |
가장 최근 stash 버리기 |
실전 시나리오 — 이럴 땐 이렇게
시나리오 1. 실수 커밋 되돌리기 — reset vs revert
두 명령어는 목적이 다릅니다.
# reset: 히스토리를 "없었던 일"로 만듭니다 (로컬 전용)
git reset --soft HEAD~1 # 커밋만 취소, 변경은 Staging에 유지
git reset --mixed HEAD~1 # 커밋+Staging 취소 (기본값, 변경은 유지)
git reset --hard HEAD~1 # 커밋+Staging+변경 전부 삭제 (주의!)
# revert: "취소하는 새 커밋"을 추가합니다 (공유 브랜치에서 안전)
git revert HEAD # 마지막 커밋의 반대 커밋 생성기준: 아직 푸시 안 했으면 reset, 이미 원격에 올라갔으면 반드시 revert를 쓰세요. 공유 브랜치를 reset --hard + push --force하면 팀원들의 히스토리가 깨집니다.
시나리오 2. 커밋 메시지 수정
# 마지막 커밋 (아직 푸시 전)
git commit --amend -m "feat: 올바른 메시지"
# 이미 푸시했다면 — 강제 푸시 필요 (팀에게 공지 후!)
git commit --amend -m "수정된 메시지"
git push --force-with-lease--force-with-lease는 --force보다 안전합니다. 내가 모르는 새 커밋이 원격에 있으면 푸시를 거부합니다.
시나리오 3. 마지막 커밋에 파일 추가
# 빠뜨린 파일 스테이징
git add src/forgotten.js
# --no-edit: 커밋 메시지 유지한 채 추가
git commit --amend --no-edit시나리오 4. 브랜치 병합 충돌 해결
git switch main
git pull
git switch feature/login
git merge main
# → 충돌 발생
# 1. 충돌 파일 열면 <<<<<<<, =======, >>>>>>> 마커가 보임
# 2. 직접 편집하여 최종 코드 결정
# 3. 해결된 파일 스테이징
git add src/auth.js
# 4. 병합 커밋 완료
git commit
# 취소하고 싶다면
git merge --abortVS Code, IntelliJ의 3-way merge 뷰를 쓰면 훨씬 수월합니다.
시나리오 5. 특정 파일만 되돌리기
# Working Directory 변경 취소
git restore src/config.js
# Staging만 취소 (변경은 유지)
git restore --staged src/config.js
# 3개 커밋 전 상태로 파일 복원
git restore --source=HEAD~3 src/config.js시나리오 6. 작업 중 급하게 다른 브랜치로 이동
# 현재 작업 임시 저장
git stash push -m "프로필 페이지 작업 중"
# 긴급 브랜치 이동
git switch hotfix/urgent
# ...핫픽스 작업...
git switch -
# 작업 복원
git stash pop.gitignore — 불필요한 파일 제외하기
프로젝트에 포함하면 안 되는 파일을 .gitignore에 등록합니다.
# 의존성
node_modules/
__pycache__/
vendor/
# 환경 변수 (비밀 키!)
.env
.env.local
.env.*.local
# 빌드 결과물
dist/
build/
.next/
.cache/
# OS 파일
.DS_Store
Thumbs.db
# IDE 설정
.vscode/
.idea/
*.swp
# 로그
*.log
npm-debug.log*주의: .env 파일은 절대 커밋하면 안 됩니다. API 키나 비밀번호가 GitHub에 올라가면 봇이 수 분 내에 스캔해서 악용합니다. 실수로 커밋했다면 즉시 키를 폐기하고 재발급하세요. git rm으로 지워도 히스토리에는 남습니다.
이미 추적 중인 파일을 .gitignore에 넣어도 무시되지 않습니다. 이럴 땐 git rm --cached <파일>로 추적 해제하세요.
커밋 메시지 컨벤션 — Conventional Commits
나쁜 커밋 메시지:
수정
fix
ㅋㅋ
asdf좋은 커밋 메시지 (Conventional Commits):
feat: 소셜 로그인 기능 추가
fix: 비밀번호 유효성 검사 오류 수정
docs: README에 설치 가이드 추가
refactor: 인증 미들웨어 구조 개선타입 레퍼런스
| 타입 | 용도 | 예시 |
|---|---|---|
feat |
새 기능 | feat: 검색 필터 추가 |
fix |
버그 수정 | fix: 날짜 포맷 오류 수정 |
docs |
문서 변경 | docs: API 문서 업데이트 |
style |
포맷, 세미콜론 등 (동작 변경 없음) | style: 들여쓰기 정리 |
refactor |
리팩토링 | refactor: 유저 서비스 분리 |
perf |
성능 개선 | perf: 쿼리 N+1 해결 |
test |
테스트 추가/수정 | test: 로그인 단위 테스트 추가 |
chore |
빌드, 설정 변경 | chore: eslint 설정 업데이트 |
ci |
CI 설정 | ci: GitHub Actions 워크플로우 추가 |
본문까지 작성한 좋은 예시
feat(auth): OAuth 2.0 기반 구글 로그인 지원
- 기존 이메일/비밀번호 로그인과 병행 동작
- 최초 로그인 시 프로필 자동 생성
- refresh token은 httpOnly 쿠키에 저장
Closes #142이 규칙을 따르면 git log만 봐도 프로젝트 히스토리가 한눈에 들어오고, 자동 릴리즈 노트 생성(semantic-release 등) 도구와도 연동됩니다.
브랜치 전략 — 팀 규모에 맞게
혼자 개발 (1인)
main ──●──●──●──●──●main 하나로 충분합니다. 실험적인 작업만 feature/로 분리하세요.
소규모 팀 (2~5명) — GitHub Flow
main ──●────────●────────●──
\ / \ /
feature/a ──●──●── ──●──●──main에서feature/기능명브랜치 생성- 작업 후 Pull Request 생성
- 코드 리뷰 후
main에 병합, 브랜치 삭제
단순하고 빠릅니다. 웹 서비스, SaaS에 잘 맞습니다.
릴리즈 주기가 있는 팀 — Git Flow (축소판)
main ──●──────────────●──
\ /
develop ──●──●──●──●──●──
\ /
feature ──●──●main(배포), develop(통합), feature(기능), hotfix(긴급 패치) 정도로 가볍게 운영하는 게 요즘 트렌드입니다. 전통적인 Git Flow 전체를 엄격히 지키는 팀은 줄어드는 추세입니다.
AI 시대의 Git 운영 팁
Claude Code, Cursor 같은 AI 코딩 도구가 코드를 대량 생성하는 지금, Git의 역할은 더 커졌습니다.
- AI가 생성한 코드도 의미 단위로 커밋하세요. "AI가 만든 것"이라고 한 덩어리로 커밋하면 추적이 어렵습니다.
- AI 작업 전 브랜치를 만드세요. 기대와 다른 결과가 나오면 브랜치를 통째로 버리면 됩니다.
- 공저자 표기를 남기세요.
git commit -m "feat: 대시보드 차트 구현
Co-Authored-By: Claude <noreply@anthropic.com>"FAQ
Q1. git pull과 git fetch의 차이는 뭔가요?
git fetch는 원격의 변경을 가져오기만 합니다. 내 로컬 브랜치는 그대로입니다. git pull은 git fetch + git merge를 한 번에 실행합니다. 충돌이 걱정되거나 원격 상황을 먼저 살펴보고 싶다면 fetch 후 git log origin/main..HEAD로 확인하는 습관을 들이세요.
Q2. rebase와 merge는 언제 어떤 걸 쓰나요?
공유 브랜치(main, develop)에 합칠 때는 merge, **내 기능 브랜치를 최신 main으로 따라갈 때는 rebase**가 일반적인 기준입니다. rebase는 히스토리를 일직선으로 만들어 깔끔하지만, 이미 푸시된 커밋을 리베이스하면 팀원의 히스토리를 망칠 수 있으니 공유된 커밋엔 절대 금지입니다. 요약: "내 브랜치 정리는 rebase, 합치는 건 merge."
Q3. 실수로 .env를 커밋했는데 어떻게 지우나요?
먼저 해당 키/비밀번호를 즉시 폐기하고 재발급하세요. 이미 GitHub에 올라간 순간 유출된 것으로 간주해야 합니다. 그 다음 git filter-repo(권장) 또는 GitHub의 Push Protection/Secret Scanning을 활용해 히스토리에서 제거합니다. git rm --cached .env + .gitignore 추가는 미래 커밋에만 영향을 주므로 충분하지 않습니다.
참고 자료
- Git 공식 문서
- Pro Git Book (한국어)
- Conventional Commits 스펙
- GitHub Skills — Git 학습 코스
git switch/git restore공식 문서
여러분은 git checkout을 아직 쓰고 계신가요, 아니면 git switch/restore로 넘어오셨나요? 나만의 Git 워크플로우나 자주 쓰는 alias가 있다면 댓글로 공유해주세요!