Bạn nên làm cả hai.
Bắt đầu với câu trả lời được chấp nhận từ @Norman: Sử dụng một kho lưu trữ với một chi nhánh được đặt tên cho mỗi bản phát hành.
Sau đó, có một bản sao cho mỗi nhánh phát hành để xây dựng và thử nghiệm.
Một lưu ý quan trọng là ngay cả khi bạn sử dụng nhiều kho, bạn nên tránh sử dụng transplant
để di chuyển các thay đổi giữa chúng vì 1) nó thay đổi băm và 2) nó có thể giới thiệu các lỗi rất khó phát hiện khi có mâu thuẫn thay đổi giữa changeset bạn cấy ghép và nhánh mục tiêu. Bạn muốn thực hiện việc hợp nhất thông thường thay vào đó (và không có premerge: luôn trực quan kiểm tra việc hợp nhất), điều này sẽ dẫn đến những gì @mg nói ở cuối câu trả lời của mình:
Biểu đồ có thể khác, nhưng nó có cùng một cấu trúc và kết quả cuối cùng là như nhau.
verbosely hơn, nếu bạn sử dụng nhiều kho, các "thân cây" kho (hoặc mặc định, chính, phát triển, bất cứ điều gì) chứa ALL changesets trong ALL kho. Mỗi kho lưu trữ/chi nhánh chỉ đơn giản là một nhánh trong thân cây, tất cả được sáp nhập ngược lại một chiều hoặc ngược lại với thân cây, cho đến khi bạn muốn để lại một bản phát hành cũ phía sau. Do đó, sự khác biệt thực sự duy nhất giữa repo chính và repo đơn trong lược đồ chi nhánh được đặt tên đơn giản là các nhánh có được đặt tên hay không.
Điều đó sẽ làm cho nó rõ ràng lý do tại sao tôi nói "bắt đầu với một repo". Đó là repo duy nhất là nơi duy nhất bạn sẽ cần phải tìm bất kỳ changeset trong bất kỳ phiên bản. Bạn có thể thêm các thay đổi trên các nhánh phát hành để phiên bản. Đó là khái niệm rõ ràng và đơn giản, và làm cho hệ thống quản trị đơn giản, vì nó là điều duy nhất mà hoàn toàn phải có sẵn và phục hồi tất cả các thời gian.
Nhưng sau đó bạn vẫn cần duy trì một bản sao cho mỗi nhánh/bản phát hành mà bạn cần xây dựng và thử nghiệm. Nó tầm thường như bạn có thể hg clone <main repo>#<branch> <branch repo>
, và sau đó hg pull
trong repo chi nhánh sẽ chỉ kéo changesets mới trên nhánh đó (cộng với changesets tổ tiên trên các nhánh trước đó đã được sáp nhập).
Thiết lập này thích hợp nhất với kernel linux cam kết mô hình puller đơn (không nó cảm thấy tốt để hành động như Chúa Linus. Tại công ty chúng tôi chúng ta gọi là vai trò tích hợp), như repo chính là chỉ điều mà các nhà phát triển cần phải sao chép và puller cần phải kéo vào. Việc duy trì các repo chi nhánh hoàn toàn là để quản lý phát hành và có thể hoàn toàn tự động. Các nhà phát triển không bao giờ cần phải kéo từ/đẩy đến repos chi nhánh.
Đây là ví dụ về @ mg được thiết lập lại này. Điểm bắt đầu:
[a] - [b]
Tạo một chi nhánh được đặt tên cho phiên bản phát hành, nói "1.0", khi bạn được phát hành alpha. Cam kết sửa lỗi trên đó:
[a] - [b] ------------------ [m1]
\ /
(1.0) - [x] - [y]
(1.0)
không phải là một thay đổi thực sự vì chi nhánh được đặt tên không tồn tại cho đến khi bạn cam kết. (Bạn có thể thực hiện một cam kết tầm thường, chẳng hạn như thêm thẻ, để đảm bảo các nhánh được đặt tên được tạo đúng cách.)
Hợp nhất [m1]
là chìa khóa để thiết lập này. Không giống như một kho lưu trữ dành cho nhà phát triển nơi có thể có số lượng đầu không giới hạn, bạn KHÔNG muốn có nhiều đầu trong repo chính của bạn (ngoại trừ chi nhánh phát hành cũ, đã chết như đã đề cập trước đó). Vì vậy, bất cứ khi nào bạn có các thay đổi mới trên các nhánh phát hành, bạn phải hợp nhất chúng trở lại nhánh mặc định (hoặc một nhánh phát hành sau) ngay lập tức. Điều này đảm bảo rằng mọi sửa lỗi trong một bản phát hành cũng được bao gồm trong tất cả các bản phát hành sau này.
Trong sự phát triển trong khi đó trên chi nhánh mặc định vẫn tiếp tục hướng tới việc phát hành tiếp theo:
------- [c] - [d]
/
[a] - [b] ------------------ [m1]
\ /
(1.0) - [x] - [y]
Và như thường lệ, bạn cần phải hợp nhất hai người đứng đầu về chi nhánh mặc định:
------- [c] - [d] -------
/ \
[a] - [b] ------------------ [m1] - [m2]
\ /
(1.0) - [x] - [y]
Và đây là 1.0 bản sao nhánh:
[a] - [b] - (1.0) - [x] - [y]
Bây giờ, bạn nên tập thêm nhánh phát hành tiếp theo . Nếu đó là 2.0 thì nó chắc chắn sẽ phân nhánh mặc định. Nếu là 1.1, bạn có thể chọn phân nhánh 1.0 hoặc mặc định. Bất kể, bất kỳ changeset mới trên 1.0 nên được sáp nhập đầu tiên vào nhánh tiếp theo, sau đó để mặc định. Điều này có thể được thực hiện tự động nếu không có xung đột, kết quả chỉ là một hợp nhất trống.
Tôi hy vọng ví dụ này làm cho các điểm trước đó của tôi rõ ràng.Tóm lại, những lợi thế của phương pháp này là:
- Kho chứa độc quyền chứa toàn bộ thay đổi và lịch sử phiên bản.
- Quản lý phát hành rõ ràng và đơn giản.
- Quy trình làm việc rõ ràng và đơn giản cho nhà phát triển và người tích hợp.
- Tạo điều kiện lặp lại quy trình làm việc (đánh giá mã) và tự động hóa (hợp nhất tự động trống).
CẬP NHẬT hg tự does this: các main repo chứa mặc định, ngành ổn định, và stable repo là chi nhánh bản sao ổn định. Tuy nhiên, nó không sử dụng branched version, vì các thẻ phiên bản dọc nhánh ổn định là đủ tốt cho các mục đích quản lý phát hành của nó.
nếu changeset đến từ một người dùng khác, mà có thể đã được ghi lại, do đó, sử dụng nhân bản là không có gì xấu. Khi đẩy một tính năng mới nó thường không thú vị để biết bạn đã làm điều đó từ một repo riêng biệt. Ngoài ra còn có một phần mở rộng localbranch, cung cấp cho bạn một chi nhánh địa phương duy nhất. Hữu ích khi nhân bản repo được kết hợp với chi phí cao (thời gian/không gian). –
tham chiếu đến: 'nhái rất tuyệt vời cho thí nghiệm nhanh' - Không, chúng không phải! Điều gì sẽ xảy ra nếu bạn có một vài tập tin trong repo? Nhân bản sẽ mất nhiều thời gian (bất cứ lúc nào trên 1 phút) trong khi nhánh chỉ chuyển đổi một lúc (<1 giây). Vẫn sử dụng các chi nhánh được đặt tên sẽ gây ô nhiễm thay đổi. Nó không phải là một kết thúc chết? Hoặc tôi đang thiếu một cái gì đó? – seler
OK seler; Âm thanh như một sửa đổi đối số ban đầu của anh ấy; Bản sao là tốt nơi mà các bản sao của nhiều bản sao hoàn chỉnh không quan trọng đối với bạn, hoặc khi bạn có thể sử dụng các liên kết/liên kết của hg để giảm thiểu chi phí của các bản sao làm việc cục bộ riêng biệt trên mỗi nhánh. –