Git 핵심 개념과 명령어 정리

2024년 09월 02일

Git의 기본 개념, 자주 사용하는 명령어를 정리했습니다.

1 Git 기본 개념

저장소 구조

  • 로컬 저장소 : 개발자의 컴퓨터에 있는 저장소
    • 독립적인 작업 가능
    • 오프라인 상태에서도 버전 관리 가능
  • 원격 저장소 : 서버에 위치한 저장소
    • (ex: Github, Gitlab, Bitbucket)
    • 팀 협업을 위한 중앙 저장소
    • 코드 백업 및 공유
    • 코드 리뷰, 이슈 트래킹 등 추가 기능

Git 설정

# 시스템 전체 설정
git config --system user.name "username"

# 현재 사용자 전역 설정
git config --global user.name "username"

# 현재 저장소만 설정
git config user.name "username"

# 설정 확인
git config --get user.name
git config --list

Git 저장소 시작

git init [directoy]

  • directory가 없으면 현재 디렉토리에서 init
  • 깃 저장소 디렉터리에 서브 디렉터리 .git 이 생성됨.
    • → 여기서 버전 관련 내용이 깃 프로그램에 의해 알아서 기록됨.

저장소 공간

  1. Working Directory(작업 디렉토리)
    • 실제 작업하는 파일들이 있는 디렉토리
  2. Staging Area(스테이징 영역 / index)
    • 개별 파일의 변경 내용을 기록하는 임시 공간
    • 커밋 수행전에 스테이지 영역에 기록해야함.
  3. Local Repository(깃 저장소)
    • .git 폴더에 저장되는 커밋된 파일들의 저장소
    • 버전이 만들어지고 관리되는 공간으로 커밋을 수행하여 특정 시점에서 스테이지의 스냅숏을 저장함.
    • 시간 흐름에 따라 커밋이 쌓이면서 커밋 이력이 관리됨.

깃 파일의 상태 변화

  • 처음 파일을 생성하면 untracked(추적되지 않음) 상태
  • git add 명령을 사용하여 스테이지에 올려야함
  • staged(스테이지에 올라옴) 상태 파일은 git commit 명령으로 . 깃저장소에 스냅샷이 기록됨.
  • 커밋 수행 직후 파일은 unmodified(수정 전) 상태가 됨
  • 이 팡리을 수정하면 modified(수정함) 상태가 됨.
  • 수정된 파일의 변경 내용을 기록하려면 스테이지에 올린 후 커밋할 수 있음.

git add : 스테이지에 파일을 추가하는 명령

  • git add files : 해당 파일들
  • git add . : 현재 + 하위 디렉터리 모두
  • git add (--a | A) : 현재 디렉터리 모두

git commit : 깃 저장소에 커밋 이력을 남기는 명령

  • git commit -m "message"
  • git commit -a -m "message" : 스테이지에 올리면서 커밋을 함께 실행
    • *신규 생성한 파일은 이렇게 불가. 일단 스테이지에 먼저 따로 올려야함.

git log : 커밋 이력을 확인하는 명령

  • git log : 현재 브랜치의 커밋정보
  • git log --oneline : 커밋 정보를 1개당 한줄로 표시
  • git log (--patch | -p) : 커밋 정보의 파일의 변경 내용 표시
  • git log --graph : 여러 브랜치를 그래프로 이력 표시
  • git log --reverse : 오래된 커밋부터 표시
  • git log --all : 모든 브랜치의 커밋 이력 표시
  • git log --n : 최근 n개 이력만
  • git show HEAD git show commitID : HEAD/commitID 이 가리키는 커밋의 기본정보를 표시하고 이전 커밋과의 차이 표시

HEAD: 현재 작업중인 브랜치를 가리킴

checkout : 버전 여행

  • HEAD를

    • 1)현재 브랜치의 과거 커밋
    • 2)다른 브랜치의 최신 커밋으로 이동할 수 있음
  • git status 명령 결과에서 작업 폴더가 깨끗(clean)해야 checkout 가능

    • clean? = 디렉토리-스테이지-저장소 3개 저장공간 내용이 동일한 상태 = 커밋 직후
    • checkout 으로 과거 커밋으로 이동하면 분리된(detached) HEAD 상태가 됨.
  • HEAD가 이동하면 상응하는 커밋 내용으로 작업 영역, 인덱스가 업데이트 됨.

  • HEAD는 시간 이동을 위한 수단으로 활용가능

    • HEAD~ HEAD^ : 직전 커밋
    • HEAD~~ HEAD~2 HEAD^^ : 전전 커밋
    • 예시
    git checkout HEAD~ //직전 커밋으로 이동
    git checkout - //직전 브랜치(이전 HEAD)위치로 이동
    git checkout _branch_ //다른 브랜치로
    

