Haribo ML, AI, MATH, Algorithm

[git 시리즈 3] Pull Request 아~~~~

2025-12-25
Haribo
 

코드를 작성하는 건 ‘개인’의 영역이지만, PR을 올리는 순간부터는 ‘팀’의 영역이다. PR(Pull Request)은 단순한 병합 요청이 아니라, “내 코드가 메인 브랜치에 들어갈 자격이 있음을 증명하는 제안서” 임.

얼마전에 ComfyUI에 들어온 Z-Image alipai controlnet PR 을 한번 보자.
PR

일단 애니프사 최소 5명이 포함된 17명이 쏼라쏼라하고있음. 처음 볼땐 헷갈렸지만 그냥 위에서 아래로 내리면서 flow를 보면된다.
PR 올리고 리뷰어들이 피드백하고 다른 repo 관련 pr들 보여주면서 도움/피드백 주고, 첨엔 복잡해 보였는데 꼭 필요한 과정으로 생각된다.

  • 근데 모델 만든거 repo 주인장이 골라서 ComfyUI에 박아주나보다.
  • 나 모델 만들었소 PR 받아주셈 ㅠㅠ 이렇게는 안되는듯? 선택 당해야하는듯..;

그렇다면 이 PR을 더 맛있게 이해하기 위해 (다른 repo들도 포함해서) 깊게 살펴보자.


1. PR의 상태와 접두사 (Status & Prefix)

PR

PR 왼쪽에 마우스 대보면 어떤거는 Draft, 어떤거는 Open, Close 이렇게 다양하다.
씹고수들은 PR 상태를 시스템 상태(System State) 와 제목 말머리(Title Prefix) 두 가지로 나누고있음.

1.1 GitHub 시스템 상태 (System State)

이건 GitHub 서버가 인식하는 공식적인 상태임

  • Open (🟢 초록색): “리뷰 받을 준비 됨.” 일반적인 상태.
  • Draft (⚪ 회색): “작업 중(WIP).” Merge 버튼이 잠김. 리뷰어에게 알림이 안감.
    • 작업 끝나면 상태변경(PR 페이지 하단) “Ready for Review” 버튼으로 open PR로 변경해주기
  • Merged (🟣 보라색): “합체 완료.” 코드가 main으로 들어가버림.
  • Closed (🔴 빨간색): “반려됨(Rejected)” 또는 “머지 안 하고 그냥 닫음.” (실험 실패 등)

1.2 제목 말머리 규칙 (Semantic Title Prefixes)

시스템 기능은 아니지만, 개발자들이 제목 맨 앞에 수동으로 적는 약속(Protocol)

1.2.1. Semantic Prefixes (Step 1 연동)

  • feat: … : 기능 추가
  • fix: … : 버그 수정
  • refactor: … : 리팩토링
  • docs: … : 문서 작업 이게 Squash Merge 할 떄 커밋 메시지가 되므로 가장 권장됨ㅇㅇ.

1.2.2 특수 상황 접두사 (Emergency & Types)

  • HOTFIX: 🚨 긴급 수정. “아시발 빨리 리뷰해라. 서버 터졌다.”
  • Security: 보안 패치. (API 키 유출 수정 등)
  • Release: 배포용 PR. (보통 v1.2.0 같은 버전 넘버가 붙음)
  • Maint: 유지보수(Maintenance). 의존성 패키지 버전 올리기 등.

1.2.3 연구 조직용 커스텀 (Research Custom)

  • Exp: 실험(Experiment). “이거 성능 테스트용 코드임. 머지할지는 모름.”
  • RFC: 의견 요청(Request For Comments). “코드 짜기 전에 설계 핑까좀.” (코드가 거의 없거나 비어있을 때 씀)

1.2.4 Outdated

  • WIP: Draft 기능 생기고 나서 멸종음. 쓰면 “틀딱” 소리 들음.

2. Labels (라벨): 분류의 미학

Label은 보니까 repo 주인장이 세팅해놓은 검색 필터링, 릴리즈 노트 자동 분류, 우선순위 큐(Priority Queue) 관리를 위한 필수 메타데이터임.
어디는 10개미만 어디는 20개 그리고 ComfyUI는 50개나 쓴다.

2.1 Standard Labels (필수)

