본문 바로가기

Git

[Git] Git Advanced

Git undoing

  • Git 작업 되돌리기(Undoing)
  • Git에서 되돌리기는 작업 상태에 따라 크게 세 가지로 분류
    1. Working Directory 작업 단계
      • Working Directory에서 수정한 파일 내용을 이전 커밋 상태로 되돌리기
      • git restore
        • Working Directory에서 수정한 파일을 수정 전 (직전 커밋)으로 되돌리기
        • 이미 버전 관리가 되고 있는 파일만 되돌리기 가능
        • git restore를 통해 되돌리면, 해당 내용을 복원할 수 없으니 주의할 것!
        • git restore {파일 이름}
    2. Staging Area 작업 단계
      • Staging Area에 반영된 파일을 Working Directory로 되돌리기 (== Unstage)
      • git rm —cached (root-commit이 없는 경우)
        • Git 저장소가 만들어지고 한 번도 커밋을 안한 경우
      • git restore —staged (root-commit이 있는 경우)
    3. Repository 작업 단계
      • 커밋을 완료한 파일을 Staging Area로 되돌리기
      • git commit —amend
      • 상황 별로 두 가지 기능으로 나뉨
        • Staging Area에 새로 올라온 내용이 없다면, 직전 커밋의 메시지만 수정
        • Staging Area에 새로 올라온 내용이 있다면, 직전 커밋을 덮어쓰기
      • 이전 커밋을 완전히 고쳐서 새 커밋으로 변경하므로, 이전 커밋은 일어나지 않은 일이 되며 히스토리에도 남지 않음을 주의할 것

Git reset

  • 프로젝트를 특정 커밋(버전) 상태로 되돌림
  • 특정 커밋으로 되돌아 갔을 때, 해당 커밋 이후로 쌓았던 커밋들은 전부 사라짐
  • git reset [옵션] {커밋 ID}
    • 옵션은 soft, mixed, hard 중 하나를 작성
    • 커밋 ID는 되돌아가고 싶은 시점의 커밋 ID를 작성
    • —soft
      • 해당 커밋으로 되돌아가고
      • 되돌아간 커밋 이후의 파일들은 Staging Area로 돌려놓음
    • —mixed
      • 해당 커밋으로 되돌아가고
      • 되돌아간 커밋 이후의 파일들은 Working Directory로 돌려놓음
      • git reset 옵션의 기본값
    • —hard
      • 해당 커밋으로 되돌아가고
      • 되돌아간 커밋 이후의 파일들은 모두 Working Directory에서 삭제 → 따라서 사용 시 주의할 것!
      • 기존의 Untracked 파일은 사라지지 않고 Untracked로 남아있음

Git revert

  • 과거를 없었던 일로 만드는 행위로, 이전 커밋을 취소한다는 새로운 커밋을 생성함
  • git revert {커밋 ID}
    • 커밋 ID는 취소하고 싶은 커밋 ID를 작성
  • git reset 과의 차이점
    • 개념적 차이
      • reset은 커밋 내역을 삭제하는 반면, revert는 새로운 커밋을 생성함
      • revert는 Github을 이용해 협업할 때, 커밋 내역의 차이로 인한 충돌 방지 가능

Git reflog

  • git reset의 hard 옵션은 Working Directory 내용까지 삭제하므로 위험할 수 있음
  • git reflog 명령어를 이용하면 reset 하기 전의 과거 커밋 내역을 모두 조회 가능
  • 이후 해당 커밋으로 reset 하면 hard 옵션으로 삭제된 파일도 복구 가능

Git branch

  • 장점
    1. 브랜치는 독립 공간을 형성하기 때문에 원본에 대해 안전함
    2. 하나의 작업은 하나의 브랜치로 나누어 진행되므로 체계적인 개발이 가능함
    3. Git은 브랜치를 만드는 속도가 굉장히 빠르고, 적은 용량을 소모함
  • 조회
    • git branch - 로컬 저장소의 브랜치 목록 확인
    • git branch -r - 원격 저장소의 브랜치 목록 확인
  • 생성
    • git branch {브랜치 이름} - 새로운 브랜치 생성
    • git branch {브랜치 이름} {커맷 Id} - 특정 커밋 기준으로 브랜치 생성
  • 삭제
    • git branch -d {브랜치 이름} - 병합된 브랜치만 삭제 가능
    • git branch -D {브랜치 이름} - 강제 삭제

Git switch

  • 현재 브랜치에서 다른 브랜치로 이동하는 명령어
  • git switch {브랜치 이름} - 다른 브랜치로 이동
  • git switch -c {브랜치 이름} - 브랜치를 새로 생성 및 이동
  • git switch -c {브랜치 이름} {커밋 ID} - 특정 커밋 기준으로 브랜치 생성 및 이동
  • switch하기 전에, 해당 브랜치의 변경 사항을 반드시 커밋 해야함을 주의 할것!
    • 다른 브랜치에서 파일을 만들고 커밋 하지 않은 상태에서 switch를 하면 브랜치를 이동했음에도 불구하고 해당 파일이 그대로 남아있게 됨

HEAD

  • HEAD는 현재 브랜치를 가리키고, 각 브랜치는 자신의 최신 커밋을 가리키므로 결국 HEAD가 현재 브랜치의 최신 커밋을 가리킨다고 할 수 있음
  • git log 혹은 cat.git/HEAD를 통해서 현재 HEAD가 어떤 브랜치를 가리키는지 알수 있음
  • 결국 git switch는 현재 브랜치에서 다른 브랜치로 HEAD를 이동시키는 명령어

