Agent Coding 101Chapter 7 of 10

Khi coding agent nói 'done', kiểm tra thế nào?

Cách review diff, đối chiếu tiêu chí hoàn thành và đòi đủ bằng chứng trước khi commit hoặc merge.

howznguyen

howznguyen

24 min read

Khi coding agent nói 'done', kiểm tra thế nào?

Ở cuối bài trước, mình nói rằng lần kiểm tra cuối phải chạy trên trạng thái đã ghép, không phải trên từng branch hoặc bản tóm tắt riêng lẻ.

Nhưng tới lúc agent báo done, mình phải kiểm tra cụ thể những gì?

Lời nhắn cuối thường nhìn khá thuyết phục. Agent liệt kê file đã sửa, nói test đã qua, giải thích vài quyết định rồi kết thúc bằng một câu kiểu “đã làm xong”.

Nếu task nhỏ và diff trông hợp lý, mình rất dễ gật đầu rồi commit luôn. Mình cũng từng làm vậy khá nhiều.

Vấn đề là done chỉ là lời báo của chính người vừa viết code. Nó chưa phải dấu mộc nghiệm thu. Nếu chữ done tự có quyền lực như vậy thì nghề review đã nhàn hơn nhiều.

Bài này không kể lại chuyện test xanh chưa chắc task đúng. Mình muốn tập trung vào phần thực tế hơn: khi agent dừng viết, mình review trạng thái cuối ra sao, cần những bằng chứng gì và lúc nào thay đổi mới thật sự sẵn sàng để commit hoặc merge.

Done là lời báo, chưa phải dấu mộc

Khi agent báo hoàn thành, mình tách ba thứ ra khỏi nhau:

PhầnCâu hỏiVí dụ
Đầu raAgent đã tạo hoặc thay đổi gì?File, migration, test, config, docs
Bằng chứngCó gì cho thấy thay đổi hoạt động?Diff, câu lệnh, kết quả test, ảnh chụp, phản hồi API, log
Kết quảHệ thống cuối cùng có làm đúng việc không?Admin tạo được lời mời, thành viên thường bị từ chối, lời mời trùng không sinh thêm bản ghi

Đầu ra là thứ mình có thể mở ra đọc.

Bằng chứng là thứ giúp mình bớt phải đoán.

Kết quả mới là lý do task tồn tại.

Một agent có thể tạo đúng năm file nhưng chọn sai cách hệ thống phải hoạt động. Nó có thể chạy một bộ test xanh lét nhưng không test đúng luồng vừa sửa. Nó cũng có thể làm đúng ở nhánh riêng, tới lúc ghép lại thì migration hoặc kiểu dữ liệu dùng chung mới bắt đầu cãi nhau.

Vì vậy, mình không review dựa trên độ tự tin của câu trả lời cuối. Mình review một chuỗi bằng chứng từ task ban đầu tới trạng thái cuối của repository.

Chuỗi bằng chứng từ lời agent báo xong tới diff, các bước kiểm tra, hành vi thật và trạng thái đã xác minh
Lời agent báo xong chỉ là điểm bắt đầu. Diff, các bước kiểm tra và hành vi thật mới cho thấy task đã được xác minh.
📝

Không cần nghi ngờ mọi thứ agent nói

Mục tiêu không phải biến mỗi task thành một cuộc điều tra. Mình chỉ cần một quy trình đủ lặp lại để độ tự tin đến từ bằng chứng, không đến từ cách agent viết lời nhắn cuối.

Đóng băng trạng thái trước khi review

Điều đầu tiên mình làm sau khi agent báo xong là yêu cầu nó dừng sửa file.

Nghe hơi thừa, nhưng ranh giới này rất quan trọng.

Nếu agent vừa tự review vừa sửa liên tục, diff mình đang đọc cứ chạy tới chạy lui. Mình xem xong file A thì agent quay lại đổi file A để chữa lỗi ở file B. Test vừa xanh cũng có thể đã chạy trên trạng thái cũ.

Trước khi review, mình muốn chụp lại trạng thái hiện tại bằng vài câu lệnh:

Bash

Nếu có thay đổi đã đưa vào vùng chờ commit, mình xem thêm:

Bash

