안녕하세요. 인포그랩 DevOps Engineer Chris입니다. Git은 SVN과 더불어 오늘날 개발자가 널리 사용하는 버전 관리 시스템(Version Control System, 이하 VCS)입니다.
현재 Git을 매일 사용하지만 git commit
과 git push
만 반복하고 계시나요? 그렇다면 Git의 강력한 기능을 제대로 활용하지 못하는 건지도 모릅니다.
버전 관리를 효율화하고, 개발 생산성을 끌어 올리려면 반드시 알아야 할 Git 명령어가 있습니다. git rebase -i
, git reflog
, git worktree
등이 그 예죠. 오늘은 실무에서 자주 사용하고, 협업과 개발 효율을 극대화하는 필수 Git 명령어 10가지를 소개하겠습니다.
Git?
먼저 리마인드 차원에서 Git의 역사와 장점을 살펴보겠습니다. Git은 리눅스 커널의 VCS로 사용하는 BitKeeper가 유료화되면서 ‘무료 오픈 소스’ 대안이 필요해 개발됐습니다. Git 개발의 목표는 아래와 같습니다.
- 빠른 속도
- 심플한 디자인
- 비선형 개발 (수많은 병렬 브랜치 지원)
- 완전 분산형 (오프라인 개발 지원)
- 리눅스 커널과 같은 대규모 프로젝트 관리
Git의 핵심 특징은 ‘완전 분산형 구조’입니다. 모든 개발자는 각자 컴퓨터에 전체 코드 히스토리를 저장하고, 인터넷 연결 없이도 변경 사항을 추적하며 작업할 수 있죠. 그 결과, 소스를 잃어버릴 위험이 줄고, 개발자 간 협업 시 병목 현상이 최소화됩니다. 이로써 더 효율적으로 개발할 수 있고요.
이제 Git을 효과적으로 활용하도록 돕는 필수 명령어 10개와 활용법을 자세히 알아보겠습니다.
git rebase -i
: 커밋 내역 정리
첫 번째로 소개할 명령어는 git rebase -i
입니다. 저도 평소 자주 사용하는 명령어죠. 로컬 커밋 내역이 있는 상태로 git rebase -i
를 사용하면, 아래와 같이 커밋 내역이 나오고요. 다양한 명령어로 커밋 내역을 정돈할 수 있습니다.

git rebase -i
를 입력해 커밋 내역이 표시된 모습
이 상태로 각 커밋에 커밋 메시지 수정, 커밋 내용 삭제, 커밋 합치기도 가능한데요. 특히 ‘커밋 합치기’ 기능인 squash
는 실무에서 매우 유용하죠. git rebase -i
에서 squash
옵션 활용법을 예제와 함께 알아보겠습니다.
저는 위에 나온 커밋 로그 중 16e7f02
.. d391561
까지 커밋을 모두 합치고, 커밋 메시지를 fix: 암복호화 모듈 프록시 로직 오류 수정
으로 변경하려고 했는데요. 먼저 vi 편집기에서 아래 형태로 편집했습니다.

git rebase -i
상태에서 편집한 내용
이 상태에서 :wq
를 실행했습니다. pick
커맨드부터 squash
커맨드까지 모든 커밋 메시지가 병합돼 기본값으로 나왔습니다. 커밋 메시지도 수정할 수 있죠.

squash
결과
여기서 불필요한 커밋 메시지를 모두 삭제하고, 커밋 메시지를 fix: 암복호화 모듈 프록시 로직 오류 수정
으로 수정했습니다.

:wq
로 빠져나와 아래와 같이 병합된 커밋 로그를 확인했습니다. 이제 커밋 정리가 완료됐습니다.

