~ 2024.4.24
분산 버전 관리 시스템 distributed version control system - DVCS (ex. GIT, Mecurial, Bazaar, Darcs)
작업의 변경점을 버전으로 기록한다. 기록된 버전의 시점에 해당하는 환경으로 돌아 갈 수 있다.
Git(깃)은 버전 관리 시스템이고, GitHub(깃허브)는 Git으로 관리하는 프로젝트를 올려둘 수 있는 사이트이다.
GIT : 로컬 버전 관리 시스템. 인터넷이 연결되지 않은 환경에서 사용되며, 다른개발자와의 작업 공유가 힘듬.
GIThub : 웹 기반 버전관리 시스템. 클라우드 서버에 소스 코드를 업로드하여 공유. 분산버전제어, 엑세스제어(권한), 소스코드관리, 버스추적, 기능요쳥 및 작업관리 기느을 제공함.
발표자료를 준비해본 사람이라면 한번쯤은 겪어봤을 최최최종.pdf 로 DVCS의 예시를 들 수 있다.
각 자료에는 저장된 당시의 내용이 기록되어있고, 사용자는 언제든지 해당 시점의 기록을 확인하고 사용할 수 있다. 작성자가 아닌 이용자도 확인하고 싶은 시점의 버전을 이용 할 수 있다. GIT도 이런 원리이다.

중앙 서버와 각각의 클라이언트는 모두 백업이력을 갖기 때문에 한곳에 문제가 생겨도 다른 저장소를 복제하여 작업을 시작 할 수 있다.
사용환경
설치 : https://git-scm.com/ (-> 설치를 시작하면 다양한 방법을 안내해주는데, 홈브루는 추후에 개발을 하면서 설치해야하는 여러가지 프로그램의 버전을 쉽게 관리 할 수 있게 도와줌으로 추천 )
설정
git config --global user.name "원하는 이름 또는 Github 닉네임"git config --global user.email "사용하는 이메일 주소 또는 Github 가입에 사용한 이메일"git config --list // 기입한 내용 확인git config --global --unset user.name // 전역 값 삭제git config user.name "원하는 이름 또는 Github 닉네임"git config user.email "사용하는 이메일 주소 또는 Github 가입에 사용한 이메일"git config --unset user.namegit config --global init.defaultBranch main변경하는 이유 : 일부 지역에서 master단어를 노예역사의 잔재로 생각하여 이슈 제기. 이후 git에서도 이것을 받아들여 main으로 사용하기를 권장함.작업할 폴더 생성. 터미널 or vscode or sourcetree등 원하는 것으로 명령.
git init : 로컬 저장소가 깃이 관리하는 저장소로 변경됨. 실행한 폴더의 숨김파일을 보면 .git파일이 생성된것을 확인 할 수 있음. 깃은 이런식으로 코드상태이력을 데이터베이스와 같은 시스템을 이용하지않고 자체적인 파일로 저장함. 해당 폴더를 삭제하면 기록도 모두 삭제됨
git status : 폴더 안에 새로운 파일을 생성 한 후 명령어를 입력하면 Untracked files 목록을 보여줌.
이것은 git의 stage로 untracked(해당 파일을 추적하지 않고 있음) / tracked(추적중) 두 가지의 상태가 있음. 위 파일은 새로 만들어서 추적하고 있지 않은 상태.

git add : 생성되어 추적불가능 하거나 수정된 파일을 스테이지에 올리는 명령어 git add 파일명 or .(모든파일)

