Làm thế nào để tôi tiếp cận một sự hợp nhất phức tạp


25

Đây là thỏa thuận, tôi đã gia nhập một công ty mới và đã được yêu cầu hoàn thành công việc tại một chi nhánh đã không được chạm tới trong gần một năm. Trong khi đó, chi nhánh chính đã phát triển với một tốc độ ổn định. Lý tưởng nhất là tôi muốn hợp nhất tất cả các thay đổi từ nhánh chính vào nhánh tính năng và tiếp tục công việc từ đó, nhưng tôi không chắc chắn làm thế nào để tiếp cận điều này.

Làm cách nào để thực hiện hợp nhất này một cách an toàn trong khi vẫn bảo tồn các thay đổi quan trọng ở cả hai phía của chi nhánh?


Cảm ơn tất cả mọi người vì phản hồi tuyệt vời. Tôi sẽ cho git-imerge đi và nếu điều đó trở nên lộn xộn, tôi sẽ sử dụng một cách tiếp cận chi nhánh mới!
Vlad Spreys

Bất cứ ai có thể giải thích tại sao chúng ta không thể sử dụng git cherry-pickở đây?
Santosh Kumar

1. Cầu nguyện. 2. nổi loạn. 3. kiểm tra. 4. hợp nhất.
AK_

1
Tôi thích nổi loạn trong tình huống này vì nó sẽ đi theo cam kết. Nó cũng sẽ cho phép bạn xóa sạch tính năng mới trước khi bạn cung cấp mã hợp nhất. YMMV.
Stephen

Câu trả lời:


27

Về cốt lõi, làm thế nào để kết hợp hai đoạn mã (có thể không tương thích) là một vấn đề phát triển , không phải là vấn đề kiểm soát phiên bản . Lệnh hợp nhất Git có thể giúp trong quá trình này, nhưng nó phụ thuộc vào hình dạng của vấn đề.

So sánh cả hai phiên bản với cơ sở đầu tiên có ý nghĩa nhất. Điều này sẽ cung cấp cho bạn một ý tưởng về chiến lược tốt nhất để thực hiện điều này. Cách tiếp cận của bạn có thể khác nhau dựa trên tính chất và sự chồng chéo của những thay đổi trong mỗi nhánh.

Hãy tưởng tượng kịch bản lý tưởng: bạn sẽ khám phá ra rằng nhánh chính và nhánh tính năng mỗi phần chỉ sửa đổi các phần loại trừ lẫn nhau của mã, vì vậy bạn có thể thực hiện tất cả các thay đổi trong đó và sẽ tốt hơn.

Tất nhiên, điều đó gần như chắc chắn sẽ không xảy ra, nhưng câu hỏi đặt ra là: nó sẽ bị loại bỏ khỏi kịch bản lý tưởng này đến mức nào? tức là xen kẽ những thay đổi như thế nào?

Ngoài ra, làm thế nào trưởng thành là nhánh tính năng cũ? Nó có ở trạng thái hoạt động tốt hay không (hoặc chưa biết)? Bao nhiêu tính năng đã được hoàn thành?

Nếu mã liên quan trong nhánh chính đã thay đổi rất nhiều trong năm qua hoặc tính năng này không ở trạng thái hoàn thiện, tôi có thể xem xét việc tạo một nhánh mới của tính năng mới nhất và kết hợp lại tính năng cũ một cách thủ công. Điều này sẽ cho phép bạn thực hiện một cách tiếp cận gia tăng để làm cho nó hoạt động.

Nếu bạn thực hiện một sự kết hợp lộn xộn của rất nhiều mã và nó không hoạt động, sẽ rất khó để gỡ lỗi. Nếu chi nhánh chính đã thay đổi rất nhiều trong năm qua, những thay đổi thiết kế lớn có thể cần thiết cho tính năng này để làm cho nó hoạt động. Sẽ không phù hợp để thực hiện những thay đổi này thông qua "giải quyết xung đột", vì điều này sẽ yêu cầu thực hiện tất cả các thay đổi cùng một lúc và hy vọng nó hoạt động. Vấn đề này sẽ được giải quyết bằng khả năng lỗi trong nhánh đã hoàn thành một phần cũ.


