Git과 Github 심화 1

j0yy00n0·2025년 5월 20일

2025.04.24

Git과 Github 심화

Branch

Git에서 독립적으로 작업을 진행할 수 있는 분리된 공간

  • 프로젝트의 메인 코드(main branch)를 유지하면서 새로운 기능 개발, 버그 수정, 실험 등을 안전하게 진행
  • 작업이 완료되면 브랜치를 메인 코드에 병합(merge)하여 변경 사항을 반영

Branch 기본 개념

Git 저장소 내에서 특정 시점의 커밋을 가리키는 이름이 붙은 포인터

  • 기본적으로 Git 저장소를 생성하면 main 이라는 기본 브랜치가 생성
  • 새로운 브랜치를 생성하여 작업하면, 기존 코드에 영향을 주지 않고 독립적인 작업을 수행
  • 안전한 개발: 메인 코드에 영향을 주지 않고 새로운 기능이나 실험을 진행할 수 있다
  • 협업 효율성: 여러 개발자가 각자의 브랜치에서 작업한 뒤, 병합하여 하나의 프로젝트로 통합
  • 버전 관리 용이: 특정 기능이나 릴리스 버전을 별도의 브랜치로 관리

Branch 명령어

git branch : 현재 브랜치 목록 확인
git branch feature/브랜치명 : 새 브랜치 생성

git checkout feature/브랜치명 : 기존 특정 브랜치로 전환
git checkout -b feature/브랜치명 : 새 브랜치를 생성하고 해당 브랜치로 전환

git merge feature/브랜치명 : 다른 브랜치를 현재 브랜치에 병합

git branch -d feature/브랜치명 : 로컬에서 특정 브랜치를 삭제
git push origin --delete feature/브랜치명 : 원격 저장소에서 특정 브랜치를 삭제 

git config --global init.defaultBranch main : 새로 생성되는 git저장소의 기본 브랜치 이름을 설정
git branch -M main : 현재 저장소의 특정 브랜치를 다른 이름으로 변경

<!-- Switch 명령어 사용법 -->
git switch feature/브랜치명 : 기존 브랜치로 전환
git switch -c feature/브랜치명 : 새 브랜치를 생성하고 해당 브랜치로 전환

Switch 명령어와 Checkout 명령어의 차이

git switch : 오직 브랜치 전환만을 목적으로 사용되며, 더 직관적이고 명확
git checkout : 브랜치 전환뿐만 아니라 파일 복구 등 다양한 용도로 사용

작업 진행

새 브랜치 생성
상태변경

  • main branch에서 브랜치로 변경
    작업 진행
  • 브랜치에서 코드를 수정하거나 파일 추가
git status : 상태확인
git add . : 모든 파일을 staging area에 추가
git commit -m "커밋 메시지" : staging area에서 local area로 이동
git log : 현재 진행된 로그 확인
- git log --all --graph --oneline : 브랜치 흐름을 간단히 시각화

병합(Merge)

  • 작업이 완료되면, 새로 만든 브랜치를 메인(main)으로 병합
git checkout main : main으로 이동
git pull origin main : 최신 상태로 갱신
git merge feature/브랜치명 : 병합

병합 후 정리

  • 병합이 완료되면 더 이상 필요없는 로컬 / 원격 브랜치를 삭제
git branch -d feature/브랜치명 : 로컬에서 삭제
git push origin --delete feature/브랜치명 : 원격 저장소에서 브랜치 삭제

Merge

Fast-forward Merge

병합 대상 브랜치가 현재 브랜치에서 직선으로 이어져 있을 경우

  • 두 브랜치 간 변경 사항이 충돌하지 않을 경우, 단순히 포인터를 이동하여 병합

3-way Merge

두 브랜치 간 변경 사항이 충돌하거나 서로 다른 변경 기록이 있을 경우, 공통 조상(merge base)을 기준으로 병합

  • Git은 세 지점(공통 조상, 현재 브랜치, 병합할 브랜치)을 비교하여 병합
  • 충돌이 발생하면 Git이 충돌 부분을 표시하며, 사용자가 직접 해결
<<<<<<< HEAD
main 브랜치의 코드
=======
feature 브랜치의 코드
>>>>>>> feature
  • 충돌 시 메인 헤더 부분과 변경된 브랜치 부분을 확인할 수 있다.
  • <<<<<<<, =======, >>>>>>> 표시를 보고 충돌한 부분을 수정
  • 수정 완료 후 충돌 표시 제거
  • 수정된 파일을 staging 영역에 추가(add) 후 commit 수행