Bốn câu lệnh đầu trả lời bốn câu khác nhau:

  • Thư mục làm việc có file nào bị sửa, xoá hoặc chưa được Git theo dõi?
  • Diff lớn tới mức nào?
  • Loại thay đổi của từng file là gì?
  • Nội dung thay đổi cụ thể ra sao?

git diff không hiển thị nội dung của file untracked. Đây là chỗ khá dễ bỏ sót. Nếu git status --short có file mới, mình vẫn phải mở file đó hoặc đưa nó vào phạm vi review bằng cách khác.

Mình cũng hay chạy:

Bash

Câu lệnh này không chứng minh code đúng. Nó chỉ bắt một số lỗi khoảng trắng trong diff. Nhưng đây là bước kiểm tra nhanh, rẻ và hợp để chạy trước khi đi sâu hơn.

⚠️

Đừng để agent tự dọn working tree

Nếu repository đã có thay đổi của bạn từ trước, không bảo agent reset, restore hoặc xoá file để làm status sạch. Trạng thái sạch không quan trọng bằng việc xác định đúng thay đổi nào thuộc task và giữ nguyên phần ngoài phạm vi.

Sau bước này, mình muốn agent trả lời được:

  • File nào do task này thay đổi?
  • File nào đã có từ trước?
  • Có file sinh tự động, file khoá phiên bản thư viện (lockfile), ảnh chụp kết quả test (snapshot) hoặc migration nào xuất hiện không?
  • Có file nào agent không chắc thuộc phạm vi không?

Nếu chưa trả lời được, mình chưa vội soi từng dòng.

Review từ task trước, đừng lao thẳng vào code

Mở diff lên đọc ngay là phản xạ khá tự nhiên.

Nhưng nếu không giữ task bên cạnh, mình rất dễ review xem code có "đẹp" không rồi quên mất nó có giải quyết đúng việc không.

Trước khi đọc phần đã làm, mình mở lại:

  • Mục tiêu của task
  • Tiêu chí hoàn thành
  • Giới hạn cần giữ
  • Phần không làm
  • Quyết định đã chốt
  • Cách kiểm tra đã dự kiến

Sau đó mình tạo một bảng đối chiếu nhỏ.

Tiêu chí hoàn thànhBằng chứng dự kiếnTrạng thái
Admin tạo được lời mờiTest tích hợp và phản hồi APIChưa kiểm tra
Thành viên thường bị từ chốiTest phân quyềnChưa kiểm tra
Lời mời trùng không tạo bản ghi mớiKiểm tra dữ liệu và test hai yêu cầu đồng thờiChưa kiểm tra
Form giữ lại email khi máy chủ trả lỗiLuồng chạy trên trình duyệtChưa kiểm tra

Bảng này không cần nằm trong spreadsheet hay công cụ phức tạp. Một bảng trong ghi chú của task là đủ.

Điểm quan trọng là mỗi tiêu chí phải có một loại bằng chứng phù hợp.

Nếu tiêu chí nói về trạng thái database, một ảnh chụp giao diện chưa đủ. Nếu tiêu chí nói về vị trí con trỏ bàn phím, unit test cho service chưa đủ. Nếu tiêu chí nói không lộ secret trong log, phản hồi API ở luồng thuận cũng chẳng chứng minh được gì.

Và nếu có dòng chưa biết kiểm tra bằng gì, mình đánh dấu Chưa xác minh.

Mình thích một dòng thật thà như vậy hơn câu “mọi bước kiểm tra đều qua” mà không nói bước nào thật sự chạm tới yêu cầu.

Review diff từ rộng tới hẹp

Sau khi task và bằng chứng dự kiến đã nằm cạnh nhau, mình mới đi vào diff.

Mình review theo thứ tự từ rộng tới hẹp. Cách này giúp bắt vấn đề về phạm vi trước khi tốn thời gian đọc chi tiết.

Một là xem phạm vi.

Mình nhìn file list và diff stat trước.

Task sửa validation của một form mà diff chạm hai mươi file, đổi cấu hình formatter và cập nhật ba package thì cần dừng lại giải thích. Có thể thay đổi đó hợp lý. Nhưng nó không tự nhiên hoá hợp lý chỉ vì agent nói dependency mới “giúp code sạch hơn”.

Những file mình để ý đặc biệt gồm:

  • Package manifest và lockfile
  • Migration, schema và client sinh tự động
  • Cấu hình build, deploy hoặc CI
  • Snapshot lớn
  • Kiểu dữ liệu công khai và thoả thuận dùng chung
  • File chứa phân quyền, xác thực hoặc cách xử lý secret
  • File ngoài thư mục đã được giao

