Giữ Git History “Sạch Bong Kin Kít” Cho Developer

5 min read

Trong quá trình làm việc nhóm tại các dự án của NCC, chắc hẳn không ít lần bạn mở Git Graph ra và đối mặt với một “mạng nhện” đúng nghĩa: các nhánh đan chéo vào nhau vô tội vạ, kèm theo hàng chục commit tự động có nội dung kiểu Merge branch 'develop' into feature/....

Lịch sử commit (Git History) rối rắm này không chỉ làm giảm tính thẩm mỹ của dự án mà còn khiến việc tracking bug, git blame hay rollback code trở thành một cực hình. Tương tự như việc dọn dẹp mã nguồn “bốc mùi” bằng các design pattern (như cách chúng ta ứng dụng Strategy Pattern để tối ưu hóa code), việc giữ cho lịch sử Git gọn gàng cũng là một kỹ năng bắt buộc của một developer chuyên nghiệp.

Để giải quyết triệt để bài toán này, Git Rebase chính là vị cứu tinh. Bài viết này sẽ giúp bạn làm chủ Git Rebase và tự tin áp dụng vào workflow hằng ngày.

Bản Chất: Git Merge và Git Rebase Khác Nhau Như Thế Nào?

Để tích hợp các thay đổi từ nhánh này (ví dụ: develop) vào nhánh tính năng của bạn (feature), Git cung cấp hai vũ khí chính: MergeRebase. Mục đích cuối cùng của chúng là giống nhau, nhưng cách thức hoạt động thì hoàn toàn khác biệt.

1. Git Merge (Hợp nhất)

Khi bạn chạy lệnh git merge develop, Git sẽ lấy commit mới nhất của hai nhánh và tạo ra một commit hợp nhất mới (gọi là Merge Commit).

  • Ưu điểm: An toàn, không thay đổi các commit cũ trong lịch sử.
  • Nhược điểm: Làm xuất hiện rất nhiều “commit rác” (Merge commits). Lịch sử Git sẽ bị chia nhánh và đan xen chằng chịt nếu dự án có nhiều người cùng code.

2. Git Rebase (Tái định cơ sở)

Thay vì tạo commit hợp nhất, git rebase develop sẽ tạm thời “nhấc” toàn bộ các commit mới trên nhánh feature của bạn ra, cập nhật gốc (base) của nhánh feature thành commit mới nhất của develop, sau đó “đặt” lại các commit của bạn lên trên cùng. Bạn có thể tra cứu sâu hơn về cơ chế này tại tài liệu chính thức của Git SCM về Rebase.

Tiêu chíGit MergeGit Rebase
Cơ chế hoạt độngTạo ra một commit mới để nối 2 nhánh lại.Di chuyển toàn bộ nhánh feature lên đầu nhánh gốc.
Git HistoryDạng cây (Non-linear), giữ nguyên dòng thời gian thực tế.Dạng đường thẳng (Linear), siêu sạch và dễ đọc.
Commit IDGiữ nguyên ID của các commit cũ.Thay đổi hoàn toàn ID của các commit được rebase (tạo ra các commit mới).

Quy Trình Áp Dụng Git Rebase Thực Chiến Trong Dự Án

Hãy tưởng tượng bạn đang code tính năng đăng nhập trên nhánh feature/login, cùng lúc đó nhánh develop của team đã có thêm 3 commit mới từ các thành viên khác. Để cập nhật code mới nhất từ develop về nhánh của mình một cách sạch sẽ, hãy làm theo các bước sau:

Bước 1: Cập nhật nhánh develop ở máy local

Trước khi rebase, hãy chắc chắn rằng nhánh develop của bạn là mới nhất.

Bash

git checkout develop
git pull origin develop

Bước 2: Chuyển về nhánh feature và tiến hành Rebase

Bash

git checkout feature/login
git rebase develop

