Git - cách buộc hợp nhất xung đột và hợp nhất thủ công trên tệp đã chọn


82

Chúng tôi duy trì ứng dụng web có nhánh chính chung và nhiều nhánh song song, một nhánh cho từng cài đặt, mỗi ứng dụng có một vài thay đổi cụ thể. Mã nguồn được quản lý bằng git và nó là công cụ tuyệt vời khi chúng ta cần chuyển các tính năng và sửa lỗi từ nhánh chính thành những cái song song. Nhưng có một số tệp nhạy cảm và việc hợp nhất tự động thường cho kết quả không tốt. Vì vậy, việc hợp nhất sẽ dễ dàng hơn nhiều nếu chúng có thể được đánh dấu bằng cách nào đó và mọi hợp nhất sẽ dẫn đến xung đột yêu cầu hợp nhất thủ công.

Tôi đã tìm kiếm câu trả lời:

  1. Tôi đang sử dụng các tùy chọn hợp nhất --no-commit--no-ff , nhưng nó không giống nhau.
  2. Ở đâyở đây ai đó hỏi cùng một câu hỏi nhưng không có giải pháp.
  3. Trường hợp tương tự dường như là cách ngăn tệp được hợp nhất bằng cách sử dụng .gitattributes chứa: somefile.php merge = our . Tôi đã cố gắng tìm một số tùy chọn hợp nhất sẽ tạo ra xung đột hoặc buộc hợp nhất thủ công nhưng không tìm thấy cho đến nay.
  4. .gitattributes chứa: somefile.php -merge không bao giờ được hợp nhất tự động và do đó buộc phải hợp nhất thủ công. Đó là giải pháp 90%, nhưng những gì tôi tìm kiếm là thử hợp nhất tự động và đánh dấu nó là xung đột bất kể nó có thành công hay không. Nhưng điều này cho đến nay là gần nhất với giải pháp. (... cảm ơn Charles Bailey đã làm rõ ...)
  5. Ai đó đề nghị viết trình điều khiển hợp nhất tùy chỉnh ( 1 , 2 ), nhưng làm thế nào để làm điều đó là xa đối với tôi.

chỉnh sửa: biến thể 4. mô tả


6
Đây sẽ không phải là câu trả lời chính xác mà bạn đang tìm kiếm, nhưng vì lý do tương tự tôi làm git fetchtrước, sau đó sử dụng git difftool <file> FETCH_HEAD, vì vậy tôi có thể áp dụng thủ công thay đổi trong nhánh từ xa cho cục bộ.
MHC

MHC: đây là một thủ thuật hay (đặc biệt nếu được lưu trong script cho từng nhánh song song + kết hợp với việc ngăn các tệp tự động hợp nhất). Bất lợi chính là trong quy trình làm việc nhóm có khả năng ai đó quên bước này và thay vào đó chỉ thực hiện hợp nhất bình thường.
Stepan

2
Cài đặt -mergekhông ngăn bạn hợp nhất các tệp, nó chỉ buộc bạn phải làm điều đó theo cách thủ công, ví dụ như với một công cụ hợp nhất. Đây không phải là những gì bạn cần?
CB Bailey

Đó là 90% những gì tôi muốn. Tôi muốn rằng quá trình hợp nhất được thực hiện tự động, nhưng đối với tệp nhạy cảm này, quá trình hợp nhất được coi là xung đột ngay cả khi không có gì nên việc kiểm tra thủ công luôn bị buộc phải thực hiện.
Stepan

@Stepan Tôi đang ở trong tình huống tương tự nên tôi muốn làm rõ điều gì đó. Những gì bạn đang nói rằng với -mergein .gitatttributes git mergekhông có gì, và tất cả công việc phải dừng lại với công cụ hợp nhất? Vì vậy, không có <<<<< ===== >>>> cho công cụ hợp nhất để sử dụng, phải không? Và giải pháp của Dan có cung cấp điều này không?
Nero gris

Câu trả lời:


59

Tùy chọn 5, một trình điều khiển hợp nhất tùy chỉnh, có lẽ là cách để đến gần nhất với những gì bạn muốn. Nó rất dễ thực hiện. Dưới đây là một ví dụ mà tôi nghĩ sẽ giúp bạn khá gần với hành vi mà bạn mong muốn.

Đầu tiên, tạo một kịch bản trình điều khiển hợp nhất có tên merge-and-verify-driver. Làm cho nó có thể thực thi và đặt nó ở một vị trí thích hợp (bạn có thể muốn xem xét kiểm tra tập lệnh này vào repo, thậm chí, vì tệp cấu hình của repo sẽ phụ thuộc vào nó). Git sẽ thực thi tập lệnh shell này để thực hiện hợp nhất các tệp nhạy cảm:

#!/bin/bash
git merge-file "${1}" "${2}" "${3}"
exit 1

Điều này chỉ thực hiện hành vi hợp nhất mặc định mà bản thân Git thường làm. Sự khác biệt chính là tập lệnh luôn trả về khác 0 (để chỉ ra rằng đã có xung đột, ngay cả khi hợp nhất thực sự được giải quyết mà không có xung đột).

Tiếp theo, bạn cần cho Git biết về sự tồn tại của trình điều khiển hợp nhất tùy chỉnh của bạn. Bạn thực hiện việc này trong tệp cấu hình của repo ( .git/config):

