Home Git Overview
Post
Cancel

Git Overview

Git

목차


Git의 역할

Git은 파일 변경 이력을 commit 단위로 저장하는 분산 버전 관리 시스템(VCS)이다. 각 개발자가 전체 저장소 복사본을 가지고 있어서, 중앙 서버 없이도 협업이 가능하다.

1
2
3
4
5
로컬 저장소 (완전한 히스토리)
    ↓
원격 저장소 (GitHub, GitLab 등)
    ↓
다른 개발자의 로컬 저장소

Git이 필요한 이유

1
2
3
4
5
6
7
8
9
10
Git 없이:
- 파일 버전 관리 불가 (file_v1.py, file_v2.py...)
- 누가 언제 뭘 바꿨는지 추적 불가
- 협업이 어려움 (파일 덮어쓰기)

Git 사용:
- 모든 변경 이력 자동 기록
- 누가 언제 뭘 바꿨는지 명확
- 여러 사람이 동시 작업 가능
- 이전 버전으로 롤백 가능

Repository

Repository란?

Repository는 Git이 모든 변경 이력과 메타데이터를 저장하는 디렉토리다.

1
2
3
4
5
6
7
8
9
my-project/
├─ .git/              ← Git 메타데이터 (숨겨진 디렉토리)
│  ├─ objects/        ← 모든 commit, tree, blob 저장
│  ├─ refs/           ← branch 포인터
│  ├─ HEAD            ← 현재 branch 가리킴
│  └─ config          ← 저장소 설정
├─ src/
├─ README.md
└─ ...

로컬 vs 원격 Repository

1
2
3
4
5
6
7
8
9
로컬 Repository (.git이 있는 곳)
- 로컬 머신에만 존재
- 모든 commit 히스토리 포함
- git log, git diff 등은 로컬에서 실행

원격 Repository (GitHub, GitLab)
- 서버에 호스팅됨
- 팀이 공유하는 중앙 저장소
- git push/pull로 동기화

Repository 생성

1
2
3
4
5
6
7
8
9
# 새 저장소 초기화
git init my-project

# 기존 저장소 복제
git clone https://github.com/user/repo.git

# 저장소 설정 확인
git config --local --list  # 로컬 설정
git config --global --list # 전역 설정

Working Tree와 Index

“working tree와 index는 무엇이 다른가?”

Working Tree, Index(Staging Area), Repository는 Git의 3가지 상태 영역이다.

1
2
3
4
5
6
7
8
┌─ Working Tree (작업 디렉토리)
│  └─ 실제 파일 (수정됨)
│
├─ Index / Staging Area
│  └─ commit할 파일 선택
│
└─ Repository (.git)
   └─ 영구 저장된 commit

각 영역의 역할

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Working Tree
- 개발자가 실제로 파일을 수정하는 곳
- git 추적 대상이 아닌 파일도 존재 가능
- 수정 내용이 즉시 반영됨

Index (Staging Area)
- "다음 commit에 포함할 파일" 선택하는 곳
- git add로 여기에 파일 추가
- 여러 번 add로 원하는 파일만 선택 가능

Repository
- 모든 commit 히스토리 저장
- 불변 (변경 불가)
- 각 commit은 고유한 hash로 식별

상태 전이

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 1. Working Tree에서 파일 수정
vi README.md

# 2. 현재 상태 확인
git status
# modified:   README.md (Working Tree에만 변경)

# 3. Index에 추가
git add README.md

# 4. 상태 다시 확인
git status
# Changes to be committed:
#   modified:   README.md (Index에 준비됨)

# 5. Repository에 commit
git commit -m "Update README"

# 6. 상태 최종 확인
git status
# nothing to commit, working tree clean

부분 커밋 (일부 파일만 선택)

1
2
3
4
5
6
7
8
9
10
11
12
# 여러 파일 수정
vi file1.py
vi file2.py
vi file3.py

# 특정 파일만 commit
git add file1.py file2.py
git commit -m "Fix bug in file1 and file2"

# file3.py는 Working Tree에만 남음
git status
# modified:   file3.py (untracked)

Commit

Commit이란?

Commit은 특정 시점의 프로젝트 전체 상태를 스냅샷으로 저장한다.

1
2
3
4
5
6
7
Commit 구성:
├─ Hash (SHA-1): 고유 식별자
├─ Author: 작성자
├─ Date: 작성 시간
├─ Message: 커밋 메시지
├─ Parent: 이전 커밋 가리킴
└─ Tree: 전체 파일 구조 스냅샷

“commit hash는 무엇을 식별하는가?”

Commit hash는 그 commit의 모든 내용(파일, 메시지, 작성자, 시간 등)을 고유하게 식별한다.

