Văn phòng của tôi muốn hợp nhất chi nhánh vô hạn như chính sách; chúng ta có những lựa chọn nào khác?


119

Văn phòng của tôi đang cố gắng tìm ra cách chúng tôi xử lý việc chia tách và sáp nhập chi nhánh và chúng tôi gặp phải một vấn đề lớn.

Vấn đề của chúng tôi là với các nhóm bên dài hạn - loại mà bạn đã có một vài người làm việc bên lề tách ra từ chủ, chúng tôi phát triển trong một vài tháng, và khi chúng tôi đạt được một cột mốc, chúng tôi đồng bộ hóa cả hai.

Bây giờ, IMHO, cách tự nhiên để xử lý việc này là, ép các mảnh vụn thành một cam kết duy nhất. mastertiếp tục tiến về phía trước; như thường lệ - chúng ta sẽ không từ bỏ các tháng phát triển song song vào masterlịch sử. Và nếu bất cứ ai cần giải quyết tốt hơn cho lịch sử của sidebranch, tất nhiên, tất cả vẫn còn đó - nó chỉ không ở trong masterđó, nó nằm trong sidebranch.

Đây là vấn đề: Tôi làm việc riêng với dòng lệnh, nhưng phần còn lại trong nhóm của tôi sử dụng GUIS. Và tôi đã phát hiện ra GUIS không có tùy chọn hợp lý để hiển thị lịch sử từ các chi nhánh khác. Vì vậy, nếu bạn đạt được một cam kết bí đao, nói rằng "sự phát triển này bị đè bẹp từ chi nhánh XYZ", sẽ rất đau đớn khi đi xem những gì trong đó XYZ.

Trên SourceTree, theo như tôi có thể tìm thấy, đó là một vấn đề đau đầu: Nếu bạn đang ở trên mastervà bạn muốn xem lịch sử từ đó master+devFeature, bạn cần phải xem master+devFeature(chạm vào từng tệp khác nhau), hoặc nếu không cuộn qua nhật ký hiển thị TẤT CẢ các nhánh của kho lưu trữ của bạn song song cho đến khi bạn tìm đúng nơi. Và chúc may mắn tìm ra bạn đang ở đâu.

Đồng đội của tôi, hoàn toàn đúng, không muốn có lịch sử phát triển nên không thể truy cập được. Vì vậy, họ muốn các nhóm phát triển lớn, dài này được hợp nhất, luôn luôn có một cam kết hợp nhất. Họ không muốn bất kỳ lịch sử nào không thể truy cập ngay lập tức từ nhánh chính.

Tôi ghét ý tưởng đó; nó có nghĩa là một mớ vô tận, không thể tránh khỏi của lịch sử phát triển song song. Nhưng tôi không thấy những gì chúng ta có. Và tôi khá bối rối; điều này dường như ngăn chặn hầu hết mọi thứ tôi biết về quản lý chi nhánh tốt và nó sẽ là nỗi thất vọng thường trực đối với tôi nếu tôi không thể tìm ra giải pháp.

Chúng ta có bất kỳ lựa chọn nào ở đây ngoài việc liên tục sáp nhập các nhóm bên thành chủ với các cam kết hợp nhất không? Hoặc, có lý do nào mà việc liên tục sử dụng các hợp nhất không tệ như tôi sợ không?


84
Là ghi lại một sự hợp nhất như là một sự hợp nhất thực sự xấu? Tôi có thể thấy rằng việc lách vào một lịch sử tuyến tính có những lợi thế của nó, nhưng tôi ngạc nhiên rằng việc không làm như vậy đi ngược lại "hầu hết mọi thứ bạn biết về quản lý chi nhánh tốt". Chính xác những vấn đề mà bạn sợ là gì?
IMSoP

65
OK, nhưng trong tâm trí tôi một cành cây dài chạy là chính xác nơi bạn làm muốn có một số tầm nhìn, để đổ lỗi và chia đôi không chỉ đất trên "sự thay đổi đã được giới thiệu như là một phần của Big Rewrite năm 2016". Tôi không đủ tự tin để đăng bài như một câu trả lời, nhưng bản năng của tôi là đó là các nhiệm vụ trong nhánh tính năng cần được xóa, để bạn có một lịch sử ngắn của dự án có thể truy cập từ lịch sử chính, mà không cần phải kiểm tra một chi nhánh mồ côi.
IMSoP

