Git의 3가지 목적
1. 버전 관리 (Version) - Commit
2. 백업 (Backup) - Push / Pull
3. 협업 (Collaboration)
깃 초기화
#initialize Repository
# 0. No directory input: create .git in current directory
# 1. If directory exists: create .git in designated directory
# 2. Otherwise: create directory then create .git inside
$ git init [directory name]
버전 관리 추상화
- Working Tree: 작업을 진행하는 공간
- Staging Area: 작업 내용 중 버전을 관리할 대상 파일들이 지정되는 공간
- Repository: 버전들이 저장되는 공간
깃 상태 확인
$ git status #show status of current working tree
버전 관리할 파일 지정
$ git add [file/directory] #add file/directory to staging area
버전 생성
$ git commit -m [message] #create a new version of files in staing area; add message
*options
-am : git add then commit (with messages) -> not applicable to untracked files
no -m: edit commit messages from text editor
--amend: modify already committed message
깃 히스토리 조회
#show previous commits (versions)
$ git log
*options
--name-only: full pathnames
--name-status: full pathnames and status
--stat: abbreviated pathnames and diffstat
이전 버전과 비교
$ git diff #show changes between latest version(commit) and working tree
버전 및 작업 내용 삭제 (사용에 주의)
*공유(Push)되기 전의 버전(Commit)들로만 리셋할 것
$ git reset [mode] [commit ID to go back] #get back to latest version
*no commit ID: to the latest version by default
*options
--hard: remove versions after the designated version AND changes in working tree
--soft: remove versions BUT NO changes in working tree
버전은 삭제하지 않되 되돌리기 (reset보다 권장됨)
git reset
이 commit 자체를 지운다면, git revert
는 해당 commit을 취소한다는 내용으로 새로 commit
$ git revert [commit ID to drop] #omit version and remove correponding changes (==undo version)
**NOTE
- All versions after the desired version must be reverted sequentially in reverse order
이전 버전으로 돌아가기
기존 버전들은 그대로 두고 원하는 이전 버전으로 되돌림
$ git checkout [commit ID] #HEAD goes back to version with the corresponding ID
깃 환경설정
*설정한 환경은 ~/.gitconfig
파일에서 확인 가능
$ git config --global [option] [value] #change git environment settings
*options:
user.name: default git user name
user.email: default git user email
core.editor: default text editor
git ignore 사용법
일반적으로 변경된 파일 전체를 add/commit하는데, 그 중 제외시킬 파일이 있는 경우:
- 보안상 위험한 파일
- 프로젝트와 관계없는 파일
- 용량이 너무 큰 파일 (model.pth 등)
git rm [file/directory]
을 사용할 수 있지만 일일이 적용하기 어려움
.gitignore
이름의 파일 생성file1.txt #특정 fileName
/file1.txt #현재 경로의 특정 fileName
directory1/ #특정 디렉토리의 모든 파일
directory1/file1.txt #특정 디렉토리의 특정 파일
directory1/**/file1.txt #특정 디렉토리 아래의 모든 특정 파일
*.txt #특정 확장자
!file2.txt #예외 만들기
Branch 기본 명령어
#Branch 종류
# - Master: git 초기화 시 기본적으로 시작하는 Branch
# - Base: 여러 개의 Branch가 있을 때 공통으로 가지고 있는 Predecessor Branch
#현재 모든 버전과 Branch의 상태를 그래프로 출력
$ git log --all --graph --oneline
#Branch 제어
$ git branch #모든 Branch의 리스트 출력; *는 현재 Branch(HEAD)를 나타냄
$ git branch [branch name] #새로운 Branch 추가
$ git checkout [branch name] #해당 Branch로 (HEAD)전환
#Branch 병합 (Merge B Branch -> A Branch)
$ git checkout A #1. switch to A (merge-to) branch
$ git merge B #2. merge B (merge-from) branch to A (current branch)
*Git Conflict 처리
서로 다른 Branch에서 같은 파일의 같은 행을 수정했을 경우에 발생 (Merge Conflict)
Merge 실행 시 해당 위치에 구분선이 표시됨:
[contents]
<<<<<<< HEAD #merge-to branch
change1 #changes from merge-to branch
======= #구분선 (division line)
change2 #changes from merge-from branch
>>>>>>> branch2 #merge-from branch
[contents]
Conflict 발생 시에 사용자는 이 구분선을 보고 이 부분만 manual하게 수정하면 됨
3-Way Merge
A, B 두 개의 Branch가 있고 이들의 Base Branch가 있을 때 A와 B를 Merge하는 경우,
1) A (혹은 B) Branch과 Base Branch와 차이가 없을 때: Base Branch와 B를 Merge
2) A와 B 모두 Base Branch와 차이가 있을 때: Merge Conflict 발생
P4Merge: 3-way merging 및 side-by-side comparison 제공 (git 환경설정 필요)
효과적인 git branch 전략
Vincent Diessen의 Branching 모델
5가지 Branch 전략
- Master: 정식 배포되는 안정적인 버전의 소스코드; 지난 배포판 버전 추적을 위해 각 버전에 태그 (tag) 부착
- Develop: 끊임없이 소스코드가 추가됨; Feature에서 수정된 코드가 Peer-Review 검토 후 최종적으로 병합됨
- Feature: 새로운 기능 개발, 버그 수정, 성능 개선 등을 위한 코드 수정이 이뤄짐; Develop의 HEAD에서 생성됨
- Release: 정기적으로 성능 개선, 기능추가, 버그 수정이 반영된 소프트웨어가 릴리즈 되는 목적으로 사용됨;
Develop을 기반으로 생성되고, QA테스트가 Release Branch를 기반으로 진행됨. 이 과정에서 발견된
버그 수정 사항이 Release/Develop에 적용되며, 메이저 기능이 중간에 추가되지는 않음
- Hotfix: 정기적인 PR,QA,릴리즈 이외에 긴급하게 수행되어야 할 버그 수정을 반영하기 위해 사용됨;
Master Branch를 기반으로 생성되고, Hotfix 후 Master에 병합되면서 태그가 생성됨;
해당 수정 사항은 Develop에도 병합되어 긴급 수정 사항이 이후 릴리즈에도 반영되도록 함.
git-flow: 위의 Branching 모델을 쉽게 사용할 수 있는 git 확장 라이브러리. (따로 정리할 예정)
cherry-pick
같은 Base를 가진 A Branch에서 B Branch의 이전 버전을 일부 병합하고 싶을 때 사용
rebase
같은 Base를 가진 B Branch의 버전들을 A Branch의 최신 버전으로 이어 붙일 때 사용 (병합+타임라인 )
Checkout vs Reset
checkout: 기본적으로 HEAD의 상태를 제어함
HEAD: 기본적으로 현재 checkout된 Branch를 가리킴
-> 만약 특정 commit에 HEAD를 직접 checkout할 경우, 이것을 detached 상태라고 함
reset: HEAD가 Branch를 가리키고 있는 동안은, Branch를 제어함 (보통 이렇게 쓰진 않음)
#상황 예시: Branch A -> #2 (commit ID), Branch B -> #3, HEAD -> Branch B
$ git reset A
#결과: HEAD -> Branch B -> #2, #3은 사라지게 됨
Remote Repository 백업 시 통신
- HTTP: 낮은 진입장벽 (공부 안해도 됨), 낮은 보안성, 낮은 편리성
- SSH: HTTP의 반대
Local -> Remote Repository 백업
$ git remote add origin https://github.com/beomwookang/my-repo.git #remote repository의 주소
# -> add 뒤에는 Remote Repo의 별명을 넣지만, 관습적으로 origin 사용
$ git push -u origin master
하나의 Local Repo는 여러 개의 Remote Repo에 올라갈 수 있지만, 기본적으로 올라갈 Repo를 지정해야 함
$ git push --set-upstream origin master
Remote -> Local Repository 복원
새롭게 Repo 복제
$ git clone [remote URL]
현재 Repo의 업데이트 내용 불러오기
$ git pull
Remote Repo 중심으로 작업할 때 git 흐름
혼자 작업할 때:
git pull -> git commit -> git push
*여러 사람이 작업할 때:
git fetch -> git merge FETCH_HEAD -> git commit -> git push
#FETCH_HEAD: 가장 최근에 fetch한 commit ID
즉, git pull
은 git fetch -> git merge
와 동일함
git fetch
를 하게 되면, Local B에서 push한 내용말고 remote의 master 내용만 가져옴git merge
를 통해 Local B의 내용도 병합할 수 있음*git fetch를 사용하는 이유
-> 업데이트 사항을 가져올 때 신중하게 적용하기 위해
Pull Request
내가 한 작업 (ex: 새로운 기능 추가)가 Master Branch에 병합되기 전에 다른 사람에게 코드 리뷰/검토를 요청할 때 사용; 즉, 코드의 품질을 높이고 Master Branch의 안정성을 높이기 위한 방법
두가지 형태의 request 방식이 존재함
git fork
사용Pull Request 코드 리뷰
Pull Request Conflict 해결
1. Web editor 사용
2. Command line을 통해 직접 해결
1) 요청한 branch로 전환 후, master를 merge하여 conflict 해결
$ git fetch origin
$ git checkout branch2
$ git merge master
2) master branch로 변경 후 새로운 branch를 merge
$ git checkout master
$ git merge --no-ff new_branch #no fast-forward
$ git push origin master
Pull Request 시 Merge 종류 차이