+1 "Tôi có thể xem xét việc tạo một ngã ba mới mới nhất và kết hợp thủ công tính năng cũ một lần nữa"
mika

1
Câu hỏi quan trọng đầu tiên là: nhánh tính năng cũ có xây dựng không? Nó có chạy không? Nếu không, sẽ rất khó để kiểm tra sự hợp nhất của bạn.
Móż

22

Theo kinh nghiệm git hạn chế của tôi, tôi có thể nói rằng đôi khi việc khởi động lại nhánh tính năng lại nhanh hơn nếu chủ đã đi quá xa điểm tách ra.

Hợp nhất hai chi nhánh mà không biết lịch sử đằng sau mã (cho rằng bạn vừa tham gia dự án) thực sự khó khăn và tôi cá rằng ngay cả một nhà phát triển đã theo dõi dự án ngay từ đầu cũng có thể mắc một số sai lầm trong việc hợp nhất.

Điều này tất nhiên có ý nghĩa nếu nhánh tính năng không lớn, nhưng bạn có thể chỉ cần mở nhánh tính năng cũ , mở lại từ chủ và giới thiệu lại các thay đổi theo cách thủ công tạo ra tính năng đó. Tôi biết đó là cách tiếp cận thủ công nhất, nhưng nó cho phép bạn kiểm soát hoàn toàn trong trường hợp thiếu mã hoặc di chuyển mã.

Lập trình cặp với một tiền bối trong trường hợp này sẽ là trường hợp tốt nhất, giúp bạn hiểu rõ hơn về mã.
Nó thậm chí có thể trở nên nhanh hơn, nếu bạn tính đến xung đột hợp nhất và thời gian thử nghiệm!

Tôi nghĩ rằng ít nhất là cố gắng hợp nhất rõ ràng là điều tốt nhất để làm. Nếu điều đó không thành công hoặc trở nên quá khó khăn, thì hãy thử hái anh đào, nếu điều đó sai đi theo cách thủ công.


2
Chắc chắn không phải là cách tiếp cận chính xác.
Andy

12
không, đây là cách tiếp cận chính xác - nếu bạn có một nhánh cổ xưa và bạn không biết mã, cố gắng hợp nhất sẽ không thành công và nó sẽ rất rủi ro. Xác định các thay đổi ban đầu được thực hiện, điều tra xem liệu chúng thậm chí có liên quan đến mã mới hay không, và sau đó áp dụng chúng để có ý nghĩa là cách để thực hiện. Đây là một cách tiếp cận thủ công, nhưng trong những trường hợp này, cách duy nhất an toàn để thực hiện. Tất nhiên, tôi vẫn thử hợp nhất trước, chỉ để xem điều gì xảy ra và tôi sẽ kiểm tra nhật ký để xem có bao nhiêu thay đổi xảy ra trên chi nhánh - có thể là tầm thường.
gbjbaanb

10
@DavidPacker: Tôi không nghĩ rằng GavianoGrifoni đề nghị ném tất cả các công việc quá mức. Ông đề nghị chuyển các thay đổi từ nhánh cũ theo cách thủ công sang dòng phát triển hiện tại, theo cách từng bước. Điều đó sẽ ném lịch sử cũ đi, không hơn.
Doc Brown

3
@DavidPacker Thứ nhất: chi nhánh đã hết hạn một năm, thứ 2: anh chàng được giao nhiệm vụ hoàn thiện nó hoàn toàn không biết mã. Với 2 yếu tố này, áp dụng lại thủ công là cách thực tế duy nhất để tiếp cận nhiệm vụ. Không ai đề xuất một bản sao đơn giản của bản sửa đổi mẹo của chi nhánh cũ.
gbjbaanb

5
@DavidPacker: Hợp nhất các xung đột có thể trở thành xấu xa - nếu bạn phải giải quyết 500 trong số chúng cùng một lúc trước khi bạn có được chương trình trong trạng thái có thể kiểm tra và kiểm tra lại được. Đó là loại tình huống mà OP đang mong đợi ở đây. Nếu bạn nghĩ rằng có thể sử dụng git một cách hiệu quả để tránh tình huống "tất cả hoặc không có gì" này, tại sao bạn không chỉnh sửa câu trả lời của mình và nói với OP cách thực hiện điều này?
Doc Brown