Github issue 대처방법

staging 취소하기

git reset : 모든 스테이지된 파일 언스테이징
git reset 파일명.확장자 : 해당 파일만 언스테이징
  • staging area에서 파일을 제거하지만 작업 디렉토리의 변경 내용은 유지

마지막 commit 취소하기

git reset --soft HEAD^ : 커밋을 취소하고 스테이징 상태 유지
  • --soft : 작업 디렉토리와 인덱스를 보존해 파일이 스테이지된 상태를 유지
  • HEAD^ : 현재 브랜치에서 직전 커밋을 가리킴

마지막 커밋 메시지 수정하기

git commit --amend -m "수정할 커밋메시지" : 직전 commit 메시지 수정

이미 푸시한 커밋 메시지 수정하기

먼저 해당 커밋으로 리베이스

git rebase -i : 커밋 내역 조회
-  --interactive, -i 옵션을 주면 커밋 목록을 텍스트 편집기로 열어 수정 가능
<커밋내역>
pick 381cd2a 코드 품질 개선
pick f772ba1 테스트ㅌ 코드 추가
pick 2ad65fe 하단 버튼 추가
  • 수정하고자 하는 커밋 해시코드 앞에 pick을 edit / e로 바꾸고 저장
pick 381cd2a 코드 품질 개선
edit f772ba1 테스트 코드 추가
pick 2ad65fe 하단 버튼 추가
  • 더 직관적이고 쉽게 커밋 정보 변경
git commit --amend -m "커밋 메시지"
  • 리베이스 계속 진행
git rebase --continue
  • 원격 저장소에 강제 푸시
git rebase --abort : 리베이스 중단
  • 원격 저장소에 강제 푸시
git push origin 브랜치명 --force : 과거 커밋 이력 변경
  • --force / -f : 협업 중인 동료의 히스토리까지 덮어쓸 수 있으므로 사전 협의 필요

커밋을 과거로 되돌리기

먼저 커밋 해시 코드 확인

git reflog : HEAD 이동 내역 및 커밋 해시 조회
git reset --mixed 해시코드 : reset의 기본 옵션, 작업 디렉토리는 그대로 유지, 헤드와 인덱스  변경
git reset --hard 해시코드 : 작업 디렉토리, 헤드, 인덱스 모두 변경
git reset -- soft 해시 코드 : 헤드만 변경(스테이징 상태 유지)
  • 이 방법은 과거 커밋으로 이동하면서 이후 커밋 기록을 삭제
  • 커밋이후 --force 으로 푸시하면 이미 푸시한 커밋까지 되돌릴 수도 있지만, 권장하는 방법은 아니다

푸시한 커밋을 과거로 되돌리기

git reflog : 커밋 로그 확인

git rever 해시코드3...해시코드1 : 되돌리고 싶은 커밋의 범위를 지정한다.
Revert "되돌리고 싶은 커밋 메시지"

git push origin master : 변경 사항 원격 반영
  • revert는 커밋을 "취소하는 새로운 커밋"을 생성하므로 기록이 보존
  • 자동으로 메시지 입력창이 뜨며, 원하는 메시지를 작성

푸시한 파일 삭제하기

git rm --cashed 파일명.확장자 : 인덱스에서만 파일 삭제, 로컬 저장소의 파일은 지우지 않는다.
  • 히스토리가 그대로 남기 때문에 민감한 파일의 경우 이 방법으로 지우면 안된다.
  • 커밋에서 제외할 파일은 미리 .gitignore 파일에 명시
  • .env, .yaml 등

푸시한 파일 흔적없이 삭제하기

git filter-branch -f --index-filter "git rm --cached --ignore-unmatch 파일명.확장자" HEAD : 모든 커밋에서 아무런 내용이 없는 빈 커밋

git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch 파일명.확장자" --prune-empty --tag-name-filter cat -- --all
  • filter-branch : 브랜치의 히스토리 전체에서 특정 커밋만 필터링 해서 수정
  • --index-filter : 인덱스에서 특정 파일 제거
  • rm --ignore-unmatch : 파일이 일치하지 않아도 에러없이 0을 리턴하도록 해서 명령이 반복되게 한다.