Với mỗi file ngoài dự kiến, agent cần giải thích vì sao nó phải thay đổi để đạt kết quả.

Hai là xem cách hệ thống hoạt động.

Mình đọc đường đi chính của dữ liệu thay vì bắt đầu từ tên biến đẹp hay xấu.

Dữ liệu đi vào đâu? Việc kiểm tra xảy ra ở lớp nào? Quyền được kiểm tra trước hay sau khi ghi dữ liệu? Lỗi nào trả về cho nơi gọi? Transaction kết thúc ở đâu? Tác động phụ như gửi email hoặc đẩy vào hàng đợi xảy ra lúc nào?

Ở đây mình tìm những thứ như:

  • Luồng thuận có đúng không?
  • Luồng lỗi có giữ trạng thái hợp lệ không?
  • Dữ liệu rỗng, null, trùng và thử lại được xử lý thế nào?
  • API công khai hoặc cách database hoạt động có đổi ngoài dự kiến không?
  • Logic mới có lách qua quyền cũ không?
  • Hai yêu cầu đồng thời có tranh chấp dữ liệu không?
  • Lỗi giữa transaction và tác động phụ để lại trạng thái gì?

Không cần task nào cũng trả lời toàn bộ danh sách. Mức review phải tỷ lệ với rủi ro.

Một thay đổi câu chữ không cần đầy đủ. Nhưng thay đổi xác thực, thanh toán, migration hoặc token thì không thể chỉ nhìn luồng thuận.

Ba là review test nghiêm túc như code chạy thật.

Agent viết test rất nhanh. Nó cũng có thể viết một test pass rất nhanh.

Mình kiểm tra test có thật sự đỏ nếu bỏ phần code vừa làm không. Điều kiện kết luận của test có chạm đúng hành vi không. Dữ liệu giả hoặc mock có che mất ranh giới tích hợp không. Agent có xoá điều kiện kiểm tra, nới cách so khớp hoặc cập nhật snapshot lớn chỉ để cả bộ test xanh không.

Test mới nên kể cùng một câu chuyện với tiêu chí hoàn thành. Nếu task yêu cầu hai lời mời trùng không tạo bản ghi mới nhưng test chỉ nhìn mã trạng thái, bằng chứng vẫn còn thiếu.

Bốn là xem tính nhất quán và độ phức tạp.

Sau khi cách hệ thống hoạt động đã ổn, mình mới nhìn sâu vào cách đặt tên, abstraction, comment và quy ước.

Agent thường có xu hướng tạo helper hoặc abstraction để diff trông gọn. Nhưng code mới không mặc định tốt hơn cách làm cũ của repository.

Mình hỏi:

  • Project đã có helper hoặc cách làm tương tự chưa?
  • Abstraction mới đang giải quyết yêu cầu hiện tại hay một tương lai tưởng tượng?
  • Comment có giải thích quyết định khó hiểu hay chỉ kể lại code?
  • Tài liệu hoặc sổ tay project có cần cập nhật vì cách hoạt động hoặc câu lệnh đã đổi không?

Google Engineering Practices cũng khuyên xem thiết kế, chức năng, độ phức tạp, test, cách đặt tên, comment, style và tài liệu trong bối cảnh của cả hệ thống. Với coding agent, danh sách đó vẫn giữ nguyên. Chỉ có tốc độ tạo diff tăng lên.

Kiểm tra từ nhanh tới gần trải nghiệm thật

Sau khi đọc diff, mình kiểm tra theo từng bậc.

Không phải lúc nào cũng cần chạy toàn bộ CI ở máy mình. Mình bắt đầu từ bước kiểm tra nhanh, gần vùng thay đổi, rồi mở rộng theo rủi ro.

Bậc 1: kiểm tra tĩnh có liên quan.

Cú pháp, format, lint, kiểm tra kiểu dữ liệu (typecheck) hoặc kiểm tra schema. Chúng bắt lỗi cơ học với chi phí thấp.

Bậc 2: test đúng vùng vừa sửa.

Chạy test gần module vừa sửa. Nếu task thay đổi cách hoạt động cũ, chạy thêm của luồng đó.

