특정 커밋 시점으로 되돌리며, 그 이후의 커밋 이력을 제거한다.
# --soft: 커밋만 되돌리고, 변경사항은 staging area에 유지
git reset --soft <커밋해시>
# --mixed (기본값): 커밋을 되돌리고, 변경사항은 working directory에 유지
git reset --mixed <커밋해시>
git reset <커밋해시>
# --hard: 커밋을 되돌리고, 변경사항도 모두 삭제
git reset --hard <커밋해시>| 옵션 | 커밋 | staging area | working directory |
|---|---|---|---|
--soft |
되돌림 | 유지 | 유지 |
--mixed |
되돌림 | 되돌림 | 유지 |
--hard |
되돌림 | 되돌림 | 되돌림 |
주의:
--hard는 변경사항이 완전히 사라지므로 신중하게 사용해야 한다.
특정 커밋의 변경사항을 취소하는 새로운 커밋을 만든다. 기존 이력이 보존된다.
# 특정 커밋을 되돌리는 새 커밋 생성
git revert <커밋해시>
# 커밋 메시지 편집 없이 바로 revert
git revert --no-edit <커밋해시>
# revert 결과를 커밋하지 않고 staging area에만 반영
git revert --no-commit <커밋해시>팁: 이미 원격 저장소에 push한 커밋을 되돌릴 때는
reset대신revert를 사용하는 것이 안전하다.
특정 커밋 시점의 상태를 임시로 확인하거나, 특정 파일을 되돌린다.
# 특정 커밋 시점으로 이동 (Detached HEAD 상태)
git checkout <커밋해시>
# 원래 브랜치로 돌아오기
git checkout <브랜치명>
# 특정 파일만 해당 커밋 시점으로 되돌리기
git checkout <커밋해시> -- <파일경로>
# 작업 중인 파일의 변경사항 취소 (마지막 커밋 상태로 복원)
git checkout -- <파일경로>참고: Git 2.23 이후부터는
checkout의 역할이switch(브랜치 전환)와restore(파일 복원)로 분리되었다.git switch <브랜치명> # 브랜치 전환 git restore <파일경로> # 파일 복원
# 브랜치 목록 확인
git branch
# 새 브랜치 생성
git branch <브랜치명>
# 브랜치 생성과 동시에 이동
git switch -c <브랜치명>
# 브랜치 이름 변경
git branch -m <기존이름> <새이름>
# 브랜치 삭제 (병합된 브랜치만 삭제 가능)
git branch -d <브랜치명>
# 브랜치 강제 삭제 (병합되지 않은 브랜치도 삭제)
git branch -D <브랜치명>참고:
-d는 병합되지 않은 브랜치를 삭제하려 하면 경고가 뜬다. 정말 삭제하려면-D를 사용한다.
두 브랜치의 변경사항을 병합 커밋을 만들어 합친다.
# main 브랜치에서 feature 브랜치를 병합
git switch main
git merge <브랜치명>- 병합 이력이 커밋으로 남아 히스토리를 추적하기 쉽다.
- Fast-forward가 가능하면 별도의 병합 커밋 없이 포인터만 이동한다.
현재 브랜치의 커밋들을 대상 브랜치 끝으로 재배치한다.
# feature 브랜치에서 main을 기준으로 rebase
git switch <브랜치명>
git rebase main- 커밋 히스토리가 깔끔한 직선으로 정리된다.
- 이미 원격에 push한 커밋은 rebase하지 않는 것이 원칙이다.
| 항목 | merge | rebase |
|---|---|---|
| 히스토리 | 병합 커밋이 남음 | 직선으로 깔끔하게 정리 |
| 기존 커밋 | 변경 없음 | 커밋 해시가 변경됨 |
| 사용 시점 | 협업 브랜치, 공개 브랜치 | 개인 작업 브랜치 정리 시 |
브랜치 병합 시 같은 파일의 같은 부분을 다르게 수정했다면 **충돌(conflict)**이 발생한다.
<<<<<<< HEAD
현재 브랜치의 내용
=======
병합 대상 브랜치의 내용
>>>>>>> <브랜치명>
# 1. 충돌 파일을 열어 원하는 내용으로 수정
# 2. 수정 완료 후 staging
git add <충돌파일>
# 3. 병합 커밋 생성
git commit# 1. 충돌 파일을 열어 원하는 내용으로 수정
# 2. 수정 완료 후 staging
git add <충돌파일>
# 3. rebase 계속 진행
git rebase --continuerebase는 커밋 단위로 재배치하므로, 여러 커밋에서 충돌이 발생하면 각 커밋마다 충돌을 해결해야 한다.
충돌 해결이 어렵거나 병합을 취소하고 싶을 때 사용한다.
# merge 중단 (병합 이전 상태로 복원)
git merge --abort
# rebase 중단 (rebase 이전 상태로 복원)
git rebase --abort# 원격 저장소 목록 확인
git remote
# 원격 저장소 상세 정보 확인 (URL 포함)
git remote -v
# 원격 저장소 추가
git remote add <원격이름> <저장소URL>
# 원격 저장소 이름 변경
git remote rename <기존이름> <새이름>
# 원격 저장소 제거
git remote remove <원격이름>참고: 기본 원격 저장소 이름은 관례적으로
origin을 사용한다.
# 로컬 커밋을 원격 저장소에 업로드
git push
# 원격 저장소의 변경사항을 로컬로 가져와 병합
git pull원격에 새로운 커밋이 있고, 로컬에도 새로운 커밋이 있을 때 pull 방식을 선택할 수 있다.
# merge 방식 (기본값): 병합 커밋을 생성
git pull --no-rebase
# rebase 방식: 로컬 커밋을 원격 커밋 뒤로 재배치
git pull --rebase| 방식 | 특징 |
|---|---|
--no-rebase |
병합 커밋이 남아 이력이 보존됨 |
--rebase |
히스토리가 깔끔한 직선으로 정리됨 |
pull 시 같은 파일의 같은 부분을 수정했다면 충돌이 발생한다.
# merge 방식에서 충돌 해결
# 1. 충돌 파일을 열어 원하는 내용으로 수정
# 2. 수정 완료 후 staging & 커밋
git add <충돌파일>
git commit
# rebase 방식에서 충돌 해결
# 1. 충돌 파일을 열어 원하는 내용으로 수정
# 2. 수정 완료 후 staging & rebase 계속
git add <충돌파일>
git rebase --continue# 로컬의 이력을 원격에 강제로 덮어씌우기
git push --force주의:
--force는 원격의 커밋을 덮어쓰므로 협업 시 다른 사람의 작업을 날릴 수 있다. 신중하게 사용해야 한다.
# 원격 브랜치 명시 및 추적 설정 (-u: --set-upstream)
git push -u origin <브랜치명>최초 push 시
-u옵션을 사용하면 이후git push,git pull만으로 해당 원격 브랜치와 연동된다.
# 로컬 + 원격 브랜치 목록 전체 확인
git branch --all
git branch -a
# 원격의 브랜치를 로컬에 받아와서 전환 (-t: --track)
git switch -t origin/<브랜치명>
# 원격의 브랜치 삭제
git push <원격이름> --delete <브랜치명>Git은 파일을 3가지 공간으로 관리한다.
| 공간 | 설명 |
|---|---|
| Working directory (작업 디렉터리) | 실제 파일을 수정하는 공간. Untracked 파일과 Tracked 파일이 존재한다. |
| Staging area (스테이징 영역) | git add로 커밋할 준비가 된 변경사항이 올라가는 공간 |
| Repository (저장소) | git commit으로 확정된 커밋 이력이 저장되는 공간 (.git 디렉터리) |
Working directory --add--> Staging area --commit--> Repository
<-----------되돌림(reset 등)-----------
- Untracked: Git이 아직 추적하지 않는 새 파일
- Tracked: Git이 관리하고 있는 파일 (수정됨, 스테이징됨, 커밋됨 등)
HEAD는 현재 작업 중인 브랜치의 최신 커밋을 가리키는 포인터이다.
위 그림처럼 각 브랜치(main, delta-branch, alpha-branch, beta-branch)는 자신만의 최신 커밋을 가리키며, HEAD는 현재 체크아웃된 브랜치의 끝을 가리킨다.
# 한 커밋 이전으로 이동
git checkout HEAD^
# 세 커밋 이전으로 이동
git checkout HEAD~3^: 한 단계 이전 커밋~N: N단계 이전 커밋
# 한 커밋 전으로 reset (변경사항은 staging area에 유지)
git reset --soft HEAD^
# 한 커밋 전으로 reset (변경사항은 working directory에 유지)
git reset --mixed HEAD^
git reset HEAD^
# 한 커밋 전으로 reset (변경사항 모두 삭제)
git reset --hard HEAD^# 이전에 있던 브랜치 또는 커밋으로 되돌아가기
git checkout -
git checkout -는 직전에 체크아웃했던 위치로 다시 전환한다. 브랜치 간 빠르게 오갈 때 유용하다.
원격 저장소의 최신 커밋을 로컬로 가져오기만 한다. 현재 작업 중인 파일에는 영향을 주지 않는다.
# 원격의 최신 정보 가져오기
git fetch
# 특정 원격 저장소만 fetch
git fetch originfetch 후에는 원격의 변경사항이
origin/main등의 원격 추적 브랜치에만 반영된다. 로컬 브랜치에 적용하려면 별도로 merge 또는 rebase가 필요하다.
원격 저장소의 최신 커밋을 가져와서 자동으로 병합까지 수행한다. 즉, fetch + merge(또는 rebase)이다.
# fetch + merge
git pull
# fetch + rebase
git pull --rebase| 명령어 | 동작 | 로컬 파일 영향 |
|---|---|---|
git fetch |
가져오기만 | 없음 |
git pull |
가져오기 + 병합(merge/rebase) | 있음 |
원격에 새로운 브랜치가 추가되었을 때, fetch 후 확인하고 가져올 수 있다.
# 원격 정보 업데이트
git fetch
# 원격 브랜치의 내용을 임시로 확인 (Detached HEAD)
git checkout origin/<브랜치명>
# 원격 브랜치를 로컬에 받아와서 전환
git switch -t origin/<브랜치명>현재 작업 중인 변경사항을 임시로 저장하고 워킹 디렉터리를 깨끗한 상태로 되돌린다. 브랜치를 전환하거나 다른 작업을 먼저 해야 할 때 유용하다.
# 현재 변경사항을 스태시에 저장
git stash
# 메시지와 함께 스태시
git stash -m "작업 메시지"
# 원하는 변경사항만 골라서 스태시 (대화형)
git stash -p
# 스태시 목록 보기
git stash list| 명령어 | 설명 |
|---|---|
git stash apply |
스태시를 적용하되, 목록에서 제거하지 않음 |
git stash drop |
스태시를 목록에서 제거 (적용하지 않음) |
git stash pop |
스태시를 적용하고 목록에서 제거 (apply + drop) |
git stash branch <브랜치명> |
새 브랜치를 만들어 스태시를 적용 |
git stash clear |
모든 스태시를 삭제 |
팁: 번호를 지정하지 않으면 가장 최근 스태시(
stash@{0})가 대상이 된다. 특정 스태시를 지정하려면git stash apply stash@{2}형태로 사용한다.
# 마지막 커밋의 메시지와 내용을 수정 (편집기가 열림)
git commit --amend
# 메시지는 그대로 두고 내용(파일)만 업데이트
git commit --amend --no-edit- 수정할 파일을
git add로 스테이징한 뒤--amend하면 마지막 커밋에 반영된다. --no-edit을 붙이면 커밋 메시지 편집 없이 내용만 갱신한다.
주의: 이미 원격에 push한 커밋을 amend하면 이력이 변경되므로,
--forcepush가 필요해진다.
git rebase -i(interactive rebase)를 사용하면 과거 커밋들을 자유롭게 편집할 수 있다.
# 대상 커밋의 바로 이전 커밋을 지정
git rebase -i <대상 바로 이전 커밋>편집기가 열리면 각 커밋 앞의 명령어를 변경하여 원하는 작업을 수행한다.
| 명령어 | 약자 | 설명 |
|---|---|---|
pick |
p |
커밋을 그대로 사용 |
reword |
r |
커밋 메시지만 수정 |
edit |
e |
커밋을 수정 (멈춤 후 직접 수정 가능) |
drop |
d |
커밋을 삭제 |
squash |
s |
이전 커밋과 합치고 메시지를 편집 |
fixup |
f |
이전 커밋과 합치되 메시지는 이전 것을 사용 |
하나의 커밋을 여러 개로 나누고 싶을 때 edit을 활용한다.
# 1. interactive rebase 시작
git rebase -i <대상 바로 이전 커밋>
# 2. 분할할 커밋을 pick → edit(e)으로 변경 후 저장
# 3. 해당 커밋에서 멈추면, 커밋을 되돌리기
git reset HEAD~
# 4. 변경사항을 원하는 단위로 나누어 스테이징 & 커밋
git add <파일1>
git commit -m "첫 번째 분할 커밋"
git add <파일2>
git commit -m "두 번째 분할 커밋"
# 5. rebase 계속 진행
git rebase --continuegit restore는 파일의 변경사항을 되돌리는 명령어이다. (git checkout -- <파일>의 역할을 대체)
# 특정 파일의 변경사항을 되돌리기 (마지막 커밋 상태로 복원)
git restore <파일명>
# 모든 파일의 변경사항을 되돌리기
git restore .git add로 스테이징한 파일을 다시 언스테이징한다. 파일의 변경 내용은 유지된 채 staging area에서만 제거된다.
git restore --staged <파일명># HEAD에서 두 단계 이전 커밋의 상태로 되돌리기
git restore --source=HEAD~2 <파일명>
# 특정 커밋 해시의 상태로 되돌리기
git restore --source=<커밋해시> <파일명>참고:
--source옵션을 사용하면 현재 커밋이 아닌 원하는 시점의 파일 상태로 복원할 수 있다.
특정 시점을 키워드로 저장하고 싶을 때, 커밋에 버전 정보를 붙이고자 할 때 사용한다.
# 마지막 커밋에 태그 달기
git tag v1.0.0
# 메시지와 함께 태그 달기
git tag v1.0.0 -m "첫 번째 릴리즈"
# annotated 태그 (편집기가 열림)
git tag -a v1.0.0
# 원하는 커밋에 태그 달기
git tag <태그명> <커밋해시> -m "메시지"
# 현존하는 태그 목록 확인
git tag
# 원하는 태그의 내용 확인
git show v1.0.0
# 태그 삭제
git tag -d v1.0.0
# 원하는 버전으로 체크아웃
git checkout v1.0.0# 특정 태그를 원격에 올리기
git push <원격명> <태그명>
# ex) git push origin v1.0.0
# 로컬의 모든 태그를 원격에 올리기
git push <원격명> --tags
# 특정 태그를 원격에서 삭제
git push --delete <원격명> <태그명>git이 두 브랜치를 병합할 때 사용하는 두 가지 방식이다.
병합 대상 브랜치가 현재 브랜치의 앞에만 있을 때 (즉, 분기 없이 직선 관계일 때) 별도의 병합 커밋 없이 포인터만 앞으로 이동시키는 방식이다.
# Fast-Forward 병합 (기본 동작)
git merge <브랜치명>
# Fast-Forward 가능해도 병합 커밋을 강제로 생성
git merge --no-ff <브랜치명>- 히스토리가 깔끔한 직선으로 유지된다.
- 별도의 병합 커밋이 남지 않아 브랜치 이력이 사라진다.
두 브랜치가 각각 다른 커밋을 가지고 있을 때 (분기된 상태) 공통 조상 커밋을 기준으로 양쪽 변경사항을 합쳐 새로운 병합 커밋을 만드는 방식이다.
- 두 브랜치의 공통 조상, 현재 브랜치의 최신 커밋, 대상 브랜치의 최신 커밋 3개를 비교하여 병합한다.
- 병합 커밋이 남아 브랜치 이력을 추적할 수 있다.
- 같은 부분을 다르게 수정했다면 충돌이 발생할 수 있다.
| 항목 | Fast-Forward | 3-way-Merge |
|---|---|---|
| 발생 조건 | 분기 없이 직선 관계일 때 | 두 브랜치가 각각 커밋을 가질 때 |
| 병합 커밋 | 생성되지 않음 | 새로운 병합 커밋 생성 |
| 히스토리 | 깔끔한 직선 | 분기와 합류가 보임 |
| 브랜치 이력 | 사라짐 | 보존됨 |
다른 브랜치에서 특정 커밋만 골라서 현재 브랜치에 가져온다.
git cherry-pick <체리의 해시>팁: 여러 커밋을 가져오고 싶다면 해시를 나열하면 된다:
git cherry-pick <해시1> <해시2>
특정 브랜치에서 파생된 브랜치를 다른 브랜치로 옮겨 붙인다.
git rebase --onto <도착 브랜치> <출발 브랜치> <이동할 브랜치><출발 브랜치>에서<이동할 브랜치>까지의 커밋들을<도착 브랜치>뒤로 재배치한다.
대상 브랜치의 모든 변경사항을 하나의 커밋으로 합쳐서 가져온다.
git merge --squash <대상 브랜치>- 변경사항들이 스테이징된 상태로 준비된다.
- 별도로
git commit후 메시지를 입력해야 한다.
참고: squash merge는 대상 브랜치의 개별 커밋 이력은 남기지 않고, 하나의 깔끔한 커밋으로 정리하고 싶을 때 유용하다.
프로젝트의 규모와 배포 방식에 따라 적합한 브랜치 전략을 선택한다.
명확한 브랜치 구조를 가진 전통적인 전략이다. 릴리즈 주기가 길고 대규모 프로젝트에 적합하며, 안정적인 버전 관리가 가능하지만 브랜치 관리가 복잡하다.
| 브랜치 | 성격 | 주요 역할 |
|---|---|---|
main |
메인 | 릴리즈된 안정 버전만 관리 |
develop |
메인 | 다음 릴리즈를 위한 개발 내용 통합 |
feature/* |
임시 | 개별 기능 개발 후 develop에 병합 |
release/* |
임시 | 릴리즈 준비 (버그 수정, 버전 번호 부여 등) |
hotfix/* |
임시 | 운영 중 발생한 긴급 버그를 main에서 분기하여 수정 |
main 브랜치 하나를 중심으로 운영되는 단순한 구조이다. 상시 배포(CD) 체계가 갖춰진 웹 서비스에 최적화되어 있다.
main브랜치는 항상 배포 가능한 상태를 유지한다.- 기능 개발 시
main에서 브랜치를 생성하고, 완료 후 Pull Request를 통해 코드 리뷰 및 피드백을 거쳐 병합한다. - 구조가 단순하여 빠른 배포와 협업이 가능하다.
모든 개발자가 하나의 main 브랜치에 매일 자주 병합하는 방식이다.
- 코드 병합 시 발생하는 충돌을 최소화하고 개발 속도를 극대화한다.
- 높은 수준의 자동화 테스트와 기능 토글(Feature Flag) 활용이 필수이다.
- 브랜치를 만들더라도 수명을 매우 짧게 유지한다.
| 전략 | 구조 | 적합한 환경 | 핵심 특징 |
|---|---|---|---|
| Git Flow | 복잡 | 릴리즈 주기가 긴 대규모 프로젝트 | 명확한 브랜치 역할, 안정적 관리 |
| GitHub Flow | 단순 | 상시 배포 웹 서비스 | PR 기반 코드 리뷰, 빠른 배포 |
| TBD | 매우 단순 | 자동화 테스트가 갖춰진 고속 개발 환경 | 잦은 병합, Feature Flag 활용 |

