Skip to main content

커밋 히스토리를 깔끔하게 관리하기

Views 36약 7분생성형 AI 활용
Summary

커밋 히스토리는 프로젝트의 기록이다

Git에서 커밋은 단순한 저장이 아닙니다. 프로젝트가 어떤 이유로, 어떤 순서로 바뀌었는지 남기는 기록입니다.

처음에는 커밋 메시지가 조금 대충이어도 큰 문제가 없어 보입니다.

git commit -m "수정"
git commit -m "다시 수정"
git commit -m "진짜 최종"

혼자 연습할 때는 괜찮을 수 있습니다. 하지만 프로젝트가 커지고 팀원이 늘어나면 이런 기록은 금방 문제가 됩니다. 나중에 버그가 생겼을 때 "어느 변경 때문에 문제가 생겼는지" 찾기 어렵습니다. 코드 리뷰를 할 때도 변경 의도를 파악하기 어렵습니다.

좋은 커밋 히스토리는 다음 질문에 답할 수 있어야 합니다.

  • 무엇을 바꿨는가?

  • 왜 바꿨는가?

  • 어떤 작업 단위로 나뉘어 있는가?

  • 문제가 생기면 어떤 커밋을 되돌리면 되는가?

히스토리가 깔끔하면 협업이 쉬워집니다. 반대로 히스토리가 복잡하면 코드보다 기록을 해석하는 데 시간이 더 많이 듭니다.

커밋 히스토리를 깔끔하게 관리하기

작은 커밋과 명확한 메시지

좋은 커밋의 기본은 작게 나누는 것입니다. 하나의 커밋에는 하나의 의미 있는 변경만 담는 것이 좋습니다.

나쁜 예시는 다음과 같습니다.

git commit -m "여러 가지 수정"

이 커밋 안에 로그인 버그 수정, 버튼 색상 변경, README 수정이 모두 들어 있다면 나중에 추적하기 어렵습니다.

더 좋은 방식은 작업을 나누는 것입니다.

git commit -m "로그인 실패 시 에러 메시지 표시"
git commit -m "로그인 버튼 스타일 정리"
git commit -m "README에 실행 방법 추가"

이렇게 나누면 코드 리뷰도 쉬워집니다. 리뷰어는 "로그인 실패 처리"만 따로 볼 수 있고, 문서 수정은 별도로 확인할 수 있습니다.

커밋 메시지는 길게 쓸 필요가 없습니다. 핵심은 구체적으로 쓰는 것입니다.

# 애매한 메시지
fix
update
수정

# 더 나은 메시지
회원가입 입력값 검증 추가
빈 할 일 등록 방지
README에 설치 방법 추가

좋은 메시지는 미래의 나와 팀원을 돕습니다. 지금은 내가 작성한 코드라서 기억할 수 있지만, 몇 주 뒤에는 기억이 흐려집니다. 그때 커밋 메시지가 작업의 단서가 됩니다.

방금 만든 커밋 고치기: git commit --amend

커밋을 만든 직후에 실수를 발견하는 경우가 많습니다.

예를 들어 방금 README 수정 내용을 커밋했는데, 저장해야 할 파일 하나를 빠뜨렸다고 해봅시다.

git status

확인해 보니 README.md는 커밋했지만 images/screenshot.png 파일을 빠뜨렸습니다. 이럴 때 새 커밋을 하나 더 만들 수도 있습니다.

git add images/screenshot.png
git commit -m "빠진 이미지 추가"

하지만 이 변경이 바로 전 커밋에 포함되는 것이 더 자연스럽다면 --amend를 사용할 수 있습니다. amend는 "방금 만든 커밋을 고친다"는 뜻으로 이해하면 됩니다.

git add images/screenshot.png
git commit --amend

그러면 Git이 마지막 커밋을 다시 열어 줍니다. 커밋 메시지를 그대로 두거나 더 알맞게 수정할 수 있습니다.

커밋 메시지만 고치고 싶을 때도 사용할 수 있습니다.

git commit --amend -m "README에 실행 방법과 스크린샷 추가"

단, 중요한 주의사항이 있습니다. --amend는 기존 커밋을 살짝 수정하는 것이 아니라, 새로운 커밋으로 다시 만드는 방식입니다. 그래서 커밋 ID가 바뀝니다.

아직 GitHub에 push하지 않은 커밋이라면 부담 없이 사용해도 됩니다. 하지만 이미 push했고 다른 사람이 그 커밋을 기준으로 작업하고 있다면 조심해야 합니다. 공유된 커밋을 바꾸면 팀원의 히스토리와 충돌할 수 있습니다.

초보자 기준으로는 이렇게 기억하면 됩니다.

  • 아직 push 전이면 --amend 사용 가능

  • 혼자 쓰는 브랜치라면 비교적 안전

  • 팀원이 함께 쓰는 브랜치라면 함부로 사용하지 않기

