본문 바로가기
개발 팁

Git 실전 명령어 모음 — rebase, stash, cherry-pick, fixup 실무 활용

by 루까(Luka) 2026. 3. 17.
반응형

왜 이 글을 쓰나

git add, git commit, git push만 쓰다가 팀 프로젝트를 시작하면 막히는 지점이 있다. PR 올리기 전에 커밋 정리해야 할 때, 다른 브랜치 커밋 하나만 가져와야 할 때, 작업 중에 갑자기 다른 이슈를 봐야 할 때. 이런 상황마다 구글링하는 게 지겨워서 정리한다. "이 상황에서 이 명령" 형식으로 뽑았다.


stash — 작업 중간에 다른 브랜치로 이동해야 할 때

작업 중인데 갑자기 다른 브랜치에서 버그를 봐야 하는 상황. commit하기는 애매하고, 그냥 이동하면 충돌 날 수 있다.

# 현재 작업 임시 저장
git stash

# 저장 목록 확인
git stash list
# stash@{0}: WIP on feature/login: a3f2b1c 로그인 폼 작업 중
# stash@{1}: WIP on main: d4e5f6a 헤더 수정

# 복원 (최근 stash, 목록에서 제거)
git stash pop

# 복원 (목록에 유지)
git stash apply stash@{1}

# 특정 stash 삭제
git stash drop stash@{0}

# 전체 삭제
git stash clear

메시지를 붙여서 저장하면 나중에 찾기 편하다:

git stash push -m "로그인 폼 유효성 검사 작업 중"

git stash pop은 충돌이 나도 stash를 목록에서 지운다. 충돌 상황이 걱정되면 apply를 쓰고 수동으로 drop하는 게 안전하다.


cherry-pick — 다른 브랜치 커밋 하나만 가져와야 할 때

feature 브랜치에서 만든 유틸 함수를 hotfix 브랜치에도 써야 할 때. 브랜치 전체를 머지하기는 부담스럽고, 커밋 하나만 필요한 경우다.

# 가져올 커밋 해시 확인
git log feature/utils --oneline
# a1b2c3d formatDate 유틸 함수 추가
# e4f5a6b 날씨 API 연동

# cherry-pick 실행
git cherry-pick a1b2c3d

# 여러 커밋 한 번에
git cherry-pick a1b2c3d e4f5a6b

# 범위 지정 (두 커밋 사이, 첫 번째 제외)
git cherry-pick a1b2c3d..e4f5a6b

충돌이 나면:

# 충돌 파일 수정 후
git add .
git cherry-pick --continue

# 포기
git cherry-pick --abort

cherry-pick은 커밋을 복사하는 개념이다. 원본 브랜치의 커밋은 그대로 남고, 새로운 커밋이 현재 브랜치에 추가된다. 커밋 해시가 달라지는 게 정상이다.


rebase — PR 전에 커밋 정리할 때

작업하다 보면 커밋이 지저분해진다. "오타 수정", "진짜 수정", "WIP" 같은 커밋들. PR 올리기 전에 정리하는 게 리뷰어에 대한 예의다.

최근 n개 커밋 정리

# 최근 3개 커밋을 interactive rebase로 열기
git rebase -i HEAD~3

에디터가 열리면:

pick a1b2c3d 로그인 폼 구현
pick e4f5a6b 오타 수정
pick c7d8e9f WIP: 유효성 검사

# Commands:
# p, pick = 커밋 유지
# r, reword = 커밋 메시지 수정
# e, edit = 커밋 내용 수정
# s, squash = 이전 커밋에 합치기 (메시지 합침)
# f, fixup = 이전 커밋에 합치기 (메시지 버림)
# d, drop = 커밋 삭제

"오타 수정", "WIP"를 앞 커밋에 합치려면:

pick a1b2c3d 로그인 폼 구현
fixup e4f5a6b 오타 수정
fixup c7d8e9f WIP: 유효성 검사

저장하면 3개가 1개로 합쳐진다.

main 브랜치 최신 상태로 동기화

# main의 최신 커밋 위에 내 작업을 쌓는다
git fetch origin
git rebase origin/main

# 충돌 시
git add .
git rebase --continue

# 포기
git rebase --abort

merge와 달리 rebase는 히스토리가 선형으로 유지된다. PR에서 "Squash and merge" 대신 직접 정리해서 올리는 팀이라면 rebase가 기본이다.

주의: 이미 push한 브랜치에 rebase를 하면 히스토리가 달라져서 git push --force-with-lease가 필요하다. 혼자 쓰는 브랜치에서만 하는 걸 권장한다.


fixup — 이미 만든 커밋에 수정을 붙일 때

커밋을 했는데 빠뜨린 파일이 생각났거나, 소소한 오타를 발견했을 때. interactive rebase 없이 빠르게 처리할 수 있다.

# 수정 사항을 staging
git add src/utils/formatDate.js

# fixup 커밋 생성 (어떤 커밋에 붙일지 명시)
git commit --fixup a1b2c3d

# autosquash로 rebase 실행 (fixup 커밋을 자동으로 합침)
git rebase -i --autosquash HEAD~3