5
Điều đó đã được nói, do đó, câu hỏi hoàn toàn có thể giảm xuống thành "Tôi đang cố gắng sử dụng git ở cấp độ cao hơn so với đồng đội của mình; làm cách nào để chúng không làm phiền tôi." Điều đó, đủ công bằng, tôi thực sự không mong đợi git log master+bugfixDec10thlà điểm đột phá: - /
Standback

26
"sidebranches dài hạn - loại mà bạn đã có một vài người làm việc cho một sidebranch tách ra từ chủ, chúng tôi phát triển trong một vài tháng, và khi chúng tôi đạt được một cột mốc, chúng tôi đồng bộ hóa cả hai." Bạn không định kỳ kéo từ chủ vào nhánh bên? Làm điều đó mỗi (một vài) cam kết làm chủ có xu hướng làm cho cuộc sống đơn giản hơn trong nhiều trường hợp.
TafT

4
merge --no-ffnhững gì bạn muốn? Về masterbản thân, bạn có một cam kết mô tả những gì đã thay đổi trong nhánh, nhưng tất cả các cam kết vẫn tồn tại và được xem là TRƯỚC.
CAD97

Câu trả lời:


243

Mặc dù tôi sử dụng Git trên dòng lệnh - tôi phải đồng ý với các đồng nghiệp của bạn. Sẽ không hợp lý khi ép những thay đổi lớn thành một cam kết duy nhất. Bạn đang mất lịch sử theo cách đó, không chỉ làm cho nó ít nhìn thấy hơn.

Điểm kiểm soát nguồn là theo dõi lịch sử của tất cả các thay đổi. Khi nào đã thay đổi tại sao? Cuối cùng, mọi cam kết đều chứa các con trỏ tới các xác nhận gốc, một khác biệt và siêu dữ liệu giống như một thông điệp cam kết. Mỗi cam kết mô tả trạng thái của mã nguồn và lịch sử đầy đủ của tất cả các thay đổi dẫn đến trạng thái đó. Trình thu gom rác có thể xóa các xác nhận không thể truy cập.

Các hành động như đánh lại, chọn anh đào, hoặc xóa hoặc xóa lịch sử. Cụ thể, các xác nhận kết quả không còn tham chiếu các cam kết ban đầu. Xem xét điều này:

  • Bạn xóa một số xác nhận và ghi chú trong thông báo cam kết rằng lịch sử bị xóa có sẵn trong bản gốc abcd123.
  • Bạn xóa [1] tất cả các nhánh hoặc thẻ bao gồm abcd123 kể từ khi chúng được hợp nhất.
  • Bạn để người thu gom rác chạy.

[1]: Một số máy chủ Git cho phép các nhánh được bảo vệ chống lại việc xóa ngẫu nhiên, nhưng tôi nghi ngờ bạn muốn giữ tất cả các nhánh tính năng của mình mãi mãi.

Bây giờ bạn không còn có thể tra cứu cam kết đó - nó không tồn tại.

Tham chiếu tên chi nhánh trong thông điệp cam kết thậm chí còn tệ hơn, vì tên chi nhánh là cục bộ của một repo. Những gì master+devFeaturetrong thanh toán địa phương của bạn có thể là doodlediduhcủa tôi. Các nhánh chỉ là các nhãn di chuyển trỏ đến một số đối tượng cam kết.

Trong tất cả các kỹ thuật viết lại lịch sử, rebasing là lành tính nhất vì nó sao chép các cam kết hoàn chỉnh với tất cả lịch sử của chúng và chỉ thay thế một cam kết cha mẹ.

Rằng masterlịch sử bao gồm lịch sử hoàn chỉnh của tất cả các chi nhánh được sáp nhập vào đó là một điều tốt, bởi vì điều đó đại diện cho thực tế. [2] Nếu có sự phát triển song song, điều đó sẽ hiển thị trong nhật ký.

[2]: Vì lý do này, tôi cũng thích các cam kết hợp nhất rõ ràng hơn lịch sử giả mạo nhưng cuối cùng là giả mạo do việc nổi loạn.

