Skip to content

9. Chính sách Workflow Nhóm

IMPORTANT

Đây không phải guideline mềm. Đây là policy vận hành cho team Penalgo hoặc HPN khi code đã có khả năng đi production.

Policy này giải quyết vấn đề gì?

Git không thất bại vì thiếu lệnh. Git thất bại vì team không thống nhất cách làm việc: branch đặt tên loạn, commit khó đọc, PR quá to, rebase sai chỗ, tag release không rõ nguồn gốc, rollback chậm và force-push trong hoảng loạn.

Policy này giải quyết đúng các điểm đó:

  • giữ main luôn ở trạng thái có thể deploy hoặc rollback an toàn
  • buộc commit phải rõ nghĩa và có thể review
  • tách ranh giới rõ ràng giữa làm sạch lịch sử cá nhânbảo toàn lịch sử shared branch
  • giảm thời gian phản ứng khi release lỗi hoặc lộ secret

Sơ đồ workflow mặc định của team

text
main (protected, deployable)
├── feature/<ticket>-<short-name>
├── fix/<ticket>-<short-name>
├── hotfix/<incident>-<short-name>
├── chore/<ticket>-<short-name>
└── release/vX.Y.Z

local cleanup only:
feature/... -> rebase allowed trước PR

shared integration:
feature/... -> Pull Request -> merge vào main
release/... -> tag annotated -> deploy
hotfix/...  -> Pull Request khẩn -> merge vào main -> tag/release nếu cần

