Pull Request là gì? Quy trình đề xuất review và merge code
Pull Request thường viết tắt là PR là một yêu cầu đề xuất đưa những thay đổi từ một branch sang branch khác để đội phát triển xem xét trước khi merge.
Pull Request không phải bản thân việc merge code.
Nó là khoảng không gian để một thay đổi được giải thích thảo luận kiểm tra và phê duyệt trước khi hợp nhất.
Đây là khác biệt quan trọng.
Một PR được mở không có nghĩa code đã được chấp nhận.
Nó chỉ có nghĩa tác giả đang đề nghị đội phát triển xem xét một thay đổi.
Pull Request cũng không phải một lệnh của Git.
Git cung cấp commit branch diff merge và nhiều cơ chế quản lý phiên bản khác.
Pull Request là workflow được các nền tảng quản lý repository xây dựng xung quanh những khả năng đó.
GitHub sử dụng thuật ngữ Pull Request.
GitLab thường sử dụng thuật ngữ Merge Request.
Tên gọi khác nhau nhưng mục tiêu cốt lõi khá giống nhau.
Một developer thường bắt đầu bằng việc tạo một branch riêng cho task đang thực hiện.
Ví dụ:
feature/payment-deposit
Developer sửa code commit các thay đổi rồi push branch lên remote repository.
Sau đó Pull Request được tạo để đề nghị merge branch đó vào một branch đích như main hoặc develop.
Một Pull Request tốt nên giải thích vì sao thay đổi này tồn tại.
Chỉ nhìn diff đôi khi không đủ.
Reviewer cần hiểu vấn đề ban đầu requirement liên quan và kết quả mong đợi.
Ví dụ một PR chỉ ghi:
Fix payment.
Thông tin như vậy gần như không giúp reviewer hiểu chuyện gì đang được sửa.
Một mô tả tốt hơn nên giải thích lỗi xảy ra trong trường hợp nào nguyên nhân là gì cách xử lý được chọn và cách kiểm chứng kết quả.
Pull Request vì vậy không chỉ dành cho code.
Nó cũng là một đơn vị giao tiếp kỹ thuật.
PR giúp người khác hiểu ý định của thay đổi.
Một Pull Request thường chứa phần diff.
Diff cho thấy những dòng code nào được thêm sửa hoặc xóa so với branch đích.
Reviewer sử dụng diff để xem chính xác thay đổi đang được đề xuất.
Tuy nhiên review chỉ dựa trên diff có thể chưa đủ.
Một thay đổi nhỏ ở một hàm có thể ảnh hưởng đến nhiều module khác trong hệ thống.
Reviewer đôi khi cần đọc thêm code liên quan hoặc chạy ứng dụng để hiểu tác động đầy đủ.
Commit và Pull Request cũng không phải một.
Commit là một snapshot của thay đổi trong lịch sử Git.
Một Pull Request có thể chứa một hoặc nhiều commit.
Trong quá trình review developer có thể tiếp tục push thêm commit vào branch và Pull Request sẽ được cập nhật.
Branch cũng khác Pull Request.
Branch là một nhánh phát triển trong repository.
Pull Request là đề nghị đưa những thay đổi của branch đó vào một branch khác.
Do đó có thể có branch mà không có Pull Request.
Nhưng Pull Request thường dựa trên sự khác biệt giữa hai branch hoặc hai ref cụ thể.
Một trong những mục đích quan trọng nhất của Pull Request là Code Review.
Reviewer có thể đọc code đặt câu hỏi đề xuất sửa lỗi hoặc yêu cầu thay đổi trước khi merge.
Review không chỉ nhằm tìm bug.
Nó còn có thể kiểm tra kiến trúc business rule security performance khả năng bảo trì và mức độ phù hợp với coding standards của dự án.
Tuy nhiên Pull Request và Code Review vẫn không phải cùng một khái niệm.
Pull Request là workflow chứa thay đổi.
Code Review là hoạt động đánh giá thay đổi đó.
Một PR có thể trải qua một hoặc nhiều vòng review.
Reviewer có thể approve nếu thay đổi đạt yêu cầu.
Reviewer cũng có thể yêu cầu chỉnh sửa.
Developer sửa code rồi push thêm thay đổi vào cùng branch.
PR sau đó tiếp tục được review.
Đây là một feedback loop.
CI thường được kết nối trực tiếp với Pull Request.
Khi PR được mở hoặc cập nhật hệ thống có thể tự động chạy build test lint type checking security scan hoặc những kiểm tra khác.
Điều này giúp phát hiện nhiều lỗi trước khi code được merge.
Một PR có review tốt nhưng test thất bại vẫn chưa nên được xem là sẵn sàng merge.
Ngược lại test xanh cũng không chứng minh code hoàn toàn đúng.
Test chỉ kiểm tra những điều đã được thiết kế để kiểm tra.
Đây là lý do Pull Request thường kết hợp cả automated checks và human review.
Branch protection có thể được sử dụng để ngăn việc merge nếu một số điều kiện chưa đạt.
Ví dụ có thể yêu cầu test phải pass cần ít nhất một reviewer approve hoặc cấm merge khi branch chưa cập nhật với branch đích.
Những điều kiện này biến quy trình review từ một lời nhắc thành một cơ chế kỹ thuật có thể thực thi.
Pull Request cũng có thể liên kết với issue user story task hoặc requirement.
Điều này giúp người đọc lần ngược từ code về lý do thay đổi được tạo ra.
Ví dụ:
Requirement → Task → Pull Request → Commit → Deployment.
Chuỗi liên kết như vậy rất hữu ích cho traceability.
Khi một lỗi xuất hiện vài tháng sau đội phát triển có thể tìm commit rồi lần về PR để xem vì sao quyết định đó được đưa ra.
Nếu PR có mô tả và discussion tốt nó trở thành một phần của lịch sử kỹ thuật dự án.
Một Pull Request cũng nên có scope đủ nhỏ.
PR chứa vài nghìn dòng thay đổi về nhiều chức năng khác nhau rất khó review chính xác.
Reviewer dễ bỏ sót vấn đề khi phải xử lý quá nhiều context cùng lúc.
PR nhỏ hơn thường dễ hiểu dễ test dễ rollback và dễ review hơn.
Tuy nhiên không có một giới hạn số dòng cố định phù hợp cho mọi dự án.
Mục tiêu là giữ mỗi Pull Request tập trung vào một mục đích rõ ràng.
Không nên tách một thay đổi thành nhiều PR nhỏ đến mức mỗi PR riêng lẻ không còn chạy được.
Cũng không nên gom năm chức năng không liên quan vào một PR chỉ vì chúng được viết trong cùng ngày.
Pull Request title nên mô tả thay đổi đủ rõ để người khác có thể hiểu khi nhìn lịch sử.
Ví dụ:
Add deposit payment validation for tour bookings
thường hữu ích hơn:
Update payment
Description nên giải thích thêm context.
Một PR description thực tế có thể trả lời các câu hỏi:
Vấn đề là gì → thay đổi gì → tại sao chọn cách này → cách kiểm thử → có rủi ro hoặc tác động nào cần chú ý.
Nếu thay đổi có giao diện người dùng screenshot hoặc video ngắn đôi khi giúp reviewer kiểm tra nhanh hơn.
Nếu thay đổi database cần nêu rõ migration rollback và compatibility.
Nếu thay đổi API cần mô tả backward compatibility.
Nếu thay đổi business rule nên liên kết requirement hoặc Acceptance Criteria.
Draft Pull Request có thể được sử dụng khi code chưa hoàn tất nhưng tác giả muốn chia sẻ sớm để nhận feedback.
Đây là cách hữu ích khi một task có quyết định kiến trúc lớn.
Developer không nhất thiết phải viết xong toàn bộ rồi mới cho người khác nhìn thấy.
Review sớm đôi khi tránh được việc làm sai hướng trong nhiều ngày.
Pull Request cũng hỗ trợ conversation.
Reviewer có thể comment trực tiếp trên dòng code.
Các discussion này nên tập trung vào vấn đề kỹ thuật thay vì biến thành cuộc thi xem ai viết code giỏi hơn.
Mục tiêu của review là cải thiện code và chia sẻ hiểu biết.
Không phải tìm người thắng.
Một comment review tốt thường chỉ ra vấn đề và lý do.
Ví dụ:
Điều kiện này có thể cho phép cùng một payment được xử lý hai lần khi hai request đến đồng thời. Có nên kiểm tra idempotency ở tầng database không?
Nhận xét như vậy hữu ích hơn:
Code này không ổn.
Pull Request cũng có thể được hỗ trợ bằng AI Code Review.
AI có thể đọc diff tìm lỗi tiềm ẩn kiểm tra edge case hoặc đề xuất những phần cần chú ý trước khi human reviewer vào cuộc.
Tuy nhiên AI review không làm Pull Request tự động trở nên an toàn.
AI vẫn có thể tạo false positive hoặc bỏ sót vấn đề.
Đặc biệt nếu AI không biết business rule.
Do đó AI Code Review nên được xem như một reviewer bổ sung.
Không phải người phê duyệt cuối cùng.
Khi sử dụng AI coding agent Pull Request còn trở nên quan trọng hơn.
Agent có thể tạo ra lượng code lớn trong thời gian ngắn.
Nhưng khả năng sinh code nhanh không làm giảm nhu cầu kiểm chứng.
Ngược lại khối lượng thay đổi tăng có thể khiến review càng quan trọng.
Một workflow có thể là:
Task Specification → Coding Agent → Tests → Pull Request → AI Code Review → Human Review → CI checks → Merge.
Tuy nhiên không nên biến workflow này thành nghi thức máy móc.
Mỗi lớp kiểm tra cần có mục đích riêng.
Formatter kiểm tra format.
Linter kiểm tra rule tĩnh.
Test kiểm tra hành vi đã định nghĩa.
AI hỗ trợ suy luận về code.
Human reviewer kiểm tra những quyết định cần hiểu requirement context và rủi ro.
Merge strategy cũng là một phần của workflow Pull Request.
Một đội có thể sử dụng merge commit squash merge hoặc rebase tùy cách quản lý lịch sử Git.
Không có một chiến lược duy nhất đúng cho mọi repository.
Quan trọng là đội phát triển thống nhất cách sử dụng để lịch sử commit không trở nên khó hiểu.
Squash merge có thể gom nhiều commit nhỏ trong PR thành một commit khi merge.
Cách này giúp lịch sử branch chính gọn hơn.
Ngược lại giữ từng commit có thể hữu ích nếu các commit được tổ chức tốt và chứa ý nghĩa riêng.
Lựa chọn phụ thuộc vào workflow của dự án.
Sau khi merge Pull Request không còn là một thay đổi đang đề xuất.
Nó trở thành một phần lịch sử giúp giải thích vì sao code hiện tại tồn tại.
Đây là lý do không nên xem PR description và discussion là nội dung dùng một lần.
Vài tháng sau chúng có thể là tài liệu tốt nhất để hiểu một quyết định cũ.
Một Pull Request tốt vì vậy không chỉ giúp merge code.
Nó giúp đội phát triển kiểm soát thay đổi chia sẻ kiến thức và lưu lại lý do kỹ thuật của quyết định.
Tag Pull Request tổng hợp các bài viết và kiến thức về branch commit diff code review CI automated checks approval merge strategy AI Code Review và cách tổ chức quy trình thay đổi mã nguồn an toàn hơn trong phát triển phần mềm.



















