Giải quyết xung đột Git với tệp nhị phân


464

Tôi đã sử dụng Git trên Windows (msysgit) để theo dõi các thay đổi cho một số công việc thiết kế tôi đang làm.

Hôm nay tôi đã làm việc trên một PC khác (với repo từ xa brian) và bây giờ tôi đang cố gắng hợp nhất các chỉnh sửa được thực hiện ngày hôm nay trở lại phiên bản cục bộ thông thường trên máy tính xách tay của tôi.

Trên máy tính xách tay của tôi, tôi đã sử dụng git pull brian masterđể thay đổi các phiên bản địa phương của mình. Mọi thứ đều ổn ngoài tài liệu InDesign chính - điều này cho thấy như một cuộc xung đột.

Phiên bản trên PC ( brian) là phiên bản mới nhất mà tôi muốn giữ nhưng tôi không biết lệnh nào cho repo sử dụng lệnh này.

Tôi đã cố gắng sao chép trực tiếp tệp trên máy tính xách tay của mình nhưng điều này dường như phá vỡ toàn bộ quá trình hợp nhất.

ai đó có thể chỉ cho tôi phương hướng đúng không?

Câu trả lời:


854

git checkoutchấp nhận một --ourshoặc --theirstùy chọn cho các trường hợp như thế này. Vì vậy, nếu bạn có xung đột hợp nhất và bạn biết bạn chỉ muốn tệp từ nhánh bạn đang hợp nhất, bạn có thể thực hiện:

$ git checkout --theirs -- path/to/conflicted-file.txt

để sử dụng phiên bản đó của tập tin. Tương tự, nếu bạn biết bạn muốn phiên bản của mình (không phải phiên bản được hợp nhất), bạn có thể sử dụng

$ git checkout --ours -- path/to/conflicted-file.txt

47
Tôi đã phải chạy 'git reset đường dẫn CHÍNH / đến / mâu thuẫn-file.txt' trên tệp trước khi sử dụng --ours, nếu không nó dường như không có hiệu lực.
Zitrax

6
@Zitrax Bạn có khác tệp sau khi chạy git checkout --ourskhông? Trang man gợi ý (IMHO) rằng thanh toán --ours / - của họ sẽ xóa thay đổi khỏi danh sách "cả sửa đổi, cần hợp nhất" và thêm nó vào chỉ mục và tôi nghĩ điều đó không chính xác. Tôi tin rằng bạn sẽ cần phải chạy git addsau khi thanh toán.
Tim Keat

15
Lưu ý: bạn vẫn muốn thực hiện "git add Xung đột-file.txt " và "git commit". Handily, khi tôi đã thử nó, thông điệp cam kết đã được điền trước bằng một ghi chú về xung đột.
Edward Falk

2
Phrasing của "nhánh bạn đang sáp nhập" rất nguy hiểm gần với "nhánh bạn đang sáp nhập", tôi nghĩ rằng chỉ cần bỏ giới từ sẽ tốt hơn: "nhánh bạn đang sáp nhập", cũng sẽ phản ánh lệnh git (tức là git merge branch_name).
andrybak

13
Một vài điểm quan trọng luôn thiếu trong phần giải thích về chủ đề này. Khi thực hiện rebase thay vì hợp nhất, ý nghĩa của --their--oursđược hoán đổi, tức là --their == nhánh thanh toán hiện tại và --ours là nhánh, thường là một nhánh từ xa hoặc thông số đường dẫn mà bạn đang cố gắng hợp nhất vào hiện tại chi nhánh. Các [space]--[space]disambiguates tùy chọn để con đường đặc tả giữa tên chi nhánh và đường dẫn spec mà cả hai xảy ra để tồn tại với cùng tên (ví dụ một cái tên chi nhánh hiện tại là "abc" và một thư mục tồn tại được gọi là "abc").
BoiseBakes

147

Bạn phải giải quyết xung đột theo cách thủ công (sao chép tệp qua) và sau đó cam kết tệp (bất kể bạn đã sao chép hoặc sử dụng phiên bản cục bộ) như thế này

git commit -a -m "Fix merge conflict in test.foo"