다시 확인하면 스테이지에 올라와 있음.
.ingnore파일 : 그러나 공유하지 않아야하는 중요한 파일도 있음. 그럴경우 해당 파일에 파일명을 입력하면 git에서 관리하지 않음.
# 모든 .c 확장자 파일
*.c
# .c 확장자지만 무시하지 않을 파일(! 느낌표)
!not_ignore_this.c
# logs란 이름의 파일 또는 폴더와 그 내용들
logs
# logs란 이름의 폴더와 그 내용들
logs/
https://www.toptal.com/developers/gitignore <- 개발 환경에 따라 추천하는 .gitignore파일을 만들어주는 사이트
git commit -m "message" : 버전을 만들어주는 명령어. 각 시점을 스냅샷(사진을 찍는것)형태로 저장한다. 협업시 커밋은 남발하지 않는것을 권장한다. 의미없이 사용하지 않아야 한다. 이력이 복잡해지기 때문이다.
#commit을 만드는 명령어 : -m은 뒤에 commit 메시지를 입력할 수 있도록 해주는 옵션
git commit -m "커밋 메시지"
#변경된 모든사항을 바로 add하고 commit하는 명령어
git commit -am "커밋 메시지" // 오류가능성이 있어 비권장
커밋은 영구적으로 저장되면 커밋 당시의 내용은 변경 할 수 없지만 커밋메세지는 수정 할 수 있음. 각 커밋은 해시값을 가지고 있다. 이미지는 --oneline을 이용하여 짧지만, 실제로는 더 길다. 하지만 앞의 7자리만 사용해도 커밋은 구분 가능하다.
git log : 커밋된 이력을 확인 할 수 있음.
git log --oneline // 한줄로보기
git reset : 원하는 시점의 커밋으로 이동함. 해당 시점의 커밋을 기준으로 이후에 작성된 커밋이력을 삭제함.
git reset --hard 커밋해시 : 이전 커밋으로 되돌리고 이후 이력 모두 삭제git reset --soft 커밋해시 : 이전 커밋으로 되돌리고 이후 이력들은 삭제되지 않고 stage에 올라감git reset --mixed 커밋해시 : 이전 커밋으로 되돌리고 이후 이력들은 삭제되지 않고 untracked됨.git revert 커밋해시 : 원하는 시점의 커밋된 내용만 삭제한다. 해당 커밋도 사라지지않고, revert했다고 이력도 남음 (= 새로운커밋생성). 그때 한 작업 내용만 삭제되는 것이다.

git reflog : git은.. 모든것을 살피고있다..! 위 명령어들을 사용하여 삭제한 내역도 확인 할 수 있다. HEAD의 참조 이력을 로그 형태로 출력해준다.
이렇게 리셋, 리버트된 커밋 모두 확인할 수 있기 때문에 해당 커밋이전으로 이동하는 get reset --hard를 이용하면 수정하기 이전의 시점으로 돌아 갈 수 있다.
git의 꽃. git이 많은 점유율을 차지하고 있는 이유 중의 하나. 어떤 작업을 독립적으로 수행하기 위한 개념이다.
여러사람이 동일한 소스코드를 기반으로 다른 작업을 진행하면 서로 다른 버전의 코드가 만들어지고, 충돌이 생길 수 밖에 없다. 이것을 방지하면서도 여러 개발자가 동시에 작업할 수 있게 만들어 주는 기능이 branch이다.
기존의 main브랜치의 코드를 복제한 각자의 독립적인 영역에서 마음대로 소스코드를 변경하고, 원래의 버전과 비교하여 하나의 새로운 버전으로 병합Merge된다.

# 브랜치 생성
git branch [브랜치 명]
예) git branch oz
# 브랜치 목록 확인
git branch
# 생성한 Branch로 이동
git switch [브랜치 명]
예) git switch oz
# 브랜치 생성과 동시에 이동하기
git switch -c oz
# 브랜치 삭제하기
git branch -D (삭제할 브랜치명)
예) git branch -D oz
# 브랜치 이름 바꾸기
git branch -m (기본 브랜치명) (새 브랜치명)
예) git branch -m oz oz_new
branch가 많아질수록 HEAD의 중요성이 올라간다. HEAD란 해당 branch의 마지막 commit을 뜻한다.

위 이미지에서 main branch의 마지막 커밋은 맨 윗줄이고 / oz branch의 마지막 커밋은 first commit임을 확인 할 수 있다.
이렇게 현재 branch의 커밋이력이 어디인지를 확인하고, 현재 작업영역이 다른branch에 비해 얼마나 커밋이 차이가 나는지 그리고 차이가 있다면 그것이 무엇인지 파악해야한다.
merge와 rebase가 있다. 브랜치에서 commit 이력을 main의 커밋 이력과 합치는 기능은 동일하지만 병합된 브랜치의 이력을 남기는지(merge) 아니면 이력을 남기지 않고 합치는지(rebase) 목적에 따라 다르게 사용될 수 있다.
병합되는 branch의 커밋이력을 유지한채 main branch에 합치는 기능으로 협업시 주로 사용한다. main으로 이동 후 진행한다.
#원하는 branch로 이동하는 명령어
git switch [이동을 원하는 branch]
#main에 branch의 커밋 이력을 합칠때 사용하는 명령어
git merge [합치고 싶은 branch]
예)
git switch main
git merge oz
#log 명령어를 통해 합쳐진 이력 확인
git log
merge의 두가지 방식

