1. Git이란?
Git은 분산 버전 관리 시스템(DVSC) 입니다.
쉽게 말해, 코드의 변경 이력을 기록하고 관리하는 도구입니다.
- 누가, 언제 ,뭘 변경했는지 전부 추적 가능
- 실수로 코드를 망쳐도 이전 상태로 되돌리기 가능
- 브랜치를 활용해 기능별로 독립적인 개발 가능
Git vs GitHub vs GitLab
| 구분 | 설명 |
| Git | 버전 관리 도구 (내 PC에서 동작) |
| GitHub | Git 원격 저장소 호스팅 서비스 (microsoft) |
| GitLab | Git 원격 저장소 호스팅 서비스 (자체 서버 구축 가능) |
- Git은 도구이고, GitHub/GitLab은 그 도구를 클라우드에서 사용할 수 있게 해주는 서비스 입니다.
2. Git 저장소의 구조
Git에는 4개의 공간이 있습니다. 코드가 이 공간들을 이동하면서 관리됩니다.
Working Directory → Staging Area → Local Repository → Remote Repository
(작업 공간) (준비 공간) (내 PC 저장소) (GitLab/GitHub)
파일 수정 → git add → git commit → git push
← ← ← git pull
각 공간의 역할
| 공간 | 설명 | 비유 |
| Working Directory | 실제로 파일을 수정하는 공간 | 작업 책상 |
| Staging Area | 커밋할 파일을 골라놓는 공간 | 택배 포장 대기 |
| Local Repository | 내 PC의 Git 저장소 | 택배 발송 완료 (아직 내 집) |
| Remote Repository | GitHub / GitLab 서버 | 상대방에게 도착 |
예시
# 1. 파일을 수정했다 (Working Directory)
echo "hello" > README.md
# 2. 이 파일을 커밋 대상으로 올린다 (Staging Area)
git add README.md
# 3. 변경 이력을 저장한다 (Local Repository)
git commit -m "Add README"
# 4. 원격 저장소에 업로드한다 (Remote Repository)
git push origin main
3. 필수 명령어 - 상태 확인
코드를 수정하기 전, 항상 현재 상태를 확인하는 습관이 필요합니다.
git status - 파일 상태 확인
$ git status
On branch develop
Changes not staged for commit:
modified: src/app.js # 수정했지만 아직 add 안 한 파일
Untracked files:
src/new-feature.js # 새로 만든 파일 (Git이 아직 모르는 파일)
- 빨간색 : 수정했지만 staging 안 된 파일
- 초록색 : staging 되어 커밋 대기 중인 파일
git log - 커밋 이력 확인
# 한 줄로 간결하게 보기
$ git log --oneline
e548571 Remove runner service and fix DB init
18e802b Merge branch 'feature/kjs3' into 'develop'
ac8897b Add error diagnostics and recording enhancements
# 그래프로 브랜치 흐름 보기
$ git log --oneline --graph --all
git diff - 변경 내용 확인
# 아직 staging 안 된 변경 내용
$ git diff
# staging된 변경 내용 (커밋 직전 확인용)
$ git diff --staged
4. 기본 워크플로우 - add, commit, push, pull
코드 올리기 (add → commit → push)
# Step 1: 변경된 파일을 staging
git add src/login.js # 특정 파일만
git add . # 모든 변경 파일
# Step 2: 커밋 (변경 이력 저장)
git commit -m "Add login feature"
# Step 3: 원격 저장소에 업로드
git push origin develop
코드 받기 (pull)
# 원격 저장소의 최신 코드 받기
git pull origin develop (브랜치명)
add와 commit을 나누는 이유
10개 파일을 수정했는데, 그중 3개만 먼저 커밋하고 싶을 때가 있습니다.
# login 관련 파일만 먼저 커밋
git add src/login.js src/auth.js
git commit -m "Add login feature"
# 나머지는 별도 커밋
git add src/dashboard.js
git commit -m "Update dashboard layout"
이렇게 하면 커밋 이력이 깔끔하게 정리됩니다.
5. 브랜치 전략과 활용법
브랜치란?
브랜치는 독립적인 작업 공간입니다.
원본 코드에 영향을 주지 않고 새로운 기능을 개발할 수 있습니다.
main(master) ───────────────────────── ← 배포용 (건들지 않음)
│
└── develop ─────────────────── ← 개발 통합 브랜치
│
├── feature/login ───── ← 로그인 기능 개발
└── feature/signup ──── ← 회원가입 기능 개발
브랜치 명령어
# 브랜치 목록 확인
git branch
# 새 브랜치 생성 + 이동 (한 번에)
git checkout -b feature/login
# 브랜치 이동
git checkout develop
# 브랜치 삭제 (merge 완료 후)
git branch -d feature/login
실무에서의 브랜치 워크플로우
프로젝트에 따라 상이할 수 있습니다.
# 1. develop 브랜치에서 시작
git checkout develop
git pull origin develop # 최신 코드 받기
# 2. 새 기능 브랜치 생성
git checkout -b feature/login
# 3. 코드 작성 + 커밋
git add .
git commit -m "Add login page"
git commit -m "Add login API integration"
# 4. 원격에 push
git push origin feature/login
# 5. GitLab에서 Merge Request 생성
# (GitHub에서는 Pull Request)
# 6. 리뷰 후 develop에 merge
Merge Request (GitLab) vs Pull Request (GitHub)
둘다 같은 기능입니다.
"내 브랜치의 코드를 본 브랜치에 합쳐주세요" 라고 요청하는 것입니다.
| GitLab | GitHub |
| Merge Request (MR) | Pull Request (PR) |
6. 파일 삭제 - 로컬과 원격에서 제거
Case 1: 로컬 + 원격 모두 삭제
파일을 원전히 제거하고 싶을 때 사용합니다.
# 파일 삭제
git rm config/old-settings.json
git commit -m "Remove old settings file"
git push origin develop
# 폴더 삭제
git rm -r logs/
git commit -m "Remove logs directory"
git push origin develop
Case 2: 원격에서만 삭제 (로컬은 유지)
`.env`, `credentials.json` 같은 파일이 실수로 원격에 올라갔을 때 유용합니다.
# 원격에서만 제거 (내 PC에는 파일 그대로)
git rm --cached .env
git commit -m "Remove .env from tracking"
git push origin develop
# 폴더 통째로
git rm -r --cached node_modules/
git commit -m "Remove node_modules from tracking"
git push origin develop
> `--cached`를 붙이면 내 PC에는 파일이 남아있고, Git 추적만 해제됩니다.
Case 3: 삭제 후 다시 올라가지 않도록 방지
`.gitignore`에 추가하면 이후부터 Git이 해당 파일을 무시합니다.
# 1. 원격에서 제거
git rm --cached .env
# 2. .gitignore에 추가
echo ".env" >> .gitignore
# 3. 커밋 + push
git add .gitignore
git commit -m "Remove .env and add to .gitignore"
git push origin develop
.gitignore 예시
# 환경 설정
.env
.env.local
# 의존성
node_modules/
vendor/
# 빌드 결과물
build/
dist/
# IDE 설정
.idea/
.vscode/
# OS 파일
.DS_Store
Thumbs.db
7. 커밋 이력(log) 삭제와 되돌리기
reset - 커밋 되돌리기
`reset`은 시간을 되돌리는 것과 같습니다.
`HEAD~N`에서 N은 되돌릴 커밋 수입니다.
- soft reset - 커밋만 취소 (파일 변경은 유지)
# 마지막 1개 커밋 취소 (변경한 코드는 그대로, staging 상태로 돌아감)
git reset --soft HEAD~1
사용 예시: 커밋 메시지를 잘못 썼을 때
git commit -m "오타있는 커밋 메시지"
git reset --soft HEAD~1
git commit -m "올바른 커밋 메시지"
- mixed reset - 커밋 + staging 취소 (파일 변경은 유지)
# 기본 reset (--mixed가 기본값)
git reset HEAD~1
사용 예시: 커밋 메시지를 잘못 썼을 때
git reset HEAD~1
# 파일을 다시 선택해서 add
git add src/login.js
git commit -m "Add login feature only"
- hard reset - 전부 삭제 (주의)
# 커밋 + 변경사항 전부 삭제
git reset --hard HEAD~1
> hard reset은 변경한 코드가 완전히 사라집니다. 신중하게 사용하세요.
reset 비교 정리
| 명령어 | 커밋 | Staging | 파일 변경 |
| `--soft` | 취소 | 유지 | 유지 |
| `--mixed` (기본) | 취소 | 취소 | 유지 |
| `--hard` | 취소 | 취소 | 삭제 |
원격 저장소의 이력도 되돌리기
로컬에서 reset한 후 원격에도 반영하려면 `--force`가 필요합니다.
# 로컬에서 되돌리기
git reset --hard HEAD~2
# 원격에 강제 반영
git push origin develop --force
> `--force`는 원격 이력을 덮어쓰기 때문에, 팀원에게 미리 알린 후 사용하세요.
특정 커밋으로 돌아가기
# 커밋 해시 확인
$ git log --oneline
e548571 세 번째 커밋
abc1234 두 번째 커밋
def5678 첫 번째 커밋
# 두 번째 커밋으로 돌아가기
git reset --hard abc1234
git push origin develop --force
민감한 파일의 이력까지 완전 삭제
비밀번호나 API 키가 커밋 이력에 남아있을 때, 모든 이력에서 완전히 제거합니다.
git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch secrets.json" \
--prune-empty -- --all
git push origin develop --force
> 이 명령은 전체 커밋 이력을 다시 쓰기때문에, 팀 전원이 `git pull --rebase`를 해야 합니다.
8. 충돌(Conflict) 해결 완전 가이드
충돌이 발생하는 이유
같은 파일의 같은 부분을 두 사람이 동시에 수정했을 때 Git이 자동으로 합칠 수 없어서 발생합니다.
개발자 A: login.js 10번째 줄을 "v1"으로 수정 → push
개발자 B: login.js 10번째 줄을 "v2"로 수정 → push (충돌 발생)
충돌 발생 시 화면
$ git pull origin develop
CONFLICT (content): Merge conflict in src/login.js
Automatic merge failed; fix conflicts and then commit the result.
충돌 파일을 열면 이렇게 보입니다:
function login() {
<<<<<<< HEAD
// 내가 수정한 코드
return axios.post('/api/v2/login', data);
=======
// 상대방이 수정한 코드
return axios.post('/api/v1/login', data);
>>>>>>> origin/develop
- `<<<<<<< HEAD` ~ `=======` : 내 코드
- `=======` ~ `>>>>>>> origin/develop` : 상대방 코드
해결 방법 3가지
방법 1: 상대방 코드로 맞추기
git checkout --theirs .
git add .
git commit -m "fix: resolve merge conflicts"
git push origin develop
방법 2: 내 코드 유지하기
git checkout --ours .
git add .
git commit -m "fix: resolve merge conflicts"
git push origin develop
방법 3: 수동으로 편집하기
파일을 직접 열어서 `<<<<<<<`, `=======`, '>>>>>>>` 를 지우고 원하는 코드만 남깁니다.
// 수정 전 (충돌 상태)
<<<<<<< HEAD
return axios.post('/api/v2/login', data);
=======
return axios.post('/api/v1/login', data);
>>>>>>> origin/develop
// 수정 후 (원하는 코드만 남김)
return axios.post('/api/v2/login', data);
git add .
git commit -m "fix: resolve merge conflicts"
git push origin develop
merge 자체를 취소하고 싶을 때
충돌이 너무 복잡하면 merge를 취소하고 처음부터 다시 할 수 있습니다.
git merge --abort
충돌 해결 순서 요약
1. git pull origin 브랜치명 ← 충돌 발생
2. 충돌 해결 (theirs/ours/수동)
3. git add .
4. git commit -m "fix: resolve merge conflicts"
5. git push origin 브랜치명
9. stash - 작업 임시 저장
stash 란?
작업 중인 변경사항을 커밋하지 않고 임시 저장하는 기능입니다.
언제 사용할까?
- 기능 개발 중인데 긴급 버그 수정을 해야 할 때
- 브랜치를 바꿔야 하는데 아직 커밋하기엔 이른코드가 있을 때
- CI/CD 서버에서 `git pull` 전에 로컬 변경사항을 치워야 할 때
사용법
# 현재 변경사항 임시 저장
git stash
# 다른 브랜치에서 작업
git checkout hotfix/bug-123
# ... 버그 수정 ...
git commit -m "Fix critical bug"
git push origin hotfix/bug-123
# 원래 브랜치로 돌아와서 임시 저장 복원
git checkout feature/login
git stash pop
statsh 관련 명령어
git stash # 임시 저장
git stash pop # 복원 + 삭제
git stash apply # 복원 (삭제 안 함)
git stash list # 임시 저장 목록 확인
git stash drop # 가장 최근 stash 삭제
git stash clear # 모든 stash 삭제
메시지와 함께 저장
# 어떤 작업이었는지 메모 남기기
git stash push -m "로그인 페이지 작업 중"
$ git stash list
stash@{0}: On feature/login: 로그인 페이지 작업 중
10. 실무에서 자주 겪는 상황별 해결법
push가 거부될 때
$ git push origin develop
! [rejected] develop -> develop (fetch first)
원격에 내가 받지 않은 커밋이 있다는 뜻입니다.
git pull origin develop # 최신 코드 받기
# 충돌 있으면 해결 후
git push origin develop
잘못된 파일을 add 했을 때
# staging 취소 (파일 변경은 유지)
git restore --staged .env
마지막 커밋 메시지를 수정하고 싶을 때
git commit --amend -m "수정된 커밋 메시지"
> 이미 push한 커밋이면 `--force` push가 필요합니다.
이미 올라간 파일을 .gitignore에 추가하고 싶을 때
git rm --cached .env # 추적 해제
# .gitignore에 .env 추가
git add .gitignore
git commit -m "Remove .env and update .gitignore"
git push origin develop
여러 원격 저장소 사용하기
# 원격 저장소 확인
$ git remote -v
origin https://gitlab.com/team/project.git (GitLab)
github https://github.com/user/project.git (GitHub)
# GitLab에만 push
git push origin develop
# GitHub에만 push
git push github develop
MERGING 상태에서 벗어나기
`(브랜치명|MERGING)` 상태가 보일 때:
# 방법 1: merge 취소
git merge --abort
# 방법 2: 충돌 해결 후 완료
git add .
git commit -m "fix: resolve merge conflicts"
11. Git 명령어 정리
일상 명령어
| 상황 | 명령어 |
| 상태 확인 | `git status` |
| 이력 확인 | `git log --oneline` |
| 변경 내용 확인 | `git diff` |
| 코드 올리기 | `git add . → git commit -m "msg" → git push origin 브랜치` |
| 코드 받기 | `git pull origin 브랜치` |
브랜치
| 상황 | 명령어 |
| 브랜치 생성 + 이동 | `git checkout -b 브랜치명` |
| 브랜치 이동 | `git checkout 브랜치명` |
| 브랜치 삭제 | `git branch -d 브랜치명` |
| 브랜치 목록 | `git branch` |
되돌리기
| 상황 | 명령어 |
| staging 취소 | `git restore --staged 파일명` |
| 커밋 취소 (코드 유지) | `git reset --soft HEAD~1` |
| 커밋 취소 (코드 삭제) | `git reset --hard HEAD~1` |
| merge 취소 | `git merge --abort` |
삭제
| 상황 | 명령어 |
| 파일 삭제 (로컬+원격) | `git rm 파일명 → commit → push` |
| 파일 삭제 (원격만) | `git rm --cached 파일명 → commit → push` |
| 커밋 이력 삭제 | `git reset --hard HEAD~N → push --force` |
| 민감 파일 이력 삭제 | `git filter-branch` |
충돌 해결
| 상황 | 명령어 |
| 상대방 코드로 | `git checkout --theirs . → add → commit → push` |
| 내 코드로 | `git checkout --ours . → add → commit → push` |
| merge 취소 | `git merge --abort` |
임시 저장
| 상황 | 명령어 |
| 임시 저장 | `git stash` |
| 복원 | `git stash pop` |
| 목록 확인 | `git stash list` |
감사합니다.
'Computer Science' 카테고리의 다른 글
| SBOM[Software Bill of Materials]란? (5) | 2025.07.24 |
|---|---|
| 수열 편집, 재배치, 중첩 문제에서 어떻게 LIS를 활용하는가? (0) | 2025.04.22 |
| LDS(최장 감소 부분 수열) (0) | 2025.04.22 |
| LIS(최장 증가 부분 수열) (1차원 DP부터 이분탐색) (1) | 2025.04.22 |
| LCS(최장 공통 부분 수열 & 문자열 DP 문제) (0) | 2025.04.22 |
