개념 정리
Git과 버전 관리 시스템
단원 개요
분산 버전 관리 시스템 Git의 4가지 작업 공간과 스냅샷 원리, 브랜치(Branch)와 HEAD 포인터, Merge vs Rebase의 히스토리 차이, 충돌(Conflict) 해결 및 되돌리기(Reset/Revert)를 학습합니다.선수 개념
필수 키워드:스냅샷(Snapshot)Git의 4단계 영역과 명령어 흐름로 로컬 커밋을 공유합니다.
git pull브랜치(Branch)와 HEAD의 정체가벼운 참조(이름표)HEADMerge (병합)병합 커밋(Merge Commit)fast-forward1
Git의 스냅샷 원리와 4대 작업 공간(Working, Staging, Local, Remote)
•
스냅샷(Snapshot) 기반 분산 버전 관리:
•
리누스 토르발즈가 개발한 Git은 커밋할 때 프로젝트 파일의 상태를 스냅샷(Snapshot)으로 기록합니다. 내용이 같은 객체는 재사용하며, 내부 압축 과정에서는 델타 표현도 쓸 수 있습니다. 객체 ID는 해시로 계산하며 일반적인 SHA-1 저장소는 16진수 40자리, SHA-256을 선택한 저장소는 64자리입니다. 내용이 바뀌면 객체 ID도 달라져 무결성 검사에 쓰이지만, 해시가 파일 수정 자체를 막는 것은 아닙니다.
•
Git의 4단계 영역과 명령어 흐름:
1
Working Directory (작업 디렉토리): 개발자가 에디터(VS Code 등)로 실제 코드를 작성하고 수정하는 로컬 폴더입니다.
2
Staging Area (Index, 스테이징 영역):
git add 명령어를 통해 '이번 다음 커밋에 포함시킬 변경 파일들만' 깔끔하게 골라 담아 준비해 두는 임시 대기소입니다.3
Local Repository (로컬 저장소,
.git 폴더): git commit -m "메시지"를 실행하여 스테이징 영역의 스냅샷을 내 컴퓨터의 영구적인 버전 히스토리로 확정 기록한 공간입니다.4
Remote Repository (원격 저장소 - GitHub, GitLab 등):
git push로 로컬 커밋을 공유합니다. git fetch는 원격 변경을 가져와 원격 추적 참조를 갱신하고, git pull은 fetch 뒤 옵션·설정에 따라 fast-forward, merge 또는 rebase 등으로 현재 브랜치에 통합합니다. 항상 fetch + merge로만 동작하는 것은 아닙니다.핵심 원리
왜 Working Directory에서 바로 커밋하지 않고 굳이 Staging Area(git add)를 거칠까요? 파일 10개를 동시에 수정했더라도 '로그인 버그 수정(3개)'과 'UI 디자인 변경(7개)'을 논리적인 작업 단위로 나누어 각각 따로 깔끔하게 커밋하기 위해서입니다!2
브랜치(Branch)와 HEAD 포인터, Merge vs Rebase, 충돌 해결
•
브랜치(Branch)와 HEAD의 정체:
•
브랜치는 특정 커밋을 가리키는 가벼운 참조(이름표)입니다. 폴더 전체를 복사하지 않으므로 생성 비용이 작지만, 저장 크기와 시간은 해시 형식·참조 저장 방식·환경에 따라 달라집니다.
HEAD는 보통 현재 브랜치를 가리키며, detached HEAD 상태에서는 커밋을 직접 가리킵니다.•
브랜치 통합의 두 가지 방식:
git merge vs git rebase:1
Merge (병합): 분기된 두 이력을 통합할 때 보통 병합 커밋(Merge Commit)을 만듭니다. 현재 커밋이 상대 브랜치의 조상이라면 fast-forward로 참조만 전진시킬 수 있고, 이때는 새 병합 커밋이 생기지 않습니다.
--no-ff 등 옵션에 따라서도 결과가 달라집니다.2
Rebase (리베이스): 내 커밋의 변경을 대상 커밋 뒤에 다시 적용하여 이력을 정리합니다. 다시 생성된 커밋의 ID는 달라지므로, 다른 사람이 기반으로 사용 중인 공유 이력은 팀 합의 없이 rebase하지 않는 것이 안전합니다.
•
충돌(Merge Conflict)이 발생하는 이유와 해결법:
•
서로 겹치지 않는 변경은 보통 자동으로 병합합니다. 같은 부분의 서로 다른 수정, 한쪽의 수정과 다른 쪽의 삭제 등 Git이 자동으로 조합할 수 없는 변경은 충돌이 됩니다. 같은 줄의 수정만이 유일한 원인은 아닙니다.
•
텍스트 충돌에는 충돌 마커(
<<<<<<< HEAD, =======, >>>>>>> feature)가 표시될 수 있습니다. 최종 내용을 정하고 마커를 지운 뒤 git add ➔ git commit으로 일반적인 merge를 완료합니다. rebase 도중에는 git rebase --continue로 이어갑니다.풀이
1) 발생하는 현상 (Merge Conflict):
동일한 파일(config.py)의 동일한 10번째 줄이 양쪽 브랜치에서 서로 다르게 수정되었으므로 자동 병합이 실패하고 충돌(Conflict)이 발생합니다. 파일 내부에는 다음과 같은 충돌 마커가 삽입됩니다:
<<<<<<< HEAD
PORT = 3000
=======
PORT = 5000
>>>>>>> feature
2) 해결 절차:
①
에디터에서
<<<<<<<, =======, >>>>>>> 마커 줄과 PORT = 3000을 모두 지우고 원하는 코드인 PORT = 5000만 남긴 뒤 파일을 저장합니다.②
git add config.py 명령어로 충돌이 해결되었음을 스테이징 영역에 알립니다.③
git commit을 실행하여 병합 완료 커밋을 생성합니다.3
실수 복구와 협업 실무: Reset vs Revert, Stash, GitHub PR 워크플로우
•
과거 커밋을 되돌리는 두 가지 명령어:
git reset vs git revert:•
git reset <커밋> (현재 브랜치의 기준 변경): 브랜치가 가리키는 커밋을 바꿉니다. --soft는 인덱스와 작업 파일을 유지하고, 기본값 --mixed는 인덱스를 대상 커밋으로 맞추되 작업 파일은 유지합니다. --hard는 인덱스와 추적 중인 작업 파일도 대상 상태로 맞추므로 커밋하지 않은 변경을 잃을 수 있습니다. 덮어쓸 경로를 막는 미추적 파일도 삭제될 수 있습니다. 참조에서 빠진 커밋은 즉시 영구 삭제되는 것이 아니며, 객체가 남아 있다면 reflog 등으로 찾을 수 있습니다. 커밋하지 않은 파일의 복구가 보장된다는 뜻은 아닙니다.•
git revert (취소 커밋 새로 추가): 기존 커밋의 변경을 되돌리는 새 커밋을 만듭니다. 공유된 이력을 다시 쓰지 않고 잘못된 변경을 취소할 때 일반적으로 권장합니다.•
git stash (임시 서랍 보관):•
작업 중인 추적 파일의 변경을 임시 보관합니다. 미추적 파일까지 포함하려면
-u 같은 옵션이 필요합니다. git stash pop으로 다시 적용할 때 충돌이 생길 수도 있으므로 결과를 확인해야 합니다.주의할 점
공유 브랜치의 이력을 reset·rebase한 뒤 강제 푸시하면 동료의 작업 기반을 바꿀 수 있습니다. 팀 합의 없이 공유 이력을 다시 쓰지 말고, 보통은 revert로 취소 커밋을 추가하세요. reset --hard는 커밋하지 않은 작업을 잃을 수 있으므로 먼저 별도 백업이나 커밋으로 보호해야 합니다.핵심 요약
- ✓Git의 작업 흐름은 Working Directory ➔(git add)➔ Staging Area ➔(git commit)➔ Local Repository ➔(git push)➔ Remote Repository 순이다.
- ✓브랜치는 커밋을 가리키는 가벼운 참조다. HEAD는 보통 브랜치를, detached HEAD 상태에서는 커밋을 직접 가리킨다.
- ✓merge는 fast-forward이면 새 커밋 없이 참조를 전진시킬 수 있다. 자동 조합이 불가능한 변경은 충돌이 되어 수동 해결이 필요하다.
- ✓reset은 참조·인덱스·작업 파일에 미치는 영향이 옵션마다 다르다. 공유 이력을 보존하며 변경을 취소하려면 보통 새 취소 커밋을 만드는 revert를 사용한다.