[Git] 내가보려고 만든 Git


초기 세팅

초기 세팅

Git 로컬 작업 폴더 원격 저장소에 연결하기 (HTTPS 방식 기준)


1. 로컬 Git 저장소 초기화 및 원격 연결

1.1 Git 초기화

git init

1.2 원격 저장소 연결

git remote add origin https://github.com/사용자명/저장소명.git

2. GitHub Personal Access Token(PAT) 사용

GitHub는 2021년부터 비밀번호 인증을 중단하고 토큰(PAT) 인증 방식만 허용함


2.1 토큰 발급 방법

  1. GitHub 로그인
  2. 우측 상단 → Settings > Developer settings > Personal access tokens
  3. Tokens (classic)Generate new token
  4. repo, workflow 등의 권한 선택 후 생성

2.2 토큰 저장 방법

방법 1: Git 사용 시 직접 입력

git push origin main

방법 2: 캐시 저장

git config --global credential.helper store

3. Git 기본 명령어 흐름

3.1 기존 원격 저장소 내용 가져오기 (선택)

git pull origin main --allow-unrelated-histories

3.2 작업 파일 스테이징

git add .

3.3 커밋

git commit -m "커밋 메시지"

3.4 원격 저장소에 푸시

git push -u origin main

✅ 최초 연결시

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란?


2. SSH 키 생성

ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

생성 결과:

→ 기존 키가 있다면 -f ~/.ssh/파일명 옵션으로 이름을 바꿔 생성


3. SSH 공개키 GitHub에 등록

  1. 공개키 복사:
cat ~/.ssh/id_rsa.pub
  1. GitHub 접속
    Settings > SSH and GPG Keys > New SSH Key
  2. 제목 입력 후 키 붙여넣기 → 저장

4. SSH 연결 테스트

ssh -T git@github.com
Hi username! You've successfully authenticated, but GitHub does not provide shell access.

5. 원격 저장소 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

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

7.4 연결 테스트

ssh -T github.com-work

✅ 보안 팁


8. GitHub에 SSH 키 자동으로 추가하는 스크립트

8.1 필요 조건


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 사용 방법

  1. 위 스크립트를 add_ssh_key.sh로 저장
  2. 실행 권한 부여:
chmod +x add_ssh_key.sh
  1. 실행:
./add_ssh_key.sh

✅ 실행되면 GitHub 계정에 SSH 키가 자동 등록됨


9. SSH 키 백업 및 복구 방법

9.1 백업 방법

mkdir -p ~/backup_ssh_keys
cp ~/.ssh/id_rsa* ~/backup_ssh_keys/

9.2 복구 방법

  1. 복사한 키 파일을 다시 ~/.ssh 디렉토리에 복원
cp ~/backup_ssh_keys/id_rsa* ~/.ssh/
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
  1. 퍼미션 문제 방지:
    • id_rsa: 600 (읽기/쓰기)
    • id_rsa.pub: 644 (읽기 가능)

9.3 권한 오류 방지

chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub

✅ 팁





.gitignore

.gitignore

.gitignore 설정


1. .gitignore란?


2. 작성 위치


3. 패턴 작성법

3.1 기본 규칙

패턴

설명

*.log

.log

확장자 파일 전체 무시

build/

build

디렉토리 무시

/secret.txt

루트 경로의

secret.txt

만 무시

*.pem

.pem

인증서 파일 전체 무시

!.gitignore

.gitignore

파일은 무시하지 않음


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 생성 도구 추천


✅ 참고 팁



.gitignore

.gitignore 템플릿


1. 공식 템플릿 저장소

📦 github/gitignore

✅ 사용 예시

curl -o .gitignore https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore

2. 자동 생성 도구

🛠 Toptal Gitignore Generator


3. 추천 템플릿 목록

🔷 Node.js

node_modules/
.env
dist/
npm-debug.log*