Lúc này, Git sẽ bắt đầu tua lại lịch sử và áp từng commit của bạn lên trên đầu của develop.

Bước 3: Đẩy code lên Remote Server (Lưu ý quan trọng)

Vì Rebase làm thay đổi ID của các commit cũ, lịch sử code ở Local của bạn hiện tại đã khác hoàn toàn với nhánh feature/login đang có trên GitHub/GitLab. Nếu bạn dùng git push thông thường, Git sẽ từ chối.

Bạn bắt buộc phải sử dụng quyền “ép buộc” nhưng hãy dùng một cách an toàn bằng lệnh:

Bash

git push origin feature/login --force-with-lease

Mẹo nâng cao: Luôn dùng --force-with-lease thay vì -f (force). Lệnh này sẽ ngăn chặn việc ghi đè nếu có một thành viên khác trong team vô tình push code mới lên nhánh feature đó mà bạn chưa kịp pull về.

“Hố Tử Thần”: Cách Xử Lý Conflict Khi Rebase

Nhiều developer sợ Rebase vì sợ đối mặt với Conflict (xung đột code). Khi Merge, bạn chỉ phải giải quyết conflict 1 lần duy nhất ở commit cuối cùng. Nhưng khi Rebase, bạn có thể phải giải quyết conflict theo từng commit một.

Đừng hoảng sợ, quy trình xử lý cực kỳ tuần tự như sau:

  1. Khi lệnh git rebase dừng lại và báo Conflict, hãy mở IDE (VS Code, WebStorm…) lên và sửa các file bị xung đột như bình thường.
  2. Sau khi sửa xong, gõ lệnh đánh dấu đã xử lý:

git add <tên_file_hết_conflict>

3. **Tuyệt đối KHÔNG gõ `git commit`**. Thay vào đó, hãy bảo Git tiếp tục quá trình rebase bằng lệnh:
   ```bash
git rebase --continue
  1. Nếu còn commit tiếp theo bị conflict, lặp lại bước 1 và 2. Nếu muốn huỷ bỏ toàn bộ quá trình rebase và quay về trạng thái ban đầu, hãy gõ: git rebase --abort.

Nguyên Tắc Vàng: Khi Nào KHÔNG Nên Dùng Git Rebase?

Dù Git Rebase rất tuyệt vời, việc lạm dụng nó có thể phá hủy mã nguồn của cả team. Hãy khắc cốt ghi tâm câu khẩu hiệu sau:

“Không bao giờ Rebase các commit đã được push lên một Public Branch (nhánh chung như main, develop, staging).”

Nếu bạn rebase nhánh develop, bạn đang thay đổi lịch sử code của tất cả mọi người trong công ty. Khi các thành viên khác pull về, hệ thống Git của họ sẽ bị loạn, dẫn đến xung đột diện rộng cực kỳ khủng khiếp.

Tóm lại:

  • NÊN DÙNG REBASE: Trên nhánh cá nhân của bạn (feature/*, bugfix/*) trước khi tạo Pull Request để làm sạch lịch sử trước khi merge vào nhánh chung.
  • NÊN DÙNG MERGE: Khi cần gộp nhánh chung lớn vào nhánh chung lớn khác (ví dụ merge develop vào main).

Kết Luận và Takeaway

Làm chủ Git Rebase là một cột mốc quan trọng đánh dấu sự trưởng thành về kỹ năng làm việc nhóm của một phần mềm kỹ sư. Nó giúp bạn quản lý code chuyên nghiệp hơn, code review dễ dàng hơn và giữ cho kho lưu trữ của dự án tại NCC luôn ở trạng thái hoàn hảo nhất.

Takeaway: Trước khi tạo Pull Request (PR) cho Tech Lead review, hãy tạo thói quen git rebase develop ở local để tự tay giải quyết hết conflict và “làm mịn” các commit của mình trước nhé!

Avatar photo

Leave a Reply

Your email address will not be published. Required fields are marked *