Search
Duplicate

Git & GitHub 기초 및 활용

VCS ?

Version Control System ( 버전 관리 시스템 ) 여기서는 VCS라는 용어만 이해합시다. 나중에 잘 써먹을 수 있게….

주요 VCS

CVS → SVNGit
1.
CVS ( Coucurrent Versions System, 동시 버전 시스템 )
서버 - 클라이언트 형상관리 시스템
1986 ~ 1990년에 출시된 VCS. SVN 출시 전까지 사용됨.
상대적으로 속도가 느리며, Commit 실패 시, Rollback 처리 불가함.
굳이… 자세한 내용은 알 필요는 없고, CVS라고 함은 옛날에 쓰던 VCS라고만 알고 있으면 됨.
2.
SVN ( Subversion )
CVS의 단점을 보강하기 위해 2000년에 만들어진 VCS.
중앙관리만을 지원하는 시스템. ( SVN 서버를 의미함 )
파일과 디렉토리의 삭제, 이동, 이름 변경 복사 등을 지원
소스 파일 외로, 이진파일 (바이너리) 저장 가능
CVS에 비하여 빠른 속도
CVS에 보다 불안정함. ( 왜인지는 잘… )
디렉토리 구조로 SVN 리파지토리가 지저분한 편
3.
Git
리눅스를 개발한 리누스 토발즈가 만든 VCS ( 2005년 출시 )
실제로 리눅스 커널 개발을 할 때 사용하려고 만들었다고함.
가장 큰 특징으로는 로컬 리파지토리와, 원격 리파지토리가 구분되어 있는 분산형 관리 시스템이라는점.
원격 리파지토리에 영향을 주지 않고 안전하게 로컬에서 작업할 수 있음.
처리 속도가 빠르고, 로컬 리파지토리에 복사본을 저장하여, 브랜치 간 빠른 전환이 가능함.
파일의 변경 이력을 확인 할 때 SVN은 반드시 SVN서버와 통신이 필요함. 반면에 Git의 경우 로컬 Git에서 파일의 수정 이력을 트래킹하기 때문에 굉장히 빠르다!
단순한 구조인 CVS, SVN에 비하여 러닝커브가 있긴함. 이 부분은 금방 적응이 가능함
소스 코드 및 이력을 로컬 저장소에도 저장하기 때문에, 중앙 서버에 장애가 발생하더라도 개발자들의 로컬 리파지토리를 활용하여 복구도 가능하다! (분산형 관리의 장점)
Git에서 제공하는 브랜치 기능을 활용하여, 여러 명이 동시에 작업하는 병렬 개발이 가능함.
협업하는 개발자 간 소스 파일을 주고 받는… 행위를 할 필요가 없다.

Git 기초 용어

Git에서 사용하는 용어들입니다.
Repository 저장소를 의미하며, 저장소는 히스토리, 태그, 소스의 가지 치기 혹은 branch에 따라 버전을 저장한다. 저장소를 통해 작업자가 변경한 모든 히스토리를 확인 할 수 있다.
Working Tree 저장소를 어느 한 시점을 바라보는 작업자의 현재 시점.
Staging Area 저장소에 커밋하기 전에 커밋을 준비하는 위치.
add 다음 변경(commit)을 기록할 때까지 변경분을 모아놓기 위해서 사용. 즉, 스테이징을 할 파일을 지정하는 역할을 한다.
commit 현재 변경된 작업 상태를 점검을 마치면 확정하고 저장소에 저장하는 작업.
head 현재 작업중인 Branch를 가리킨다.
branch 가지 또는 분기점을 의미하며, 작업을 할때에 현재 상태를 복사하여 Branch에서 작업을 한 후에 완전하다 싶을때 Merge를 하여 작업을 한다.
merge 다른 Branch의 내용을 현재 Branch로 가져와 합치는 작업을 의미한다.
init git으로 버전관리 하고싶은 폴더에서 초기화를 하는 준비. 해당 디렉토리에 .git 이라는 숨김폴더가 생성이된다. (git 관련 파일들이 위치함)
checkout 독립된 작업 공간인 브랜치를 자유롭게 이동할 수 있다.
pull 리모트 저장소의 변경된 내용을 로컬(내 컴퓨터) 저장소에 적용하는 작업을 pull이라 한다.
fetch 원격 저장소에 있는 프로젝트를 로컬 저장소에 가져오는 것
master git init을 했을 때, default로 만들어지는 브랜치가 'master'이다.