참고: Node.gitignore 또는 Node + macOS + VSCode


🐍 Python

__pycache__/
*.py[cod]
*.sqlite3
.env

참고: Python.gitignore + Global/Windows.gitignore


☕ Java (Maven/Gradle/IDE 포함)

*.class
*.jar
*.war
target/
*.iml
.idea/
*.log

참고: Java.gitignore + Global/JetBrains.gitignore


💡 VS Code 전용

.vscode/
.history/

참고: Global/VisualStudioCode.gitignore


🐳 Docker 프로젝트

docker-compose.override.yml
.env
*.pid
*.bak
*.swp

참고: 직접 구성 또는 Docker.gitignore


4. 커스터마이징 팁


✅ 정리

목적

추천 소스

빠른 템플릿 찾기

github/gitignore

자동 생성 도구

Toptal Gitignore Generator

로컬 전용 제외

.git/info/exclude 사용



명령어

명령어

HEAD vs main (+특수 HEAD 종류 정리)


1. 개요

용어

역할

예시

HEAD

현재 작업 중인 커밋을 가리키는 포인터

HEAD → main 또는 HEAD → <커밋 해시>

main

기본 브랜치 이름 (Git 2.28+ 기본 브랜치)

main → C3 커밋


2. 개념 비교

항목

HEAD

(포인터)

main

(브랜치)

정체

특수 포인터

이름 있는 참조

용도

"현재 내가 작업 중인 위치" 추적

커밋들을 연결하는 선

이동 가능성

하나만 존재, 항상 이동함

여러 브랜치 중 하나, 직접 이동 안 함

Git 명령어 관련

reset, checkout, reflog

merge, push, checkout 대상

실제 저장 위치

.git/HEAD

.git/refs/heads/main


3. 시각적 예시

A---B---C---D
         ↑
       main
         ↑
       HEAD

4. HEAD의 두 가지 상태

상태

설명

결과

Attached HEAD

HEAD가 브랜치를 가리킴

✅ 정상 상태 (

HEAD → main

)

Detached HEAD

HEAD가 특정 커밋 해시를 직접 가리킴

🌀 브랜치가 아님, 새 커밋은 임시 상태

git checkout main       # HEAD → main
git checkout a1b2c3d    # HEAD → a1b2c3d (Detached)

5. 관련 명령어

명령어

설명

git symbolic-ref HEAD

HEAD가 가리키는 브랜치 경로 확인

cat .git/HEAD

HEAD 내용 확인 (

ref: refs/heads/main

)

git log

HEAD 기준 커밋 히스토리 확인

git reflog

HEAD 이동 이력 추적 (복구용)


6. 요약 비교표

구분

HEADmain

유형

포인터 (현재 위치)

브랜치 이름

갯수

항상 1개

여러 개 가능

의미

현재 체크아웃된 브랜치/커밋

브랜치(커밋 선형 연결)

이동 가능 여부

명령어로 이동 가능

직접 이동 불가 (커밋 시 이동)


7. 특수 HEAD 종류 정리

이름

설명

HEAD

현재 작업 중인 커밋 (or 브랜치) 포인터

FETCH_HEAD

git fetch 시 받아온 원격 커밋 참조

MERGE_HEAD

git merge진행 중, 병합 대상 커밋 참조

ORIG_HEAD

직전의 HEAD가 가리키던 위치 백업 (ex. reset 이전 커밋)

CHERRY_PICK_HEAD

cherry-pick도중 충돌 시 저장되는 대상 커밋

REBASE_HEAD

rebase 도중 기준이 되는 커밋 저장


8. 활용 예시

git reset --hard ORIG_HEAD   # 직전 상태로 롤백

git merge feature            # 병합 시 MERGE_HEAD 생성됨
cat .git/MERGE_HEAD          # 병합 대상 커밋 확인

git fetch origin             # FETCH_HEAD 갱신
cat .git/FETCH_HEAD