16

git-imerge được thiết kế chính xác cho mục đích này. Nó là một công cụ git cung cấp một phương thức để hợp nhất gia tăng . Bằng cách hợp nhất gia tăng, bạn chỉ cần xử lý các va chạm giữa hai phiên bản, không bao giờ hơn. Hơn nữa, số lượng hợp nhất lớn hơn nhiều có thể được thực hiện tự động vì các thay đổi riêng lẻ nhỏ hơn.


6

Cố gắng hợp nhất đầu đường chính vào một nhánh cũ có thể là một bài tập trong sự thất vọng và làm sâu thêm vết lõm trên bàn bằng trán của bạn.

Tuyến chính không đi đến đâu trong một tháng. Nó cũng có sự phát triển và phát hành. Cố gắng mang tất cả cập nhật trong một hợp nhất nguyên khối có thể là quá sức.

Thay vào đó, hãy bắt đầu bằng cách hợp nhất từ ​​tính năng đầu tiên hợp nhất trở lại vào dòng chính sau khi tách nhánh cũ. Làm cho hợp nhất làm việc. Sau đó, tính năng tiếp theo hợp nhất. Và như vậy. Nhiều trong số các tính năng hợp nhất sẽ hợp nhất mà không có xung đột. Điều quan trọng là phải đảm bảo rằng chức năng hiện tại của nhánh cũ vẫn tương thích với hướng mà tuyến chính đã đi.

Bạn có thể muốn phân nhánh từ người đứng đầu chi nhánh cũ cho vai trò hợp nhất trong các thay đổi khác. Đây là nhiều hơn về việc đảm bảo rằng các cam kết và lịch sử khi ai đó nhìn lại nó rõ ràng và truyền đạt vai trò và chính sách của mỗi chi nhánh là gì. Nhánh cũ là một nhánh tính năng. Một trong những bạn đang làm việc là một chi nhánh tích lũy và hòa giải.

Phần lớn việc này sẽ dễ dàng hơn nếu tính năng cũ hoặc các nhánh phát hành vẫn tồn tại ngoài đó và có thể truy cập dễ dàng (một số nơi có chính sách làm sạch tên của các nhánh cũ hơn một số ngày để danh sách các nhánh không bị áp đảo ).

Điều quan trọng trong tất cả những điều này là đảm bảo rằng bạn kiểm tra và sửa chữa sau khi hợp nhất thành công từng phần của lịch sử tuyến chính vào vị trí. Mặc dù một cái gì đó có thể hợp nhất mà không có xung đột, điều đó chỉ có nghĩa là không xung đột. Nếu cách mà tính năng cũ bị truy cập bị phản đối hoặc bị loại bỏ, có thể cần phải sửa lỗi sau khi hợp nhất thành công.

Bên cạnh đó, điều này cũng hoạt động cho các hệ thống kiểm soát phiên bản khác. Thỉnh thoảng tôi cần phải hợp nhất một nhóm svn cụ thể vào một nhánh (hái anh đào) cho một tính năng, sửa nhánh để hoạt động với tính năng đó và sau đó hợp nhất nhóm svn tiếp theo thay vì chỉ thực hiện svn bán buôn hợp nhất.

Mặc dù người ta có thể thực hiện git cherry-pick ở đây và nó cho phép mang lại những cam kết cụ thể , nhưng điều này có một số nhược điểm có thể làm phức tạp quá trình. Lựa chọn anh đào sẽ không hiển thị thông tin về cam kết bạn đã chọn (bạn có thể thêm nó vào thông điệp cam kết). Điều này làm cho việc theo dõi các cam kết trong lịch sử khó hơn.

Hơn nữa, điều đó có nghĩa là bạn sẽ không phát lại chính chủ một cách hiệu quả trên nhánh cũ - bạn sẽ chọn các tính năng có thể không đầy đủ - và các tính năng đó có thể bị lỗi.

