การแก้ไขข้อขัดแย้ง Git ด้วยไฟล์ไบนารี


464

ฉันใช้ Git บน Windows (msysgit) เพื่อติดตามการเปลี่ยนแปลงสำหรับงานออกแบบบางอย่างที่ฉันทำ

วันนี้ฉันได้ทำงานกับพีซีเครื่องอื่น (ด้วย repo ระยะไกลbrian) และตอนนี้ฉันพยายามรวมการแก้ไขที่ทำในวันนี้กลับเป็นเวอร์ชันท้องถิ่นของฉันบนแล็ปท็อปของฉัน

บนแล็ปท็อปของฉันฉันเคยgit pull brian masterดึงการเปลี่ยนแปลงเป็นเวอร์ชันในเครื่องของฉัน ทุกอย่างแตกต่างจากเอกสาร InDesign หลัก - นี่แสดงว่าเป็นข้อขัดแย้ง

เวอร์ชั่นบนพีซี ( brian) เป็นเวอร์ชั่นล่าสุดที่ฉันต้องการเก็บไว้ แต่ฉันไม่รู้ว่าคำสั่งใดบอกให้ repo ใช้อันนี้

ฉันพยายามคัดลอกไฟล์ไปยังแล็ปท็อปของฉันโดยตรง แต่สิ่งนี้ดูเหมือนว่าจะเป็นการขัดจังหวะกระบวนการทั้งหมด

ใครช่วยชี้ฉันในทิศทางที่ถูกต้องได้ไหม

คำตอบ:


854

git checkoutยอมรับ--oursหรือ--theirsตัวเลือกสำหรับกรณีเช่นนี้ ดังนั้นหากคุณมีข้อขัดแย้งในการรวมและคุณรู้ว่าคุณต้องการไฟล์จากสาขาที่คุณกำลังผสานคุณสามารถทำได้:

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

เพื่อใช้ไฟล์เวอร์ชันนั้น ในทำนองเดียวกันหากคุณรู้ว่าคุณต้องการเวอร์ชันของคุณ (ไม่ใช่เวอร์ชันที่รวมอยู่) คุณสามารถใช้

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

47
ฉันต้องเรียกใช้ 'git reset HEAD path / to / ขัดแย้ง-file.txt' ในไฟล์ก่อนที่จะใช้ --ours มิฉะนั้นจะดูเหมือนไม่มีผล
Zitrax

6
@Zitrax คุณแตกไฟล์หลังจากใช้งานgit checkout --oursหรือไม่ หน้าคนแนะนำ (IMHO) ว่าการชำระเงิน - สี่ / - พวกเขาจะลบการเปลี่ยนแปลงจากรายการ "ทั้งแก้ไขต้องรวม" และเพิ่มไปยังดัชนีและฉันคิดว่ามันไม่ถูกต้อง ฉันเชื่อว่าคุณจะต้องทำงานgit addหลังจากเช็คเอาต์
Tim Keating

15
หมายเหตุ: คุณยังต้องการทำ "git add ที่ขัดแย้งกัน-file.txt " และ "git กระทำ" เมื่อฉันลองใช้งานข้อความยืนยันจะถูกเติมไว้ล่วงหน้าพร้อมกับข้อความเกี่ยวกับความขัดแย้ง
Edward Falk

2
การกล่าวคำว่า "สาขาที่คุณรวมอยู่" เป็นอันตรายใกล้กับ "สาขาที่คุณรวมเข้าด้วยกัน" ฉันคิดว่าการทิ้งคำบุพบทจะดีกว่า: "สาขาที่คุณกำลังผสาน" ซึ่งจะสะท้อนถึงคำสั่ง git เช่นกัน (เช่นgit merge branch_name)
andrybak