요약

.git/HEAD

현재 위치 추적

.git/ORIG_HEAD

reset/merge 전 원래 HEAD

.git/FETCH_HEAD

fetch로 받아온 최신 원격 커밋 위치

.git/MERGE_HEAD

merge 병합 대상 커밋



명령어

Git 명령어 정리


1. Git Commit

1.1 개념

1.2 명령어

git commit

2. Git Branch

2.1 개념

2.2 명령어

git branch -f <branch>
git checkout <branch>  # 브랜치로 이동

3. Git Merge

3.1 개념

3.2 명령어

git merge <branch>

4. Git Rebase

4.1 개념

4.2 명령어

git rebase <branch>

5. Git Checkout

5.1 개념

5.2 명령어

git checkout <branch or commit>

6. 상대 참조 (Relative Reference)

6.1 기호 설명

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 개념

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 개념

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 개념

13.2 특징

13.3 예시

git remote
git checkout origin/main

14. Git Fetch

14.1 개념

14.2 명령어

git fetch <remote>

15. Git Pull

15.1 개념

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란?


2. 기본 출력 형식

<tag>_<N>_g<short-hash>

항목

설명

<tag>

가장 가까운 태그 이름

<N>

태그 이후 몇 번째 커밋인지 (0이면 태그 본인)

g<해시>

해당 커밋의 Git short hash


3. 자주 쓰는 옵션

3.1 --tags

git describe --tags

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 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. 병합 결과


7. 주의사항

항목

설명

HEAD 위치

항상 병합될 대상 브랜치에 있어야 함 (git checkout <대상브랜치>)

충돌 가능성

변경사항이 겹치는 경우 conflict 발생 가능 → 수동 해결 필요

커밋 전 병합 여부

병합 대상 브랜치의 작업이 커밋되지 않았다면 병합되지 않음


8. 추가 팁

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 브랜치의 특정 커밋 C3main 브랜치로 가져오기


📌 기존 상태

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. 사용 예시 요약

상황

설명

🔧 버그 수정

main에서 수정한 버그 커밋을 release 브랜치에도 적용

🎯 기능 분리

여러 기능 중 하나만 따로 적용

🧪 실험

실험용 브랜치에 특정 수정만 적용해서 테스트


7. cherry-pick vs merge vs rebase

명령어

적용 범위

히스토리 영향

특징

merge

전체 브랜치

O (병합 커밋 생성)

원본 히스토리 유지

rebase

전체 브랜치

O (히스토리 수정)

깔끔한 직선형 히스토리

cherry-pick

개별 커밋

O (복제 커밋 생성)

선택 적용 가능


8. 주의사항



명령어

git pull --allow-unrelated-histories


1. git pull --allow-unrelated-histories 란?

--allow-unrelated-histories는 Git에서 서로 연관되지 않은 두 히스토리를 강제로 병합할 때 사용하는 옵션이다.

보통 서로 다른 프로젝트를 하나로 합치거나, 원격 저장소와 로컬 저장소가 서로 공통 조상을 갖지 않을 때 사용한다.


2. 오류 상황 예시

fatal: refusing to merge unrelated histories

🧨 언제 발생하나?


3. 해결 방법

git pull origin main --allow-unrelated-histories

4. 사용 예

# 로컬 초기화
git init
git remote add origin https://github.com/user/repo.git

# 강제 병합
git pull origin main --allow-unrelated-histories

5. 주의사항


6. 관련 옵션

옵션

설명

--rebase

병합 대신 리베이스로 히스토리 깔끔하게 유지

--no-commit

병합하되 커밋은 직접 하고 싶을 때

--strategy=ours / theirs

충돌 시 우선할 히스토리 선택




명령어

git reset


1. Git Reset 이란?

git reset은 Git에서 브랜치의 현재 위치(HEAD)를 다른 커밋으로 되돌리거나, 스테이징 상태를 해제하거나, 작업 디렉토리까지 초기화하는 명령어이다.