자주 쓰이는 Git 명령어

보통 개발자들은 IDE의 플러그인을 통한 GUI 환경에서 Git을 사용합니다. GUI 기반의 플러그인은 내부적으로 로컬 컴퓨터의 설치된 git으로 명령어를 전달하는 개념이기 때문에, Git을 제대로 활용하기 위해서는 CLI 환경에서 Git을 이용하지 않더라도 주요 명령어의 동작 원리를 이해하는것이 중요합니다.
git config
로컬 PC에 Git을 설치 후 사용자에 대한 설정
# 사용자 이름, Email 설정 git config --global user.name “[firstname lastname]git config --global user.email “[valid-email]# 사용자 설정 정보 확인 git config --list # 사용자 이름, Email 확인 git config --global user.email git config --global user.name
Bash
복사
git init
기존 디렉토리를 Git 저장소로 만들기
# 프로젝트 directory로 이동 cd [my_project path] # README 파일 생성 echo "# my_project" >> README.md # git 저장소로 등록 git init # 관리할 file을 Staging Area 추가 git add README.md # Staging Area 에 추가된 파일 commit git commit -m "first commit" # 최초 등록된 master branch 대신 main branch 사용하도록 변경 git branch -M main # 원격 remote repository에 추가 git remote add origin [git URL] # git push git push -u origin main
Bash
복사
git clone
git repository 가져오기
git clone [url]
Bash
복사
git add
Staging Area에 파일을 추가
git add [file]
Bash
복사
git status
Staging Area, UnStage Area에 있는 파일 및 Untracked 상태의 파일을 확인할 수 있다.
git status
Bash
복사
git diff
두 트리 개체의 차이를 보고 싶을 때 사용한다.
# stage 되지 않은 변경 비교 git diff # stage 되어 있으나 아직 commit 되지 않은 변경 비교 git diff --staged
Bash
복사
git commit
Staging Area의 모든 파일을 커밋한다. 저장소에는 하나의 스냅샷으로 기록된다. 그 뒤 현재 Branch가 새 커밋을 가리키게 한다.
git commit -m '[커밋 상세 메시지]' # --amend 옵션으로 최근 커밋을 재작성할 수 있다 git commit --amend # 아래와 같이 commit에 깜박한 파일이 있으면 아래와 같이 수정 가능하다. # 이렇게 --amend 옵션으로 커밋을 고치는 작업은 이전의 커밋을 완전히 새로 고쳐서 # 새 커밋으로 변경하는 것을 의미한다. # 이전의 커밋은 일어나지 않은 일이 되는 것이고 당연히 히스토리에도 남지 않는다. git commit -m 'initial commit' git add forgotten_file # 최근 커밋에 누락된 파일 지정 git commit --amend
Bash
복사
git reset
되돌리는(Undo) 명령이다. git reset명령은 매우 위험하므로 주의하여 사용하여야 한다.
# Staged 상태의 파일을 Unstage 로 변경 git reset # staging area가 초기화되고 working tree를 특정 커밋시점으로 덮어쓰기 git reset --hard [commit] # 이전 Head 시점으로 초기화. working directory, 최근 commit 이력이 삭제된다. git reset --hard HEAD^
Bash
복사
git rm
Staging Area나 Working directory에 있는 파일을 삭제한다.
git rm [file]
Bash
복사
git clean
working directory에서 필요 없는 파일을 삭제한다. 충돌로 생긴 파일이나 build artifact 파일을 삭제할 때 편리하다.
git clean
Bash
복사
git mv
파일/폴더의 이름을 변경한다.
git mv [existing-path] [new-path]
Bash
복사
git branch
branch를 관리하는 명령어 이다.
# branch 목록 조회, *가 현재 branch git branch vim@pjw MINGW64 /d/dev/crinity_project/cts/crinity-total-suite (master) $ git branch aws_cts calendar_basic * master # 원격 branch 목록 조회 git branch -r # 전체 branch 목록 조회 git branch -a # branch 생성 git branch [branch-name]
Bash
복사
git checkout
Branch를 변경하고 해당 파일을 Working directory로 복사한다
# branch checkout git checkout [branch-name]
Bash
복사
git merge
다른 Branch를 현재 Checkout된 Branch에 Merge 한다. Merge 하고 나서 현재 Branch가 Merge 된 결과를 가리키도록 옮긴다.
# 특정 branch를 현재 checkout 된 branch에 merge git merge [branch] # remote origin의 main branch merge git merge origin/main # local 저장소의 main branch merge git merge main
Bash
복사
git log
commit 히스토리를 시간의 역순으로 보여준다.
# 커밋 히스토리를 시간 순으로 조회 git log # 최근 number개만 노출 git log -[number] # oneline 으로 히스토리 노출 git log --oneline # graph 로 출력 git log --graph
Bash
복사
git fetch
로컬 저장소에 있는 것을 뺀 remote 저장소의 모든 것을 가져온다.
git fetch [remote] # --prune 옵션으로 remote 저장소에 지워진 브랜치를 local 반영하여 # local의 불필요한 branch를 삭제한다. git fetch --prune
Bash
복사
git pull
remote의 commit을 가져오고 병합한다. git fetch 와 git merge 명령을 순서대로 실행하는 것과 같다.
git pull
Bash
복사
git push
로컬 저장소의 commit 내역을 remote 저장소로 전송한다.
git push [remote] [branch] # -u 옵션은 upstream repository를 설정해준다. # 즉 한번 설정한 후로는 git push, git pull 만 간단히 쓸 수 있다. git push -u origin main
Bash
복사
git remote
원격 저장소 설정 관리 도구. remote , push를 제외한 다른 명령어들은 Local Git에서만 영향을 준다는 점을 인지하자.
# 현재 프로젝트에 등록된 리모트 저장소를 확인 git remote # 단축이름과 URL을 함께 조회 git remote -v # git url 에 remote(저장소) 이름으로 등록한다. git remote add [remote] [url] git remote add origin https://github.com/cusbert/TIL.git
Bash
복사
git stash
현재 작업을 임시 저장하는데 사용한다. A라는 작업을 진행하다가 잠깐 다른 B 작업을 우선 할 일이 생겼다. 이 때 A를 커밋하지 않고 Stash 했다가 B를 끝낸 후 다시 A라는 작업을 진행 할 수 있다. Branch에 상관없이 아직 끝내지 않은 수정사항을 스택에 잠시 임시저장했다가 나중에 다시 적용할 수 있다.
# modified, staged 변경 내용 임시 저장 git stash # stashed 조회 git stash list # stash 내역 working directory로 추가 git stash pop # stash file 제거 git stash drop
Bash
복사
git rebase
두 개의 공통 Base를 가진 Branch에서 한 Branch의 Base를 다른 Branch의 최신 커밋으로 branch의 base를 옮기는 작업 상황에 따라서 Base를 Master 혹은 특정 Branch로 할 수 있습니다. (주로 Master) 클라우드 메일와 같이 여러 개발자가 같은 리파지토리에서 여러 기능을 개발하는 환경에서 많이 사용합니다. 중요!
git checkout feature/abc git rebase master
Bash
복사