Trên dòng lệnh, git logcố gắng đơn giản hóa lịch sử được hiển thị và giữ tất cả các cam kết được hiển thị có liên quan. Bạn có thể điều chỉnh đơn giản hóa lịch sử cho phù hợp với nhu cầu của bạn. Bạn có thể muốn viết công cụ nhật ký git của riêng mình để đi qua biểu đồ cam kết, nhưng nói chung là không thể trả lời được là cam kết này ban đầu được cam kết trên nhánh này hay nhánh đó? Cha mẹ đầu tiên của một cam kết hợp nhất là trước đó HEAD, tức là cam kết trong nhánh mà bạn đang hợp nhất. Nhưng điều đó giả định rằng bạn đã không thực hiện hợp nhất ngược từ chủ vào nhánh tính năng, sau đó chuyển tiếp nhanh thành chủ hợp nhất.

Giải pháp tốt nhất cho các chi nhánh dài hạn mà tôi gặp phải là ngăn chặn các chi nhánh chỉ được sáp nhập sau một vài tháng. Sáp nhập là dễ nhất khi những thay đổi gần đây và nhỏ. Lý tưởng nhất là bạn sẽ hợp nhất ít nhất một lần mỗi tuần. Tích hợp liên tục (như trong Lập trình cực đoan, không như trong Hãy hãy thiết lập một máy chủ Jenkins), thậm chí đề xuất nhiều sự hợp nhất mỗi ngày, tức là không duy trì các nhánh tính năng riêng biệt mà chia sẻ một nhánh phát triển thành một nhóm. Hợp nhất trước một tính năng là QA yêu cầu rằng tính năng này được ẩn đằng sau cờ tính năng.

Đổi lại, việc tích hợp thường xuyên giúp có thể phát hiện ra các vấn đề tiềm ẩn sớm hơn nhiều và giúp giữ một kiến ​​trúc nhất quán: có thể thay đổi sâu rộng vì những thay đổi này nhanh chóng được bao gồm trong tất cả các chi nhánh. Nếu một thay đổi phá vỡ một số mã, nó sẽ chỉ phá vỡ một vài ngày làm việc, không phải một vài tháng.

Viết lại lịch sử có thể có ý nghĩa đối với các dự án thực sự lớn khi có nhiều triệu dòng mã và hàng trăm hoặc hàng ngàn nhà phát triển đang hoạt động. Có một câu hỏi đặt ra là tại sao một dự án lớn như vậy lại phải là một repo git duy nhất thay vì được chia thành các thư viện riêng biệt, nhưng ở quy mô đó sẽ thuận tiện hơn nếu repo trung tâm chỉ chứa các bản phát hành của các thành phần riêng lẻ. Ví dụ, nhân Linux sử dụng squash để giữ cho lịch sử chính có thể quản lý được. Một số dự án nguồn mở yêu cầu các bản vá được gửi qua email, thay vì hợp nhất cấp git.


43
@Standback Tôi không quan tâm những gì nhà phát triển thực hiện tại địa phương, sử dụng Cam kết của Wip, cam kết thêm cho mỗi lỗi đánh máy, lỗi. Điều đó tốt, tốt hơn là cam kết quá thường xuyên. Lý tưởng nhất, nhà phát triển sẽ dọn sạch những cam kết đó trước khi chúng được đẩy, như kết hợp tất cả các cam kết chỉ sửa một số lỗi chính tả. Vẫn là một ý tưởng tốt để giữ các cam kết riêng biệt nếu chúng làm những việc khác nhau, ví dụ: một cam kết cho chức năng thực tế và các thử nghiệm liên quan, một thử nghiệm khác cho các lỗi chính tả không liên quan. Nhưng một khi các cam kết được đẩy, viết lại hoặc xóa lịch sử sẽ rắc rối hơn giá trị của nó, ít nhất là theo kinh nghiệm của tôi.
amon

11
"Nói chung là không thể trả lời được, vì cam kết này ban đầu được cam kết ở nhánh này hay nhánh kia?" . Tôi thực sự muốn có thể hỏi hệ thống kiểm soát phiên bản của mình "cái gì ở nhánh x vào ngày y".
Peter Green

80
Không có gì bực bội hơn khi cố gắng xác định nguyên nhân gây ra lỗi trong mã bằng cách sử dụng git bisect, chỉ để nó đến được 10.000 dòng uber-commit từ một nhánh bên.
tpg2114