Lý do chính mà người ta nên hợp nhất từ các cam kết lịch sử để làm chủ trên nhánh cũ là để có thể giữ, hãy gọi nó là "lịch sử tương lai" của nhánh cũ trong trạng thái mà bạn có thể suy luận. Bạn có thể thấy rõ sự hợp nhất từ ​​lịch sử vào nhánh cũ và các bản sửa lỗi để tái hòa nhập chức năng. Các tính năng đang được thêm vào theo thứ tự như chúng đã thành thạo. Và khi bạn đã hoàn tất, và cuối cùng thực hiện việc hợp nhất từ ​​người đứng đầu lên nhánh cũ, bạn biết rằng mọi thứ đã được hợp nhất và bạn không bỏ lỡ bất kỳ cam kết nào.


+1 Đây là một giải pháp thay thế tiềm năng thú vị sử dụng hợp nhất để kết hợp các thay đổi lớn. Tuy nhiên, tôi có thể thấy một nhược điểm: giả sử bạn có các phiên bản chính ABCDE và bạn muốn kết hợp nhánh tính năng A1 vào E. Có thể có rất nhiều nỗ lực lãng phí khi hợp nhất mã vào BC và D. Ví dụ: nếu D thành E là gì một thay đổi thiết kế lớn làm cho các thay đổi gia tăng trong B, C và D không liên quan? Ngoài ra, nó một lần nữa phụ thuộc vào mức độ trưởng thành của tính năng ở vị trí đầu tiên. Một cách tiếp cận tiềm năng hữu ích, nhưng sự phù hợp của nó cần được xem xét trước khi bắt đầu.

1

Bước 1. Tìm hiểu về mã, phân tích kiến ​​trúc của nó và các thay đổi đã được thực hiện trên cả hai nhánh kể từ tổ tiên chung mới nhất.

Bước 2. Nếu tính năng này xuất hiện độc lập rộng rãi và chủ yếu chạm vào các khu vực khác nhau của mã, hợp nhất, sửa lỗi xung đột, kiểm tra, sửa chữa, v.v ... Đó là con đường hạnh phúc, bạn sẽ khá tốt để đi. Nếu không, hãy đến Bước 3

Bước 3. Phân tích các lĩnh vực xung đột, hiểu chi tiết về tác động và lý do chức năng. Có thể dễ dàng có xung đột trong các yêu cầu kinh doanh được đưa ra ánh sáng ở đây. Thảo luận với BA, các nhà phát triển khác khi thích hợp. Hãy cảm nhận sự phức tạp liên quan đến việc giải quyết nhiễu.

Bước 4. Trước những điều trên, hãy quyết định xem có nên hợp nhất / chọn cherry / thậm chí cắt chỉ dán những phần không xung đột và viết lại các phần xung đột hay không, hoặc có nên viết lại toàn bộ tính năng từ đầu không .


0

1. Chuyển sang nhánh được sử dụng làm nhánh phát triển / phát hành chính.

Đây là chi nhánh chứa các thay đổi mới nhất cho hệ thống. Có thể master, core, dev, nó phụ thuộc vào công ty. Trong trường hợp của bạn, nó có thể là mastertrực tiếp.

git checkout master
git pull

Kéo để đảm bảo bạn có phiên bản mới nhất của nhánh phát triển chính.

2. Thanh toán và kéo chi nhánh chứa công việc bạn phải hoàn thành.

Bạn kéo để đảm bảo rằng bạn thực sự có nội dung mới nhất của chi nhánh. Bằng cách kiểm tra trực tiếp, không cần tạo cục bộ trước, bạn đảm bảo không có nội dung mới từ master(hoặc nhánh dev chính tương ứng) trong đó.

git checkout <name of the obsolete branch>
git pull origin <name of the obsolete branch>

3. Hợp nhất nhánh phát triển chính thành nhánh lỗi thời.

Trước khi chạy lệnh sau, hãy đảm bảo, bằng cách nhập git branchhoặc git statusbạn đang ở nhánh lỗi thời.

git merge master

Các git mergelệnh sẽ cố gắng kết hợp các nội dung từ các chi nhánh quy định, trong trường hợp này master, để các chi nhánh bạn hiện tại đang có.

