CodeGym /Các khóa học /JAVA 25 SELF /Thử nghiệm an toàn: làm việc với các nhánh

Thử nghiệm an toàn: làm việc với các nhánh

JAVA 25 SELF
Mức độ , Bài học
Có sẵn

1. Nhánh là gì và chúng dùng để làm gì?

Làm việc với branches trong Git — là một trong những khía cạnh then chốt của quản lý phiên bản, cho phép song song phát triển nhiều dòng trong cùng một kho (repository). Việc tạo nhánh khiến Git trở thành công cụ mạnh mẽ cho hợp tác, thử nghiệm và quản lý các phiên bản khác nhau của dự án.

            gitGraph
            commit id: "Initial setup"
            commit id: "Add base features"
            branch feature/new-idea
            checkout feature/new-idea
            commit id: "Implement new logic"
            commit id: "Refactor the logic"
            checkout main
            commit id: "Urgent bugfix on main"
            merge feature/new-idea
            commit id: "Prepare for release"
        
Từ nhánh chính main tách ra một nhánh mới, feature/new-idea, để phát triển an toàn. Sau khi hoàn thành, nó được gộp trở lại vào main.

Hãy tưởng tượng bạn muốn chỉnh sửa lớn trong dự án của mình hoặc thực hiện một thử nghiệm rủi ro. Nếu không có Git, bạn sẽ làm gì? Rất có thể bạn sẽ sao chép toàn bộ dự án vào một thư mục mới và làm việc ở đó. Nếu kết quả ổn — bạn sẽ chuyển nó vào thư mục chính. Nếu không — chỉ cần xóa bản sao.

Các nhánh trong Git hoạt động theo cùng nguyên tắc, nhưng tinh gọn hơn nhiều. Hãy xem ví dụ viết sách:

  1. Bạn có một bản thảo đã sẵn sàng (đó là nhánh chính của bạn main).
  2. Bạn muốn viết một cái kết thay thế (tạo một nhánh mới, ví dụ feature/new-idea).
  3. Bạn viết cái kết mới mà không ảnh hưởng đến phần văn bản chính của bản thảo (làm việc trong nhánh mới).
  4. Nếu cái kết mới tốt hơn, bạn thay thế cái cũ bằng nó (thực hiện gộp nhánh — merge).
  5. Bản nháp cũ với cái kết không cần thiết có thể xóa (xóa nhánh).

2. Tạo nhánh mới và làm việc trong đó

Bước 1. Mở menu quản lý nhánh.

Trên thanh trên của IDE có một widget hiển thị tên nhánh hiện tại (mặc định — main). Nhấp vào nó và chọn + New Branch.

Bước 2. Tên nhánh mới.

Một thực hành tốt — đặt tên nhánh theo nhiệm vụ bạn đang giải quyết. Ví dụ, feature/add-usage-examples.

Sau khi tạo nhánh, IDE sẽ tự động chuyển sang nhánh đó. Bạn sẽ thấy tên mới trong cùng widget.

Bước 3. Thực hiện và commit thay đổi.

Bây giờ bạn đang ở “sandbox” của mình. Hãy thêm vào tệp README.md một phần mới với ví dụ sử dụng. Thực hiện thay đổi và tạo commit, như bạn đã học trong bài trước.

3. Chuyển đổi giữa các nhánh

Các thay đổi với phần ví dụ sử dụng của bạn hiện đã được lưu an toàn trong nhánh feature/add-usage-examples. Hãy quay lại nhánh chính main và xem có gì ở đó.

Bước 1. Nhấp lại vào widget hiển thị tên nhánh hiện tại.

Bước 2. Trong danh sách Local hoặc Recent, chọn nhánh main, và trong menu xuất hiện hãy nhấn Checkout.

Bước 3. Kiểm tra kết quả.

Ngay khi chuyển nhánh, hãy mở tệp README.md. Bạn sẽ thấy phần ví dụ sử dụng không có ở đây! Nó vẫn ở nhánh khác. Nhờ vậy, bạn có thể phát triển chức năng mới mà không ảnh hưởng đến phiên bản ổn định trong nhánh main.

4. Gộp nhánh (Merge)

Lệnh merge lấy tất cả các commit từ nhánh feature/add-examples (trong trường hợp này, commit C3) và hợp nhất chúng với nhánh hiện tại main, tạo ra một commit gộp mới.

            gitGraph
            commit id: "C1"
            commit id: "C2"
            branch feature/add-examples
            checkout feature/add-examples
            commit id: "C3: Add new section"
            checkout main
            merge feature/add-examples
        

Vậy là bạn đã hoàn thành công việc trong nhánh feature/add-usage-examples và muốn đưa các thay đổi đó vào dự án chính.

Bước 1. Chuyển sang nhánh đích.

Hãy chắc chắn rằng bạn đang ở nhánh NƠI bạn muốn thêm thay đổi. Trong ví dụ của chúng ta là main.

Bước 2. Thực hiện gộp.

Nhấn lại vào widget quản lý nhánh. Trong danh sách, chọn nhánh TỪ ĐÓ bạn muốn lấy thay đổi (feature/add-usage-examples), và trong menu con chọn Merge feature/add-usage-examples vào main.

Bước 3. Kiểm tra kết quả.

