_

Always be tactful

멋쟁이사자처럼/정기 세션

[🦁1] Git & GitHub

funczun 2025. 3. 14. 03:14
깃은 형상관리 시스템이다.

이미지 출처: https://docs.nesi.org.nz/Getting_Started/Cheat_Sheets/Git-Reference_Sheet/


학습 순서

 

 기본적인 Git 사용법 → 변경 사항 관리 → 협업 & 고급 기능


이번 주 키워드
  • Working Directory
  • git reset & git revert
  • git stash
  • Conflict
  • git rebase
  • cherry-pick

1. Working Directory

 

 우선, 깃의 추적 여부에 따라 `Untracked`와 `Tracked`로 나뉨. 여기서 깃의 추적이라고 함은 깃이 관리하는 파일인가를 뜻하는데, 깃의 관리 기준은 "git add를 한 번이라도 하였는가?"로 이해하면 쉬움.

  • git add를 한 번도 하지 않은 새 파일 → Untracked
  • git add를 한 번이라도 한 파일 → Tracked

 파일이 한 번이라도 git add 된 경우 Tracked 상태가 유지되며, 해당 파일은 수정 여부에 따라 `Unmodified`와 `Modified` 상태로 나뉨.

 

 이해하기 쉽게 시간순으로 예시를 들자면, 아래와 같음.

UntrackedStaged → Unmodified → ModifiedStaged → (...)

*최초 생성 후 `Untracked`였던 파일은 git add를 통해 커밋 준비가 된 `Staged` 상태가 되며, 이 파일은 git commit을 통해 `Unmodified` 상태가 됨. 이후 변경 사항이 생기면 `Modified`, 이를 git add 하면 다시 `Staged` 상태가 됨.

 

 요지는 "작업 디렉토리 내에서 이런 식으로 파일 상태가 바뀌더라." 정도로 이해하자는 것임.


2. git reset & git revert

 

 두 명령어 모두 브랜치를 특정 커밋의 상태로 되돌리는 역할을 함. 그러나 방식에서 차이가 있음. git reset은 되돌리고 싶은 커밋 이후의 기록을 없애버리지만, git revert는 기존 이력을 유지하면서 취소하는 새 커밋을 추가함. 쉽게 말해 git reset은 히스토리를 수정하지만 git revert는 히스토리를 유지함.

 

🔹git reset

  • 특정 커밋 이후의 변경 사항을 없앰. 되돌린 기록이 남지 않음.

🔹git revert

  • '특정 커밋을 취소하는 새로운 커밋'을 생성해 기록을 남김.

 핵심은 타 개발자와 협업할 때 git reset을 지양하자는 것임. 공유된 브랜치에서 git reset을 사용하는 경우 혼란은 물론이고 문제가 생길 수 있음. 협업 환경이라면 git revert를 통해 안전하게 사용하는 것을 추천함.


📌 더 알아보기

 

 git reset의 경우 상황에 따른 세 가지 옵션이 존재함. 이 옵션들 간의 차이를 이해하려거든, 일단 `HEAD`, `Staging Area`, `Working Directory`를 먼저 이해할 필요가 있음.

Working Directory git status에서 변경 사항이 감지되는 영역 (실제로 파일을 수정하는 작업 공간)
Staging Area (Index) git add 후 들어가는 영역 (git commit 준비가 된 파일이 저장되는 공간)
HEAD git checkout 된 Commit (현재 브랜치의 최신 Commit)

*쉽게 비유해서 Working Directory (초안 작성) → Staging Area (발표할 원고 정리) → HEAD (최종 발표된 문서)임.

 

 git reset 시 따로 옵션을 지정하지 않은 경우 --mixed가 기본값이 되며, 각 옵션에 따른 특징은 아래와 같음.

옵션 HEAD (브랜치 이동) Index (스테이징 초기화) WorkingDirectory 영향
--soft ✅ 변경 ❌ 유지 ❌ 유지
--mixed (기본값) ✅ 변경 ✅ 초기화 ❌ 유지
--hard ✅ 변경 ✅ 초기화 ✅ 초기화 (삭제)

🔹git reset --soft HEAD^

  • 해당 커밋이 취소되며 HEAD가 이전 커밋으로 이동할 뿐임. 파일은 Staging Area에 그대로 남아 있으며, git commit을 하면 다시 원래대로 돌아감.

🔹git reset --mixed HEAD^

  • 해당 커밋과 git add 한 기록이 사라지지만, 파일 수정 내용은 그대로 남아 있음. git add, git commit을 통해 다시 돌아갈 수 있음.

🔹git reset --hard HEAD^

  • 해당 커밋 이후의 모든 작업이 사라지며 되돌릴 수 없음. 되돌린다기보다는 진짜 삭제에 가까운 개념임.

git revert <Commit ID>

*다시 말하지만, 어차피 협업할 일이 잦을텐데 git revert를 사용하는 편이 좋을 듯함. 근데 알아두어야 할 게, git revert는 기본적으로 한 번에 하나의 커밋만 되돌림. 그래서 여러 커밋을 되돌리고 싶다면 git revert도 여러번 해주어야 함.

# 커밋 히스토리 예시
A - B - C - D - E (현재 HEAD)