GitHub ?

Git을 사용하는 프로젝트를 지원하는 웹 호스팅 서비스
Github와 유사한 역할을 하는 저장소 서비스
1.
GitLab :: 설치형 GitHub 컨셉으로 시작되었다!
2.
BitBucket :: JIRA 개발사인 atlassian에서 개발. 설치형, SaaS 모두 제공
3.
AWS CodeCommit ← SirTeam 서비스 사용!
4.
Azure Repos

주요 용어 정리

Repository GitHub에서 관리하는 원격 저장소. 공개, 비공개로 구분된다.
Clone 원격 저장소 자체를 로컬 저장소에 복제한다.
README.md 프로젝트의 대한 설명을 작성한다. 리파지토리의 최상위 디렉토리에 작성.
Contributors 프로젝트의 기여자 리스트. Commit, Review 등 프로젝트의 기여자를 확인할 수 있다.
Pull request(PR) 브랜치에서 작업한 이력을, 특정 브랜치로 Merge 요청한다.
A브랜치 → Master
A브랜치 → B브랜치
PR을 할 때, 메시지를 작성할 수 있는데, 리뷰어가 수정범위 파악에 도움이 되도록 동기, 중요 변경점, 주의 사항 정도를 정리하여 작성 하는 것이 좋다.
아래와 같이 PR 메시지의 템플릿을 설정할 수 있다.
PULL_REQUEST_TEMPLATE.md
0.1KB
활용 사례
1.
Master → A 브랜치 생성
2.
A브랜치에서 기능 수정
3.
Master로 Pull request
4.
리뷰어의 검토 이후 Merge 되거나 거절
Fork 특정 리파지토리를 본인 계정의 리파지토리로 복사하는 기능. 주로 오픈소스에 기여하고자 할 때 사용한다.
활용 사례
1.
A 리파지토리의 특정 브랜치 Fork
2.
포크한 리파지토리의 브랜치 생성 후 기능 수정
3.
A 리파지토리에 Pull request
4.
리뷰어의 검토 이후 Merge 되거나 거절

