2013-12-12 14 views
9

Trong khi mã nguồn tái cấu trúc, đôi khi bạn cần di chuyển khối văn bản lớn bên trong một tệp hoặc thậm chí vào tệp mới. Bạn tạo một chi nhánh refactored và cam kết đi:Đọc git để theo dõi nội dung đã di chuyển (không chỉ đơn giản là di chuyển tệp)

$git checkout master 
$git branch refactored 
$git checkout refactored 
<move code around> 
$git commit -m "refactored code" 

Tuy nhiên, người ta có thể cam kết trên đầu trang của các chi nhánh trước Refactor cũ, thay đổi mã đã được chuyển:

$git checkout master 
<change code that was moved elsewhere on branch refactored> 
$git commit -m "bugfix" 

Mở chi nhánh refactored, bạn sau đó muốn kết hợp các thay đổi được thực hiện trong master:

$git checkout refactored 
$git merge master 
<giant merge conflict> 

Điều này dẫn đến xung đột hợp nhất lớn. Nếu có một cách để nói với git rằng nội dung chỉ đơn giản là di chuyển, nó sẽ có thể hợp nhất tự động.

Phần tồi tệ hơn là, ngay cả sau khi giải quyết các xung đột và commiting nó, git vẫn không thể sử dụng độ phân giải để tìm ra hòa trộn thêm:

<fix conflicts> 
$git commit -m "merge master into refactored" 
$git checkout master 
<change more code> 
$git commit -m "bugfix2" 
$git checkout refactored 
$git merge master 
<another giant merge conflict> 

Đây có phải là có thể tránh được ở tất cả? Tôi đã thử git rerere và không thể giải quyết xung đột ở đây. Có cách nào git có thể thấy di chuyển một khối văn bản như một động thái thực tế, thay vì xóa và chèn? Nếu nó không thể, cách tiếp cận tốt nhất để giảm thiểu xung đột hợp nhất là gì, nếu bạn cần giữ hai nhánh song song trong một thời gian?

Trong khi điều này đủ dễ dàng cho moving the contents of a complete file, tôi không thể tìm thấy thông tin về việc di chuyển chỉ phần của nó hoặc di chuyển bên trong cùng một tệp.

Ngoài ra, nếu có giải pháp cho việc này, hành vi của git blame trên mã số được cấu trúc lại là gì? Nó sẽ trỏ đến cam kết tái cấu trúc, hoặc bỏ qua nó? Có cách nào để đạt được sau này không?

Trong trường hợp có ai quan tâm, tôi đã đặt một mã hóa base64 tar.gz của (rất ít) kho Tôi đang sử dụng để thử nghiệm on pastebin

Giải pháp tiềm năng

Một giải pháp tiềm năng có thể được thực hiện hợp nhất bằng cách áp dụng một bản vá được sửa đổi (tự động) với những thay đổi trong nhánh được tái cấu trúc trước. Có phần mềm nào được phát triển để làm điều này không? Sử dụng phương pháp này, tôi đoán rằng, vì đây là minh bạch để git, git blame sẽ trỏ đến cam kết tái cấu trúc.

Tôi đã tìm thấy the same question, applied to diff. Không có đề cập đến bất kỳ triển khai không độc quyền hiện có, nhưng có đề cập đến một thuật toán theo dõi chuyển động khối

+0

Tôi đề nghị bạn thực hiện nhiều cam kết. Khi bạn thay đổi nhiều dữ liệu, bạn càng có nhiều cam kết, ít gặp vấn đề khi hợp nhất mã. – sensorario

+0

@sensorario, đó là một gợi ý hay nói chung. Tôi không chắc chắn cách bạn áp dụng nó để tái cấu trúc, mặc dù - di chuyển một chức năng/khối nhỏ tại một thời điểm sẽ không giúp đỡ – goncalopp

+0

Nếu bạn thay đổi tệp bạn có hai nội dung khác nhau. Có, cũng nếu bạn di chuyển một chức năng từ một tập tin khác. Nếu bạn muốn giảm thiểu xung đột, hãy thực hiện nhiều cam kết hơn. Vui lòng thử. – sensorario

Trả lời

1

Thật không may là bạn không thể thay thế chiến lược hợp nhất git được tạo sẵn. Điều này có nghĩa là bạn không thể ngừng xung đột, tuy nhiên bạn có thể sử dụng một công cụ thông minh để giải quyết chúng.

này một Semantic Merge vẻ thú vị, nó cũng có thể used by git

+0

Tôi đã thử SemanticMerge trên kho lưu trữ ví dụ. Thứ nhất, trên Linux, nó giới thiệu 80MB phụ thuộc - rất nhiều gói từ plasticcm và những gì dường như là mono. Việc hợp nhất phải được thực hiện bằng tay bằng cách sử dụng 'git mergetool', và công cụ cần tương tác (" Hit return to start ") và sử dụng GUI (không thể chạy nó từ CLI, AFAICT). Cuối cùng, nó không thể hợp nhất các xung đột trong ví dụ của tôi, với "lỗi phân tích cú pháp đã được tìm thấy, cây có thể không phù hợp". Tôi không chắc công cụ này có thực sự làm gì không, vì sau đó tôi nhận được một lỗi "Tham chiếu đối tượng không được đặt thành một thể hiện của một đối tượng". – goncalopp

+0

Để công bằng, tôi đã thử nó trên ubuntu 12.04 LTS (Chính xác tê tê), không nhất thiết được hỗ trợ ('chúng tôi chỉ đảm bảo hỗ trợ cho Debian 6.0, nhưng kho lưu trữ này cũng có thể được nhắm mục tiêu đến phiên bản Debian mới hơn (như 7.0, ví dụ) và các bản phân phối Ubuntu (đặc biệt là các phiên bản LTS) ') – goncalopp

0

Nó không phải là có thể để tránh nỗ lực này, nhưng sau đó một lần nữa đó là cách Git là nghĩa vụ phải làm việc:

Các khác cơ bản quyết định thiết kế thông minh là cách Git hợp nhất. Các thuật toán hợp nhất là thông minh nhưng chúng không cố gắng quá thông minh. Các quyết định rõ ràng được thực hiện tự động, nhưng khi có nghi ngờ , tùy thuộc vào người dùng quyết định. Nó nên như vậy. Bạn không cần muốn một chiếc máy đưa ra quyết định đó cho bạn. Bạn sẽ không bao giờ muốn nó. Đó là thông tin cơ bản trong cách tiếp cận Git để hợp nhất: trong khi mọi hệ thống kiểm soát phiên bản khác đang cố gắng thông minh hơn, Git là vui vẻ tự mô tả là "người quản lý nội dung ngu ngốc" và đó là tốt hơn cho nó.

(Từ Wincent Colaiuta's blog)

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