# C, D, E 커밋 되돌리기
git revert E
git revert D
git revert C

# 최종 모습
A - B - C - D - E - E' - D' - C'

2-2. git checkout & git switch

 

 본 포스트에서 `HEAD`를 설명하며 git checkout을 언급하게 되었는데, 문득 세션 중에 git checkout과 git switch가 비슷한 기능이라는 식으로 언급되었던 게 기억남. 근데 분명 차이가 있기 때문에 둘 다 존재하는 것이란 확신이 생겨 찾아봄.

 

 찾아본 결과, git checkout과 git switch는 둘 다 브랜치를 변경하는 기능을 하지만 분명한 차이가 있었음. 요점만 말하자면 git switch는 더 명확하고 안전한 방식으로 분리된 명령어임.

git checkout 브랜치 이동 + 특정 커밋 체크아웃 + 파일 변경 취소 다양한 기능을 한 명령어에 포함
git switch 브랜치 이동 전용 브랜치 변경만 가능 (더 직관적)

*더 쉽게 말해서, git switch는 git checkout의 브랜치 변경 기능만 분리한 명령어임. (Git 2.23 도입)

 

 좀 더 심화해서 보면 git checkout은 기능이 많이 포함되어 헷갈릴 수 있음. 그래서 쪼개져 나온 것이 git switch와 git restore이므로 git switch + git restore 조합을 사용하는 것을 권장함.


3. git stash

 

 git stash는 작업 중인 변경 사항을 임시로 저장하고 나중에 다시 적용하는 기능임. 말 그대로 변경 사항을 커밋하지 않고도 임시로 저장할 수 있기에 유용한 명령어라고 볼 수 있음.

 

🔹주요 명령어

  • git stash
  • git stash list
  • git stash apply
  • git stash pop
  • git stash drop
  • git stash clear
git stash # 변경 사항이 stash에 저장됨. (작업 디렉토리 클린)

git stash list # 저장된 stash 목록을 확인함.

git stash apply # 가장 최근의 stash 변경 사항을 다시 적용함. (stash 유지)

git stash pop # 가장 최근의 stash 변경 사항을 다시 적용함. (stash 삭제)

git stash drop stash@{0} # 특정 stash를 삭제함. (stash@{0}은 가장 최근 stash)

git stash clear # 저장된 모든 stash를 삭제함.

 

💡 `git stash`는 언제 사용할까?

  • 브랜치를 변경해야 하는데 아직 커밋하기 애매할 때.
  • 급하게 다른 작업을 해야 할 때.

4. Conflict

 

 브랜치를 병합(git merge)하거나 리베이스(git rebase)할 때 충돌(conflict)이 발생할 수 있음. 따라서 충돌에 대한 해결 방법을 아는 것이 필수적임.

 

🔹근본적인 해결 방법 (모든 브랜치, 수동)

# 충돌 파일 예시
<<<<<<< HEAD
// 현재 브랜치 변경 사항
=======
// 병합 대상 브랜치 변경 사항
>>>>>>> feature-branch
  1. git status로 충돌 파일 확인
  2. 충돌 파일을 열어 <<<<<<<, =======, >>>>>>> 표시된 부분을 수정
  3. 수정 후 git add <파일명>
  4. git commit으로 충돌 해결

🔹병합 및 리베이스 중단 (임시 해결)

  • git merge --abort → 병합 중단
  • git rebase --abort → 리베이스 중단

🔹특정 브랜치 수락 (선택되지 않은 브랜치 내용 버리기)

git checkout --ours conflicted-file.txt    # 현재 브랜치의 변경 사항만 유지

git checkout --theirs conflicted-file.txt  # 병합 대상 브랜치의 변경 사항만 유지

5. git rebase

 

 `git rebase`는 브랜치의 기반(base)을 다른 브랜치로 변경하는 명령어임.

 

🔹 사용법

git checkout feature-branch git rebase main
  • feature-branch를 main 브랜치 위에 다시 쌓음.

💡 `git rebase`는 왜 사용할까?

  • 커밋 이력을 깔끔하게 정리하기 위해 (merge 대신 rebase 사용)
  • 협업할 때 다른 사람이 변경한 최신 코드 위에서 작업을 이어가기 위해

 단, 이미 공유된 브랜치에서는 git rebase를 하면 안 됨. 기록이 변경되기 때문임.


6. git cherry-pick

 

 특정 브랜치의 특정 커밋만 골라서 다른 브랜치에 적용하는 명령어임. 아래 사이트를 통해 연습해 볼 수 있음.

 

↓ 링크 ↓

https://learngitbranching.js.org/?locale=ko

 

🔹 사용법

git cherry-pick <커밋 해시>

 

💡 `git cherry-pick`은 언제 사용할까?

  • 다른 브랜치에서 필요한 변경 사항만 가져오고 싶을 때
  • 긴급 버그 수정(commit)만 특정 브랜치에 반영할 때

'멋쟁이사자처럼 > 정기 세션' 카테고리의 다른 글

[🦁3] 객체 지향 설계: OOP  (2) 2025.03.28
[🦁2] Web App & Spring MVC #2  (2) 2025.03.23
[🦁2] Web App & Spring MVC #1  (0) 2025.03.21