Nhấn mạnh vào sẽ cố gắng . Có thể có xung đột hợp nhất, chỉ cần bạn và bạn giải quyết.

4. Khắc phục xung đột hợp nhất, cam kết và đẩy sửa lỗi xung đột

Sau khi sửa lỗi xung đột hợp nhất trong tất cả các tệp có, giai đoạn, cam kết và đẩy giải quyết xung đột sang origin.

git add .
git commit -m "fixed the merge conflict from the past year to update the branch"
git push

Bạn thường có thể gọi git add .đến giai đoạn tất cả các tệp cho cam kết. Khi xử lý xung đột hợp nhất, bạn muốn tất cả các tệp cần thiết được cập nhật.

Ghi chú bổ sung

Giải quyết xung đột hợp nhất có thể là một công việc tẻ nhạt. Đặc biệt nếu bạn là người mới tại một công ty. Bạn thậm chí có thể không có kiến ​​thức phù hợp để giải quyết tất cả các xung đột hợp nhất một mình.

Dành thời gian của bạn để kiểm tra cẩn thận tất cả các xung đột đã xảy ra và khắc phục chúng một cách thích hợp, trước khi tiếp tục công việc của bạn.


Điều đó có thể xảy ra vì vậy, bạn bắt đầu làm việc trên một chi nhánh cũ một năm, hợp nhất trạng thái phát triển hiện tại vào đó và sẽ không có bất kỳ xung đột hợp nhất nào cả.

Điều này xảy ra khi mặc dù hệ thống đã thay đổi rất nhiều trong năm, nhưng không ai chạm vào các tệp thực sự bị thay đổi trong nhánh một năm tuổi.


6
# 4 có khả năng là vấn đề. Nếu có nhiều thay đổi trong năm ngoái, những thay đổi lớn đối với tính năng cũ có thể được yêu cầu. Làm điều này bằng cách hợp nhất đòi hỏi bạn phải thực hiện các thay đổi lớn đối với mã tất cả trong một lần và hy vọng nó hoạt động, đó không phải là thực tiễn phát triển tốt. Cộng với ai biết trạng thái của tính năng chưa hoàn thành là gì? Bạn có thể kết thúc với một mớ hỗn độn mã không hoạt động, và ai biết liệu đó có phải là do vấn đề với bản gốc hoặc những thay đổi bạn đã thực hiện không?

David, miễn là phương pháp tiêu chuẩn này hoạt động, nó vẫn ổn, và OP nên thử điều này trước. Nhưng chắc chắn có nguy cơ nhận quá nhiều xung đột hợp nhất trong tình huống được mô tả để xử lý chúng theo cách "tất cả hoặc không có gì" này.
Doc Brown

@ dan1111 Rằng có những xung đột hợp nhất là hoàn toàn OK, và trên thực tế, vượt qua chúng là con đường để đi. Vì chi nhánh không được sử dụng trong một năm, bạn có thể chắc chắn rằng nó không có gì quan trọng và sẽ không ảnh hưởng nhiều đến hệ thống. Vì vậy, mặc dù chi nhánh chậm hơn một năm, bạn có thể nhận được ít nhất 2 đến không có xung đột hợp nhất.
Andy

4
Giả định rằng chi nhánh này không quan trọng là không có cơ sở. Nó có thể là một thay đổi thiết kế cơ bản đã bị bỏ rơi và bây giờ được chọn lại. Nó có thể là bất cứ điều gì. Bạn đúng rằng đó có thể là một vấn đề đơn giản và có thể có ít hoặc không có xung đột - trong trường hợp đó câu trả lời của bạn sẽ đúng. Nhưng đó không phải là khả năng duy nhất.

@ dan1111 Nếu ai đó chưa chạm vào một vị trí tính năng trong một chi nhánh riêng trong một năm, điều đó sẽ không phản ánh về những thay đổi hệ thống nhiều như vậy. Điều này xuất phát từ kinh nghiệm của riêng tôi với các chi nhánh (6+ tháng tuổi) đã lỗi thời.
Andy
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.