- 개인적으로 공부하면서 지속적으로 정보를 추가, 수정, 삭제합니다.
- 정확하지 않은 부분 피드백 주시면 감사합니다.
- 노란색 하이라이트는 블로그 주인의 생각 + 개인적으로 이해가 더 필요한 부분을 표시한 것입니다. 특별히 더 중요한 개념으로 표시한 것이 아닙니다.
- 본 노트는 책 『팀 개발을 위한 Git, GitHub 시작하기』을 보면서 정리한 내용입니다.
출처: 『팀 개발을 위한 Git, GitHub 시작하기』, 정호영, 진유림, 한빛미디어, 2020.
Git과 GitHub 기본 활용
1. Git과 GitHub의 개념
1. Git의 유래와 정의
- 개발자의 일을 도와주는 ‘도구’
- 분산 버전 관리 시스템
- 리눅스 창시자 리누스 토발즈가 리눅스의 소스코드를 관리하기 위해 개발 → 리눅스와 비슷하고, 리눅스의 철학을 가지고 있음
2. Git의 장점
- 협업을 위해 소스코드의 버전 관리를 쉽게 할 수 있게 해준다 (만약 Git과 같은 툴이 없다면 일일이 소스코드 공유와 검토를 메일로 주고 받아야 할 수도 있다.)
3. 버전 관리와 버전 관리 시스템의 필요성
- 버전 관리 : 내가 원하는 버전(시점)으로 이동할 수 있게 해주는 것
- 버전 관리 시스템 : 버전 관리를 도와주는 툴(포토샵의 히스토리 팔레트를 떠올려라)
- 버전 관리의 필요성: 개인이 혼자 사용한다면 필요 없을 수도 있다, but 팀 프로젝트라면? ☞ 인원이 많을수록 어느 것이 최종 업데이트 파일인지 확인하기 어려움
4. Git과 Github
- 소스코드 버전을 관리할 수 있게 해주는 시스템이 Git ☞ Git은 데이터를 저장할 공간만 있다면 어디서든 사용 가능! (ex. USB, 클라우드 서버, 개인 컴퓨터 등)
- Git으로 관리하는 프로젝트를 올려둘 수 있는 Git 호스팅 사이트 중 하나가 GitHub ☞ 블로그를 만드는 곳이 다음, 네이버, 워드프레스 등 다양한 것처럼 Git으로 관리하는 프로젝트를 올리는 사이트도 GitLab, BitBucket 등 다양함.
5. GitHub을 비롯한 Git 호스팅 사이트 사용의 장점
- 시공간 제약 없이 누구와도 협업 가능
- 누구든지 기여할 수 있는 공개저장소 프로젝트 ☞ 오픈소스라고 함
- 오픈소스는 개발의 꽃
2. 내 컴퓨터에서 Git 사용하기
0. 사용할 도구 및 웹사이트 : Git, Git Bash, GitHub
1. Git 설치하기
- 다운로드 : https://git-scm.com/download/win
- Git Bash 실행하기
$ git
→ git 기본 명령어 설명이 나오면 제대로 설치된 것
2. 로컬저장소 만들기 (= [.git] 폴더 만들기)
- 프로젝트 폴더 안에 내가 사용할 폴더 생성 (여기서는 iTshirt-cat라는 폴더를 생성 → 프로젝트명-개발자명)
- README.txt 파일 생성
- 폴더 화면 → 우클릭 → Git Bash Here
- 폴더 경로에서 Git Bash가 실행 됨
- git 초기화 과정 거치기(※ 초기화 과정이란 로컬 저장소를 생성한다는 것, 이미 [.git]이 만들어진 폴더에서 사용하면 꼬인다) ^fa14cf
$ git init
→Initialized empty Git repository in 폴더경로/.git/
나오면 성공
- [.git] 이라는 폴더가 생성됨 (숨김 설정 되어있으므로 숨김 항목 보기 체크)
- Git으로 생상한 버전들의 정보, 원격저장소 주소 등이 들어갈 예정
- 이 폴더를 로컬저장소라고 부른다!
- 이제 이 프로젝트 폴더에서 버전 관리를 할 수 있게 된다
3. 여러 커밋을 만들고 시간 여행하기 (※ Git에서는 생성된 각 버전을 commit이라고 부름)
- 첫 번째 커밋 만들기
- 각 버전을 누가 만들었는지 표기하기 위해 내 정보를 등록한다 (GitHub 계정 정보를 입력하라) ^1ac90c
$ git config --global user.email "깃헙이메일"
$ git config --global user.name "GitHub유저네임"
- 커밋에 추가할 파일을 선택하기 ☞
$ git add 파일명.확장자
- 방금 만든 README.txt 파일을 선택할 예정
$ git add README.txt
- 커밋에 상세 설명 적기 (※ 내가 왜 이 파일을 만들었는지, 왜 수정했는지 표기해주는 것) ☞
$ git commit -m "메시지"
^5584ed$ git commit -m "사이트 설명 추가"
→-m
은 메시지의 약자1 file changed, 1 insertion(+)
나오면 첫 번째 버전 만들기 성공!
- 각 버전을 누가 만들었는지 표기하기 위해 내 정보를 등록한다 (GitHub 계정 정보를 입력하라) ^1ac90c
- 두 번째 커밋 만들기
- 방금 커밋한 README.txt 파일의 두 번째 커밋을 만들어 볼 예정
- README.txt 파일을 열어 내용을 수정하기
- README.txt 파일을 다시 커밋에 추가 ☞
$ git add 파일명.확장자
- 커밋에 상세 설명 적기 ☞
$ git commit -m "메시지"
1 file changed, 1 insertion(+), 1 deletion(-)
나오면 두 번째 버전 만들기 성공!
- 다른 커밋으로 시간 여행하기 (※ checkout 한다고 표현한다!)
- 첫 번째 커밋으로 돌아가보자
- 커밋 기록을 확인하기 ☞
$ git log
- 두 개의 커밋을 확인할 수 있을 텐데, 다음과 같은 정보를 보여줄 것 (
git log
명령어는 최신 커밋부터 보여준다!)
commit 96a3dk3 ~ : 메시지 / 날짜 ☞ 두 번째 커밋 commit 5929bb3 ~ : 메시지 / 날짜 ☞ 첫 번째 커밋
- 돌아갈 커밋(여기서는 첫 번째 커밋)의 앞 7자리 커밋 아이디(혹은 커밋 해시, 커밋 체크섬)를 복사 (앞 7자리 뿐 아니라 전체 아이디를 다 복사해도 가능)
$ git checkout 96a3dk3
HEAD is now at 96a3dk3 메시지
이렇게 보이면 해당 커밋으로 돌아가기 성공!- 실제로 README.txt 파일을 선택해서 확인하면 첫 번째 버전으로 돌아간 것을 볼 수 있을 것
- 커밋 기록을 확인하기 ☞
- 다시 최근 커밋으로 돌아가보자 ☞
$ git checkout -
$git checkout 최근커밋아이디
를 해도 되지만, 커밋 아이디 대신에 간단히-
붙이면 됨
- 첫 번째 커밋으로 돌아가보자
3. 협업을 위한 GitHub 원격저장소에 커밋 올리기
1. 원격저장소 만들기
- 원격저장소란?
- GitHub에서는 원격저장소를 레포지토리 Repository 라고 부름
- 원격저장소 ↔ 로컬저장소 라고 생각하면 됨
- 원격저장소를 만들어 관리하는 두 가지 방법(※ 지금은 두 번째 방법)
- GitHub에서 원격저장소 생성 → 내 컴퓨터에 클론
- 내 컴퓨터에 로컬저장소 생성 → Github에 원격저장소 생성 → 로컬저장소에서 원격저장소 주소를
remote add
- GitHub → New repository → Repository name, 공개 모드 설정, description을 적절히 작성한 뒤 생성 (※ 비공개는 3인 이하의 공동작업자에게만 무료)
- 추가 정보
- Initialize with a README : README로 첫 내용 설정 ☞ 빈 저장소에 README.md 파일을 만든 채로 저장소 생성. README.md 파일에는 보통 저소에 대한 설명, 설치 방법, 저장소 기여한 사람 등 작성. 저장소를 클릭하면 바로 첫 화면에 표시 됨.
- Add .gitignore : .gitignore 파일 추가 ☞ 작업하면서 굳이 GitHub에 올릴 필요 없는 파일 (ex. 보안 상 공개하면 안되는 파일, 자동으로 생성된 설정 파일 등) 을 선택함
- Add a license : 라이선스 파일 추가 ☞ 지적 재산권 관련 규정을 안내해주는 파일
- ex) MIT License: 비교적 널널한 라이선스. 재가공, 재배포 가능
- 추가 정보
- repository → code → HTTPS 저장소 주소 복사 (※ 다른 개발자와 협업하고 싶을때 이 주소를 알려주면 됨!)
- GitHub → New repository → Repository name, 공개 모드 설정, description을 적절히 작성한 뒤 생성 (※ 비공개는 3인 이하의 공동작업자에게만 무료)
2. 원격저장소에 커밋 올리기
- 로컬저장소에 원격저장소 주소 알려주기 ☞
$ git remote add 원격저장소닉네임 원격저장소주소
- 프로젝트 폴더 (여기서는 iTshirt-cat 폴더)에서 Git Bash Here
$ git remote add origin https://github.com/gcount85/iTshirt.git
- origin은 다음에 나오는 연결할 원격저장소의 닉네임!
- 로컬저장소에서 만들었던 커밋들을 원격저장소에 올리기(※ 푸시한다라고 표현함) ☞
$ git push 원격저장소닉네임(일반적으로origin) 커밋브랜치이름(일반적으로master혹은main)
$ git push origin master
제에발 그냥 git push 말고 이렇게 쓰장!!!- origin이라고 별명 붙인 원격저장소에, master라고 이름 붙인 커밋 줄기(브랜치, 현재 커밋을 하고 있는 이 흐름)를 올리겠다는 의미!
- 한번 이렇게 설정하면 다음엔
git push
만 써도 처음 이 옵션대로 푸쉬 됨. - 써보니 푸쉬는 마구마구 하기 보다는 좀 확실한(?) 커밋을 만든 후 하는 게 나은 듯함 → 원격으로 푸쉬 된 내용까지 되돌리거나 수정하려면 강제 푸쉬 등이 필요한 경우가 생겨서.
- GitHub 로그인 페이지가 뜨면 로그인
- 100% done이 뜨면 성공!
- GitHub의 레포지토리에서 확인하면 커밋과 파일이 잘 올라간 것을 확인
3. 원격저장소의 커밋을 로컬저장소에 내려받기 (다른 개발자가 올린 커밋을 내 컴퓨터에 받아오기!)
- 로컬저장소에 내려받기 ☞
$ git clone 복사할원격저장소주소 .
- 프로젝트 폴더에 내가 사용할 폴더 말고, 다른 개발자의 커밋을 받을 폴더를 만듦 (여기서는 iTshirt-oct)
- 해당 폴더에서 Git Bash Here
$ git clone https://github.com/gcount85/iTshirt.git .
- 복사할 원격 저장소 뒤에,
.
을 빼먹지 않는다! - 이는 현재 폴더에 다운로드 받으라는 뜻
- 만약 점을 안 찍으면 iTshirt-oct 폴더 안에 iTshirt라는 폴더가 생김 → 헷갈리겠쥬
- 복사할 원격 저장소 뒤에,
- README.txt 파일을 내 맘대로 수정해보기
- 그 파일을 커밋 생성
- 원격저장소에 푸쉬
- 레포지토리에 가면 내가 수정한 커밋이 올라가 있는 것을 확인 가능!
- 원격저장소의 새로운 커밋을 로컬저장소에 업데이트하기 ☞
$ git pull origin master
- 앞서 다른 개발자(oct, 문어 개발자)가 만든 커밋을 다시 고양이 개발자 폴더에 갱신하고자 함
- 고양이 개발자 폴더 → Git Bash Here
$ git pull origin master
1 file changed
나오면 성공!- 로컬저장소의 파일을 확인해서 최신 커밋의 상태로 갱신된 것을 확인!
GUI 환경에서 버전 관리 시작하기
1. GUI 버전 관리 환경 구축하기
0. 사용할 도구 및 웹사이트 : 소스트리, GitHub, VS Code
1. 소스트리를 이용해 커밋하기
- 지금까지 Git Bash를 이용해 CLI 방식으로 했던 것을 Git 사용을 도와주는 GUI 프로그램인 소스트리를 통해 마우스 클릭으로 진행할 예정
- 소스트리를 설치한다
- BitBucket 계정을 생성한다
- 과정 중에 Mercurial은 설치하지 않음(Git 같은 버전관리 툴이라고 함)
- Git 계정은 GitHub을 사용할 예정이니 GitHub 계정 정보로 등록
- SSH 키란 안전하게 로그인할 수 있는 장치를 갖추겠냐는 건데, 아니요를 선택
- 소스트리에 GitHub계정을 추가
2. VS Code 설치하기
내용 생략
2. GUI 방식으로 혼자 버전 관리하기
1. 로컬저장소를 소스트리에 불러오기
- Add → 로컬저장소 폴더 추가
- clone, add, create 의 차이
- Clone : 원격저장소를 내 컴에 불러오고, 소스트리에도 추가
- Add : 내 컴퓨터에 이미 있는 로컬저장소를 소스트리에 추가
- Create : 내 컴에 새로운 로컬저장소 추가 (※
$ git init
명령어와 같은 역할)
- clone, add, create 의 차이
- History 란에서 브랜치를 확인
- 원리
- 이는 [.git] 폴더 내에 저장된 정보 때문이며, 이 폴더가 바로 로컬저장소!
- Git은 이 폴더 안에 버전 관리한 데이터, 이를 올릴 원격저장소 주소 등의 정보를 저장함
- 원리
2. 소스트리에서 파일 선택하고 커밋하기
- VS code로 파일을 수정한다
- 소스트리 → History → 커밋하지 않은 변경사항 → 스테이지에 올라가지 않은 파일
- 커밋 → 스테이지에 올라갈 파일 + 버튼으로 추가 → 메시지 작성(※
$ git commit -m "메시지"
역할) → 커밋origin/master에 바로 푸시
를 선택하면 아래 3의 과정을 거치지 않아도 될 듯
커밋할 내용 없음
이라는 문구가 보이면 성공!- History → 브랜치에 커밋 추가된 것 확인!
3. 커밋을 원격저장소에 푸시하기
- 커밋 메시지에 붙은 꼬리표를 확인한다
- 실습한 바에 따르면
origin/master
,master
라는 꼬리표를 확인할 수 있음- 추가 정보
- ☞ 전자의 origin은 우리가 원격저장소의 닉네임으로 설정한 것이므로, 원격저장소에 저장된 브랜치의 버전을 나타내는 것! 후자는 로컬저장소의 버전을 말하는 것!
- 이것이 서로 일치하지 않다면, 원격저장소에도 커밋을 해줄 수 있음
- 추가 정보
- Push → 브랜치 선택(실습에 따르면
master
) → Push 버튼 클릭 (※$ git push origin master
역할) - 꼬리표가 모두 동일한 커밋에 붙어 있으면 성공!
3. 여러 명이 함께 Git으로 협업하기
0. 한 파일을 두 사람이 동시에 작업하는 경우엔 꼬이지 않을까?─즉, 병렬 버전 관리에 대한 해답
1. 브랜치Branch와 포인터 개념 이해하기
- Git이 커밋을 관리하는 방식
- 커밋은 줄줄이 기차처럼 이전 커밋과 연결되어 있음
- 만약 두 사람이 한 커밋에 동시에 수정을 한다면, 한 줄로 커밋을 이어갈 수 없게 됨 → 자연스레 두 줄로 갈래가 나뉘게 됨!
- 이렇게 특정 기준에서 줄기를 나누어 작업할 수 있는 기능을 브랜치(branch)라고 함
- 만약 브랜치를 나누지 않고 한 커밋을 기준으로 두 개의 커밋을 만드려고 하면 오류가 남 (※ 먼저 푸시한 커밋이 올라가고 뒤늦은 커밋은 '최신 코드에 푸시하라’는 오류가 남)
- 브랜치란
- 소스트리에서 커밋할 때 붙어있던 [master], [origin/master] 꼬리표가 git에서 기본적으로 제공하는 브랜치
- 브랜치는 실제 가지처럼 물리적으로 존재하는 길의 개념이 아닌, ‘포인터pointer’! (마우스 커서처럼 가리키고 있는 것을 떠올려라)
- 새로 커밋을 할 때마다 [master] 브랜치는 최신 커밋을 ‘가리킨다.’
- 만약 실제로 물리적인 길이 만들어졌다면, 브랜치를 생성할 때마다 분기가 되는 가지를 복사해와야 함 but 포인터이기에 그저 가리키기만 하면 되므로 가볍고 빠름.
- 헤드(head)란?
- HEAD라는 포인터는 브랜치, 커밋을 가리키는 포인터!
- 헤드를 이용해서 브랜치 사이를 넘나들 수 있음 (like 타임머신)
- 분리된 HEAD(Detached HEAD) 상태란 [master] 브랜치의 포인터와 [HEAD] 포인터가 서로 떨어져있는 상태를 말함 (HEAD포인터가 과거 커밋을 가리키고 있을 때)
2. 브랜치 만들고 이동하기
- 브랜치 만들기
- [master] 브랜치의 최신 커밋을 base로 [브랜치] 아이콘 클릭
- [feature/기능이름] 형식으로 브랜치를 만든다
- 추가 정보
/
는 폴더처럼 구분해주는 역할을 해줌- 미리 브랜치 규칙을 정하는 것이 일반적
- 일반적인 규칙
- 하나의 개발 브랜치에는 한 사람만 작업해서 올리는 것이 바람직
- [master] 브랜치에는 직접 커밋을 올리지 않음 (동시에 작업하다 꼬일 수 있으니)
- 기능 개발을 하기 전 [master] 브랜치를 기준으로 새로운 브랜치를 만듦
- 브랜치 이름은 [feature/기능이름] 형식으로 할 것
- [feature/기능이름] 브랜치에서 기능 개발이 끝나면 [master] 브랜치에 합칠 것 (합치기 전 pull request를 할 것 ─ 이에 대한 설명은 추후에 다시)
- 추가 정보
- 현재 브랜치가 [master]로 되어 있는지 확인 (base 브랜치를 의미)
- [새 브랜치 체크아웃]을 체크하고 브랜치 생성
- 체크아웃은 브랜치를 이동하는 명령. 브랜치를 만듦과 동시에 그 브랜치로 이동하는 것.(체크를 해제하면 브랜치는 만들어져도 HEAD 포인터가 여전히 master에 있음)
- VS code를 이용해 새로운 기능을 나타내는 파일을 만들고 커밋
- 방금 만든 브랜치의 태그가 새로운 커밋 옆에 붙어있으면 성공!
- github에도 새로 만든 브랜치가 잘 올라간 것을 확인하면 성공!
- 브랜치로 이동하기
- 브랜치를 이동하는 명령은 “체크아웃checkout”
- [master] 브랜치를 베이스로 다른 기능을 개발할 새로운 브랜치를 하나 더 만들기
- 소스트리에서 브랜치 이름에다 대고 체크아웃 명령 클릭 or 더블 클릭
- 일부러 충돌을 일으키기 위해 동일한 라인을 수정한 후 커밋 (추후 병합하면서 해결)
3. 브랜치 병합(merge)하기
- 병합이란?
- 두 버전의 합집합을 구하는 것!
- 병합의 종류
- 병합 커밋 merge commit
- 빨리 감기 fast-forward : 합친 결과가 뒷 문어와 동일 → 뒷 문어의 상태로 바꿔주면 될 일!
- 충돌 conflict : 동일한 부분이 수정되어 충돌 → 충돌 난 부분을 확인한 후 어떤 부분을 남길 지 선택하면 됨
- 두 브랜치 합치기
- 합칠 때 주의사항
- 새로운 기능을 위해 만든 브랜치가 [master] 브랜치와 잘 합병되면 삭제해도 됨
- 어떤 브랜치를 기준(base)으로 병합할 것인지 선택 잘하기!
- ex) [master] 브랜치를 기준으로 병합한다 ☞ 합친 결과물을 [master] 브랜치에 반영하겠다(git merge OOO ⇒ OOO브랜치를 내 몸(기준 브랜치)에 붙인다)
- 기준이 되는 브랜치로 이동한다(실습에서는 [master] 브랜치)
- 병합을 원하는 커밋에 우클릭 → 병합 선택
OR 소스트리 사이드바에서 합치려는 브랜치 이름에 우클릭 → 현재 브랜치로 병합 선택- [fast-forward가 가능해도 새 커밋으로 생성]한다는 것은 명시적으로 병합 커밋을 만들겠다는 것(병합 기록이 남기에 선호하는 사람도 있음)
- 원격저장소에도 push하기
- 합칠 때 주의사항
4. 병합 충돌 해결하기
- 병합 충돌을 방지하기 위한 작업 요약
- 병합 충돌을 방지하기 위해, 기능 개발을 위해 작업한 브랜치를 바로 [master] 브랜치와 병합하지 말고, [master] 브랜치를 먼저 내 기능 브랜치로 병합하여 확인하는 것이 좋다!
- 병합한 커밋이 문제가 없으면, 그때 [master] 브랜치에 반영
- 마스터 브랜치를 내 기능 브랜치로 합쳐서 충돌 확인하기
- 내 기능 브랜치로 이동(체크아웃)
- [master] 브랜치의 커밋을 선택 후 병합
- 병합 충돌 오류 발생
- “커밋하지 않은 변경사항” 선택 → 스테이지에 올라가지 않은 파일에 ⚠️ 이런 마크의 파일이 보일 것 → 충돌이 발생한 파일임!
- VS code를 통해 충돌 난 파일 확인 →
=====
를 기준으로 윗 부분은 베이스 브랜치의 코드, 아래는 병합의 대상인 브랜치의 코드가 보일 것! - 적절히 수정한 후 저장
- 다시 소스트리로 돌아가서 충돌 났던 파일을 스테이지에 올림(add)
- 커밋 → 영문 커밋 메시지가 자동으로 생성 됨 → 커밋 완료!
- ‘history’ 탭에서 병합 커밋이 생성된 것을 확인하고 push까지 마치면 성공! (※ 내 기능 브랜치가 마스터 브랜치와 합쳤을 때 이상이 없다는 것을 확인한 단계!)
- 충돌 해결 후 내 기능 브랜치를 마스터 브랜치로 병합하기
- 마스터 브랜치로 이동
- 합치려는 기능 브랜치의 최신 커밋과 병합 → Push
- 히스토리 탭에 잘 반영되면 성공!
5. 풀 리퀘스트pull request 보내기
- 풀 리퀘스트의 의의
- 충돌만 없다고 무작정 합치기보단, 내가 무엇을 바꾸었는지 협력자collaborator 가 확인하는 과정을 거치는 것이 좋음 (사수 개발자의 허락을 맡는 것)
- 확인해달라고 메시지를 보내는 과정이 풀 리퀘스트
- 새로운 브랜치를 만든 뒤 로컬저장소, 원격저장소 모두 커밋
- github → [compare & pull request] 버튼
- 네가 최근 이 브랜치에 코드를 업데이트했으니 협력자에게 풀 리퀘스트를 보내려고 하면 이 버튼을 클릭해! 라는 의미
- 다른 브랜치로 풀 리퀘스트를 보내고 싶거나 설정을 변경하길 원하면 [New pull request]
- base 브랜치와 compare 브랜치를 확인
- base 브랜치 : 병합 결과물이 올라갈 브랜치
- compare 브랜치 : base 브랜치와 비교 대상이 되는 브랜치
- 커밋과 파일을 잘 확인 후, 개발 완료한 기능의 제목, 설명을 적고 생성
- 풀 리퀘스트 제목, 내용 : 동료 개발자가 잘 이해할 수 있는 제목, 스크린샷, 테스트 하는 방법 등 첨부
- reviewers : 협력자를 지정할 수 있음 → 이 기능을 검토해야 할 관련자를 선택
- assignees : 풀 리퀘스트를 담당하는 동료, 보통 나 자신
- labels : 풀 리퀘스트에 대한 라벨. 버그, 리뷰 필요, 프런트엔드, 백엔드 등
- 풀 리퀘스트를 받은 자는 수락accept, 수정 요청request change, 병합merge pull request 을 선택할 수 있음 → 확인해보고 이상 없으면 병합한다고 가정하고 병합을 선택해보자!
- [Merge pull request] → 깃헙 안에서 병합 커밋을 만드는 것(※ 과정은 GUI 환경에서 하나 CLI 환경에서 하나 동일)
- 완료된 풀 리퀘스트는 [closed] 탭에서 확인 가능
- 소스트리에서 [패치] 아이콘을 누르면 깃헙에서 업데이트 된 이력이 적용 됨!
- pull과의 차이점: pull은 실제로 코드를 내려 받는 것이고, 패치fetch는 그래프만 업데이트하므로 코드와 상관 무, 소스트리는 자동으로 패치를 정기적으로 진행함
- 소스트리 → 마스터 브랜치 → pull해서 로컬 저장소에도 새로운 커밋을 받으면 완성.
6. 출시하기: 릴리즈(release)
- 버전명 원칙
- vn.n.n의 형식으로 사용함
- "메이저 버전 업.마이너 버전 업.유지보수/버그 수정"의 기준으로 숫자를 하나씩 올림
- 제일 최초의 버전은 “v1.0.0”
- 특정 커밋에 태그 달기
- 마스터 브랜치 → 태그 아이콘 →
v1.0.0
이라고 적고 태그 추가 - 마스터 브랜치 옆에 태그가 붙어 있는 것을 확인 → 역시나 포인터 역할을 함!
- 태그도 푸쉬를 해줘야 함 → '모든 태그 푸시’에 체크 후 푸쉬
- 마스터 브랜치 → 태그 아이콘 →
- 깃헙에서 릴리즈 확인하기
- 깃헙 → 저장소 → tag 탭에서
1 release
를 확인하면 성공!
- 깃헙 → 저장소 → tag 탭에서
4. 둘 이상의 원격저장소로 협업하기
0. 깃헙을 돌아다니다가 마음에 드는 프로젝트를 발견, 기여자contributor로 참여하고 싶을 때
- 기본적으로 원본저장소에 커밋을 올리려면 소유자 or 혹은 소유자가 권한을 부여한 콜라보레이터만 가능
- 하지만 콜라보레이터가 너무 많아지면 관리가 어렵다 → 기여자로서 풀 리퀘스트를 하게 한다!
- 기여자란, 원본저장소에 바로 커밋을 올릴 수 있는 권한은 없지만, 저장소 관리자가 확인하여 기능을 추가하도록 한 사람
- 오픈 소스에 풀 리퀘스트를 보내기 전에 '컨트리뷰션 가이드라인’을 확인하라 → 보통 원본저장소의 readme.md 파일에 링크
- 기여자의 입장에서 실습을 설명할 예정!
2. 포크fork하기
- 브랜치와 포크의 차이
- 브랜치는 모든 이력을 볼 수 있지만, 포크된 저장소의 이력을 보려면 그 저장소의 주소를 등록해야 함
- 일반적으로 5명 이하인 경우 동일한 저장소 내에서 브랜치를 나눠 협력하는 것이 효율적 but 50명 이상인 경우는 말이 달라진다.
- 포크하려는 저장소로 들어간다 → fork → 내 저장소에 원본저장소가 복붙됨
- 기여자의 계정으로 소스트리 로그인
- 옵션 → 인증 → 계정 추가 → github 계정 추가 → ✅인증 성공 → [default account for 깃헙.com]의 설정 초기화하여 '예’로 바꾸기
- 클론 → 포크한 깃헙 저장소의 주소를 이용해 로컬저장소로 클론
- 소스코드 수정 후 커밋
- 커밋 권한 오류 발생시 해결 참조 ☞ https://github.com/Cat-Hanbit/README/issues/3
- 커밋 페이지 하단의 계정이 기여자의 계정으로 되어 있는지 확인 → 아니라면 대체 작성자 정보 사용으로 계정 정보 넣기 → 커밋
- push까지 하면 성공!
3. 원본저장소에 풀 리퀘스트 보내기
- 기여자 계정으로 로그인 → [new pull request]
- [head repository]에는 내가 포크한 원격저장소, [base repository]에는 원본저장소가 보여야 함
- [create pull request]
4. 풀 리퀘스트를 승인하고 병합하기
- 원본저장소의 소유주 계정으로 로그인
- [insights] 탭에서 [forks]를 확인하면 누가 포크했는지 알 수 있음
- [pull requests] 탭 → 들어온 리퀘스트 확인
- [comment] : 댓글만 달고 싶을 때
- [approve] : 코드가 좋아서 바로 병합하고 싶을 때
- [request changes] : 수정 요청할 때
- [merge pull request] → [confirm merge]
OOO merged commit
메시지가 뜨면 성공- [insights] 탭에서 [contributor] 메뉴에 가면 기여자가 포함 된 것을 확인!
- 기여자 계정 → [your profile] → [customize your pins] → 핀하고 싶은 원본 저장소를 지정할 수 있음
5. 묵은 커밋을 새로운 커밋으로 이력 조작하기: 재배치rebase
- 재배치rebase란
- 재배치의 의의
- 커밋을 만든 후, 원본 저장소에 풀 리퀘스트를 하려 했더니 이미 최신 커밋이 생긴 경우엔 그대로 진행하면 충돌이 일어남
- 원본저장소의 커밋을 내꺼에 먼저 합친 후 그걸 다시 원본저장소에 풀 리퀘스트 하는 방법이 있음
- but 그러면 내 저장소에 불필요한 커밋 이력이 생김(원본저장소의 최신 커밋과 내 커밋을 합치는 병합 이력)
- 이렇게 하지 않고 원본 저장소의 최신 커밋에 내 이력을 이어 붙이면서 충돌을 해결하려고 할 때(※ 이 경우 fast-forward 병합인 셈) 사용함 (즉, 말 그대로 base가 되는 커밋을 바꾸는 것)
- 원격에 푸시한 브랜치는 rebase를 하지 말 것을 권함. 가급적 푸시하지 않은 혼자 사용하는 로컬 브랜치에만 적용하기!
- 재배치의 원리
- HEAD의 대상 브랜치의 공통 조상을 찾음
- 공통 조상 이후에 생성된 커밋을 대상 브랜치 뒤로 재배치
- 이때 재배치되어 옮겨진 커밋들은 이전 커밋의 사본이므로, 이전 커밋과 동일한 아이디를 갖지 않음.
- 재배치의 의의
- 기여자 계정으로 커밋 생성
- 원본저장소 소유주 계정으로 커밋 생성(※ 기여자의 커밋과 충돌을 유발하게끔 동일한 라인 수정 → 이 상태에서 기여자가 풀 리퀘스트를 보내면 충돌이 생김)
- 기여자 계정으로 원본저장소에 [new pull request] →
can't automatically merge
라는 충돌 메시지 확인 - 기여자 계정의 소스트리에서 원본저장소를 추적하도록 주소 추가(
$ git add remote
)- 하나의 로컬저장소에서 여러 원격저장소를 추적하려고 하는 것! (※ 기존에는 1로컬저장소-1원격저장소 였던 것과 다름!)
- 기여자 계정 → 저장소 → 원격 저장소 추가 클릭
upstream
으로 이름 설정(※ 원본저장소를 지칭하는 관용적 닉넴) + URL에 원본저장소 주소- 사이드바 → 원격 → upstream 우클릭 → upstream에서 가져오기 클릭(fetch)
- history 탭에서 [upstream/master]라는 태그가 보이는 것을 알 수 있음
- 새로운 베이스로 삼고 싶은 upstream 커밋을 우클릭 → 재배치
- 주의! 재배치와 같이 이력 조작을 할 때에는 해당 브랜치를 혼자만 사용하고 있어야 함! 아니면 다른 개발자에게 혼동을 줄 수 있음
- 원본 저장소의 최신 커밋과 내 커밋의 충돌이 있다면 해결
- 소스트리 액션 → 재배치 계속 → 그래프의 베이스가 바뀐 것을 확인하면 성공
- 리베이스는 커밋을 하나씩 비교하며 충돌을 확인하기에 충돌이 여러번 날 수도 있음!
- 재배치는 일반 푸쉬를 사용할 수 없고, 강제 푸쉬를 사용함
- git → 강제 푸시 가능 → 안전한 강제 푸시 사용 체크
- 푸쉬 → 강제 푸쉬 체크
- 원격저장소에도 바뀐 이력이 적용되었으면 성공!
- 기여자 계정으로 다시 원본저장소에 풀 리퀘스트 →
able to merge
라는 메시지가 뜨면 충돌이 해결된 것! - 소유주가 요청을 확인하고 승인, 병합하면 성공!
5. Git의 기타 명령어 다루기
1. amend
- 수정 못한 파일이 있어서 방금 만든 커밋에 추가하고 싶을 때, 새로 커밋을 또 만들지 않고 수정하는 것
- 첫 번째 커밋 생성
- 첫 번째 커밋에서 수정할 부분 인지 → 일단 소스코드 수정
- 커밋 → 커밋 옵션 → 마지막 커밋 정정(amend last commit)
- 도중 어멘드를 그만두고 싶다면 체크 해제
- 위의 커밋 메시지로 바꾸겠습니까 나오면 확인 → 커밋 메시지를 수정하고 싶으면 수정 → 커밋
- 원격저장소에 푸시를 안했다면 푸시
OR 이미 원격저장소에 푸시를 한 경우에는 강제 푸시(※ 이 경우 해당 브랜치를 나 혼자만 쓰고 있을 때 해야 안전함!)
2. cherry-pick
- 필요한 배경 지식
- 체리픽이란 맘에 드는 커밋 하나만 떼서 지금 브랜치에 똑 붙이고 싶을 때 사용하는 기능
- 브랜치 전략에 따라 달라짐 → Gitflow Workflow 전략을 따른다면, 아직 다른 기능은 latest 브랜치로 출시될 시점이 아닌데, 급한 버그만을 수정해서 커밋해야 하는 경우 등 사용함 ☞ 하단의 '브랜치 전략’에서 참고
- A 브랜치 생성한 후, 복수의 커밋하기
- B브랜치를 생성한 후, A 브랜치의 커밋 하나만 B 브랜치에 반영하기
- 반영하고 싶은 커밋 우클릭 → 체리픽 → 확인
- 체리픽한 커밋이 B 브랜치의 최신 커밋 위에 달라붙은 것을 확인하면 성공! (※ A 브랜치의 해당 커밋과 B 브랜치로 체리픽된 커밋의 ID가 다름 → 서로 같은 커밋은 아닌 사본 같은 개념!)
3. reset
- 옛날 커밋으로 브랜치를 되돌리고 싶을 때
- 되돌리고 싶은 시점의 커밋 우클릭 → 이 커밋까지 현재 브랜치를 초기화
- reset 옵션 3가지 ^f72090
- soft/mixed : 원하는 커밋으로 이력을 되돌리지만, 이 다음에 추가했던 모든 변경사항을 stage에 추가할 수 있게 데리고 옴
- mixed는 스테이지에 추가되지 않은 상태, soft는 스테이지에 추가 된 상태로 리셋 됨
- hard : 변경사항 이력을 남기지 않고 말 그대로 리셋
- soft/mixed : 원하는 커밋으로 이력을 되돌리지만, 이 다음에 추가했던 모든 변경사항을 stage에 추가할 수 있게 데리고 옴
- reset 옵션 3가지 ^f72090
- 푸시를 하는 경우 강제 푸시(※ 조심, 나만 쓸때만 하세요)
4. revert
- reset과 달리, 변경사항을 되돌리는 커밋을 또 하나 생성하는 것! (이력 관리가 중요한 경우 이렇게 사용) 최신 커밋부터 되돌리는 것이 좋음. 기능을 다 만들어서 마스터에 통합해놓고 그 기능을 취소해야 할 때 많이 사용함.
- 되돌리고 싶은 이상한 커밋 우클릭 → 커밋 되돌리기
Revert "되돌린 커밋의 메시지"
를 메시지로 한 커밋이 생성 됨
5. stash
- 변경사항을 잠시 다른 곳에 저장하고 커밋 만들기를 보류할 때
- 소스코드 수정 → 스태시 → 적절한 설명 작성한 후 스태시
- 스태시가 가능한 파일은 tracked 모드의 파일만 가능. 새로 만든 파일은 untracked 상태라 들어가지 않음.
- 사이드바의 스태시 → 원하는 스태시 우클릭 → 스태시 적용 → 스태시를 계속 쓸 것이 아니면 적용후 삭제 체크
CLI 환경에서 버전 관리 시작하기
1. 기본 명령어 실행하기
1. 왜 CLI를 사용할까?
- 소스트리같은 GUI 환경은 자주 쓰는 기능을 편하게 쓸 수 있게 모아둔 것 → GUI 환경에서 할 수 없는 몇몇 고급 명령, 세세한 작업을 하려면 CLI
- 작업 속도가 더 빠름
- 리눅서 서버 같은 환경에서는 GUI 프로그램을 사용할 수 없는 경우도 있음
2. GUI와 CLI의 차이
- 화면을 모든 정보에 보여주는가
- 마우스를 사용하는가
- 명령을 능동적으로 입력하는가
3. CLI 시작 전 주의사항
- 에러 메시지를 꼼꼼히 읽어라
2. Git Bash로 기본 명령하기
1. Git Bash란?
- CLI 프로그램
- window 운영체제(OS)환경에서도 리눅스 커맨드를 사용할 수 있게 만드는 프로그램
2. 기본 용어 및 기본 동작
- 아래에서 기술 될 명령어 中 괄호의 의미는
<필수요인>
,[생략가능요인]
이므로 참고할 것 - 프롬프트prompt :
$
기호와 윗줄에 표시된 경로 등을 합친 것으로, cli에서 가장 기본적인 정보를 나타냄. git bash에서는사용자아이디@현재pc이름 현재폴더위치
이렇게 나타나는 것이 기본. 소스트리에서 터미널을 클릭하면 해당 git 작업 폴더로 기본 설정되고, 브랜치명이 추가로 표시 됨. - 현재 폴더 위치
~
: 사용자의 홈 폴더. 홈 폴더란c:\Users\사용자ID
폴더를 말함- 바탕화면 폴더는 임시 폴더에 가까운 느낌이고
c:\Users\사용자ID\Documents
폴더가 작업 폴더로 개발자들이 선호 함
- 바탕화면 폴더는 임시 폴더에 가까운 느낌이고
- git 용어 정리
- 워킹트리(= 워크트리, 워킹 디렉토리, 작업 디렉토리) : 커밋을 체크아웃하면 생성되는 파일과 디렉토리. 작업 폴더에서 [.git] 폴더를 뺀 나머지 부분.
- 로컬 저장소: [.git] 폴더. 커밋 정보는 이곳에 들어 있음.
- 원격 저장소: 깃헙
- 작업 폴더: 워킹트리 + 로컬저장소
- git 저장소: 엄밀히 말하면 로컬저장소. 넓은 의미로 작업 폴더.
3. git 로컬 저장소에서 작업하고 커밋 완료하기
- git 로컬 저장소 생성하기
- 리눅스 명령어로 프로젝트 폴더 생성
- 그 해당 폴더로 이동
$ git status
git 저장소가 아니라는 에러를 확인할 것! (※ 만약 git 저장소가 맞다고 뜬다면 상위 폴더 중 git 초기화 된 폴더가 있는 것이므로 확인!)$ git init
git 저장소 초기화 ☞ [[Zettelkasten/3 자기계발/360 배움/362 프로그래밍/362z 기타 프로그래밍 지식/Git & GitHub 다루기#^fa14cf|Git & GitHub 다루기#^fa14cf]]$ git config --범위옵션 <옵션명> [옵션새로운값]
옵션 설정하기 ☞ [[Zettelkasten/3 자기계발/360 배움/362 프로그래밍/362z 기타 프로그래밍 지식/Git & GitHub 다루기#^1ac90c|Git & GitHub 다루기#^1ac90c]]- 범위 옵션(우선순위 순)
- 지역옵션(
--local
) : 현재 git 저장소에서만 유효한 옵션(공용 PC, git을 잠깐 쓸 경우) - 전역옵션(
--global
) : 현재 사용자를 위한 옵션(일반적인 개인 PC에서 사용) - 시스템 환경 옵션(
--system
) : PC 전체 사용자를 위한 옵션(git이나 소스트리 설치시 몇 가지 지정되며, 직접 수정할 일은 별로 없음)
- 지역옵션(
- 옵션명
user.name
user.email
core.editor
: 리눅스 기본 에디터인 vim, nano로 설정되어 있다면 VS code로 바꾸는 것을 추천 (각자 편한 에디터로) ☞ git을 처음 설치할 때 디폴트 에디터로 설정하는 옵션이 있음
- 범위 옵션(우선순위 순)
- 워킹트리에 파일 생성하고 스테이징하기 & 언스테이징하기
echo "hello git" > file1.txt
☞ ""안의 메시지를 담은 파일 생성git status
☞ untracked file에 file1.txt가 표시되는 것을 확인하면 성공!git add file1.txt
git status
☞ changes to be committed에 file1.txt가 표시되면 성공!git reset [파일명] [파일명2] …
: 소스트리의 reset 명령과 같음. 옵션이 없으면 mixed reset으로 기본 설정. 이는 파일 내용은 그대로 두고 언스테이징만 하는 것. ☞ [[Zettelkasten/3 자기계발/360 배움/362 프로그래밍/362z 기타 프로그래밍 지식/Git & GitHub 다루기#^f72090|Git & GitHub 다루기#^f72090]]
ORgit rm --cached <파일명.txt> <파일명.txt> …
- 커밋하기 ☞ [[Zettelkasten/3 자기계발/360 배움/362 프로그래밍/362z 기타 프로그래밍 지식/Git & GitHub 다루기#^5584ed|Git & GitHub 다루기#^5584ed]]
git commit
- 기본 에디터로 설정된 VS code가 뜰 것
- 첫 줄에 제목, 한 줄 비우고, 세번째 줄에 자세한 커밋 내용 → 저장 후 닫기
- 수정 안하고 닫기하면 커밋도 자동 취소
- 좋은 커밋 메시지의 7가지 규칙
- 제목과 본문을 빈 줄로 분리
- 제목은 50자 이내
- 제목을 영어로 쓸 경우 첫 글자는 대문자
- 제목에 마침표 X
- 제목을 영어로 쓸 경우 동사원형으로 시작
- 본문을 72자로 줄바꿈
- 어떻게 보다 무엇과 왜를 설명
- 커밋 확인하기
git log
옵션을 조합하여 사용 가능git log --oneline --graph --all --decorate
: 깔끔하게 볼 수 있는 방법으로 추천함 (원기어때로 외운다)git log -n<숫자>
: 최신 몇 개만 확인git log --decorate
: 원래는--decorate=short
옵션을 의미하며, 간결히 표시하는 것git log --all
: all 옵션이 없으면 HEAD와 관계 없는 옵션은 보여주지 않음
4. 원격저장소에 푸쉬하기
- 깃헙에 원격저장소 생성 (※ 이때 readme.md 등 파일을 만들지 않고 빈 프로젝트로 만들기를 추천, 그렇지 않으면 커밋 충돌나서 강제 푸쉬해야 해서)
git remote add <원격저장소이름> <원격저장소주소>
→ 이 상태에서 바로 push만 하면 에러뜸! 왜냐면 브랜치 지정을 안 해줘서.git push -u <원격저장소이름> <브랜치명ex;master>
5. clone하기
- 클론은 원격저장소를 복사하는 것으로, 꼭 원격저장소를 복사할 필요는 없음! 때에 따라 로컬저장소를 클론하여 사용하기도 가능.
- 상위 폴더로 이동
git clone <원격저장소주소> [새로운폴더명]
3. 브랜치 다루기
1. 새로운 브랜치 만들어서 커밋한 후 마스터 브랜치로 빨리 감기fast-forward 병합하기
- 브랜치 만들고 체크아웃하기
git branch 브랜치이름
→git checkout 브랜치이름
- 위 두 명령을 동시에 ☞
git checkout -b 브랜치이름
- 새로 만든 브랜치에서 커밋 생성하기
- 새로 만든 브랜치를 마스터 브랜치에 통합하기
- 마스터 브랜치로 체크아웃
git merge <새브랜치>
2. 1에서 한 빨리감기 병합을 취소하고 재배치rebase로 빨리감기 병합하기
git reset --hard <이동할커밋체크섬>
reset --hard
명령은 다음 명령 세 가지를 한번에 수행하는 것임git checkout <커밋체크섬>
: 특정 커밋으로 돌아가겠다(Detached HEAD 상황)git branch -f master
: 그 커밋을 master 브랜치로 다시 명명하겠다git checkout master
: 마스터로 체크아웃 하겠다 ⇒ 리셋한 것과 같은 결과
- 마스터 브랜치로 체크아웃
git rebase <새로운브랜치>
3. 푸시, 브랜치 삭제
git push
git branch -d <새로운브랜치>
4. 태깅하여 배포하기
git tag -a -m <"간단한 메시지"> <태그이름> [브랜치나 체크섬]
git push <원격저장소별명> <태그명>
5. 3-way 병합하기
- 긴급한 버그 처리 시나리오
- 필요하다면 오류가 없는 버전으로 롤백(주로 태그가 있는 커밋)
- [master] 브랜치로부터 [hotfix] 브랜치 생성
- 빠르게 소스코드 수정, 테스트 완료
- [master] 브랜치로 병합(fast-forward) 및 배포
- 개발 중인 브랜치에도 병합
merge
명령을 사용하기 (병합 커밋이 생성되고, 동일 파일을 수정했다면 충돌 가능성 높음!)git checkout <개발중인브랜치>
git merge master
→Automatic merge failed
메시지가 뜬 경우 충돌한 것git status
→both modified: 충돌한파일
에 해당하는 파일을 수정할 것git merge --abort
: merge 과정 취소하기git add 충돌한파일
: 충돌난 파일을 다시 스테이징!git status
:All confilcts fixed but you are still merging.
- 커밋하기
rebase
명령을 사용하기 (트리가 깔끔해짐)git checkout <개발중인브랜치>
git rebase master
→Failed to merge in the changes
메시지가 뜨면 충돌한 것- 충돌 해결 후 다시 스테이징
git rebase --continue
(※ 병합 과정에서 마지막 단계에서git commit
명령을 사용하는 것과 다름!) → 충돌을 해결할 때마다 계속 입력- 마스터 브랜치로 체크아웃
- 개발중인 브랜치와 병합 → 빨리감기 병합이 됨
- 두 대의 PC가 동시에 작업해서 병합 커밋이 생성된 경우
- 한 PC에서 커밋 생성 + push
- 다른 PC에서 pull 하지 않고 커밋 생성 → pull
- 자동적으로 병합 커밋이 생김(※ pull은 fetch + merge이므로)
- 이때 병합 커밋을 제거하고 rebase를 통해 히스토리를 깔끔하게 만들 수 있음
git reset --hard <커밋체크섬>
git rebase origin/master
- 푸쉬하기
6. 임시 브랜치를 만들어 병합, 재배치 테스트하기
git branch <임시브랜치> <작업하려는브랜치>
git checkout 임시브랜치
- test 브랜치에서 자유롭게 작업
git branch -D test
: 임시 브랜치 삭제
4. Git의 원리 이해하기
1. 커밋과 브랜치의 원리
- 커밋은 델타(차이점)가 아니라 스냅샷
- 커밋할 때 변경사항을 저장하는 것이 아니라, 변경된 파일을 통째로 저장함
- SVN(SubVersion)과 같은 버전 관리 시스템은 변경사항만 저장 but Git은 변경된 전체 파일을 저장(변경되지 않은 파일은 이전 파일의 링크만 저장) → 오히려 SVN은 처음 파일까지 계산을 거슬러 올라가야 하는 반면, Git은 그러지 않아도 돼서 가볍고 빠름
- 커밋은 부모 커밋에 대한 정보를 담고 있고, 자식 커밋에 대한 정보는 X
- 그래서 최신 커밋에서 부모 커밋으로 화살표를 그려서 표현
- 병합을 통해 생성된 커밋은 부모 커밋이 두개 존재함.
- 브랜치란 하나의 커밋 객체를 가리키는 것
- 커밋하면 커밋 객체가 생김
- 커밋 객체에는 부모 커밋에 대한 참조 정보, 실제 커밋을 구성하는 파일 객체가 들어 있음
- 브랜치는 논리적으로는 어떤 커밋과 그 조상들을 묶어서 뜻하지만, 사실은 단순히 커밋 개체 하나를 가리킬 뿐임!
2. 브랜치를 사용하는 이유
- 새로운 기능 추가 : [master] 브랜치의 최신 커밋으로부터 브랜치를 생성해 기능을 개발. 코드 리뷰, 테스트까지 모두 이상 없을 때 [master] 브랜치로 병합
- 버그 수정 : 버그 발생 시 [master] 브랜치로부터 새로운 브랜치를 만들어서 작업. 이때 브랜치 이름은 ‘hotFix’, ‘bugFix’ 같은 이름을 사용함. 버그 수정이 끝나면 [master]로 병합. 이때 이후에 새로 개발한 내용을 다시 [master] 브랜치에 병합할 때, 버그 수정으로 인한 충돌이 생길 수 있기 때문에 주의할 것.
- 병합과 리베이스 테스트 : 임시 브랜치를 만들어 입문자에게 까다로운 병합, 리베이스 테스트를 함. 잘못 된 경우 브랜치를 그냥 삭제하면 됨.
- 이전 코드 개선 : 이미 기능 구현은 됐는데 로직이나 코드가 맘에 안들어서 개선하고 싶을 때, 새로 브랜치를 만들어 코드 개선하는 방법을 추천함.
- 특정 커밋으로 돌아가고 싶을 때 : 이미 저장 된 특정 커밋으로 돌아가고 싶을 때, hard reset이나 revert를 사용하는 것 외에도 할 수 있는 방법임. hard reset은 커밋이 없어질 수 있고, revert는 조금 사용이 까다로움. 이 경우 브랜치를 새로 만들어서 작업하고 이후 리베이스나 병합을 사용하는 방법이 있음.
4. Git의 4가지 파일 상태
- untracked : 한번도 커밋하지 않은 파일의 상태. 버전이 기록되지 않는 상태.
- staged : add 명령어를 통해 파일을 스테이지에 올림
- unmodified : staged된 파일을 커밋한 이후의 파일의 상태 → 이 상태로 다시 다른 수정을 할 수 있음
- modified : staged된 파일이 수정된 경우 → 다시 커밋할 수 있음 → 앞서 만든 커밋과 연결되어 있기에 Git은 어떤 것이 변경되었는지 계산할 수 있게 됨
3. Git의 add와 commit
- 간단히 이해하기
- add : 앞으로 버전을 추적할 놈들을 스테이지로 올리는 것 → “이 파일을 앞으로 추적하겠다”
- commit : 그 시점에 스테이지에 올라 와 있는 놈들의 상태를 저장
- 저수준 CLI 명령어를 통해 이해하기
- 스테이징
- index 파일
git hash-object 파일
을 통해 생성한 파일의 체크섬 확인- add한다
- .git 폴더에 index라는 파일이 생성됨 (※ index란 스테이지의 다른 이름! 즉 이 파일이 git의 스테이지.)
- 스테이지의 내용을 확인하면 방금 add한 파일의 체크섬 값이 들어있음.
- object 폴더
.git/objects
디렉토리 확인- 생성한 파일의 체크섬 아이디의 앞 두글자로 시작하는 폴더에 들어감
- 나머지 체크섬 값을 가진 파일이 생성됨!
- [objects] 폴더에 있는 파일은 git 객체임.
- 체크섬 명령어 이용
git cat-file -t 체크섬값
→ blob 객체라고 뜸- blob 객체란, binary large object의 줄임말.
git cat-file blob 체크섬값
→ 생성한 파일에 내가 작성한 내용을 보여줌!
- index 파일
git commit
으로 커밋하기- 커밋하기
git commit
으로 커밋 후,git status
에서working tree clean
이라는 문구를 볼 수 있음 → 이는 스테이지, 워킹트리, HEAD의 내용이 모두 동일하다는 뜻!git log
를 통해 방금 만든 커밋의 체크섬 아이디를 확인
- 스테이지 (= index 파일)
4.git ls-files --stage
로 스테이지를 확인하면, 커밋한 상태 워킹트리의 파일 체크섬 아이디가 올라와 있음 → 스테이지는 커밋해도 비워지지 않음 - object 폴더
- 방금 만든 커밋의 체크섬 아이디를 가진 commit 객체가 생성 됨 ☞ 이때, 내용이 같은 파일이어도 커밋의 객체는 항상 다름
- commit 객체의 내용에는 "tree 객체 아이디 + 커밋 메시지"로 구성됨
- commit 객체 외에, tree 객체가 생성됨!
- tree 객체의 내용에는 해당 커밋 당시의 스테이지에 올라온 파일의 정보가 들어있음
- 방금 만든 커밋의 체크섬 아이디를 가진 commit 객체가 생성 됨 ☞ 이때, 내용이 같은 파일이어도 커밋의 객체는 항상 다름
- 커밋하기
- 수동 커밋하기
- 파일 수정하기
- 파일을 수정하면, 파일의 체크섬 아이디가 변함
- 하지만 스테이지, HEAD 커밋에는 업데이트 되어있지 않음 → modified 상태로 인식
- 추가 커밋하기
- 변경된 파일을 add
- stage를 확인하면 수정된 파일의 체크섬 아이디가 올라감
- 수동으로 트리 만들기
git write-tree
로 트리 생성 ☞ 현재 스테이지의 상태를 tree 객체에 저장하는 것!- 생성된 트리 객체를 확인하면 방금 add 된 파일의 체크섬 아이디가 포함됨
- 트리로 커밋하기
echo "커밋 메시지" | git commit-tree 트리아이디 -p HEAD
→ 새로 만들어진 커밋 아이디가 출력 됨-p HEAD
: 부모 커밋이 HEAD
- 방금 만들어진 커밋 객체 내용을 확인하면, '우리가 만든 tree 값 + 부모 커밋 아이디 + 저자 + 커밋한 사람’의 내용이 포함됨
git log
를 확인하면 커밋이 로그에서 표현되지 않음 → HEAD 갱신이 필요함
- HEAD 갱신하기
- .git/HEAD파일 내용 확인 →
refs/heads/master(혹은 다른 브랜치이름)
라는 디렉토리를 포함함 - 해당 파일을 확인하면 특정 커밋 아이디를 담고 있음 ☞ 이것이 해당 브랜치가 가리키고 있는 커밋!
git update-ref refs/heads/master 커밋아이디
명령어를 통해 마스터 브랜치의 헤드 포인터 값을 업데이트!- 정상적으로
git log
에서 표현 됨
- .git/HEAD파일 내용 확인 →
- 파일 수정하기
- 중복 파일 관리하기
- git에서 파일은 blob으로 관리 됨
- blob은 파일의 제목, 생성 날짜와는 관계 없이 내용이 같을 경우, 같은 체크섬을 가짐!
- 따라서 동일한 파일이 100개가 있어도, 아이디는 한개로 관리 됨 → 빠르고 효율적
- 브랜치 작업하기
- 브랜치 생성하기
- 브랜치를 생성하면 .git/refs/heads 폴더에 해당 브랜치이름을 파일명으로 하는 파일이 생김
- 그 안에 해당 브랜치의 최신 커밋 체크섬값이 담겨 있음
- 브랜치 삭제하기
- 브랜치를 삭제하면 위에서 말한 그 파일이 삭제됨
- 브랜치 체크아웃
- .git/HEAD 파일의 내용에 체크아웃한 브랜치의 커밋 주소가 담겨 있음 (헤드 갱신)
- 워킹트리, 스테이지의 내용이 해당 커밋의 내용으로 변경함 (워킹트리 뿐만 아니라, 스테이지의 내용도)
- 수동 체크아웃
echo "ref: refs/heads/master" > .git/HEAD
: HEAD 파일의 내용을 직접 수정(master 브랜치로 체크아웃 하겠다)- 스테이지, 워킹트리는 아직 변하지 않음!
- 일일이 스테이지와 워킹트리 상태를 파일 수정을 통해 바꿔줌
ORgit reset --hard
를 통해 되돌림 : 커밋, 스테이지, 워킹트리의 내용이 모두 같아짐!
- 브랜치 생성하기
- 스테이징
5. 인증 기능 살펴보기
1. 인증 관련 기능 사용하기
- 윈도우 - 자격 증명 관리(credential)
git config [--local/global/system] credential.helper
옵션을 이용 → 자격 증명 관리를 어떤 방법으로 하는지 알려 줌- 일반적으로 윈도우에선
--system
옵션으로manager
라고 설정 됨 - 이는 윈도우 자격 증명 관리 프로그램으로 저장한다는 얘기
- 일반적으로 윈도우에선
- 윈도우 검색 → 자격 증명 관리자 → window 자격 증명 → 모든 github 아이디, pw, 소스트리 등 사이트 정보가 저장 됨
- 새로 로그인 창을 띄우기 위해서는 git: 으로 시작하는 관련된 기존 자격 증명을 모두 삭제 (소스트리의 인증 정보에서 삭제해도 됨)
git push
→ 로그인 창
- 리눅스 - cache 옵션 사용하기
- 보통 리눅스는 서버 os로 사용함
git config [--local/global/system] credential.helper
옵션으로 확인하면 아무 옵션도 설정되어 있지 않는 것이 일반적 → 매번 아이디와 패스워드를 물어 봄cache
,store
옵션을 지정함cache
옵션- 지정한 시간 만큼 사용자 아이디, pw를 저장함
git config credential.helper "cache --timeout=30"
: 30초간 저장git push
→ 최초 1회 아디, 비번 입력 → 30초 지나서 하면 다시 입력
store
옵션- 영구적으로 아디, 비번 저장
- 편리해서 서버에서 git과 관련된 스크립트를 작성할 때 많이 사용 but 사용자의 아이디와 pw가 홈 폴더의 .git-credentials 라는 파일에 저장 됨 → 아디 비번 노출이 꺼려지면 사용 X
git config credential.helper store
- 인증 초기화
git config --unset credential.helper
rm ~/.git-credentials
해당 파일 삭제
2. SSH 키 생성 및 사용하기
- SSH란?
- secure shell의 약자
- 클라우드, 리눅스 등 서버에 접속하기 위해 주로 사용
- https 방식은 로그인을 통해 사용자 인증을 하지만, ssh는 공개키+비밀키 방식을 이용함, 이둘은 자물쇠 + 열쇠 역할 (github 등 원격저장소에 공개키 저장, 내 컴에 비밀키 저장)
- 패스워드가 노출되지 않는 장점이 있어 종종 사용
- 비밀키가 노출 되면 제거 후 새로 만들어서 등록하면 됨.
- SSH키 생성
$ ssh-keygen
cd ~/.ssh/
비밀키가 저장된 폴더cat id_rsa.pub
공개키 확인 후 복사.id_rsa
는 비밀키
- github에 키 등록
- SSH and GPG keys 메뉴 → title, 공개키 복붙 (※ 참고로 GPG 키는 작업 서명 키)
- 저장소 클론
git clone git@github.com:사용자id/저장소명.git
- ! https 를 사용했던 기존 원격저장소 주소랑 다름 주의
6. git의 CLI 명령어 요약
1. 원격저장소 복사 & origin 확인
git clone <원격저장소주소> [디렉토리]
: origin을 해당 원격저장소 주소로 설정하고 저장소의 main 브랜치를 로컬 저장소의 해당 디렉토리로 복제함git clone --branch[줄여서-b] [태그/branch이름] [원격저장소주소]
: 특정 브랜치나 태그의 내용만 클론git remote -v
: 해당 로컬저장소와 연결되어 있는 원격저장소 목록 확인하기git remote remove 원격저장소별명
: 해당 원격저장소 삭제하기git remote rename <기존 이름> <변경할 이름>
: 해당 원격 저장소 이름 변경하기git remote add <원격저장소별명> <저장소주소>
: 원격저장소 추가하기git remote set-url origin <new-remote-URL>
: 원격저장소의 url 변경하기
2. 초기화, 커밋, 푸시, 풀 하기
- 초기화하기/추적하기/확인하기
git help <명령어>
해당 명령어의 도움말 표시git status
: git 저장소의 상태를 알려줌. git 워킹트리에서만 정상 작동. 워킹트리, 스테이지, HEAD 커밋 세 가지 저장 공간의 차이를 비교해서 보여줌git status -s
:-s
는 short의 약자로, 짧게 요약해서 보여달라는 옵션git branch -u <원격저장소이름/브랜치이름>
,git branch --set-upstream-to=origin/<원격저장소브랜치명> <로컬저장소브랜치명>
: 추적할 원격저장소의 브랜치를 설정함git config --list
:--list
옵션은 현 프로젝트의 모든 옵션을 살펴보겠다는 것git fetch [원격저장소별명] [브랜치이름]
: 해당 브랜치를 동기화. 옵션을 설정하지 않으면 전체 브랜치 동기화.
- 스테이징하기
git add 파일1 파일2 …
: 해당 파일만 addgit add .
: 모든 파일 addgit restore .
모든 파일 add 취소git reset HEAD [file]
: git add 취소. 파일명 입력하면 특정 파일만 add 취소.
- 커밋하기
git commit
git commit -a
: add 명령을 생략하고 바로 커밋. 새로 만든 파일은 untracked 상태이므로 커밋되지 않으므로 이 경우는 직접 addgit commit -m "커밋 메시지"
: 커밋 메시지를 적음
- 푸시하기
git push [-u] [원격저장소별명] [브랜치이름]
:-u
옵션은--set-upstream
의 약자로 브랜치의 원격저장소를 설정해주는 것으로, 한번 지정하면git push
만 해도 됨git push --force
,git push -f
: 강제 푸쉬(혼자만 사용하는 브랜치인 경우에만 할 것!)git push <원격저장소별명> <source 브랜치>:<dest 브랜치>
: 소스 브랜치를 원격의 해당 브랜치에 push (※ fast-forward 병합이나--force
옵션으로 강제 푸쉬만 가능하므로, dest 브랜치가 혼자만 쓰는 브랜치가 맞는지 확인!!! (fork, clone한 사람 없는지))git push <원격저장소별명> HEAD:branch2
: 지금HEAD
커밋을branch2
에 push
- 풀하기
git pull
:git fetch + git merge
명령어임!
- 스태시하기
git stash
: 변경 내용 임시저장하기git stash save "스태시메시지"
: 스태시 메시지와 함께 임시저장하기git stash list
내가 stash 했던 내용 보기git stash apply
가장 최근 stash 가져오기git stash apply stash@{인덱스}
: 특정 stash 가져오기git stash drop
: 가장 최근 stash 지우기git stash drop stash@{인덱스}
: 특정 stash 지우기git stash clear
: 한번에 stash 모두 지우기git stash pop
:apply
+drop
3. 브랜치 다루기
- 명령어
- 브랜치 목록 보기
git branch
: 로컬 저장소의 브랜치 목록 보기git branch -a
: 로컬, 원격 저장소의 모든 브랜치 목록 보기git branch -v
: 로컬 저장소의 브랜치 목록 불러오기. -v 옵션은 마지막 커밋도 같이 표시.*
가 붙은 것이 HEAD 브랜치.
- 브랜치 만들기
git branch [-f] <브랜치이름> [커밋체크섬]
: 새로운 브랜치를 만듦. 커밋체크섬 값을 주지 않으면 HEAD로부터 브랜치를 만듦. 이미 있는 브랜치를 다른 커밋으로 옮기고 싶을 때-f
옵션을 사용.git branch -r[v]
: 원격 저장소에 있는 브랜치를 보고 싶을 때.-v
옵션은 커밋 요약을 볼 수 있음.git checkout -b <브랜치이름> [커밋체크섬]
: 특정 커밋에서 브랜치를 새로 만들고 거길로 체크아웃까지 하는 명령. 간결해서 자주 사용.git checkout -t <원격저장소별명/브랜치이름>
: 원격저장소 브랜치의 이름 그대로 로컬 브랜치를 만들고 체크아웃.
- 브랜치 삭제
git branch -d <브랜치명>
: 특정 브랜치 삭제. head 브랜치나 병합이 되지 않은 브랜치는 삭제 못함.git branch -D <브랜치명>
: 브랜치를 강제 삭제. -d로 지울 수 없는 브랜치를 지우고 싶을 때. 조심!git push origin --delete <브랜치명>
: 원격저장소에 올라가 있는 브랜치를 삭제git remote prune origin
: 로컬 브랜치에서 삭제된 원격저장소의 브랜치 정리
- 브랜치로 이동하기
git checkout <브랜치이름>
: 특정 브랜치로 체크아웃 할 때 사용. 브랜치 이름 대신 커밋 체크섬을 쓸 수 있지만 브랜치 이름 쓰는 것을 강력 권장한다 함.git checkout <커밋체크섬>
: 이 경우 HEAD와 브랜치가 분리되는 Detached HEAD 상황이 됨. 여전히 커밋을 생성할 수 있지만 다른 브랜치로 체크아웃하는 순간 Detached HEAD의 커밋은 다 사라짐.git reflog
명령으로 복구할 수 있지만 권장하지 않는 작업 방법이라 함. 브랜치를 이용해 체크아웃 할 것!git checkout -
: 가장 최근 커밋체크섬으로 이동
- 브랜치 병합하기
git merge <대상브랜치>
: 현재 브랜치와 대상 브랜치를 병합할 때. 병합 커밋이 생기는 경우가 많음. (merge를 나한테 갖다 붙인다는 뜻으로 생각해보자.) 충돌이 나면add
후 다시commit
하기git merge --abort
: merge 과정 취소하기
- 브랜치 재배치하기
git rebase <대상브랜치>
: 내 브랜치 커밋을 대상 브랜치에 재배치. 재배치할 커밋이 없으면 아무 일도 일어나지 않음. 히스토리가 깔끔해지나 조심.git rebase --continue
: 충돌을 해결한 후 리베이스 계속 진행. 재배치 대상 커밋이 여러 개인 경우 여러번 충돌이 발생하므로, 충돌을 해결할 때마다 이 명령어를 계속 입력해야 함.
- 브랜치 목록 보기
- 체크섬 표현하기
HEAD~<숫자>
: 숫자를 지정하지 않으면 부모 커밋.2
는 조부모 커밋.n
은 n번째 위쪽 조상을 가리킴.HEAD^<숫자>
: 숫자를 지정하지 않으면 부모 커밋.2
는 두 번째 부모를 가리킴. (병합 커밋처럼 부모가 둘 이상일 때 사용)
4. 배포하기
git tag -a -m <"간단한 메시지"> <태그이름> [브랜치나 체크섬]
:-a
는 주석 있는 태그(annotated)를 생성하는 것. 브랜치나 체크섬을 생략하면 HEAD에 태그를 생성함.git push <원격저장소별명> <태그명>
: 원격 저장소에 태그 업로드(그냥git push
는 태그까지 업로드 안 해줌)
5. 커밋 수정, 리셋하기
- 직전의 커밋 수정하기
git add .
(빠뜨린 파일 있으면) →git commit --amend -m "New commit message"
→git push [--force]
((※조심) 이미 원격에 푸시된 상태인 경우만 강제 푸시 옵션을 달 것, 강제 푸시는 항상 혼자 쓰는 브랜치에만!)
- 이전 커밋, 여러 커밋 수정하기
git rebase -i HEAD~n
: 최신 커밋부터 n개의 커밋 보여줌pick
이란 단어를reword
등 다른 단어로 바꾼 후 저장, 종료- 각각 커밋을 수정하는 편집기가 뜸 → 수정 → 강제 푸시
6. 인증 관련
git config credential.helper "cache --timeout=<초 단위>"
: 30초간 사용자 아이디, pw를 저장git config --unset credential.helper
: 인증 초기화
7. 기타 옵션
git config --global core.quotepath off
: 터미널에서 한글 문자 깨져서 나올 때git config --global commit.template <템플릿.txt 디렉토리>
: 커밋 메시지 템플릿 등록하기git config --global core.autocrlf true
: (Windows 환경) 저장소에서 가져올 때 LF를 CRLF로 변경. 저장소로 보낼 때는 CRLF를 LF로 변경.git config --global core.autocrlf input
: (Mac, 리눅스, 유닉스 환경) 개행문자 LF만 사용하도록 함
8. 저수준 명령어(많이 사용X)
git hash-object <파일명>
일반 파일의 체크섬 확인git show <쳌섬>
해당 체크섬을 가진 객체의 내용을 표시git ls-files --stage
: 스테이지 파일의 내용을 표시..git/index
파일이 스테이지 파일임git cat-file -t 체크섬값
: 체크섬으로 해당 객체의 종류 알아봄git cat-file 객체종류 체크섬값
: 해당 객체의 내용 들어다보기
브랜치 전략 (Git Workflow)
-
★ 책에서 소개된 일반적인 브랜치 전략(Gitflow Workflow?)
- feat/기능이름: 각 개발자가 개발중인 브랜치로, 직접 커밋을 올림
- master :
feat/기능이름
브랜치에서 개발 완료된 코드가 합쳐진 브랜치로, 출시 전인 베타 버전, 직접 커밋을 하지 않고 병합을 통해서만 코드 업데이트 → “test.도메인.com” 에 배포됨 - latest : 실제 출시할 코드(대중에게 보여줄 완벽한 코드)를 올리는 브랜치로,
master
브랜치에서 주요 개발이 끝나면 출시 시점에latest
브랜치로 코드를 병합함 → “도메인.com” 으로 배포됨
-
Git Workflow 자세한 소개 및 비교 : Git Workflow | Atlassian Git Tutorial
- Feature Branch Workflow: 이 방법은 모든 새로운 기능을 위해 별도의 브랜치를 만드는 것. 개발자가 독립적으로 작업하고, 완료된 기능을 ‘master’ 브랜치에 병합
- Gitflow Workflow: 이 방법은 ‘develop’, ‘feature’, ‘release’, ‘hotfix’ 등 여러 종류의 브랜치를 사용.
- ‘main’ 브랜치에는 버전 태그와 함께 공식적인 배포 커밋을 담음. feature 브랜치는 직접적으로 main 브랜치에 병합되면 안 됨.
- ‘develop’ 브랜치에서 모든 최신 개발 진행
- ‘feature’ 브랜치에서 새로운 기능을 개발
- ‘release’ 브랜치는 새로운 버전의 배포 준비를 위해 사용
- ‘hotfix’ 브랜치는 긴급한 버그 수정을 위해 사용
- Forking Workflow: 이 방법은 개발자 각각이 중앙 저장소를 포크하여 자신의 저장소에서 작업하는 것. 개발자는 변경 사항을 자신의 저장소에 커밋하고, 완료되면 중앙 저장소에 풀 리퀘스트를 보냄.
- Trunk Based Development: 이 방법은 모든 개발자가 하나의 브랜치(‘trunk’ 또는 ‘master’)에서 작업하는 것을 의미. 짧은 생명주기를 가진 작은 브랜치들이 'trunk’에서 파생되어 작업이 완료되면 바로 병합
그 외 Git 사용 관련
.gitignore
파일 생성하기 ☞ gitignore.io - 자신의 프로젝트에 꼭 맞는 .gitignore 파일을 만드세요 (toptal.com).gitignore
먹히지 않을 때는 한번 삭제한 후 재커밋 ☞ https://kotlinworld.com/269
용어
- Git : 깃, 버전 관리 시스템
- GitHub : 깃허브, Git으로 관리하는 시스템을 올려둘 수 있는 사이트
- GUI : 그래픽 유저 인터페이스. 마우스로 클릭해서 쓰는 방식
- CLI : 커맨드 라인 인터페이스. 명령어를 하나씩 입력하는 방식
- Git Bash : CLI 방식으로 git을 사용할 수 있는 환경
- add : 하나의 버전을 만들기 위해 변경사항을 선택하는 과정
- 커밋commit : 버전 관리를 통해 생성된 파일, 혹은 그 행위(add한 변경사항을 하나로 묶어 버전으로 만든 것)
- 체크아웃한다 : checkout 명령어로 원하는 지점으로 파일을 되돌릴 수 있음 (like 타임머신)
- 로컬저장소 : Git으로 버전 관리하는 내 컴퓨터 안의 폴더를 의미
- 원격저장소 : GitHub에서 협업하는 공간(폴더)
- 레포지토리 : 원격저장소를 멋있게 부르는 말
- 푸시 : 로컬저장소의 커밋(버전 관리한 파일)을 원격저장소에 올리는 것
- 풀 : 원격저장소의 커밋을 로컬저장소에 내려받는 것
- 브랜치 : 특정 브랜치 이름을 가진 커밋을 가리킴.
- HEAD : 현재 작업중인 브랜치를 가리킴. 브랜치는 커밋을 가리키므로, 결국 HEAD는 해당 브랜치의 최근 커밋을 가리킴.
*
기호가 붙어있거나, 소스트리에서는 굵은 글씨로 표시되는 커밋 - gist : 저장소보다 작은 코드를 올리고 싶을 때 유용, 작은 코드 조각을 간편하게 올릴 수 있음
- 풀 리퀘스트
- 패치
- 포크fork
- 프롬프트
추가로 확인하면 좋을 자료
- 『Pro Git 2판』
- 『Git from the Bottom-up』, John Wigley.
'Git & GitHub' 카테고리의 다른 글
이미 추적 중인 파일 gitignore 적용 시키기 (0) | 2023.08.21 |
---|