많은 사람들과 협업할 때 하나의 브랜치에서 모두가 작업하는 방식은 적절하지 않다고 생각됩니다.
작업이 유의미하게 분리되고 서로의 작업을 침범하지 않으려면 적절하게 브랜치를 분기해야 하고 이때 어떤 방식으로 브랜치를 만들어 갈지 고민하게 됩니다.
또한 커밋이라 하면 유의미한 변화가 이루어진 하나의 작업 단위라고 합니다. 이때 commit-history는 작업일지와 같은데 어떤 방식으로 일지를 남길지 고민하게 됩니다.
정해진 규칙대로 브랜치를 분기하고 commit-message를 작성하게 되면 아래와 같은 이점을 얻을 수 있습니다.
Git 컨벤션을 따라야하는 이유
- 주관적인 스타일에서 벗어나 통일된 스타일을 추구
- 올바른 branch name 을 통한 workflow 유지와 해당 task 추적을 용이하게 함
- 새로운 팀원이 들어왔을 때 생길 수 있는 Commit의 혼란 방지
- 커밋 히스토리를 깔끔하게 유지하여, 변경 내역을 추적하기 용이함
그렇다면 어떠한 방식으로 브랜치를 만들고 commit-message를 작성하는 것이 좋은지 알아보도록 하겠습니다.
Workflow
브랜치를 관리하는 전략을 workflow라고 합니다.
대표적인 workflow의 종류로는 Gitflow
, Github flow
, Gitlab flow
가 존재합니다.
그중 제가 설명드릴 전략은 Gitflow입니다.
Gitflow
gitflow에서는 브랜치의 종류를 master
develop
release
hotfix
feature
5개로 구분하여 사용합니다.
Master
- master 브랜치는 절대 직접적으로 수정하지 않습니다.
- Production에서 사용 중인 브랜치입니다. 작업내용의 추가는 release 또는 hotfix를 통해서만 이루어집니다.
- 태그를 통해서 versioning을 진행할 수 있으며, merge가 이루어질 때마다 version을 올려줍니다.
Develop
- develop 브랜치는 절대 직접적으로 수정하지 않습니다.
- Producetion의 다음 버전을 개발하기 위한 브랜치입니다.
- 개발의 편의성을 위해 develop 브랜치를 사용하는 테스트 서버를 만드는 것이 좋습니다.
- 새로운 기능(feature)을 개발하기 위해서는 반드시 develop으로부터 분기해야 합니다. 또한 완성된 기능은 develop으로 merge 됩니다.
Release
- QA(quality assurance)가 진행되는 branch입니다.
- 배포가 예정되어 있을 때 develop을 분기해서 만들어지며 develop의 작업내용을 테스트하여 master로 갈 수 있는지 확인합니다.
- 수정사항은 추가 작업을 하고, 이상이 없다면 master로 merge 한 이후에 branch를 삭제합니다.
Hotfix
- Production에 버그가 발생했을 때, 버그를 수정하기 위해서 master에서 분기되는 브랜치입니다.
- master에서 분기 후, 버그 수정을 완료하면 master로 merge 합니다. 팀에서 정해진 규칙에 따라 version을 올려줄 수도 있습니다.
- 작업이 완료된 브랜치는 삭제합니다.
Feature
- 기능을 개발하기 위한 브랜치입니다.
- develop에서 분기한 후 작업이 완료되면 develop으로 merge 합니다.
- 하나의 feature에서는 하나의 기능만 완성하는 것을 권장합니다.
- 여러 feature가 develop에 모여서 적절한 시점이 됐을 때 배포를 계획합니다.
추천 사항
기본적으로는 feature
에서는 하나의 기능이 나옵니다. (feature/<feature-name>
)
단, 하나의 기능에 여러 가지 기능이 묶여있거나, 코드 작업의 양이 많을 것으로 예상될 때 하나의 feature로부터
여러 개의 sub-feature
를 만드는 것을 추천드립니다
→ 코드 리뷰를 작은 단위로 해서 코드 퀄리티를 유지하기 위함입니다.
feature/<main-feautre>
→feature/<main-feature>-<sub-feature>
feature/<main-feature>
브랜치에 여러 sub-feature들이 모여서 하나의 기능을 완성하게 됩니다.
이제 브랜치를 만드는 방법은 해결했습니다.
다음으로는 좋은 commit-message는 무엇인지 그리고 왜 commit-history를 이쁘게 만들어야 하는지 알아보도록 하겠습니다.
Commit message
Why?
Commit Message는 하나의 의미 있는 변경사항으로서 우리가 작성한 코드의 의미를 이해하는 단서가 되기도 하고, 프로젝트 개발의 흐름과 방향을 가늠해볼 수 있게 하기도 합니다.
즉 commit-message는 팀원들의 개발 log로써 남게 됩니다.
이러한 용도를 고려해 볼 때 commit-message는 큰 흐름에서 보았을 때 commit의 내용을 쉽게 파악할 수 있도록 간명해야 하고, 작성한 코드의 의미를 잘 설명해 주어야 한다는 것을 짐작해볼 수 있습니다.
기본적으로 좋은 commit-message는 다음과 같은 규칙을 갖는 것이 좋습니다.
- 제목과 본문을 한 줄 띄워 분리하기
- 제목은 영문 기준 50자 이내로
- 제목 첫 글자를 대문자로
- 제목 끝에. 금지
- 제목은
명령조
로 - Github - 제목(이나 본문)에 이슈 번호 붙이기
- 본문은 영문 기준 72자마다 줄 바꾸기
- 본문은
어떻게
보다무엇을
,왜
에 맞춰 작성하기
위 규칙들이 작성하는 내용에 관한 것들이었다면 아래 내용은 어떤 형식을 갖출 것인지에 대한 내용입니다.
저는 commit-message를 작성하기 위해 Conventional Commits가이드를 따르도록 했습니다.
Conventional Commits
conventaionl commits은 다음과 같은 형식을 갖습니다.
# conventional commits 의 기본 형식
<type>(<optional scope>): <subject>
<BLANK LINE>
<optional body>
<BLANK LINE>
<optional footer>
그중 타입에 대해서 자세하게 알아보도록 하겠습니다.
Type
- fix : 버그 수정에 관한 내용입니다.
- feat : 새로운 기능 추가입니다.
- docs : 문서 수정을 할 때 사용하며 오타 수정 등이 해당합니다 *. md 파일에 자주 사용합니다.
- style : 코드 포맷팅, 세미콜론 누락 등 코드 변경이 없는 경우 사용합니다.
- refactor : 버그와 기능 추가 아닌 코드 수정으로 변수의 이름 변경 등 코드 리팩터링에 사용됩니다. (기능 추가나 버그가 아닌 소스코드 변경에 사용)
- perf : 성능을 높이기 위한 코드 수정에 사용합니다.
- test : 테스트 코드, 리팩터링 테스트 코드 추가에 사용합니다.
- build: 빌드 업무 수정, 패키지 매니저 수정 등 개발 환경 변화에 사용합니다.
- ci : CI 설정과 script 관련 내용에 사용합니다.
- chore : 그 외 자잘한 수정으로 package update 반영 등에 사용합니다. 다른 브랜치를 Merge Pull 할 때도 사용됩니다. (소스코드를 직접 건들지 않는 수정이라고 생각하면 될 거 같습니다.)
Example
conventional-changelog-metahub
Commit History
Commit들이 모여서 시간 순으로 정렬된 것을 Commit History라고 합니다.
나중에 보니 불필요하거나, 앞선 커밋과 내용이 겹친 거나, 사소해서 유의미한 커밋이 아닌 것 같은 경우가 생기기 때문에 Commit History를 관리하는 습관을 가져야 합니다
Commit 메시지 정리하기 / 되돌리기
만약 가장 최근의 commit에 합치고 싶다면 git commit --amned를
이용하는 게 좋습니다
그 외의 경우 다음과 같은 방법이 있습니다
Reset
- 본인의 작업을 누군가 pull 할 일이 없을 경우 사용합니다
git reset <옵션> <돌아가고 싶은 커밋>
--hard
돌아가려는 이력 이후의 모든 내용을 지워 버리기 때문에 주의해서 사용해야 합니다. (없어진 커밋 내용을 복구 불가)--soft
돌아가려 했던 이력으로 되돌아 가지만, 내용이 staging 되어 남습니다.--mixed
기본값입니다. 변경된 내용이 남아있지만 staging 되어있지 않습니다.git reset HEAD~6
현재로부터 6개 전으로 돌아갈 수 있습니다.git push -f
를 통해 기존의 commit을 지우고 push 할 수 있습니다. 해당 기능은 혼자 작업 중인 branch에서만 사용하셔야 합니다.
Revert
- 이미 push 되어 있는 commit의 print와 log 등을 지울 때 사용합니다.
- 과거 커밋 내용을 수정후 새로운 커밋을 생성합니다.
git revert <되돌릴 커밋>
또는git revert <커밋>.. <커밋>
범위를 지정할 수 있습니다Revert: "<되돌린 커밋의 메시지>"
를 commit message로 작성합니다 Ex(Revert: "first commit")
Reference
Commit History를 효과적으로 관리하기 위한 규약: Conventional Commits
[초보용] Git 되돌리기( Reset, Revert )