fast-forword : main branch에서 새로운 branch가 분기해나가는 시점 = 두 브랜치가 공통으로 가지고 있는 commit을 base라고 한다. 여기서 이미지와 같이 새로운 branch는 새로운 커밋이 생겼지만, main branch는 그렇지 않기 때문에 merge해도 새로운 커밋이 생성되지 않고 병합된다. 마치 점프하듯 상대 브린채의 참조값으로 이동하는 모습을 본따서 fast-forward라고 부른다. git merge --ff [브랜치명], git merge --no-f [브랜치명] 명렁어를 사용하여 fast-forword으로 merge할지 정할 수 있다.

3-way-merge 방식 : 보통의 흔한 merge방식. 두 브랜치 중 어느 것도 base에 위치하지 않은 상태일 때 git merge 명령을 실행하면 새로운 commit이 생성된다. 기존커밋, 새로운브랜치의 새로운커밋, 메인브랜치의 새로운커밋의 3가지의 커밋을 기준으로 병합하기 때문에 3-way이다.
-git merge --squash (대상 브랜치) : 강력한 병합방식. commit이력과 merge된 브랜치 이력도 남기지 않고, 새로운 commit에 상대 브랜치의 내용을 모두 집어 넣는다. 자동 커밋이 되지 않아 별도의 커밋이 필요하다.

위 이미지와 같이 분기된 브랜치의 이력을

main 브랜치와 연결지어 하나의 이력으로 만들어줌. 기존 branch의 이력이 사라져 하나의 깨끗한 이력을 관리하기가 용이하지만 하나의 이력으로 만드는 과정에서 모든 커밋이 재정렬되어 해시값이 변경되고 충돌이 발생 할 수 있음.
#합치려는 branch로 이동하는 명령어
git switch [이동을 원하는 branch]
#합치려는 branch의 커밋 이력을 합칠때 사용하는 명령어
git rebase main
#main branch로 이동
git switch main
#main에서 main branch와 합치고자하는 branch를 merge 진행
git merge [합치고자하는 branch명]
예)git switch develop
git rebase main
git switch main
git merge develop
Rebase를 실행하면 branch 이력이 삭제되고 main에 커밋 이력들이 합쳐지는데 이때 main의 head는 main에서 커밋된 마지막 위치에 있기 때문 merge를 이용해 병합한 branch와 다시 한번 합치는 과정을 진행해야 한다.
병합을 하는 두개의 branch에서 같은 파일에 같은 값이 서로 다르게 수정되어 있으면 충돌이 발생한다.

변경사항을 결정 한 후에 반드시 저장!!!!! 하고 스테이지에 올린 후(git add) 커밋해준다. vim 편집기 화면이 나오는데 최상단에 커밋 이력이 자동으로 입력되어 있기 떄문에 wq로 저장하고 나오면 된다. 완료되면 머지되었다는 새로운 커밋이 생성된다.
git rebase --continue 충돌이 해결 될 때까지 반복하면 되고, 더이상 수정할 사항이 없다는 알림이 보이면 main으로 이동하여 merge한다.
내 GIT에 존재하던 자료, commit, branch를 저장하는 웹상의 클라우드 저장소.
생성시 README.md를 만들겠냐는 옵션은 비추천 (github에는 존재하지만 나의 로컬git에는 없어서 따로 만들어주는 번거로운 과정 필요해짐)
git remote add origin [원격 저장소 주소]
git push -u origin main // 저장소에 이력 저장
위 명렁어를 사용하여 로컬저장소와 연결해줘야 함.
git remote -v로 현재 내 git에 연결된 github repository를 화인 할 수 있음.git remote remove [origin과 같은 별칭 입력] 주소 삭제git push -u origin from-localgit fetch, git branch -a, git switch -t origin/from-remotegit push (원격 이름) --delete (원격의 브랜치명)깃허브 원격저장소에 있는 프로젝트를 로컬저장소로 가져오는 방법은 3가지가 있다.
git pullgit pull --rebase : rebase는 전에 공부한것처럼 이력을 마치 하나처럼 보이게 한다. 이 명령어 또한 이력을 하나로 맞추고 해시를 재정렬한다. 