Bậc 3: trạng thái sau khi ghép.

Chạy test hoặc build trên trạng thái cuối sau khi tất cả phần đã được tích hợp. Đây là bậc rất dễ bị bỏ qua khi nhiều agent làm trên nhiều branch.

Bậc 4: hành vi thật.

Mở giao diện, gọi API, nhìn database, log, ảnh chụp hoặc đầu ra cuối. Chọn thứ gần nhất với kết quả mà người dùng sẽ trải nghiệm.

Một task backend không phải lúc nào cũng cần trình duyệt. Một task giao diện không phải lúc nào cũng cần cả bộ . Nhưng task người dùng trực tiếp chạm vào mà chỉ được kiểm tra bằng typecheck thì thường chưa đi đủ xa.

Các câu lệnh cụ thể phải lấy từ sổ tay project và repository hiện tại. Đừng để agent tự đoán npm test trong một project dùng bun, hoặc chạy cả bộ test bốn mươi phút khi đã có một câu lệnh gọn và đúng vùng hơn.

Ghi lại câu lệnh chính xác

Đừng chỉ ghi "test đã qua". Hãy ghi câu lệnh đã chạy, kết quả, phạm vi nó kiểm tra và thời điểm chạy trên trạng thái cuối. Không cần dán cả cuộn log nếu mã thoát cùng phần tóm tắt đã đủ.

Bắt agent tự soi bài trước khi mình review

Tự review không thay được một lượt review độc lập. Nhưng đây là cái lọc rẻ, bỏ qua thì hơi phí.

Sau khi làm xong, mình yêu cầu agent thực thi dừng sửa và viết báo cáo kiểm tra trước. Prompt có thể như vầy:

Plain Text

Điểm mình thích ở prompt này là agent không được vừa review vừa âm thầm sửa.

Nếu báo cáo phát hiện lỗi, mình mở một vòng sửa riêng. Sửa xong, agent phải chạy lại bước kiểm tra bị ảnh hưởng và cập nhật báo cáo theo trạng thái mới.

Báo cáo cuối có thể theo mẫu ngắn:

Plain Text

PASS, FAILNOT VERIFIED quan trọng hơn một đoạn văn nghe rất tự tin nhưng chẳng chứng minh được gì.

Quy trình làm, đóng băng trạng thái, review, sửa và kiểm tra lại trước khi hoàn thành
Mỗi lần sửa đều làm thay đổi trạng thái đã review. Vì vậy vòng lặp phải kết thúc bằng một lượt kiểm tra lại trên trạng thái cuối.

Khi nào nên dùng một agent khác để review

Chính agent vừa viết code vẫn có thể tự review khá tốt. Nó biết quyết định đã chọn và file nào liên quan.

Nhưng nó cũng mang theo những giả định cũ.

Một agent review khác hữu ích khi:

  • Diff đủ lớn để agent thực thi dễ bỏ sót chi tiết
  • Task liên quan xác thực, phân quyền, xử lý đồng thời, migration hoặc mất dữ liệu
  • Agent thực thi đã sửa cùng một lỗi nhiều lần
  • Có nhiều agent vừa gom kết quả vào cùng một trạng thái cuối
  • Test đã qua nhưng cách hệ thống hoạt động vẫn làm mình không chắc
  • Cần một góc nhìn chuyên môn như bảo mật, khả năng tiếp cận hoặc hiệu năng

Agent review nên bắt đầu ở chế độ chỉ đọc.

Mình không giao một prompt mơ hồ kiểu “review code giúp mình”. Nó cần task, tiêu chí hoàn thành, diff cuối, sổ tay project và phạm vi review.

Prompt có thể như sau:

Plain Text

Agent review không cần sửa ngay vì tìm vấn đề và sửa vấn đề là hai chế độ làm việc khác nhau.

Nếu agent review vừa thấy lỗi vừa tự thay code, agent thực thi có thể không còn biết quyết định nào đã đổi. Diff lại chạy tới chạy lui. Mình thích nhận danh sách vấn đề trước, phân loại, rồi mới giao phần sửa cho một người rõ ràng.

Một nhận xét cũng không tự đúng chỉ vì nó đến từ agent thứ hai.

Mình vẫn yêu cầu file, vị trí, bằng chứng và ảnh hưởng. Nếu agent review nói có race condition, nó cần chỉ ra trạng thái dùng chung và thứ tự chạy có thể gây lỗi. Nếu nói thiếu test, nó cần nói hành vi nào chưa được kiểm tra.

