Git
Source code의 변경 이력을 추적하고, 여러 개발자가 협업할 수 있도록 지원하는 분산 버전 관리 시스템.
Git 필요 이유
아래와 같은 상황을 경험한 적 있을 것이다.

개발을 하다 보면 위와 같은 상황이 정확히 재현됨. git은 이 문제를 해결한다.
git은 프로젝트의 타임머신 이라고 보면 된다. 파일을 복사해서 보관하는 것이 아닌, 변경된 내용을 snapshot 형태로 차곡차곡 쌓아둔다.

위 과정의 각 점을 commit 이라고 보면 된다.
- commit(commit) – 저장 버튼이다. “지금 이 상태를 기록해줘” 라고 git에 명령하는것. save point라고 보면됨.
- repository(저장소) – 줄여서 repo라고 부름. commit들이 쌓이는 곳. 내 pc에 있는 것은 local repository, github에 올린 것은 remote repository이다.
- head – “지금 내가 보고 있는 위치”. timeline에서 현재 내 위치를 가리키는 pointer.
Git의 3가지 영역

Working Directory
- 실제로 파일을 열고 수정하는 곳. Linux의 cwd(current working directory)와 같다고 보면 됨.
- 여기서 뭔가를 수정하더라도 git은 아무것도 모름.
Staging Area
- “이것들을 저장할 거야” 라고 골라담는 곳.
- 실제 path는 .git/index 이다. (type: file)
- “git add”로 파일을 여기에 올림.
- staging area의 존재 이유
- 바로 저장하면 되는데 왜 중간 단계가 있는지 궁금하다.
- 이유는 선택적으로 저장하기 위해서임.
- 예를 들어 하루동안 두가지 작업을 했다고 해봅시다.
- login.js – 로그인 기능 개발
- style.css – UI 색상 조금 수정
- 이 둘을 한 commit에 묶으면 나중에 이력을 볼때 “이 commit이 기능 추가야, 디자인 수정이야?” 혼란스러울 수 있음.
- staging area 덕분에 두가지 수정을 따로 commit할 수 있음.
Repository
- commit이 영구 보관되는 곳.
- 실제 path는 .git/objects 이다. (type: directory)
- “git commit”으로 staging area의 내용이 여기에 확정 저장됨.
핵심 명령어와 영역의 관계
| Command | Description |
| git add <filename> | working dir -> staging area |
| git add . | 변경된 전체 파일을 staging 으로 (변경 자동 감지) |
| git commit -m “<message>” | staging area -> repository |
| git status | 각 영역의 현재 상태 확인 |
git add가 파일 변경을 감지하는 방법
1. OS Metadata 비교
– 파일 크기
– 최종 수정 시간 (mtime)
– inode 번호
-> metadata 일치여부에 따라 다음 단계로 이동 여부 결정.
2. SHA-1 Hash 계산
– 파일 내용 전체를 읽어서 Digest 계산.
– .git/index의 digest값과 비교.
-> digest 일치여부에 따라 Staging Area로 이동여부 결정.
=> SHA-1 계산은 파일을 전부 읽어야 해서 파일이 크면 클수록 시간이 오래 걸림. 반면 metadata 비교는 이미 staging area(.git/index)에 보유하고 있는 head commit의 정보를 비교하기에 거의 즉시 비교 가능.
=> 파일을 수정했다가 다시 원래대로 되돌리면 metadata는 바뀌었지만 SHA-1은 동일하기에 이 경우에 git은 2단계까지 확인하고 “변경 없음”으로 처리함.
Git의 3가지 영역(그리고, Remote Repository)과 git 명령어의 관계를 시각화한다면 아래와 같다.

Commit
git은 commit마다 변경된 차이(diff)를 기록하는 것이 아니라, commit 시점의 프로젝트 전체 파일의 상태를 기록함. 이것을 snapshot이라고 함. 단, 똑같은 파일은 중복 저장하지 않음.
commit object의 실제 내부 구조는 아래와 같다.