Git thường tự động sau khi hợp nhất, nhưng khi phát hiện xung đột, nó không thể tự giải quyết, nó áp dụng tất cả các bản vá mà nó đã tìm ra và để phần còn lại cho bạn giải quyết và cam kết bằng tay. Trang Git Merge Man , Khóa học Git-SVN hoặc mục blog này có thể làm sáng tỏ về cách thức hoạt động của nó.

Chỉnh sửa: Xem bài đăng dưới đây, bạn thực sự không phải sao chép các tệp, nhưng có thể sử dụng

git checkout --ours -- path/to/file.txt
git checkout --theirs -- path/to/file.txt

để chọn phiên bản của tập tin bạn muốn. Sao chép / chỉnh sửa tập tin sẽ chỉ cần thiết nếu bạn muốn kết hợp cả hai phiên bản.

Vui lòng đánh dấu câu trả lời mipadis là đúng.


1
Cảm ơn vì điều đó. Tôi không chắc chắn nếu có một số cách tích hợp để đánh dấu một tệp là 'chính xác'. Giải thích tại sao tôi không thể tìm thấy lệnh không tồn tại!
Kevin Wilson

Đúng, đó là một chút không trực quan - một cái gì đó như git giải quyết sẽ tốt, nhưng cũng sẽ là một bước bổ sung ...
ROLA

120

Bạn cũng có thể khắc phục vấn đề này với

git mergetool

nguyên nhân gittạo ra các bản sao cục bộ của nhị phân xung đột và sinh ra trình soạn thảo mặc định của bạn trên chúng:

  • {conflicted}.HEAD
  • {conflicted}
  • {conflicted}.REMOTE

Rõ ràng bạn không thể chỉnh sửa các tệp nhị phân một cách hữu ích trong trình soạn thảo văn bản. Thay vào đó, bạn sao chép {conflicted}.REMOTEtệp mới {conflicted}mà không đóng trình chỉnh sửa. Sau đó, khi bạn đóng trình soạn thảo gitsẽ thấy rằng bản sao làm việc chưa được chỉnh sửa đã được thay đổi và xung đột hợp nhất của bạn được giải quyết theo cách thông thường.


8
Nếu các tệp lớn hoặc bạn không muốn mạo hiểm mở tệp nhị phân trong trình soạn thảo văn bản, bạn có thể nhấn ctrl + c tại dấu nhắc mergetool (" Hit return to start merge resolution tool") và git sẽ để các tệp bổ sung vào vị trí. Sau đó, bạn có thể sửa đổi chúng hoặc hợp nhất chúng trong một công cụ bên ngoài (hữu ích cho các định dạng tài liệu nhị phân như LibreOffice / OpenOffice / MSWord) và lưu kết quả trở lại tên tệp gốc. Để thông báo cho git rằng xung đột đã được giải quyết, git addtên tệp gốc và sau đó bạn có thể hoàn thành cam kết hợp nhất.
Felix

18

Để giải quyết bằng cách giữ phiên bản trong nhánh hiện tại của bạn (bỏ qua phiên bản từ nhánh bạn đang hợp nhất), chỉ cần thêm và cam kết tệp:

git commit -a

Để giải quyết bằng cách ghi đè phiên bản trong nhánh hiện tại của bạn bằng phiên bản từ nhánh bạn đang hợp nhất, trước tiên bạn cần truy xuất phiên bản đó vào thư mục làm việc của mình, sau đó thêm / cam kết nó:

git checkout otherbranch theconflictedfile
git commit -a

Giải thích chi tiết hơn


1
Tôi thích biến thể này hơn câu trả lời được chấp nhận, bởi vì nó trực quan hơn, đặc biệt là xem xét rằng ý nghĩa của "--ours" và "--theirs" được hoán đổi trong trường hợp nổi loạn.
Antony Hatchkins

11

Câu trả lời của mipadi không phù hợp với tôi, tôi cần phải làm điều này:

kiểm tra git - đường dẫn / đến / file.bin

hoặc, để giữ cho phiên bản được hợp nhất trong:

kiểm tra git - đường dẫn / đến / file.bin

sau đó

git thêm đường dẫn / đến / file.bin