Bây giờ trong tệp README.md ở nhánh main đã xuất hiện phần mới với các ví dụ của bạn. Bạn đã gộp thành công công việc của mình vào phiên bản chính của dự án!

5. Xung đột khi gộp: đừng lo, điều đó là bình thường!

Đôi khi khi gộp nhánh sẽ xuất hiện xung đột. Điều này xảy ra khi ở cả hai nhánh đều sửa các dòng giống nhau trong cùng một tệp. Git không thể tự quyết định phiên bản nào đúng, và sẽ yêu cầu bạn hỗ trợ.

            gitGraph
            commit id: "C1: Nền tảng chung"
            branch feature/new-title
            checkout main
            commit id: "C2: Thay đổi ở main"
            checkout feature/new-title
            commit id: "C3: Thay đổi ở feature"
        
Cả hai nhánh, mainfeature/new-title, đều có các commit mới (C2 và C3), dựa trên tổ tiên chung (C1). Điều này chắc chắn dẫn đến xung đột khi gộp.

Hãy mô phỏng xung đột:

  1. Đảm bảo bạn đang ở nhánh main và không có thay đổi chưa lưu.
  2. Tạo ngay một nhánh mới feature/new-title, nhưng chưa chuyển sang nhánh đó. Đảm bảo bỏ chọn Checkout branch.
  3. Bây giờ, khi đang ở nhánh main, hãy đổi dòng đầu tiên trong README.md thành "My Awesome Project" và tạo commit.
  4. Chuyển sang nhánh feature/new-title. Bạn sẽ thấy dòng đầu tiên trong README.md ở đây vẫn là bản cũ: đó là trạng thái tệp tại thời điểm tạo nhánh. Hãy đổi chính dòng này thành "My Super Project" và tạo commit.
  5. Quay lại nhánh main và gộp với feature/new-title.

Bây giờ Git sẽ thấy rằng cả hai nhánh đều có lịch sử mới, tách ra từ tổ tiên chung của chúng. Ở cả hai lịch sử, cùng một dòng đã bị thay đổi, vì vậy Git không thể chọn phiên bản nào đúng và sẽ hiển thị cửa sổ để bạn giải quyết xung đột.

Merge Revision

Bạn thấy gì ở đây:

  • Bên trái (Your changes): phiên bản tệp từ nhánh hiện tại của bạn (main).
  • Bên phải (Changes from branch...): phiên bản tệp từ nhánh bạn đang gộp vào.
  • Ở giữa (Result): phiên bản cuối cùng của tệp mà bạn cần tổng hợp.

Bạn có thể nhấn vào các mũi tên >> hoặc << để chấp nhận toàn bộ một phương án.

Khi kết quả ở bảng trung tâm khiến bạn hài lòng, hãy nhấn Apply. IDE sẽ tự tạo commit gộp, và xung đột sẽ được giải quyết.

Vì sao không xuất hiện xung đột?

Có thể xảy ra tình huống bạn đã làm đủ các bước mà không có xung đột. Thường là do Git có thể thực hiện fast-forward merge, vì lịch sử của một nhánh chỉ đơn giản là tiếp nối lịch sử của nhánh kia. Để đảm bảo có xung đột, lịch sử các nhánh phải tách ra theo những hướng khác nhau từ tổ tiên chung.

Ví dụ:

  1. Bạn có một commit nào đó trong main (giả sử C1).
  2. Bạn tạo một commit mới trong main với nội dung "My Awesome Project". Nhánh main giờ trỏ tới commit C2 (main -> C1 -> C2).
  3. Bạn tạo nhánh feature/new-title từ vị trí hiện tại của nhánh main. Điều này có nghĩa nhánh mới cũng bắt đầu từ commit C2.
  4. Bạn tạo commit trong feature/new-title với nội dung "My Super Project". Nhánh này “tiến lên phía trước” và giờ trỏ tới commit C3 (feature/new-title -> C1 -> C2 -> C3).
  5. Bạn quay lại main (vẫn đang ở commit C2) và ra lệnh gộp feature/new-title.

Git quan sát tình huống và thấy rằng nhánh main là tổ tiên trực tiếp của nhánh feature/new-title. Trong lịch sử của main không có commit mới nào khi bạn làm việc ở nhánh kia. Git nghĩ: “À, vậy chỉ cần tua main tiến lên tới commit C3. Không có mâu thuẫn nào cả”. Và nó chỉ việc di chuyển con trỏ main tới commit C3.

            gitGraph
            commit id: "C1"
            commit id: "C2"
            branch feature/new-title
            checkout feature/new-title
            commit id: "C3"
            checkout main
            merge feature/new-title
        

6. Xem lịch sử thay đổi

Để hiểu rõ hơn điều gì đang xảy ra trong dự án của bạn, thật hữu ích khi xem lịch sử của nó.

Mở thẻ Git ở phần dưới của IDE và chọn Log. Bạn sẽ thấy biểu diễn trực quan tất cả các nhánh và commit của mình. Điều này giúp bạn theo dõi rõ ràng nhánh nào tách ra từ đâu và chúng được gộp ở đâu.

Tại đây bạn có thể nhấp vào bất kỳ commit nào để xem những thay đổi được đưa vào, ai và khi nào đã thực hiện. Đây thực sự là cỗ máy thời gian cho mã nguồn!

Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION