Git 고급 활용법 — rebase, stash, bisect, worktree 실전 가이드
add/commit/push만 쓰고 있다면. rebase, interactive staging, bisect, worktree 등 Git 고급 기능 실전 가이드.
Git을 쓰면서 add, commit, push, pull 정도만 쓰고 있다면 Git의 10% 정도를 쓰고 있는 거다. 나머지 90%에는 작업 효율을 크게 올려주는 기능들이 숨어있다.
git rebase — 깔끔한 히스토리
merge와 rebase는 둘 다 브랜치를 합치는 방법인데, 결과가 다르다.
merge는 두 브랜치의 갈래가 그대로 남는다. merge commit이 생기고, 히스토리가 갈라졌다가 합쳐지는 모양이 된다.
rebase는 현재 브랜치의 커밋들을 대상 브랜치 끝에 다시 쌓는다. 마치 처음부터 대상 브랜치에서 작업한 것처럼 히스토리가 일직선이 된다.
# feature 브랜치를 main 위에 rebase
git checkout feature
git rebase main
언제 rebase를 쓸까
개인 작업 브랜치에서 main의 최신 변경사항을 가져올 때. git pull --rebase로 리모트 변경사항을 가져오면서 rebase를 동시에 할 수 있다.
# pull 할 때 merge 대신 rebase
git pull --rebase origin main
절대 하지 말아야 할 것
이미 push한 커밋을 rebase하지 마라. 다른 사람이 같은 커밋을 기반으로 작업하고 있을 수 있다. rebase는 커밋 해시를 바꾸기 때문에, 다른 사람의 작업과 충돌이 생긴다. "공유된 브랜치에서는 merge, 개인 브랜치에서는 rebase"가 일반적인 규칙이다.
git rebase -i — 커밋 정리
Interactive rebase는 커밋을 합치고, 순서를 바꾸고, 메시지를 수정하는 도구다.
# 최근 3개 커밋을 정리
git rebase -i HEAD~3
에디터에 커밋 목록이 뜬다:
pick abc1234 기능 A 추가
pick def5678 오타 수정
pick ghi9012 기능 A 마무리
각 줄 앞의 명령어를 바꿀 수 있다:
pick— 커밋 유지squash(또는s) — 이전 커밋에 합침fixup(또는f) — 합치면서 커밋 메시지 버림reword(또는r) — 커밋 메시지 수정drop(또는d) — 커밋 삭제edit(또는e) — 커밋에서 멈추고 수정 허용
pick abc1234 기능 A 추가
fixup def5678 오타 수정
fixup ghi9012 기능 A 마무리
이러면 세 커밋이 하나로 합쳐지고, 메시지는 첫 번째 것만 남는다. PR 올리기 전에 WIP 커밋들을 정리할 때 필수적이다.
git stash — 작업 임시 저장
코드를 수정하다가 급하게 다른 브랜치로 전환해야 할 때. 커밋하기엔 애매한 작업 중 상태를 임시로 저장하는 게 stash다.
# 현재 변경사항 저장
git stash
# 메시지 붙여서 저장
git stash push -m "로그인 폼 작업 중"
# 저장 목록 확인
git stash list
# 가장 최근 stash 복원
git stash pop
# 특정 stash 복원
git stash pop stash@{2}
# 복원하되 stash에서 삭제하지 않음
git stash apply
pop은 복원하면서 stash에서 삭제하고, apply는 복원만 한다. 여러 브랜치에 같은 변경을 적용해야 할 때 apply가 유용하다.
부분 stash
# 파일 단위로 선택해서 stash
git stash push -m "설명" -- path/to/file.ts
# untracked 파일도 포함
git stash -u
git bisect — 이진 탐색으로 버그 커밋 찾기
"2주 전까지는 잘 됐는데 언제부터 안 되는지 모르겠다." 이런 상황에서 빛을 발한다. 커밋 히스토리를 이진 탐색으로 반씩 쪼개면서 버그가 도입된 커밋을 찾는다.
# bisect 시작
git bisect start
# 현재(버그 있음)를 bad로 표시
git bisect bad
# 정상이던 커밋을 good으로 표시
git bisect good abc1234
그러면 Git이 중간 지점의 커밋을 checkout해준다. 해당 커밋에서 버그가 있는지 확인하고:
# 버그 있으면
git bisect bad
# 버그 없으면
git bisect good
이걸 반복하면 Git이 범위를 절반씩 좁혀간다. 1000개의 커밋 중에서도 10번 이내에 원인 커밋을 찾는다.
# 다 끝나면
git bisect reset
자동화도 가능하다
# 테스트 스크립트로 자동 판별
git bisect run npm test
테스트가 통과하면 good, 실패하면 bad로 자동 판별해서 사람 개입 없이 원인 커밋을 찾아준다.
git worktree — 여러 브랜치 동시 작업
feature 브랜치에서 작업 중인데 hotfix를 해야 한다. stash 하고 브랜치 바꾸고, hotfix 끝나면 다시 돌아오고... 번거롭다.
worktree는 같은 레포의 다른 브랜치를 별도 디렉토리에 체크아웃하는 기능이다.
# main 브랜치를 ../project-main 디렉토리에 체크아웃
git worktree add ../project-main main
# 새 브랜치를 만들면서 체크아웃
git worktree add ../project-hotfix -b hotfix/urgent
# worktree 목록 확인
git worktree list
# 다 쓴 worktree 제거
git worktree remove ../project-hotfix
.git 데이터를 공유하니까 디스크 공간도 적게 쓰고, 각 디렉토리에서 독립적으로 빌드하고 테스트할 수 있다.
git log 잘 쓰기
기본 git log는 정보가 너무 많다. 원하는 것만 보는 옵션을 알아두면 편하다.
# 한 줄씩 간결하게
git log --oneline
# 그래프로 브랜치 흐름 시각화
git log --oneline --graph --all
# 특정 파일의 변경 이력
git log --oneline -- src/auth.ts
# 특정 문자열이 추가/삭제된 커밋 찾기
git log -S "deprecated" --oneline
# 특정 기간
git log --after="2026-01-01" --before="2026-02-01"
# 특정 작성자
git log --author="mason"
-S 옵션(pickaxe)은 특정 문자열이 변경 내용에 포함된 커밋을 찾는다. "이 함수를 언제 추가했지?" 같은 질문에 유용하다.
git reflog — 실수 복구
브랜치를 잘못 삭제했거나, reset으로 커밋을 날렸거나. 이런 실수를 복구할 수 있는 마지막 안전망이 reflog다.
# HEAD가 가리켰던 모든 이력
git reflog
# 특정 시점으로 복구
git reset --hard HEAD@{5}
reflog는 로컬에만 존재하고, 기본적으로 90일간 보관된다. "Git에서 데이터를 완전히 잃어버리는 건 거의 불가능하다"는 말이 나오는 이유가 reflog 때문이다.
실전 팁 몇 가지
커밋 메시지에 타입 접두사를 붙이자. feat:, fix:, refactor:, docs: 같은 Conventional Commits 규칙을 따르면 히스토리가 읽기 쉬워진다. 나중에 자동 변경 로그 생성도 가능해진다.
.gitignore 글로벌 설정도 해두면 좋다. .DS_Store, Thumbs.db, IDE 설정 파일 같은 건 프로젝트 .gitignore에 넣을 필요 없이 글로벌로 무시하면 된다.
git config --global core.excludesfile ~/.gitignore_global
alias를 설정하자. 자주 쓰는 긴 명령어를 줄여두면 생산성이 올라간다.
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.lg "log --oneline --graph --all"
git config --global alias.st "status --short"
Git은 결국 도구다. 도구를 잘 다루면 코드에 더 집중할 수 있다. 위에 소개한 기능들을 전부 외울 필요는 없고, 필요한 상황이 왔을 때 "아, 이런 기능이 있었지" 하고 떠올리면 된다.