2
@Standback IMHO cam kết càng nhỏ thì càng dễ đọc và thân thiện. Một cam kết chạm nhiều hơn vài điểm là không thể nắm bắt ngay từ cái nhìn đầu tiên, vì vậy bạn chỉ cần lấy mô tả theo mệnh giá. Đó là tính dễ đọc của mô tả (ví dụ: "tính năng X được triển khai"), chứ không phải bản thân cam kết (mã). Tôi muốn có 1000 cam kết một chữ cái như "đã thay đổi http thành https" :)
Agent_L

2
cherry-pick không viết lại hoặc xóa lịch sử. nó chỉ tạo ra các xác nhận mới sao chép các thay đổi từ các cam kết hiện có
SUND Borsch

110

Tôi thích câu trả lời của Amon , nhưng tôi cảm thấy một phần nhỏ cần nhấn mạnh hơn nhiều: Bạn có thể dễ dàng đơn giản hóa lịch sử trong khi xem nhật ký để đáp ứng nhu cầu của mình, nhưng những người khác không thể thêm lịch sử trong khi xem nhật ký để đáp ứng nhu cầu của họ. Đây là lý do tại sao giữ lịch sử như nó xảy ra là tốt hơn.

Đây là một ví dụ từ một trong các kho lưu trữ của chúng tôi. Chúng tôi sử dụng mô hình yêu cầu kéo, vì vậy mọi tính năng trông giống như các nhánh chạy dài của bạn trong lịch sử, mặc dù chúng thường chỉ chạy một tuần hoặc ít hơn. Các nhà phát triển cá nhân đôi khi chọn xóa sổ lịch sử của họ trước khi hợp nhất, nhưng chúng tôi thường kết hợp các tính năng, vì vậy điều đó tương đối bất thường. Đây là một vài cam kết hàng đầu gitk, gui đi kèm với git:

xem gitk tiêu chuẩn

Vâng, một chút rối, nhưng chúng tôi cũng thích nó bởi vì chúng tôi có thể thấy chính xác ai đã thay đổi vào thời gian nào. Nó phản ánh chính xác lịch sử phát triển của chúng tôi. Nếu chúng ta muốn xem chế độ xem cấp cao hơn, một yêu cầu kéo hợp nhất tại một thời điểm, chúng ta có thể xem chế độ xem sau, tương đương với git log --first-parentlệnh:

xem gitk với --first-Parent

git logcó nhiều tùy chọn hơn được thiết kế để cung cấp cho bạn chính xác các chế độ xem bạn muốn. gitkcó thể lấy bất kỳ git logđối số tùy ý để xây dựng chế độ xem đồ họa. Tôi chắc rằng các GUI khác có khả năng tương tự. Đọc tài liệu và học cách sử dụng nó đúng cách, thay vì thực thi git logchế độ xem ưa thích của bạn đối với mọi người tại thời điểm hợp nhất.


24
Tôi không quen thuộc với tùy chọn này! Đây là một trợ giúp lớn cho tôi và có vẻ như việc tìm hiểu thêm các tùy chọn nhật ký sẽ cho phép tôi sống với điều này dễ dàng hơn.
Trở lại

25
+1 cho "Bạn có thể dễ dàng đơn giản hóa lịch sử trong khi xem nhật ký để đáp ứng nhu cầu của mình, nhưng những người khác không thể thêm lịch sử trong khi xem nhật ký để đáp ứng nhu cầu của họ." Viết lại lịch sử luôn là câu hỏi. Nếu bạn nghĩ rằng nó quan trọng để ghi lại tại thời điểm cam kết thì nó rất quan trọng. Ngay cả khi bạn thấy nó sai hoặc làm lại sau đó là một phần của lịch sử. Một số sai lầm chỉ có ý nghĩa khi bạn có thể thấy trong sự đổ lỗi rằng dòng này còn sót lại sau khi viết lại. Khi những sai lầm được xếp lại với phần còn lại của sử thi, bạn không thể xem lại lý do tại sao mọi thứ lại kết thúc như thế nào.
TafT

@Standback Liên quan, một điều giúp duy trì cấu trúc này cho tôi, là sử dụng merge --no-ff- không sử dụng kết hợp chuyển tiếp nhanh, thay vào đó luôn tạo một cam kết hợp nhất để --first-parentcó một cái gì đó hoạt động
Izkata

