CodeGym /Các khóa học /C# 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

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

1. Nhánh là gì và tại sao cần chúng?

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 duy trì nhiều dòng phát triển song song trong cùng một repository. Branching làm cho Git trở thành một công cụ mạnh mẽ cho cộng 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 công việc nó được merge lại vào main.

Hãy tưởng tượng bạn muốn chỉnh sửa lớn trong dự án 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 thế nào? Có lẽ sẽ copy toàn bộ dự án vào thư mục mới và làm việc ở đó. Nếu kết quả tốt — chuyển vào thư mục chính. Nếu không — xóa bản copy.

Nhánh trong Git hoạt động theo cùng nguyên lý đó nhưng thanh lịch hơn nhiều. Hãy xem ví dụ viết một cuốn sách:

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

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

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

Ở thanh trên cùng của IDE có 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.

Tốt nhất là đặt tên nhánh theo nhiệm vụ bạn làm. 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 ở cùng widget.

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

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

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

Các thay đổi với ví dụ sử dụng giờ được lưu an toàn trong nhánh feature/add-usage-examples. Hãy quay về nhánh chính main và xem ở đó có gì.

Bước 1. Nhấp lại vào widget 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 phụ xuất hiện nhấn Checkout.

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

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

4. Merge nhánh

Lệnh merge lấy tất cả commit từ nhánh feature/add-examples (ở đây là commit C3) và kết hợp chúng vào nhánh hiện tại main, tạo ra một commit merge 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 thêm những thay đổi đó vào dự án chính.

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

Đảm bảo bạn đang ở nhánh mà bạn muốn THÊM các thay đổi vào. Ở ví dụ này là main.

Bước 2. Thực hiện merge.

Nhấp lại vào widget quản lý nhánh. Trong danh sách chọn nhánh mà bạn muốn lấy thay đổi từ đó (feature/add-usage-examples), và trong menu phụ chọn Merge feature/add-usage-examples vào main.

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

Bây giờ trong file README.md ở nhánh main đã xuất hiện phần ví dụ của bạn. Bạn đã merge 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 merge: đừng sợ, điều đó bình thường!

Đôi khi khi merge nhánh sẽ xảy ra xung đột. Điều này xảy ra khi cả hai nhánh đều chỉnh sửa cùng những dòng trong cùng một file. Git không thể tự quyết định phiên bản nào đúng và cần sự trợ giúp của bạn.

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

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 nó. Đảm bảo tích Checkout branch bị bỏ.
  3. Bây giờ, đang ở nhánh main, thay đổi dòng đầu tiên trong README.md thành "My Awesome Project" và làm commit.
  4. Chuyển sang nhánh feature/new-title. Bạn sẽ thấy dòng đầu tiên trong README.md vẫn là bản cũ: đó là trạng thái file khi tạo nhánh. Thay cùng một dòng này thành "My Super Project" và làm commit.
  5. Quay về nhánh main và thực hiện merge 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ùng một dòng bị thay đổi trong cả hai lịch sử, nên 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 file từ nhánh hiện tại của bạn (main).
  • Bên phải (Changes from branch...): phiên bản file từ nhánh mà bạn đang merge.
  • Ở giữa (Result): phiên bản cuối cùng của file mà bạn phải ghép lại.

Bạn có thể nhấn vào các mũi tên >> hoặc << để chấp nhận hoàn toàn phiên bản này hay phiên bản kia.

Khi kết quả ở bảng giữa làm bạn hài lòng, nhấn Apply. IDE sẽ tự tạo commit merge và xung đột sẽ được giải quyết.

Tại sao lại không có xung đột?

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

Ví dụ:

  1. Bạn có một commit nào đó trên main (giả sử C1).
  2. Bạn làm commit mới trên 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 main. Nghĩa là nhánh mới cũng bắt đầu từ commit C2.
  4. Bạn làm commit trên feature/new-title với nội dung "My Super Project". Nhánh này "chạy trước" và giờ trỏ tới commit C3 (feature/new-title -> C1 -> C2 -> C3).
  5. Bạn quay về main (vẫn ở commit C2) và yêu cầu merge feature/new-title.

Git nhìn vào 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ử main không có commit mới nào trong khi bạn làm việc ở nhánh khác. Git nghĩ: "À, ở đây chỉ cần tua main tới commit C3. Không có xung đột." Và nó chỉ 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 chuyện gì đang xảy ra trong dự án của bạn, hữu ích khi nhìn vào lịch sử của nó.

Mở tab Git ở phần dưới cùng của IDE và chọn Log. Bạn sẽ thấy biểu diễn đồ họa của tất cả các nhánh và commit. Điều này giúp theo dõi trực quan nhánh nào tách ra từ nhánh nào và nơi chúng đã được merge.

Ở đây bạn có thể click vào bất kỳ commit nào để xem những thay đổi đã vào commit đó, ai và khi nào làm. Đây thực sự là cỗ máy thời gian cho code!

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