SVN → Git 변경 이유 ?

저희 팀에서 형상관리를 Git으로 변경하게된 계기를 소개합니다.
1.
XXX 서비스 규모가 커짐에 따라 많은 기능 개선 필요성 증가.
2.
각 팀원별로 다른 기능을 개발하다보니 매번 코드를 병합하기 쉽지 않음.
3.
자연스럽게 커밋 눈치 싸움(?)을 하다보니 피곤해져서, 브랜치 전략이 필요해졌음.
4.
SVN은 로컬 리파지토리를 제공하지 않기 때문에, Trunk or Branch에 Commit을 하기 애매한 상황이라면, 개발자 PC 개발환경에 고대로 보관을 해야한다. 이러한 상황이 많아진다면 같은 개발환경을 여러개 꾸며야하는 상황이 자주 발생한다.
5.
편리한 병렬 개발을 위한 브랜치 전략을 활용하려면, 신규 리파지토리를 생성하여 기존 브랜치 소스를 Trunk로 이전을 하는 과정이 필요했음.
→ 즉, 형상을 이전하는 시기가 왔기 때문에, SVN에 남을지, Git으로 변경할지 갈림길에 선 상태..
6.
두 VCS 중 브랜치 전략을 활용하는 관점에서 이점이 많은 Git을 생각하게됨.
→ 물론… Git을 사용하고자 하는 팀 구성원들의 의지도 컸음.
7.
XXX 서비스 특성상, 소스의 형상을 이전하는데 제약조건이 크지 않았음.
XXX 서비스 브랜치만 Git으로 이전할 때 다른 개발자들에게 피해를 주지 않음.
8.
개인적으로 체계적인 코드 리뷰 문화를 만들고 싶었는데, Git과 GitHub를 사용하게 되면
코드 리뷰를 편하고, 체계적으로 정착시킬 수 있다고 생각했음.

SVN 과 Git의 차이점