git pull --no-rebase 아래는 git pull --rebase로 불러와서 병합했다. 소스트리로 그래프를 확인해보면 rebase는 하나의 이력으로 정리됐다.
사용해보기 위해서 원격저장소에서 직접 파일을 수정한 후 git fetch를 했다. 위 이미지는 git log origin을 해서 원격저장소의 커밋내역을 확인하고 아래이미지는 git log해서 로컬저장소의 커밋내역을 확인했다. 차이가있다.(그냥 log origin해서는 안된다 패치해야 차이가 생긴다 당연한가)
확인하고 나면 pull 하면 된다. (결국 pull이구먼 뭔가 다른줄알았다)
무분별한 Branch 생성으로 협무의 효율이 떨어지지 않도록 협업을 위한 전략이 많이 존재한다.

커밋 이력의 특정 시점을 키워드로 저장하여 버전을 붙이고자 할 때 사용한다.
https://semver.org/
vM.M.P (예. V2.0.0)
Major version : API 변경이 필요할 정도의 변화
Miner version : 기능 추가 정도의 변화
Patch version : 버그 수정 정도의 변화
| 태그종류 | 설명 |
|---|---|
| lightweight | 특정 커밋을 가리키는 용도 |
| annotated | 작성자 정보와 날짜, 메세지, GPG서명 포함 가능 |
사용방법
git tag v2.0.0 : lightweight. 마지막 커밋에 태그를 달아줌
git tag : 현존하는 태그 확인
git show v2.0.0 : 원하는 태그의 내용 확인
git tag -d v2.0.0 : 태그 삭제
git tag -a v2.0.0 : annotated 방식으로 태그 추가. 입력하면 메세지 입력창 뜸
git tag (태그명) (커밋 해시) -m (메시지) : 원하는 커밋에 태그 달기

숨겨져있는 .git폴더를 보면 많은 sample이 있음. sample을 때면 동작함. Git상의 이벤트마다 자동으로 실행될 스크립트를 지정할 수 있음 (푸시 혹은 커밋될 때마다 이모지추가 or 테스트코드 자동실행 후 검증 or gitAction과같은 CI/CD)

brew install gitmojigitmoji -i


git프로젝트에 다른 git프로젝트를 하위 디렉토리에 포함시키는 방법.
상위 레포지토리를 슈퍼 프로젝트(superproject), 하위 레포지토리를 서브 모듈(submodule)이라고 부른다. (혹은 부모 저장소, 자식 저장소라고 부르기도 한다.)
하나의 저장소에 여러개의 프로젝트를 관리하며 각 프로젝트는 별도의 저장소로 유지됨. 여러 프로젝트에서 사용되는 공통 모듈일 때 유용하다.(라이브러리 등)
git submodule add (submodule의 GitHub 레포지토리 주소) (하위폴더명, 없을 시 생략)submodule폴더와 .gitmodules 파일이 생성됨. -> commit
같은 프로젝트를 관리하는 데 사용하는 Github 그룹 계정, 개인 레파지토리에서 작업하는 것 보다 효율적임.
권한관리, 이슈 및 pull Request관리, 프로젝트 관리, 보안 및 액세스 제어 가능
생성 후 팀원 초대
repository 생성
이슈 템플릿 생성 가능
프로젝트 관리 템플릿 가능

이미지에서는 식사추천을 하고있지만!
저런식으로 각각의 이슈를 만들어서 해당 이슈를 누가 작업할지, 무엇을 어떻게 작업할지를 정할 수 있고 팀장에게 pull request를 신청하고 통과되어 merge되면 done으로 자동으로 이동됨.
이런식으로 라벨을 붙일 수도 있고, 작업한 내용이 남으며 서로 코멘트도 남길 수 있음.
pull request : 여기서 Pull Request란 '코드를 수정했는데 당신도 코드를 수정했다면 제 수정한 내용도 적용시켜 주세요'라는 의미다. 병합하기 전에 팀원 or 리더가 코드를 확인하는 과정으로 이후 merge가 진행된다. 원본 저장소의 내용을 fork한 후 내가 작업한 내용을 원본저장소에 적용하길 원할 때 요청한다.
Git&GitHub를 연습해볼 수 있는 사이트