Git merge

  • 분기된 브랜치(branch)들을 하나로 합치는 명령어
  • master 브랜치가 상용이므로, 주로 master 브랜치에 병합
  • git merge {합칠 브랜치 이름}
    • 병합하기 전에 브랜치를 합치려고 하는, 즉 메인 브랜치로 switch 해야함
    • 병합에는 세 종류가 존재
      1. Fast-Forward
        • 브랜치가 가리키는 커밋을 앞으로 이동
        • (master) $ git merge hotfix
      2. 3-way Merge
        • 각 브랜치의 커밋 두 개와 공통 조상 하나를 사용하여 병합하는 방법
        • (master) $ git merge hotfix
      3. Merge Conflict
        • 두 브랜치에서 같은 부분을 수정한 경우, Git이 어느 브랜치의 내용으로 작성해야 하는지 판단하지 못하여 충돌(Conflict)이 발생했을 때 이를 해결하며 병합하는 방법
        • 보통 같은 파일의 같은 부분을 수정했을 때 자주 발생함

Git workflow

  • Branch와 원격 저장소를 이용해 협업을 하는 두 가지 방법
    • 원격 저장소 소유권이 있는 경우 → Shared repository model
    • 원격 저장소 소유권이 없는 경우 → Fork & Pull model

Shared repository model

  • 원격 저장소가 자신의 소유이거나 Collaborator로 등록되어 있는 경우
  • master 브랜치에 직접 개발하는 것이 아니라, 기능별로 브랜치를 따로 만들어 개발
  • Pull Request를 사용하여 팀원 간 변경 내용에 대한 소통 진행
  • 방법
    1. 소유권이 있는 원격 저장소를 로컬 저장소로 clone 받기
    2. 사용자는 자신이 작업할 기능에 대한 브랜치를 생성하고, 그 안에서 기능을 구현
    3. 기능 구현 완료 → 원격 저장소에 해당 브랜치 push
    4. 각 기능의 브랜치가 원격 저장소에 반영됨
    5. Pull Request를 통해 브랜치를 master에 반영해달라는 요청을 보냄
    6. 병합 완료된 브랜치는 불필요 → 원격 저장소에서 삭제
    7. 원격 저장소에서 병합이 완료 → 사용자는 로컬에서 master 브랜치로 switch
    8. 병합 후 변경된 원격 저장소의 master 내용을 로컬에 Pull
    9. 원격 저장소 master의 내용을 받았으므로, 기존 로컬 브랜치 삭제 (한 사이클 종료)
    10. 새 기능 추가를 위해 새로운 브랜치를 생성하며 지금까지의 과정을 반복

Fork & Pull model

  • 오픈소스 프르젝트와 같이, 자신의 소유가 아닌 원격 저장소인 경우
  • 원본 원격 저장소를 그대로 내 원격 저장소에 복제 (이러한 행위를 Fork라고 함)
  • 기능 완성 후 복제한 내 원격 저장소에 Push
  • 이후 Pull Request를 통해 원본 원격 저장소에 반영될 수 있도록 요청함
  • 방법
    1. 소유권이 없는 원격 저장소 fork를 통해 내 원격 저장소로 복제
    2. fork 이후 clone
    3. 이후에 로컬 저장소와 원본 원격 저장소를 동기화 하기 위해 연결
    4. 사용자는 자신이 작업할 기능에 대한 브랜치를 생성하고, 그 안에서 기능을 구현
    5. 기능 구현이 완료되면, 복제 원격 저장소(origin)에 해당 브랜치 push
    6. 복제 원격 저장소(origin)에 브랜치 반영됨
    7. Pull Request를 통해 origin의 브랜치를 upstream에 반영해달라는 요청을 보냄
    8. upstream 에 브랜치가 병합되면 origin의 브랜치 삭제
    9. 이후 사용자는 로컬에서 master 브랜치로 switch
    10. 병합으로 인해 변경된 upstream의 master 내용을 로컬에 Pull
    11. upstream의 master 내용을 받았으므로, 기존 로컬 브랜치 삭제
    12. 새로운 기능 추가를 위해 새로운 브랜치를 생성하며 위 과정을 반복

Git 브랜치 전략

  • 여러 개발자가 하나의 레포지토리를 사용하는 환경에서 변경 내용의 충돌을 줄이고 협업을 효율적으로 하고자 만들어진 브랜치 생성 규칙 혹은 방법론
  • gitlab-flow
    • github-flow의 배포 이슈를 보완하기 위해 gitlab에서 사용하는 방식
    • master 브랜치와 production 브랜치 사이에 pre-production 브랜치를 두어 개발 내용을 바로 반영하지 않고, 배포 시기를 조절함
  • github-flow
    • 복잡한 git-flow를 개선하여 github에서 사용하는 방식
    • Pull Request 기능 사용 권장, 병합 후 배포가 자동화로 이루어짐
  • git-flow
    • master : 제품으로 출시될 수 있는 브랜치
    • develop : 다음 출시 버전을 개발하는 브랜치
    • feature : 기능을 개발하는 브랜치
    • release : 이번 출시 버전을 준비하는 브랜치
    • hotfix : 출시 버전에서 발생한 버그를 수정 하는 브랜치

'Git' 카테고리의 다른 글

[Git] git stash, git stash pop  (1) 2023.04.02