--fixup으로 만든 커밋은 fixup! 원본커밋메시지 형태로 생성된다. --autosquash가 이걸 감지해서 자동으로 fixup으로 마킹한다. 에디터에서 직접 수정할 필요가 없다.

자주 쓴다면 전역 설정으로 항상 autosquash를 켜둬도 된다:

git config --global rebase.autosquash true

reset — 커밋을 되돌릴 때

옵션 작업 디렉터리 staging 커밋
--soft 유지 유지 되돌림
--mixed (기본) 유지 초기화 되돌림
--hard 삭제 초기화 되돌림
# 마지막 커밋 취소, 작업 내용은 살려두기
git reset --soft HEAD~1

# 마지막 커밋 취소, staging도 초기화 (코드는 유지)
git reset HEAD~1

# 마지막 커밋 완전히 삭제 (코드도 사라짐)
git reset --hard HEAD~1

# 특정 파일만 unstage
git reset HEAD src/App.js

--hard는 작업 내용까지 날린다. push 전에만 써야 하고, push한 커밋에 쓰면 팀원 히스토리가 꼬인다.


revert — push한 커밋을 안전하게 되돌릴 때

reset과 달리 revert는 기존 커밋을 지우지 않고, "이 커밋을 되돌린다"는 새 커밋을 만든다. 이미 공유된 브랜치에서 안전하게 쓸 수 있다.

# 특정 커밋을 되돌리는 커밋 생성
git revert a1b2c3d

# 커밋 메시지 편집 없이 바로 생성
git revert a1b2c3d --no-edit

# 여러 커밋 한 번에
git revert HEAD~3..HEAD

main 브랜치에 잘못 머지된 것을 되돌릴 때 쓴다. revert한 결과가 히스토리에 남으니 "언제, 왜 돌렸는지" 추적이 가능하다.


reflog — 실수로 날린 작업을 복구할 때

reset --hard로 날린 커밋, rebase로 사라진 작업. Git은 웬만한 건 내부에 가지고 있다. reflog가 그 기록이다.

# 최근 HEAD 이동 기록 전체 확인
git reflog

# 출력 예시
# a1b2c3d HEAD@{0}: reset: moving to HEAD~1
# e4f5a6b HEAD@{1}: commit: 로그인 폼 구현
# c7d8e9f HEAD@{2}: checkout: moving from main to feature/login

# 복구하려면 해당 시점으로 reset
git reset --hard e4f5a6b

reflog는 로컬에만 존재하고, 일정 시간(기본 90일)이 지나면 GC로 지워진다. 실수했다면 빨리 복구해야 한다.


상황별 명령어 요약

상황 명령어
작업 중 다른 브랜치 이동 git stash / git stash pop
다른 브랜치 커밋 하나만 가져오기 git cherry-pick <hash>
PR 전 커밋 정리 git rebase -i HEAD~n
커밋에 수정 붙이기 git commit --fixup <hash> + git rebase -i --autosquash
로컬 커밋 취소 (코드 유지) git reset --soft HEAD~1
공유 브랜치 커밋 되돌리기 git revert <hash>
날린 커밋 복구 git refloggit reset --hard <hash>
main 최신화 후 내 작업 올리기 git fetch origin + git rebase origin/main

삽질 기록

rebase 후 push가 거부됐다

$ git push origin feature/login
! [rejected] feature/login -> feature/login (non-fast-forward)

rebase를 하면 로컬 커밋 해시가 바뀐다. 리모트와 히스토리가 달라지니 일반 push가 거부된다.

# 혼자 쓰는 브랜치라면
git push --force-with-lease origin feature/login

--force가 아니라 --force-with-lease를 쓴다. 다른 사람이 중간에 push한 게 있으면 force를 막아준다. 조금 더 안전하다.

cherry-pick 후 PR에서 중복 커밋이 보인다

feature 브랜치를 main에 머지할 때, cherry-pick으로 이미 가져온 커밋이 PR에 다시 나타나는 경우가 있다. 커밋 내용은 같아도 해시가 다르기 때문이다. 이 경우 rebase로 커밋을 정리하거나, cherry-pick 대신 머지를 검토하는 게 낫다.

stash pop 후 충돌이 났는데 stash가 사라졌다

git stash pop은 충돌이 발생해도 stash 목록에서 제거한다. 충돌 해결 중에 실수로 다른 작업을 하면 stash 내용을 잃을 수 있다. 불안하면 git stash apply를 쓰고 충돌 해결 후 수동으로 git stash drop한다.


마무리

Git은 기본 명령만 써도 개발은 된다. 하지만 팀 단위로 일하거나 오래된 프로젝트를 건드릴수록 히스토리 관리가 중요해진다. 깔끔한 커밋 히스토리는 리뷰를 빠르게 하고, 버그 추적을 쉽게 만든다.

rebase -istash만 제대로 써도 일하는 방식이 달라진다.


사용 Git 버전: 2.43+
참고: git help <command>로 각 명령의 전체 옵션 확인 가능

반응형