실험 커밋을 하나로 합치기: squash merge

기능을 만들다 보면 실험 커밋이 많이 생깁니다.

git commit -m "할 일 추가 폼 생성"
git commit -m "버튼 위치 수정"
git commit -m "오타 수정"
git commit -m "에러 처리 추가"
git commit -m "리뷰 반영"

작업 중에는 이런 커밋이 자연스럽습니다. 문제는 이 모든 커밋이 그대로 main 브랜치에 들어가면 히스토리가 복잡해질 수 있다는 점입니다.

이럴 때 GitHub의 Squash merge를 사용할 수 있습니다. Squash는 여러 커밋을 하나로 압축한다는 뜻입니다.

예를 들어 feature/add-todo-form 브랜치에서 여러 커밋으로 작업했다고 해봅시다. Pull Request에서 리뷰를 받고 나서 병합할 때 Squash and merge를 선택하면, main 브랜치에는 하나의 커밋만 남길 수 있습니다.

여러 실험 커밋
→ main에는 하나의 의미 있는 커밋으로 기록

최종 커밋 메시지는 이렇게 정리할 수 있습니다.

할 일 추가 폼 구현

이 방식의 장점은 분명합니다.

  • main 브랜치의 히스토리가 깔끔해집니다.

  • 작업 단위가 Pull Request 단위로 정리됩니다.

  • 리뷰 과정에서 생긴 사소한 수정 커밋이 남지 않습니다.

다만 모든 경우에 squash가 정답은 아닙니다. 커밋 하나하나가 의미 있고 나중에 따로 추적할 가치가 있다면 그대로 병합하는 것이 더 좋을 수 있습니다. 하지만 초보자와 작은 팀에서는 기능 브랜치를 PR 단위로 squash merge하는 방식이 이해하기 쉽고 관리하기도 편합니다.

최신 기준 위로 다시 쌓기: git rebase

rebase는 초보자에게 조금 어렵게 느껴질 수 있습니다. 하지만 개념은 단순합니다.

내 브랜치의 커밋을 최신 main 브랜치 위에 다시 쌓는 작업입니다.

예를 들어 내가 feature/profile 브랜치에서 작업하는 동안 다른 팀원이 main에 새 커밋을 추가했다고 해봅시다.

main:     A -- B -- C
                \
feature:         D -- E

그 사이 main은 더 앞으로 나아갔습니다.

main:     A -- B -- C -- F -- G
                \
feature:         D -- E

이때 rebase를 하면 내 커밋 D, E를 최신 main의 끝인 G 위에 다시 올립니다.

main:     A -- B -- C -- F -- G
                              \
feature:                       D' -- E'

실제 명령어는 다음과 같습니다.

git fetch origin
git switch feature/profile
git rebase origin/main

여기서 git fetch origin은 GitHub의 최신 상태를 가져오는 명령입니다. 그다음 내 브랜치로 이동하고, origin/main 위로 내 커밋을 다시 쌓습니다.

rebase 중 충돌이 날 수도 있습니다. 충돌이 나면 Git이 어떤 파일에서 문제가 생겼는지 알려줍니다. 파일을 열어 충돌을 고친 뒤 다음 명령을 실행합니다.

git add 충돌을_해결한_파일
git rebase --continue

만약 rebase를 멈추고 원래 상태로 돌아가고 싶다면 다음 명령을 사용합니다.

git rebase --abort

rebase의 장점은 히스토리가 직선처럼 깔끔해진다는 것입니다. 불필요한 병합 커밋이 줄어들고, 작업 흐름을 순서대로 읽기 쉬워집니다.

하지만 주의할 점이 있습니다. rebase도 커밋을 다시 만드는 작업입니다. 따라서 이미 다른 사람과 공유한 브랜치에서 함부로 rebase하면 문제가 생길 수 있습니다.

초보자는 이렇게 사용하면 안전합니다.

  • 내 개인 작업 브랜치에서만 rebase하기

  • main 브랜치에서는 rebase하지 않기

  • 이미 여러 사람이 함께 쓰는 브랜치는 rebase하지 않기

  • rebase가 불안하면 팀의 규칙을 먼저 확인하기

버전 지점을 표시하기: git tag

커밋 히스토리는 계속 앞으로 나아갑니다. 그런데 어느 시점이 정식 버전인지 표시하고 싶을 때가 있습니다.

예를 들어 프로젝트의 첫 번째 안정 버전을 만들었다면 다음처럼 표시할 수 있습니다.

git tag -a v1.0.0 -m "첫 번째 안정 버전"

이 명령은 현재 커밋에 v1.0.0이라는 태그를 붙입니다. 태그는 특정 커밋에 붙이는 이름표라고 생각하면 됩니다.