git filter-branch -f --prune-empty HEAD : 모든 히스토리에서 빈 커밋을 제거
git push -f origin master : 모든 커밋 푸시
  • 민감한 정보가 유출된 경우 이 방법 사용

원격 저장소에서 업데이트 받아오기

git fetch origin : 원격 저장소의 최신 커밋들을 로컬 저장소로 가져온다.
  • origin : 원격 저장소 이름
  • git checkout 브랜치명 -> 명령으로 원격 저장소에서 가져온 업데이트를 확인할 수 있다
git checkout 브랜치명 : 브랜치 이동
git merge origin/브랜치명 : 병합
  • 병합과정에서 충돌(Conflicts)이 발생하면 직접 파일을 수정
git pull origin 브랜치명
  • fetch 와 merge 를 연달아 진행
  • 현재 체크아웃하고 있는 브랜치의 원격 저장소에서 내용을 가져오는 경우 매개변수(예시에서는 origin 브랜치명 )를 생략해도 된다

병합 커밋없이 풀하기

원격 저장소와 로컬 저장소 모두 새로운 커밋을 가지고 있으면 논 패스트 포워드(Non fast-forward) 발생

  • "Merge branch ‘master’ of https://github.com/브랜치/브랜치 와 같은 메시지를 가진 별도의 병합 커밋이 필요하다.
  • 병합 커밋을 만들기 시작하면 히스토리가 지저분해진다.
 git pull --rebase : 리베이스 병합
  • 로컬 브랜치의 커밋을 원격 브랜치 위로 다시 쌓아 올리는 방식
  • 이때 스테이징되지 않은 변경 사항이 있으면 안된다.

포크한 로컬 저장소를 최신으로 유지하기

git remote add upstream https://github.com/원본저장소/프로젝트.git
  • upstream은 원본 저장소(내가 포크해온 대상)
  • origin은 내 GitHub 계정의 포크된 저장소
git remote --verbose : 원격 저장소 목록

origin https://github.com/내계정/프로젝트.git
upstream https://github.com/원본계정/프로젝트.git
git fetch upstream
git checkout master
git merge upstream/master
  • 원본 저장소(upstream)의 master 브랜치를 내 로컬 master 브랜치와 병합하여 최신 상태로 유지

작업 내용 백업 -> 다른 브랜치에 체크아웃하기

git stash : 작업 디렉토리 헤드로 이동
  • 현재 작업 중인 변경 사항을 임시로 저장하고, HEAD 기준으로 작업 디렉토리를 깨끗한 상태로 초기화
  • 커밋하지 않은 변경사항(수정/삭제)은 저장되지만, 새로 생성된 파일은 stash에 저장되지 않음
git checkout 브랜치명 : 다른 브랜치로 이동
git stash pop : 백업한 내용 되돌리기
  • 가장 최근의 stash 내용을 복원하고 목록에서 제거
git stash save 설명 : 설명 붙여서 백업
git stash list : 목록 확인

git stash pop stash@{아이디} : 특정 백업 복원
  • 특정 stash 항목을 복원하고 삭제
git stash apply stash@{1}
  • 복원만 하고 삭제하지 않는 방법

풀 리퀘스트에서 Squash and Merge된 커밋 제외하기

main → featA → featB 구조에서,
featA는 이미 Squash and Merge 방식으로 main에 merge되었고,
featB만 따로 PR 보내고 싶은 상황

git checkout featB

git rebase --onto master featA
- git rebase --onto [새 베이스] [제거할 부모] [브랜치]

git push -f origin featB
  • featB에서 featA에서만 나온 커밋들을 main을 부모로 하여 다시 적용
  • 커밋을 제외하거나 뺀다는 개념이 아니고 새로운 베이스(main) 위에 커밋을 다시 쌓는다는 개념
  • 커밋이 버려지지만 사라지지는 않는다.

병합 충돌 해결하고 풀 리퀘스트 보내기

  1. 다른 브랜치의 main을 가져와 현재 나의 브랜치에 merge
git pull origin master
  • 현재 브랜치에서 master를 병합
  • HEAD는 현재 나의 변경사항이고 === 아래는 다른 브랜치의 main 내용이다.
  • <<<<<<<, =======, >>>>>>> 표기된 부분 수정
git add .
git merge --comtinue
git push origin 브랜치명

Merge branch 'master' of https://github.com/원격 저장소/브랜치명 : 병합 커밋 메시지
  1. 브랜치를 main 브랜치의 최신 커밋에 rebase