13
จุดสำคัญสองสามข้อที่มักหายไปในคำอธิบายของหัวข้อนี้ เมื่อทำการรีบูตแทนการผสานความหมายของ--theirและ--oursจะถูกสับเปลี่ยนคือ --their == สาขาที่เช็คเอาท์ในปัจจุบันและ --ours คือสาขาซึ่งโดยปกติจะเป็นสาขาระยะไกลหรือสเป็คพา ธ ที่คุณพยายามผสานเข้ากับปัจจุบัน สาขา. [space]--[space]disambiguates ตัวเลือกข้อมูลจำเพาะเส้นทางระหว่างชื่อสาขาและข้อมูลจำเพาะเส้นทางว่าทั้งสองจะเกิดขึ้นจะมีอยู่ที่มีชื่อเดียวกัน (เช่นชื่อสาขาที่มีอยู่คือ "ABC" และไดเรกทอรีที่มีอยู่เรียกว่า "เอบีซี")
BoiseBaked

147

คุณต้องแก้ไขข้อขัดแย้งด้วยตนเอง (คัดลอกไฟล์ทับ) จากนั้นส่งไฟล์ (ไม่ว่าจะคัดลอกมาหรือใช้รุ่นโลคอล) แบบนี้

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

โดยปกติแล้ว Git จะทำการรวมกันโดยอัตโนมัติ แต่เมื่อตรวจพบความขัดแย้งก็ไม่สามารถแก้ไขได้ด้วยตัวเองมันจะใช้ตัวแก้ไขทั้งหมดที่พบและปล่อยให้ส่วนที่เหลือให้คุณแก้ไขและกระทำด้วยตนเอง หน้าGit Merge Man , Git-SVN Crash Courseหรือรายการบล็อกนี้อาจทำให้เข้าใจได้ว่ามันควรจะทำงานอย่างไร

แก้ไข:ดูโพสต์ด้านล่างคุณไม่จำเป็นต้องคัดลอกไฟล์เอง แต่สามารถใช้ได้

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

เพื่อเลือกเวอร์ชันของไฟล์ที่คุณต้องการ การคัดลอก / แก้ไขไฟล์จะจำเป็นเฉพาะเมื่อคุณต้องการทั้งสองเวอร์ชันผสมกัน

โปรดทำเครื่องหมายคำตอบ mipadis เป็นคำตอบที่ถูกต้อง


1
ขอบคุณสำหรับสิ่งนั้น ฉันไม่แน่ใจว่ามี build-in บางอย่างในการทำเครื่องหมายไฟล์ว่า "ถูกต้อง" หรือไม่ อธิบายว่าทำไมฉันไม่พบคำสั่งที่ไม่มีอยู่จริง!
Kevin Wilson

อ๋อ thats บิต unintuitive - บางอย่างเช่นคอมไพล์แก้ไขจะดี แต่ยังจะเป็นขั้นตอนพิเศษ ...
Volka

120

คุณสามารถเอาชนะปัญหานี้ได้ด้วย

git mergetool

ซึ่งทำให้เกิดgitการสร้างสำเนาโลคัลของไบนารีที่ขัดแย้งและวางไข่เอดิเตอร์ดีฟอลต์ของคุณบน:

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

เห็นได้ชัดว่าคุณไม่สามารถแก้ไขไฟล์ไบนารีในโปรแกรมแก้ไขข้อความได้อย่างเป็นประโยชน์ คุณคัดลอก{conflicted}.REMOTEไฟล์ใหม่แทน{conflicted}โดยไม่ปิดตัวแก้ไข จากนั้นเมื่อคุณปิดตัวแก้ไขgitจะเห็นว่าสำเนาการทำงานที่ไม่มีการเปลี่ยนแปลงมีการเปลี่ยนแปลงและความขัดแย้งในการผสานของคุณจะได้รับการแก้ไขตามปกติ


