01. 로컬 저장소 다루기
사용자 정보 설정
Git은 모든 버전에 누가 만들었는지 기록한다. 이 정보를 설정하는 것은 필수이다.
- Global 설정
~/.gitconfig 파일에 저장되며, 이 컴퓨터에서 시작하는 모든 Git 프로젝트의 기본값이 된다.
1
2
| git config --global user.name "Your Name"
git config --global user.email "your@email.com"
|
- Local 설정
- 해당 프로젝트 폴더 안에서
--global 옵션을 빼고 설정하면 된다. 해당 프로젝트의 .git/config 파일에 저장된다.
1
2
| git config user.name "Your Name"
git config user.email "your@email.com"
|
새로운 저장소 시작하기
1
2
3
| mkdir my-project
cd my-project
git init
|
1
2
| cd existing-project
git init
|
핵심 워크 플로우
- 파일 수정 또는 생성 (Working Directory)
- 변경사항 확인(
status): 현재 Git 상태를 확인1
2
3
4
| git status
# Changes to be committed: Staging Area에 올라가 있는, 커밋 대기 중인 변경사항.
# Changes not staged for commit: Working Directory에서 수정되었지만 아직 스테이징되지 않은 변경사항.
# Untracked files: 새로 생성되어 Git이 한 번도 관리한 적 없는 파일.
|
변경사항을 스테이징하기(add): Working Directory의 변경사항을 Staging Area로 옮기는 작업
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| # 특정 파일 하나만 올리기
git add file1.txt
# 특정 폴더 전체를 올리기
git add docs/
# 변경된 모든 파일을 올리기
git add .
# 변경된 부분을 하나씩 확인하며 선택적으로 올리기
git add -p
# 스테이징된 파일 되돌리기
git restore --staged file1.txt
# 스테이징된 모든 파일을 한 번에 내리고 싶을 때
git restore --staged .
|
스테이징된 내용을 버전으로 기록(commit): Staging Area에 있는 파일들을 하나의 의미있는 버전(스냅샷)으로 만들어 Repository에 영구 저장한다.
1
2
3
4
5
| # -m 옵션으로 커밋 메시지를 바로 입력
git commit -m "Feat: 사용자 로그인 기능 구현"
# 제목과 본문을 나누어 상세한 메시지 작성 (-m 옵션 여러 번 사용)
git commit -m "Fix: 이메일 유효성 검사 오류 수정" -m "정규 표현식에서 '+' 문자를 지원하지 않던 문제를 해결함."
|
Commit Message 작성법 (권장)
- 구조
1
2
3
4
5
| <type>(<scope>): <subject>
<body>
<footer>
|
- 타입(type)
- 이 커밋이 어떤 종류의 작업인지 나타냄
- feat: 새로운 기능 추가
- fix: 버그 수정
- docs: 문서 수정
- style: 코드 스타일 변경 (로직 변경 없음)
- refactor: 코드 리팩토링 (기능 변경 없음)
- test: 테스트 코드 추가
- chore: 빌드 시스템 또는 패키지 관리 작업
- 스코프(scope)
- 이 커밋이 영향을 미치는 범위를 괄호 안에 명시
- 제목(subject)
- 커밋의 핵심 내용을 간략하게 요약하여 명령문, 현재 시제로 작성한다. 첫 글자는 대문자로, 문장 끝에 마침표를 붙이지 않는다. (예:
Add login feature) - 본문(body)
- 제목과 한 줄을 비우고 작성한다. 커밋의 상세 내용을 작성한다.
- 꼬리말(footer)
- 본문과 한 줄을 비우고 작성한다. 관련된 이슈 번호 등을 작성한다. (예:
Closes #123, See also #456)
과거 기록 살펴보기
- log
- 커밋 히스토리 조회
1
2
3
4
5
6
7
8
| # 전체 기록 보기
git log
# 한 줄로 깔끔하게 보기
git log --oneline
# 브랜치 관계를 그래프로 보기
git log --oneline --graph --all
|
- diff
- 변경 내용 비교
1
2
3
4
5
6
7
8
| # Working Directory와 Staging Area 비교 (add 하기 전의 변경사항)
git diff
# Staging Area와 마지막 커밋 비교 (add 한 후의 변경사항)
git diff --staged
# 두 커밋 사이의 차이 비교
git diff <커밋_해시_A> <커밋_해시_B>
|
02. 원격 저장소 다루기
원격 저장소(remote) 관리
Remote는 내 컴퓨터가 아닌 다른 곳, 주로 GitHub에 있는 저장소를 가리키는 별명이다.
1
2
3
| # 보통 origin이라는 별명을 사용
# git remote add origin https://github.com/user/repo.git
git remote add <별명> <URL>
|
1
2
| # git remote remove origin
git remote remove <별명>
|
데이터 교환
- clone
- 원격 저장소를 내 컴퓨터에 통째로 복제한다. 자동으로
origin이라는 이름의 remote가 원본 URL을 가리키도록 설정된다.
1
2
| # git clone https://github.com/user/repo.git
git clone <URL>
|
- fetch
- 원격 저장소의 최신 변경사항을 가져오기만 한다. (내 로컬 파일은 전혀 건드리지 않음).
1
2
| # git fetch origin
git fetch <별명>
|
- pull
- 원격 저장소의 최신 변경사항을 가져오고 내 브랜치와 자동으로 병합한다.
1
2
| # git pull origin main
git pull <별명> <브랜치>
|
- push
- 내 로컬 브랜치의 변경사항을 원격 저장소에 업로드한다.
1
2
3
4
5
| # git push origin main
git push <별명> <브랜치>
# 만약 로컬에만 있는 새로운 브랜치를 push할 경우, -u 옵션으로 원격 브랜치와 연결
git push -u origin feature/new-login
|
03. 브랜치 다루기
브랜치는 독립적인 작업 공간을 만드는 Git의 가장 강력한 기능이다. main 브랜치를 안전하게 유지하면서, 새로운 기능 개발이나 버그 수정을 병렬적으로 진행할 수 있다.
브랜치 생성 및 이동
1
2
3
4
| git switch <이동할_브랜치_이름>
# 생성과 동시에 이동
git switch -c <이동할_브랜치_이름>
|
1
| git branch -d <삭제할_브랜치_이름>
|
브랜치 병합 (merge)
독립적으로 작업한 브랜치의 내용을 다른 브랜치(보통 main)와 합치는 과정이다.
- 합쳐질 브랜치로 먼저 이동한다.
- 최신 상태로 업데이트한다.
- 합칠 브랜치를 현재 브랜치로 가져와 병합한다.
1
2
| git merge <가져올_브랜치_이름>
# 예: git merge feature/new-login
|
- 충돌(Conflict) 해결: 병합 중 두 브랜치에서 같은 파일의 같은 부분을 수정한 경우 발생. Git이 알려주는 충돌 파일을 열어 직접 수정한 뒤, 다시
add -> commit을 진행하여 병합을 완료한다.
04. 작업 되돌리기 및 임시 저장
과거로 돌아가기
- reset
- 과거의 특정 커밋으로 상태를 되돌린다(히스토리 자체를 수정). 주의해서 사용해야 한다.
--soft: 커밋만 취소하고, 변경 내용은 Staging Area에 남겨둔다.--mixed(기본값): 커밋과 스테이징을 취소하고, Working Directory는 그대로 유지한다.--hard(위험): 커밋과 변경 내용을 모두 취소하고, Working Directory의 변경 내용을 모두 날려버린다.
1
2
3
| git reset --soft <커밋_해시>
git reset --mixed <커밋_해시>
git reset --hard <커밋_해시>
|
- revert
- 특정 커밋의 변경사항을 취소하는 새로운 커밋을 생성한다. 기존 히스토리를 건드리지 않아 원격 저장소에 미리 올라간 커밋을 되돌릴 때 안전하다.
작업 임시 저장
- stash
- 다른 브랜치로 급하게 이동해야 하는데 아직 커밋하기 애매한 작업이 있을 때 사용한다.
1
2
3
4
5
6
7
8
9
| # 현재 변경사항 임시 저장
git stash
# 임시 저장한 내용 다시 가져오기
# 가장 최근에 저장한 내용을 가져와 목록에서 삭제
git stash pop
# 임시 저장 목록 보기
git stash list
|
05. git rebase
- rebase
- 아직
push하지 않은 나만의 로컬 브랜치를 정리할 때만 사용하는 것으로 생각하자.
06. tag
- tag
- 특정 커밋에
v1.0.0이나 beta-release와 같이 잊기 어려운 이름표를 붙이는 기능이다. 커밋 해시는 기억하기 어렵지만, 태그는 의미를 가지므로 중요한 릴리즈 시점을 표시하는 데 매우 유용하다. 또한, tag는 커밋할 때 붙이는 것이 아니라, 이미 존재하는 특정 커밋에 이름표를 붙이는 것이다.
- Light Weight Tag: 단순한 책갈피처럼 특정 커밋을 기리키는 태그
- Annotated Tag: 태그를 만든 사람, 이메일, 날짜, 그리고 태그 메시지까지 별도의 객체로 저장하는 공식적인 태그이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| # 1. 주석 태그 생성 (가장 일반적인 방법)
# -a는 annotated, -m은 태그 메시지
git tag -a v1.0.0 -m "Initial stable release of the project"
# 2. 현재까지 생성된 태그 목록 보기
git tag
# 출력 예시:
# v1.0.0
# 3. 특정 태그의 상세 정보 보기
git show v1.0.0
# 4. 태그를 원격 저장소에 Push하기
# 태그는 git push를 해도 자동으로 올라가지 않고, 명시적으로 push 해야 한다.
git push origin v1.0.0
# (혹은 로컬의 모든 태그를 한 번에 push)
# git push origin --tags
|
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
| # 1. 여러 번의 커밋을 통해 작업을 진행한다.
git commit -m "Feat: Add user profile page"
git commit -m "Fix: Correct typo in main title"
git commit -m "Refactor: Optimize database queries" # <- 이 커밋이 v1.0.0 릴리즈 시점이라고 결정.
# 2. 로그를 확인하여 태그를 붙일 커밋의 해시를 확인하거나,
# 가장 최신 커밋에 붙일 것이라면 그냥 진행한다.
git log --oneline
# 출력 예시:
# a1b2c3d Refactor: Optimize database queries
# b2c3d4e Fix: Correct typo in main title
# c3d4e5f Feat: Add user profile page
# 3. 'git tag' 명령어를 사용해 이름표를 붙인다.
# 커밋 해시를 지정하지 않으면, 자동으로 가장 최신 커밋(HEAD)에 태그가 붙는다.
git tag -a v1.0.0 -m "Version 1.0.0 Release"
# (만약 과거의 특정 커밋, 예를 들어 'b2c3d4e'에 붙이고 싶다면)
# git tag -a v0.9.0 -m "Pre-release version" b2c3d4e
# 4. 태그가 잘 붙었는지 로그로 확인
git log --oneline
# 출력 예시:
# a1b2c3d (HEAD -> main, tag: v1.0.0) Refactor: Optimize database queries
# ...
|
07. Fork & Pull Request (PR)
Fork & PR 워크플로우
Fork: 원본 프로젝트를 내 GitHub 계정으로 그대로 복사한다.Clone: 내가 Fork한 Repository를 내 컴퓨터로 clone한다.Upstream: 내 로컬 저장소가 원본 프로젝트의 변경사항을 추적할 수 있도록, 원본 프로젝트의 주소를 upstream이라는 이름의 remote로 등록한다.1
2
3
4
5
6
| git remote add upstream https://github.com/original-owner/original-repo.git
git remote -v
# origin https://github.com/my-username/awesome-project.git (fetch)
# origin https://github.com/my-username/awesome-project.git (push)
# upstream https://github.com/original-owner/awesome-project.git (fetch)
# upstream https://github.com/original-owner/awesome-project.git (push)
|
- Branch & Code: 새로운 기능 추가를 위해 브랜치를 만들고 코드를 수정한다.
1
| git switch -c feature/add-new-button
|
- Sync & Push: 내 작업을 원본의 최신 변경사항과 동기화한 후, 내 Fork Repository(
origin)에 push한다.1
2
3
| git fetch upstream
git rebase upstream/main
git push origin feature/add-new-button
|
- Pull Request (PR): GitHub 웹사이트에서, 내가
push한 feature/add-new-button 브랜치의 내용을 원본 프로젝트의 main 브랜치로 합쳐달라는 공식적인 요청(PR)을 보낸다. 이제 원본 프로젝트의 관리자가 내 코드를 리뷰하고 병합 여부를 결정하게 된다.
Fork & Clone 후 개인화 예제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| git remote add upstream https://github.com/original-owner/original-repo.git
git remote -v
# origin https://github.com/my-username/awesome-project.git (fetch)
# origin https://github.com/my-username/awesome-project.git (push)
# upstream https://github.com/original-owner/awesome-project.git (fetch)
# upstream https://github.com/original-owner/awesome-project.git (push)
# 'main' 브랜치에서 'my-personal-dev' 라는 이름의 새 브랜치를 만들고 이동
git switch -c my-personal-dev
# 1. 파일 수정 및 생성
# ... 코드 작업 ...
# 2. 작업 내용 커밋
git add .
git commit -m "Feat: Add my custom feature"
# 3. 내 개인 작업 브랜치('my-personal-dev')를 내 개인 리포지토리('origin')로 push
# -u 옵션은 최초 push 시 로컬 브랜치와 원격 브랜치를 연결해준다.
git push -u origin my-personal-dev
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| # 1. 동기화 작업을 위해 'main' 브랜치로 이동
# (내 개인 작업 브랜치가 아닌, 깨끗한 main 브랜치에서 진행)
git switch main
# 2. 공식 리포지토리('upstream')의 최신 내용을 가져옴
git fetch upstream
# 3. 가져온 'upstream/main'의 내용을 내 로컬 'main' 브랜치에 병합(merge)
# (rebase를 사용해도 되지만, merge가 더 직관적이고 안전)
git merge upstream/main
# 4. 이제 내 로컬 'main' 브랜치는 공식 리포지토리와 완전히 동일한 최신 상태가 됨
# 이 최신 상태를 내 GitHub 개인 리포지토리('origin')에도 저장해 둠
git push origin main
# 5. 마지막으로, 내 개인 작업 브랜치로 돌아와서 최신화된 'main'의 내용을 합쳐줌
git switch my-personal-dev
git merge main
|
08. 브랜치 전략
Git Flow
- 개념
main, develop이라는 두 개의 핵심 브랜치와 feature, release, hotfix라는 보조 브랜치들을 사용하는 전략
main: 오직 배포된 버전의 코드만 존재하는 가장 안정적인 브랜치develop: 다음 버전을 위해 개발중인 코드가 모이는 브랜치feature: develop에서 분기하여 새로운 기능을 개발하고, 완료되면 develop으로 변합release: 배포 준비를 위해 develop에서 분기하여 QA 및 버그 수정을 진행하고, 완료되면 main과 develop 양쪽에 모두 병합hotfix: main에서 발생한 긴급 버그를 수정하기 위해 분기하고, 완료되면 main과 develop에 병합
GitHub Flow
- 개념
main 브랜치는 항상 배포 가능한 상태로 유지되어야 한다는 원칙을 가진 단순하고 빠른 전략
main에서 기능 개발을 위한 브랜치를 딴다.- 개발 및 커밋을 진행한다.
- Pull Request를 생성하여 코드 리뷰와 논의를 거친다.
- 리뷰가 완료되면
main에 병합한다. - 병합된
main은 즉시 또는 주기적으로 배포된다.
09. Submodule
1
2
3
4
5
6
7
8
9
| # submodule 추가
git submodule add <레포지토리_URL>
# submodule 업데이트
cd <서브모듈_디렉토리>
git pull origin main # 또는 master
cd ..
git add <서브모듈_디렉토리>
git commit -m "Update submodule"
|