Git 완벽 정리

Git의 내부 동작 원리부터 기본/고급 명령어, 브랜치 전략, 협업, 트러블슈팅까지 한 문서로 정리한 실전 레퍼런스.


Git의 내부 동작 원리부터 기본/고급 명령어, 브랜치 전략, 협업, 트러블슈팅까지 한 문서로 정리한 실전 레퍼런스.

목표: 어떤 상황에서도 “지금 무슨 일이 일어났고, 어떻게 되돌리는지” 스스로 판단할 수 있는 수준.

[!warning] 히스토리 변경 주의 reset --hard, push --force, rebase, commit --amend는 작업을 잃거나 동료의 작업을 덮어쓸 수 있다. 공유 브랜치에서는 절대 강제로 히스토리를 바꾸지 말 것. 꼭 필요하면 먼저 백업 브랜치(git branch backup/now)를 만든다.


🧠 Git의 멘탈 모델

Git은 “스냅샷”을 저장한다

대부분의 VCS가 파일의 변경분(diff) 을 저장하는 반면, Git은 매 커밋마다 프로젝트 전체의 스냅샷을 저장한다. 바뀌지 않은 파일은 이전 스냅샷에 대한 참조(포인터)만 남긴다.

세 가지 영역 + 저장소

graph LR
    WD["💻 Working Directory<br/>(작업 디렉토리)"] -->|"git add"| STAGE["📋 Staging Area<br/>(Index)"]
    STAGE -->|"git commit"| REPO["📦 Local Repository<br/>(.git)"]
    REPO -->|"git push"| REMOTE["🌐 Remote<br/>(origin)"]
    REMOTE -->|"git fetch"| REPO
    REPO -->|"git checkout / restore"| WD
    STAGE -->|"git restore --staged"| WD
영역설명확인 명령
Working Directory실제로 편집 중인 파일git status
Staging Area (Index)다음 커밋에 포함될 변경git diff --staged
Local Repository커밋된 히스토리 (.git)git log
Remote원격 공유 저장소git remote -v

파일의 4가지 상태

stateDiagram-v2
    [*] --> Untracked: 새 파일
    Untracked --> Staged: git add
    Staged --> Unmodified: git commit
    Unmodified --> Modified: 파일 편집
    Modified --> Staged: git add
    Staged --> Modified: 다시 편집
    Unmodified --> Untracked: git rm

📝 기본 명령어

초기 설정

# 사용자 정보 (커밋에 기록됨)
git config --global user.name "Your Name"
git config --global user.email "you@example.com"

# 기본 브랜치 이름을 main으로
git config --global init.defaultBranch main

# 줄바꿈 자동 변환 (Windows: true, mac/Linux: input)
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.lg "log --oneline --graph --all"

# 설정 확인 / 위치 확인
git config --list --show-origin

저장소 시작

git init                              # 현재 폴더를 저장소로
git clone <url>                       # 원격 복제
git clone <url> my-folder             # 폴더명 지정
git clone --depth 1 <url>             # 최신 1개 커밋만 (얕은 복제)

일상 워크플로우

git status                            # 현재 상태
git status -s                         # 짧게 보기

git add file.txt                      # 특정 파일
git add .                             # 전체
git add -p                            # 변경을 조각(hunk)별로 선택 ⭐

git commit -m "feat: 로그인 추가"
git commit                            # 에디터로 본문까지 작성
git commit -am "fix: 버그 수정"        # 추적 중인 파일 add+commit

git push origin main
git push -u origin main               # upstream 설정 (이후 git push만으로 OK)

git pull                              # fetch + merge
git pull --rebase                     # fetch + rebase (히스토리 깔끔)
git fetch                             # 받아오기만 (병합 X)

🔍 히스토리 보기 & 비교

# 로그
git log --oneline --graph --all       # 그래프로 한눈에 ⭐
git log -p file.txt                   # 특정 파일의 변경 내역
git log --author="Jongmin"            # 작성자별
git log --since="2 weeks ago"         # 기간별
git log -S "함수명"                    # 특정 코드가 추가/삭제된 커밋 찾기 (pickaxe)

# 차이 비교
git diff                              # 작업 디렉토리 vs 스테이징
git diff --staged                     # 스테이징 vs 마지막 커밋
git diff main..feature                # 브랜치 간 비교
git diff HEAD~3                       # 3커밋 전과 비교

# 한 줄의 작성자 추적
git blame file.txt
git blame -L 10,20 file.txt           # 10~20줄만

# 특정 커밋 상세
git show <commit>

🌿 브랜치 & 병합