git rebase
로 병합된 커밋 로그
혹자는 ‘git rebase
와 git merge
도 있는데 왜 굳이 git rebase -i
를 써야 하나?’라고 생각할 수도 있죠. git rebase
로 선형적인 히스토리를 만들면 프로젝트의 히스토리를 파악하는 데 도움이 됩니다. 그러나 매번 git rebase
를 활용해 프로젝트를 관리하면 개별 커밋 단위로 충돌을 해결해야 해 피로합니다.
Jira, Wiki Confluence 등을 개발한 Atlassian은 ‘git rebase
를 개인 브랜치(개인 업무 공간) 정리에 사용하고, git merge
를 공개 브랜치(협업 공간)에 사용하라’고 권장합니다. 그러나 git rebase -i
를 활용하면, 원격 리포지터리에 push 할 최종 커밋 내역을 원하는 대로 다듬을 수 있어 더 편리합니다.
git rebase
와 git merge
차이
특징 | git rebase | git merge |
---|---|---|
히스토리 형태 | 선형적인 히스토리 생성 | 브랜치의 병합 지점이 명시적으로 보임 |
병합 커밋 | 생성되지 않음 | 병합 시점에 새로운 병합 커밋 생성 |
git reflog
: HEAD 이동 추적
git rebase
를 실행하면, Git이 가리키는 HEAD 포인터가 트리에서 이동해 히스토리상 보이지 않습니다. 이러한 커밋은 ‘고아 커밋(Orphan Commit)’ 상태가 되고요. 30일(기본값) 커밋 만료 기간 이후, Git GC(Garbage Collector)가 이를 정리합니다.
git reflog
를 사용하면, HEAD 포인터의 이동을 자세히 추적할 수 있습니다. 즉, git rebase
를 실행하기 전과 후 모든 HEAD 포인터 이동 이력을 확인할 수 있죠.

git reflog
입력 시 로그
HEAD 포인터가 앞뒤로 트리를 이동한 커밋 히스토리더라도, 커밋 만료 전에 git reflog
를 실행해 이전 커밋을 쉽게 찾을 수 있습니다. 이전 커밋으로 돌아가려면 git reset ${Commit SHA-1}
을 실행합니다. 그러면 HEAD 포인터를 이동할 수 있습니다.

git reflog
로 이전 커밋을 찾은 뒤, git reset
으로 복원한 뒤 git rebase -i
화면
git worktree
: 브랜치 전환 없이 동시 작업
개발할 때 핫픽스(Hotfix) 사항이 발생하면, 기존 작업을 제쳐 두고 우선순위에 따라 다른 일을 병행하기도 하죠. 이때 git stash
를 실행해 작업 중인 스테이징 영역의 내용을 보류하고, 브랜치를 이동해 동시 작업할 때가 많은데요.
git worktree
를 사용하면, 전용 워킹 디렉터리를 하나 더 만들어 브랜치를 생성하고요. 워킹 디렉터리에서 다른 브랜치를 참조하며, 브랜치 전환 없이도 작업을 효율적으로 병행할 수 있습니다. git worktree
사용법을 예제로 살펴보겠습니다.
아래 명령어를 실행하면, Git 워킹 디렉터리가 proxy-dev-work라는 이름으로 생성됩니다.
# git worktree add -b ${생성 브랜치} ${워킹디렉터리 지정폴더} ${대상 브랜치}
git worktree add -b hotfix/proxy ../proxy-dev-work main

이때 git branch -a
로 브랜치 목록을 확인할 수 있습니다. 자기 워킹 디렉터리 외에 참조하는 브랜치는 “+”로, 자기 워킹 디렉터리에서 참조하는 브랜치는 “*”로 표시됩니다.

git branch -a
로 브랜치 목록을 조회한 결과
git worktree list
를 실행하면, ‘무슨 디렉터리가 어떤 브랜치 상태로 현재 의존 중인지’ 확인할 수 있죠.

