기간
2022/12/13 ~ 2022/12/15
수업
실시간 ZOOM 수업
git add
라는 명령어를 통해서 어떤 파일을 관리할지 지정하고, git commit
이라는 명령어를 통해서 현재 관리 중인 파일을 하나의 버전으로 저장한다. 그러면 commit을 통해서 저장된 버전 간에 자유롭게 이동이 가능해진다.
git은 아직 git add를 통해 관리되기 전의 파일들을 untracked file
이라고 하고, 관리되는 파일들을 tracked file
이라고 한다.
그런데 add를 한다고 바로 하나의 버전으로서 저장되는 것이 아니라 add 이후에 commit을 꼭 해야만 하나의 버전으로 저장이 된다. 그래서 수정사항이 관리는 되고 있지만 commit이 되기 전까지의 상태를 staged 상태
라고 한다.
git revert
는 현재까지의 commit 기록을 유지하면서 특정한 commit 이전으로 되돌리는 명령어로, 주의할 점은 되돌아가고 싶은 commit 버전을 적는 게 아니라 되돌리고 싶은 commit 버전을 적어야 한다.
commit version은
git log
로 볼 수 있다.
git revert [commit version]
git reset
은 특정 커밋으로 돌아가면서 그 커밋 이후의 커밋 기록을 삭제하는 명령어로, 마치 그 이후의 커밋이 없었던 것처럼 만들어는 것이다. 주의할 점은 revert와 반대로 되돌아가고 싶은 commit 버전을 적어야 한다.
git reset 옵션
--soft : 파일은 변경된 그대로 두고 기록만 삭제
--hard : 파일도 기록도 리셋
--mixed : soft와 비슷한데, 수정사항들을 commit 이전으로 되돌리는 것이 아니라 add 이전으로 되돌림
mkdir [new folderName]
rm -rf [delete folderName]
git init
git remove add [remoteName] [repo addr]
git add [fileName]
git commit -m"[commit message]"
git log --oneline
git revert [commit version]
git reset --soft/hard/mixed [commit version]
git push/pull [remoteName] [branchName]
git branch -m [branchName]
git clone [repo addr]
VsCode 단축키
ctrl + shift + ~ : terminal on
git merge
는 서로 다른 branch의 작업 내용을 하나의 branch로 통합하기 위한 명령어
conflict가 난 경우
수정하고 다시 add -> commit -> push
이 상태에서 main 브랜치에 develop 브랜치를 merge하면 Fast-forward라는 문구가 뜨고 log에 merge 되었다는 새로운 커밋이 생기지 않는다.
즉, 새로운 commit이 생기는 것이 아니라 그냥 main 브랜치에 develop 브랜치의 commit 기록이 병합되면서 아래와 같은 형태로 커밋 기록이 만들어지는 것을 fast-forward라고 한다.
줄기가 나눠진 형태로 커밋 기록을 남기고 싶다면 --no-ff
를 붙여 merge하면 된다.
Fast-forward의 개념이 중요한 이유
커밋 기록(히스토리)을 어떻게 관리할지 정할 때 사용되기 때문이다.
만약 하나의 줄기로 관리를 하고자 한다면 rebase와 함께 fast-forward 형태로 병합을 진행시키면 되고, 브랜치의 줄기를 남기고자 한다면 no-ff 형태로 병합을 진행시키면 된다.
하지만 보통은 no-ff 형태로 병합을 진행해서 브랜치 작업을 확인할 수 있도록 기록을 남기는 경우가 많다.
git rebase
는 특정 브랜치를 base(기준)로 놓고 커밋 이력을 정렬하겠다는 명령어
이런 형태로 브랜치가 나뉘어져 있을 때 main에서 rebase develop을 할 경우
이렇게 develop의 커밋 이력을 base로 해서 main의 커밋 이력이 정렬된다.
이어지는 main의 커밋 이력은 이전과 동일해보이지만 정확히는 이전과 다른 커밋 이력이다.
fast-forward 된 merge처럼 하나의 줄기로 커밋 이력이 정렬되는 것이다.
conflict가 난 경우
수정하고 add -> commit대신git rebase --continue
-> push
conflict 상황에서 rebase를 취소하고 싶다면git rebase --abort
rebase
는 정확히 말하면 병합을 위한 것이 아니라 커밋 히스토리를 정렬하기 위한 명령어다. 이미 병합된 브랜치가 있더라도 거기서 rebase를 하면 커밋 히스토리를 다시 정렬할 수 있다. 따라서 커밋 이력을 단순히 관리하고 싶을 때 사용한다.
merge
는 변경 이력을 모두 남기고 싶을 때 사용하는 명령어다. 실제로는 커밋 이력을 남기는 것이 굉장히 중요하기 때문에 rebase는 fork 시에 원본 프로젝트에 맞게 (동기화해서) 변경 이력을 관리하고자 하는 등의 특수한 상황에서만 사용하고 보통은 merge를 사용한다.
git config --global init.defaultBranch main
//git init하면 default branch main으로 설정
git switch -c [new branchName]
git switch [branchName]
//checkout보다 switch
git branch --list
git branch -d [delete branchName]
rm -rf .git
git merge [merge할 branchName]
//실무에선 command로 merge할 일은 없음
git log --oneline --graph --decorate
git merge [merge할 branchName] --no-ff
//fast-forward로 merge 안 하게
git rebase [rebase할 branchName]
git fetch --prune
//pr하고 삭제된 branch 정리
//로컬 브랜치도 -d로 삭제(띄어쓰기로 구분)
📑 Github default branch 변경하기 (master to main)
git branch -m master main
git push -u [remoteName] main
clone 의 경우
git branch -m master main
git fetch origin
git branch -u [remoteName]/main main
git remote set-head [remoteName] -a
📑 How do I delete a Git branch locally and remotely?
git push -d [remoteName] [branchName]
git branch -d [branchName]
Note: In most cases, [remoteName] will be origin.
hotfix
release
feature
는 필요할 때마다 브랜치를 만들고 merge가 되면 삭제
merge 순서
--no-ff
옵션 붙임
feature
->develop
->realease
->master
브랜치 | 설명 | 부모 브랜치 | 자손 브랜치 | PR받는 브랜치 | PR나가는 브랜치 |
---|---|---|---|---|---|
master | 소비자가 사용하는 제품이 존재하는 (배포될 코드가 있는) 브랜치 | - | hotfix develop | release | - |
hotfix | 배포된 서비스에 대한 긴급 버그 수정을 진행하는 브랜치 | master | - | - | develop master |
release | 배포 전에 제품을 테스트 (QA, 품질검사)하는 브랜치realease-* (release-1) 같은 형태로 이름을 지정해서 만듦 | develop | - | - | develop master |
develop | 개발 단계의 코드가 있는 (개발의 중심) 브랜치 | master | feature release | feature | - |
feature | 특정한 기능 (단위 기능)을 구현하는 브랜치feature/* (feature/기능명) 같은 형태로 이름을 지정해서 만듦 | develop | - | - | develop |
유용한 경우
- 큰 규모의 팀
- 퀄리티 보장이 중요한 프로덕트
- release된 프로덕트에 대한 관리 사이클이 긴 경우
브랜치 | 설명 | 부모 브랜치 | 자손 브랜치 | PR받는 브랜치 | PR나가는 브랜치 |
---|---|---|---|---|---|
master | 소비자가 사용하는 제품이 존재하는 (배포될 코드가 있는) 브랜치 자동배포 설정 | - | feature | feature | - |
feature | 특정한 기능 (단위 기능)을 구현하는 브랜치 git flow보다 더 구체적이고 명확하게 작업명 작성 | master | - | - | master |
유용한 경우
- 작은 규모의 팀
- release된 프로덕트에 대한 관리 사이클이 짧은 경우(업데이트 주기가 짧은 경우)
- 빠른 배포와 관리가 필요한 경우
github flow는 테스트를 위한 브랜치가 없고, 배포용 브랜치가 따로 없기 때문에 큰 규모의 서비스에는 적합하지 않다. 그래서 github flow의 단순함과 git flow의 체계적인 관리를 합쳐서 절충적으로 git을 활용하는 방식이 gitlab flow이다.
pre-production
브랜치가 테스트를 담당하고, master
브랜츠가 개발용 브랜츠로 역할한다. feature
브랜치는 다른 flow와 마찬가지로 merge되면 삭제된다.
브랜치 | 설명 | 부모 브랜치 | 자손 브랜치 | PR받는 브랜치 | PR나가는 브랜치 |
---|---|---|---|---|---|
production | 소비자가 사용하는 제품이 존재하는 (배포될 코드가 있는) 브랜치 | master | - | pre-production | - |
pre-production | 배포 전에 제품을 테스트 (QA, 품질검사)하는 브랜치 | master | - | master | production master |
master | 개발 단계의 코드가 있는 (개발의 중심) 브랜치 | - | feature | feature pre-production | pre-production |
feature | 특정한 기능 (단위 기능)을 구현하는 브랜치 github flow처럼 작업명 작성 | master | - | - | master |
유용한 경우
- 중간 규모의 팀
- 퀄리티 보장이 중요한 프로덕트
- 빠른 배포와 관리가 필요한 경우
스타트업 정도의 규모에선 gitlab flow
정도가 적절하다. 작은 규모의 팀에서는 git flow
는 오히려 비효율적으로 느껴질 수 있다.
하지만 gitlab flow
의 네이밍이 헷갈리기 때문에 배포용을 deploy
, 테스트용 test
, 개발용 main
, 기능개발용 feature
정도로 나눠 개발을 진행해도 좋을 것 같다.
git branch 전략은 팀마다 나름대로의 규칙과 방식을 정해서 진행하는 것이 바람직하고, 단순히 이미 만들어져있는 flow를 따라서 쓰는 것은 불편할 수 있다.
커밋 메시지
란 커밋을 할 때, 현재 commit이 정확히 무엇과 관련한 개발에 해당하고, 어떤 변경사항이 있는지 등을 작성하는 것을 말한다.
커밋 메시지를 잘 작성하면 커밋 이력만 보고도 현재까지 어떤 개발이 진행되었고 어떤 커밋에서 문제가 발생했는지를 알 수 있게 된다. 특히 규모가 큰 개발일 수록 커밋 메시지가 중요해진다.
메시지 규칙 예시 출처
1. 제목과 본문은 한 줄을 띄워서 작성한다.
2. 제목은 영문 기준 50자 이내로 작성한다.
3. 제목 첫글자는 무조건 대문자로 작성한다.
4. 제목 끝에는 마침표를 찍지 않는다.
5. 제목은 개조식(영어라면 명령문)으로 작성한다.
(Update code, Fix bug 등 만약 한글이라면 'abc 함수 수정')
6. 본문은 영문 기준 72자마자 줄바꿈을 한다.
7. 본문은 무엇을
왜
에 맞춰서 작성한다.
제목
은 간단하게 해당 커밋의 목적을 요약해서 작성한다.
Feat: 로그인 함수 추가
타입
- Feat: 새로운 기능 추가
- Fix: 버그 수정
- Env: 개발 환경 관련 설정
- Style: 코드 스타일 수정(세미콜론, 인덴트 등의 스타일적인 부분만)
- Refactor: 코드 리팩토링
- Design: CSS 등 디자인 추가/수정
- Comment: 주석 추가/수정
- Docs: 내부 문서 추가/수정
- Test: 테스트 추가/수정
- Chore: 빌드 관련 코드 수정
- Rename: 파일 및 폴더명 수정
- Remove: 파일 삭제
본문
은
로그인 기능 구현을 위해 로그인 요청을 보내는 axios 함수 작성
무엇을
왜
변경했는지 작성 (코드 자체를 상세히 적는 건 지양)꼬리말
은
Close: #123
Github 상의 이슈를 닫는 것과 관련해서 커밋 메시지를 통해서도 이슈를 닫을 수 있다.
1. 꼬리말은 어디까지나 선택사항
2. 유형: 이슈번호 형식으로 작성
3. 유형은 Close, Fix, Resolve 등을 활용(보통 Close는 일반 개발 이슈를 닫을 때, Fix는 버그 이슈를 닫을 때, Resolve는 문의나 요청사항에 대한 이슈를 닫을 때 사용)
4. 이슈 닫는 메시지는 본문에 작성하기도 한다.
본문과 꼬리말은 커밋메시지보다 PR 메시지에 작성하는 것이 효율적이다.
로컬 브랜치의 커밋 이력과 리모트 브랜치(github)의 커밋 이력이 충돌하는 경우 발생할 수 있다.
예를 들어 내가 push한 후에 누군가 github에 push를 하는 경우 생길 수 있다.
git pull
의 근본적인 원리는 github 쪽의 브랜츠와 로컬 브랜치를 merge 혹은 rebase를 통해 합치는 것으로 이루어진다. 그런데 해당 에러는 git이 pull을 할 때 정확히 merge, rebase 혹은 fast-forward merge 중에 무엇을 선택해야할지 모르겠으니 지정해달라고 하는 것이다.
(main 브랜치에 직접 push하지 않고 pr을 통해서만 merge를 하면 이런 에러가 발생할 일은 없을 것이다.)
해결법
git config pull.rebase false
같이 git 설정 자체를 바꾸기 보다는
git pull origin main --no-ff
같이 no fast forward merge 방식으로 pull하는 것을 권장
git pull [remoteName] [branchName] --no-ff
//git pull error시
📑 How do I undo 'git add' before commit?
git reset [file]
if this tried then
fatal: Failed to resolve 'HEAD' as a valid ref.
solution
git rm -r --cached [file]