1
2
3
4
5
6
7
8
commit 3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d
Author: John Doe <john@example.com>
Date:   Mon May 23 10:15:30 2026 +0900

    Fix bug in login flow

- Hash 변경 = 완전히 다른 commit (변경 불가능)
- 같은 파일 내용이라도 시간이 다르면 hash가 다름

Commit 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 기본 commit
git commit -m "Brief description"

# 상세 메시지
git commit -m "Brief description" -m "Detailed explanation
- bullet point 1
- bullet point 2"

# 모든 수정된 파일을 자동 추가 (새 파일 제외)
git commit -am "Update multiple files"

# 이전 commit 수정
git commit --amend

# 빈 commit (테스트 목적)
git commit --allow-empty -m "Trigger CI/CD"

Commit 조회

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 전체 히스토리
git log

# 한 줄씩 간결하게
git log --oneline

# 그래프로 시각화 (branch 보임)
git log --oneline --graph --all

# 특정 파일의 히스토리
git log -- file.py

# 특정 범위
git log main..feature  # feature에만 있는 commit

# 특정 내용 검색
git log -S "bug fix"   # 이 텍스트를 포함하는 commit

Branch

Branch란?

Branch는 독립적인 개발 흐름을 만드는 포인터다. 같은 저장소에서 여러 버전을 동시에 개발할 수 있다.

1
2
3
4
5
       feature1         feature2
         ↑               ↑
c1 ← c2 ← c3          c4
     ↑
    main (기본 branch)

Branch의 용도

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
main (master)
- 프로덕션에 배포되는 코드
- 항상 안정적이어야 함

develop
- 다음 버전 개발
- feature branch들의 기반

feature/...
- 새로운 기능 개발
- develop에서 생성, 완료 후 develop에 merge

hotfix/...
- 긴급 버그 수정
- main에서 생성, 수정 후 main과 develop에 merge

Branch 관리

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 현재 branch 확인
git branch

# 새 branch 생성
git branch feature/new-feature

# branch 전환
git checkout feature/new-feature
# 또는 (최신 Git)
git switch feature/new-feature

# 생성과 전환을 한 번에
git checkout -b feature/new-feature
git switch -c feature/new-feature

# branch 삭제
git branch -d feature/new-feature  # 안전 삭제 (merge 확인)
git branch -D feature/new-feature  # 강제 삭제

# branch 이름 변경
git branch -m old-name new-name

# 모든 branch 보기 (원격 포함)
git branch -a

Branch 전환

1
2
3
4
5
6
7
8
9
10
11
12
# feature branch로 전환
git switch feature/login

# 이제 이 branch에서 작업
vi login.py
git add login.py
git commit -m "Implement login form"

# main으로 돌아가기
git switch main

# main의 파일들로 작업 디렉토리 변경됨 (feature의 변경사항 보이지 않음)

Merge와 Rebase

“merge와 rebase는 무엇이 다른가?”

Merge는 두 branch의 변경사항을 모두 유지하며 합치고, Rebase는 한 branch의 commit을 다른 branch 위에 순차적으로 재배치한다.

Merge

1
2
3
4
5
6
7
8
9
10
11
12
feature branch:
c1 - c2 - c3

main branch:
m1 - m2

Merge 후:
       c3
       /  \
m1 - m2    merge commit
       \  /
       (feature branch의 모든 변경사항 유지)
1
2
3
4
5
6
# feature branch의 변경사항을 main에 merge
git switch main
git merge feature/login

# merge commit이 생성됨
# feature의 모든 변경사항이 main에 포함

Rebase

1
2
3
4
5
6
7
8
9
feature branch:
c1 - c2 - c3

main branch:
m1 - m2

Rebase 후:
m1 - m2 - c1' - c2' - c3'
(feature의 commit들이 main 위에 순차적으로 배치)
1
2
3
4
5
6
7
8
9
10
# feature branch의 commit들을 main 위에 배치
git switch feature/login
git rebase main

# 이제 feature는 main의 최신 위에 있음
# commit 히스토리가 선형적 (일직선)

# main으로 돌아가서 fast-forward merge
git switch main
git merge feature/login

Merge vs Rebase 비교

 MergeRebase
Commit 히스토리병렬 구조 (보존)선형 구조 (재정렬)
Commit 수merge commit 추가기존 commit 수 유지
장점히스토리 보존, 안전히스토리 깔끔, 읽기 쉬움
단점히스토리 복잡기존 commit hash 변경
사용처공개 branch로컬 branch

실전 가이드

1
2
3
4
5
6
7
8
9
# 로컬에서만 사용할 branch는 rebase (깔끔한 히스토리)
git switch feature/login
git rebase main
git switch main
git merge feature/login

# 공개 branch는 merge (안전성)
git switch main
git merge develop  # develop의 모든 변경사항 유지