태그를 확인하려면 다음 명령을 사용합니다.

git tag

태그를 GitHub에 올리려면 push해야 합니다.

git push origin v1.0.0

여러 태그를 한 번에 올릴 수도 있습니다.

git push origin --tags

버전 이름은 보통 v1.0.0, v1.1.0, v2.0.0처럼 작성합니다. 간단히 이해하면 다음과 같습니다.

  • v1.0.0: 첫 번째 정식 버전

  • v1.1.0: 기능이 추가된 버전

  • v1.1.1: 버그를 고친 작은 수정 버전

  • v2.0.0: 큰 변화가 있는 새 버전

태그를 사용하면 나중에 "이때 배포한 코드가 정확히 무엇이었는지" 찾기 쉽습니다. GitHub의 Releases 기능과 연결하면 사용자에게 배포 노트도 함께 제공할 수 있습니다. 배포와 릴리스 관리는 뒤에서 더 자세히 다룹니다.

실전 예시: 기능 작업부터 버전 표시까지

간단한 할 일 앱에 "완료한 할 일 숨기기" 기능을 추가한다고 해봅시다.

먼저 작업 브랜치를 만듭니다.

git switch -c feature/hide-completed-todos

작업하면서 의미 있는 단위로 커밋합니다.

git add src/TodoFilter.js
git commit -m "완료한 할 일 필터 추가"

git add src/App.js
git commit -m "필터 상태를 화면에 연결"

그런데 방금 커밋한 뒤 테스트 파일을 빠뜨린 것을 발견했습니다.

git add src/TodoFilter.test.js
git commit --amend

이제 GitHub에 push하고 Pull Request를 만듭니다.

git push -u origin feature/hide-completed-todos

PR을 열었는데 그 사이 main 브랜치가 업데이트되었습니다. 내 브랜치를 최신 기준에 맞춥니다.

git fetch origin
git rebase origin/main

충돌이 없다면 그대로 PR을 업데이트합니다. 이미 원격 브랜치에 push한 뒤 rebase했다면 커밋 ID가 바뀌었기 때문에 일반 git push가 거절될 수 있습니다. 이때는 팀 규칙을 확인한 뒤 신중하게 처리해야 합니다. 혼자 쓰는 브랜치이고, 원격에 다른 사람이 추가로 올린 커밋이 없다고 확신할 때만 다음 명령을 사용할 수 있습니다.

git push --force-with-lease

--force-with-lease는 강제로 덮어쓰되, 내가 모르는 다른 사람의 변경이 있으면 막아 주는 비교적 안전한 방식입니다. 그래도 공유 브랜치에서는 조심해야 합니다. 초보자는 이 명령을 쓰기 전에 "이 브랜치를 나만 쓰고 있는가?"를 반드시 확인하세요.

리뷰가 끝나면 GitHub에서 Squash and merge를 선택합니다. 그러면 main에는 다음과 같은 하나의 커밋으로 정리됩니다.

완료한 할 일 숨기기 기능 추가

마지막으로 이 기능을 포함한 새 버전을 표시합니다.

git switch main
git pull origin main
git tag -a v1.1.0 -m "완료한 할 일 숨기기 기능 추가"
git push origin v1.1.0

이제 v1.1.0 태그를 보면 해당 버전에 어떤 코드가 들어갔는지 확인할 수 있습니다.

정리

깔끔한 커밋 히스토리는 보기 좋은 장식이 아닙니다. 팀원이 변경 이유를 이해하고, 버그를 추적하고, 릴리스를 관리하는 데 필요한 실용적인 도구입니다.

이번 장의 핵심은 다음과 같습니다.

  • 커밋은 작은 단위로 나누고 메시지는 구체적으로 작성합니다.

  • 방금 만든 커밋의 메시지나 빠진 파일은 git commit --amend로 고칠 수 있습니다.

  • PR에 쌓인 여러 실험 커밋은 Squash merge로 하나의 의미 있는 커밋으로 정리할 수 있습니다.

  • git rebase는 내 커밋을 최신 기준 위로 다시 쌓는 작업입니다.

  • 공유된 브랜치에서 amend나 rebase를 사용할 때는 커밋 ID가 바뀌므로 주의해야 합니다.

  • git tag는 v1.0.0 같은 버전 지점을 표시할 때 사용합니다.

처음부터 완벽한 히스토리를 만들 필요는 없습니다. 다만 커밋을 만들 때마다 "나중에 이 기록을 읽는 사람이 이해할 수 있을까?"를 생각하면 됩니다. 그 습관이 쌓이면 프로젝트의 이력은 자연스럽게 읽기 쉬워집니다.

책 목록

GitHub 첫걸음부터 실무 협업까지

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기