git worktree list
로 디렉터리 상태를 조회한 화면
이렇게 같은 원격 리포지터리를 두고, 여러 브랜치를 동시에 참조하는 구조를 만들 수 있고요. 그 결과, 브랜치 전환 없이도 동시 작업을 원활하게 수행할 수 있습니다.
작업이 끝나면, git worktree remove
로 사용하지 않는 worktree를 제거하면 됩니다. git worktree lock
을 사용하면 해당 worktree가 Git GC 정리 대상에서 제외되며, git worktree prune
*로 삭제되지 않도록 보호할 수 있습니다.
*git worktree prune
: 사용하지 않는 worktree 제 거
git bisect
: 특정 커밋 자동 찾기
git bisect
는 이진 탐색(Binary Search)으로 특정 커밋을 자동으로 찾습니다. 특히 버그가 발생한 커밋을 신속하게 찾는 데 도움이 되죠.
일반적으로 git bisect
는 bad
, good
을 수동으로 표시해 탐색마다 범위를 지정하는 방식으로 사용하는데요. 저는 아래 테스트 스크립트를 활용해 특정 커밋을 자동으로 더 빠르게 찾는 방법을 소개하겠습니다.
아래는 나쁜 커밋을 자동으로 판단하는 테스트 스크립트입니다. 현재 테스트 스크립트 형태는 특정 커밋 번호를 지정하는 방식인데요. 특정 테스트 케이스 통과/실패로 변경됐을 때 오류가 있는 최초 커밋을 빨리 발견하는 데 유용합니다.
#!/bin/bash
# 찾고자 하는 나쁜 커밋의 SHA-1 해시
BAD_COMMIT="ca50f794fcf6eb7444585a593b000d26ea1046e2" # 이 부분을 실제 찾고자 하는 커밋 해시로 변경하세요
# 현재 커밋의 SHA-1 해시 가져오기
CURRENT_COMMIT=$(git rev-parse HEAD)
# 현재 커밋이 찾고자 하는 나쁜 커밋인지 확인
if [ "$CURRENT_COMMIT" = "$BAD_COMMIT" ]; then
echo "나쁜 커밋을 찾았습니다: $BAD_COMMIT"
exit 1 # 나쁜 커밋이면 1 반환 (git bisect bad)
else
echo "이 커밋은 나쁜 커밋이 아닙니다: $CURRENT_COMMIT"
exit 0 # 나쁜 커밋이 아니면 0 반환 (git bisect good)
fi
테스트를 위해 아래 명령어로 이진 탐색 범위를 지정해 나쁜 커밋을 자동으로 찾습니다.
git bisect start
git bisect bad ca50f794fcf6eb7444585a593b000d26ea1046e2 # 나쁜 커밋 example 를 잘못된 커밋으로 지정
git bisect good $(git rev-list --max-parents=0 HEAD) # 최초 커밋을 올바른 커밋으로 지정
git bisect run ./test-script.sh # 상대경로이면 상대경로를 명확히 넣어주어야 합니다
git bisect reset # 찾은 후 HEAD 포인터 변경
git bisect
가 아래와 같이 나쁜 커밋을 1개 찾아냈습니다.

git bisect
로 나쁜 커밋을 찾은 결과
git format-patch
& git am
: 패치 파일 생성, 적용
git format-patch
를 사용하면, 패치 파일이 생성돼 이메일 기반 코드 리뷰에 활용할 수 있습니다.
먼저 git format-patch HEAD~3 -o ./patches
를 실행하면, 각 커밋 내용이 패치 파일로 ./patches
디렉터리 아래에 생성됩니다.

git format-patch
로 패 치 파일을 생성한 모습
사용자는 해당 패치 커밋을 압축하거나 하나의 파일로 만들어 코드 리뷰어에게 이메일로 전송할 수 있습니다.
코드 리뷰어는 이메일에서 해당 패치 파일을 다운로드 받고요. 그다음, 자기 브랜치에서 이 파일을 git am *.patch
나 단일 파일 패치 git am 0001-Update-file-aip_encrypt.go.patch
로 적용하고, 코드 리뷰를 진행하면 됩니다.
git bundle
: 리포지터리 백업
git am
이 커밋 단위로 패치를 적용한다면, git bundle
은 리포지터리 전체를 하나의 파일로 저장합니다. 이로써 네트워크가 없는 환경에서도 저장소를 공유하거나, 백업과 복원 작업을 수행할 수 있죠.
git bundle create ../master.bundle HEAD
를 실행하면, 현재 HEAD 포인터가 가리키는 코드 히스토리만 번들 파일로 만들 수 있습니다.

git bundle
로 번들 파일을 생성한 모습
이때 만든 파일은 리포지터리이므로 git clone
, git fetch
를 사용해 읽을 수 있습니다. git clone
을 실행하면, 아래와 같이 번들 파일에서 리포지터리를 복원할 수 있습니다. git fetch