Remote

Remote란?

Remote는 원격 저장소에 대한 별칭이다. 보통 origin이라 부른다.

1
2
3
4
5
6
7
8
9
10
11
12
13
# remote 확인
git remote -v
# origin  https://github.com/user/repo.git (fetch)
# origin  https://github.com/user/repo.git (push)

# remote 추가
git remote add origin https://github.com/user/repo.git

# remote 제거
git remote remove origin

# remote 이름 변경
git remote rename origin upstream

Push

1
2
3
4
5
6
7
8
9
10
11
# 로컬 commit을 원격에 보내기
git push

# 특정 branch 지정
git push origin main

# 첫 push일 때 branch 생성
git push -u origin feature/login

# 강제 push (주의! 팀 협업 시 위험)
git push --force

Pull

1
2
3
4
5
6
7
8
9
# 원격의 변경사항을 가져와서 merge
git pull

# 실제로는 fetch + merge
git fetch origin
git merge origin/main

# rebase로 merge (깔끔한 히스토리)
git pull --rebase

Fetch vs Pull

1
2
3
4
5
6
7
8
9
Fetch
- 원격의 변경사항을 로컬에 다운로드
- 로컬 branch 변경 안 함
- 안전 (손상 위험 없음)

Pull
- Fetch + Merge
- 로컬 branch 자동 업데이트
- 충돌 가능성 있음

Tracking Branch

1
2
3
4
5
6
7
8
9
# feature/login을 원격과 동기화하도록 설정
git branch -u origin/feature/login

# 또는 push할 때
git push -u origin feature/login

# 확인
git branch -vv
# feature/login  abc1234 [origin/feature/login] Commit message

Conflict

“conflict는 왜 발생하는가?”

Conflict는 같은 파일의 같은 부분을 두 branch에서 다르게 수정했을 때 발생한다.

1
2
3
4
5
6
7
8
9
10
main branch:
def login():
    return "success"  ← 메인에서 수정

feature branch:
def login():
    return "login success"  ← feature에서 수정

Merge 시도 → Conflict!
Git은 어느 것이 맞는지 알 수 없음

Conflict 발생 상황

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# main에서 작업
git checkout main
vi app.py  # 수정
git commit -m "Update app.py"

# feature에서 같은 파일 수정
git checkout feature/login
vi app.py  # 다른 부분 수정
git commit -m "Update app.py"

# merge 시도
git checkout main
git merge feature/login
# CONFLICT (content conflict): Merge conflict in app.py

Conflict 해결

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 충돌 파일 확인
git status
# both modified:   app.py

# 파일 내용
cat app.py
# <<<<<<< HEAD
# def login():
#     return "success"
# =======
# def login():
#     return "login success"
# >>>>>>> feature/login

# 수동으로 수정
vi app.py
# 원하는 부분만 유지, 충돌 마커 제거

# 수정 후 완료
git add app.py
git commit -m "Resolve conflict in app.py"

Conflict 예방

1
2
3
4
5
6
7
8
9
10
11
# 1. 자주 동기화
git pull --rebase origin main  # 주기적으로 최신 유지

# 2. 더 작은 단위의 commit
# 작은 변경 → 충돌 가능성 ↓

# 3. 팀 규칙 정하기
# 같은 파일을 동시에 수정하지 않기

# 4. merge tool 사용
git mergetool  # IDE 통합 툴로 해결

Merge 취소

1
2
3
4
5
# merge 중단 (conflict 발생 시)
git merge --abort

# merge 후 취소
git revert -m 1 <merge-commit-hash>

실전 워크플로우

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 1. main에서 feature branch 생성
git switch main
git pull origin main
git switch -c feature/user-auth

# 2. 작업 진행
vi auth.py
git add auth.py
git commit -m "Implement user authentication"

vi test_auth.py
git add test_auth.py
git commit -m "Add tests for auth"

# 3. 원격에 push
git push -u origin feature/user-auth

# 4. Pull Request 생성 (GitHub)
# → Code Review 후 Approval

# 5. main에 merge
git switch main
git pull origin main
git merge feature/user-auth

# 6. 원격에 push
git push origin main

# 7. feature branch 정리
git branch -d feature/user-auth
git push origin -d feature/user-auth

정리

개념설명
Working Tree실제 작업 디렉토리
IndexCommit할 파일 선택 영역
Repository모든 commit 히스토리 저장소
Commit특정 시점의 스냅샷
Branch독립적인 개발 흐름
Merge두 branch를 병렬 구조로 합침
Rebase한 branch를 다른 위에 순차 배치
Remote원격 저장소 참조
Conflict같은 부분을 다르게 수정했을 때

This post is licensed under CC BY 4.0 by the author.