브랜치 조작

git branch                            # 목록
git branch -a                         # 원격 포함
git branch -vv                        # upstream + 마지막 커밋

git switch -c feature/login           # 생성 + 전환 (최신 권장) ⭐
git checkout -b feature/login         # 동일 (구식 방식)

git switch main                       # 전환
git branch -d feature/login           # 병합된 브랜치 삭제
git branch -D feature/login           # 강제 삭제
git branch -m old new                 # 이름 변경
git push origin --delete feature/x    # 원격 브랜치 삭제

Merge vs Rebase

graph TB
    subgraph "Merge (병합 커밋 생성)"
        M1["A"] --> M2["B"] --> M3["C"]
        M1 --> M4["D"] --> M5["E"]
        M3 --> M6["Merge"]
        M5 --> M6
    end
    subgraph "Rebase (선형 히스토리)"
        R1["A"] --> R2["B"] --> R3["C"] --> R4["D'"] --> R5["E'"]
    end
구분MergeRebase
히스토리분기 그대로 보존선형으로 재작성
커밋 해시유지변경됨
충돌 해결한 번커밋마다 가능
공유 브랜치✅ 안전❌ 위험 (절대 금지)
추천 상황협업 main 통합내 로컬 feature 정리
# Merge
git switch main
git merge feature/login
git merge --no-ff feature/login       # 항상 병합 커밋 생성

# Rebase
git switch feature/login
git rebase main                       # main 위로 내 커밋 재배치

# 대화형 리베이스 (커밋 정리: squash/reword/drop)
git rebase -i HEAD~3

[!tip] 황금 규칙 이미 push 해서 남과 공유한 커밋은 rebase 하지 않는다. 내 로컬에만 있는 커밋을 정리할 때만 rebase를 사용한다.

충돌(Conflict) 해결

# 충돌 발생 시
git status                            # 충돌 파일 확인
# <<<<<<< / ======= / >>>>>>> 마커를 직접 편집
git add 해결된파일
git merge --continue                  # 또는 git rebase --continue

git merge --abort                     # 병합 취소하고 원상복구
git rebase --abort

🎒 자주 쓰는 실전 명령어

Stash — 작업 임시 보관

급하게 브랜치를 바꿔야 하는데 커밋하긴 이른 변경이 있을 때.

git stash                             # 변경을 치워두기
git stash -u                          # untracked 파일까지 포함
git stash push -m "로그인 작업 중"     # 메시지 붙여 저장
git stash list                        # 목록
git stash pop                         # 최근 것 꺼내고 삭제
git stash apply stash@{1}             # 특정 것 적용 (보관 유지)
git stash drop stash@{0}              # 삭제

Tag — 버전 표시

git tag v1.0.0                        # 가벼운 태그
git tag -a v1.0.0 -m "첫 릴리스"       # 주석 태그 (권장)
git tag                               # 목록
git push origin v1.0.0                # 태그 푸시
git push origin --tags                # 전체 태그 푸시

Cherry-pick — 특정 커밋만 가져오기

git cherry-pick <commit>              # 다른 브랜치의 커밋 1개만 적용
git cherry-pick A^..B                 # 범위 적용

Reflog — 잃어버린 커밋 복구 ⭐

reset --hard나 잘못된 rebase로 커밋이 사라진 것 같을 때, Git은 거의 아무것도 진짜로 지우지 않는다.

git reflog                            # HEAD가 거쳐온 모든 이동 기록
git reset --hard HEAD@{2}             # 2단계 전 상태로 복구

⏪ 되돌리기 총정리

상황별로 명령이 다르므로 무엇을 되돌릴지 먼저 판단한다.

상황명령위험도
스테이징만 취소git restore --staged file🟢 안전
파일 편집 내용 버리기git restore file🟡 변경 손실
마지막 커밋 메시지 수정git commit --amend🟡 해시 변경
공개된 커밋 되돌리기git revert <commit>🟢 안전 (새 커밋)
커밋만 취소, 변경 유지git reset --soft HEAD~1🟢 안전
커밋+스테이징 취소git reset HEAD~1 (mixed)🟡
모두 버리기git reset --hard HEAD~1🔴 작업 손실
graph TB
    Q1{"이미 push 했나?"} -->|"예"| REVERT["git revert<br/>(되돌리는 새 커밋)"]
    Q1 -->|"아니오"| Q2{"변경을 유지?"}
    Q2 -->|"커밋만 취소"| SOFT["git reset --soft"]
    Q2 -->|"전부 버림"| HARD["git reset --hard"]