버전 / 커밋간 파일 비교

  • git diff commit1 commit2 _:_commit1을 기준으로 commit2가 어떻게 변경되었는지 표시

    git diff HEAD~ HEAD //직전을 기준으로 현재가 어떻게 변경되었는지 표시
    

2 브랜치

브랜치 : 특정 목록을 가진 독립적 개발 흐름.

  • 기본 브랜치 (master 혹은 main)이 주어짐

  • 기능 추가, 개선, 버그 수정을 위해 각각 별도 브랜치를 만들어서 작업함.

  • 브랜치는 커밋 이력을 가지며, 브랜치 이름은 커밋이력에서 최신 커밋을 가리킴.

  • 예시

    git init myProject 
    
    git branch -m master //현재 브랜치 이름을 master로 수정
    
    git commit -m A
    git branch -m main //이름을 다시 main으로 수정
    
    git log
    

Branch 확인과 생성

  • git branch / git branch —list : 브랜치 이름 나열
  • git branch -v : 브랜치 마다 상세한 정보도 나열
  • git branch newBranchName : 새로운 브랜치 생성 (HEAD는 이동하지 않음)
  • git switch newBranchName : 새로운 브랜치 생성 + HEAD 이동
  • git checkout -b newBranchName : 새로운 브랜치 생성 + HEAD 이동

작업브랜치 이동

  • git switch branchName / git checkout branchName : 브랜치 이동
  • git switch : 직전 브랜치로 HEAD 이동

예시

git branch develop //브랜치 생성
git branch
git switch develop

이전 커밋으로의 이동

  • git checkout [-d] HEAD~ : HEAD가 분리되어 HEAD~(이전)로 이동
  • git switch -d HEAD~ : HEAD가 분리되어 HEAD~로 이동
  • git switch -d [commit] : HEAD가 분리되어 commit으로 이동

병합 여부 확인

git branch -—merged 현재 작업 브랜치 기준으로 병합된(도달 가능한) 브랜치 표시

git branch -—no-merged현재 작업 브랜치 기준으로 병합되지 않은(도달 불가) 브랜치 표시

git branch -—merged branchName 주어진 브랜치 기준으로 병합된(도달 가능한) 브랜치 표시

git branch -—no-merged branchName 주어진 브랜치 기준으로 병합되지 않은(도달 불가) 브랜치 표시

브랜치 삭제

git branch -d branchName 이미 명합된 브랜치 삭제

git branch -D branchName 이미 병합되지 않았더라도 브랜치를 삭제 (*위험)

브랜치 병합

fast-forward 병합

  • 자손 브랜치(최신)의 커밋 이력이 조상 브랜치(원래의 브랜치)의 커밋 이력을 모두 포함한 경우에 가능
  • 즉, 조상 브랜치를 자손. ㅡ랜치 위치로 이동하는 것
  • 순서
    • 먼저 조상브랜치로 HEAD 이동하고
    • git merge childBranch
  • 예시
    • main이 커밋 1-2-3 을 갖고있고
    • dev가 여기서 따온 후에 1-2-3-4-5 로 4-5를 추가했다면
      • dev(자손이) 조상(main)을 이력을 다 포함하고 있기 때문에 fast-forward가능.
    • 결과로는 실제로 합친다기보다 1-2-3-4-5 커밋이력에 main이 3 / dev가 5에 위치하고 있었던 것에서 → main을 5로 이동시키는 것.

3-way 병합

한 커밋에서 갈라져 나온 두 브랜치를 병합함

  • 어느 시점 이후 대상 커밋의 변경을 현재 브랜치에 병합
  • 병합을 의미하는 새로운 커밋이 생김(커밋 메세지 입력)
  • (HEAD→현재브랜치)가 새로운 커밋으로 이동됨

git merge -m “message” branch

강제 3-way 병합

  • fast-forward 병합이 가능하나 3-way 병합을 수행.
  • 3-way가 되니 추가 커밋이 생김

git merge --no-ff branchName -m "message"

Squash 병합

3way 병합이지만, 병합만 진행하고 커밋 직전까지만 수행함. 추후에 커밋 해야함

브랜치 병합 충돌 / 해결

  • 충돌
    • 두 브랜치에서 같은 파일-같은 위치를 동시에 수정한 경우
    • 자동 3way 병합을 할 수 없어서 충돌이 발생함
  • 해결
    • vi / IDE에서 개발자가 해결해야함

3 Stash

stash

마지막 커밋 이후 → 변경된 작업 영역, 스테이지 영역을 임시 저장

  • 작업중에 급하게 작업 브랜치를 바꿔야할 때 사용
  • git checkout / git switch 명령은 작업 폴더가 깨끗한 상태에서 가능하기에

git stash스택 구조의 임시 저장소(stash)에 저장함

→ 작업 영역 / 스테이지 영역은 마지막 커밋과 동일한 깨끗한 상태가 됨.