Sau khi agent thực thi sửa, agent review hoặc agent chính kiểm tra lại vấn đề trên diff cuối. Một lần đồng ý cũ không nên được giữ nguyên cho đoạn code đã thay đổi đáng kể.

Ví dụ review tính năng mời vào workspace

Quay lại tính năng mời vào workspace đã đi cùng series từ bài 04.

Giả sử agent thực thi vừa hoàn thành task “Admin tạo lời mời” và báo:

Plain Text

Phần tóm tắt này chưa sai. Nhưng nó chưa đủ để merge.

Mình mở lại tiêu chí hoàn thành và dựng bảng đối chiếu:

Tiêu chí hoàn thànhBằng chứng cần cóKết quả review
Chỉ admin của workspace được tạo lời mờiTest phân quyền và phản hồi APIThành viên thường nhận forbidden, không có bản ghi mới
Email đã là thành viên không tạo lời mờiTest service hoặc test tích hợpSố bản ghi trong database không đổi
Chỉ có một lời mời đang chờ cho cùng workspace và emailRàng buộc dữ liệu cùng test trùngHai yêu cầu không tạo hai bản ghi
Email được chuẩn hoá nhất quánTest chữ hoa và khoảng trắngCác chỗ tra cứu cùng dùng giá trị đã chuẩn hoá
Token thô không xuất hiện trong logReview diff và kiểm tra logChỉ giá trị đã băm hoặc che bớt được ghi
Email chỉ được đưa vào hàng đợi cho lời mời hợp lệTest tích hợp hoặc kiểm tra adapter giảKhông đưa vào hàng đợi khi transaction lỗi

Sau đó mình review file list.

Service, route, migration, email adapter và test đều có lý do hợp lý. Nhưng nếu diff còn đổi cấu hình package manager hoặc refactor toàn bộ module thành viên, đó là phần cần giải thích trước.

Khi xem cách hệ thống hoạt động, mình nhìn kỹ:

  • Việc kiểm tra quyền có dùng helper hiện tại không?
  • Email được chuẩn hoá trước hay sau khi kiểm tra trùng?
  • Database constraint có khớp với rule trong service không?
  • Hai yêu cầu đồng thời có thể cùng vượt qua bước kiểm tra rồi cùng ghi dữ liệu không?
  • Email được đưa vào hàng đợi trước hay sau khi transaction hoàn tất?
  • Error có làm lộ thông tin membership không?
  • Raw token có đi vào log, exception hoặc queue payload không?

Tiếp theo mới tới bước kiểm tra.

Mình chạy test đúng vào service và route. Sau đó chạy luồng tích hợp trên database thật của môi trường test. Nếu email dùng adapter giả, báo cáo phải nói rõ việc gửi thật vẫn chưa được kiểm tra.

Một báo cáo thật thà có thể kết thúc như sau:

Plain Text

NOT VERIFIED không tự động làm task thất bại.

Nó giúp người merge biết chính xác mình đang chấp nhận phần chưa chắc chắn nào.

Khi bước kiểm tra thất bại

Bước kiểm tra thất bại không có nghĩa phải bảo agent “sửa test đi” ngay.

Mình phân loại lỗi trước:

  1. Phần làm sai: code không đáp ứng cách hoạt động đã chốt.
  2. Task hoặc tiêu chí hoàn thành mơ hồ: code và test đang bám hai cách hiểu khác nhau.
  3. Test hoặc bộ khung test sai: bước kiểm tra không phản ánh yêu cầu, thiết lập thiếu hoặc fixture đã cũ.
  4. Môi trường sai: dependency, service, cổng, thông tin đăng nhập hoặc dữ liệu local làm kết quả không đáng tin.

Nếu phần làm sai, giao lại vấn đề cụ thể cùng bằng chứng.

Nếu yêu cầu mơ hồ, dừng code và đưa quyết định về cho người sở hữu. Đừng để agent tự chọn cách hoạt động chỉ để test xanh.

Nếu test sai, sửa test nhưng vẫn phải chứng minh phần code đúng bằng bằng chứng khác trong lúc test chưa đáng tin.