[merge "verify"]
        name = merge and verify driver
        driver = ./merge-and-verify-driver %A %O %B

Trong ví dụ này, tôi đã đặt merge-and-verify-drivertrong thư mục cấp cao nhất của repo ( ./). Bạn sẽ cần chỉ định đường dẫn đến tập lệnh cho phù hợp.

Bây giờ, bạn chỉ cần cung cấp cho các tệp nhạy cảm các thuộc tính thích hợp để trình điều khiển hợp nhất tùy chỉnh được sử dụng khi hợp nhất các tệp đó. Thêm cái này vào .gitattributestệp của bạn :

*.sensitive merge=verify

Ở đây, tôi đã nói với Git rằng bất kỳ tệp nào có tên phù hợp với mẫu *.sensitivesẽ sử dụng trình điều khiển hợp nhất tùy chỉnh. Rõ ràng, bạn cần sử dụng mẫu phù hợp với (các) tệp của mình.


Cảm ơn rất nhiều cho hướng dẫn chi tiết này!
Stepan

13
Có vẻ như trình điều khiển hợp nhất không được gọi trong các giải pháp "hiển nhiên". Ví dụ: nếu tệp chỉ được thay đổi trên một nhánh và bạn thực hiện hợp nhất, tệp "nhạy cảm" sẽ bị ghi đè và trình điều khiển hợp nhất sẽ không được gọi. Có cách nào để khắc phục điều đó không?
VitalyB

Liệu điều này có thực sự hoạt động như @VitalyB gợi ý không? cảm ơn!
filippo

1
Điều này hoạt động, nhưng có cách nào để làm cho tùy chọn này trở thành tùy chọn chung trên tất cả các kho lưu trữ trên máy không? Ngoài ra, có cách nào để gọi nó bằng dòng lệnh không? Tôi ước có một cách nào đó để thực hiện việc này đơn giản như thay đổi chiến lược hợp nhất trên dòng lệnh.
user1748155

4
thêm vào bình luận @VitalyB. Hợp nhất cũng không xuất hiện nếu cả hai nhánh thực hiện cùng một thay đổi đối với một tệp. Ví dụ, cả hai chi nhánh tăng phiên bản 1, và bạn muốn tăng 2 trong khi cố gắng kết hợp ... vấn đề Rất thực tế, chưa được giải quyết chưa :(.
VasiliNovikov

1

Hai lệnh này dường như có tác dụng giống như sử dụng trình điều khiển hợp nhất tùy chỉnh:

git merge --no-commit your_target_branch
git checkout --conflict merge .   (do not forget the . and run it in the top dir of the repository)

Lệnh đầu tiên dừng hợp nhất trước khi tạo cam kết hợp nhất và lệnh thứ hai đánh dấu tất cả các tệp được sửa đổi trong hai nhánh là xung đột cần giải quyết ngay cả khi không có xung đột ban đầu.


Tôi thích ý tưởng về giải pháp "một lần" (tôi vừa gặp phải trường hợp như vậy), tuy nhiên điều này không hiệu quả với tôi. Git đã làm một FF dẫn đến một sự hợp nhất tồi (về cơ bản nó là sự hợp nhất của chúng tôi và của chúng tôi).
Nero gris

@Nerogris Thật vậy, nó sẽ không hoạt động đối với các hợp nhất tua đi nhanh. Bạn luôn có thể thêm tùy chọn --no-ff nhưng lệnh thứ hai sẽ không tạo ra xung đột vì không có thay đổi nào so với tổ tiên chung ở một trong hai nhánh của hợp nhất.
louisiuol

Tôi đã đặt ff thành false trong cấu hình chung của mình. Khi tôi nói đó là một hợp nhất FF, tôi có nghĩa là nếu tôi không bảo Git đừng làm những điều đó, thì nó sẽ có.
Nero gris

0

Lưu ý: bài viết này " Viết trình điều khiển hợp nhất git cho tệp PO " minh họa loại thao tác bạn có thể thực hiện khi hợp nhất tệp theo cách thủ công: bạn có thể xử lý trước để hợp nhất thủ công của bạn có sẵn một số dữ liệu nhất định.

git merge-filechẳng hạn, có thể được sử dụng để DECRYPT (và mã hóa lại) tệp trước khi hợp nhất (!)

Trong trường hợp của bạn, việc thoát khỏi trình điều khiển hợp nhất của bạn với trạng thái khác 0 đảm bảo rằng quá trình hợp nhất sẽ là thủ công.


2
Bạn có thể nói rõ hơn về liên kết "hợp nhất trình điều khiển cho các tệp PO" vì điều đó dường như dẫn đến quyền truy cập bị từ chối đối với tôi không? Tôi hy vọng nó sẽ cung cấp câu trả lời cho câu hỏi stackoverflow.com/questions/16214067/...
Mikko Rantalainen

@MikkoRantalainen bị chặn ở cơ quan, vì vậy tôi sẽ cố gắng tối nay từ nhà.
VonC

1
Những "tài xế hợp nhất cho các tập tin PO" không làm việc cho tôi, hoặc :(
sampablokuper

1
@sampablokuper Tôi đồng tình: bài báo bị chặn đối với người đọc "không được phép". Tôi không biết tại sao.
VonC

1
@sampablokuper Tôi không có quyền truy cập vào blog này ngay bây giờ. Tôi sẽ tiếp tục tìm kiếm nội dung của nó.
VonC
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.