목차
Git 명령어를 작업 흐름으로 익히기
명령을 외우기 전에 변경 사항이 어디에 있는지 구분하면 실수를 줄일 수 있다. 파일을 편집하면 작업 디렉터리가 바뀌고, git add는 다음 커밋에 넣을 내용을 인덱스(스테이징 영역)에 기록한다. git commit은 그 인덱스를 로컬 저장소의 새 기록으로 만든다. 원격 저장소에 반영하려면 별도의 git push가 필요하다. 아래 표는 가장 기본적인 명령을 정리한 과거 메모이며, 실제 확인 순서는 뒤의 예제를 따른다.
| 목표 | 명령어 | 설명 |
| 저장소 생성 | git init | 실행한 위치를 git 저장소로 초기화 |
| 저장소에 파일 추가 | git add 파일이름 | 해당 파일을 git이 추적할 수 있게 저장소에 추가 |
| 저장소에 수정 내역 제출 | git commit | 변경된 파일을 저장소에 제출 |
| 저장소 상태 확인 | git status | 현재 저장소의 상태를 출력 |
파일을 수정한 뒤 커밋하기
git status
git diff
git add README.md
git diff --cached
git commit -m "docs: README 사용법 보완"
git status는 현재 브랜치와 추적 상태를 보여 주고, git diff는 아직 스테이징하지 않은 변경을 보여 준다. git add는 파일을 저장소에 영구 제출하는 명령이 아니라 다음 커밋에 넣을 변경을 스테이징한다. git diff --cached로 스테이징된 내용을 확인한 뒤 커밋한다.
flowchart LR 작업[작업 디렉터리] -->|git add| 스테이지[스테이징 영역] 스테이지 -->|git commit| 기록[커밋 기록]
git init은 현재 디렉터리에 새 저장소를 만든다. 이미 저장소인 디렉터리에서는 git status로 먼저 위치와 변경 사항을 확인한다. 여러 파일을 수정했다면 git add .를 무심코 실행하기보다 커밋할 범위를 선택하는 편이 검토하기 쉽다.
새 저장소에서 변경을 추적해 보기
mkdir git-practice
cd git-practice
git init
printf '# 실습\n' > README.md
git status --short
git add README.md
git diff --cached
git commit -m "docs: 첫 README 추가"
git log --oneline -1
처음 status --short에서 ?? README.md는 아직 추적하지 않는 파일이라는 뜻이다. git add 뒤에는 A README.md처럼 인덱스(스테이징 영역)에 추가됐다는 표시가 나온다. 커밋 후 git log는 새 스냅샷의 ID와 메시지를 보여 준다. 커밋은 원격 서버로 보내는 명령이 아니다. 저장소를 공유하려면 원격을 설정하고 git push가 별도로 필요하다.
flowchart LR W[작업 디렉터리] -->|git add| I[인덱스] I -->|git commit| H[로컬 커밋 기록] H -->|git push| R[원격 저장소] R -->|git fetch| H
기존 표에서 git add를 “저장소에 파일 추가”, git commit을 “저장소에 제출”이라고 표현하면 두 단계의 차이가 흐려진다. add는 다음 커밋의 내용 선택, commit은 선택한 내용을 로컬 기록에 저장하는 동작이다. git diff는 작업 디렉터리와 인덱스의 차이, git diff --cached는 인덱스와 마지막 커밋의 차이를 보여 준다. 같은 파일의 일부만 커밋하고 싶으면 git add -p로 변경 덩어리를 선택한다.
수정·실수의 범위를 구분하기
| 상황 | 확인할 명령 | 일반적인 조치 |
|---|---|---|
아직 add하지 않은 수정 | git diff -- 파일 | 수정 내용 검토 후 add 또는 수동 편집 |
add했지만 커밋하지 않은 수정 | git diff --cached -- 파일 | git restore --staged 파일로 스테이지에서 빼기 |
| 방금 만든 로컬 커밋 | git show --stat HEAD | 팀과 공유하기 전 수정 필요성 판단 |
| 원격과 로컬의 차이 | git fetch, git log --oneline --graph --all | 합칠 이력을 검토한 뒤 merge/rebase 결정 |
git restore --staged는 인덱스만 바꾸며 작업 디렉터리의 수정 내용은 남긴다. 반대로 git restore 파일은 커밋되지 않은 작업 디렉터리 변경을 버릴 수 있으므로 실행 전에 git diff를 읽어야 한다. git reset --hard도 작업 중인 변경을 지울 수 있다. 이미 공유한 커밋을 고쳐야 할 때는 팀과 협의하고, 일반적으로 기록을 다시 쓰는 대신 git revert로 되돌리는 새 커밋을 만든다.
.gitignore는 빌드 산출물처럼 아직 추적하지 않는 파일을 기본적으로 제외한다. 이미 커밋한 파일을 .gitignore에 적는 것만으로 추적이 멈추지는 않는다. 비밀 값을 커밋했다면 파일을 나중에 지우는 것만으로 노출을 없앨 수 없으므로 키를 교체하고 저장소 기록과 공유 범위를 점검해야 한다.
기능 브랜치에서 작업하고 합치기
팀에서 하나의 브랜치에 모든 수정을 직접 쌓으면 서로의 변경을 구분하기 어렵다. 다음은 main에서 새 브랜치를 만든 뒤 작업 내용을 로컬에서 병합하는 흐름이다. 실습 저장소에 이미 main 브랜치가 있고 커밋할 변경이 없다는 전제다.
git status --short
git switch main
git switch -c docs/readme-example
# README.md를 편집한 뒤
git add README.md
git commit -m "docs: README 예제 추가"
git switch main
git merge docs/readme-example
git log --oneline --graph -5
git switch -c는 브랜치를 만들고 그 브랜치로 이동한다. merge 결과가 Fast-forward라면 main이 기능 브랜치의 커밋으로 그대로 전진한 것이다. 그동안 main에서도 커밋이 생겼다면 병합 커밋이 만들어지거나 충돌 해결이 필요할 수 있다. 두 사람이 같은 줄을 다르게 고친 경우 Git은 어느 내용을 택할지 자동으로 결정하지 못한다.
충돌이 나면 git status로 충돌 파일을 찾고 파일 안의 <<<<<<<, =======, >>>>>>> 표시를 확인한다. 필요한 내용을 수동으로 정리하고 테스트한 뒤 git add 파일, git commit으로 병합을 완료한다. 해결 방향이 불분명하면 git merge --abort로 이번 병합 시도를 취소하고 변경 기록을 다시 살펴본다. 충돌 표시를 지우는 것만으로 코드가 올바르다는 보장은 없으므로 테스트와 동료 검토가 필요하다.
원격에서 다른 작업을 받으려면 먼저 git fetch origin으로 원격 추적 브랜치를 갱신하고 git log --oneline --graph --all로 두 이력의 관계를 확인한다. git pull은 가져오기와 병합 또는 재배치를 한 번에 수행하므로, 처음에는 분리해서 살피는 편이 각 단계의 결과를 이해하기 쉽다. 이미 공유한 브랜치를 강제 푸시하면 다른 사람의 이력을 덮어쓸 수 있으므로 협업 규칙을 따른다.