34

Vấn đề của chúng tôi là với các nhóm bên dài hạn - loại mà bạn đã có một vài người làm việc bên lề tách ra từ chủ, chúng tôi phát triển trong một vài tháng, và khi chúng tôi đạt được một cột mốc, chúng tôi đồng bộ hóa cả hai.

Suy nghĩ đầu tiên của tôi là - thậm chí không làm điều này trừ khi thực sự cần thiết. Sự hợp nhất của bạn đôi khi phải là thách thức. Giữ các chi nhánh độc lập và càng ngắn càng tốt. Đó là một dấu hiệu cho thấy bạn cần chia câu chuyện của mình thành các phần thực hiện nhỏ hơn.

Trong trường hợp bạn phải làm điều này, thì có thể hợp nhất trong git với tùy chọn --no-ff để lịch sử được giữ riêng biệt trên nhánh riêng của chúng. Các cam kết sẽ vẫn xuất hiện trong lịch sử được hợp nhất nhưng cũng có thể được nhìn thấy riêng trên nhánh tính năng để ít nhất có thể xác định dòng phát triển nào chúng là một phần của.

Tôi phải thừa nhận khi lần đầu tiên bắt đầu sử dụng git, tôi thấy hơi lạ là nhánh cam kết xuất hiện trong cùng lịch sử với nhánh chính sau khi hợp nhất. Đó là một chút bối rối bởi vì dường như những cam kết đó không thuộc về lịch sử đó. Nhưng trong thực tế, đó không phải là điều gì đó thực sự đau đớn, nếu người ta cho rằng nhánh tích hợp chỉ là như vậy - toàn bộ mục đích của nó là kết hợp các nhánh tính năng. Trong nhóm của chúng tôi, chúng tôi không bí, và chúng tôi thường xuyên thực hiện các cam kết. Chúng tôi sử dụng --no-ff mọi lúc để đảm bảo rằng dễ dàng xem lịch sử chính xác của bất kỳ tính năng nào nếu chúng tôi muốn điều tra về nó.


3
Tôi hoàn toàn đồng ý; mọi người rất thích bám sát chủ. Nhưng đó là một vấn đề khác, lớn hơn nhiều và ít hơn nhiều dưới ảnh hưởng khiêm tốn của riêng tôi :-P
Standback

2
+1 chogit merge --no-ff
0xcaff

1
Cũng +1 cho git merge --no-ff. Nếu bạn sử dụng gitflow, điều này trở thành mặc định.
David Hammen

10

Hãy để tôi trả lời điểm của bạn trực tiếp và rõ ràng:

Vấn đề của chúng tôi là với các nhóm bên dài hạn - loại mà bạn đã có một vài người làm việc bên lề tách ra từ chủ, chúng tôi phát triển trong một vài tháng, và khi chúng tôi đạt được một cột mốc, chúng tôi đồng bộ hóa cả hai.

Bạn thường không muốn để chi nhánh của bạn không được đồng bộ trong nhiều tháng.

Chi nhánh tính năng của bạn đã phân nhánh một cái gì đó tùy thuộc vào quy trình làm việc của bạn; Hãy gọi nó masterlà vì đơn giản. Bây giờ, bất cứ khi nào bạn cam kết làm chủ, bạn có thể và nên git checkout long_running_feature ; git rebase master. Điều này có nghĩa là các chi nhánh của bạn, theo thiết kế, luôn đồng bộ.

git rebasecũng là điều chính xác để làm ở đây. Nó không phải là một hack hoặc một cái gì đó kỳ lạ hoặc nguy hiểm, nhưng hoàn toàn tự nhiên. Bạn mất một chút thông tin, đó là "sinh nhật" của nhánh tính năng, nhưng đó là thông tin. Nếu someobody thấy điều đó là quan trọng, nó có thể được cung cấp bằng cách lưu nó ở một nơi khác (trong hệ thống vé của bạn, hoặc, nếu nhu cầu là rất lớn, trong một git tag...).

Bây giờ, IMHO, cách tự nhiên để xử lý việc này là, ép các mảnh vụn thành một cam kết duy nhất.