"방금 했던 커밋/추가/수정... 지우고 다시 하고 싶어!" 할 때 사용한다.


2. reset 동작 범위 비교

옵션

HEAD 이동

Staging Area 변경

작업 디렉토리 변경

--soft

✅ O

❌ 그대로

❌ 그대로

--mixed

✅ O

✅ 초기화

❌ 그대로

--hard

✅ 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 비교

명령어

기존 커밋을

새로운 커밋?

안전성

사용처

reset

삭제함

❌ X

위험

혼자 쓰는 브랜치, 최근 실수 복구

revert

보존함

✅ O

안전

협업 브랜치, 히스토리 보존 필요 시


✅ 요약

옵션

설명

주의 사항

--soft

커밋만 취소, staging은 그대로

메시지 실수 복구에 유용

--mixed

커밋 + staging 취소, 작업물은 유지

기본값

--hard

커밋 + staging + 작업물 전부 취소

되돌릴 수 없음 *주의



명령어

revert

명령어

git tag


1. Git 태그란?


2. 브랜치와 태그의 차이

항목

브랜치

태그

역할

작업을 이어가는 지점

이정표(마일스톤) 고정 지점

상태

계속 이동함 (새 커밋이 생기면 이동)

고정됨 (절대 이동하지 않음)

커밋 가능 여부

가능

불가능 (태그에서 커밋 시 분리된 HEAD)

대표적 용도

기능 개발, 병합 관리

릴리즈, 버전 마킹


3. 태그 종류

3.1 Lightweight Tag (경량 태그)

git tag v1.0.0

3.2 Annotated Tag (주석 태그)

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
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
v1.0.0-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 tag v1.0.0

주석 태그

git tag -a v1.0.0 -m "메시지"

태그 보기

git tag

태그 푸시

git push origin v1.0.0

태그 전체 푸시

git push origin --tags

태그 삭제

git tag -d v1.0.0

원격 태그 삭제

git push origin --delete tag v1.0.0

태그 기준 커밋 설명

git describe



명령어

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}

📌 정리

명령어

설명

git reflog

HEAD, 브랜치 이동 이력 확인

git reset --hard HEAD@{n}

과거 커밋 상태로 복원

git checkout -b <이름> HEAD@{n}

복구 브랜치 생성 (더 안전)




병합

병합

Git 브랜치 병합 전략 비교: merge, rebase, cherry-pick


목차

  1. 기본 개념 요약
  2. 명령어별 상세 설명
  3. 커밋 이력 비교
  4. 적합한 상황
  5. 주의사항
  6. 요약 표
  7. 시각적 예제
  8. 추가 명령어: revert, reset, stash

1. 기본 개념 요약

명령어

설명

merge

브랜치 간 변경사항을 병합, 병합 커밋 생성

rebase

커밋 기반을 다른 브랜치 위로 옮겨 이력 재정렬

cherry-pick

특정 커밋만 골라 현재 브랜치에 복사


2. 명령어별 상세 설명

git merge <브랜치명>

git checkout main        # 병합 대상 브랜치
git merge feature/login  # 병합할 소스 브랜치

git rebase <브랜치명>

git checkout feature/login
git rebase 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. 적합한 상황

상황

추천 명령어

팀 프로젝트에서 병합 이력 유지

merge

개인 작업 커밋 정리

rebase

특정 버그 수정만 따로 반영

cherry-pick


5. 주의사항


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

특정 커밋을 취소하는

새 커밋 생성

실수한 커밋을 안전하게 되돌림

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)

커밋할 파일을 담아두는 임시 공간 (git add)

로컬 저장소

커밋이 저장되는 .git 디렉토리


3. 주요 Git 내부 객체

Git은 4가지 핵심 객체로 이루어져 있습니다:

객체

설명

예시

🔹 Blob

