Post

Git(Hub) 기초 정리

Git(Hub) 기초 정리

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
  • 기존 프로젝트를 Git으로 관리 시작
1
2
cd existing-project
git init

핵심 워크 플로우

  1. 파일 수정 또는 생성 (Working Directory)
  2. 변경사항 확인(status): 현재 Git 상태를 확인
    1
    2
    3
    4
    
     git status
     # Changes to be committed: Staging Area에 올라가 있는, 커밋 대기 중인 변경사항.
     # Changes not staged for commit: Working Directory에서 수정되었지만 아직 스테이징되지 않은 변경사항.
     # Untracked files: 새로 생성되어 Git이 한 번도 관리한 적 없는 파일.
    
  3. 변경사항을 스테이징하기(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 .
    
  4. 스테이징된 내용을 버전으로 기록(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
git remote -v
  • 새로운 원격 저장소 추가
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
git branch
  • 새로운 브랜치 생성
1
git branch <브랜치_이름>
  • 브랜치 이동 (checkout)
1
2
3
4
git switch <이동할_브랜치_이름>

# 생성과 동시에 이동
git switch -c <이동할_브랜치_이름>
  • 브랜치 삭제
1
git branch -d <삭제할_브랜치_이름>

브랜치 병합 (merge)

독립적으로 작업한 브랜치의 내용을 다른 브랜치(보통 main)와 합치는 과정이다.

  1. 합쳐질 브랜치로 먼저 이동한다.
    1
    
    git switch main
    
  2. 최신 상태로 업데이트한다.
    1
    
    git pull origin main
    
  3. 합칠 브랜치를 현재 브랜치로 가져와 병합한다.
    1
    2
    
    git merge <가져올_브랜치_이름>
    # 예: git merge feature/new-login
    
  4. 충돌(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
특정 커밋의 변경사항을 취소하는 새로운 커밋을 생성한다. 기존 히스토리를 건드리지 않아 원격 저장소에 미리 올라간 커밋을 되돌릴 때 안전하다.
1
git 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는 커밋할 때 붙이는 것이 아니라, 이미 존재하는 특정 커밋에 이름표를 붙이는 것이다.
  1. Light Weight Tag: 단순한 책갈피처럼 특정 커밋을 기리키는 태그
  2. Annotated Tag: 태그를 만든 사람, 이메일, 날짜, 그리고 태그 메시지까지 별도의 객체로 저장하는 공식적인 태그이다.
  • 워크플로우 및 코드 예시 1
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
  • 워크플로우 및 코드 예시 2
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 워크플로우

  1. Fork: 원본 프로젝트를 내 GitHub 계정으로 그대로 복사한다.
  2. Clone: 내가 Fork한 Repository를 내 컴퓨터로 clone한다.
  3. 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)
    
  4. Branch & Code: 새로운 기능 추가를 위해 브랜치를 만들고 코드를 수정한다.
    1
    
     git switch -c feature/add-new-button
    
  5. Sync & Push: 내 작업을 원본의 최신 변경사항과 동기화한 후, 내 Fork Repository(origin)에 push한다.
    1
    2
    3
    
     git fetch upstream
     git rebase upstream/main
     git push origin feature/add-new-button
    
  6. Pull Request (PR): GitHub 웹사이트에서, 내가 pushfeature/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 및 버그 수정을 진행하고, 완료되면 maindevelop 양쪽에 모두 병합
  • hotfix: main에서 발생한 긴급 버그를 수정하기 위해 분기하고, 완료되면 maindevelop에 병합

GitHub Flow

개념
main 브랜치는 항상 배포 가능한 상태로 유지되어야 한다는 원칙을 가진 단순하고 빠른 전략
  1. main에서 기능 개발을 위한 브랜치를 딴다.
  2. 개발 및 커밋을 진행한다.
  3. Pull Request를 생성하여 코드 리뷰와 논의를 거친다.
  4. 리뷰가 완료되면 main에 병합한다.
  5. 병합된 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"
This post is licensed under CC BY 4.0 by the author.