2011-10-18 30 views
10

Xin lưu ý: Tôi không cố gắng khởi động lại đối số cho dù Mercurial hoặc Git là tốt hơn, tôi chỉ có một câu hỏi kỹ thuật mà tôi, như một người sử dụng Mercurial, không hiểu. Tôi cũng không chắc liệu SO là đúng nơi để đặt câu hỏi như vậy, nhưng nó liên quan đến lập trình. Đã có nhiều cuộc thảo luận về việc hai hệ thống điều khiển phiên bản Git và Mercurial khác nhau như thế nào từ quan điểm của người dùng (ví dụ: và http://felipec.wordpress.com/2011/01/16/mercurial-vs-git-its-all-in-the-branches/), và sự khác biệt chính là xử lý các chi nhánh. Tôi đã đọc qua nhiều cuộc thảo luận này, nhưng tôi cứ tự hỏi mình câu hỏi này:Tại sao Git không lưu tên chi nhánh như một phần của cam kết?

Tại sao Git không lưu tên chi nhánh như một phần của cam kết?

Tôi không thực sự thấy lý do chính đáng để không làm điều đó; nó có nghĩa là dữ liệu không thể chỉ đơn giản biến mất vì không có tham chiếu (tag, branch, anything) poiting cho nó.

Tôi thấy việc lưu trữ chi nhánh trong cam kết là một điểm cộng lớn cho Mercurial, vì điều đó làm cho việc mất dữ liệu trở nên khó khăn hơn.

Điểm chính của đám đông Git ủng hộ mô hình phân nhánh của Git, bạn chỉ có thể xóa nhánh, không ngăn Git lưu tên của chi nhánh như một phần của mỗi cam kết: Nếu cam kết của chi nhánh bị xóa , các tham chiếu đến nhánh đó cũng vậy. Nó cũng sẽ không can thiệp vào đối số "phân nhánh giá rẻ": các chi nhánh sẽ không tốn kém hơn để quản lý. Và tôi không nghĩ rằng lưu trữ bổ sung cần phải được quan tâm: nó chỉ là một vài byte cho mỗi cam kết.

+0

Tôi đang bối rối, khi nào bạn mất dữ liệu vào lúc này? – Useless

+1

Tôi không, nhưng nó có thể: Theo như tôi hiểu, một đầu tách rời sẽ được thu gom rác khi bạn không chỉ một thẻ hoặc một chi nhánh ở đó. –

+1

@danielkullmann: đã thu thập rác, vâng, nhưng không phải trước ít nhất hai tuần: http://stackoverflow.com/questions/5772192/git-how-can-i-reconcile-detached-head-with-master-origin – VonC

Trả lời

14

Một trong những nguồn dứt khoát về chi nhánh cho Git và Mercurial là câu hỏi SO:

"Git and Mercurial - Compare and Contrast"

Trong tài liệu tham khảo Git (chi nhánh, chi nhánh từ xa theo dõi và thẻ) cư trú bên ngoài DAG của cam kết.

(Điều đó cho phép để quản lý không gian tên khác nhau liên quan đến ngành, cho các chi nhánh địa phương và từ xa)

Bạn có một khái niệm tương tự với Mercurial với các ngành bookmark (mà có thể được đẩy/kéo).

Lưu ý rằng trong Git, dữ liệu sẽ không "biến mất" vì không có tham chiếu: bạn vẫn có reflog để truy xuất các cam kết không được chấp nhận đó.

Tại sao Git không lưu tên chi nhánh như một phần của cam kết?
Tôi không thực sự nhìn thấy một lý do chính đáng để không làm điều đó

Ý tưởng là để tách đã thay đổi (các cam kết) từ tại sao m tức là từ bối cảnh của sự thay đổi (tên của chi nhánh).
Vì bạn có thể fast-forward merge một chi nhánh, cam kết từ một chi nhánh có thể là một phần của chi nhánh khác bất kỳ lúc nào.

Đó là lý do tại sao Jakub Narębski đặt câu hỏi về thiết kế của Mercurial "chi nhánh có tên là" (với tên chi nhánh nhúng trong siêu dữ liệu changeset), đặc biệt là với một toàn cầu namespace , không phải là rất thích hợp cho một hệ thống kiểm soát phiên bản phân phối.

Bạn tạo một chi nhánh để cô lập nỗ lực phát triển (xem "When should you branch?"), nhưng với DVCS, nỗ lực phát triển (tập hợp các cam kết) sẽ được xuất bản dưới bất kỳ tên chi nhánh nào. Ngữ cảnh cục bộ (tên chi nhánh) bạn đã xác định có thể không hợp lệ khi được xuất bản cho một repo Git khác.

+0

+1 Cảm ơn, điều đó cực kỳ khai sáng! –

+0

Tôi thấy điều đó thật đáng lo ngại khi mọi người nói "đừng sợ hãi, điều đó sẽ không biến mất; nó ở trong quá trình reflog". Việc reflog là tạm thời. Nó biến mất. Sau khi nó biến mất, làm thế nào để bạn có được các phần không được quan tâm của đồ thị cam kết? –

+0

@DonHatch biến mất? Chỉ sau 90 ngày theo mặc định. Nếu bạn thực sự cần thông tin đó sau 90 ngày, tôi cho rằng bạn có thể lấy thông tin từ bản sao lưu của repo của bạn. – VonC

8

Mô hình hoạt động cơ bản của Mercurial là các nhánh vô danh, đơn giản tạo thành đồ thị theo chu kỳ (DAG), và vì các tên chi nhánh này có tầm quan trọng rất ít và bạn sẽ giải quyết chúng ít hơn rất nhiều. Các chi nhánh được đặt tên có chủ yếu cho mục đích tổ chức (các nhánh phát hành, vv), mà tôi cho rằng một không gian tên toàn cầu có ý nghĩa hơn hoặc ít nhất là ít bị phản đối. Git có một mô hình phân nhánh phức tạp và được quản lý hơn Mercurial, nơi mà các thay đổi cục bộ của bạn được xử lý như một nhánh riêng biệt, và đối mặt với rất nhiều chi nhánh được đặt tên, bạn phải giới thiệu các không gian tên để quản lý chúng. Vì lý do tương tự, Git có khái niệm về việc hợp nhất nhanh, một cái gì đó không áp dụng cho Mercurial bởi vì bạn sẽ không tạo ra một chi nhánh riêng biệt ngay từ đầu.

Cả hai khái niệm này thêm độ phức tạp hơn, đồng thời chặn các tính năng hữu ích như lưu tên chi nhánh cùng với cam kết. Điều này là do bạn không thể lưu trữ các chi nhánh không có tên mà không có một số không gian toàn cầu, và git không có.

Lỗ hổng trong đối số cho không gian tên mà VonC tham chiếu ở trên là nó giả định có vấn đề nếu bạn và tôi tạo cả một chi nhánh có tên là ‘x’. Không có, giống như không có vấn đề gì khi bạn tạo một chi nhánh được đặt tên, hợp nhất nó và sau đó tạo một tên khác có cùng tên. Một cái tên được lựa chọn mô tả chi nhánh không quan trọng ai là tác giả, và nếu bạn cần phân biệt nhiều tác giả được lưu trữ ngay cùng với tên chi nhánh, và tất cả điều này là vĩnh viễn.

Tôi nghĩ rằng đó là một quyết định rất tốt của dự án Mercurial để lưu trữ tên chi nhánh cùng với cam kết. Cũng giống như thông điệp cam kết và tác giả, bối cảnh của tác phẩm (nhánh) là thông tin meta quan trọng và hữu ích. Nó làm cho nó dễ dàng hơn nhiều để xem dòng chảy của changesets khi kiểm tra lịch sử, bởi vì bạn có thể nhìn thấy bối cảnh mà họ đã được thực hiện in Trong Git tôi đã có kinh nghiệm mà không có thông tin này, lịch sử nhanh chóng trở thành một mớ hỗn độn của dòng jumbly đó là khó khăn để làm cho đầu hoặc đuôi của. Tôi nghĩ rằng việc này có giá trị đáng kể khi không có không gian tên. Tôi nghĩ bạn có thể nói sự khác biệt về triết học là Mercurial coi các nhánh được đặt tên là siêu dữ liệu vĩnh viễn cung cấp thêm thông tin về một dòng cam kết, trong khi các nhánh Git là một hệ thống quản lý không phiên bản cho các nhà phát triển ở trên cùng của DAG. Mercurial cũng có những cái này dưới cái tên 'bookmark' bằng cách (như phiên bản 1.8 là một tính năng cốt lõi), nhưng chúng thực sự là một công cụ theo dõi và được xử lý như các nhãn thay vì các nhánh.

+0

Cảm ơn, rất thú vị! –

Các vấn đề liên quan