Và sau đó tôi đã có thể thực hiện "git mergetool" một lần nữa và tiếp tục cuộc xung đột tiếp theo.


6

Từ các git checkouttài liệu

git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>...

--ours
--theirs
Khi kiểm tra các đường dẫn từ chỉ mục, hãy kiểm tra giai đoạn # 2 ( ours) hoặc # 3 ( theirs) để biết các đường dẫn không được trộn.

Chỉ mục có thể chứa các mục nhập không được hợp nhất do hợp nhất không thành công trước đó. Theo mặc định, nếu bạn cố kiểm tra một mục như vậy từ chỉ mục, thao tác thanh toán sẽ thất bại và không có gì được kiểm tra. Sử dụng -fsẽ bỏ qua các mục không hợp nhất. Các nội dung từ một mặt cụ thể của hợp nhất có thể được kiểm tra ra khỏi chỉ mục bằng cách sử dụng --ourshoặc --theirs. Với -m, các thay đổi được thực hiện cho tệp cây làm việc có thể được loại bỏ để tạo lại kết quả hợp nhất xung đột ban đầu.


4

Tôi đã gặp một vấn đề tương tự (muốn thực hiện một cam kết bao gồm một số tệp nhị phân gây ra xung đột khi sáp nhập), nhưng đã gặp một giải pháp khác có thể được thực hiện hoàn toàn bằng git (nghĩa là không phải sao chép thủ công các tệp). Tôi hình dung tôi sẽ đưa nó vào đây để ít nhất tôi có thể nhớ nó vào lần tiếp theo tôi cần. :) Các bước trông như thế này:

% git fetch

Điều này tìm nạp (các) cam kết mới nhất từ ​​kho lưu trữ từ xa (bạn có thể cần chỉ định tên chi nhánh từ xa, tùy thuộc vào thiết lập của bạn), nhưng không thử hợp nhất chúng. Nó ghi lại các cam kết trong FETCH_HEAD

% git checkout FETCH_HEAD stuff/to/update

Cái này lấy bản sao của các tệp nhị phân mà tôi muốn và ghi đè lên những gì trong cây làm việc với phiên bản được lấy từ nhánh từ xa. git không cố gắng thực hiện bất kỳ sự hợp nhất nào, vì vậy bạn chỉ cần kết thúc với một bản sao chính xác của tệp nhị phân từ nhánh từ xa. Khi đã xong, bạn có thể thêm / cam kết bản sao mới giống như bình thường.


4

Quy trình này là để giải quyết xung đột tệp nhị phân sau khi bạn đã gửi yêu cầu kéo tới Github:

  1. Vì vậy, trên Github, bạn thấy yêu cầu kéo của mình có xung đột trên tệp nhị phân.
  2. Bây giờ hãy quay lại chi nhánh git trên máy tính cục bộ của bạn.
  3. Bạn (a) tạo lại / xây dựng lại tệp nhị phân này một lần nữa và (b) cam kết tệp nhị phân kết quả cho cùng nhánh git này.
  4. Sau đó, bạn đẩy chi nhánh git này một lần nữa vào Github.

Trên Github, theo yêu cầu kéo của bạn, xung đột sẽ biến mất.


Đây chính xác là thủ tục tôi cần
Huifang Feng

2

Nếu nhị phân là một cái gì đó nhiều hơn một dll hoặc một cái gì đó có thể được chỉnh sửa trực tiếp như hình ảnh hoặc tệp pha trộn (và bạn không cần phải rác / chọn một tệp này hoặc tệp khác), một sự hợp nhất thực sự sẽ giống như:

Tôi đề nghị tìm kiếm một công cụ tìm khác biệt hướng đến tệp nhị phân của bạn là gì, ví dụ như có một số công cụ miễn phí cho các tệp hình ảnh chẳng hạn

và so sánh chúng.

Nếu không có công cụ tìm khác để so sánh các tệp của bạn, thì nếu bạn có trình tạo gốc của tệp bin (nghĩa là tồn tại trình chỉnh sửa cho nó ... như máy xay 3d, thì bạn cũng có thể kiểm tra các tệp đó theo cách thủ công xem nhật ký và hỏi người khác những gì bạn nên đưa vào) và thực hiện xuất ra các tệp với https://git-scm.com/book/es/v2/Git-Tools-Avised-Merging#_manual_remerge