commit끼리는 chain으로 연결됨. 각 commit은 parent로 이전 commit을 가리킵니다. 이 chain 덕분에 git은 두 commit 사이에 뭐가 바뀌었지?를 언제든 계산해낼 수 있음. (이것이 git diff의 원리.)
정리하면 commit = snapshot + metadata(who, when, why)
snapshot = tree(folder structure) + blob(file contents를 의미)
같은 내용 = 같은 hash = 하나만 저장 (deduplicate)
Git Basic Commands
git은 아래와 같은 기본 명령어들이 있다.
- git init (이 폴더를 git 저장소로 만들어줘)
- git status (지금 상태는?)
- git add (이 파일을 commit 준비 목록(staging area)에 올려줘)
- git commit (staging의 내용을 역사에 기록해줘)
- git log (지금까지의 commit 이력을 보여줘)
git init
initialization (초기화)
프로젝트를 시작할 때 최초 1회만 실행.
실행하면 폴더 안에 .git directory가 생성되고, 그 안에 git이 필요한 모든 것을 저장함.
; 프로젝트를 진행할 Directory 생성 후, 해당 Directory로 이동.
# mkdir my-project && cd my-project
; init 명령어를 통하여 Git 프로젝트 시작
# git init
Initialized empty Git repository in /root/my-project/.git/
; .git 폴더 생성 확인
# ls -al
drwxr-xr-x 7 root root 4096 May 15 15:02 .git
.git Directory에는 commit history, branch information, configuration 등 설정들이 들어있음.
이 폴더를 지우면 Git 이력이 전부 사라지기 때문에 삭제하면 안됨.
git status
현재 상태(Status)를 확인. 어떤 파일이 수정되었는지. Staging에 올라왔는지, 아직 추적되지 않는 파일이 있는지 등.
; init만 한 상황 (아직 git이 모르는 파일들이 출력됨)
# git status
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
index.html
style.css
nothing added to commit but untracked files present (use "git add" to track)
; staging area로 파일 이동 후 상태 확인
# git add index.html
# git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: index.html
Untracked files:
(use "git add <file>..." to include in what will be committed)
style.css
git add
Working Directory -> Staging Area로 파일을 올림. 어떤 파일을 이번 commit에 포함할지 고르는 단계.
; 파일 하나만
# git add index.html
; 파일 여러개
# git add index.html style.css
; 변경된 파일 전부 (많이 사용됨)
# git add .
; 특정 디렉터리 (모든 하위 파일 및 디렉터리)
# git add src/
git commit
Staging area에 올라온 파일들을 하나의 Snapshot으로 저장. -m 옵션을 통해 Message(comment)를 붙여야 나중에 이 commit이 뭔지 알 수가 있음.
; 기본 커밋
# git commit -m "feat: 메인 페이지 추가"
[master (root-commit) 2a9fef4] feat: 메인 페이지 추가
2 files changed, 4 insertions(+)
create mode 100644 index.html
create mode 100644 style.css
; 기존 파일 수정 후, add + commit 한번에 하기
# git commit -am "fix: 메인 페이지 제목 수정"
[master a2362d6] fix: 메인 페이지 제목 수정
1 file changed, 1 insertion(+), 1 deletion(-)
git log
commit 이력을 최신 순으로 보여줌. option에 따라서 보기 방식을 다양하게 변경 가능.
; 기본 (상세하게)
# git log
commit a2362d63d6eb6c95708eac077193721bacf0be04 (HEAD -> master)
Author: YC <yc@it-blog.kr>
Date: Thu May 21 15:43:25 2026 +0900
fix: 메인 페이지 제목 수정
commit 2a9fef44a6d538f0d01b8308bacf1d9e12152a35
Author: YC <yc@it-blog.kr>
Date: Thu May 21 15:42:03 2026 +0900
feat: 메인 페이지 추가
; 한줄 요약
# git log --oneline
a2362d6 (HEAD -> master) fix: 메인 페이지 제목 수정
2a9fef4 feat: 메인 페이지 추가
; 최근 1개만
# git log --oneline -1
a2362d6 (HEAD -> master) fix: 메인 페이지 제목 수정
Test Flow
; 1. 프로젝트 시작
# mkdir my-project && cd my-project
# git init
; 2. 파일 만들기
# echo "<h1>Hello World!</h1>" > index.html
; 3. Staging에 올리기
# git add .
; 4. 상태 확인
# git status
; 5. 커밋
# git commit -m "init: 프로젝트 시작"
; 6. 이력 확인
# git log --oneline
되돌리기
이전 버전으로 되돌리고 싶을 때 사용할 수 있음.
- git diff (뭐가 바뀌었는지 보여줘)
- git restore (파일을 이전 상태로 되돌려줘)
- git reset (commit을 취소해줘)
git diff
commit하기 전에 내가 뭘 바꿨는지를 확인할 때 사용.
; 아무것도 수정하지 않은 상황 (출력 없음)
# git diff
; 파일 수정 후
# git diff
diff --git a/index.html b/index.html
index de8b69b..a260fb1 100644
--- a/index.html
+++ b/index.html
@@ -1 +1 @@
-<h1>Hello World!</h1>
+<h1>Hello World!!!</h1>
; staging area에 올린 후 (이때, git diff의 출력은 없음.)
# git add .
# git diff --staged
diff --git a/index.html b/index.html
index de8b69b..a260fb1 100644
--- a/index.html
+++ b/index.html
@@ -1 +1 @@
-<h1>Hello World!</h1>
+<h1>Hello World!!!</h1>
; 특정 파일만
# git diff --staged index.html
diff --git a/index.html b/index.html
index de8b69b..a260fb1 100644
--- a/index.html
+++ b/index.html
@@ -1 +1 @@
-<h1>Hello World!</h1>
+<h1>Hello World!!!</h1>
; 두 commit 사이 비교
# git diff 95778b6 12d7642
diff --git a/index.html b/index.html
index de8b69b..a260fb1 100644
--- a/index.html
+++ b/index.html
@@ -1 +1 @@
-<h1>Hello World!</h1>
+<h1>Hello World!!!</h1>
git restore
commit하기 전의 변경사항을 취소할 때 사용.
두가지 용도가 있음.
- 수정한 파일 되돌리기 (add 전, Working dir 변경 취소)
- Staging 취소하기 (add 했는데 빼고 싶을 때)
git reset
이미 commit한 것을 없애고 싶을 때 사용.
옵션에 따라서 파일 내용을 보존할지 말지가 갈림.

.gitignore
더 알아볼것
- snapshot
- metadata
- mtime
- inode