이 글이 다루는 내용:
- Bisect — 버그 도입 커밋을 이진 탐색으로 찾기
- Submodule — 외부 저장소를 프로젝트에 포함
- Worktree — 여러 브랜치를 동시에 작업
- Hooks — 커밋·푸시 시 자동 스크립트 실행
- Alias — 긴 명령어를 짧게 단축
- Blame — 라인별 작성자 추적
- Clean — 미추적 파일 삭제
1 Git Bisect: 버그 커밋 찾기
git bisect는 이진 탐색을 사용하여 버그가 도입된 커밋을 빠르게 찾아낸다. 100개의 커밋 중에서도 7번의 확인만으로 원인 커밋을 찾을 수 있다.
1.1 기본 사용법
Bisecting: 30 revisions left to test after this (roughly 5 steps)
[m2a3b4c] feat: Add payment processing
Git이 bad/good 범위의 중간 커밋으로 자동 체크아웃한다. 30 revisions left, roughly 5 steps 로 남은 탐색 횟수를 알려준다.
Bisecting: 14 revisions left to test after this (roughly 4 steps)
[x7y8z9a] refactor: Optimize database queries
Bisecting: 7 revisions left to test after this (roughly 3 steps)
[n1o2p3q] feat: Update user authentication
abc1234 is the first bad commit
commit abc1234
Author: 홍길동 <hong@example.com>
Date: Mon Jan 15 14:00:00 2024 +0900
feat: Add new payment logic
src/payment.js | 23 +++++++++++++++++++++++
is the first bad commit 메시지가 나오면 버그가 처음 도입된 커밋을 찾은 것이다.
Previous HEAD position was abc1234 feat: Add new payment logic
Switched to branch 'main'
1.2 자동 bisect
테스트 스크립트가 있다면 자동으로 bisect를 실행할 수 있다:
2 Git Submodule: 외부 저장소 포함
Submodule은 Git 저장소 안에 다른 Git 저장소를 포함시키는 기능이다. 공통 라이브러리, 공유 컴포넌트 등을 관리할 때 사용한다.
2.1 서브모듈 추가
Cloning into '/project/libs/shared-lib'...
remote: Enumerating objects: 156, done.
remote: Counting objects: 100% (156/156), done.
Receiving objects: 100% (156/156), 45.23 KiB | 2.14 MiB/s, done.
자동으로 shared-lib 를 클론하고 .gitmodules 파일을 생성한다.
2.2 서브모듈이 포함된 저장소 Clone
2.3 서브모듈 업데이트
2.4 서브모듈 제거
# 1. 서브모듈 등록 해제
git submodule deinit libs/shared-lib
# 2. .git/modules에서 제거
git rm libs/shared-lib
# 3. 커밋
git commit -m "chore: Remove shared-lib submodule"Submodule은 강력하지만 관리가 복잡하다. 단순한 의존성 관리라면 패키지 매니저(npm, pip 등)를 사용하는 것이 더 적합할 수 있다.
3 Git Worktree: 동시 브랜치 작업
Worktree를 사용하면 하나의 Git 저장소에서 여러 브랜치를 동시에 다른 디렉토리에 열어놓고 작업할 수 있다. 브랜치 전환 없이 여러 브랜치를 동시에 작업할 때 유용하다.
3.1 기본 사용법
# 새 worktree 생성 (기존 브랜치)
git worktree add ../project-hotfix hotfix/critical-bug
# 새 worktree 생성 (새 브랜치 생성과 동시에)
git worktree add -b feature/new-ui ../project-new-ui
# worktree 목록 확인
git worktree list/home/user/project abc1234 [main] /home/user/project-hotfix def5678 [hotfix/critical-bug] /home/user/project-new-ui ghi9012 [feature/new-ui]
각 항목은 `경로 / 해시 / [브랜치명]` 형식이다.
# worktree 제거
git worktree remove ../project-hotfix
성공 시 아무 출력도 없다.
# 사용하지 않는 worktree 정리
git worktree prune
3.2 활용 시나리오
# 메인 디렉토리에서 feature 작업 중
# 긴급 버그 수정이 필요할 때
# 1. 별도 디렉토리에 hotfix worktree 생성
git worktree add ../project-hotfix -b hotfix/bug main
# 2. hotfix 디렉토리에서 버그 수정
cd ../project-hotfix
# ... 버그 수정 ...
git add .
git commit -m "fix: Critical bug"
git push
# 3. 원래 디렉토리로 돌아가서 feature 작업 계속
cd ../project
# 기존 작업 상태 그대로 유지되어 있음Worktree는 git stash의 대안이 될 수 있다. stash는 변경사항을 숨겼다가 꺼내야 하지만, worktree는 여러 브랜치를 동시에 열어둘 수 있어 컨텍스트 전환이 더 빠르다.
4 Git Hooks: 자동화
Git Hooks는 특정 Git 이벤트(커밋, 푸시 등) 발생 시 자동으로 스크립트를 실행하는 기능이다.
4.1 Hook 종류
4.1.1 클라이언트 측 Hook
| Hook | 실행 시점 | 용도 |
|---|---|---|
pre-commit |
커밋 직전 | 린트, 포맷팅 검사 |
commit-msg |
커밋 메시지 작성 후 | 메시지 형식 검증 |
pre-push |
push 직전 | 테스트 실행 |
post-commit |
커밋 완료 후 | 알림 발송 |
post-merge |
merge 완료 후 | 의존성 설치 |
4.1.2 서버 측 Hook
| Hook | 실행 시점 | 용도 |
|---|---|---|
pre-receive |
push 수신 전 | 정책 검증 |
post-receive |
push 수신 후 | 배포 트리거 |
4.2 Hook 설정 방법
Hook 스크립트는 .git/hooks/ 디렉토리에 저장한다.
4.3 pre-commit 프레임워크 (권장)
직접 hook 스크립트를 작성하는 대신, pre-commit 프레임워크를 사용하면 더 쉽게 관리할 수 있다.
프로젝트 루트에 .pre-commit-config.yaml 생성:
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- repo: https://github.com/psf/black
rev: 24.1.1
hooks:
- id: black
- repo: https://github.com/pycqa/flake8
rev: 7.0.0
hooks:
- id: flake8.pre-commit-config.yaml은 저장소에 포함되므로 팀 전체가 동일한 검사를 적용받는다. .git/hooks/에 직접 넣는 방식보다 관리가 편하다.
5 Git Alias: 명령어 단축
자주 사용하는 긴 명령어를 짧게 줄일 수 있다.
5.1 별칭 설정
# 기본 별칭
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.sw switch
# 복합 명령어 별칭
git config --global alias.graph "log --oneline --graph --all --decorate"
git config --global alias.last "log -1 HEAD"
git config --global alias.unstage "restore --staged"
git config --global alias.amend "commit --amend --no-edit"
# 상태 요약
git config --global alias.ss "status -s"5.2 사용 예시
5.3 별칭 확인 및 삭제
alias.st status
alias.co checkout
alias.br branch
alias.graph log --oneline --graph --all --decorate
alias.last log -1 HEAD
alias.unstage restore --staged
6 Git Blame: 라인별 작성자 확인
특정 파일의 각 줄을 누가, 언제, 어떤 커밋에서 수정했는지 확인한다.
abc1234 (홍길동 2024-03-01 10:30:00 +0900 1) def main():
def5678 (김영희 2024-03-05 14:22:15 +0900 2) print("Hello")
ghi9012 (홍길동 2024-03-10 09:15:45 +0900 3) return True
커밋해시 (작성자 날짜 줄번호) 코드 형식이다. 어떤 줄이 언제 누구에 의해 수정됐는지 한눈에 파악할 수 있다.
7 Git Clean: 추적되지 않는 파일 삭제
# 삭제될 파일 미리 확인 (dry run)
git clean -nd
# 추적되지 않는 파일 삭제
git clean -fd
# 무시된 파일도 포함하여 삭제
git clean -fdx
# 대화형 모드
git clean -idgit clean은 되돌릴 수 없다. 반드시 -n 옵션으로 먼저 확인하고 실행하자.
8 요약
| 기능 | 명령어 | 용도 |
|---|---|---|
| Bisect | git bisect start/bad/good |
버그 커밋 이진 탐색 |
| Submodule | git submodule add/update |
외부 저장소 포함 |
| Worktree | git worktree add/remove |
동시 브랜치 작업 |
| Hooks | .git/hooks/ 또는 pre-commit |
자동화 |
| Alias | git config alias.<name> |
명령어 단축 |
| Blame | git blame <file> |
라인별 작성자 확인 |
| Clean | git clean -fd |
미추적 파일 삭제 |