Chi nhánh phân nhánh của Free có nghĩa là gì trong Git?


27

"Phân nhánh là miễn phí" có nghĩa là gì trong Git?

Tôi nghe thấy điều này rất nhiều mỗi khi Git được đề cập so với các hệ thống kiểm soát phiên bản khác.

Tôi chưa có cơ hội (?) Để giao dịch với người khác ( SVN , v.v.), vậy làm thế nào để phân nhánh "đắt" ở người khác?

Câu trả lời:


28

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:

Làm thế nào được thực hiện trong git?

Kho git, .gitchủ 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:

  • Một tham chiếu được tạo cho chi nhánh địa phương tại: .git/refs/heads/{name_of_branch}
  • Nhật ký lịch sử được tạo cho chi nhánh địa phương tại: .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-foundhoặc git-fsck --lost-foundtạ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/HEADtệp, trông giống như thế này nếu bạn ở trên masternhánh.

ref: refs/heads/master

Chuyển nhánh chỉ đơn giản là thay đổi tham chiếu trong .git/HEADtệ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.

Làm thế nào để so sánh trong các hệ thống kiểm soát phiên bản khác?

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:

  • Sao chép thư mục nguồn, ví dụ trunk, vào thư mục đích,
  • Cam kết thay đổi để hoàn thiện hành động sao chép.

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 updatengụ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-submodulenhư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 tipsvà thay vào đó branchesbookmarkstheo thuật ngữ đồng bóng.


Ồ Rất cám ơn lời giải thích "đắt đỏ".
laggingreflex

2
Từ nguồn của riêng bạn: 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.
Bobson

@Bobson Tôi đã suy nghĩ về việc viết lại các bit khi phân nhánh, vì tôi đang thực hiện nhiều thao tác liên quan đến điều đó, nhưng quan điểm của tôi vẫn là một cam kết được yêu cầu để tạo một nhánh trong khi ở Git thì không. Theo kinh nghiệm khiêm tốn của tôi, tôi vẫn cảm thấy mặc dù việc chuyển đổi chi nhánh trong SVN chậm hơn so với Git nhưng tôi không thể chỉ ra bất kỳ lý do cụ thể nào tại sao.
Spoike

2
@Spoike - Chuyển đổi, chắc chắn. Và một cam kết chắc chắn là cần thiết. Tôi đã thực hiện một chỉnh sửa để làm rõ bit tôi có vấn đề với. Hãy thoải mái hoàn nguyên nó nếu bạn thích.
Bobson


10

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ể.


4
Với Git, nó thậm chí còn ít hơn một cam kết - một chi nhánh chỉ là một nhãn hiệu. Và SVN nghe có vẻ đắt như CVS, vì cả hai đều sao chép tất cả các tệp.
Izkata

8
@Izkata: nếu chúng tôi nhìn từ quan điểm người dùng - có, tất cả các tệp được sao chép, từ quan điểm thực hiện (và hiệu suất) - không, chỉ một bản ghi về bản sao được thêm vào.
maxim1000

@Izkata quá nhiều để bình luận - xem câu trả lời của tôi.
gbjbaanb

6
@Izkata SVN tạo con trỏ và tham chiếu, nó không sao chép mọi thứ.
Aaron McIver

2
Chi nhánh Git không phải là một cam kết, nó chỉ là một tham chiếu đến một cam kết có thể được di chuyển tự do sang các cam kết khác. Hãy nghĩ về một repo Git giống như một cây hoa hồng và các nhánh như những nốt dính có thể được tự do di chuyển xung quanh đến các cam kết khác nhau trên cây đó.
40XUserNotFound

5

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í'.


5

Đó 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').

Các chi nhánh của git về cơ bản là các nhãn chỉ vào một cam kết và do đó tránh các vấn đề trên.


1

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.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.