Git
- 초기 세팅
- .gitignore
- 명령어
- HEAD vs main (+특수 HEAD 종류 정리)
- Git 명령어 정리
- git describe
- git merge
- cherry-pick
- git pull --allow-unrelated-histories
- git reset
- revert
- git tag
- git reflog (git reset 후 커밋 복구)
- 병합
- 구조
초기 세팅
Git 로컬 작업 폴더 원격 저장소에 연결하기 (HTTPS 방식 기준)
1. 로컬 Git 저장소 초기화 및 원격 연결
1.1 Git 초기화
git init
- 현재 폴더를 Git 저장소로 초기화 (
.git
폴더 생성)
1.2 원격 저장소 연결
git remote add origin https://github.com/사용자명/저장소명.git
- GitHub에서 생성한 저장소 주소를
origin
이라는 이름으로 등록
2. GitHub Personal Access Token(PAT) 사용
GitHub는 2021년부터 비밀번호 인증을 중단하고 토큰(PAT) 인증 방식만 허용함
2.1 토큰 발급 방법
- GitHub 로그인
- 우측 상단 →
Settings > Developer settings > Personal access tokens
Tokens (classic)
→Generate new token
repo
,workflow
등의 권한 선택 후 생성
2.2 토큰 저장 방법
방법 1: Git 사용 시 직접 입력
git push origin main
- GitHub 사용자명 입력 후
비밀번호 자리에 토큰 붙여넣기
방법 2: 캐시 저장
git config --global credential.helper store
- 한 번 입력하면 이후 저장됨 (로컬 평문 저장 주의)
3. Git 기본 명령어 흐름
3.1 기존 원격 저장소 내용 가져오기 (선택)
git pull origin main --allow-unrelated-histories
- 로컬과 원격 저장소에 공통 커밋이 없을 때 충돌 방지용
- 초기 1회만 사용
3.2 작업 파일 스테이징
git add .
- 현재 폴더의 모든 변경 파일을 스테이징 영역에 추가
3.3 커밋
git commit -m "커밋 메시지"
- 변경 내용을 로컬 저장소에 기록
3.4 원격 저장소에 푸시
git push -u origin main
-u
옵션은 이후git push
만으로도 기본 원격 브랜치 지정됨
✅ 최초 연결시
git init
git remote add origin https://github.com/username/repo.git
git pull origin main --allow-unrelated-histories
git add .
git commit -m "초기 커밋"
git push -u origin main
GitHub – SSH 방식 연결 방법
1. SSH란?
- SSH(Secure Shell)는 암호화된 인증 방식으로 GitHub 등 원격 서버에 안전하게 연결할 수 있게 해준다.
- Git 작업 시 매번 사용자명/비밀번호 또는 토큰 입력 대신, 공개키 기반 인증으로 로그인 가능하다.
- HTTPS보다 보안성/편의성이 뛰어나며, 개발자들이 선호하는 방식이다.
2. SSH 키 생성
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
-t rsa
: 키 유형 (보통rsa
)-b 4096
: 비트 수 (보안성 높음)-C
: 식별용 주석(보통 이메일 사용)
생성 결과:
- 비공개 키:
~/.ssh/id_rsa
- 공개 키:
~/.ssh/id_rsa.pub
→ 기존 키가 있다면 -f ~/.ssh/파일명
옵션으로 이름을 바꿔 생성
3. SSH 공개키 GitHub에 등록
- 공개키 복사:
cat ~/.ssh/id_rsa.pub
- GitHub 접속
Settings > SSH and GPG Keys > New SSH Key
- 제목 입력 후 키 붙여넣기 → 저장
4. SSH 연결 테스트
ssh -T git@github.com
- 최초 연결 시
yes
입력 필요 - 성공 메시지:
Hi username! You've successfully authenticated, but GitHub does not provide shell access.
5. 원격 저장소 SSH 주소로 연결
- HTTPS가 아닌 SSH 주소를 사용해야 한다:
git remote add origin git@github.com:username/repository.git
- 기존 원격 주소 변경:
git remote set-url origin git@github.com:username/repository.git
6. Git 기본 작업 흐름 (SSH 사용 시)
git pull origin main
git add .
git commit -m "커밋 메시지"
git push origin main
- 최초
git push -u origin main
으로 업스트림 설정 권장
7. SSH 키를 여러 개 사용하는 방법
7.1 SSH 키 여러 개 생성
ssh-keygen -t rsa -C "email1@example.com" -f ~/.ssh/id_rsa_personal
ssh-keygen -t rsa -C "email2@example.com" -f ~/.ssh/id_rsa_work
7.2 ~/.ssh/config
설정
Host github.com-personal
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa_personal
Host github.com-work
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa_work
7.3 저장소 원격 주소 설정
git remote set-url origin git@github.com-work:username/repo.git
github.com-work
는~/.ssh/config
에 정의된 Host 이름과 일치해야 함
7.4 연결 테스트
ssh -T github.com-work
✅ 보안 팁
- SSH 비공개키는 절대 외부에 공유하지 말 것
.ssh/config
는 접근 권한을 600으로 설정- 필요 시
ssh-add ~/.ssh/id_rsa_파일명
으로 ssh-agent에 등록 가능 - 키 생성 시 패스프레이즈를 설정하면 보안 강화
8. GitHub에 SSH 키 자동으로 추가하는 스크립트
8.1 필요 조건
- GitHub 계정의 Personal Access Token (토큰 방식 로그인 필요)
curl
명령어 사용 가능 환경
8.2 스크립트 예시
#!/bin/bash
# 설정: 사용자 정보 입력
GITHUB_USERNAME="your-username"
GITHUB_TOKEN="your-personal-access-token"
SSH_KEY_TITLE="My Laptop SSH Key"
SSH_KEY_PATH="$HOME/.ssh/id_rsa.pub"
# 공개키 가져오기
PUB_KEY=$(cat $SSH_KEY_PATH)
# GitHub API로 키 등록
curl -u "$GITHUB_USERNAME:$GITHUB_TOKEN" \
--data "{\"title\":\"$SSH_KEY_TITLE\",\"key\":\"$PUB_KEY\"}" \
https://api.github.com/user/keys
8.3 사용 방법
- 위 스크립트를
add_ssh_key.sh
로 저장 - 실행 권한 부여:
chmod +x add_ssh_key.sh
- 실행:
./add_ssh_key.sh
✅ 실행되면 GitHub 계정에 SSH 키가 자동 등록됨
9. SSH 키 백업 및 복구 방법
9.1 백업 방법
mkdir -p ~/backup_ssh_keys
cp ~/.ssh/id_rsa* ~/backup_ssh_keys/
id_rsa
: 비공개 키id_rsa.pub
: 공개 키- 외장하드, USB, 클라우드 등 보안된 저장소에 보관할 것
9.2 복구 방법
- 복사한 키 파일을 다시
~/.ssh
디렉토리에 복원
cp ~/backup_ssh_keys/id_rsa* ~/.ssh/
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
- 퍼미션 문제 방지:
id_rsa
: 600 (읽기/쓰기)id_rsa.pub
: 644 (읽기 가능)
9.3 권한 오류 방지
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
✅ 팁
- 여러 장비에 동일한 SSH 키를 복사해도 됨
- 단, GitHub는 키 값이 같으면 한 번만 등록 가능
- 새로운 장비에서 키 재생성해도 되고, 기존 키 재사용도 가능
.gitignore
.gitignore 설정
1. .gitignore
란?
.gitignore
는 Git이 추적하지 않을 파일/폴더를 명시하는 설정 파일이다.- 주로 아래와 같은 파일들을 제외할 때 사용한다:
- OS/IDE 생성 파일 (
.DS_Store
,Thumbs.db
,.vscode/
) - 로그, 빌드 결과물 (
*.log
,dist/
,build/
) - 민감 정보 (
.env
,*.pem
,secret.txt
) - 의존성 디렉토리 (
node_modules/
,vendor/
)
- OS/IDE 생성 파일 (
2. 작성 위치
.gitignore
파일은 저장소 루트 경로에 위치한다.- 하위 폴더에 별도로 둘 수도 있으나, 일반적으로 루트에 하나만 둠.
3. 패턴 작성법
3.1 기본 규칙
패턴 | 설명 |
---|---|
|
|
|
|
| 루트 경로의 |
|
|
|
|
3.2 주석 사용
# 로그 파일 무시
*.log
3.3 제외 항목 설정
# 모든 .env 파일은 무시
*.env
# 단, .env.example은 추적
!.env.example
4. 자주 사용하는 .gitignore 예시
4.1 Node.js
node_modules/
npm-debug.log
.env
dist/
4.2 Python
__pycache__/
*.py[cod]
.env
*.sqlite3
4.3 Java (IntelliJ 포함)
*.class
*.jar
*.war
*.log
target/
.idea/
*.iml
5. 이미 추적 중인 파일 무시하기
.gitignore
에 추가했지만 이미 추적 중인 파일은 무시되지 않는다.
5.1 캐시 삭제 후 반영
git rm --cached 파일명
또는 전체 캐시 삭제:
git rm -r --cached .
git add .
git commit -m "Update .gitignore rules"
6. .gitignore 생성 도구 추천
- https://www.toptal.com/developers/gitignore
→ 언어/프레임워크/IDE 선택만 하면 자동 생성
✅ 참고 팁
.gitignore
는 로컬에서만 적용되는 규칙이며, Git이 실제로 commit할 파일을 결정하는 기준이다.- 회사/협업 프로젝트는 공통된
.gitignore
템플릿을 맞춰야 충돌 예방 가능 .git/info/exclude
를 사용하면 개인용 ignore 설정도 가능 (공유 안 됨)
명령어
HEAD vs main (+특수 HEAD 종류 정리)
1. 개요
용어 | 역할 | 예시 |
---|---|---|
| 현재 작업 중인 커밋을 가리키는 포인터 |
|
| 기본 브랜치 이름 (Git 2.28+ 기본 브랜치) |
|
2. 개념 비교
항목 | HEAD (포인터) | main (브랜치) |
---|---|---|
정체 | 특수 포인터 | 이름 있는 참조 |
용도 | "현재 내가 작업 중인 위치" 추적 | 커밋들을 연결하는 선 |
이동 가능성 | 하나만 존재, 항상 이동함 | 여러 브랜치 중 하나, 직접 이동 안 함 |
Git 명령어 관련 |
|
|
실제 저장 위치 |
|
|
3. 시각적 예시
A---B---C---D
↑
main
↑
HEAD
HEAD → main → D 커밋
git checkout main
→HEAD
가main
브랜치를 가리킴git checkout <커밋 해시>
→HEAD
가 Detached 상태
4. HEAD의 두 가지 상태
상태 | 설명 | 결과 |
---|---|---|
Attached HEAD | HEAD가 브랜치를 가리킴 | ✅ 정상 상태 (
) |
Detached HEAD | HEAD가 특정 커밋 해시를 직접 가리킴 | 🌀 브랜치가 아님, 새 커밋은 임시 상태 |
git checkout main # HEAD → main
git checkout a1b2c3d # HEAD → a1b2c3d (Detached)
5. 관련 명령어
명령어 | 설명 |
---|---|
| HEAD가 가리키는 브랜치 경로 확인 |
| HEAD 내용 확인 (
) |
| HEAD 기준 커밋 히스토리 확인 |
| HEAD 이동 이력 추적 (복구용) |
6. 요약 비교표
구분 | HEAD | main |
---|---|---|
유형 | 포인터 (현재 위치) | 브랜치 이름 |
갯수 | 항상 1개 | 여러 개 가능 |
의미 | 현재 체크아웃된 브랜치/커밋 | 브랜치(커밋 선형 연결) |
이동 가능 여부 | 명령어로 이동 가능 | 직접 이동 불가 (커밋 시 이동) |
7. 특수 HEAD 종류 정리
이름 | 설명 |
---|---|
| 현재 작업 중인 커밋 (or 브랜치) 포인터 |
|
|
|
|
| 직전의 |
|
|
|
|
8. 활용 예시
git reset --hard ORIG_HEAD # 직전 상태로 롤백
git merge feature # 병합 시 MERGE_HEAD 생성됨
cat .git/MERGE_HEAD # 병합 대상 커밋 확인
git fetch origin # FETCH_HEAD 갱신
cat .git/FETCH_HEAD
요약
| 현재 위치 추적 |
| reset/merge 전 원래 HEAD |
| fetch로 받아온 최신 원격 커밋 위치 |
| merge 병합 대상 커밋 |
Git 명령어 정리
1. Git Commit
1.1 개념
- Git은 디렉토리 전체의 스냅샷을 기록하지만, 실제로는 변경된 부분(delta)만 저장하여 가볍게 유지함.
- 대부분의 커밋은 그 위의 부모 커밋을 가리킴.
1.2 명령어
git commit
2. Git Branch
2.1 개념
- Git의 브랜치는 커밋에 대한 참조(reference)로 매우 가볍다.
- “하나의 커밋과 그 조상 커밋들을 포함하는 작업 내역”이라고 볼 수 있음.
- 브랜치를 많이 만들어도 성능이나 저장공간에 영향이 없음.
2.2 명령어
git branch -f <branch>
git checkout <branch> # 브랜치로 이동
3. Git Merge
3.1 개념
- Merge는 두 부모를 갖는 특별한 커밋을 만들어 병합을 수행.
- 모든 부모 커밋의 작업 내역을 포함함.
3.2 명령어
git merge <branch>
4. Git Rebase
4.1 개념
- 커밋들을 모아서 복사한 후, 다른 브랜치에 붙이는 방식.
- 커밋 로그를 한 줄로 정리 가능.
A에서 B로 리베이스
→ A의 기반(base)을 B로 변경.
4.2 명령어
git rebase <branch>
5. Git Checkout
5.1 개념
HEAD
는 브랜치나 커밋을 가리키는 이동 가능한 포인터.checkout
은 특정 브랜치나 커밋으로 이동시킴.HEAD
가 커밋을 직접 가리킬 때는 분리된 HEAD 상태.
5.2 명령어
git checkout <branch or commit>
6. 상대 참조 (Relative Reference)
6.1 기호 설명
^
: 한 커밋 위로~<n>
: 여러 커밋 위로
6.2 예시
git HEAD^
git HEAD~2
7. Git Reset & Revert
7.1 git reset
- 브랜치를 예전 커밋으로 이동시켜 변경 사항을 되돌림.
- 히스토리가 삭제됨, 공동 작업 시 주의 필요.
git reset <commit>
7.2 git revert
- 현재 브랜치에서 역 변경 커밋을 새로 만들어 안전하게 되돌림.
git revert <commit>
8. Git Cherry-pick
8.1 개념
- 원하는 커밋만 선택적으로 복사해서 HEAD 밑에 적용.
- 해시값을 명확히 알고 있을 때 유용.
8.2 명령어
git cherry-pick <commit1> <commit2> ...
9. Git Interactive Rebase
9.1 개념
- 체리픽처럼 커밋을 고르는 게 아니라 목록을 직접 수정해서 순서 변경, 제거 가능.
9.2 명령어
git rebase -i <base>
10. Git Tag
10.1 개념
- 커밋에 대한 영구적인 닻. 릴리즈 버전 등에 주로 사용.
- 브랜치와 달리 절대 움직이지 않음.
10.2 명령어
git tag <tag> <commit>
11. Git Describe
11.1 개념
- **가장 가까운 태그(tag)**를 기준으로 현재 위치를 설명함.
11.2 명령어
git describe <ref>
11.3 결과 형식
<tag>_<numCommits>_g<hash>
12. Git Clone
12.1 개념
- 원격 저장소를 로컬로 복제.
12.2 명령어
git clone <repo_url>
13. Git Remote
13.1 개념
- 원격 저장소와의 연결 정보
- clone 시 기본 이름은
origin
.
13.2 특징
origin/main
은 원격 브랜치, 체크아웃하면 분리된 HEAD 상태.
13.3 예시
git remote
git checkout origin/main
14. Git Fetch
14.1 개념
- 원격 저장소로부터 새 커밋 다운로드, 브랜치는 변경하지 않음.
14.2 명령어
git fetch <remote>
15. Git Pull
15.1 개념
fetch
+merge
를 한 번에 수행.- 원격 저장소와 로컬 브랜치 동기화.
15.2 명령어
git pull origin main
git diff HEAD origin/main # 차이 확인
16. Git Push
16.1 개념
- 자신의 커밋을 공개 및 공유. 원격 저장소에 업로드.
16.2 명령어
git push origin <branch>
17. Git fakeTeamwork
17.1 개념
- 협업자 또는 가상의 작업자 변경 내역을 로컬로 가져오는 시뮬레이션 개념.
git describe
1. Git Describe란?
git describe
는 현재 커밋(또는 ref)이 가장 가까운 태그로부터 몇 번째 커밋인지, 어떤 커밋인지 요약해주는 명령어이다.- 주로 버전 관리, 릴리즈 스크립트 자동화, 디버깅 시 위치 파악 등에 활용됨.
2. 기본 출력 형식
<tag>_<N>_g<short-hash>
항목 | 설명 |
---|---|
| 가장 가까운 태그 이름 |
| 태그 이후 몇 번째 커밋인지 (0이면 태그 본인) |
| 해당 커밋의 Git short hash |
3. 자주 쓰는 옵션
3.1 --tags
git describe --tags
- 기본 동작은 annotated tag만 검색.
--tags
를 붙이면 lightweight tag도 포함하여 검색.
3.2 --abbrev=0
git describe --abbrev=0
- 가장 가까운 태그 이름만 출력하고, 커밋 수나 해시는 생략됨.
- 릴리즈 버전명만 필요할 때 유용.
3.3 --exact-match
git describe --exact-match
- 현재 커밋이 태그와 정확히 일치할 때만 태그 이름을 출력.
- 그렇지 않으면 아무 출력도 하지 않음.
4. 사용 예시
git describe # v2.0.0-2-gabc1234
git describe --tags # lightweight 포함
git describe --abbrev=0 # v2.0.0
git describe --exact-match # v2.0.0 (태그된 커밋일 때만)
5. 주의사항
git describe
는 기본적으로 annotated tag만 대상으로 함.- lightweight 태그까지 포함하고 싶으면
--tags
옵션 사용. - 스크립트/자동화에서는 보통
--tags --abbrev=0
조합 사용. - 태그가 없는 경우, 결과가 출력되지 않거나 에러 발생 가능성 있음.
git merge
1. Git Merge란?
git merge
는 다른 브랜치의 변경사항을 현재 브랜치에 병합할 때 사용하는 명령어이다.
2. 기본 형식
git merge <브랜치명>
용어 | 설명 |
---|---|
현재 브랜치 | 병합이 적용될 대상 브랜치 |
| 병합할 소스 브랜치 (변경사항을 가져올 브랜치) |
📌 즉, 현재 브랜치 ← <브랜치명>
의 변경 사항을 병합
3. 사용 예시
git checkout main # main 브랜치로 이동 (병합 대상)
git merge feature/login # feature/login 브랜치를 main에 병합
🧠 의미:feature/login
의 변경사항을 main
브랜치로 가져오겠다는 뜻입니다.
4. 흐름 시각화
main ◀── 병합 ─── feature/login
↑
(HEAD 포인터)
5. 사용 절차
5.1 병합 대상 브랜치로 이동
git checkout main
5.2 병합 수행
git merge feature/login
6. 병합 결과
- ✅ Fast-forward merge: 브랜치가 갈라지지 않았다면 병합 커밋 없이 연결됨
- 🔀 Merge commit: 브랜치가 갈라졌다면 새 병합 커밋이 생성됨
7. 주의사항
항목 | 설명 |
---|---|
HEAD 위치 | 항상 병합될 대상 브랜치에 있어야 함 ( |
충돌 가능성 | 변경사항이 겹치는 경우 conflict 발생 가능 → 수동 해결 필요 |
커밋 전 병합 여부 | 병합 대상 브랜치의 작업이 커밋되지 않았다면 병합되지 않음 |
8. 추가 팁
- 병합 전 현재 브랜치가 최신 상태인지
git pull
로 동기화 권장 - 병합 후에는
git log
또는gitk
로 히스토리 확인 가능 - 병합 전략 지정 시
--no-ff
옵션 사용해 강제로 병합 커밋 생성 가능:
git merge --no-ff feature/login
cherry-pick
1. Git Cherry-pick이란?
git cherry-pick
은 다른 브랜치의 특정 커밋 하나만 골라 현재 브랜치에 적용하는 명령어이다.
"딱 필요한 커밋 하나만 따로 복사해오고 싶을 때" 사용한다.
2. 기본 문법
git cherry-pick <커밋 해시>
예:
git cherry-pick a1b2c3d
3. 시각화 예시
🎯 목적: feature
브랜치의 특정 커밋 C3
만 main
브랜치로 가져오기
📌 기존 상태
main: A---B
\
feature: C1---C2---C3---C4
git checkout main
git cherry-pick C3
📌 결과 상태
main: A---B---C3'
\
feature: C1---C2---C3---C4
🔄
C3'
는C3
와 동일한 내용이지만 다른 커밋 해시를 가진 복제 커밋한다.
4. 여러 커밋 cherry-pick
git cherry-pick <시작해시>^..<끝해시>
예:
git cherry-pick C2^..C4
→ C2, C3, C4를 현재 브랜치로 모두 적용
5. 충돌 발생 시
- 충돌 발생 시 수동 해결 필요
git add .
git cherry-pick --continue
- 중단하고 원래대로 되돌릴 때:
git cherry-pick --abort
6. 사용 예시 요약
상황 | 설명 |
---|---|
🔧 버그 수정 |
|
🎯 기능 분리 | 여러 기능 중 하나만 따로 적용 |
🧪 실험 | 실험용 브랜치에 특정 수정만 적용해서 테스트 |
7. cherry-pick vs merge vs rebase
명령어 | 적용 범위 | 히스토리 영향 | 특징 |
---|---|---|---|
| 전체 브랜치 | O (병합 커밋 생성) | 원본 히스토리 유지 |
| 전체 브랜치 | O (히스토리 수정) | 깔끔한 직선형 히스토리 |
| 개별 커밋 | O (복제 커밋 생성) | 선택 적용 가능 |
8. 주의사항
- 커밋 해시는 같아 보여도 내부적으로 새 커밋(C3′) 이 생성됨
- 여러 번 cherry-pick 시 중복 충돌이 발생할 수 있음
- 동일 커밋을 여러 브랜치에서 사용 시 히스토리 혼동 가능성 있음
git pull --allow-unrelated-histories
1. git pull --allow-unrelated-histories 란?
보통 서로 다른 프로젝트를 하나로 합치거나, 원격 저장소와 로컬 저장소가 서로 공통 조상을 갖지 않을 때 사용한다.
2. 오류 상황 예시
fatal: refusing to merge unrelated histories
🧨 언제 발생하나?
- 로컬에서
git init
으로 새 저장소 생성 후 커밋 - 원격 저장소(GitHub)에 다른 초기 커밋이 존재 (예: README.md)
- 이후
git pull origin main
시 위 오류 발생
3. 해결 방법
git pull origin main --allow-unrelated-histories
- 두 히스토리 병합 강제 수행
- 이후 충돌(conflict)이 발생할 수 있으니 수동으로 해결 필요
4. 사용 예
# 로컬 초기화
git init
git remote add origin https://github.com/user/repo.git
# 강제 병합
git pull origin main --allow-unrelated-histories
5. 주의사항
- 한 번만 사용하면 충분: 병합이 끝나고 연결되면, 이후부터는 일반
git pull
로도 작동합니다. - 병합 충돌 발생 가능성이 크므로 사용 후 커밋 기록 확인 필수
6. 관련 옵션
옵션 | 설명 |
---|---|
| 병합 대신 리베이스로 히스토리 깔끔하게 유지 |
| 병합하되 커밋은 직접 하고 싶을 때 |
| 충돌 시 우선할 히스토리 선택 |
git reset
1. Git Reset 이란?
git reset
은 Git에서 브랜치의 현재 위치(HEAD)를 다른 커밋으로 되돌리거나, 스테이징 상태를 해제하거나, 작업 디렉토리까지 초기화하는 명령어이다.
"방금 했던 커밋/추가/수정... 지우고 다시 하고 싶어!" 할 때 사용한다.
2. reset 동작 범위 비교
옵션 | HEAD 이동 | Staging Area 변경 | 작업 디렉토리 변경 |
---|---|---|---|
| ✅ O | ❌ 그대로 | ❌ 그대로 |
| ✅ O | ✅ 초기화 | ❌ 그대로 |
| ✅ O | ✅ 초기화 | ✅ 완전 초기화 |
3. 시각화 예시
현재 상태:
A---B---C---D (HEAD)
↑
현재 브랜치
git reset --soft B
결과:
A---B (HEAD)
↑
스테이징 영역에는 C, D의 변경사항이 유지됨
git reset --hard B
결과:
A---B (HEAD)
↑
C, D 커밋은 완전히 제거됨 (작업 디렉토리도 초기화)
4. 옵션별 설명
🔹 --soft
git reset --soft <커밋해시>
- 커밋만 되돌림
- 변경사항은 스테이징 상태로 유지됨
📌 사용 예:
커밋 메시지를 실수했을 때, 커밋만 취소하고 다시 커밋하고 싶을 때
🔹 --mixed
(기본 옵션)
git reset --mixed <커밋해시>
- 커밋 & 스테이징만 초기화
- 작업 디렉토리는 그대로 남음
📌 사용 예:
add만 하고 아직 커밋 안 했을 때,
git add
를 되돌리고 싶을 때
🔹 --hard
git reset --hard <커밋해시>
- 커밋, 스테이징, 작업 디렉토리 전부 초기화
📌 사용 예:
모든 변경사항을 완전히 삭제하고 과거 상태로 돌리고 싶을 때
⚠️ 복구 불가한 경우가 많으므로 주의!
5. 실습 예시
# 초기 커밋 3개 생성
echo "a" > a.txt && git add . && git commit -m "A"
echo "b" > b.txt && git add . && git commit -m "B"
echo "c" > c.txt && git add . && git commit -m "C"
git log --oneline
# 마지막 커밋을 취소하고 이전 상태로 복귀
git reset --soft HEAD~1 # C는 스테이징 상태로 돌아감
git reset --mixed HEAD~1 # C는 unstage됨
git reset --hard HEAD~1 # C는 완전히 삭제됨
6. git reset
vs git revert
비교
명령어 | 기존 커밋을 | 새로운 커밋? | 안전성 | 사용처 |
---|---|---|---|---|
| 삭제함 | ❌ X | 위험 | 혼자 쓰는 브랜치, 최근 실수 복구 |
| 보존함 | ✅ O | 안전 | 협업 브랜치, 히스토리 보존 필요 시 |
✅ 요약
옵션 | 설명 | 주의 사항 |
---|---|---|
| 커밋만 취소, staging은 그대로 | 메시지 실수 복구에 유용 |
| 커밋 + staging 취소, 작업물은 유지 | 기본값 |
| 커밋 + staging + 작업물 전부 취소 | 되돌릴 수 없음 *주의 |
revert
git tag
1. Git 태그란?
- **Git 태그(Tag)**는 프로젝트의 커밋 히스토리에서 중요한 지점을 영구적으로 표시하는 기능이다.
- 브랜치와 다르게, 태그는 절대 이동하지 않으며 단순히 커밋을 가리키는 고정 포인터 역할을 한다.
- 주로 버전 릴리즈, 큰 기능 병합 후, 배포 이력 저장 등에 사용된다.
2. 브랜치와 태그의 차이
항목 | 브랜치 | 태그 |
---|---|---|
역할 | 작업을 이어가는 지점 | 이정표(마일스톤) 고정 지점 |
상태 | 계속 이동함 (새 커밋이 생기면 이동) | 고정됨 (절대 이동하지 않음) |
커밋 가능 여부 | 가능 | 불가능 (태그에서 커밋 시 분리된 HEAD) |
대표적 용도 | 기능 개발, 병합 관리 | 릴리즈, 버전 마킹 |
3. 태그 종류
3.1 Lightweight Tag (경량 태그)
- 단순히 커밋을 가리키는 라벨만 붙임
- 메타데이터 없음 (작성자, 날짜, 메시지 등 기록 X)
git tag v1.0.0
3.2 Annotated Tag (주석 태그)
- 릴리즈용으로 사용
- 작성자, 날짜, 메시지 포함. GPG 서명도 가능
git tag -a v1.0.0 -m "Release version 1.0.0"
4. 태그 명령어 모음
4.1 태그 목록 보기
git tag
4.2 특정 커밋에 태그 달기
git tag v1 <커밋해시>
4.3 태그 체크아웃
git checkout v1
- 결과: 분리된 HEAD(detached HEAD) 상태
- → 커밋할 수 없으며, 하려면 새 브랜치를 생성해야 함
git checkout -b new-branch-from-v1
4.4 태그 삭제
git tag -d v1
4.5 원격 저장소에 태그 푸시
git push origin v1
- 모든 태그 푸시
git push origin --tags
4.6 원격에서 태그 삭제
git push origin --delete tag v1
5. git describe: 태그 활용한 위치 설명
5.1 사용법
git describe
- 현재 HEAD에서 가장 가까운 태그 기준으로 현재 커밋을 설명
v1.0.0-2-g9f23a1c
v1.0.0
→ 가장 가까운 태그-2
→ 태그 이후 2번째 커밋g9f23a1c
→ 현재 커밋 해시 요약
6. 주의사항
- 태그는 브랜치처럼 체크아웃할 수 있지만, 작업을 이어갈 수는 없음
- 커밋하려면 새 브랜치를 만들어야 함:
git checkout -b fix-hotbug v1.0.0
7. 태그 사용 예시
# 최신 커밋에 경량 태그
git tag v2.0.0
# 과거 커밋에 주석 태그
git tag -a v1.0.0 <커밋해시> -m "Initial release"
# 태그 확인
git tag
# 태그 푸시
git push origin --tags
✅ 마무리 요약
목적 | 명령어 예시 |
---|---|
태그 생성 |
|
주석 태그 |
|
태그 보기 |
|
태그 푸시 |
|
태그 전체 푸시 |
|
태그 삭제 |
|
원격 태그 삭제 |
|
태그 기준 커밋 설명 |
|
git reflog (git reset 후 커밋 복구)
1. 상황 예시
git reset --hard HEAD~1
이 명령어로 가장 최근 커밋이 삭제되었고, 스테이징/작업 디렉토리도 초기화됨.
2. git reflog
란?
Git에서 브랜치가 가리키던 과거 위치들을 기록해 놓은 로그입니다.
git reflog
실행하면 다음과 같은 출력이 나온다.
c3d9f7b HEAD@{0}: reset: moving to HEAD~1
e7a1b2a HEAD@{1}: commit: 구현 완료
...
→ 이때 HEAD@{1}
이 우리가 잃어버린 커밋이다.
3. 복구 방법
git reset --hard HEAD@{1}
또는 해시값 직접 지정:
git reset --hard e7a1b2a
→ 이 명령으로 삭제된 커밋과 작업 내용 복원 완료!
추가 팁: 안전하게 복원하기
👉 --hard
는 위험하니, 안전하게 복원하려면 브랜치를 새로 만들어서 이전 커밋으로 가도 된다.
git checkout -b recovery HEAD@{1}
📌 정리
명령어 | 설명 |
---|---|
| HEAD, 브랜치 이동 이력 확인 |
| 과거 커밋 상태로 복원 |
| 복구 브랜치 생성 (더 안전) |
병합
Git 브랜치 병합 전략 비교: merge, rebase, cherry-pick
목차
1. 기본 개념 요약
명령어 | 설명 |
---|---|
| 브랜치 간 변경사항을 병합, 병합 커밋 생성 |
| 커밋 기반을 다른 브랜치 위로 옮겨 이력 재정렬 |
| 특정 커밋만 골라 현재 브랜치에 복사 |
2. 명령어별 상세 설명
git merge <브랜치명>
- 역할: 다른 브랜치의 변경 내용을 현재 브랜치에 병합
- 병합 커밋을 만들어 두 브랜치의 내용을 하나로 합침
git checkout main # 병합 대상 브랜치
git merge feature/login # 병합할 소스 브랜치
- 💡 즉:
main ← feature/login
병합됨
git rebase <브랜치명>
- 역할: 현재 브랜치 커밋을
<브랜치명>
위로 옮김 - 커밋이 새로 복사되어 SHA 변경
- 병합 커밋 없이 깔끔한 직선형 이력 생성
git checkout feature/login
git rebase main
- 💡 즉:
feature/login
을main
기준으로 다시 쌓음
git cherry-pick <커밋해시>
- 역할: 특정 커밋 하나를 현재 브랜치로 가져옴
- 전체 브랜치를 병합하지 않고 선택적 반영
git checkout main
git cherry-pick 7a1f3b2
3. 커밋 이력 비교
merge
A---B---C---M (main)
\ /
D---E (feature)
rebase
A---B---C---D'---E' (feature rebased onto main)
cherry-pick
main: A---B---C---E'
feature: D---E
4. 적합한 상황
상황 | 추천 명령어 |
---|---|
팀 프로젝트에서 병합 이력 유지 |
|
개인 작업 커밋 정리 |
|
특정 버그 수정만 따로 반영 |
|
5. 주의사항
merge
: 병합 커밋으로 이력이 복잡해질 수 있음rebase
: 협업 중인 브랜치에 사용 금지 (이력 충돌)cherry-pick
: 동일 커밋이 중복될 수 있음
6. 요약 표
항목 | merge | rebase | cherry-pick |
---|---|---|---|
대상 | 브랜치 전체 | 브랜치 전체 | 특정 커밋 |
이력 변경 여부 | ❌ (유지) | ✅ (SHA 변경됨) | ✅ (선택적 커밋 복사) |
병합 커밋 | 생성됨 | 생성 안됨 | 없음 |
협업 안정성 | ✅ 안전 | ⚠️ 위험 | ✅ 안전 |
7. 시각적 예제
# 예제 환경 구성
git init
echo "A" > f.txt && git add . && git commit -m "A"
echo "B" >> f.txt && git commit -am "B"
git checkout -b feature
echo "C" >> f.txt && git commit -am "C"
git checkout main
echo "D" >> f.txt && git commit -am "D"
merge
git merge feature
rebase
git checkout feature
git rebase main
cherry-pick
git log --oneline # 커밋 해시 확인
git cherry-pick <커밋 해시>
8. 추가 명령어: revert
, reset
, stash
명령어 | 역할 | 주 사용 목적 |
---|---|---|
| 특정 커밋을 취소하는 새 커밋 생성 | 실수한 커밋을 안전하게 되돌림 |
| 커밋 이력/스테이징/작업 폴더 상태를 되돌림 | 브랜치나 파일을 과거 상태로 복구 |
| 현재 작업을 임시로 저장 | 급히 브랜치를 바꿔야 할 때 |
# revert: 안전한 취소
git revert <커밋 해시>
# reset: 이력 되돌리기
git reset --soft HEAD~1 # 커밋만 되돌림
git reset --hard HEAD~1 # 작업 내용까지 삭제
# stash: 현재 작업 저장
git stash
git stash pop
구조
Git 내부 구조 (Basic)
1. Git은 파일 버전이 아닌 스냅샷 시스템
Git은 "변경점(diff)"이 아니라, 전체 프로젝트의 스냅샷(상태)을 저장한다.
커밋 하나 = 전체 폴더의 압축 스냅샷 (단, 중복은 자동 제거됨)
2. Git의 3대 영역
작업 디렉토리 → 스테이징 영역 → 로컬 저장소
(Working Directory) (Staging/Index) (Repository/.git)
코드 작성 git add git commit
영역 | 설명 |
---|---|
작업 디렉토리 | 실제로 코드 작성/수정하는 공간 |
스테이징 영역 (Index) | 커밋할 파일을 담아두는 임시 공간 ( |
로컬 저장소 | 커밋이 저장되는 |
3. 주요 Git 내부 객체
Git은 4가지 핵심 객체로 이루어져 있습니다:
객체 | 설명 | 예시 |
---|---|---|
🔹 Blob | 파일 내용 저장 (binary large object) |
|
🔸 Tree | 디렉토리 구조와 파일 리스트 | 폴더 구조 |
🔹 Commit | 커밋 메타데이터 + 부모 커밋 + tree | "커밋 메시지" |
🔸 Tag | 특정 커밋에 이름 부여 | v1.0.0 |
📦 커밋은 tree를 가리키고, tree는 blob들을 가리킵니다.
[commit]
|
v
[tree]
├── [blob] hello.txt
└── [blob] app.js
4. HEAD란?
HEAD → 현재 체크아웃한 브랜치 or 커밋
- 보통은
HEAD → main
git checkout
하면 HEAD가 다른 커밋을 가리킴git reset
은 HEAD의 위치를 옮기는 것
5. 브랜치란?
브랜치는 단지 커밋을 가리키는 포인터이다.
A---B---C ← main (브랜치)
↑
HEAD
- 브랜치를 옮긴다 → 포인터 이동
- 커밋한다 → 현재 브랜치가 가리키는 곳에서 새로운 커밋 추가
6. Reflog란?
git reflog
→ HEAD와 브랜치가 가리키던 이전 위치들의 로그
reset
이나checkout
후에도 추적 가능- 내부적으로 Git은 HEAD의 이동을 계속 추적함
7. .git 디렉토리 구조 요약
.git/
├── objects/ ← 커밋, 트리, 블롭, 태그 객체 저장소
├── refs/ ← 브랜치, 태그 등의 포인터
├── HEAD ← 현재 가리키는 브랜치
├── index ← 스테이징 정보
├── logs/ ← reflog 정보 저장
└── config ← Git 설정
📌 정리
개념 | 설명 |
---|---|
Commit | 전체 스냅샷 + 부모 커밋 정보 |
Blob | 파일 내용 저장 |
Tree | 폴더 구조 |
Branch | 커밋을 가리키는 포인터 |
HEAD | 현재 브랜치 or 커밋 |
Staging Area | 다음 커밋을 준비하는 공간 |
Reflog | HEAD의 이동 이력 추적 가능 (복구에 유용) |
Git 내부 구조 (Advanced)
1. 🔐 Git 객체의 SHA-1 해시 구조
1.1 개요
Git은 모든 객체(blob, tree, commit 등)를 SHA-1 해시 값을 통해 식별한다.
하나의 커밋은 고유한 40자리 16진수 해시로 구분됨
1.2 예시
e83c5163... ← 커밋, 블롭, 트리 모두 이 해시값으로 관리됨
1.3 내부 생성 방식
- Git은 객체의 타입 + 크기 + 내용을 문자열로 만듦
예:blob 12\0Hello World\n
- 이를 SHA-1으로 해싱하여 파일 이름으로 저장
echo "Hello World" | git hash-object --stdin
→ 557db03de997c86a4a028e1ebd3a1ceb225be238
2. Git의 packfile 압축 구조
2.1 개요
Git은 수천 개의 객체를 .git/objects
디렉토리에 저장하지만, 리포지토리가 커지면 성능 저하가 발생합니다. 이를 해결하기 위해 **packfile(.pack)**을 사용합니다.
2.2 packfile이란?
여러 Git 객체를 압축하고 델타(차이) 형태로 저장한 파일
2.3 저장 구조
.git/
└── objects/
├── pack/
│ ├── pack-xxxxx.pack ← 실제 압축된 객체
│ └── pack-xxxxx.idx ← 인덱스 파일
2.4 생성 명령어
git gc # 자동으로 packfile 생성 (garbage collection)
2.5 특징
특징 | 설명 |
---|---|
공간 절약 | 비슷한 파일은 델타 방식으로 저장됨 |
빠른 복사 | clone, fetch, push 성능 향상 |
불변성 보장 | packfile 내 객체는 변경 불가, 안전함 |
3. Git vs SVN 비교
항목 | Git | SVN |
---|---|---|
저장 방식 | 분산 버전 관리 (DVCS) | 중앙 집중식 (CVCS) |
커밋 저장소 | 로컬과 원격 모두 | 중앙 서버 |
브랜치 | 가볍고 빠름 (포인터) | 디렉토리 복사 방식 |
네트워크 필요 여부 | X (로컬 커밋 가능) | O (항상 서버 접속 필요) |
속도 | 빠름 (로컬 기반) | 느림 (서버 기반) |
merge & rebase | 고급 기능 다양 | 제한적 기능 |
사용 예 | GitHub, GitLab, OSS 등 | 일부 기업 내부 시스템 |
3.1 핵심 차이
| Git은 로컬에서도 모든 기능 사용 가능, 브랜치가 lightweight
→ 오프라인, 분기 많은 프로젝트에 최적화
| SVN은 중앙 서버 기반으로 단순하고 통제된 작업에 적합
→ 사내 규칙이 명확한 환경에 적합
요약
주제 | 요점 |
---|---|
SHA-1 해시 | Git 객체는 타입+내용 기반으로 해시 생성 |
packfile | 성능 최적화를 위한 객체 압축 저장소 |
Git vs SVN | Git은 분산 & 유연, SVN은 중앙 & 단순 |
commit 생성시 .git 내부 변화
시나리오
hello.txt
파일 생성git add hello.txt
git commit -m "Add hello"
1. 작업 디렉토리 (Working Directory)
echo "Hello Git" > hello.txt
- 파일 생성됨
- 아직 Git은 이 파일을 추적하지 않음
2. git add hello.txt
git add hello.txt
내부 변화:
구성요소 | 변화 내용 |
---|---|
| 스테이징 영역에 파일 등록됨 (경로, 해시, 권한 등 저장) |
|
의 내용이
객체로 저장됨 (SHA-1 해시 기반) |
📦 예시 구조:
.git/
└── objects/
└── 3a/
└── 3efbed4aef... ← hello.txt의 blob 객체
3. git commit -m "Add hello"
내부 변화:
.git/objects/
객체 | 내용 |
---|---|
객체 | 커밋 당시의 디렉토리 구조 (hello.txt 포함) |
객체 | 커밋 메시지, 트리 포인터, 작성자 등 메타데이터 포함 |
.git/objects/
├── 3a/...(blob)
├── 47/... (tree)
└── a1/... (commit)
.git/refs/heads/main
- 브랜치 포인터가 새 커밋 해시로 갱신됨
refs/heads/main → a1b2c3d4e5...
.git/HEAD
- 여전히
ref: refs/heads/main
상태 → main 브랜치를 따라감
.git/logs/HEAD & logs/refs/heads/main
- 커밋 전후
HEAD
포인터 변경 이력 추가됨 (reflog)
0000000 → a1b2c3d4 Commit: Add hello
전체 흐름 (커밋 1회 시)
📁 Working Directory ← hello.txt 생성
↓ git add
📂 .git/index ← 스테이징 정보 저장
↓ git commit
📦 .git/objects/
├── blob (파일 내용)
├── tree (디렉토리 구조)
└── commit (메타데이터)
📄 .git/refs/heads/main ← 브랜치 → 커밋 연결
↑
📌 .git/HEAD ← 현재 브랜치 추적
🕓 .git/logs/ ← HEAD/브랜치 이력 추적
실제 파일 (커밋 후)
cat .git/HEAD
# ref: refs/heads/main
cat .git/refs/heads/main
# a1b2c3d4e5...
git ls-tree HEAD
# 100644 blob 3a3efbed... hello.txt
git cat-file -p <커밋해시>
# tree 47fa...
# author ...
# message: Add hello
요약
단계 | 설명 |
---|---|
| blob 객체 생성 + index 등록 |
| tree + commit 객체 생성, 브랜치 포인터 이동 |
| objects, refs, HEAD, logs 전부 갱신 |
Git 명령어에 따른 .git 내부 구조 변화(1부)
1. git merge
시 내부 변화
1.1 예시 명령어
git checkout main
git merge feature
1.2 .git
내부 변화
구성 요소 | 변화 내용 |
---|---|
| 병합 결과로 새로운 merge commit 객체 생성 |
| 브랜치 포인터가 merge 커밋으로 이동 |
| 여전히 |
| 병합 대상 커밋( |
| HEAD의 이동 이력 반영됨 (reflog) |
1.3 도식 예시
A---B---C ← main
\
D---E ← feature
▶ git merge feature
결과:
A---B---C-------M (merge commit) ← main, HEAD
\ /
D---E
2. git rebase
시 내부 변화
2.1 예시 명령어
git checkout feature
git rebase main
2.2 .git
내부 변화
구성 요소 | 변화 내용 |
---|---|
|
|
| 브랜치가 새 커밋들로 덮어씀 |
| 리베이스 기준 커밋을 기록 |
| 여전히 |
| HEAD의 커밋 재작성 이력 반영됨 |
2.3 도식 예시
main: A---B---C
feature: D---E
▶ git rebase main
결과:
main: A---B---C
feature: D'---E' ← HEAD
원래 커밋 D, E는 삭제되지 않고
.git/objects
에 보존됨
3. git reset
시 내부 변화
3.1 예시 명령어
git reset --hard HEAD~1
3.2 .git
내부 변화
구성 요소 | 변화 내용 |
---|---|
| 브랜치 포인터가 이전 커밋으로 이동 |
| 여전히 |
| 되돌린 커밋 시점으로 스테이징 영역 초기화 |
작업 디렉토리 |
|
| 이전 HEAD 커밋 해시를 저장 |
| 이동 전후 이력 기록됨 |
3.3 도식 예시
A---B---C ← main, HEAD
↑
ORIG_HEAD
▶ git reset --hard B
결과:
A---B ← main, HEAD
4. 특수 HEAD 파일 요약
파일 이름 | 생성 시점 | 설명 |
---|---|---|
|
| 병합 대상 커밋 해시 저장 |
|
| 기준 커밋 해시 저장 |
|
| 리셋 전 커밋 백업 |
|
| 원격에서 받아온 커밋들 정보 |
|
| 적용 대상 커밋 기록 |
5. 요약 비교표
명령어 | 커밋 이동 | 브랜치 이동 | HEAD 변경 | 디렉토리 영향 | 특수 파일 생성 |
---|---|---|---|---|---|
| ⭕ | ⭕ | ⭕ | 충돌 시 변동 있음 |
|
| ⭕ (rewrite) | ⭕ | ⭕ | 충돌 시 변동 있음 |
|
| ⭕ (이전 커밋으로) | ⭕ | ⭕ | ✔️ 완전 초기화 |
|
Git 명령어에 따른 .git 내부 구조 변화 (2부)
4. git stash
시 내부 변화
4.1 예시 명령어
git stash
4.2 .git
내부 변화
구성 요소 | 변화 내용 |
---|---|
| 현재 작업 상태(스냅샷)가 |
| 새로운 stash가 추가된 로그 생성 |
| 가장 최신 stash를 가리키는 포인터 (없으면 새로 생성됨) |
.git/
├── objects/ ← stash 내용 포함 커밋 객체 추가
├── refs/stash ← 최신 stash 참조
├── logs/refs/stash ← stash 이력 저장
4.3 도식 예시
main: A---B---C
↑
HEAD / index
▶ git stash
결과:
- 워킹 디렉토리와 인덱스 초기화됨
- .git/refs/stash → stash 커밋 가리킴
5. git cherry-pick
시 내부 변화
5.1 예시 명령어
git cherry-pick a1b2c3d
5.2 .git
내부 변화
구성 요소 | 변화 내용 |
---|---|
| cherry-pick된 커밋 내용 기반으로 새 커밋 객체 생성 |
| 대상 커밋의 해시 저장 (충돌 발생 시 사용됨) |
| 현재 브랜치에 새 커밋 추가 |
| 병합 결과 반영 |
5.3 도식 예시
main: A---B---C ← HEAD
feature: D---E ← cherry-pick 대상
▶ git cherry-pick E
결과:
main: A---B---C---E' ← HEAD
E와 동일한 내용이지만 새 커밋 E′가 만들어짐
6. git revert
시 내부 변화
6.1 예시 명령어
git revert C
6.2 .git
내부 변화
구성 요소 | 변화 내용 |
---|---|
| revert용 새 커밋 객체 생성 |
| C의 반대 연산 내용 반영 |
| 새 커밋으로 이동 |
revert
는 원본 커밋을 삭제하지 않고, "반대로 되돌리는" 커밋을 추가한다.
6.3 도식 예시
A---B---C ← HEAD
▶ git revert C
결과:
A---B---C---C' ← HEAD (C를 무효화하는 커밋)
7. 특수 파일 요약 (2부)
파일 이름 | 생성 명령어 | 설명 |
---|---|---|
|
| 적용 중인 커밋 해시 저장 (충돌 시 사용) |
|
| revert 진행 중인 커밋 정보 |
|
| 가장 최근 stash 참조 |
|
| stash 추가 이력 저장 |
8. 요약 비교표 (2부)
명령어 | 새 커밋 생성 | 기존 커밋 삭제 | HEAD 이동 | 특수 파일 | 비고 |
---|---|---|---|---|---|
| O (임시 커밋) | ❌ | ❌ |
| 작업 보관 |
| O | ❌ | O |
| 선택 커밋 복사 |
| O | ❌ | O |
| 기존 커밋 반전 |
도식화
1. 전체 구조 개요
.git/
├── HEAD ← 현재 가리키는 브랜치 (예: ref: refs/heads/main)
├── config ← 로컬 Git 설정
├── description ← 주로 bare repo에서 사용
├── index ← 스테이징 영역 정보 (트래킹 중인 파일 목록)
├── objects/ ← Git 객체 저장소 (blob, tree, commit, tag)
│ ├── xx/xxxx... ← SHA-1 해시로 저장된 개별 객체
│ └── pack/ ← 압축된 객체 저장소 (.pack, .idx)
├── refs/ ← 브랜치, 태그 등 참조(포인터)
│ ├── heads/ ← 브랜치 참조 (예: main, feature)
│ ├── remotes/ ← 원격 브랜치 정보 (예: origin/main)
│ └── tags/ ← 태그 정보
├── logs/ ← HEAD 및 refs의 이동 이력 (reflog 저장소)
│ ├── HEAD
│ └── refs/
├── info/ ← exclude 설정 등 부가 정보
└── hooks/ ← 커밋, 푸시 등 Git 이벤트용 스크립트
2. 각 구성 요소 설명
🔹 .git/HEAD
- 현재 Git이 바라보는 위치
- 대부분
ref: refs/heads/main
형태 - HEAD → 브랜치 → 커밋
🔹 .git/objects/
- Git의 핵심: 모든 파일/폴더/커밋을 SHA-1 해시값으로 저장
- 하위 폴더 + 해시 기반 객체들
.git/objects/
├── a7/...
├── d1/...
└── pack/ ← packfile 압축 저장소
🔹 .git/refs/
- 브랜치/태그가 어떤 커밋을 가리키는지 저장
.git/refs/heads/main → a1b2c3d4e5 (커밋 해시)
🔹 .git/logs/
git reflog
명령에서 쓰이는 내부 이력HEAD
,branches
,remotes
이동 내역 저장
🔹 .git/index
- 스테이징 영역(index)의 내부 상태를 저장하는 바이너리 파일
git add
→ index에 등록 →git commit
때 커밋됨
🔹 .git/hooks/
- 커밋/푸시/머지 전후에 실행되는 자동화 스크립트
pre-commit, post-commit, pre-push 등
3. 핵심 흐름
📁 Working Directory
↓ git add
📂 .git/index (Staging Area)
↓ git commit
📦 .git/objects/ (커밋, 트리, 블롭 저장)
↓ 브랜치 포인터 이동
📄 .git/refs/heads/main
↑ HEAD → 현재 브랜치 참조
요약
구성요소 | 설명 |
---|---|
| 현재 브랜치 또는 커밋을 가리킴 |
| 브랜치/태그 → 커밋 연결 |
| 모든 데이터(SHA-1 기반) 저장소 |
| 스테이징 상태 추적 |
| HEAD 및 브랜치 이동 이력 (reflog) |
| Git 이벤트 발생 시 실행되는 스크립트 |
마인드맵
Git 내부 구조
├── 1. Working Directory
│ └── 실제 작업 공간 (코드 작성, 수정)
│
├── 2. Index (Staging Area) ← .git/index
│ └── git add로 관리됨
│
├── 3. Local Repository (.git/)
│ ├── 3.1 objects/
│ │ ├── blob: 파일 내용
│ │ ├── tree: 디렉토리 구조
│ │ └── commit: 스냅샷 + 부모 참조 + 메타
│ │
│ ├── 3.2 refs/
│ │ ├── heads/: 브랜치 포인터
│ │ ├── remotes/: 원격 브랜치
│ │ └── tags/: 태그 포인터
│ │
│ ├── 3.3 HEAD
│ │ ├── 현재 브랜치 참조 (예: ref: refs/heads/main)
│ │ └── detached 상태 가능
│ │
│ ├── 3.4 logs/
│ │ └── HEAD 및 refs의 이동 이력 (reflog)
│ │
│ ├── 3.5 config
│ │ └── 사용자 설정 정보
│ │
│ ├── 3.6 hooks/
│ │ └── pre-commit, post-commit 등 자동화 스크립트
│ │
│ └── 3.7 특수 HEAD 파일
│ ├── MERGE_HEAD ← merge 중 생성
│ ├── REBASE_HEAD ← rebase 중 생성
│ ├── ORIG_HEAD ← reset 전 위치 백업
│ ├── CHERRY_PICK_HEAD ← cherry-pick 중 충돌 시
│ ├── REVERT_HEAD ← revert 충돌 시
│ └── FETCH_HEAD ← fetch 결과
│
├── 4. 명령어 동작 흐름
│ ├── git add
│ │ └── 파일 → index 등록
│ ├── git commit
│ │ ├── index → commit 객체 생성
│ │ └── 브랜치 포인터 → 새 커밋
│ ├── git reset
│ │ ├── HEAD/브랜치 포인터 이동
│ │ └── --hard 시 index + 작업 디렉토리도 초기화
│ ├── git merge
│ │ ├── merge commit 생성
│ │ └── MERGE_HEAD 기록
│ ├── git rebase
│ │ ├── 커밋 재작성 (rewrite)
│ │ └── REBASE_HEAD 기록
│ ├── git cherry-pick
│ │ ├── 커밋 복사
│ │ └── CHERRY_PICK_HEAD 기록
│ ├── git revert
│ │ ├── 반전 커밋 추가
│ │ └── REVERT_HEAD 기록
│ └── git stash
│ ├── 현재 상태를 임시 커밋으로 보관
│ ├── refs/stash 생성
│ └── logs/refs/stash 이력 저장
│
└── 5. 복구 및 확인
├── git reflog → HEAD, 브랜치 이동 이력 추적
├── git log → 커밋 히스토리
├── git cat-file -p <해시> → 객체 내용 확인
└── git fsck → 저장소 무결성 점검
요약
키워드 | 의미 |
---|---|
blob | 파일 내용 |
tree | 폴더 구조 |
commit | 전체 스냅샷 |
HEAD | 현재 위치 추적 포인터 |
refs | 브랜치/태그가 가리키는 대상 |
logs | HEAD/브랜치 이동 기록 (reflog) |
index | 커밋 준비 상태 저장 |
stash | 작업 보관소 (임시 커밋) |