많은 차이점이 있겠지만, 여기서는 저희 개발자가 느낄 수 있는 부분을 설명합니다.
종류
Commit 대상
로컬 저장소
소스 체크아웃
로컬 브랜치 전환
Git
개발자 → 로컬 → 리모트
O
Git 리파지토리 소스 전체 다운로드
로컬 리파지토리에서 포인터만 변경 (매우 빠름)
SVN
개발자 → 리모트
X
SVN 브랜치 소스만 다운로드
브랜치 별로 워크스페이스를 옮겨야 함 (개발환경 여러개..)
SVN의 경우 브랜치별로 소스코드를 내려 받아 개발환경 구성하는 방식
동일한 브랜치에서 여러 기능을 개발해야하는 경우, 기능 별로 커밋을 하기 위하여 동일한 개발환경을 여러번 구성
Git의 경우 리파지토리를 전체 Clone특정 브랜치를 체크아웃을 받아 개발환경 구성하는 방식 동일한 브랜치에서 여러 기능을 개발해야하는 경우,
이미 구성된 개발환경에서 브랜치 전환(체크아웃)만 하여 개발

SVN 사용 환경

운영 환경에 배포된 소스의 형상관리를 하기 위하여 수정 내용 반영전까지 커밋하지 못함
여러 개발자가 같은 브랜치에 다른 기능을 개발할 때, 개발자간 파일을 주고 받거나,
미완료 상태의 코드를 커밋을 해야함 (찝찝함..)
개발자 혼자 여러기능을 개발할 때, 기능 단위 커밋을 하기 위하여, 동일한 개발 환경을 여러개 꾸며야함.
코드 리뷰 및 테스트를 하려면, 개발자의 PC에서 하거나, 리뷰어가 개발환경을 다시 꾸며야함.
주니어 개발자의 경우 SVN 서버에 바로 Commit을 해야하니 많은 부담감을 느낌.
덩달아 선배 개발자의 마음도 불안..

Git, GitHub, 브랜치 전략 사용 환경

실제 배포가 되는 브랜치가 아닌 기능 개발을 위한 브랜치에 커밋을 한다. 즉, 운영 배포 시기와 별개로 커밋을 자유롭게 할 수 있다.
여러 개발자가 같은 리파지토리(SVN 기준 브랜치)에서 서로 다른 기능을 개발할 때,
개발자 별로 브랜치를 생성하여 서로 간섭없이 작업을 할 수 있고 서로의 코드를 편리하게 확인 할 수 있다.
개발자 혼자 여러기능을 개발할 때, 로컬 브랜치(기능 단위)를 생성하여
필요 시, 브랜치 전환(체크아웃)만 하여 이미 꾸며진 개발환경에서 개발을 할 수 있다.
같은 형상일 경우 개발환경을 한번만 꾸미면 된다!
코드 리뷰 및 테스트를 할 때, 리뷰어는 본인의 개발환경에서 해당 브랜치만 체크아웃
하여 빠르고 간편하게 확인 및 테스트를 할 수 있다.
개발자는 본인이 생성한 원격지 브랜치에 커밋을 하고 코드 리뷰를 진행한 뒤 Master 리파지토리에 병합이 되기 때문에, 작업에 대한 부담감이 상대적으로 적다.

브랜치 전략 채택 : GitHub flow!

주요 브랜치 전략으로는 Git flow, GitLab flow, GitHub flow가 있다. 쉽고 빠른 코드 통합이 중요한 XXX 서비스에는 GitHub flow가 적합하다고 판단되었음.
release 브런치가 명확하지 않은 시스템에서 사용에 맞게 되어있다.
여기에는 GitHub의 서비스 특성상. 릴리즈라는 개념이 없는 서비스를 진행하고 있어서 그런 것으로 보이며, 웹 서비스들이 릴리즈라는 개념이 없이지고 있으니 사용하기 편할 것으로 보인다.
hotfix와 가장 작은 기능을 구분하지 않는다. 어차피 둘 다 개발자가 수정해야 되는 일중에 하나이다. 단지 우선순위가 어디가 높냐라는 단계이다.

GitHub Flow 사용법!

1. master 브런치는 어떤 때든 배포가 가능하다.

master 브런치는 항상 최신의 상태이며, stable 상태로 Product에 배포되는 브런치이다. 그리고 이 브런치에 대해서는 엄격한 role를 주어 사용한다.