Không, bạn hoàn toàn không muốn điều đó, bạn muốn một cam kết hợp nhất. Một cam kết hợp nhất cũng là một "cam kết duy nhất". Nó không, bằng cách nào đó, chèn tất cả các nhánh riêng lẻ cam kết "vào" chủ. Đó là một cam kết duy nhất với hai cha mẹ - người masterđứng đầu và người đứng đầu chi nhánh tại thời điểm hợp nhất.

Hãy chắc chắn để xác định các --no-fftùy chọn, tất nhiên; sáp nhập mà không --no-ffnên, trong kịch bản của bạn, bị nghiêm cấm. Thật không may, --no-ffkhông phải là mặc định; nhưng tôi tin rằng có một tùy chọn bạn có thể thiết lập để làm cho nó như vậy. Xem git help mergeđể làm gì --no-ff(nói ngắn gọn: nó kích hoạt hành vi tôi đã mô tả trong đoạn trước), nó rất quan trọng.

chúng ta không từ bỏ các tháng phát triển song song vào lịch sử của bậc thầy.

Hoàn toàn không - bạn sẽ không bao giờ bỏ thứ gì đó "vào lịch sử" của một số chi nhánh, đặc biệt là không có cam kết hợp nhất.

Và nếu bất cứ ai cần giải quyết tốt hơn cho lịch sử của sidebranch, tất nhiên, tất cả vẫn còn đó - đó không phải là chủ, nó nằm trong sidebranch.

Với một cam kết hợp nhất, nó vẫn còn đó. Không phải trong chủ, nhưng trong sidebranch, có thể thấy rõ là một trong những cha mẹ của cam kết hợp nhất, và được giữ mãi mãi, như nó phải vậy.

Xem những gì tôi đã làm? Tất cả những điều bạn mô tả cho cam kết squash của bạn đều ở ngay đó với --no-ffcam kết hợp nhất .

Đây là vấn đề: Tôi làm việc riêng với dòng lệnh, nhưng phần còn lại trong nhóm của tôi sử dụng GUIS.

(Nhận xét bên lề: Tôi hầu như chỉ làm việc với dòng lệnh (cũng vậy, đó là lời nói dối, tôi thường sử dụng ma thuật emacs, nhưng đó là một câu chuyện khác - nếu tôi không ở một nơi thuận tiện với thiết lập emacs cá nhân của mình, tôi thích lệnh này dòng cũng). Nhưng hãy làm cho mình một ưu và thử ít nhất git guimột lần. Đó là vì thế hiệu quả hơn để chọn dòng, hunks vv để thêm / hoàn tác thêm.)

Và tôi đã phát hiện ra GUIS không có tùy chọn hợp lý để hiển thị lịch sử từ các chi nhánh khác.

Đó là bởi vì những gì bạn đang cố gắng làm là hoàn toàn trái với tinh thần git. gitxây dựng từ cốt lõi trên một "biểu đồ chu kỳ có hướng", có nghĩa là, rất nhiều thông tin nằm trong mối quan hệ giữa cha mẹ và con cái. Và, đối với sáp nhập, điều đó có nghĩa là cam kết hợp nhất thực sự với hai cha mẹ và một con. GUI của các đồng nghiệp của bạn sẽ ổn ngay khi bạn sử dụng các no-ffcam kết hợp nhất.

Vì vậy, nếu bạn đạt được một cam kết bí đao, nói rằng "sự phát triển này bị đè bẹp từ nhánh XYZ", sẽ rất đau đớn khi đi xem những gì trong XYZ.

Có, nhưng đó không phải là vấn đề của GUI, mà là của cam kết squash. Sử dụng squash có nghĩa là bạn rời khỏi đầu nhánh tính năng và tạo ra một cam kết hoàn toàn mới master. Điều này phá vỡ cấu trúc trên hai cấp độ, tạo ra một mớ hỗn độn lớn.

Vì vậy, họ muốn các nhóm phát triển lớn, dài này được hợp nhất, luôn luôn có một cam kết hợp nhất.

Và họ hoàn toàn đúng. Nhưng họ không phải là "sáp nhập trong ", họ chỉ là sáp nhập. Hợp nhất là một thứ thực sự cân bằng, nó không có mặt ưa thích nào được hợp nhất "thành" bên kia ( git checkout A ; git merge Bhoàn toàn giống với git checkout B ; git merge Angoại trừ những khác biệt nhỏ về thị giác như các nhánh được hoán đổi trong git logv.v.).

