Git 정리

밤무스·2022년 2월 14일
0

Git 기본 개념 및 버전 관리

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] 을 사용할 수 있지만 일일이 적용하기 어려움

  1. 깃 최상위 폴더에서 .gitignore 이름의 파일 생성
  2. 한 줄씩 제외할 파일 혹은 폴더명 입력 (정규표현식 사용 가능)
    file1.txt             	  #특정 fileName
    /file1.txt                #현재 경로의 특정 fileName
    directory1/               #특정 디렉토리의 모든 파일
    directory1/file1.txt      #특정 디렉토리의 특정 파일
    directory1/**/file1.txt   #특정 디렉토리 아래의 모든 특정 파일
    *.txt					  #특정 확장자
    !file2.txt				  #예외 만들기
    

Git Branch 기능

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은 사라지게 됨

Git을 통한 백업

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

Git을 통합 협업

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 pullgit fetch -> git merge와 동일함

  • Local A에서 git fetch를 하게 되면, Local B에서 push한 내용말고 remote의 master 내용만 가져옴
  • 그 다음 git merge를 통해 Local B의 내용도 병합할 수 있음

*git fetch를 사용하는 이유
-> 업데이트 사항을 가져올 때 신중하게 적용하기 위해

Pull Request
내가 한 작업 (ex: 새로운 기능 추가)가 Master Branch에 병합되기 전에 다른 사람에게 코드 리뷰/검토를 요청할 때 사용; 즉, 코드의 품질을 높이고 Master Branch의 안정성을 높이기 위한 방법

두가지 형태의 request 방식이 존재함

  1. Remote Repo에 대한 직접적인 접근 권한을 가지고 있는 경우:
    • 코드에 대한 다른 사람의 의견이나 검토를 받을 때 사용됨
  2. Read 권한만 있고 Write 권한은 없는 경우 (대표적으로 오픈소스 프로젝트):
      1. "Remote Repo 복제" 를 위해 git fork 사용
      1. 수정 사항이 프로젝트에도 유용하다고 생각될 때 original repo 소유자에게 검토 요청

Pull Request 코드 리뷰

  • Files Changed에 들어가서 각 행 별로 코멘트를 작성할 수 있음
    - Add single comment: 해당 부분에 대해 바로 요청자가 볼 수 있는 댓글 작성
    - Start review: 여러 부분에 대한 리뷰를 묶어서 전달
    • Insert suggestion: 실제 코드 제안 가능

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 종류 차이

  • 일반적인 Merge: 새로운 Branch의 History를 그대로 Merge
  • Squash and Merge: 새로운 Branch의 history를 하나의 Commit으로 통합하여 Merge
  • Rebase and Merge: 새로운 Branch의 history를 Master Branch와 하나의 타임라인으로 통합

0개의 댓글