파일 내용 저장 (binary large object)

hello.java 내용

🔸 Tree

디렉토리 구조와 파일 리스트

폴더 구조

🔹 Commit

커밋 메타데이터 + 부모 커밋 + tree

"커밋 메시지"

🔸 Tag

특정 커밋에 이름 부여

v1.0.0

📦 커밋은 tree를 가리키고, tree는 blob들을 가리킵니다.

[commit]
   |
   v
[tree]
 ├── [blob] hello.txt
 └── [blob] app.js

4. HEAD란?

HEAD → 현재 체크아웃한 브랜치 or 커밋

5. 브랜치란?

브랜치는 단지 커밋을 가리키는 포인터이다.

A---B---C  ← main (브랜치)
        ↑
      HEAD

6. Reflog란?

git reflog

→ 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 내부 생성 방식

  1. Git은 객체의 타입 + 크기 + 내용을 문자열로 만듦
    예: blob 12\0Hello World\n
  2. 이를 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 내부 변화


시나리오

  1. hello.txt 파일 생성
  2. git add hello.txt
  3. git commit -m "Add hello"

1. 작업 디렉토리 (Working Directory)

echo "Hello Git" > hello.txt

2. git add hello.txt

git add hello.txt

내부 변화:

구성요소

변화 내용

.git/index

스테이징 영역에 파일 등록됨 (경로, 해시, 권한 등 저장)

.git/objects/

hello.txt

의 내용이

blob

객체로 저장됨 (SHA-1 해시 기반)

📦 예시 구조:

.git/
└── objects/
    └── 3a/
        └── 3efbed4aef... ← hello.txt의 blob 객체

3. git commit -m "Add hello"

내부 변화:

.git/objects/

객체

내용

tree

객체

커밋 당시의 디렉토리 구조 (hello.txt 포함)

commit

객체

커밋 메시지, 트리 포인터, 작성자 등 메타데이터 포함

.git/objects/
├── 3a/...(blob)
├── 47/... (tree)
└── a1/... (commit)

.git/refs/heads/main

refs/heads/main → a1b2c3d4e5...

.git/HEAD

.git/logs/HEAD & logs/refs/heads/main

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

요약

단계

설명

git add

blob 객체 생성 + index 등록

git commit

tree + commit 객체 생성, 브랜치 포인터 이동

.git 내부

objects, refs, HEAD, logs 전부 갱신




구조

Git 명령어에 따른 .git 내부 구조 변화(1부)


1. git merge 시 내부 변화

1.1 예시 명령어


git checkout main
git merge feature

1.2 .git 내부 변화

구성 요소

변화 내용

.git/objects/

병합 결과로 새로운 merge commit 객체 생성

.git/refs/heads/main

브랜치 포인터가 merge 커밋으로 이동

.git/HEAD

여전히 ref: refs/heads/main 유지

.git/MERGE_HEAD

병합 대상 커밋(feature) 해시 저장 (병합 중일 때 생성됨)

.git/logs/HEAD

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 내부 변화

구성 요소

변화 내용

.git/objects/

feature의 커밋들을 기반 변경 후 새 커밋으로 재작성

.git/refs/heads/feature

브랜치가 새 커밋들로 덮어씀

.git/REBASE_HEAD

리베이스 기준 커밋을 기록

.git/HEAD

여전히 ref: refs/heads/feature

.git/logs/HEAD

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 내부 변화

구성 요소

변화 내용

.git/refs/heads/main

브랜치 포인터가 이전 커밋으로 이동

.git/HEAD

여전히 ref: refs/heads/main

.git/index

되돌린 커밋 시점으로 스테이징 영역 초기화

작업 디렉토리

--hard인 경우 파일도 초기화

.git/ORIG_HEAD

이전 HEAD 커밋 해시를 저장

.git/logs/HEAD

이동 전후 이력 기록됨

3.3 도식 예시