Họ không muốn bất kỳ lịch sử nào không thể truy cập ngay lập tức từ nhánh chính.

Điều này là hoàn toàn chính xác. Vào thời điểm không có các tính năng chưa được hợp nhất, bạn sẽ có một nhánh duy nhất mastervới lịch sử phong phú bao trùm tất cả các dòng cam kết tính năng từng có, quay trở lại git initcam kết từ đầu (lưu ý rằng tôi đặc biệt tránh sử dụng thuật ngữ này " các nhánh "ở phần sau của đoạn đó vì lịch sử tại thời điểm đó không còn là" các nhánh "nữa, mặc dù biểu đồ cam kết sẽ khá phân nhánh).

Tôi ghét ý tưởng đó;

Sau đó, bạn đang có một chút đau đớn, vì bạn đang làm việc chống lại công cụ bạn đang sử dụng. Cách gittiếp cận rất thanh lịch và mạnh mẽ, đặc biệt là trong khu vực phân nhánh / sáp nhập; nếu bạn làm đúng (như đã nói ở trên, đặc biệt là với --no-ff) thì đó là những bước nhảy vọt cho các cách tiếp cận khác (ví dụ, sự lộn xộn của việc có cấu trúc thư mục song song cho các nhánh).

nó có nghĩa là một mớ vô tận, không thể tránh khỏi của lịch sử phát triển song song.

Vô tận, song song - có.

Không thể chối cãi, rối - không.

Nhưng tôi không thấy những gì chúng ta có.

Tại sao không làm việc giống như nhà phát minh git, đồng nghiệp của bạn và phần còn lại của thế giới làm, mỗi ngày?

Chúng ta có bất kỳ lựa chọn nào ở đây ngoài việc liên tục sáp nhập các nhóm bên thành chủ với các cam kết hợp nhất không? Hoặc, có lý do nào mà việc liên tục sử dụng các hợp nhất không tệ như tôi sợ không?

Không có lựa chọn khác; không tệ


10

Siết chặt một sidebranch dài hạn sẽ làm cho bạn mất rất nhiều thông tin.

Những gì tôi sẽ làm là cố gắng đẩy chủ nhân vào sidebranch dài hạn trước khi sáp nhập sidebranch thành master . Bằng cách đó, bạn giữ mọi cam kết trong tổng thể, đồng thời làm cho lịch sử cam kết tuyến tính và dễ hiểu hơn.

Nếu tôi không thể làm điều đó một cách dễ dàng ở mỗi lần cam kết, tôi sẽ để nó phi tuyến tính , để giữ cho bối cảnh phát triển rõ ràng. Theo ý kiến ​​của tôi, nếu tôi có một sự hợp nhất có vấn đề trong cuộc nổi loạn của chủ nhân vào bên lề, điều đó có nghĩa là sự phi tuyến tính có ý nghĩa trong thế giới thực. Điều đó có nghĩa là sẽ dễ hiểu hơn những gì đã xảy ra trong trường hợp tôi cần đi sâu vào lịch sử. Tôi cũng nhận được lợi ích ngay lập tức khi không phải thực hiện một cuộc nổi loạn.


: + để đề cập rebase. Dù đó có phải là cách tiếp cận tốt nhất ở đây hay không (cá nhân tôi chưa có trải nghiệm tuyệt vời với nó, mặc dù tôi chưa sử dụng nhiều), nó dường như là điều gần nhất với những gì OP thực sự muốn - cụ thể là thỏa hiệp giữa một bãi rác lịch sử không theo trật tự và hoàn toàn che giấu lịch sử đó.
Kyle Strand

1

Cá nhân tôi thích thực hiện phát triển của mình trong một ngã ba, sau đó kéo các yêu cầu để hợp nhất vào kho lưu trữ chính.

Điều đó có nghĩa là nếu tôi muốn chống lại các thay đổi của mình trên đỉnh chính hoặc xóa một số cam kết WIP, tôi hoàn toàn có thể làm điều đó. Hoặc tôi chỉ có thể yêu cầu rằng toàn bộ lịch sử của tôi cũng được hợp nhất.

Những gì tôi muốn làm là phát triển trên một nhánh nhưng thường xuyên chống lại chủ / dev. Bằng cách đó, tôi nhận được các thay đổi gần đây nhất từ ​​chủ mà không có một loạt các cam kết hợp nhất vào chi nhánh của mình hoặc phải xử lý toàn bộ tải xung đột hợp nhất khi đến lúc hợp nhất thành chủ.

