Github로 협업을 한다는 것
Git의 일반적인 사용 흐름
핵심 개념 정리
- 핵심 구조와 파일의 상태 변화
- 커밋
작업 내용의 '스냅샷'
커밋하면 이력이 남아서 문제가 발생했을 때 이전 상태로 쉽게 되돌릴 수 있음
Git에서 관리하는 가장 작은 단위의 버전
- 커밋 vs. 푸시
커밋: 커밋은 로컬 저장소에 변경 내역을 저장하는 동작
푸시: 이 변경 내역을 원격 저장소에 업로드하는 동작
- 브랜치
독립적으로 작업을 진행하고 그 결과를 저장할 수 있는 개별적인 흐름
서로 다른 작업을 별도로 진행하고 나중에 하나의 코드베이스로 병합할 수 있음
여러 개발자가 동시에 다양한 작업을 진행할 때 매우 유용
일반적인 Git의 작업 흐름
git pull
먼저 원격 저장소에서 최신 코드를 받아옴
이를 통해 현재 로컬 코드가 최신 상태인지 확인하고, 다른 사람이 진행한 작업을 로컬 리포지토리에 포함시킴
git checkout -b add_profile_page
새로운 기능을 위한 브랜치를 생성
이 브랜치는 "사용자 프로필 페이지"를 추가하는 작업을 포함하며, 브랜치 이름에 이 내용을 반영하는 것이 좋음
git add -A
새로운 프로필 페이지에 필요한 모든 파일과 변경 사항을 staging area에 추가
이는 새로운 HTML, CSS, JavaScript 파일 등이 될 수 있음
git commit -m "feat: add user profile page"
staging area에 있는 변경사항을 커밋하여, 작업 내용에 대한 스냅샷을 생성
git push
커밋한 변경 사항을 원격 저장소에 푸시
이를 통해 다른 팀원들이 이 변경 사항을 볼 수 있게 됨
GitHub 훑어보기
- 팀을 만들기 위한 기능: Organization
- Issues: 버그 추적과 프로젝트 관련 토론을 위한 중요한 기능
- Pull Requests: 다른 사용자들에게 자신이 작업한 코드 변경 사항을 검토하고 병합해달라고 요청하는 기능
- Code Reviews: Pull Requests를 통해 다른 사람들이 작업한 코드를 검토하고 피드백을 주고받을 수 있음
Pull Request
Pull Request(PR)란?
- 다른 GitHub 사용자들에게 자신의 작업한 내용을 검토하고 머지해 달라고 요청하는 GitHub의 기능
- 특정 시간에 맞추지 않아도 되고, 서로의 의견을 자유롭게 교환할 수 있으며, 더 효율적이고 품질 높은 코드를 작성할 수 있음
과정
git pull
→ 브랜치 생성 (git checkout -b
) → 변경 사항 커밋 (git add
& git commit
) → git push
→ PR 생성
Pull Request의 상태
- Open
아직 검토가 완료되지 않았거나, 추가적인 작업이 필요한 상태
더 많은 커밋을 추가하거나, 토론을 진행하며 수정을 요청할 수 있음
- Merged
소스 코드의 기본 브랜치로 병합된 상태
해당 PR의 변경 사항이 승인되었고, 코드에 통합되었다는 것을 의미함
PR이 병합된 후에는 Closed 상태로 표시되며, 이후 추가적인 변경이나 커밋을 추가할 수 없음
- Closed
거부되었거나, 더 이상 유효하지 않은 PR
병합되지 않았지만 더 이상 필요하지 않거나 다른 이유로 인해 종료된 상태
Closed 상태로 전환된 후에도 브랜치가 존재한다면 다시 Open 상태로 되돌릴 수 있음
PR Merge
두 개의 브랜치를 머지하는 3가지의 방법이 있음
Merge Commit을 만들며 합치기
두 브랜치의 변경 사항을 모두 유지하면서 병합
각 브랜치의 변경 사항이 과거의 커밋으로 보존되고, 새로운 커밋이 추가되어 최종 병합
- 장점
브랜치의 히스토리를 모두 유지하면서 변경 사항을 병합할 수 있음
커밋 아이디가 바뀌는 경우가 없기 때문에 다음에 다룰 squash와 rebase 방식에 비해서 비교적 사용이 쉬움
- 단점
커밋 히스토리가 복잡해질 수 있음
팀이 커지면 커질수록 이 복잡성은 빠르게 증가함
Squash and Merge
랜치에서의 모든 변경 사항을 하나의 커밋으로 압축하여 병합하는 방식
각각의 커밋에서 발생한 모든 변경 사항을 병합 후에 하나의 새로운 커밋을 생성
- 장점
커밋 히스토리를 간단하게 유지할 수 있음
커밋 하나하나가 완성된 기능을 의미하게 됨
- 단점
작업의 상세한 이력을 잃게 됨
기존의 작업 커밋의 아이디들이 하나로 합쳐지며 사라지고 새로운 커밋 아이디가 생성되기 때문에 여러명이서 해당 브랜치를 기반으로 작업을 수행하고 있었다면 병합이 이뤄지는 경우 복잡한 문제를 야기할 수 있음
(모든 커밋 내역이 날아가는 것은 아닌데 Git 자체가 아닌 GitHub에는 해당 커밋 기록들이 모두 남아있기 때문에 Pull Request를 검색해서 해당 작업의 커밋 히스토리를 확인 할 수 있음)
Rebase and Merge
현재 브랜치를 target 브랜치에 재위치(rebase)시킨 후 병합하는 방식
target 브랜치의 커밋 위로 현재 브랜치의 모든 커밋을 옮겨 놓는 것과 같음
- 장점
깨끗하고 선형적인 커밋 히스토리를 만들어서 히스토리 파악 및 코드의 변화 이해가 더욱 쉬워질 수 있음
- 단점
관련된 커밋의 ID들이 모두 바뀌게 되어 혼란을 초래할 수 있음
PR별로 다른 기능으로 나뉘어 있던 작업 이력이 하나의 선형적인 히스토리로 합쳐서 특정 기능이 어디서부터 어디까지의 커밋으로 구현되었는지 알기 어려워짐
Fork해서 PR 만들기
Fork의 개념
- Git의 기능이 아니라 Git을 호스팅 하는 서비스인 GityHub나 GitLab과 같은 서비스에서 제공하는 기능
- Fork는 이미 존재하는 원격 Git repository를 사용자의 계정으로 복사하는 기능
Fork 된 repository는 기존 repositry와 완전히 분리되어 있으므로 사용자는 자신의 repository에서 자유롭게 변경 사항을 반영할 수 있음
- 작업이 끝난 후에는 Pull Request 기능으로 원본 repository에 기여할 수도 있음
왜 굳이 Fork로 PR을 만들어요?
- 브랜치를 사용한 방식은 원본 저장소에 직접 접근하여 작업하고, 변경 사항을 PR로 제안하는 방식
- 오픈소스는 다양한 규모의 팀, 커뮤니티 및 개인들이 참여하는 매우 큰 규모의 프로젝트임 따라서
- 코드를 수정할 수 있는 권한 관리도 필요
- 단일 브랜치만으로는 작업이 충분하지 않을 때가 많음
- Fork를 사용한 방식은 Fork 된 저장소에서 작업을 진행하고, 원본 저장소의 소유자에게 PR을 제안하는 방식
- 다수의 개발자가 각자의 저장소에서 독립적으로 작업하고 변경 사항을 제안할 수 있음
- 개발자는 자신의 저장소에서 브랜치를 생성하고 작업하기 때문에 심리적인 부담도 적음
Fork로 Pull Request(PR) 생성하는 방법
- GitHub에서 원하는 프로젝트의 페이지로 이동
- 우측 상단에 있는 'Fork' 버튼을 클릭하여 해당 프로젝트를 자신의 계정으로 Fork
3 .Fork 된 저장소로 이동하고, 변경 사항을 반영할 브랜치를 생성
- 변경 사항을 커밋하고 푸시
- GitHub 웹 사이트에서 Fork 된 저장소로 이동한 후, 'New pull request' 버튼 클릭
- 변경 사항을 반영할 원본 저장소와 브랜치를 선택
- Pull Request를 작성하고 제출
PR 충돌을 최소화하는 방법
-
최신 코드 유지
개발 기간이 길어질수록 메인 브랜치와 개발 중인 브랜치 간의 차이가 커지며 충돌 가능성도 증가함
이 문제를 해결하기 위한 간단한 방법은 주기적으로 원본 브랜치의 최신 변경 이력을 main 브랜치로 가져오는 것(git merge feat)임
동기화를 위한 정기적인 루틴을 만들어두는 것이 중요함 (매일 아침 동기화 수행하기)
-
작은 Pull Request 만들기
이는 소프트웨어의 구조가 잘 구성되어 있지 않다면 불가능할 수 있음
-
파일을 작게 만들기
소프트웨어의 아키텍처가 잘 구성되어 있지 않은 경우에는 적용하기 어려울 수 있음
-
동료들과 많은 커뮤니케이션 수행하기
좋은 Pull Reuqest란?
개발자 커뮤니티에는 일반적으로 이해하기 쉽고 명확한 PR을 좋은 PR이라고 생각함
즉 PR은 목적과 변경 사항, 그리고 그것이 어떻게 프로젝트에 영향을 미치는지를 리뷰어가 편하게 PR을 보며 리뷰를 할 수 있어야 함
- Communication
전달하려는 내용을 다양한 방법을 이용해서 명확하게 표현하기
- Pull Request를 작게 만들기
- 하나의 PR은 하나의 문제를 해결해야 함
- PR은 하루 안에 끝낼 수 있는 크기로 만들어야 함
- 커밋을 활용해 논리적 그룹을 만들어야 함
- 코드 스타일을 깔끔하게 유지하기
- 작성한 코드를 테스트하기
Pull Request를 위한 다양한 설정 및 편의 기능들
팀원들의 실수를 방지하고 불필요한 커뮤니케이션을 줄이며, 협업의 효율을 높이는 ‘울타리’ 같은 기능
- Default branch
- Pull Request의 머지 종류 제한하기
- Pull request가 머지된 이후, 자동으로 브랜치 삭제하기
- 브랜치 보호 설정
- Branch name pattern
- Require a pull request before merging
- Require linear history
- Do not allow bypassing the above settings
등
codeit-Pull Request를 위한 다양한 설정 및 편의 기능들
코드 리뷰
코드 리뷰를 위한 좋은 Commit 만들기
- 의미 있는 단위의 작업을 해야함
한 개의 커밋이 하나의 기능이나 작업을 완성해야 좋은 커밋임
작업의 크기는 작게 유지하는 것이 좋지만, 그렇다고 너무 작은 단위로 커밋하는 것은 다량의 커밋만 생성할 뿐 좋은 커밋이라고 할 수 없음
어떤 경우든지, 동료들이 사용하는 단위를 크게 벗어나지 않게 작업하는 것을 권장
- 생성된 커밋은 동작이 가능한 형태여야 할 것
- 커밋 메시지는 명확하고 간결하게 작성되어야 할 것
이를 위해 Conventional Commit
이라는 커밋 메시지 규칙이 생김
<type>(<scope>): <subject>
: type은 커밋의 종류를, scope는 커밋이 영향을 미치는 범위를 나타내고 subject에는 커밋의 간략한 설명을 적음
feat(UserProfile): Add email verification
커밋 메시지의 원하는 부분을 추출해서 자동으로 문서화할 수 있음
예를 들자면 feat type을 가진 커밋 메시지를 모아서 Release Note 등을 자동으로 생성할 수 있음
변형해서 사용할 수도 있음
자동으로 코드 Style 맞추기
Linting 툴이 작성된 코드의 규칙 위반 여부를 검사만 한다면, Formatter는 Linting에 맞도록 자동으로 코드를 바꿔줌