포스트

[TIL] Special lecture on Git & PR + CI/CD

This article summarizes what I studied after attending a special lecture on Git & PR + CI/CD.

한국어 원문은 여기에서 볼 수 있습니다.
[TIL] Special lecture on Git & PR + CI/CD

What I studied

Git Flow branching strategy

Without a branching strategy, accidents can occur, such as your work overwriting a colleague’s work, unfinished code mixed in when you’re about to deploy, or you wanting to roll back but having no reference point.

→ Branch strategy = accident prevention device

  • 5 branches of Git Flow

    branchrolebranchMerge targetlife
    mainProduction code. Always deployableeverlasting
    developNext release integration branch. Where all features come togetherFirst time in maineverlasting
    feature/*Develop new featuresdevelopdeveloptemporary
    release/*Ready for launch. Allow bug fixes onlydevelopmain + developtemporary
    hotfix/*Emergency fix for operational bugsmainmain + developtemporary

    image

  • Github Flow and Git Flow

    divisionGit FlowGithub Flow
    branch structureStrictly managed with 5 branchesmain • Use only feature (simple)
    suitable situationRegular releases, version managementWeb services, SaaS, CD where quick deployment is important
    A domain that fits wellMobile apps, package librariesweb service
    disadvantagecomplicacy. May be overkill for small teamsDifficult to operate multiple versions simultaneously
    Compatibility with distributionNot compatible with rapid distribution (CD)PR Merge = Immediate Deployment
    prerequisitesAutomated testing is an essential premise

    Most startups/web services start with Github Flow and expand to Git Flow as they grow.

PR Workflow and Code Review

  • Pull Request (PR): A formal request to merge my branch work into main (or develop)

  • 3 things PR does

    roleexplanation
    👀 Code review chapterA space for colleagues to view changes and leave feedback
    🧪 Automatic Verification TriggerExecute CI pipeline (automatically perform build/test)
    📜 Record change historyPermanently preserve why/what/when you changed
    • PR is a trigger that starts a code review and a change diary that I will read in the future.
  • PR life cycle

    1
    2
    3
    4
    5
    6
    
      1. Branch → feature/login 같은 작업 브랜치 생성
      2. Commit & Push → 작업 내용을 원격에 푸시
      3. Open PR → GitHub UI에서 PR 생성, 리뷰어 지정
      4. Review → 코드 리뷰 + CI 검증 → 수정 → 재푸시
      5. Approve & Merge → 승인 후 머지, 브랜치 삭제
    
    
  • Actual command flow

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
      # 1. 브랜치 생성
      git checkout -b feature/login
    
      # 2. 커밋
      git add .
      git commit -m "feat(auth): 로그인 토큰 검증 로직 추가"
    
      # 3. 푸시
      git push origin feature/login
    
      # 4~5. 여기서부터는 GitHub/GitLab 웹 UI에서 진행
    
  • How to write a good PR

    • Break it down into small pieces - 200 to 400 lines / single purpose

    • Title should be clear in one line - ex) [FIX] 로그인 토큰 만료 시 자동 리프레시 처리

    • Include context in the text

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      
        ## What
        - AccessToken 만료 시 자동으로 RefreshToken으로 재발급
      
        ## Why
        - 사용자가 30분 후 갑자기 로그아웃되는 이슈 (#142)
      
        ## How
        - AxiosInterceptor에 401 응답 시 재발급 로직 추가
        - 동시 요청 race condition은 Promise 큐로 직렬화
      
        ## Test
        - [x] 단위 테스트 추가 (auth.spec.ts)
        - [x] QA 시나리오 통과
        - [ ] 부하 테스트는 별도 PR
      
      
    • Self-review first - Re-read self-PR immediately after push

  • Code review is not censorship

    • As a reviewer,
      • Criticize the code, but not the people

      • Ask questions first, no assumptions

      • Praise the things you did well

    • As an author,
      • Explain your intentions without being defensive.

      • If you agree, reflect, if you disagree, discuss based on the evidence.

      • Reviews will be responded to within 24 hours

      • Thank you

Merge and Rebase

  • Merge: Merge commit to combine two histories image

    • Preservation of history - who worked on which branch remains intact

    • Safe - existing commits are never changed- History becomes complicated - As merge commits accumulate, git log becomes complicated.

  • Rebase: Paste my commit at the end of main image

    • History is clean - git log is in one straight line

    • No merge commits - remove noise

    • Existing commits are replaced by new commits - Collaboration is destroyed if done on a shared branch

  • When to use what (Merge & Rebase)

    standardMergeRebase
    historypreserved as isorganized in one line
    commit hashunchangedNewly created
    Conflict handlingat onceper commit
    Recommended SituationShared branch integrationClean up my local branch

    → You should never rebase a public branch that has already been pushed

  • What you should never do

    • git push -- force on the shared branch → completely destroys the colleague’s commit

    • Where force push is safe
      • My local feature branch

      • I push it, but only I use the branch.

      • Clean up commits just before PR merge

      • After reflecting the review, squash

    • Absolutely prohibited.
      • main / develop

      • Branch pushed by multiple people

      • Merged PR branch

      • Branch with release tag

Using git push --force-with-lease causes it to fail when the remote is not what I expected → If force push is necessary, definitely --force-with-lease

Conflict resolution

Conflicts occur when two branches modify the same line in the same file differently.

  • Conflict markers that Git leaves in files

    1
    2
    3
    4
    5
    
      <<<<<<< HEAD
        private final int TIMEOUT = 3000;       // 내 변경 (현재 브랜치)
      =======
        private final int TIMEOUT = 5000;       // 들어오는 변경 (다른 브랜치)
      >>>>>>> feature/api
    

    → Conflicts are not errors, but Git is requesting my judgment.

  • 5 steps to conflict resolution

    1. Check current status - git status

    2. Open the file and find the marker
      Check the location of <<<<<<< / ======= / >>>>>>> → Decide which code to use

    3. Modify to desired form

    4. Staging + Commit

      1
      2
      3
      
       git add .
       git commit
       # 머지 진행 중 상태가 종료됨
      
  1. Test + Push

    1
    2
    3
    4
    
     ```bash
     npm test       # 충돌 해결로 깨진 곳이 없는지 반드시 확인
     git push
     ```
    
    • If it’s still a mess

      1
      2
      
        git merge --abort   # 머지 시작 전으로 되돌림
        git rebase --abort  # rebase 중이면
      

CI/CD Pipeline Introduction

  • Difference between manual deployment and automation image

    • After introducing CI/CD
      • Test runs automatically when PR is raised

      • main merge = automatic deployment

      • Immediate Slack notification in case of failure

      • No room for human error

      • Number of distributions ↑ / Accidents ↓

  • CI/CD pipeline flow

    image

    stepwhat to do
    SourceTriggered by PR/Push event
    BuildCompilation / packaging / Docker image creation
    TestUnit Testing + Integration Testing + Lint
    DeployStage environment deployment → Prod deployment

    → If even one step fails, it stops immediately + notification / broken builds never advance to the next step

CI/CD Terminology

AbbreviationFull nameMeaning
CIContinuous IntegrationFrequent code integration and automatic verification
CDContinuous DeliveryStay deployable at any time (manual approval)
CDContinuous DeploymentIf passed, automatically distributed to operation
  • Get started in 30 lines with Github Actions
    ### .github/workflows/ci.yml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    
      name: CI
    
      on:
        push:
          branches: [main, develop]
        pull_request:
          branches: [main, develop]
    
      jobs:
        build-and-test:
          runs-on: ubuntu-latest
          steps:
            - name: 코드 체크아웃
              uses: actions/checkout@v4
    
            - name: JDK 17 설정
              uses: actions/setup-java@v4
              with:
                distribution: 'temurin'
                java-version: '17'
    
            - name: Gradle Wrapper 캐시
              uses: gradle/actions/setup-gradle@v3
    
            - name: gradlew 실행 권한 부여
              run: chmod +x ./gradlew
    
            - name: 테스트 실행
              run: ./gradlew test
    
            - name: 빌드
              run: ./gradlew build -x test
    
            - name: 테스트 결과 리포트
              if: always()    # 테스트가 실패해도 리포트는 업로드
              uses: actions/upload-artifact@v4
              with:
                name: test-reports
                path: build/reports/tests/test
    
    • What happens the moment it moves
      1. When you upload a PR, GitHub automatically executes the above sequence.

      2. If even one step fails, mark x in PR

      3. Merge button is automatically disabled (when Branch Protection is set)

      4. Merge is possible only if all checks pass.

    • One step further to CD

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      
        deploy:
          needs: build-and-test     # 위 job이 성공해야만 실행
          if: github.ref == 'refs/heads/main'
          runs-on: ubuntu-latest
          steps:
            - uses: actions/checkout@v4
      
            - name: JDK 17 설정
              uses: actions/setup-java@v4
              with:
                distribution: 'temurin'
                java-version: '17'
      
            - name: JAR 빌드
              run: ./gradlew bootJar -x test
      
            - name: AWS EC2로 배포
              run: ./scripts/deploy.sh build/libs/app.jar
              env:
                AWS_KEY: $
      
      • needs: test — If the test fails, it will not be distributed

      • if: github.ref == 'refs/heads/main' — only during main merge- secrets.* — Sensitive information is stored in GitHub Secrets

Problems & Errors

Q. Should I use Squash merge / Rebase merge / Merge commit?

There is no correct answer. The answer is to set a team convention and go consistently

  • Squash merge: compresses PR into 1 commit / cleanest history (most used)

  • Rebase merge: Attach PR commits in a row to main / Enable track of commit units

  • Merge commit: Merge commit creation / PR units are clearly distinguished

Q. Merge & Rebase

image

image

Q. This is my first time with CI/CD. Where do I start?

Start with one of the simplest workflows in GitHub Actions.

  1. Just run npm test automatically first.

  2. Add builds as you get used to it

  3. Then deploy Most people give up trying to “automate everything at once”.