개발자들에겐 없어서는 안될 서비스 중 하나인 GitHub를 얼마나 잘 활용하고 있으신가요? 단순 Git의 원격 저장소로써 팀원들의 코드를 한 곳에 합쳐두는 용도로만 사용하고 있나요? 토이 프로젝트를 팀 단위로 수행할 때 GitHub를 조금 더 똑똑하게 활용하는 방법을 소개해 보겠습니다. (대부분 이미 알고 있을)현직자 분들보단 취업 준비를 하며 프로젝트를 진행하는 분들에게 도움이 되었으면 좋겠습니다.
Pull Requests의 병합 방식 정하기
토이 프로젝트라도 Git을 더 많이 활용해 보겠다는 생각을 가졌다면 기능별/작업 유형 별 브랜치를 나누어 개발을 한 뒤, 최종적으로 main
브랜치에 코드를 합칠 것입니다. 이를 위해 커밋 메시지 규칙도 정하고 브랜치 이름 규칙도 정하겠죠. 하지만 (Git이 아닌) GitHub가 익숙하지 않다면 PR을 어떻게 활용할지 햇갈릴 수 있을 겁니다. GitHUb에서 제공하는 브랜치 머지 전략인 PR을 더 세세하게 설정하고 활용해 볼까요?
위의 이미지는 GitHub 프로젝트의 Settings-General에 있는 PullRequests 항목입니다. PR을 merging할 때 사용할 수 있는 병합 방식을 설정할 수 있는데요. 각 방식들을 간단한 그림과 함께 살펴보겠습니다.
Allow merge commits
Allow merge commits(병합 커밋 허용)는 병합 커밋을 허용하는 것으로 기본적인 병합 방식입니다. PR의 모든 커밋을 그대로 유지하면서 병합하려는 브랜치(base branch)에 병합 커밋을 추가합니다. Git의 명령어인 git merge
와 동일하게 동작하며, 병합 커밋이 별도로 생성됩니다. 커밋이 하나하나 그대로 유지되어 자세한 히스토리를 볼 수 있습니다.
하지만 어떤 기능의 개발이 어떤 커밋부터 어떤 커밋까지 인지 알아보기 힘들 수 있고 충돌 해결에 대한 커밋, 병합을 위한 커밋 등 더 많은 로그가 쌓여 복잡하고 지저분해 질 수가 있습니다.
Allow squash merging
Allow squash merging(스쿼시 병합 허용)은 PR에 포함된 모든 커밋을 하나로 합쳐서 대상 브랜치에 병합합니다. git merge --squash
와 같은 방식으로 병합됩니다. GItHub는 기본적으로 GitHub는 병합 시 기본적으로 PR 제목 + (PR 번호) 형식의 메시지를 자동 삽입하기 때문에 PR의 개별 커밋도 GitHub에서는 쉽게 추적이 가능합니다. "기능 단위"로 커밋을 나누고자할 때 적합하며 Linear history
로 깔끔하게 기록을 관리할 수 있습니다.
로컬에서는 RP내의 세세한 커밋을 볼 수 없고 PR로 생성된 커밋 메시지만을 확인할 수 있으므로 PR의 내용을 자세하게 적어주어야 하고 커밋의 author가 실제 작업한 사람이 아닌 PR을 생성한 사람으로 설정되어 실제 작업자와 커밋에 표시된 작성자가 다를 수 있어 이런 상황을 피하기 위해 주의하여야 합니다. 여러 명의 기여자가 있다면 co-author를 명시하는 것이 좋을 수 있습니다.
또 다른 단점으로는 "A" 브랜치에서 작업 중 해당 브랜치를 베이스로 브랜치 "B"를 만든 다음, "A"브랜치를 main 브랜치에 sqush merge하면 "A" 브랜치의 개별 커밋들은 사라지게 됩니다. 이 상황에서는 "B"브랜치가 참조하던 커밋들이 사라져 "B" 브랜치를 다시 main에 합칠 경우 "A"에서 이미 병합된 커밋들은 충돌로 인식되어 주의가 필요합니다. 이경우 "B" 브랜치를 main으로 rebase시킨 뒤 병합을 진행하는 것이 더욱 안전합니다. 더 나은 방법은 새로운 브랜치를 만들땐 main에서만 따오는 것입니다. 이 경우 "A"를 main에 squash merge를 진행한 후 "B" 브랜치를 만들어야 합니다.
Allow rebase merging
Allow rebase merging(리베이스 병합 허용)은 PR의 커밋들을 base 브랜치 위에 올리는 방식입니다. git rebase
와 비슷하게 동작하며 각 커밋이 base 브랜치의 마지막 커밋 위에 새롭게 작성되어 합쳐집니다. 병합된 이후의 커밋을 보면 마치 원래부터 base 브랜치 위에 작업한 것처럼 보일 수 있습니다. 커밋 기록이 세세하면서도 깔끔하게 선형으로 유지되는 것을 원한다면 rebase merge가 좋은 선택입니다.
rebase가 되므로 커밋의 해시값이 변경되고 기존의 커밋과 전혀 다른 커밋이 만들어집니다. 그래서 병합 전 커밋을 base로 가진 다른 브랜치가 있다면 그 브랜치는 부모 커밋을 찾을 수 없게 됩니다. 그래서 협업 중인 브랜치에는 rebase merge를 하는 것은 위험할 수 있습니다.
다른 좋은 설정
설명한 PR의 병합 방식 외에도 아래에 3가지 설정이 더 있는데, 개인적으론 Automatically delete head branches를 활성화하여 병합된 브랜치를 자동으로 삭제하는 것을 추천합니다. 이렇게 하면 너무 많은 브랜치가 생성되어 레포지토리가 복잡해지는 것을 방지할 수 있습니다.
추가로 각 병합 방식을 체크 해제하여 특정 방식의 병합을 사용하지 못하게 제외할 수 있습니다.
Rules
레포지토리에 룰을 설정하는 항목입니다.
룰을 설정하기 위해서는 Rules - Rulesets에서 Ruleset Name을 정하고 Enforcement status를 Active로 바꾸어줍니다. Bypass list를 등록하면 해당하는 작업자는 이 규칙에서 제외됩니다.
Targets에선 규칙이 적용될 브랜치를 선택합니다.
마지막으로 Rules 섹션은 브랜치 보호 규칙(Branch Protection Rules)을 정의하여, 협업 중 실수 방지, 코드 품질 보장, 배포 안정성 확보 등을 가능하게 하는 기능입니다. 직접 브랜치를 선택하여 추가할 수 있고 Target branches에서 Include by pattern를 사용하여 브랜치 이름의 패턴으로 선택하여 추가할 수도 있습니다. 이미 간단한 설명이 붙어있지만 조금 더 자세한 설명을 추가하겠습니다.
- Restrict creations: 매칭되는 ref(브랜치 또는 태그)를 만들 수 있는 사용자를 제한
- 특정 브랜치나 태그를 생성하지 못하게 합니다.
- Restrict updates: 매칭되는 ref를 수정할 수 있는 사용자를 제한
- 브랜치에 직접 커밋하거나 push할 수 없게 제한합니다.
- 보통 `main`, 'release` 브랜치에 설정하여 직접 push할 수 없게 만듭니다.
- Restrict deletions: 매칭되는 ref를 삭제할 수 있는 사용자를 제한
- 중요한 브랜치나 태그가 실수로 삭제되는 것을 방지합니다.
- `main`, `release`등의 브랜치가 삭제되지 않게 설정할 수 있습니다.
- Require linear history: 직선적인 히스토리만 허용 (merge commit 금지)
- PR을 병합할 때 squash 또는 rebase 병합만 허용합니다.
- Require deployments to succeed: 지정된 환경에 배포가 성공해야 병합 가능
- production 등 정해진 환경에 자동 배포가 완료되기 전까지는 브랜치에 병합 불가능하도록 설정하는 방식입니다.
- CI/CD 연동 시 사용합니다.
- Require signed commits: 서명된 커밋만 허용 (GPG 또는 SSH 서명 필요)
- 커밋자가 실제 본인이 맞는지를 보장합니다.
- Require a pull request before merging: 반드시 PR을 통해서만 병합 가능
- 브랜치에 직접 커밋하는 것을 방지하고, 반드시 리뷰 과정을 거쳐야만 병합되도록 합니다.
- 코드 리뷰, 테스트 자동화, 리뷰어 승인 등 협업 필수 프로세스를 강제합니다.
- Require status checks to pass: CI 등 상태 검사 통과가 필요
- 지정된 테스트, 린트 검사, 타입 검사 등이 모두 통과해야만 병합을 할 수 있습니다.
- GitHub Actions와 같은 CI 도구와 연동이 되어 있어야 작동합니다.
- Block force pushes: 강제 푸시(Force push) 금지
- 이름 그대로 입니다...
- Require code scanning results: 코드 보안 스캔 결과 필수
- GitHub Advanced Security 또는 CodeQL, Snyk 등의 도구로 스캔한 보안 이슈 분석 결과가 존재해야 병합 가능합니다.
'개발 > 기타' 카테고리의 다른 글
로그 출력을 깨끗하게 만드는 방법과 대화형 CLI 만들기 (0) | 2025.03.30 |
---|---|
웹성능은 어떻게 개선할수 있을까요? (0) | 2024.09.02 |
언제까지 add, commit, push만 사용할 건가요? - commit과 관련된 다른 git 명령어들 (0) | 2024.06.18 |
웹 개발자라면 정규 표현식은 알아야지 (0) | 2024.03.18 |
TDD(Test Driven Develop, 테스트 주도 개발) (0) | 2024.03.12 |