Các mô hình dữ liệu nội bộ về cơ bản là khác nhau.
Về cơ bản, ở SVN, khi bạn nhìn vào lịch sử của một chi nhánh, bạn chỉ thấy những gì đã xảy ra trong chi nhánh đó. Vì vậy, khi bạn hợp nhất từ nhánh này B
sang nhánh khác A
, lịch sử của nhánh A
sẽ chứa một cam kết lớn chứa tất cả các thay đổi được thực hiện rõ ràng B
kể từ khi nó được phân nhánh.
Trong các phiên bản đầu tiên của SVN, nếu bạn phải hợp nhất chi nhánh B
thành chi nhánh A
một lần nữa, bạn phải chỉ định thủ công phạm vi sửa đổi của chi nhánh B
mà bạn muốn hợp nhất để tránh hợp nhất hai lần sửa đổi. Nhà phát triển thông minh tất nhiên sẽ sử dụng một thông điệp cam kết như 'Đã hợp nhất trong B: 1234'.
SVN 1.5 "cố định" cái này. Nhưng nó không thay đổi cách áp dụng sáp nhập một cách cơ bản. Nó chỉ thêm một số siêu dữ liệu bổ sung vào chi nhánh A
, cho SVN biết rằng phiên bản 1234 đã được hợp nhất, cho phép SVN tự động chọn phạm vi sửa đổi chính xác.
Nhưng giải pháp này về cơ bản là một giải pháp cho một mô hình dữ liệu về cơ bản không hỗ trợ theo dõi những gì đã được hợp nhất.
Hợp nhất hai nhánh là một ví dụ tương đối đơn giản. Nhưng hình ảnh kịch bản phức tạp hơn này
- Tạo chi nhánh
A
từ trunk
và thực hiện một số cam kết tại đây
- Tạo chi nhánh
B
từ A
và thực hiện một số cam kết ở đây
- Thực hiện một vài cam kết trong
trunk
vàA
- Hợp nhất
B
thànhtrunk
- Hợp nhất
A
thànhB
- Hợp nhất
A
thànhtrunk
- Hợp nhất
B
vào trunk
(điều này thực sự không nên làm gì cả)
Xử lý chính xác việc sử dụng mô hình siêu dữ liệu này trở nên cực kỳ phức tạp (Tôi không biết liệu SVN có thực sự xử lý chính xác kịch bản này hay không và tôi không cảm thấy có xu hướng kiểm tra nó).
Xử lý tình huống này trong git là cực kỳ đơn giản.
Trong git, mỗi khi bạn cam kết, đối tượng bên trong đại diện cho cam kết đó chứa tham chiếu đến phần đầu trước đó. Khi bạn hợp nhất trong một nhánh, cam kết chứa tham chiếu đến đầu trước của tất cả các nhánh được hợp nhất (bạn có thể hợp nhất nhiều nhánh tại một thời điểm trong git)
Do đó, khi bạn kiểm tra lịch sử của một cam kết trong git, bạn có thể thấy tất cả lịch sử, bạn có thể thấy khi nào nó được phân nhánh, khi nó được hợp nhất và bạn có thể thấy lịch sử của cả hai nhánh giữa phân nhánh và sáp nhập.
Do đó, khi sáp nhập trong một nhánh đã được sáp nhập một phần, việc xác định những gì đã được sáp nhập là vô cùng đơn giản và những gì chưa được hợp nhất.
Tôi không có kinh nghiệm với Mercurial, nhưng tôi nghi ngờ rằng hoạt động bên trong của nó tương tự như git.
Về cơ bản, đối với SVN, đó là một mục tiêu thiết kế để làm cho chi nhánh rẻ. Nhưng trong git, đó là một mục tiêu thiết kế để làm cho việc sáp nhập giá rẻ.
Cuối cùng, lần trước tôi đã sử dụng SVN, nó không thể xử lý các phép hợp nhất, trong đó một tệp được đổi tên trong một nhánh và được sửa đổi trong một nhánh khác.