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] switch vs checkout checkout은 브랜치 전환·파일 복원·커밋 체크아웃을 모두 하는 과적 명령이라 헷갈린다. 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
항목MergeRebase
히스토리분기 보존선형
커밋 해시유지재생성
병합 커밋생김없음
공유 브랜치✅ 안전❌ 금지
용도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 (선형 히스토리)

fetchgit 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    # 특정 파일 스테이징 취소

세 모드 비교:

모드HEADStagingWorking 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 refloggit 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