Làm sao giữ Git Diff nhỏ khi dùng AI Coding?
Nếu bạn đã từng dùng AI coding trong dự án thật, có một hiện tượng rất quen thuộc và cũng rất dễ làm reviewer nhăn mặt. Bạn chỉ muốn sửa một feature nhỏ. AI thì nhiệt tình quá mức. Nó sửa luôn controller, service, validation, DTO, test, một ít helper, đôi khi bonus thêm vài chỗ rename cho “đồng bộ”. Kết quả là pull request dài 500 dòng chỉ để thêm một endpoint.
Git diff khổng lồ không chỉ gây khó chịu theo kiểu mỹ học lập trình. Nó làm code review khó hơn, rollback khó hơn, bug dễ lọt hơn và toàn bộ pipeline phát triển chậm lại theo một cách khá âm thầm. Mà cái gì âm thầm thì thường nguy hiểm, vì team rất dễ quen dần với nó như thể đó là định mệnh.
Cho nên câu hỏi rất thực tế là: làm sao giữ git diff nhỏ khi vẫn tận dụng được AI coding? Tin vui là có cách. Tin kém vui là nó đòi hỏi kỷ luật workflow, chứ không chỉ thêm câu “please keep it minimal” vào prompt rồi cầu nguyện.
Vì sao AI thường tạo Git Diff lớn?
Trước khi nói về giải pháp, cần hiểu nguyên nhân. Nếu không hiểu cơ chế, team rất dễ vá phần ngọn rồi vài tuần sau đâu lại vào đấy.
1. AI không biết phần nào là “quan trọng nhất” theo ngữ cảnh team
AI nhìn vào context của code và cố tạo ra lời giải có vẻ hợp lý nhất về mặt cục bộ. Nếu nó thấy đổi thêm vài tên biến sẽ “đẹp hơn”, nó đổi. Nếu thấy tách thêm một helper sẽ “sạch hơn”, nó tách. Nếu thấy test cũ trông chưa đồng đều, nó chỉnh luôn. Với AI, đây là một dạng tối ưu hóa tự nhiên. Với production team, đây là mở rộng phạm vi thay đổi ngoài dự kiến.
Điểm mấu chốt là: AI không tự biết phần nào thật sự quan trọng với ticket hiện tại và phần nào nên để yên cho reviewer đỡ khổ. Nếu không có ràng buộc rõ, nó sẽ tiếp tục rất chăm chỉ theo cách khiến người review mất ngủ.
2. AI thích refactor khi thấy cơ hội
Khi AI thấy code có thể “cải thiện”, nó thường tiện tay refactor luôn. Điều này nghe có vẻ tốt, nhưng refactor và feature là hai loại thay đổi nên được tách riêng trong workflow lành mạnh. Trộn chúng vào cùng một PR là cách nhanh nhất để biến một thay đổi rõ ràng thành một cuộc điều tra hiện trường.
Nói vui một chút, AI hơi giống một đồng nghiệp rất nhiệt tình: nhờ sửa bóng đèn thì tiện tay sơn lại tường và dời luôn cái tủ cho hợp phong thủy. Có tâm đấy. Nhưng chưa chắc hợp việc.
3. Context càng lớn, diff càng dễ lan rộng
Khi repository lớn, AI phải đọc nhiều file hơn và suy luận trên nhiều ngữ cảnh hơn. Điều đó đồng nghĩa với việc nó nhìn thấy nhiều cơ hội để sửa thêm hơn. Chỉ cần một yêu cầu nhỏ chạm vào vùng có nhiều phụ thuộc, AI rất dễ mở rộng thay đổi ra xa hơn phạm vi thực tế mà ticket cần.
Đó là lý do ở các codebase production, cùng một kiểu prompt nhưng repo càng lớn thì diff càng có xu hướng phình. Không phải AI dở đi. Chỉ là bài toán phức tạp hơn và không có lan can thì nó sẽ chạy rộng hơn.
Tại sao Git diff lớn nguy hiểm đến vậy?
Nhiều người nghĩ diff lớn chỉ là chuyện “đọc lâu hơn một chút”. Thực tế nó đắt hơn nhiều.
- Reviewer khó nhìn ra thay đổi cốt lõi của business logic
- Bug dễ lọt hơn vì con người có giới hạn tập trung
- Rollback khó hơn vì commit chứa quá nhiều thay đổi trộn lẫn
- Diff lớn làm team mất dần kỷ luật giữ PR nhỏ và rõ
- Lịch sử repository ngày càng khó đọc lại sau này
Nếu review là tuyến phòng thủ cuối cùng, thì diff lớn chính là cách làm tuyến phòng thủ đó kiệt sức nhanh nhất. Và production thường tận dụng rất tốt những lúc con người mệt.
Nguyên tắc giữ Git Diff nhỏ khi dùng AI Coding
Có một vài nguyên tắc nghe đơn giản nhưng hiệu quả rất cao nếu team làm thật.
1. Tách feature thành thay đổi nhỏ
Thay vì bảo AI tạo một feature lớn từ A đến Z, hãy chia feature thành các bước nhỏ hơn. Ví dụ:
- tạo schema hoặc model
- tạo endpoint
- thêm validation
- bổ sung test
Mỗi thay đổi nhỏ tạo ra một diff nhỏ hơn, dễ review hơn và dễ rollback hơn. Đây là nguyên tắc quan trọng nhất, vì nó không chỉ giúp AI. Nó giúp cả workflow kỹ thuật khỏe hơn.
2. Cấm trộn feature và refactor trong cùng pull request
Nếu cần refactor, hãy làm trong PR riêng. Nếu cần chỉnh naming hoặc dọn code, hãy làm ở nhánh riêng. Feature và refactor trộn lẫn là combo rất dễ khiến reviewer bỏ sót phần quan trọng nhất. Đặc biệt khi AI tham gia, vì nó vốn đã có xu hướng làm nhiều hơn yêu cầu.
Một nguyên tắc rất hữu ích là: nếu thay đổi đó không cần để feature chạy đúng, hãy đẩy nó sang PR khác.
3. Prompt phải bó phạm vi thay đổi thật rõ
Nhiều team viết prompt kiểu “thêm endpoint create user và cập nhật code liên quan”. Câu này với AI nghe như lời mời buffet. Nếu muốn diff nhỏ, prompt nên rõ hơn nhiều:
- chỉ sửa trong module cụ thể
- không refactor file ngoài phạm vi
- giữ nguyên naming hiện tại trừ khi bắt buộc
- không thay đổi test cũ nếu không cần
AI không tự biết ranh giới nếu team không vẽ ranh giới.
4. Giữ cấu trúc code ổn định và dễ đoán
Khi cấu trúc code rõ ràng, AI ít có xu hướng thay đổi nhiều file hơn. Nếu project có convention tốt, layering rõ, boundary rõ, các thay đổi cũng dễ khu trú hơn. Nói cách khác, git diff nhỏ không chỉ là thành quả của prompt tốt. Nó còn là thành quả của kiến trúc đủ rõ để AI không phải đoán nhiều.
5. Review ở mức “vì sao thay đổi” chứ không chỉ “đã thay đổi gì”
Một team muốn giữ diff nhỏ lâu dài phải tạo được văn hóa review phản hồi vào phạm vi thay đổi. Nếu reviewer liên tục chấp nhận các PR quá rộng, AI và người dùng AI sẽ học rằng chuyện đó bình thường. Ngược lại, nếu reviewer thường xuyên hỏi “phần này có cần cho ticket không?”, chất lượng phạm vi thay đổi sẽ tăng lên rất nhanh.
Một cách tiếp cận khác: đừng để AI sửa code trực tiếp
Nhiều team đi xa hơn một bước và chọn cách không để AI sửa code trực tiếp trong repository production. Thay vào đó:
- AI giúp viết contract
- compiler sinh code từ contract
Khi contract thay đổi, code được sinh lại theo cấu trúc ổn định. Điều này làm git diff rõ ràng hơn rất nhiều, vì thay đổi cốt lõi nằm ở lớp mô tả hệ thống thay vì lan ra hàng loạt file implementation.
Ví dụ, nếu contract mô tả API:
endpoint: createUser method: POST path: /users
Nếu API thay đổi, developer chỉ cần sửa contract. Code backend được sinh lại theo rule có sẵn. Diff lúc này thường tập trung ở contract và những phần thật sự đổi, thay vì thành một festival của controller, DTO và validation cùng nhảy múa.
Một checklist thực tế để giữ diff nhỏ
- Feature hiện tại có thể chia thành 2-3 PR nhỏ hơn không?
- Có đang trộn refactor với business logic không?
- Prompt đã nói rõ phạm vi file hoặc module chưa?
- Có phần nào AI sửa thêm nhưng không bắt buộc cho ticket không?
- Nếu rollback, team có biết chính xác phần nào cần rollback không?
Nếu mấy câu hỏi này không trả lời được rõ ràng, khả năng cao diff vẫn đang quá rộng.
Kết luận
Git diff lớn là một trong những vấn đề phổ biến và tốn kém nhất khi dùng AI coding. Nhưng nó không phải số phận bắt buộc. Với workflow phù hợp, team hoàn toàn có thể giữ diff nhỏ hơn, rõ hơn và dễ review hơn.
Nguyên tắc quan trọng nhất vẫn là:
giữ thay đổi nhỏ và rõ ràng.
Khi AI được dùng đúng cách, nó vẫn có thể tăng tốc phát triển mà không làm codebase thành bãi chiến trường.
Một ví dụ rất đời về diff nhỏ và diff to
Giả sử ticket của bạn là thêm field phone_number vào API tạo người dùng. Một diff nhỏ, khỏe mạnh thường sẽ gồm:
- cập nhật request schema hoặc contract
- thêm rule validation liên quan
- chỉnh đúng một đoạn mapping cần thiết
- thêm test cho field mới
Một diff to, mệt mỏi thường gồm thêm vài món khuyến mãi như:
- rename hàng loạt biến cho “đồng bộ hơn”
- tách helper mới vì AI thấy có thể tái sử dụng
- đổi format error ở vài chỗ không liên quan
- dọn test cũ vì “tiện thì sửa luôn”
Về mặt cảm xúc, diff thứ hai có thể khiến người tạo thấy mình làm được nhiều việc. Về mặt engineering, nó khiến reviewer phải bỏ nhiều năng lượng hơn để tìm phần thay đổi thực sự có ý nghĩa với ticket. Tức là công sức review bị chuyển từ “xác minh business logic” sang “lọc nhiễu”. Đó là một thương vụ rất dở.
Prompt tốt để giữ diff nhỏ thường trông như thế nào?
Nhiều team chỉ nói với AI là “hãy giữ thay đổi tối thiểu”. Câu này có thiện chí nhưng hơi chung chung. Một prompt tốt để giữ git diff nhỏ nên có ít nhất bốn ý rõ ràng:
- nêu chính xác mục tiêu business
- giới hạn module hoặc file được phép đụng vào
- cấm refactor ngoài phạm vi
- yêu cầu liệt kê file dự kiến thay đổi trước khi sửa
Ví dụ thay vì viết:
Thêm endpoint create user và cập nhật các phần liên quan.
Bạn nên viết rõ hơn:
Thêm field
phone_numbercho endpoint create user. Chỉ sửa module user, không refactor file ngoài phạm vi, không đổi naming cũ, không chỉnh test cũ nếu không bắt buộc. Hãy liệt kê file sẽ sửa trước.
Nghe kém thơ hơn, nhưng repo production không cần thơ. Repo production cần người review không bị đau đầu.
Code review nên phản ứng thế nào với diff quá lớn?
Nếu reviewer chỉ lặng lẽ merge những PR rộng bất thường, team sẽ dạy cho cả con người lẫn AI rằng việc đó là bình thường. Muốn giữ diff nhỏ bền vững, review phải phản hồi vào phạm vi thay đổi, không chỉ vào chất lượng từng dòng code.
Một vài câu hỏi reviewer nên hỏi rất thường xuyên:
- Phần nào trong diff là bắt buộc để ticket này chạy đúng?
- Phần nào là refactor nên tách sang PR riêng?
- Nếu rollback, team có rollback được riêng business change không?
- Diff này có thể tách thành 2-3 PR nhỏ hơn không?
Đây không phải kiểu “khó tính cho vui”. Đây là cơ chế bảo vệ tốc độ dài hạn. Vì diff nhỏ không chỉ giúp reviewer hôm nay, nó còn giúp người đọc lịch sử repo sáu tháng sau đỡ chửi thầm.
Kiến trúc tốt giúp diff nhỏ tự nhiên hơn
Nhiều người xem git diff lớn là vấn đề prompt. Thật ra nó còn là vấn đề kiến trúc. Nếu boundary giữa module rõ, controller không chứa business logic, schema tách bạch, shared abstraction đủ hợp lý, thì thay đổi sẽ tự nhiên được khu trú. Ngược lại, nếu codebase đã rối sẵn, AI chỉ cần chạm vào một điểm là hiệu ứng domino bắt đầu.
Bởi vậy, giữ git diff nhỏ không chỉ là kỹ thuật nói chuyện với AI. Nó còn là kỹ thuật tổ chức code sao cho mỗi thay đổi có chỗ đứng rõ ràng. Kiến trúc càng rõ, AI càng ít phải đoán. AI càng ít phải đoán, diff càng ít lan.
Khi nào nên chuyển từ prompt tối giản sang contract?
Nếu team liên tục gặp các dấu hiệu sau, có lẽ đã đến lúc chuyển một phần workflow sang contract coding:
- cùng một loại endpoint nhưng PR nào cũng phình to
- phần lớn diff nằm ở boilerplate
- review thường xuyên hỏi “sao sửa cả chỗ này?”
- AI hay tiện tay refactor nhiều lớp cùng lúc
- rollback khó vì implementation change lẫn với structural change
Contract giúp khóa phạm vi thay đổi vào tầng mô tả hệ thống. Khi contract đổi, generated code đổi theo quy tắc. Điều này không làm mất hết diff, nhưng làm diff có cấu trúc hơn rất nhiều. Và trong review, có cấu trúc gần như luôn đồng nghĩa với ít đau đầu hơn.
Kết luận
Giữ git diff nhỏ khi dùng AI coding không phải chuyện trang trí quy trình. Nó là điều kiện để code review còn hiệu quả, rollback còn khả thi và repo còn giữ được sự tin cậy. Muốn làm được điều đó, team cần chia nhỏ task, tách refactor khỏi feature, viết prompt bó phạm vi thật rõ, dùng review để kiểm soát độ rộng của thay đổi và khi cần thì đẩy phần lặp sang contract/generator.
Nói ngắn gọn, đừng chỉ hỏi AI có thể sửa nhanh cỡ nào. Hãy hỏi repo của bạn có hấp thụ nổi kiểu thay đổi đó không. Nếu câu trả lời chưa chắc, thì giữ diff nhỏ chính là cách thông minh nhất để đi nhanh mà không lao thẳng xuống ruộng.