Câu trả lời:
Khiếu nại rằng "phân nhánh là miễn phí trong git" là một sự đơn giản hóa thực tế bởi vì nó không "miễn phí" mỗi se. Nhìn dưới mui xe một tuyên bố chính xác hơn sẽ là để nói rằng phân nhánh là redonkulously giá rẻ thay vì các chi nhánh về cơ bản tham chiếu đến các cam kết . Tôi định nghĩa "giá rẻ" ở đây là càng ít chi phí càng rẻ.
Hãy tìm hiểu lý do tại sao Git lại "rẻ" bằng cách kiểm tra xem nó có những loại chi phí nào:
Kho git, .git
chủ yếu bao gồm các thư mục chứa các tệp chứa siêu dữ liệu mà git sử dụng. Bất cứ khi nào bạn tạo một nhánh trong git, ví dụ git branch {name_of_branch}
, một vài điều xảy ra:
.git/refs/heads/{name_of_branch}
.git/logs/refs/heads/{name_of_branch}
Về cơ bản, một vài tệp văn bản được tạo. Nếu bạn mở tham chiếu dưới dạng tệp văn bản, nội dung sẽ là id-sha của cam kết mà nhánh đang trỏ tới. Lưu ý rằng việc phân nhánh không yêu cầu bạn thực hiện bất kỳ cam kết nào vì chúng là một loại đối tượng khác. Cả hai nhánh và cam kết đều là "công dân hạng nhất" trong git và một cách là nghĩ về mối quan hệ giữa các nhánh với nhau như một tập hợp chứ không phải là một tác phẩm. Nếu bạn loại bỏ một nhánh, các cam kết vẫn sẽ tồn tại dưới dạng "lơ lửng". Nếu bạn vô tình xóa một nhánh, bạn luôn có thể cố gắng tìm cam kết với git-lost-found
hoặc git-fsck --lost-found
tạo một nhánh trên sha-id mà bạn thấy bị treo trái (và miễn là git chưa thực hiện bất kỳ bộ sưu tập rác nào).
Vậy làm thế nào để git theo dõi chi nhánh bạn đang làm việc? Câu trả lời là với .git/HEAD
tệp, trông giống như thế này nếu bạn ở trên master
nhánh.
ref: refs/heads/master
Chuyển nhánh chỉ đơn giản là thay đổi tham chiếu trong .git/HEAD
tệp và sau đó tiến hành thay đổi nội dung của không gian làm việc của bạn với các nội dung được xác định trong cam kết.
Trong Subversion , các nhánh là các thư mục ảo trong kho lưu trữ . Vì vậy, cách dễ nhất để phân nhánh là làm điều đó từ xa, với một lớp lót svn copy {trunk-url} {branch-url} -m "Branched it!"
. Những gì SVN sẽ làm là như sau:
trunk
, vào thư mục đích,Bạn sẽ muốn thực hiện hành động này từ xa trên máy chủ, bởi vì việc sao chép cục bộ đó là hoạt động theo thời gian tuyến tính, với các tệp được sao chép và liên kết tượng trưng. Đây là một hoạt động rất chậm , trong khi thực hiện nó trên máy chủ là một hoạt động thời gian không đổi. Lưu ý rằng ngay cả khi thực hiện nhánh trên sever, lật đổ yêu cầu một cam kết khi phân nhánh trong khi git thì không, đó là một sự khác biệt chính. Đó là một loại chi phí khiến SVN rẻ hơn một chút so với Git.
Lệnh chuyển đổi các nhánh trong SVN , nghĩa là svn switch
, thực sự là svn update
ngụy trang. Nhờ khái niệm thư mục ảo, lệnh linh hoạt hơn một chút trong svn so với git. Thư mục con trong không gian làm việc của bạn có thể được chuyển ra để phản chiếu một url kho lưu trữ khác. Điều gần nhất sẽ là sử dụng git-submodule
nhưng sử dụng nó hoàn toàn khác với việc phân nhánh. Thật không may, đây cũng là một quyết định thiết kế làm cho việc chuyển đổi chậm hơn một chút trong SVN so với Git vì nó phải kiểm tra mọi thư mục không gian làm việc mà url từ xa đang phản chiếu. Theo kinh nghiệm của tôi, Git chuyển đổi chi nhánh nhanh hơn SVN.
Chi nhánh của SVN đi kèm với chi phí vì nó sao chép các tệp và luôn cần được cung cấp công khai. Trong git, như đã giải thích ở trên, các nhánh "chỉ là tài liệu tham khảo" và có thể được lưu trong kho lưu trữ cục bộ của bạn và được xuất bản theo ý của bạn. Tuy nhiên, theo kinh nghiệm của tôi, SVN vẫn rẻ hơn đáng kể và hiệu suất cao hơn, ví dụ như ClearCase.
Đó chỉ là một mánh khóe mà SVN không được phân cấp. Bạn có thể có nhiều kho lưu trữ như được nhân đôi với một số repo nguồn nhưng việc đồng bộ hóa các thay đổi khác nhau, nhiều kho lưu trữ SVN là không thể vì SVN không có mã định danh duy nhất cho các xác nhận (git đã băm định danh dựa trên nội dung của cam kết). Lý do tại sao cá nhân tôi bắt đầu sử dụng git qua SVN là vì việc khởi tạo một kho lưu trữ dễ dàng hơn và rẻ hơn trong git . Về mặt khái niệm về mặt quản lý cấu hình phần mềm, mỗi bản sao khác nhau của một dự án (bản sao, ngã ba, không gian làm việc hoặc bất cứ thứ gì) là một "nhánh" và do thuật ngữ này tạo ra một bản sao mới trong SVN không rẻ như Git, nơi mà bản sau có chi nhánh "tích hợp".
Một ví dụ khác, trong Mercurial , việc phân nhánh bắt đầu hơi khác một chút như DVCS và tạo / hủy các nhánh được đặt tên theo yêu cầu riêng biệt. Các nhà phát triển Mercurial đã triển khai sau này trong các dấu trang phát triển để bắt chước mô hình phân nhánh tương tự của git mặc dù heads
được gọi tips
và thay vào đó branches
là bookmarks
theo thuật ngữ đồng bóng.
This command causes a near-instantaneous commit in the repository, creating a new directory in revision 341. The new directory is a copy of /calc/trunk.
- Tạo chi nhánh là chuyện nhỏ trong SVN, trừ khi bạn rõ ràng tạo một bản sao của mọi tệp.
Chi phí thực sự của một chi nhánh là hợp nhất nó. Git làm cho điều này dễ dàng hơn một số hệ thống kiểm soát nguồn khác. Xem câu hỏi về Stack Overflow Làm thế nào và / hoặc tại sao hợp nhất trong Git tốt hơn trong SVN? .
Trong Git, một nhánh chỉ tham chiếu đến một cam kết với repo cục bộ. Tạo ra nó rất rẻ, không có mạng nào cả. Không hoàn toàn miễn phí (bạn đã phải gõ một lệnh), nhưng chết tiệt gần.
Việc phân nhánh không đặc biệt tốn kém ở SVN - đó chỉ là một bản sao, đây là một cam kết rất rẻ. SVN có một mô hình kho lưu trữ trung tâm, vì vậy đó là một truy cập mạng, nhưng không phải là một mô hình khủng khiếp.
Trong CVS đáng kính, mặt khác, phân nhánh là RẤT tốn kém. Về cơ bản, các nhánh CVS liên quan đến việc thêm một thẻ, nhưng trong CVS có nghĩa là MỌI FILE AFFECTED phải được sửa đổi. Mỗi tệp được viết lại để bao gồm thẻ mới. Đó là đắt khủng khiếp. Và nếu kho lưu trữ của bạn lớn, nó cũng chậm khủng khiếp. Trên thực tế, nếu bạn đang ở trong một dự án lớn, nó đủ chậm để một số người có xu hướng tránh làm chi nhánh nếu có thể.
Chi nhánh của SVN cũng miễn phí như Git. Đó chỉ là một chút dữ liệu vệ sinh cho biết chi nhánh bắt đầu từ đâu, không có thay đổi nào đối với các tệp được lưu trữ. Một "bản sao" trong SVN giống như thêm một liên kết tượng trưng vào thư mục Unix. Lưu ý rằng chi nhánh SVN sẽ không yêu cầu một chuyến đi mạng cho đến khi bạn cam kết thay đổi bản sao làm việc của mình (nhưng không có nhiều điểm có SCM nếu bạn không cam kết ngoài địa phương tại một số điểm).
Lưu ý rằng một chi nhánh Git cũng sẽ liên quan đến một số dịch vụ dọn phòng - như thêm thẻ đó vào bên trong - sẽ phải được lưu trữ ở đâu đó khi bạn cam kết. Đó không phải là một vấn đề lớn, đó là lý do tại sao nó được gọi là 'miễn phí'.
Đó là 'miễn phí' (trong ngữ cảnh này 'miễn phí' thực sự có nghĩa là nhanh chóng và dễ dàng và không chiếm dung lượng) bởi vì trong một số hệ thống kiểm soát phiên bản cũ hơn, một nhánh là một bản sao hoàn chỉnh của mã tại thời điểm đó, vì vậy các chi nhánh chiếm rất nhiều không gian và thật dễ dàng để kết thúc với rất nhiều phiên bản phần mềm hoàn toàn khác nhau nằm xung quanh, sau đó được quản lý. Trong những trường hợp khác, nó không phải là một bản sao hoàn chỉnh của mã nhưng mọi tệp vẫn cần được sửa đổi cho một thẻ vì vậy rất chậm và đau đớn ('tốn kém').
Một khía cạnh khác của "miễn phí / rẻ / đắt" là liên quan đến chi phí tài nguyên của nhà phát triển để giải quyết các hậu quả hạ nguồn của việc phân nhánh; tức là quá trình hợp nhất thay đổi từ các chi nhánh.
Và ở đây, việc hợp nhất các nhánh trong các hệ thống DVCS như Git và Mercurial dễ dàng hơn so với các hệ thống cũ ... bởi vì các hệ thống DVCS thực hiện công việc theo dõi lịch sử của các phiên bản trong biểu đồ tốt hơn nhiều; tức là nơi mà sự phân nhánh trước đó đã xảy ra. Điều này làm cho việc hợp nhất trở nên chính xác hơn, giảm các xung đột không cần thiết và ... làm cho việc hợp nhất trở nên "dễ dàng" hơn hoặc "ít đáng sợ hơn" đối với các nhà phát triển có liên quan.