Git undoing
- Git 작업 되돌리기(Undoing)
- Git에서 되돌리기는 작업 상태에 따라 크게 세 가지로 분류
- Working Directory 작업 단계
- Working Directory에서 수정한 파일 내용을 이전 커밋 상태로 되돌리기
- git restore
- Working Directory에서 수정한 파일을 수정 전 (직전 커밋)으로 되돌리기
- 이미 버전 관리가 되고 있는 파일만 되돌리기 가능
- git restore를 통해 되돌리면, 해당 내용을 복원할 수 없으니 주의할 것!
- git restore {파일 이름}
- Staging Area 작업 단계
- Staging Area에 반영된 파일을 Working Directory로 되돌리기 (== Unstage)
- git rm —cached (root-commit이 없는 경우)
- Git 저장소가 만들어지고 한 번도 커밋을 안한 경우
- git restore —staged (root-commit이 있는 경우)
- 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}
- git reset 과의 차이점
- 개념적 차이
- reset은 커밋 내역을 삭제하는 반면, revert는 새로운 커밋을 생성함
- revert는 Github을 이용해 협업할 때, 커밋 내역의 차이로 인한 충돌 방지 가능
Git reflog
- git reset의 hard 옵션은 Working Directory 내용까지 삭제하므로 위험할 수 있음
- git reflog 명령어를 이용하면 reset 하기 전의 과거 커밋 내역을 모두 조회 가능
- 이후 해당 커밋으로 reset 하면 hard 옵션으로 삭제된 파일도 복구 가능
Git branch
- 장점
- 브랜치는 독립 공간을 형성하기 때문에 원본에 대해 안전함
- 하나의 작업은 하나의 브랜치로 나누어 진행되므로 체계적인 개발이 가능함
- 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 해야함
- 병합에는 세 종류가 존재
- Fast-Forward
- 브랜치가 가리키는 커밋을 앞으로 이동
- (master) $ git merge hotfix
- 3-way Merge
- 각 브랜치의 커밋 두 개와 공통 조상 하나를 사용하여 병합하는 방법
- (master) $ git merge hotfix
- Merge Conflict
- 두 브랜치에서 같은 부분을 수정한 경우, Git이 어느 브랜치의 내용으로 작성해야 하는지 판단하지 못하여 충돌(Conflict)이 발생했을 때 이를 해결하며 병합하는 방법
- 보통 같은 파일의 같은 부분을 수정했을 때 자주 발생함
Git workflow
- Branch와 원격 저장소를 이용해 협업을 하는 두 가지 방법
- 원격 저장소 소유권이 있는 경우 → Shared repository model
- 원격 저장소 소유권이 없는 경우 → Fork & Pull model
Shared repository model
- 원격 저장소가 자신의 소유이거나 Collaborator로 등록되어 있는 경우
- master 브랜치에 직접 개발하는 것이 아니라, 기능별로 브랜치를 따로 만들어 개발
- Pull Request를 사용하여 팀원 간 변경 내용에 대한 소통 진행
- 방법
- 소유권이 있는 원격 저장소를 로컬 저장소로 clone 받기
- 사용자는 자신이 작업할 기능에 대한 브랜치를 생성하고, 그 안에서 기능을 구현
- 기능 구현 완료 → 원격 저장소에 해당 브랜치 push
- 각 기능의 브랜치가 원격 저장소에 반영됨
- Pull Request를 통해 브랜치를 master에 반영해달라는 요청을 보냄
- 병합 완료된 브랜치는 불필요 → 원격 저장소에서 삭제
- 원격 저장소에서 병합이 완료 → 사용자는 로컬에서 master 브랜치로 switch
- 병합 후 변경된 원격 저장소의 master 내용을 로컬에 Pull
- 원격 저장소 master의 내용을 받았으므로, 기존 로컬 브랜치 삭제 (한 사이클 종료)
- 새 기능 추가를 위해 새로운 브랜치를 생성하며 지금까지의 과정을 반복
Fork & Pull model
- 오픈소스 프르젝트와 같이, 자신의 소유가 아닌 원격 저장소인 경우
- 원본 원격 저장소를 그대로 내 원격 저장소에 복제 (이러한 행위를 Fork라고 함)
- 기능 완성 후 복제한 내 원격 저장소에 Push
- 이후 Pull Request를 통해 원본 원격 저장소에 반영될 수 있도록 요청함
- 방법
- 소유권이 없는 원격 저장소 fork를 통해 내 원격 저장소로 복제
- fork 이후 clone
- 이후에 로컬 저장소와 원본 원격 저장소를 동기화 하기 위해 연결
- 사용자는 자신이 작업할 기능에 대한 브랜치를 생성하고, 그 안에서 기능을 구현
- 기능 구현이 완료되면, 복제 원격 저장소(origin)에 해당 브랜치 push
- 복제 원격 저장소(origin)에 브랜치 반영됨
- Pull Request를 통해 origin의 브랜치를 upstream에 반영해달라는 요청을 보냄
- upstream 에 브랜치가 병합되면 origin의 브랜치 삭제
- 이후 사용자는 로컬에서 master 브랜치로 switch
- 병합으로 인해 변경된 upstream의 master 내용을 로컬에 Pull
- upstream의 master 내용을 받았으므로, 기존 로컬 브랜치 삭제
- 새로운 기능 추가를 위해 새로운 브랜치를 생성하며 위 과정을 반복
Git 브랜치 전략
- 여러 개발자가 하나의 레포지토리를 사용하는 환경에서 변경 내용의 충돌을 줄이고 협업을 효율적으로 하고자 만들어진 브랜치 생성 규칙 혹은 방법론
- gitlab-flow
- github-flow의 배포 이슈를 보완하기 위해 gitlab에서 사용하는 방식
- master 브랜치와 production 브랜치 사이에 pre-production 브랜치를 두어 개발 내용을 바로 반영하지 않고, 배포 시기를 조절함
- github-flow
- 복잡한 git-flow를 개선하여 github에서 사용하는 방식
- Pull Request 기능 사용 권장, 병합 후 배포가 자동화로 이루어짐
- git-flow
- master : 제품으로 출시될 수 있는 브랜치
- develop : 다음 출시 버전을 개발하는 브랜치
- feature : 기능을 개발하는 브랜치
- release : 이번 출시 버전을 준비하는 브랜치
- hotfix : 출시 버전에서 발생한 버그를 수정 하는 브랜치