Non-negotiables

  1. Production first: mọi thay đổi phải nghĩ tới deploy, audit và rollback.
  2. Atomic commits: một commit chỉ chứa một ý thay đổi có thể giải thích được.
  3. Clarity over cleverness: commit message, PR title, tag message và branch name phải đọc là hiểu.
  4. Recovery before panic: production lỗi thì revert hoặc rollback trước, tranh luận kiến trúc sau.
  5. Không force-push lên shared branches: main, release/*, và mọi branch có nhiều người cùng dùng.

1) Quy tắc đặt tên branch

Format bắt buộc

bash
feature/<ticket>-<short-name>
fix/<ticket>-<short-name>
hotfix/<incident>-<short-name>
chore/<ticket>-<short-name>
release/vX.Y.Z
docs/<ticket>-<short-name>

Ví dụ hợp lệ

bash
feature/pla-142-payment-retry
fix/pla-203-login-timeout
hotfix/inc-481-checkout-null-guard
chore/pla-210-upgrade-vitest
release/v1.4.0
docs/pla-188-git-phase1-policy

Quy tắc cụ thể

Quy tắcBắt buộc
Prefix đúng loại công việcfeature, fix, hotfix, chore, docs, release
Có mã ticket hoặc incidentĐể truy vết được lý do thay đổi
Dùng chữ thường, kebab-caseKhông dấu cách, không camelCase
Tên ngắn nhưng đủ nghĩaTối đa khoảng 3-6 từ mô tả
Không dùng tên mơ hồCấm test, update, final, new-branch

CẤM LÀM

  • commit trực tiếp trên main
  • tạo branch kiểu bugfix, temp, abc, work, trying
  • dùng một branch cho nhiều mục tiêu không liên quan

2) Quy tắc commit message

Format mặc định

text
<type>(<scope>): <mô tả ngắn>

Types được dùng

TypeKhi dùng
featthêm tính năng
fixsửa bug
docscập nhật tài liệu
refactorđổi cấu trúc nhưng không đổi behavior mong đợi
testthêm hoặc sửa test
choreviệc bảo trì, config, tooling
cipipeline, workflow automation
perftối ưu hiệu năng
reverthoàn tác thay đổi đã có

Scopes nên rõ theo domain

auth, payments, git, release, docs, ci, search, api, ui

Ví dụ đạt chuẩn

bash
feat(payments): add retry guard for duplicate webhook events
fix(auth): prevent session refresh loop on expired token
docs(git): define team workflow policy for phase 1
ci(release): require build before annotated tag creation
revert(checkout): rollback optimistic stock reservation

Ví dụ không đạt

bash
fix stuff
update code
WIP
final version
misc changes

Chính sách commit

  • Không push commit WIP, fix later, temp, debug, again.
  • Trước khi mở PR, author phải tự dọn các commit rác trên branch cá nhân.
  • Không gom nhiều thay đổi không liên quan vào một commit chỉ để “ít commit hơn”.
  • Nếu commit đã push lên shared branch và message dở, không rewrite lịch sử shared branch chỉ để làm đẹp.

3) Kỳ vọng với Pull Request

PR chỉ được mở khi đủ điều kiện

  • branch build được hoặc ít nhất không làm hỏng trạng thái repo
  • author đã tự review diff trước
  • không còn file debug, secret, log tạm, dữ liệu local
  • tiêu đề PR rõ mục tiêu business hoặc kỹ thuật

Nội dung PR bắt buộc

MụcKỳ vọng
ProblemĐang sửa hoặc thêm cái gì
ScopeNhững phần nào bị ảnh hưởng
RiskChỗ có thể gây lỗi production
VerificationĐã test gì
RollbackNếu lỗi sẽ revert commit hoặc tag nào

Quy mô PR

  • Lý tưởng: dưới ~400 dòng thay đổi thực chất để reviewer đọc trong một lần.
  • Cần giải thích thêm: trên ~800 dòng hoặc chạm nhiều domain.
  • Nên tách PR nếu vừa refactor, vừa đổi behavior, vừa đổi config release.

Review rules

  • Tối thiểu 1 reviewer cho thay đổi thường.
  • Tối thiểu 2 reviewer cho thay đổi liên quan security, release, auth, payment, hoặc production incident.
  • Không tự merge khi còn comment quan trọng chưa được xử lý.
  • Reviewer review logic và rủi ro, không chỉ nhìn pass CI.

4) Policy merge vs rebase

Rebase được phép khi nào?

  • Chỉ trên branch cá nhân hoặc private branch
  • Trước khi mở PR để dọn history
  • Khi sync với origin/main mà branch chưa bị nhiều người cùng dùng
bash
git fetch origin
git rebase origin/main

Merge bắt buộc khi nào?

  • Khi tích hợp code đã review vào main
  • Khi branch đã shared cho nhiều người
  • Khi cần giữ mốc tích hợp để audit, release hoặc rollback

Quy tắc cứng

Tình huốngPolicy
mainKhông rebase, không force-push
release/*Không rebase sau khi branch đã công bố
hotfix/*Có thể cleanup local, nhưng merge vào main qua PR
Branch cá nhân trước PRCó thể interactive rebase
Branch đã nhiều người cùng dùngTránh rebase, ưu tiên merge

Merge method mặc định của team

  • Mặc định: merge PR bằng merge commit
  • Cho phép squash chỉ khi branch có nhiều commit rác nhỏ và reviewer đồng ý
  • Không dùng rebase merge vào main vì làm mất điểm tích hợp rõ ràng

WHY

Merge commit giữ dấu vết “feature này đi vào main ở thời điểm nào”, cực hữu ích khi audit release hoặc revert một cụm thay đổi.

5) Protected branch rules

Các branch phải được bảo vệ

  • main
  • release/*

Rule bắt buộc

  • cấm push trực tiếp
  • cấm force-push
  • cấm delete branch nếu chưa theo policy release hoặc retention
  • yêu cầu PR review trước khi merge
  • yêu cầu status checks quan trọng pass trước khi merge

Status checks tối thiểu

  • build
  • test hoặc validation phù hợp với repo
  • secret scan hoặc security gate nếu có

Quyền bypass

Chỉ maintainer được bypass trong incident thật sự, và vẫn phải:

  1. ghi rõ lý do trong kênh incident hoặc ticket
  2. tạo PR hoặc postmortem follow-up sau đó
  3. không dùng bypass để né review thông thường

6) Policy release tags

Format tag phát hành

bash
vX.Y.Z
vX.Y.Z-rc.1

Rule bắt buộc

  • Tag release phải là annotated tag
  • Tag phải trỏ tới commit đã có trong main hoặc release/*
  • Không tag từ máy local chưa đồng bộ
  • Release notes phải lấy từ commit history và PR thực tế, không “nhớ mang máng”

Ví dụ

bash
git tag -a v1.4.0 -m "Release v1.4.0"
git push origin v1.4.0

Sai tag thì xử lý thế nào?

  • Không retarget tag cũ sang commit khác
  • Không force-update tag đã public
  • Cách đúng: tạo tag mới, ví dụ v1.4.1, và ghi rõ lý do correction

7) Policy secret handling

Tuyệt đối không commit

  • .env, .env.*
  • private keys, certificates, SSH keys
  • access token, API key, webhook secret
  • database dump, production snapshot, local SQLite file
  • file config chứa credential thật

Phòng ngừa bắt buộc

  • dùng secret manager hoặc environment variables
  • cấu hình .gitignore đúng từ đầu
  • review git diff --cached trước mỗi commit quan trọng
  • bật secret scanning nếu nền tảng hỗ trợ

Nếu lỡ stage secret nhưng chưa commit

bash
git restore --staged <file>

Nếu đã commit local nhưng chưa push

  • xóa secret khỏi file
  • git commit --amend hoặc rebase local để sửa
  • verify lại diff trước khi push

Nếu đã push lên remote

  1. Rotate secret ngay
  2. báo team và maintainer ngay lập tức
  3. chặn hoặc thu hồi access liên quan
  4. đánh giá cần revert, purge history hay cả hai
  5. chỉ rewrite history khi đã có owner điều phối

THỨ TỰ ĐÚNG

Rotate trước. Dọn Git sau. Không làm ngược.

8) Kỳ vọng rollback và xử lý incident

Nguyên tắc chung

  • Production lỗi thì ưu tiên khôi phục dịch vụ, không ưu tiên “giữ lịch sử đẹp”.
  • Shared history đã public thì ưu tiên git revert, không dùng reset --hard.
  • Mọi PR chạm production phải có ý rollback tối thiểu 1 dòng.

Team expectation

Tình huốngKỳ vọng
Release gây lỗiquyết định rollback hoặc revert nhanh, không tranh luận quá lâu
Commit lỗi trên maintạo revert commit rõ ràng
Cần hotfixtách branch hotfix/..., review nhanh, merge lại main
Không chắc nhánh nào an toàndùng tag release gần nhất hoặc commit đã xác minh

Lệnh ưu tiên khi rollback shared branch

bash
git revert <commit>
git revert <oldest>^..<newest>

Điều bị cấm trong incident

  • force-push lên main
  • rebase main
  • xóa tag release để “coi như chưa từng xảy ra”
  • sửa commit history trong lúc cả team đang pull

Khi nào không được phá lệ policy này?

Chỉ có hai trường hợp:

  1. incident production cần bypass tạm để khôi phục dịch vụ
  2. repo owner yêu cầu bằng văn bản trong ticket hoặc PR vì lý do đặc biệt

Ngoài hai trường hợp này, “để nhanh hơn” không phải lý do hợp lệ.

Nếu dùng sai policy thì khôi phục thế nào?

Sai lầmCách khôi phục an toàn
Commit nhầm lên main nhưng chưa pushtạo branch cứu hộ, reset local về đúng trạng thái
Commit xấu trên feature branch cá nhâninteractive rebase trước PR
Rebase nhầm shared branchdừng lại, dùng git reflog, phối hợp maintainer trước mọi force action
Merge sai vào maingit revert merge hoặc revert commit liên quan
Push secretrotate secret, báo team, rồi mới xử lý history
Tag sai releasetạo tag release mới, không sửa tag cũ

Ví dụ thực tế: release lỗi lúc 3 giờ sáng

Tình huống:

  • main vừa merge PR feat(payments): add retry worker
  • tag v1.4.0 đã phát hành
  • production bắt đầu tạo duplicate charge

Xử lý đúng theo policy:

  1. on-call xác nhận impact và dừng rollout
  2. team chọn rollback nhanh về release an toàn hoặc git revert commit lỗi
  3. không rebase main, không force-push
  4. tạo hotfix/inc-481-disable-retry-worker nếu cần patch khẩn
  5. sau khi dịch vụ ổn định mới làm RCA và tối ưu dài hạn

Điểm quan trọng: khôi phục trước, tối ưu sau. Người dùng không quan tâm lịch sử Git đẹp; họ quan tâm hệ thống sống lại.

Quick practice

Hãy tự trả lời 4 câu hỏi sau trước khi bạn mở PR tiếp theo:

  1. Branch của tôi có đúng format và truy vết được ticket chưa?
  2. Commit history của tôi có đọc hiểu được khi reviewer chưa biết context không?
  3. Nếu PR này gây lỗi production, tôi sẽ revert commit nào hoặc rollback tag nào?
  4. Tôi có đang dùng rebase đúng trên branch cá nhân, hay đang chuẩn bị phá shared history?

Trang trước: 08. Disaster Recovery Cheatsheet