라벨 색상 의미 릴리즈 노트 섹션
bug 🔴 Red 버그 수정 Bug Fixes
enhancement 🔵 Blue 새로운 기능 Features
documentation 🔵 Blue 문서 작업 Documentation
invalid 🟡 Yellow 재현 불가/잘못된 요청 (무시됨)
question 🟣 Purple 질문/토론 (무시됨)
wontfix ⚪ White 수정 안 하기로 결정함 (무시됨)

2.2 Scoped Labels (Gemini 추천)

프로젝트 규모가 커지면 단순 라벨로는 부족한디… 그래서 키: 값 형태로 체계화해야 해주면 좋다고함.

우선 순위

  • priority: critical: 🚨 당장 서버 터짐. 실험 중단됨. (오늘 집에 못 감)
  • priority: high: 이번 주 안에는 무조건 머지해야 함.
  • priority: medium: 일반적인 기능 개발.
  • priority: low: 시간 남으면 하기. (Tech Debt 등)

영역 (Component) - AI 연구 맞춤

  • area: model: 모델 아키텍처(ResNet, UNet) 수정.
  • area: dataset: 데이터 로더, 전처리, Augmentation 수정.
  • area: training: 학습 루프, Loss 함수, Optimizer 수정.
  • area: inference: 추론, 데모 코드, 샘플링 로직 수정.
  • area: infra: Dockerfile, CUDA 설정, SLURM 스크립트.

이제뭔가 이렇게 해두면 분업/협업 빡시게 효율적으로 가능할꺼같긴함.

  • 근데 ComfyUI는 key-val 없이 50개 다 때려박긴함

3. PR Template (템플릿): 표준화

.github/pull_request_template.md에 마크다운 파일을 만들어두면, PR을 열 때마다 자동으로 본문에 그 양식이 채워짐.
팀원한테 “테스트 했?”라고 물어보면 “아맞다 ㅋㅋ”라고함. 입아프니까 템플릿에 체크리스트(Checklist) 를 박아넣어서 강제해주면 좋음.

pull_request_template.md 템플릿 예시

## 1. 개요 (Summary)
- 변경 사항 요약: (예: Cross-Attention 레이어 추가)
- 관련 이슈: #332

## 2. 변경 이유 (Motivation)
- 기존 방식의 문제점: (예: 텍스트 프롬프트가 이미지에 반영이 잘 안됨)
- 해결 방안: (예: Attention 메커니즘 개선)

## 3. 상세 내용 (Details)
- [ ] 모델 레이어 변경: `Conv2d` -> `Linear`
- [ ] 하이퍼파라미터 변경: Learning Rate `1e-4` -> `1e-5`

## 4. 테스트 결과 (Test Results)
- [ ] Unit Test 통과 (`pytest tests/`)
- [ ] 실험 결과 (WandB 링크 또는 Loss 그래프 스크린샷 필수)
    - Before: FID 15.2
    - After: FID 12.5

## 5. 체크리스트 (Self-Check)
- [ ] 불필요한 로그(`print`) 제거함
- [ ] `.gitignore`에 가중치 파일(`.pth`) 포함됨 확인 (커밋에 포함 금지)

4. 연결 고리 (Magic Links & Keywords)

PR을 보다보면 링크 #332 이렇게 박아두고 대화하는데 이게 도대체 어떻게 가져오는걸까. 폼떨어지게 issue나 예전 PR 숫자기억해뒀다가 쓰는걸까?

  • 문법: # 뒤에 이슈 번호 삽입 (# 누르면 이슈 리스트 쫙 나옴)
  • 기능
    • 텍스트가 하이퍼링크로 변함
    • Back-reference: 해당 이슈 페이지에 가면 “내가 이 이슈를 참조 했읍니다” 라는 로그가 타임라인에 남음
  • 용도: “이 PR은 #332 이슈와 관련이 있지만, 그걸 완전히 해결하는 건 아님”을 알릴 때.

4.2 Closing Keywords (자동 종료)

  • 문법: 예약어(Keyword) 바로 뒤에 이슈 번호를 작성
    • Closes #332
    • Fixes #332
    • Resolves #332
  • 기능
    • 이 PR이 Default Branch(보통 main)에 Merge되는 순간, 연결된 332번 이슈가 자동으로 Closed 상태로 변함
  • Why?
    • Traceability (추적성): 나중에 332번 이슈(버그)를 봤을 때, “도대체 무슨 코드를 고쳐서 이게 해결된 거지?”를 찾으려면, 이슈가 닫힌 시점에 연결된 PR 링크가 있어야함.
    • Efficiency: 일일이 이슈 찾아가서 ‘Close Issue’ 버튼 누르는 귀찮음을 없앰.

