Git은 분산형 버전 관리 도구이고 GitHub은 인터넷에 코드를 올릴 수 있도록 도와준다

working tree의 구성 working directory, staging area, (local directory).git directory 이렇게 3가지로 구성된다
working directory는 실제로 코드를 작성하고 편집하는 영역인데, Git으로 변경사항을 기록하기 전 단계이므로, 우리가 Git으로 기록할 파일과 그렇지 않을 파일을 구분한다
Stage area에서는 commit으로 넘어가기 전 단계로 추적할 파일을 선택한다
local directory 는 실제로 commit(기록)되는 건데 빈번히 사용될거임.
전체적인 흐름은 이런거같아. 소스코드를 작성했어. 워킹디렉토리에서 기록할거랑 기록하지 않을걸 구분하고, 스테이지 에리어에서 커밋 할 파일을 선택해. 커밋의 결과물은 영어랑 숫자가 조합된 해시값으로 기록된다. 커밋이 이뤄지지않으면 원격저장소로 들어가지도 못해. 원격 저장소에 업로드하기 전에 마지막 결과가 스냅샷이다. 특정 시점의 프로젝트의 특정 버전인데 사진 촬영하듯이 하니까 스냅샷이라 한다.
그럼 코드에 문제가 생겨서 특정 시점의 commit으로 돌아가고싶으면, 이때 기록한 hash값을 기억해서 해당 커밋으로 돌아가는 것이 가능해진다.
head는 현재 작업하고 있는 위치인데, 최신 커밋을 찍으면 최신커밋이 가리키는 위치가 head임
특정 브랜치의 최신 커밋과도 같은 말이다.
그럼 브랜치가 뭐냐?
하나의 프로젝트를 3명이서 개발한다고 하자. 그럼 로그인/장바구니/결제 기능을 만들어야겟지 그럼 개발범위를 구분하고 격리해줘야겟지. 이때 사용하는게 브랜치임. dev/stage/prod로 구분해서 사용하는데 추후 더 자세히 다룰 예정

Branch에서 서로 다른 브랜치에서 기능을 구현하면 하나로 합쳐야지? 이때 사용하는게 merge임. 이 코드를 합치는 과정에서 발생하는 여러 문제를 잘 추적해야함.
git add는 원격 저장소로 코드를 업로드하는 커밋 작업을 기록할 때까지 변경 사항을 모아놓기 위해 사용된다
stage ared에서 git이 추적할 수 있도록 기록하는게 add다!
그래서 commit으로 기록을 남기기 전까지 add를 아무리 치더라도 git 저장소의 변경 이력에는 아무 일도 없다.
해보니까 git init으로 일단 시작하는거고 add를 통해서 뭐 어떤 파일을 commit할지 걸러주는 작업을 하는거임, 근데 git add dummy.txt를하고나서 dummy.txt파일을 수정하고 git status를 찍어보면 붉은 글씨로 수정되었다고 하나가 추가되는게 생긴다 일종의 경고문. 그럼 다시 add 해줘야하는거같음
초록색으로 표기되는건 추적하겠다는거고 빨간건 안하겠다는거네! 수정함은 주의하라는거고
이걸로 stage area로 넘어가는 파일을 정하는거구나? 초록색은 stage area로 넘기겟다는거네
commit을 하게되면 터미널에서 해시코드도 출력된다 앞서 봣던 해시값으로 저장된다는게 이 말이엿다
vim
g는 처음으로 G는 끝으로 이동
맥북은 control v로 블럭선택가능 윈도우는 shift v
git 버전 돌리기 (reset/restore/revert)
왜 3가지나 되는건가
reset은 과거를 지우는 방식 - 특정 커밋 이후의 모든 기록을 삭제
restore 특정 파일단위로 되돌리는 방식이다
revert 되돌리지만 기록을 유지한다 - 과거 특정 커밋 변경 사항을 취소하고, 새 커밋을 생성한다(협업 환경에서 안전하지만,관리할 때 보기가 안좋긴함)
틀린거 보이면 펜으로 슥 그어버리고 다시쓰는 느낌임
reset
--soft는 커밋 상태만 되돌리는것
--mixed는 커밋 상태도 돌려놓고 add하기 전 단계로 돌리는 것
--hard는 상태도 다 돌리고, 파일도 바꿔버리는거임(남발주의)
restore
git add전에 가장 최신의 커밋 상태로 되돌리는 것
restore --staged
텍스트는 지워지지 않고, stage area로 올라갔던 것은 복구 시키는거임