8
หากไฟล์มีขนาดใหญ่หรือคุณไม่ต้องการเสี่ยงต่อการเปิดไบนารีในตัวแก้ไขข้อความเลยคุณสามารถกด ctrl + c ได้ที่พร้อมต์ mergetool (" Hit return to start merge resolution tool") และ git จะปล่อยไฟล์พิเศษไว้ จากนั้นคุณสามารถปรับเปลี่ยนหรือผสานพวกเขาในเครื่องมือภายนอก (มีประโยชน์สำหรับรูปแบบเอกสารไบนารีเช่น LibreOffice / OpenOffice / MSWord) และบันทึกผลลัพธ์กลับไปที่ชื่อไฟล์เดิม หากต้องการแจ้งให้ git ทราบว่าความขัดแย้งนั้นได้รับการแก้ไขแล้วgit addชื่อไฟล์ดั้งเดิมและคุณสามารถทำการผสานให้เสร็จสิ้นได้
เฟลิกซ์

18

หากต้องการแก้ไขโดยเก็บเวอร์ชันไว้ในสาขาปัจจุบันของคุณ (ไม่ต้องสนใจเวอร์ชันจากสาขาที่คุณกำลังรวมอยู่) เพียงแค่เพิ่มและส่งไฟล์:

git commit -a

หากต้องการแก้ไขโดยการเขียนทับเวอร์ชันในสาขาปัจจุบันของคุณด้วยเวอร์ชันจากสาขาที่คุณกำลังผสานคุณจะต้องดึงเวอร์ชันนั้นไปยังไดเรกทอรีที่ใช้งานของคุณก่อนจากนั้นจึงเพิ่ม / ส่งมัน:

git checkout otherbranch theconflictedfile
git commit -a

อธิบายรายละเอียดเพิ่มเติม


1
ฉันชอบตัวแปรนี้มากกว่าคำตอบที่ยอมรับเพราะมันง่ายกว่าโดยเฉพาะเมื่อพิจารณาว่าความหมายของ "--ours" และ "- theirs" เหล่านั้นถูกสลับในกรณีที่มีการรีบูต
Antony Hatchkins

11

คำตอบของ mipadi ไม่ได้ผลสำหรับฉันฉันต้องทำสิ่งนี้:

ชำระเงิน git - เส้นทางของเรา / to / file.bin

หรือเพื่อให้เวอร์ชันถูกรวมอยู่ใน:

git checkout - พา ธ ของพวกเขา / ไปยัง / file.bin

แล้วก็

git เพิ่ม path / to / file.bin

และจากนั้นฉันก็สามารถทำ "git mergetool" อีกครั้งและดำเนินการต่อไปในความขัดแย้งครั้งต่อไป


6

จากgit checkoutเอกสาร

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

--ours
--theirs
เมื่อตรวจสอบเส้นทางจากดัชนีให้ตรวจสอบขั้นตอน # 2 ( ours) หรือ # 3 ( theirs) สำหรับเส้นทางที่ไม่รวม

ดัชนีอาจมีรายการที่ไม่ถูกรวมเนื่องจากการผสานล้มเหลวก่อนหน้า โดยค่าเริ่มต้นหากคุณพยายามที่จะตรวจสอบรายการดังกล่าวจากดัชนีการดำเนินการเช็คเอาต์จะล้มเหลวและจะไม่มีการชำระเงินใด ๆ การใช้-fจะไม่สนใจรายการที่ไม่ได้รวมเหล่านี้ เนื้อหาจากด้านที่เฉพาะเจาะจงของการผสานสามารถตรวจสอบได้จากดัชนีโดยใช้หรือ--ours --theirsด้วย-mการเปลี่ยนแปลงที่ทำกับไฟล์แผนผังการทำงานสามารถละทิ้งเพื่อสร้างผลลัพธ์การผสานที่ขัดแย้งเดิม


4

ฉันเจอปัญหาที่คล้ายกัน (ต้องการดึงการคอมมิชชันที่มีไฟล์ไบนารี่บางไฟล์ซึ่งก่อให้เกิดข้อขัดแย้งเมื่อรวม) แต่เจอวิธีแก้ไขปัญหาอื่นที่สามารถทำได้ทั้งหมดโดยใช้ git (เช่นไม่ต้องคัดลอกไฟล์ด้วยตนเอง) ฉันคิดว่าฉันจะรวมมันที่นี่ดังนั้นอย่างน้อยที่สุดฉันสามารถจำได้ในครั้งต่อไปที่ฉันต้องการมัน :) ขั้นตอนมีลักษณะดังนี้:

% git fetch

สิ่งนี้จะเรียกการส่งล่าสุดจากที่เก็บข้อมูลระยะไกล (คุณอาจต้องระบุชื่อสาขาระยะไกลขึ้นอยู่กับการตั้งค่าของคุณ) แต่ไม่ได้พยายามรวมเข้าด้วยกัน มันบันทึกการกระทำใน FETCH_HEAD

% git checkout FETCH_HEAD stuff/to/update

นี่เป็นการคัดลอกไฟล์ไบนารีที่ฉันต้องการและเขียนทับสิ่งที่อยู่ในแผนผังการทำงานด้วยเวอร์ชันที่ดึงมาจากสาขาระยะไกล git ไม่พยายามทำการผสานดังนั้นคุณแค่จบลงด้วยการคัดลอกไบนารีไฟล์จากสาขาระยะไกล เมื่อเสร็จแล้วคุณสามารถเพิ่ม / ส่งสำเนาใหม่เหมือนปกติ


4

ขั้นตอนนี้คือการแก้ไขข้อขัดแย้งของไฟล์ไบนารีหลังจากที่คุณส่งคำขอดึงไปยัง Github:

  1. ดังนั้นใน Github คุณพบว่าคำขอการดึงของคุณมีข้อขัดแย้งในไฟล์ไบนารี
  2. ตอนนี้กลับไปที่สาขา git เดียวกันบนคอมพิวเตอร์ของคุณ
  3. คุณ (a) สร้าง / สร้างใหม่อีกครั้งไฟล์ไบนารีนี้อีกครั้งและ (b) ส่งมอบไฟล์ไบนารีที่ได้ไปยังสาขา git เดียวกันนี้
  4. จากนั้นคุณดันสาขา git เดียวกันนี้อีกครั้งเพื่อ Github

บน Github เมื่อมีการร้องขอการดึงความขัดแย้งจะหายไป


ตรงนี้เป็นขั้นตอนที่ฉันต้องการ
Huifang Feng

2

หากไบนารีเป็นสิ่งที่มากกว่า dllหรือสิ่งที่สามารถแก้ไขได้โดยตรงเช่นรูปภาพหรือไฟล์ผสมผสาน (และคุณไม่จำเป็นต้องทิ้ง / เลือกไฟล์หนึ่งไฟล์หรืออื่น ๆ ) การผสานที่แท้จริงจะเป็นดังนี้:

ฉันขอแนะนำให้ค้นหาเครื่องมือ diff ที่มุ่งเน้นไปที่สิ่งที่คุณเป็นไฟล์ไบนารีตัวอย่างเช่นมีบางคนที่ว่างสำหรับไฟล์ภาพเช่น

และเปรียบเทียบพวกเขา

หากไม่มีเครื่องมือ diff ออกเพื่อเปรียบเทียบไฟล์ของคุณหากคุณมีเครื่องกำเนิดไฟล์ต้นฉบับของ bin (นั่นคือมีโปรแกรมแก้ไขอยู่ ... เช่น blender 3d คุณสามารถตรวจสอบไฟล์เหล่านั้นด้วยตนเองได้เช่นกัน ดูบันทึกและถามคนอื่น ๆ ว่าคุณควรรวมอะไร) และทำการส่งออกไฟล์ด้วยhttps://git-scm.com/book/es/v2/Git-Tools-Advanced-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