주의!!

  • 추적되지 않은 파일(add 안한) 도 저장하려면!

    —-include-untracked / -u 사용하기

  • 마지막 커밋 이후 변경이 없으면 stash 할게 없으니 안됨.

  • git stash [-m message] : 스태시 저장

  • git stash push [-m message] : 위와 동일

  • git stash save [message] : 위와 동일

  • git stash -u : 작업영역의 추적되지 않는 파일(=아직 스테이지 안올라온 파일도) 저장

  • git stash list : 저장된 목록 확인

  • git stash show [stash@{n}] 최종 커밋 - 스태시 저장된 내용 비교해서 보여줌. 명시한 스태시가 없으면 최신 저장항목과 비교

    • git stash show stash@0 : 최신 stash랑 비교
    • git stash show stash@1 : 2번째 stash와 비교

stash 적용 (복원)

git stash apply [stash@{n}]

  • 기본적으로 작업 영역으로 복원된다. 원래 스테이지에 있었다고 하더라도.
  • 복원할 때 스테이지 영역까지 올라가도록 복원시키려면 --index 옵션 사용 (스테이지=인덱스)

stash 삭제

  • git stash drop [stash@{n}] : 특정 스태시 삭제

  • git stash claer 모두 삭제

  • git stash pop [stash@{n}] : 적용하면서 삭제

Stash 활용

git stash branch branchName : 새로운 브랜치 만들고, 기존 브랜치의 최신 스태시를 적용(apply함)

기타

git clean : 추적되지 않는 파일 삭제

  • n: 실제로 제거하지는 않고 어떤 파일이 제거되는지 확인
  • f: 강제 삭제 실행
  • d: 디렉토리도 포함하여 삭제

Reset

  • HEAD위치를 이전 특정 커밋으로 되돌리는 기능. 버전을 과거로 완.전.히. 되돌리는 것
  • 해당 커밋 이후의 커밋 이력은 삭제됨.
  • 새로운 커밋은 생성되지 않음

3가지 모드

git reset --hard commit

  • 작업 디렉토리 / 스테이징 영역 / Git 저장소 모두를 지정한 커밋 상태로 되돌림.

git reset [--mixed] commit

  • Git 저장소 / 스테이징 영역만 되돌림.
  • 작업 디렉토리는 현재 상태 그대로 유지
  • git reset의 디폴트 옵션

git reset --soft commit

  • Git 저장소만 되돌림.
  • 스테이지 영역, 작업 디렉토리는 현재 상태 유지.
git reset --hard HEAD~ 
//이전 커밋으로 돌아감

git reset --hard ORIG_HEAD 
//돌아왔던 가장 최신 커밋으로 돌아감. 

Revert

  • 최근 커밋부터 차례로 이전 커밋을 취소할 때 사용.
  • 리셋(--hard 옵션)과 유사하나 기존 커밋을 삭제하지 않고, 커밋 이력을 남겨둔 채 ‘커밋 취소’를 의미하는 새로운 커밋 생성.
    • → 협업시 권장되는 방식

git revert commit

git revert commit --no-edit : 커밋 메세지를 “Revert - 주어진 커밋 메세지”로 기록됨

주의

  • 작업 폴더가 깨끗한 상태야 revert 수행 가능. (reset은 그냥 가능했는데)
  • 한번에 한 커밋만 취소하므로 → 충돌이 발생하지 않으려면 최신 커밋부터 순차적으로 여러 번 취소
  • 충돌이 발생한다면
    1. 충돌된 파일을 찾아 수정
    2. 수정한 파일을 인덱스(스테이지)에 등록
    3. git revert --continue로 명령을 계속 진행

git reset --hard HEAD : HEAD니까. 뒤로 돌리는 건 아니고 작업 영역 stage에 있는 것들 날리는 것.

리버트의 연속 적용

순서대로 리버트 수행하여 과거의 커밋으로 이동

git revert HEAD HEAD~ HEAD~2

  • 취소(revert) 커밋이 3개가 추가됨.

범위로도 가능, 위와 동일한 다른 표현

git revert HEAD~3… (*HEAD3의 다음부터~ )

git revert HEAD~3…HEAD

고급 활용

  • 여러 커밋 취소를 하나의 커밋으로 만들기
    1. git revert --no-commit HEAD~3..HEAD
    2. 변경사항 확인 및 필요시 수정
    3. git commit -m "여러 커밋 취소"
  • 여러 개의 커밋을 취소해서 스테이지에 쌓아놓고, 커밋 한개만 생성할수 있음
  • revert는 한개 커밋마다 한개 revert 커밋이 생겨서 별로인데, 이렇게 하면 좋음.

권장 사항

  1. 개인 브랜치에서는 reset 사용해도 됨.
  2. 공유 브랜치에서는 revert 사용 권장
  3. 작업 전 항상 현재 상태 확인 git status

TAGS
GIT