4.3 Keywords 뉘앙스 차이

  • Fix / Fixes / Fixed: 명확한 버그(Bug)를 고쳤을 때.
  • Close / Closes / Closed: 버그는 아니지만, 작업(Task) 이 끝났을 때. (예: 문서 작성 완료)
  • Resolve / Resolves / Resolved: 질문(Question) 에 대한 답변이나 해결책을 적용했을 때.

4.4 심층 분석: 번호 할당의 원리 (Global Counter)

Q: issue랑 PR 같은 번호표 기계에서 나오는거임?
A: ㅇㅇ 맞음

Global Sequence: GitHub 리포지토리당 내부적으로 하나의 Auto-increment Counter가 돈다.

  • 누가 Issue를 생성함 -> #1 할당.
  • 또 Issue를 생성함 -> #2 할당.
  • 내가 Pull Request를 생성함 -> #3 할당. (#1 아님!)

5. The PR Lifecycle (타임라인)

“올리고, 까이고, 고치고, 합치는” 전체 워크플로우를 타임라인 순으로 한번 보자

  • 물론 회사마다 규칙이 다를 수 잇음.

Step 1. PR 생성 (Open)

  • feature/model-fuck 브랜치를 말아 올리고 PR을 올림.
  • CI(GitHub Actions) 가동: 자동으로 테스트가 돌아감. 여기서 빨간불(Fail) 뜨면 리뷰어는 쳐다도 안봄. 일단 테스트부터 통과시키자.

Step 2. 리뷰어의 태클 (Request Changes)

  • 팀원이 코드를 보고 줄 단위로 댓글(Comment)을 담.
  • 상태가 Changes requested(수정 요청)로 바뀜.
  • TODO: 댓글 하나하나 읽어보고 대답ㄱㄱ.
  • 선 댓글 후 수정

Step 3. 수정 및 반영 (Fix & Push) -> 여기가 제일 중요

  • 행동: 로컬에서 코드를 수정하고 git add, git commit, git push ㄱㄱ.
  • 결과:
    • 새 PR을 파는거 아님.
    • 기존 PR에 새로운 커밋이 자동으로 추가됨.
    • “Changed files” 탭이 자동으로 갱신함.
  • 꿀팁: 커밋 메시지를 fix: apply review feedback 처럼 남기면, 리뷰어가 “아 고쳤구나” 하고 바로 앎.

Step 4. 대화 종료 (Resolve Conversation)

  • 기능: 댓글 스레드 옆에 있는 Resolve conversation 버튼.
  • 의미: “이 지적 사항은 해결되었으니 이제 안 봐도 됨(접기).”
  • 누가 누르나? (Protocol):
    • 일반적: 수정한 사람이 “고침(Done)” 댓글 달고 직접 Resolve 누름.
    • 엄격한 팀: 수정자가 “고침요”만 하고, 리뷰어가 확인 후 Resolve 누름.
      • (팀바팀이지만 본인 코드에대한 책임감으로 내가 누르는게 맞을듯. 지금까지는 눈치때문에 내가 못눌럿음.)

Step 5. 재검토 요청 (Re-request Review)

  • 수정을 다 했으면 리뷰어 이름 옆의 순환 화살표 아이콘(Re-request review) 을 눌러줌.
  • 이걸 안 누르면 리뷰어는 내가 고쳤는지 안 고쳤는지 모름. (알림이 안 감ㅇㅇ)

Step 6. 승인 (Approve)

  • 리뷰어가 다시 보고 만족하면 Approve 도장을 찍어줌.
  • PR 상태가 초록색 Approved로 바뀜.

Step 7. 최종 병합 (Merge)

  • Q: Approval 되면 걍 머지 하면 되는거?
  • 조건
    • 리뷰어 승인 (Approved)
    • CI 테스트 통과 (All checks passed)
    • 충돌 없음 (Branch has no conflicts)
  • Merge pull request ㄱㄱ
  • 주의 (Merge Strategy): 버튼 옆 화살표를 눌러서 Squash and merge를 선택하는 게 정신건강에 좋음. (지저분한 수정 내역을 하나로 압축)
  • Merge 하고 “Delete Branch” 버튼 눌러주기

6. 나도 근데 리뷰해야함.