ฉันเจอสองกลวิธีในการจัดการ diff / merge ของไฟล์ไบนารีด้วย Git บน windows

  1. Tortoise git ให้คุณกำหนดค่าเครื่องมือ diff / merge สำหรับไฟล์ประเภทต่าง ๆ ตามนามสกุลของไฟล์ ดู 2.35.4.3 Diff / ผสานตั้งค่าขั้นสูงhttp://tortoisegit.org/docs/tortoisegit/tgit-dug-settings.html แน่นอนว่ากลยุทธ์นี้ใช้เครื่องมือ diff / merge ที่เหมาะสมที่มีอยู่

  2. การใช้คุณสมบัติ git คุณสามารถระบุเครื่องมือ / คำสั่งเพื่อแปลงไฟล์ไบนารีของคุณเป็นข้อความแล้วปล่อยให้เครื่องมือ diff / merge เริ่มต้นของคุณทำสิ่งนั้น ดูhttp://git-scm.com/book/it/v2/Customizing-Git-Git-Attributes บทความนี้ยังให้ตัวอย่างของการใช้ข้อมูลเมตาเพื่อกระจายภาพ

ฉันได้ทั้งสองกลยุทธ์ในการทำงานกับไฟล์ไบนารีของแบบจำลองซอฟต์แวร์ แต่เราไปกับคอมไพล์เต่าเนื่องจากการกำหนดค่าเป็นเรื่องง่าย


0

ฉันใช้ Git Workflow สำหรับ Excel - https://www.xltrail.com/blog/git-workflow-for-excelแอปพลิเคชันเพื่อแก้ไขปัญหาส่วนใหญ่ของไฟล์ไบนารีที่เกี่ยวข้องกับการผสาน แอพโอเพนซอร์ซนี้ช่วยให้ฉันแก้ไขปัญหาได้อย่างมีประสิทธิภาพโดยไม่ต้องใช้เวลามากเกินไปและให้ฉันเลือกรุ่นที่ถูกต้องของไฟล์โดยไม่สับสน


0

กรณีของฉันดูเหมือนว่าเป็นข้อผิดพลาด .... โดยใช้ git 2.21.0

ฉันดึง ... มันบ่นเกี่ยวกับไฟล์ไบนารี:

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.

และจากนั้นไม่มีคำตอบใด ๆ ที่นี่ส่งผลให้เกิดความรู้สึกใด ๆ

หากฉันดูไฟล์ที่ฉันมีอยู่ตอนนี้ ... เป็นไฟล์ที่ฉันแก้ไข ถ้าฉันทำอย่างใดอย่างหนึ่ง:

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

ฉันได้รับผลลัพธ์:

Updated 0 paths from the index

และฉันยังมีไฟล์เวอร์ชันของฉันอยู่ ถ้าฉันเช็คเอาท์แล้วมันจะบอกว่า 1 แทน แต่มันก็ยังให้ไฟล์เวอร์ชันของฉัน

git mergetool พูดว่า

No files need merging

และสถานะ git พูดว่า

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

ทางเลือกหนึ่งคือการยกเลิกการกระทำ ... แต่ฉันโชคร้ายและฉันมีความมุ่งมั่นมากมายและสิ่งที่ไม่ดีครั้งนี้เป็นครั้งแรก ฉันไม่อยากเสียเวลาพูดซ้ำ

ดังนั้นเพื่อแก้ความบ้าคลั่งนี้:

ฉันเพิ่งวิ่ง

git commit

ซึ่งสูญเสียรุ่นระยะไกลและอาจทำให้เปลืองพื้นที่ในการจัดเก็บไฟล์ไบนารีเพิ่มเติม ... จากนั้น

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

ซึ่งให้ฉันกลับรุ่นระยะไกล

จากนั้นแก้ไขไฟล์อีกครั้ง ... จากนั้นส่งและพุชซึ่งอาจหมายถึงการสิ้นเปลืองพื้นที่ด้วยสำเนาของไฟล์ไบนารีอีกครั้ง


ในกรณีของฉันหลังจากพยายามgit checkout --ours <path>รับมาUpdated 0 paths from the index แล้ว ฉันแก้ไขด้วยgit add <path>คำสั่งซึ่งทำเช่นเดียวกัน
Andriy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.