Để trả lời rõ ràng câu hỏi của bạn:

Chúng ta có bất kỳ lựa chọn nào ở đây ngoài việc liên tục sáp nhập các nhóm bên thành chủ với các cam kết hợp nhất không?

Có - bạn có thể hợp nhất chúng một lần trên mỗi nhánh (khi tính năng hoặc sửa lỗi là "hoàn thành") hoặc nếu bạn không muốn có các cam kết hợp nhất trong lịch sử của mình, bạn có thể chỉ cần thực hiện hợp nhất chuyển tiếp nhanh trên chủ sau khi thực hiện phản hồi cuối cùng.


3
Tôi xin lỗi - Tôi cũng làm điều tương tự, nhưng tôi không thấy cách này trả lời câu hỏi: - /
Standback

2
Đã thêm một câu trả lời rõ ràng cho câu hỏi đã nêu của bạn.
Wayne Werner

Vì vậy, điều đó tốt cho các cam kết của riêng tôi, nhưng tôi (và nhóm của tôi) sẽ giải quyết công việc của mọi người . Giữ lịch sử của riêng tôi sạch sẽ là dễ dàng; làm việc trong một lịch sử dev lộn xộn là vấn đề ở đây.
Trở lại

Bạn có nghĩa là bạn muốn yêu cầu các nhà phát triển khác để ... những gì? Không rebase và chỉ squash khi hợp nhất? Hay bạn chỉ đăng câu hỏi này để hiểu về đồng nghiệp của bạn thiếu kỷ luật git?
Wayne Werner

1
thường xuyên khởi động lại không hữu ích nếu một số nhà phát triển đang làm việc trên nhánh tính năng đó.
Paŭlo Ebermann

-1

Kiểm soát sửa đổi là rác thải ra.

Vấn đề là tiến trình làm việc trên nhánh tính năng có thể chứa rất nhiều "hãy thử điều này ... không, nó không hoạt động, hãy thay thế nó bằng" và tất cả các cam kết ngoại trừ "kết thúc" cuối cùng làm ô nhiễm lịch sử một cách vô ích.

Cuối cùng, lịch sử nên được lưu giữ (một số có thể sẽ được sử dụng trong tương lai), nhưng chỉ nên hợp nhất một "bản sao sạch".

Với Git, điều này có thể được thực hiện bằng cách phân nhánh nhánh tính năng trước (để giữ tất cả lịch sử), sau đó (tương tác) khởi động lại nhánh của nhánh tính năng từ chủ và sau đó hợp nhất nhánh bị từ chối.


1
Chỉ cần làm rõ: những gì bạn đang nói là viết lại lịch sử trên (một bản sao) nhánh tính năng, do đó, nó có một lịch sử ngắn, rõ ràng - loại bỏ tất cả các quá trình phát triển ban đầu. Và sau đó, việc hợp nhất nhánh viết lại thành chủ đơn giản và gọn gàng hơn. Tôi đã hiểu đúng về bạn chưa?
Trở lại

1
Đúng. Và khi bạn hợp nhất thành chủ, nó sẽ chỉ là một chuyển tiếp nhanh (giả sử bạn đã nổi loạn gần đây trước khi hợp nhất).
DepressionDaniel

Nhưng lịch sử này sau đó được lưu giữ như thế nào? Bạn có để chi nhánh tính năng ban đầu nằm xung quanh?
Paŭlo Ebermann

@ PaŭloEbermann Bingo.
DepressionDaniel

Vâng, như một người khác đã nói trong một nhận xét: các nhánh chỉ là con trỏ vào biểu đồ lịch sử gitvà chúng là cục bộ. Những gì được đặt tên footrong một repo có thể được đặt tên bartheo một cái khác. Và chúng có nghĩa là tạm thời: Bạn không muốn làm lộn xộn repo của mình với hàng ngàn nhánh tính năng cần được giữ để tránh mất lịch sử. Và bạn sẽ cần phải giữ các nhánh đó để giữ lịch sử tham chiếu, gitcuối cùng sẽ xóa bất kỳ cam kết nào mà nhánh đó không thể truy cập được nữa.
cmaster
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.