A---B---C ← main, HEAD
        ↑
     ORIG_HEAD

▶ git reset --hard B

결과:

A---B ← main, HEAD

4. 특수 HEAD 파일 요약

파일 이름

생성 시점

설명

.git/MERGE_HEAD

git merge 수행 중

병합 대상 커밋 해시 저장

.git/REBASE_HEAD

git rebase 수행 중

기준 커밋 해시 저장

.git/ORIG_HEAD

git reset, merge

리셋 전 커밋 백업

.git/FETCH_HEAD

git fetch 이후

원격에서 받아온 커밋들 정보

.git/CHERRY_PICK_HEAD

git cherry-pick 중 충돌 시

적용 대상 커밋 기록


5. 요약 비교표

명령어

커밋 이동

브랜치 이동

HEAD 변경

디렉토리 영향

특수 파일 생성

merge

충돌 시 변동 있음

MERGE_HEAD

rebase

⭕ (rewrite)

충돌 시 변동 있음

REBASE_HEAD

reset --hard

⭕ (이전 커밋으로)

✔️ 완전 초기화

ORIG_HEAD




구조

Git 명령어에 따른 .git 내부 구조 변화 (2부)


4. git stash 시 내부 변화

4.1 예시 명령어

git stash

4.2 .git 내부 변화

구성 요소

변화 내용

.git/objects/

현재 작업 상태(스냅샷)가 stash용 커밋으로 저장됨 (2~3개의 커밋 객체)

.git/logs/refs/stash

새로운 stash가 추가된 로그 생성

.git/refs/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 내부 변화

구성 요소

변화 내용

.git/objects/

cherry-pick된 커밋 내용 기반으로 새 커밋 객체 생성

.git/CHERRY_PICK_HEAD

대상 커밋의 해시 저장 (충돌 발생 시 사용됨)

.git/HEAD

현재 브랜치에 새 커밋 추가

.git/index

병합 결과 반영

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 내부 변화

구성 요소

변화 내용

.git/objects/

revert용 새 커밋 객체 생성

.git/index

C의 반대 연산 내용 반영

.git/HEAD

새 커밋으로 이동

revert는 원본 커밋을 삭제하지 않고, "반대로 되돌리는" 커밋을 추가한다.

6.3 도식 예시

A---B---C ← HEAD

▶ git revert C

결과:

A---B---C---C' ← HEAD (C를 무효화하는 커밋)

7. 특수 파일 요약 (2부)

파일 이름

생성 명령어

설명

.git/CHERRY_PICK_HEAD

git cherry-pick

적용 중인 커밋 해시 저장 (충돌 시 사용)

.git/REVERT_HEAD

git revert (중단 시)

revert 진행 중인 커밋 정보

.git/refs/stash

git stash

가장 최근 stash 참조

.git/logs/refs/stash

git stash

stash 추가 이력 저장


8. 요약 비교표 (2부)

명령어

새 커밋 생성

기존 커밋 삭제

HEAD 이동

특수 파일

비고

stash

O (임시 커밋)

refs/stash

작업 보관

cherry-pick

O

O

CHERRY_PICK_HEAD

선택 커밋 복사

revert

O

O

REVERT_HEAD

기존 커밋 반전




구조

도식화


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/objects/

.git/objects/
├── a7/...
├── d1/...
└── pack/    ← packfile 압축 저장소

🔹 .git/refs/

.git/refs/heads/main → a1b2c3d4e5 (커밋 해시)

🔹 .git/logs/

🔹 .git/index

🔹 .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 → 현재 브랜치 참조

요약

구성요소

설명

HEAD

현재 브랜치 또는 커밋을 가리킴

refs

브랜치/태그 → 커밋 연결

objects

모든 데이터(SHA-1 기반) 저장소

index

스테이징 상태 추적

logs

HEAD 및 브랜치 이동 이력 (reflog)

hooks

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

작업 보관소 (임시 커밋)