revert
기존 커밋을 취소하고 이 기록을 보존하면서 새로운 커밋을 생성하는거임
commit이 주체이다!
그러니까 revert를 하게 되면, 기존 커밋이 잘못된걸 알려주고, 새로운 시작점에서 다시 시작하면 됨.
revert -n <해시>
취소하고싶은 커밋을 제거. 취소된 변경 사항을 다시 워킹 디렉토리에 복구함.
특정 버전의 커밋 가져오기
브랜치는 가지잖아? 사실 main도 브랜치의 일종임
브랜치를 쓰는 이유는 뭘까? 개발하는 환경과 테스트하는 환경을 분리하는거임
또 사용자들이 접속하는 환경도 나눠서 관리해야겠지?
-> 그럼 그 분리 시켜주는게 브랜치로 코드를 격리 시켜서 사용해야 하는 것이다
브랜치 생성
현재 브랜치는 git branch로 확인할 수 있어
git branch <이름>으로 새로운 브랜치를 만들 수 있어
브랜치를 생성할 때 어떤 브랜치를 기준으로 만드는 걸까?
생성하는 브랜치의 가장 최신 커밋을 기준으로 생성된다
브랜치 이동하기
git checkout <이름>으로 새로운 브랜치로 진행하는 것
git cherry-pick <해시값> :다른 브랜치에 있는 특정 커밋을 골라서 현재 브랜치에 적용하는 명령어
지금 우연히 브랜치 이름이랑 겹친거같은데? 맞음
근데 cherry-pick 사용하면 과거의 일을 가져와서 현재에 반영하는거니까 conflict가 발생할 수 있는 점을 유의하고, 특수 케이스에 사용하는 걸 인지하자
fork
다른 사람의 코드 공개저장소를 내 깃헙으로 찍어서 가져온다!
그럼 fork랑 clone은 같은거아니야?
fork는 다른 사람이 만든걸 내 계정으로 복제해오는거지 로컬 저장소로 가져오는건 아니야
근데 clone은 코드를 내 로컬 저장소로 가져오는거야. 근데 계정에 복제 해오는건 아니야
업스트림 다운스트림
내가 뭘 포크해왔다고 치면 포크한 사람의 레포지토리는 다운스트림이고 원래 오픈 소스 레포지토리가 업스트림이 된다. 그러니까 원본이 업스트림이 되는거다. 따라서 업 스트림에서 업데이트가 발생하면, 이를 pull해서 내 포크 레포지토리로 가져올 수 있다.
zip 다운로드 하면 안되는 이유
집 파일로 받는건 정적인거야 근데 git으로 클론한 저장소는 git pull로 업데이트가 가능해. 만약 업스트림에서 뭔가 수정이 발생한다면 pull로 바로 수정이 가능한거지.
cherry-pick으로 가져오는거랑, pull로 가져오는건 다르다
체리픽은 이전 브랜치 히스토리를 다 가져오는게 아니고 커밋 하나만 가져오기 때문에 작업 이력 조회가 어렵다
그래서, pull을 통해서 가져오면, 코드의 유지보수가 굉장해진다
issue가 하는일?
작업에 대한 계획을 세우거나 토론을하고 진행 경과를 추적하기 위해 사용된다
Wiki에서 하는거?
문서화가 주 목적임
브랜치 관리
브랜치 역할별 설명이 존재한다.(이거 튜터님한테 여쭤본 내용인데 강의에 나오네)
(참고:https://wikidocs.net/332863)
Dev,Stage,Prod / main,feature,hotfix 이런식으로 크게 두개로 나눠지는거같은데
Dev Stage Prod 브랜치 구성의 사용 목적

Dev 브랜치 - 새로운 기능 개발, 버그 수정을 포함한 모든 작업의 기반 브랜치
Stage 브랜치 - 배포 전 최종 테스트 환경 제공하며 통합 테스트와 품질 보증이 이뤄진다. dev 브랜치에서 충분히 검증된 코드를 이 브랜치로 병합해서 테스트
Prod 브랜치 - 실제 사용자가 접근하는 프로덕션 환경의 코드를 포함하는 브랜치. 최대한 안정적이고 배포 가능해야한다
RISKY - Staging 브랜치에서 검증되지 않은 코를 pord에 반영하면 위험하잖아 시스템 장애를 일으키거나 UX가 저하됨. 철저한 QA테스트가 필요한 이유다
SLOW - 변경사항이 많으면 당연히 테스트와 배포에 필요한 시간이 증가해서 오래걸리겠지
FAT RELEASE - staging에서 prod로 병합될 때 한 번에 많은 양의 코드반영되는 대규모 릴리스임. 배포 속도도 늦추고 문제 해결 및 롤백 과정도 복잡하게 만든다 -> 작은 릴리스(small release로 나눠서 점진적 배포하면 낫겟네)
main hotfix release feature

feature 브랜치는 새로운 기능을 개발하는 브랜치임
개발이 완료되면 develop 브랜치로 병합됨
release 브랜치는 stage 브랜치랑 비슷하다. develop브랜치에서 분기하며 모든 버그가 수정되고 테스트 통ㅎ과하면 master브랜치에 병합됨
hotfix 브랜치는 프로덕션에 발생한 긴급 버그 수정을 위한 브랜치이다
그러니까 master브랜치에서 분기되는거지.
x.x.x 버전 읽는 법
mjaor.minor.patch 순서로 구성되어있음
기능이 완전 새롭게 바뀌거나 API호환성이 깨지면 major를 변경
새로운 기능 추가가 있지만 호환성이 유지되고 새로운 API가 추가되어도 기존 API가 작동되는경우에 minor를 변경
버그 수정과 같은 작은 변경이 있을 경우patch변경
게임에서 패치내역 바꾸는거처럼 만드는 느낌이다
어떤 브랜치 전략이 오픈소스에서 어떻게 사용되는지 이제 깃헙을 보면 좀 이해가 되겠구나
브랜치 전략2
git flow / github flow/ trunked-based 의 장단점을 파악해보자
브랜치 구성의 전략도 배포주기나 브랜치 관리등으로 설명하기 어려운 것들이 많은데, 예제를 통해서 전문적으로 설명한 용어들을 기반으로 git 브랜치 관리 전략을 살펴보자

git flow :
우선 처음에 master(main)에서 있던 코드를 develop브랜치로 가져와서 여기서 신규코드를 추가해서 사용하다가 신기능이 필요하면 feature 브랜치를 만들어서 작업할 거임. 여기서 PR로 팀원들에게 리뷰받고 PR을 머지하는 방식으로 처리된다
develop에서 release로 넘어가는 과정을 보면 feature에서 기능이 잘 동작하는거같으면 develop브랜치로 합치기 시작하면 develop 브랜치에서 release 브랜치르 따서 배포를 준비한다 release에 반영되ㅏ면 테스트가 수행되고 뭔가 문제가 발생하면 다시 develop에서 작업을 수정하고 release 로 합치기도한다
release에서 충분한 테스트가 끝나면 master로 합쳐주고 버그수정이 필요하지면 마스터 브랜치에서 핫픽스 브랜치를 만들어서 수정!
각 브랜치에 따라 업데이트가 빈번히 발생하는데 이는 코드의 안정성을 극도로 중요하게 생각하기 때문이다
github flow:
배포해야될 브랜치 main, feature 두개만 운영해서 빠르게 배포하기 위한 전략이다

신규 기능이 필요하면 feature 브랜치로 만든다 master는 배포만 관리한다.
검증과정이 없기때문에 주의가 필요하다. 작은 규모의 프로젝트라면 브랜치가 그렇게 많을 필요도 없다.스타트업, 소규모 프로젝트에선 이러한 전략이 적합하다
Trunk-based Development(TBD):
조금 더 작게 기능 개발을 해서 트렁크에 합치는 느낌이다

신규 배포하기 전에는 별다른 브랜치가 존재하지 않는다. 배포 브랜치를 (trunk or master)로 칭하고 아래 부분에서 매우 소규모의 브랜치 생성과 커밋이 이뤄지고 있다
붉은 부분이 커밋하는 행위들이고, 릴리즈 되어 있는 버전들에 직접 커밋하지 말라고 경고하고 있다. 그러니까 각 릴리즈마다 고유 기능만 담당하고싶은거같음
조금 더 작게 개발해서 즉시 배포 브랜치에 합치기 때문에 깃헙 플로우 보다 배포 속도는 빠를것이다
코드리뷰하기도 용이하다.
다만 큰 기능을 개발해서 합치기 어렵고 의존적 기능 문제가 ㅍ발생함(다른 기능 만들었는데 main합쳐진 후 개발이 가능하니까)
내가 어떤 전략을 취할지 내가 속한 공동체가 어떤 전략을 사용하고 있는지 파악하는 것이 중요하다
변경 충돌 사항 해결하기
과제에서 다뤘던 내용인데 잘 공부해보자
Rebase?
커밋이 꼬인다? reset revert +rebase
rebase : 한 브랜치의 변경 이력을 다른 브랜치 위로 다시 쌓아서 합치는 명령
이미 작업한 내용을 최신 브랜치에 깔끔하게 재정렬하는 것
rebase를 사용하면, 최신 커밋을 반영할 수 있고 커밋 이력을 남기지 않아서 commit history가 깔끔해진다
아 rebase하면 임의의 브랜치가 하나 생긴다
commit --amend:
커밋 내용 빠져먹은거 수정하거나 파일추가하기
git rebase -i HEAD~N
마지막 N개의 커밋을 대상으로 rebase를 진행하겠다.(i는 interactive)
그럼 편집 파일이 뜨고 아래에 커맨드가 뜬다 원하는 커맨드로 변경후 사용
edit하면 git이 해당 커밋에 멈춘 상태가 된다 이제 커밋을 2개로 쪼개기 위해서 soft reset으로 가장 최근에 amend한걸 되돌려준다
그리고 파일에서 커밋 1,2를 추가하고 add commit해준다
그리고 새로운 라인에 커밋3를 적고 add commit해준다
그럼 커밋이 쪼개져서 올라간다
합치는것도 똑같다 git rebase -i HEAD~N 최신 커밋 N개를 대상으로 rebase
squash로 선택한 커밋이 이전 커밋과 합쳐질 수 있게 해준다
Release note
특정 버전에 브랜치, 코드르 묶어서 사용할 수 있게 제공
어떤 버전에 어ㅈ떤 기능이 추가 수정되었는지 알려준다
PR, issue 작성법도 템플릿을 정할 수 있다
릴리즈 노트를 포함한 문서화가 있어야
팀원간 이슈를 반복 논의하지 않게함
히스토리 투명하고 쉽게 추적가능
팀원이나 외부 협력자에게 빠르게 공유
명확한 커밋 메세지를 통해 의미를 전달
PR에서 주요 변경사항이나 의도를 설명하자
버전 태깅을 잘해 특정 릴리즈 시점을 잘 찾게하자
피처 버그 커스텀 템플릿같은거 만들 때 왜 커밋하는가?
내 생각엔 일단 세이브 포인트를 찍어둬서 돌아갈 수 있게하고, 커밋을 통해서 기록을 남기기 위함 아닐까?
tag와 브랜치의 차이는 무엇인가?
태그는 일정 버전을 고정해놓고 언제든 돌아갈 수 있는 스냅샨을 저장하는 역할인거지
브랜치는 새로운 기능을 개발하거나 버그 수정하는 동안 커밋이 쌓이고 이동하는 작업 흐름을 나타낸다
오픈소스
대가없이 코드를 가져와 쓸 수 있는데 분산형 프로덕션 모델이라고도 한다
오픈소스 코드의 장점은 기술의 발전에 빠르게 기여할 수 있다는 것