남의 코드를 심사하는 입장(Reviewer)도 되어야함.
단순히 “오타요” 하는 건 하수임. “로직의 결함” 을 찾아내고 “설계의 구멍” 을 찔러줘야함.

6.1. Diff의 해부학 (Hunk Header 해석)

Q: PR 파일 보다 보면 골뱅이(@@)로 원본 코드 위에 있던데 뭐임?
A: Git이 변경 사항을 보여줄 때 사용하는 Unified Diff Format의 표준 헤더(Hunk Header). 그냥 장식이 아님.

6.1.1 구조 분석 (Anatomy)

@@ -10,7 +10,7 @@ def train_step(batch):
  • @@ ... @@: 헤더의 시작과 끝.
  • -10,7: 원본 파일(Old)의 10번째 줄부터 7줄을 보여줌.
  • +10,7: 수정된 파일(New)의 10번째 줄부터 7줄을 보여줌.
  • def train_step(batch):: Context Hint. 변경 사항이 어느 함수/클래스 내부인지 알려줌.

6.1.2 왜 중요한가? (Context Awareness)

Python 코드를 볼 때, 단순히 바뀐 줄만 보면 스코프(Scope) 오류를 놓치게됨.

  • 상황: if 문이 추가되면서 들여쓰기(Indentation)가 바뀌었는데, Diff에서는 + 된 줄만 보임.
  • 위험: 기존 코드가 if 블록 안으로 들어갔는지, 밖으로 나갔는지 @@ 뒤의 문맥과 공백을 보고 판단해야함.
  • Review Tip: GitHub에서 파일명 옆의 Show file 버튼을 누르거나, 줄 번호를 클릭해서 “Expand Up/Down” 을 눌러 주변 코드를 꼭 확인해줘야함.

6.2. 리뷰어의 무기: Comment, Request Changes, Approve

PR의 Files changed 탭에 들어가면 우측 상단에 Review changes 버튼이 있음.

6.2.1 Comment (단순 코멘트)

  • 의미: “승인도 반려도 아님. 그냥 할 말 있음.”
  • 용도:
    • 궁금한 거 물어볼 때 (“이거 왜 이렇게 짰노?”)
    • 칭찬할 때 (“오, 이 로직 신기하네.”)
    • 중요: 이걸로는 PR 진행이 막히지 않음. 머지 가능 상태가 유지.

6.2.2 Request Changes (수정 요청 - 반려) 🚨

  • 의미: “이대로는 절대 머지 못 해. 고쳐와.”
  • 기능: PR의 Merge 버튼을 비활성화(Block) 시킴. 내가 다시 와서 풀어주기 전까진 절대 머지 못함.
  • 용도:
    • 치명적인 버그 발견.
    • 설계 방향이 완전히 틀림.
    • 컨벤션 개판임.

6.2.3 Approve (승인) ✅

  • 의미: “내 이름 걸고 보증함. 머지해도 됨.”
  • 책임: 내가 Approve 찍고 머지된 코드가 서버를 터뜨리면? 내 책임도 50%임.

6.3. 토론의 장: Issues vs Discussions

Q: “Discussions? 얘네는 뭐하는거? Issue는 어떻게 보는거?”
A; 둘 다 글 쓰는 곳이지만, 목적(Goal)이 완전히 달라버림

6.3.1 Issues (할 일 관리)

  • 성격: Actionable (실행 가능해야 함).
  • 상태: Open -> (작업) -> Closed로 명확한 끝이 있음.
  • 용도:
    • Bug Report: “로그인 버튼 안 눌림.”
    • Feature Request: “다크 모드 추가해 주셈.”
    • Bad Case: “이 모델 구조 좀 이상한거같은디;” (이런 건 답이 없어서 Issue에 쓰면 안 됨. 영원히 Open 상태로 남음.)

6.3.2 Discussions (지식 공유 & 포럼)

  • 성격: Open-ended (결론 없어도 됨). StackOverflow나 Reddit 게시판임.
  • 기능:
    • Category: Q&A, Ideas, Show and tell 등으로 분류 가능.
    • Mark as answer: 질문글에 대해 누가 좋은 답을 주면 “채택” 가능 (이슈 닫기와는 다름).
  • 용도:
    • “PyTorch vs TensorFlow 뭐가 정배임?”
    • “이번 논문 읽어보신 분?”
    • “에러 로그 공유해유. (해결책 모름)”

Similar Posts

Comments