$ git show :1:hello.blend > hello.common.blend $ git show :2:hello.blend > hello.ours.blend $ git show :3:hello.blend > hello.theirs.blend


1

Tôi đã bắt gặp hai chiến lược để quản lý diff / merge các tệp nhị phân với Git trên windows.

  1. Rùa git cho phép bạn định cấu hình các công cụ diff / merge cho các loại tệp khác nhau dựa trên các phần mở rộng tệp của chúng. Xem 2.35.4.3. Cài đặt nâng cao / hợp nhất http://tortoisegit.org/docs/tortoisegit/tgit-dug-sinstall.html . Chiến lược này tất nhiên dựa vào các công cụ diff / merge phù hợp đang có sẵn.

  2. Sử dụng các thuộc tính git, bạn có thể chỉ định một công cụ / lệnh để chuyển đổi tệp nhị phân của mình thành văn bản và sau đó để công cụ diff / merge mặc định của bạn thực hiện điều đó. Xem http://git-scm.com/book/it/v2/Customizing-Git-Git-Attribution . Bài báo thậm chí còn đưa ra một ví dụ về việc sử dụng dữ liệu meta cho hình ảnh khác.

Tôi có cả hai chiến lược để làm việc với các tệp nhị phân của các mô hình phần mềm, nhưng chúng tôi đã sử dụng tortit git vì cấu hình rất dễ dàng.


0

Tôi sử dụng Git Workflow cho Excel - https://www.xltrail.com/blog/git-workflow-for-excel để giải quyết hầu hết các vấn đề hợp nhất tệp nhị phân của tôi. Ứng dụng mã nguồn mở này giúp tôi giải quyết các vấn đề một cách hiệu quả mà không mất quá nhiều thời gian và cho phép tôi chọn phiên bản đúng của tệp mà không có bất kỳ sự nhầm lẫn nào.


0

trường hợp của tôi có vẻ như là một lỗi .... sử dụng git 2.21.0

Tôi đã thực hiện ... nó phàn nàn về các tệp nhị phân:

warning: Cannot merge binary files: <path>
Auto-merging <path>
CONFLICT (content): Merge conflict in <path>
Automatic merge failed; fix conflicts and then commit the result.

Và sau đó không có gì trong bất kỳ câu trả lời nào ở đây dẫn đến bất kỳ đầu ra nào có ý nghĩa.

Nếu tôi nhìn vào tập tin nào tôi có bây giờ ... đó là tập tin tôi đã chỉnh sửa. Nếu tôi làm một trong hai:

git checkout --theirs -- <path>
git checkout --ours -- <path>

Tôi nhận được đầu ra:

Updated 0 paths from the index

và tôi vẫn có phiên bản của tập tin. Nếu tôi rm và sau đó kiểm tra, nó sẽ nói 1 thay vào đó, nhưng nó vẫn cung cấp cho tôi phiên bản tệp của tôi.

git mergetool nói

No files need merging

và trạng thái git nói

    All conflicts fixed but you are still merging.
    (use "git commit" to conclude merge)

Một lựa chọn là hoàn tác cam kết ... nhưng tôi đã không may mắn và tôi có nhiều cam kết, và điều tồi tệ này là lần đầu tiên. Tôi không muốn lãng phí thời gian để lặp lại điều đó.

để giải quyết sự điên rồ này:

Tôi vừa mới chạy

git commit

làm mất phiên bản từ xa và có thể lãng phí không gian lưu trữ tệp nhị phân bổ sung ... sau đó

git checkout <commit where the remote version exists> <path>

đưa tôi trở lại phiên bản từ xa

sau đó chỉnh sửa lại tệp ... và sau đó cam kết và đẩy, điều này có thể có nghĩa là lãng phí không gian với một bản sao khác của tệp nhị phân.


Trong trường hợp của tôi, sau khi thử git checkout --ours <path>tôi đã nhận được Updated 0 paths from the index . Tôi đã sửa lỗi đó bằng git add <path>lệnh, thao tác này cũng tương tự.
Andriy
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.