Nếu môi trường sai, ghi rõ chỗ đang chặn. Không đổi assertion hoặc bỏ bước kiểm tra chỉ để biến lỗi hạ tầng thành màu xanh.

Sau mỗi lần sửa, mình không chỉ chạy lại câu lệnh vừa lỗi. Mình chạy thêm regression test gần vùng bị ảnh hưởng, vì một chỗ sửa có thể làm đổi hành vi khác.

Workflow sẽ là:

Plain Text

Không có đường tắt từ Fix tới Done.

Checklist trước khi commit hoặc merge

Đây là checklist ngắn mình có thể dùng cho phần lớn task:

  • Task, tiêu chí hoàn thành và phần không làm vẫn là nguồn chuẩn hiện tại
  • git status và file list đã được kiểm tra
  • Mọi file thay đổi đều có lý do thuộc phạm vi
  • Dependency, lockfile, migration, file sinh tự động và snapshot đã được review có chủ đích
  • API công khai, phân quyền, cách dữ liệu hoạt động và luồng lỗi không đổi ngoài dự kiến
  • Test mới thật sự kiểm tra hành vi, không chỉ làm cả bộ test xanh
  • Không có test hoặc assertion cũ bị nới lỏng mà chưa giải thích
  • Mỗi tiêu chí hoàn thành có bằng chứng hoặc được đánh dấu NOT VERIFIED
  • Câu lệnh kiểm tra chạy trên trạng thái cuối sau lần sửa cuối
  • Hành vi người dùng nhìn thấy đã được kiểm tra ở mức phù hợp
  • Secret, token và dữ liệu nhạy cảm không đi vào code, log hoặc đầu ra
  • Rủi ro còn lại và phần chưa kiểm tra đã được ghi rõ
  • Nhận xét quan trọng từ lượt review độc lập đã được phân loại và kiểm tra lại

Không phải task nào cũng cần tất cả các dòng.

Nhưng nếu task liên quan dữ liệu thật, xác thực hoặc thanh toán mà mình bỏ qua nửa danh sách, đó không còn là quy trình gọn nữa. Đó là đang đánh cược.

Với Knowns, kết quả review không nên biến mất trong chat

Khi dùng Knowns, mình giữ tiêu chí hoàn thành và phạm vi trong task thay vì dán lại qua nhiều session.

Agent thực thi có thể ghi câu lệnh đã chạy, bằng chứng và rủi ro vào ghi chú task. Agent review trả nhận xét kèm file và vị trí. Agent chính chỉ đánh dấu tiêu chí hoàn thành sau khi vấn đề quan trọng đã được xử lý và lượt kiểm tra cuối đã qua.

Task vì vậy không chuyển từ in-progress sang done chỉ vì agent thực thi gửi lời nhắn cuối.

Nó đi qua một trạng thái review có bằng chứng.

Điểm mình thích ở cách này là session sau vẫn biết vì sao task được xem là hoàn thành. Không cần tin vào ký ức của một đoạn chat đã rút gọn hoặc câu “ổn hết rồi” đã rơi mất ngữ cảnh.

Knowns không tự review code thay mình.

Nó chỉ giữ thoả thuận và dấu vết công việc để kết quả review không biến mất khi agent hoặc session thay đổi.

Kết

Coding agent nói done không phải chuyện xấu.

Đó là tín hiệu agent đã sẵn sàng đưa bài cho người review, không phải lời tuyên bố vụ án đã khép lại.

Từ đó, mình cần một vòng lặp rõ:

  • Đóng băng trạng thái
  • Mở lại task và tiêu chí hoàn thành
  • Kiểm tra phạm vi trước khi đọc chi tiết
  • Review cách hoạt động, test và tính nhất quán
  • Chạy kiểm tra theo rủi ro
  • Ghi bằng chứng, rủi ro và phần chưa kiểm tra
  • Sửa trong phạm vi rồi kiểm tra lại trạng thái cuối

Mình không cần đọc code với tâm thế agent chắc chắn đã làm sai.

Mình chỉ không muốn độ tự tin của mình phụ thuộc vào độ trôi chảy của lời nhắn cuối.

Khi done dẫn tới một diff đã hiểu, một bảng có đủ bằng chứng và một trạng thái cuối đã được kiểm tra, lúc đó commit hoặc merge mới thật sự là bước cuối thay vì một cú nhắm mắt.

See yah.

Tài liệu tham khảo