[!danger] revert vs reset 공유 브랜치는 무조건 revert. reset은 히스토리를 다시 쓰므로 남이 받은 커밋과 어긋난다.


🌳 브랜치 전략

GitHub Flow (단순·추천)

graph LR
    MAIN["main (항상 배포 가능)"] -->|"브랜치"| FEAT["feature/xyz"]
    FEAT -->|"PR"| PR["Pull Request + CI"]
    PR -->|"리뷰·승인"| MAIN
    MAIN -->|"자동 배포"| PROD["Production"]
  • main은 항상 배포 가능 상태 유지
  • 모든 작업은 feature 브랜치 → PR → 리뷰 → 머지
  • 소규모 팀, 지속적 배포에 적합

Git Flow (릴리스 주기가 명확할 때)

graph TB
    MAIN["main"] --> HOT["hotfix/*"]
    MAIN --> REL["release/*"]
    REL --> DEV["develop"]
    DEV --> FEAT["feature/*"]
    FEAT --> DEV
    DEV --> REL
    REL --> MAIN
    HOT --> MAIN
    HOT --> DEV
  • main(프로덕션) / develop(통합) / feature / release / hotfix
  • 정해진 릴리스 주기·버전이 있는 제품에 적합하지만 복잡함

Trunk-Based (대규모·CI 성숙 팀)

  • 모두가 main(trunk)에 짧게 사는 브랜치로 자주 머지
  • Feature Flag로 미완성 기능 숨김 → CI/CD와 궁합 최고

🤝 협업 워크플로우

표준 PR 흐름

git switch -c feature/login           # 1. 브랜치
git add . && git commit -m "feat: 로그인 추가"  # 2. 작업
git push -u origin feature/login      # 3. 푸시
# 4. GitHub/GitLab에서 PR 생성 → CI 통과 → 리뷰
# 5. 머지 후 로컬 정리
git switch main && git pull
git branch -d feature/login

커밋 메시지 컨벤션 (Conventional Commits)

<type>(<scope>): <subject>

<body>

<footer>
타입의미
feat새 기능
fix버그 수정
docs문서
style포맷팅(동작 변화 없음)
refactor리팩토링
test테스트
chore빌드·설정 등 잡무
git commit -m "feat(auth): JWT 인증 추가

- 토큰 생성·검증 미들웨어 구현
- 로그인 엔드포인트 수정

Closes #123"

.gitignore

# 의존성
node_modules/
__pycache__/

# 빌드 산출물
dist/
build/
*.log

# 환경·비밀
.env
.env.local
*.key

# OS·에디터
.DS_Store
.idea/
.vscode/

[!tip] 이미 추적된 파일을 무시하려면 .gitignore추적 안 된 파일에만 적용된다. 이미 커밋된 파일은: git rm --cached file 후 커밋해야 무시가 적용된다.


🚑 트러블슈팅 (자주 겪는 상황)

상황해결
방금 커밋 메시지 오타git commit --amend
잘못된 브랜치에 커밋함git switch 올바른브랜치git cherry-pick <커밋> → 원래 브랜치에서 git reset --hard HEAD~1
reset --hard로 날린 커밋 복구git refloggit reset --hard HEAD@{n}
push 거부됨 (non-fast-forward)git pull --rebase 후 다시 push
큰 파일 실수로 커밋history 정리는 git filter-repo 또는 BFG 사용
충돌 무서워서 못 합치겠음git merge --abort로 안전하게 취소 가능
특정 파일만 다른 브랜치 버전으로git checkout <브랜치> -- file
변경 다 무시하고 원격과 동일하게git fetch && git reset --hard origin/main 🔴

📋 학습 체크리스트

  • 세 영역(Working/Staging/Repo)과 파일 상태 흐름 이해
  • git add -p로 부분 스테이징
  • git log --oneline --graph --all로 히스토리 읽기
  • Merge와 Rebase의 차이·황금 규칙
  • 충돌 해결 + --abort로 안전 탈출
  • stash / tag / cherry-pick 활용
  • reflog로 잃은 커밋 복구
  • reset(soft/mixed/hard) vs revert 구분
  • 브랜치 전략 1개 이상 설명 가능
  • PR 흐름 + 커밋 컨벤션 + .gitignore

🔗 관련 노트

  • 01-02-버전관리-Git — Git 기본(기존 정리 문서)
  • 01-01-CI-CD-개념 — CI/CD 파이프라인
  • 02-02-GitHub-Actions — GitHub Actions 자동화
  • 03-01-GitOps-원칙 — Git을 단일 진실 공급원으로

마지막 업데이트: 2026-06-02