Git 상세 가이드
Git의 모든 핵심 명령어를 명령어별로 깊게 파헤친 완벽 가이드. 옵션·출력 예시·실전 조합까지.
Git의 모든 핵심 명령어를 명령어별로 깊게 파헤친 완벽 가이드. 옵션·출력 예시·실전 조합까지.
목표: 문서 없이도 어떤 Git 상황이든 스스로 진단하고 해결할 수 있는 수준
[!warning] 히스토리 변경 주의
reset --hard,push --force,rebase,commit --amend는 작업을 잃거나 동료의 커밋을 덮어쓸 수 있다. 공유 브랜치에서는 히스토리를 다시 쓰지 말 것. 위험한 작업 전에는git branch backup/$(date +%s)로 백업한다.
🧠 Git의 동작 원리
Git은 스냅샷을 저장한다
다른 VCS가 파일별 변경분(diff)을 저장하는 것과 달리, Git은 매 커밋마다 프로젝트 전체의 스냅샷을 찍는다. 변경되지 않은 파일은 이전 스냅샷을 가리키는 포인터만 남겨 공간을 아낀다.
4개의 영역
graph LR
WD["💻 Working Directory"] -->|"git add"| STAGE["📋 Staging (Index)"]
STAGE -->|"git commit"| REPO["📦 Local Repo (.git)"]
REPO -->|"git push"| REMOTE["🌐 Remote (origin)"]
REMOTE -->|"git fetch"| REPO
REPO -->|"git checkout"| WD
STAGE -->|"git restore --staged"| WD
| 영역 | 의미 | 확인 명령 |
|---|---|---|
| Working Directory | 편집 중인 실제 파일 | git status |
| Staging Area (Index) | 다음 커밋에 담길 변경 | git diff --staged |
| Local Repository | 커밋된 히스토리 | git log |
| Remote | 원격 공유본 | git remote -v |
핵심 용어
| 용어 | 설명 |
|---|---|
| HEAD | 현재 체크아웃된 커밋(보통 현재 브랜치의 최신) 포인터 |
| commit | 스냅샷 + 메타데이터(작성자/시간/부모). SHA-1 해시로 식별 |
| branch | 특정 커밋을 가리키는 움직이는 포인터 |
| tag | 특정 커밋을 가리키는 고정 포인터 (보통 릴리스) |
| origin | 기본 원격 저장소의 관례적 이름 |
| upstream | 로컬 브랜치가 추적하는 원격 브랜치 |
⚙️ 설정 — git config
사용자 정보 (커밋에 기록되므로 필수)
git config --global user.name "Jongmin"
git config --global user.email "you@example.com"
설정 범위(scope)
git config --system ... # 모든 사용자 (/etc/gitconfig)
git config --global ... # 현재 사용자 (~/.gitconfig)
git config --local ... # 현재 저장소 (.git/config) — 기본값
우선순위는 local > global > system. 저장소별로 다른 이메일을 쓰려면 해당 폴더에서 --local로 덮어쓴다.
자주 쓰는 설정
git config --global init.defaultBranch main # 기본 브랜치명
git config --global core.editor "code --wait" # 커밋 에디터를 VS Code로
git config --global pull.rebase true # pull 시 rebase 기본
git config --global core.autocrlf true # Windows 줄바꿈
git config --global core.autocrlf input # mac/Linux 줄바꿈
별칭(alias) — 타이핑 절약
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.lg "log --oneline --graph --all --decorate"
# 이후: git lg
설정 확인
git config --list # 전체
git config --list --show-origin # 각 설정이 어느 파일에서 왔는지
git config user.email # 특정 값만
📦 저장소 시작 — git init / git clone
git init — 새 저장소
git init # 현재 폴더를 저장소로 (.git 생성)
git init my-project # 새 폴더 생성하며 초기화
git init --bare # 작업 디렉토리 없는 중앙 저장소 (서버용)
git clone — 원격 복제
git clone <url> # 복제
git clone <url> my-folder # 폴더명 지정
git clone --depth 1 <url> # 최근 1커밋만 (얕은 복제, CI에 유용)
git clone --branch develop <url> # 특정 브랜치만
git clone --recursive <url> # 서브모듈까지 함께
[!tip] 얕은 복제(shallow clone)
--depth 1은 히스토리를 잘라 다운로드를 크게 줄인다. 나중에 전체가 필요하면git fetch --unshallow로 복원한다.
📝 기본 워크플로우
git status — 현재 상태
git status # 변경된 파일, 스테이징 상태, 브랜치 정보
git status -s # 짧은 형식
git status -sb # 짧게 + 브랜치 정보
-s 출력 읽는 법:
M file1.txt # 우측 M: 작업 디렉토리에서 수정됨 (미스테이징)
M file2.txt # 좌측 M: 스테이징됨
A file3.txt # 새로 추가됨(스테이징)
?? file4.txt # untracked (추적 안 됨)
MM file5.txt # 스테이징 후 또 수정됨
git add — 스테이징
git add file.txt # 특정 파일
git add . # 현재 폴더 이하 전체
git add -A # 저장소 전체(삭제 포함)
git add *.js # 패턴
git add -p # 변경을 조각(hunk) 단위로 골라 담기 ⭐
git add -u # 추적 중인 파일의 변경만
[!tip]
git add -p한 파일 안의 여러 변경 중 일부만 커밋하고 싶을 때. 각 조각마다y(담기)/n(건너뜀)/s(더 쪼개기)/q(종료)를 선택한다. 커밋을 논리 단위로 쪼개는 핵심 습관.
git commit — 커밋
git commit -m "feat: 로그인 추가" # 한 줄 메시지
git commit # 에디터로 본문까지 작성
git commit -am "fix: 버그" # 추적 파일 add + commit (untracked 제외)
git commit --amend # 마지막 커밋 수정 (메시지/내용)
git commit --amend --no-edit # 메시지 그대로, 내용만 추가
git commit --allow-empty -m "trigger" # 빈 커밋 (CI 트리거용)
[!warning]
--amend는 새 커밋을 만든다 마지막 커밋을 고치는 게 아니라 해시가 바뀐 새 커밋으로 교체한다. 이미 push 한 커밋에 amend 하면 강제 push가 필요해지므로 공유 브랜치에서는 피한다.
원격 동기화
git push origin main # 푸시
git push -u origin main # upstream 설정 (이후 git push만으로)
git push # upstream이 설정됐다면
git pull # fetch + merge(or rebase)
git pull --rebase # fetch + rebase
git fetch # 받기만 (병합 안 함, 안전)
git fetch --prune # 원격에서 삭제된 브랜치 정리
🔍 히스토리 조회 & 비교
git log — 커밋 히스토리
git log # 기본
git log --oneline # 한 줄 요약
git log --oneline --graph --all # 그래프로 전체 브랜치 ⭐
git log -3 # 최근 3개
git log -p file.txt # 특정 파일의 변경 패치까지
git log --stat # 파일별 변경량 요약
git log --author="Jongmin" # 작성자 필터
git log --since="2 weeks ago" # 기간 필터
git log --grep="로그인" # 커밋 메시지 검색
git log -S "함수명" # 해당 코드가 추가/삭제된 커밋 (pickaxe) ⭐
git log main..feature # main에 없고 feature에만 있는 커밋
예쁜 포맷 별칭:
git log --pretty=format:"%h %ad %an %s" --date=short
# 9f3a1c2 2026-06-02 Jongmin feat: 로그인 추가
git show — 특정 커밋 상세
git show <commit> # 커밋의 변경 내용 전체
git show HEAD # 마지막 커밋
git show HEAD~2 # 2커밋 전
git show <commit>:file.txt # 그 커밋 시점의 파일 내용
git diff — 차이 비교
git diff # 작업 디렉토리 vs 스테이징
git diff --staged # 스테이징 vs 마지막 커밋 (= --cached)
git diff HEAD # 작업 디렉토리 vs 마지막 커밋 (둘 다)
git diff main feature # 브랜치 간
git diff HEAD~3 HEAD # 3커밋 전과 현재
git diff --stat # 변경량 요약만
git diff --name-only # 바뀐 파일 이름만
git blame — 줄별 작성자 추적
git blame file.txt # 각 줄을 마지막으로 바꾼 커밋/작성자
git blame -L 10,20 file.txt # 10~20줄만
git blame -w file.txt # 공백 변경 무시
git reflog — HEAD 이동 기록 (구원투수) ⭐
git reflog # HEAD가 거쳐온 모든 위치
git reflog show feature # 특정 브랜치의 이동 기록
reset --hard, 잘못된 rebase, 브랜치 삭제로 사라진 것 같은 커밋도 reflog에 남아 있어 복구 가능. (git reset --hard HEAD@{3})
🌿 브랜치 — git branch / switch
조회
git branch # 로컬 브랜치 목록 (현재 *)
git branch -a # 원격 포함
git branch -v # 마지막 커밋 함께
git branch -vv # upstream 정보까지
git branch --merged # 현재 브랜치에 병합된 브랜치
git branch --no-merged # 아직 병합 안 된 브랜치 (삭제 전 점검)
생성 / 전환
git switch -c feature/login # 생성 + 전환 (최신 권장) ⭐
git switch main # 전환
git switch - # 직전 브랜치로 토글
git checkout -b feature/login # 구식: 생성 + 전환
git switch -c hotfix abc123 # 특정 커밋에서 분기
삭제 / 이름변경
git branch -d feature/login # 병합된 브랜치 삭제 (안전)
git branch -D feature/login # 강제 삭제 (병합 안 됐어도)
git branch -m old-name new-name # 이름 변경
git push origin --delete feature/x # 원격 브랜치 삭제
[!tip]
switchvscheckoutcheckout은 브랜치 전환·파일 복원·커밋 체크아웃을 모두 하는 과적 명령이라 헷갈린다. Git 2.23+는 역할을 분리한switch(브랜치) 와restore(파일) 사용을 권장한다.
🔀 병합 & 리베이스
Merge vs Rebase 개념
graph TB
subgraph "Merge — 분기 보존 + 병합 커밋"
A1["A"] --> B1["B"] --> C1["C"]
A1 --> D1["D"] --> E1["E"]
C1 --> M1["Merge commit"]
E1 --> M1
end
subgraph "Rebase — 선형으로 재작성"
A2["A"] --> B2["B"] --> C2["C"] --> D2["D'"] --> E2["E'"]
end
| 항목 | Merge | Rebase |
|---|---|---|
| 히스토리 | 분기 보존 | 선형 |
| 커밋 해시 | 유지 | 재생성 |
| 병합 커밋 | 생김 | 없음 |
| 공유 브랜치 | ✅ 안전 | ❌ 금지 |
| 용도 | main 통합 | 내 로컬 feature 정리 |
git merge
git switch main
git merge feature/login # feature를 main에 병합
git merge --no-ff feature/login # 항상 병합 커밋 생성 (분기 흔적 보존)
git merge --squash feature/x # 변경을 한 커밋으로 합쳐 가져오기
git merge --abort # 충돌 시 병합 취소·원상복구
git rebase
git switch feature/login
git rebase main # 내 커밋들을 main 최신 위로 재배치
git rebase --continue # 충돌 해결 후 계속
git rebase --abort # 취소
git rebase --onto main old new # 특정 구간만 옮기기
[!danger] 리베이스 황금 규칙 이미 push 해서 공유한 커밋은 절대 rebase 하지 않는다. 해시가 바뀌어 동료의 히스토리와 충돌한다. 오직 내 로컬에만 있는 커밋 정리에만 사용.
git rebase -i — 대화형 (커밋 정리)
git rebase -i HEAD~3 # 최근 3커밋을 편집
편집 화면에서 각 커밋에 적용할 동작:
| 명령 | 의미 |
|---|---|
pick | 그대로 사용 |
reword | 메시지만 수정 |
edit | 멈춰서 내용 수정 |
squash | 이전 커밋에 합치고 메시지 합침 |
fixup | 이전 커밋에 합치고 메시지 버림 |
drop | 커밋 삭제 |
충돌 해결 절차
# 병합/리베이스 중 충돌 발생
git status # 충돌(unmerged) 파일 확인
# 파일 열어 마커 편집:
# <<<<<<< HEAD
# 내 변경
# =======
# 상대 변경
# >>>>>>> feature
git add 해결된파일 # 해결 표시
git merge --continue # 또는 git rebase --continue
# 무서우면 언제든:
git merge --abort # 안전하게 원상복구
🌐 원격 — git remote
원격 관리
git remote -v # 등록된 원격 목록
git remote add origin <url> # 원격 추가
git remote add upstream <포크원본url> # 포크 워크플로우
git remote set-url origin <new-url> # URL 변경
git remote remove origin # 제거
git remote show origin # 원격 상세 정보
git push 옵션
git push origin main # 푸시
git push -u origin feature # upstream 설정
git push --tags # 태그 전체 푸시
git push origin --delete feature # 원격 브랜치 삭제
git push --force-with-lease # 안전한 강제 푸시 (남의 커밋 보호) ⭐
git push --force # 강제 푸시 (위험 🔴)
[!tip]
--force-with-lease를 써라 그냥--force는 내가 마지막으로 본 이후 남이 push 한 커밋을 무조건 덮어쓴다.--force-with-lease는 원격이 내 예상과 다르면 거부하므로 사고를 막는다.
git fetch vs git pull
git fetch origin # 원격 변경을 받기만 (작업물 안전)
git pull origin main # fetch + merge
git pull --rebase # fetch + rebase (선형 히스토리)
fetch 후 git log origin/main으로 확인하고 병합하는 습관이 안전하다.
🎒 임시 저장 · 태그 · 체리픽
git stash — 작업 임시 보관
git stash # 변경을 치워두고 깨끗한 상태로
git stash -u # untracked 파일까지 포함
git stash push -m "로그인 작업" # 메시지 붙여 저장
git stash list # 보관 목록 (stash@{0}, {1}...)
git stash show -p stash@{0} # 내용 미리보기
git stash pop # 최근 것 꺼내고 목록에서 삭제
git stash apply stash@{1} # 특정 것 적용(목록에 유지)
git stash drop stash@{0} # 삭제
git stash clear # 전체 삭제
용도: 급히 다른 브랜치로 가야 하는데 커밋하기 애매한 변경이 있을 때.
git tag — 버전 태그
git tag # 목록
git tag v1.0.0 # 가벼운 태그
git tag -a v1.0.0 -m "첫 릴리스" # 주석 태그 (작성자·날짜·메시지, 권장)
git tag -a v1.0.0 <commit> # 특정 커밋에 태그
git show v1.0.0 # 태그 정보
git push origin v1.0.0 # 태그 푸시 (push는 태그를 자동 전송 안 함)
git push origin --tags # 전체 태그
git tag -d v1.0.0 # 로컬 삭제
git push origin --delete v1.0.0 # 원격 삭제
git cherry-pick — 특정 커밋만 가져오기
git cherry-pick <commit> # 다른 브랜치의 커밋 1개를 현재로 복사
git cherry-pick A B C # 여러 개
git cherry-pick A^..B # 범위
git cherry-pick -n <commit> # 적용만 하고 커밋은 보류
git cherry-pick --abort # 충돌 시 취소
용도: hotfix 커밋을 release 브랜치에도 반영할 때 등.
⏪ 되돌리기 — 상황별 정확히
[!danger] 가장 중요한 분기점 이미 push 해서 공유한 커밋 →
revert(새 커밋으로 안전하게). 내 로컬에만 있는 커밋 →reset로 다시 써도 됨.
git restore — 파일 단위 복원 (Git 2.23+)
git restore file.txt # 작업 디렉토리 변경 버리기 (마지막 커밋으로)
git restore --staged file.txt # 스테이징만 취소 (변경은 유지)
git restore --source=HEAD~2 file.txt # 2커밋 전 버전으로
git restore . # 전체 변경 버리기 🟡
git reset — 브랜치 포인터 이동
git reset --soft HEAD~1 # 커밋만 취소, 변경은 스테이징에 유지
git reset HEAD~1 # (mixed,기본) 커밋+스테이징 취소, 변경은 유지
git reset --hard HEAD~1 # 커밋·스테이징·작업 모두 삭제 🔴
git reset HEAD file.txt # 특정 파일 스테이징 취소
세 모드 비교:
| 모드 | HEAD | Staging | Working Dir |
|---|---|---|---|
--soft | 이동 | 유지 | 유지 |
--mixed(기본) | 이동 | 리셋 | 유지 |
--hard | 이동 | 리셋 | 리셋(손실) |
git revert — 되돌리는 새 커밋
git revert <commit> # 해당 커밋을 무효화하는 새 커밋 생성 (안전)
git revert HEAD # 마지막 커밋 되돌리기
git revert -n <commit> # 커밋은 보류하고 변경만
공유 브랜치에서 잘못된 커밋을 없애는 유일하게 안전한 방법. 히스토리를 지우지 않고 “되돌림”을 기록한다.
git clean — untracked 파일 제거
git clean -n # 삭제될 파일 미리보기 (dry-run) ⭐
git clean -f # untracked 파일 삭제
git clean -fd # 디렉토리까지
git clean -fdx # .gitignore 대상까지 전부 🔴
반드시 -n으로 먼저 확인할 것.
graph TB
Q1{"이미 push 했나?"} -->|"예"| REVERT["git revert"]
Q1 -->|"아니오"| Q2{"무엇을 되돌리나?"}
Q2 -->|"파일 편집"| RESTORE["git restore"]
Q2 -->|"커밋만 취소"| SOFT["git reset --soft"]
Q2 -->|"전부 버림"| HARD["git reset --hard 🔴"]
🔬 고급 도구
git bisect — 버그 도입 커밋 이진 탐색
git bisect start
git bisect bad # 현재(버그 있음) 표시
git bisect good v1.0.0 # 정상이던 시점 표시
# Git이 중간 커밋으로 이동 → 테스트 후:
git bisect good # 또는 git bisect bad
# 반복하면 범인 커밋을 자동 특정
git bisect reset # 종료
수백 커밋도 log₂ 번 테스트로 범인을 찾는다.
git worktree — 여러 브랜치 동시 체크아웃
git worktree add ../hotfix-dir hotfix # 다른 폴더에 hotfix 브랜치를
git worktree list # 목록
git worktree remove ../hotfix-dir # 정리
stash 없이 다른 브랜치를 별도 폴더에서 동시에 작업.
git submodule — 저장소 안의 저장소
git submodule add <url> libs/foo # 추가
git submodule update --init --recursive # 클론 후 내용 채우기
git submodule update --remote # 서브모듈 최신화
🚫 .gitignore
기본 작성
# 의존성
node_modules/
__pycache__/
vendor/
# 빌드 산출물
dist/
build/
*.o
*.log
# 환경·비밀 (절대 커밋 금지)
.env
.env.*
*.key
*.pem
# OS / 에디터
.DS_Store
Thumbs.db
.idea/
.vscode/
# 예외: 무시 안 함
!.vscode/settings.json
이미 추적 중인 파일 무시하기
.gitignore는 추적 안 된 파일에만 적용된다. 이미 커밋된 파일은 캐시에서 빼야 한다.
git rm --cached file.txt # 추적만 해제 (파일은 유지)
git rm -r --cached node_modules # 디렉토리
git commit -m "chore: gitignore 적용"
무시 규칙 디버깅
git check-ignore -v file.txt # 어떤 규칙이 이 파일을 무시하는지
git status --ignored # 무시된 파일 함께 보기
🤝 협업 워크플로우
표준 Pull Request 흐름
git switch main && git pull # 1. 최신화
git switch -c feature/login # 2. 브랜치
# ... 작업 ...
git add -p && git commit -m "feat: 로그인 추가" # 3. 논리 단위 커밋
git push -u origin feature/login # 4. 푸시
# 5. GitHub/GitLab에서 PR 생성 → CI 통과 → 리뷰 → 머지
git switch main && git pull # 6. 로컬 정리
git branch -d feature/login
포크(Fork) 워크플로우 (오픈소스)
git clone <내포크url>
git remote add upstream <원본url> # 원본을 upstream으로
git fetch upstream
git rebase upstream/main # 원본 최신과 동기화
커밋 메시지 컨벤션 (Conventional Commits)
<type>(<scope>): <subject> # 50자 이내, 명령형
<body> # 무엇을·왜 (어떻게는 코드가 설명)
<footer> # Closes #123, BREAKING CHANGE:
| 타입 | 의미 | 예시 |
|---|---|---|
feat | 새 기능 | feat(auth): JWT 인증 추가 |
fix | 버그 수정 | fix: 널 포인터 예외 처리 |
docs | 문서 | docs: README 설치법 보강 |
style | 포맷팅(동작 무관) | style: 들여쓰기 정리 |
refactor | 리팩토링 | refactor: 중복 로직 추출 |
test | 테스트 | test: 로그인 케이스 추가 |
chore | 잡무·설정 | chore: 의존성 업그레이드 |
🚑 트러블슈팅
| 상황 | 해결 |
|---|---|
| 방금 커밋 메시지 오타 | git commit --amend (push 전) |
| 잘못된 브랜치에 커밋함 | 올바른 브랜치에서 git cherry-pick <커밋> → 원래에서 git reset --hard HEAD~1 |
reset --hard로 날린 커밋 | git reflog → git reset --hard HEAD@{n} |
| 삭제한 브랜치 복구 | git reflog에서 커밋 찾아 git switch -c 브랜치 <commit> |
| push 거부(non-fast-forward) | git pull --rebase 후 다시 push |
| 강제 push 했는데 남 커밋 날림 | 상대가 git reflog로 자기 커밋 복구 가능 |
| 큰 파일/비밀키 실수로 커밋 | git filter-repo 또는 BFG로 히스토리 정리 후 강제 push |
| 특정 파일만 다른 브랜치 버전으로 | git restore --source=<브랜치> -- file |
| 충돌이 무서움 | git merge --abort / git rebase --abort로 언제든 원상복구 |
| 변경 전부 버리고 원격과 동일하게 | git fetch && git reset --hard origin/main 🔴 |
| 커밋 작성자가 잘못 찍힘 | git commit --amend --author="Name <email>" |
📋 학습 체크리스트
- 4개 영역과 HEAD/branch/tag 개념
-
git add -p로 논리 단위 커밋 -
git log --oneline --graph --all로 히스토리 읽기 -
git log -S로 코드 추적 - Merge vs Rebase + 황금 규칙
-
rebase -i로 커밋 정리(squash/reword/drop) - 충돌 해결 +
--abort탈출 - stash / tag / cherry-pick
- reflog로 잃은 커밋·브랜치 복구
- reset 3모드 vs revert vs restore 구분
-
--force-with-lease로 안전한 강제 push - bisect / worktree
-
.gitignore+ 추적 해제(rm --cached) - PR / 포크 워크플로우 + 커밋 컨벤션
🔗 관련 노트
- Git-요약-정리 — 핵심만 빠르게 보는 요약본
- 01-02-버전관리-Git — 기존 Git 정리
- 01-01-CI-CD-개념 — CI/CD 파이프라인
- 02-02-GitHub-Actions — GitHub Actions 자동화
- 03-01-GitOps-원칙 — Git을 단일 진실 공급원으로
마지막 업데이트: 2026-06-02