2. 새로운 일을 시작하기 위해 브런치를 master 에서 딴다면 이름은 어떤 일을 하는지 명확하게 작성한다.

git flow 와는 다르게 feature 브런치나 develop 브런치가 존재하지 않는다. 그렇기에 새로운 기능을 추가하거나 버그를 해결하기 위한 브런치의 이름은 자세하게 어떤 일을 하고 있는지에 대해서 작성해주도록 하자. Github 페이지에서 보면 어떤 일들이 진행되고 있는지를 확인하기 쉽게 말이다.

3. 원격지 브런치로 수시로 push를 한다.

git flow 와 가장 상반되는 방식이다. 항상 원격지에 자신이 하고 있는 일들을 올려 다른 사람들도 확인할 수 있도록 해준다.이 방법의 좋은 점은 하드웨어에 문제가 발생하여 작업하던 부분이 없어지더라도 원격지에 있는 소스를 받아서 작업을 할 수 있도록 해준다.

4. 피드백이나 도움이 필요할 때, 그리고 머징 준비가 완료되었을 때는 pull request를 생성한다.

pull request 는 코드 리뷰를 도와주는 시스템이다.그렇기에 이것을 이용하여 자신의 코드를 공유하고, 리뷰를 받을 수 있도록 한다. 물론 머지가 준비 완료되어 master 브런치로 반영을 요구하여도 된다.

5. 기능에 대한 리뷰와 사인이 끝난 후 master로 머지한다.

곧장 product로 반영이될 기능이기에 이해관계가 연결된 사람들과 충분한 논의 이후 반영하도록 한다.

6. master로 머지되고 푸시되었을 때는 즉시 배포되어야 한다.

GitHub Flow의 핵심인듯한 master로 머지가 일어나면 hubot을 이용하여 자동으로 배포가 되도록 설정해놓는다. 라고 하지만….. 저희 클라우드 서비스의 경우 수동 배포를 합니다. (물론 젠킨스로..)

장점 ?

브런치 전략이 단순하다.
처음 git을 접하는 사람에게 정말 좋은 시스템이 된다.
Github 사이트에서 제공하는 기능을 모두 사용하여 작업을 진행한다.
코드 리뷰를 자연스럽게 사용할 수 있다.
CI가 필수적이며, 배포는 자동으로 진행할 수 있다.
Github가 작업을 할 때 이렇게 작업하고 있다.

단점 ?

CI와 배포 자동화가 되어있지 않은 시스템에서는 사람이 관련된 업무를 진행한다.
많은 것들이 올라오기 시작하면… 그때부터는 헬이…

Pull request를 활용한 코드 리뷰 문화

저희 XXX팀에서는 선, 후배 상관없이 1 on 1으로 서로의 코드를 리뷰하고 있습니다. 참고로 제 파트너는 XXX님이에요!
리뷰어의 시간을 아껴줄 수 있도록 좋은 Pull request를 쓰도록 합시다!
기능 단위의 브랜치에서 작업을 하고, Master 브랜치에 Merge가 되는 과정입니다.
1.
개발자 : Master Branch → Feature Branch 생성 → 개발 → Local Branch Commit → Remote Branch Push
2.
개발자 : Pull Request
3.
리뷰어 : 코드 리뷰 → 피드백
코드에 문제가 없다면, Master Branch로 MergeFeature Branch는 삭제한다.
현재 Master 코드와 충돌 되지 않는다면 자동으로 Master Branch에 Merge 된다.
코드에 문제가 있는 경우, 코멘트 기능을 활용하여 피드백 후, 해당 request를 Close한다.
단순 댓글 뿐만 아니라, 특정 코드 라인에 대한 코멘트를 작성할 수 있음.
4.
개발자 : 피드백 받은 부분에 대하여 수정 후, 추가 Commit.
5.
개발자 : Close 된 Pull request를 다시 Open.
6.
리뷰어 : 코드 리뷰 → Master Branch Merge → Feature Branch 삭제