Git이란?
Git은 파일의 변경 이력을 관리하는 분산 버전 관리 시스템이다.
코드를 작성하다 보면 다음과 같은 상황이 자주 발생한다.
- 이전 코드로 돌아가고 싶다.
- 어떤 파일을 언제 수정했는지 알고 싶다.
- 여러 사람이 같은 프로젝트를 함께 수정해야 한다.
- 실험적인 기능을 따로 만들고 싶다.
- 원격 저장소에 코드를 백업하고 싶다.
Git은 이런 문제를 해결하기 위해 사용한다.
Repository
Repository는 Git이 변경 이력을 관리하는 프로젝트 저장소이다.
기존 디렉토리를 Git 저장소로 만들려면 다음 명령어를 사용한다.
git init
그러면 프로젝트 안에 .git 디렉토리가 생긴다.
이 디렉토리에 커밋 기록, 브랜치 정보, 설정 등이 저장된다.
이미 존재하는 원격 저장소를 가져올 때는 clone을 사용한다.
git clone https://github.com/user/project.git
Git의 기본 흐름
Git의 기본 흐름은 다음과 같다.
Working Tree -> Staging Area -> Repository
Working Tree
현재 실제로 작업 중인 파일들이 있는 공간이다.
파일을 수정하면 먼저 working tree에 변경사항이 생긴다.
Staging Area
다음 커밋에 포함할 변경사항을 모아두는 공간이다.
git add file.py
또는 전체 변경사항을 올릴 수 있다.
git add .
Repository
커밋이 저장되는 공간이다.
git commit -m "message"
커밋은 특정 시점의 스냅샷이다.
상태 확인
현재 변경 상태를 확인할 때는 status를 사용한다.
git status
자주 보는 상태는 다음과 같다.
| 상태 | 의미 |
|---|---|
untracked | Git이 아직 추적하지 않는 새 파일 |
modified | 추적 중인 파일이 수정됨 |
staged | 다음 커밋에 포함될 변경사항 |
clean | 커밋할 변경사항이 없음 |
작업 중에는 git status를 자주 확인하는 습관이 좋다.
변경 내용 확인
아직 staging area에 올리지 않은 변경사항은 diff로 확인한다.
git diff
staging area에 올라간 변경사항은 다음처럼 확인한다.
git diff --cached
또는
git diff --staged
커밋하기 전에 diff를 확인하면 실수로 불필요한 변경사항을 포함하는 일을 줄일 수 있다.
Commit
커밋은 의미 있는 작업 단위로 만드는 것이 좋다.
git commit -m "feat: add login form"
좋은 커밋은 다음 성질을 가진다.
- 하나의 목적을 가진다.
- 메시지만 보고 변경 의도를 알 수 있다.
- 너무 많은 기능을 한 번에 담지 않는다.
나쁜 예시는 다음과 같다.
git commit -m "update"
무엇을 수정했는지 알기 어렵다.
더 나은 예시는 다음과 같다.
git commit -m "fix: handle empty search query"
Log
커밋 기록을 볼 때는 log를 사용한다.
git log
한 줄로 간단히 보고 싶으면 다음 명령어가 편하다.
git log --oneline
브랜치 그래프까지 보고 싶으면 다음처럼 사용할 수 있다.
git log --oneline --graph --decorate
Branch
Branch는 작업 흐름을 분리하기 위해 사용한다.
현재 브랜치를 확인한다.
git branch
새 브랜치를 만든다.
git branch feature/login
브랜치를 이동한다.
git switch feature/login
브랜치를 만들면서 바로 이동할 수도 있다.
git switch -c feature/login
브랜치를 사용하면 main 브랜치를 건드리지 않고 새로운 기능을 개발할 수 있다.
Merge
브랜치에서 작업한 내용을 다른 브랜치로 합칠 때는 merge를 사용한다.
예를 들어 feature/login 브랜치를 main에 합치려면 먼저 main으로 이동한다.
git switch main
그 다음 merge한다.
git merge feature/login
두 브랜치에서 같은 파일의 같은 부분을 수정했다면 conflict가 발생할 수 있다.
Conflict
Conflict는 Git이 어떤 변경사항을 선택해야 할지 자동으로 판단하지 못하는 상태이다.
충돌이 발생하면 파일 안에 다음과 같은 표시가 생긴다.
<<<<<<< HEAD
현재 브랜치 내용
=======
합치려는 브랜치 내용
>>>>>>> feature/login
개발자가 직접 올바른 내용을 선택한 뒤 conflict 표시를 제거해야 한다.
수정 후 다시 staging area에 올린다.
git add file.py
그 다음 merge commit을 만든다.
git commit
Remote
원격 저장소는 GitHub 같은 외부 저장소를 의미한다.
현재 등록된 원격 저장소를 확인한다.
git remote -v
원격 저장소를 추가한다.
git remote add origin https://github.com/user/project.git
로컬 커밋을 원격 저장소로 올린다.
git push origin main
원격 저장소의 변경사항을 가져온다.
git pull origin main
Pull과 Fetch
pull은 원격 저장소의 변경사항을 가져오고 현재 브랜치에 합친다.
git pull
fetch는 원격 저장소의 변경사항을 가져오기만 하고, 현재 브랜치에는 합치지 않는다.
git fetch
안전하게 확인하고 싶을 때는 fetch 후 diff나 log를 확인한 다음 merge하는 방식이 좋다.
되돌리기
Git에서 되돌리기는 조심해야 한다.
작업 중인 파일의 수정사항을 버리고 싶다면 다음 명령어를 사용한다.
git restore file.py
staging area에 올린 파일을 다시 내리고 싶다면 다음처럼 한다.
git restore --staged file.py
이미 만든 커밋을 되돌리는 커밋을 새로 만들고 싶다면 revert를 사용한다.
git revert <commit>
reset은 기록 자체를 이동시키므로 더 조심해야 한다.
git reset --soft <commit>
git reset --mixed <commit>
git reset --hard <commit>
특히 --hard는 작업 중인 변경사항을 삭제할 수 있으므로 신중하게 사용해야 한다.
자주 쓰는 명령어 정리
| 명령어 | 설명 |
|---|---|
git status | 현재 상태 확인 |
git add . | 변경사항 staging |
git commit -m "message" | 커밋 생성 |
git log --oneline | 커밋 기록 확인 |
git diff | unstaged 변경사항 확인 |
git diff --cached | staged 변경사항 확인 |
git switch -c branch | 새 브랜치 생성 후 이동 |
git merge branch | 브랜치 병합 |
git push origin main | 원격 저장소로 push |
git pull origin main | 원격 저장소 변경사항 반영 |
좋은 습관
Git을 사용할 때는 다음 습관이 중요하다.
- 작업 전
git status확인 - 커밋 전
git diff확인 - 의미 있는 단위로 커밋
- 커밋 메시지에 변경 의도 작성
- 실험적인 작업은 브랜치에서 진행
reset --hard사용 전 신중하게 확인
Git은 단순히 코드를 저장하는 도구가 아니다.
변경 이력을 읽고, 작업을 분리하고, 협업을 가능하게 만드는 도구이다.
따라서 명령어를 외우는 것보다 Git이 어떤 상태를 관리하는지 이해하는 것이 더 중요하다.