git checkout 브랜치명
git pull --rebase origin master
  • master의 커밋 위에 현재 브랜치의 커밋들을 하나씩 재적용
  • 브랜치가 main의 커밋에 하나씩 이동하여 가장 최신의 커밋으로 이동한다.
  • 이동 중에 병합 충돌이 발생하면 리베이스가 중단된다.
  • 충돌 시 <<<<<<<, =======, >>>>>>> 표시를 보고 충돌한 부분을 수정
git add .
git rebase --continue : 리베이스 계속 진행
  • 이전 커밋에서 충돌이 있었으니 다음 커밋에서도 같은 충돌이 발생한다.
  • 충돌을 해결한다.
git push -f origin 브랜치명
  • 리베이스 방식을 사용할 때는 병합 충돌이 있는 모든 커밋들에 대해 충돌을 일일이 해결해줘야한다.

다른 브랜치에서 특정 커밋 복사해오기

브랜치 a의 파일을 복사해서 브랜치 b로 옮긴다.

  • 복사할 커밋의 해시를 확인
git checkout featA
git reflog
- git log
git checkout featB
git cherry-pick a의 변경할 파일의 해시코드
  • 해당 커밋만 featB에 반영

브랜치 이름 수정

git branch -m 기존이름 새이름
git push origin :기존이름     # 기존 브랜치 삭제
git push origin 새이름        # 새 브랜치 푸시
git push origin -u 새이름     # 추적 설정까지
  • 원격 브랜치까지 변경

Git 명령어 축약하기

.gitconfig 파일에서 alias를 설정

  • [ alias] 섹션에 축약형과 축약할 명령을 작성하고 저장
vim ~/.gitconfig : 설정 파일 열기

[alias]
축약형 = 축약할 명령
[alias]
co = checkout
br = branch
ci = commit
st = status
lg = log --oneline --graph --decorate --all

Github 협업 가이드

용어 정의

Issue(이슈)

프로젝트를 진행하면서 발생하는 다양한 이벤트들을 의미

  • 발견된 버그나 추가할 기능, 개발해야 할 새로운 이슈나 설계사항들을 이슈로 만들어서 동료들과 협업을 진행

  • Settings → Issues에서 이슈 템플릿을 설정할 수 있다.

  • 템플릿을 통해 작성 형식을 팀에서 통일할 수 있다

  • Template content 직접 수정해서 원하는 형식으로 고정 가능

  • 이슈 템플릿을 정하면 이슈를 정할 때 원하는 형식으로 나오게 된다.

Assignee(담당자)

해당 이슈 또는 Pull Request(Pull 요청)에 대해 책임지고 처리할 담당자

  • 한 명 또는 여러 명 지정 가능

Label(레이블)

다양한 종류의 이슈 중 각 이슈가 어떤 종류, 상태, 우선순위 등을 구별하기 위한 것

  • 다수의 라벨을 동시에 부착할 수 있으며, 필터링 기능으로 관리에 용이

Milestones(마일스톤)

스프린트 개발 방법론을 지원하기 위한 기능

  • 특정 기간 내 해결해야 할 이슈들을 묶어 관리
  • 관련 이슈들을 생성한 후 엮여 있는 이슈들의 Open, Close 상태를 추적
  • 전체 이슈 중 몇 개의 이슈가 Close 되었는지를 추적해서 마일스톤의 진척상황으로 퍼센트로 보여준다

Projects(프로젝트)

작업 현황과 진행도를 볼 수 있는 메뉴

  • 이슈, PR 들을 하나의 작업으로 구분해 그 작업이 현재 어느 정도 진행되었는지 확인
  • Todo, In Progress, Done과 같은 기능을 제공 -> 프로젝트 진행상황을 한 번에 파악하기 수월
  • GitHub Issues 및 PR과 연동 가능

Pull Requests

코드 변경 사항을 특정 브랜치(main 등)에 병합해 달라고 요청하는 기능

  • 리뷰어 지정, 코멘트 추가, 변경 요청 등이 가능하며, 병합 시 merge, squash, rebase 방식 선택 가능
  • PR 본문에 Closes #이슈번호를 쓰면 병합 시 이슈도 자동으로 닫힘

Workflows

이슈나 PR에 이벤트 기반 자동 작업 설정 가능 (GitHub Actions 활용)

profile
잔디 속 새싹 하나

0개의 댓글