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


197

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


1
คำตอบด้านล่างนี้ให้ความกระจ่างแก่ฉันมาก มีจุดที่ลึกซึ้งสองสามอย่างที่ทำให้สิ่งต่าง ๆ ชัดเจนสำหรับฉันฉันขอแนะนำผู้ใช้ที่ไม่ใช่ผู้เชี่ยวชาญของ GIT ให้อ่านความคิดเห็นทั้งหมดด้านล่างโพสต์ด้านล่างและขอบคุณ Brian!
Tom DeMille

คำตอบ:


332

git checkoutมี--oursตัวเลือกให้ตรวจสอบเวอร์ชันของไฟล์ที่คุณมีในเครื่อง (ตรงข้ามกับ--theirsซึ่งเป็นเวอร์ชันที่คุณดึงเข้าไป) คุณสามารถส่ง.ต่อgit checkoutเพื่อบอกให้ตรวจสอบทุกอย่างในต้นไม้ จากนั้นคุณต้องทำเครื่องหมายข้อขัดแย้งตามที่ได้รับการแก้ไขซึ่งคุณสามารถทำได้git addและมอบหมายงานของคุณเมื่อเสร็จแล้ว:

git checkout --ours .  # checkout our local version of all files
git add -u             # mark all conflicted files as merged
git commit             # commit the merge

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

นอกจากนี้ยังเป็นนิสัยที่ดีที่จะมีเมื่อผ่านในชื่อไฟล์ที่จะชดเชยด้วยเช่น-- git checkout --ours -- <filename>หากคุณไม่ทำเช่นนี้และชื่อไฟล์นั้นตรงกับชื่อของสาขาหรือแท็ก Git จะคิดว่าคุณต้องการตรวจสอบการแก้ไขนั้นแทนการตรวจสอบชื่อไฟล์นั้นและใช้รูปแบบแรกของcheckoutคำสั่ง .

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

ที่ง่ายที่สุดคือคุณอยู่ในการแก้ไขเดียวกัน ในกรณีนี้คุณเป็น "ทันสมัยอยู่แล้ว" และไม่มีอะไรเกิดขึ้น

ความเป็นไปได้อีกอย่างก็คือการแก้ไขของพวกเขาเป็นเพียงการสืบทอดของคุณซึ่งในกรณีนี้คุณจะมี "การผสานการกรอไปข้างหน้า" ซึ่งเป็นค่าเริ่มต้น HEADเพิ่งได้รับการอัปเดตเป็นคอมมิชชันโดยไม่มีการรวมเกิดขึ้น ต้องการบันทึกการผสานโดยใช้--no-ff)

จากนั้นคุณจะเข้าสู่สถานการณ์ที่คุณจำเป็นต้องรวมการแก้ไขสองครั้ง ในกรณีนี้มีสองผลลัพธ์ที่เป็นไปได้ หนึ่งคือการผสานที่เกิดขึ้นอย่างหมดจด; การเปลี่ยนแปลงทั้งหมดอยู่ในไฟล์ที่แตกต่างกันหรืออยู่ในไฟล์เดียวกัน แต่ไกลพอที่จะใช้การเปลี่ยนแปลงทั้งสองชุดได้โดยไม่มีปัญหา ตามค่าเริ่มต้นเมื่อมีการผสานที่สะอาดแล้วจะมีการกำหนดโดยอัตโนมัติแม้ว่าคุณจะสามารถปิดการใช้งานนี้ได้--no-commitหากคุณต้องการแก้ไขก่อน (เช่นหากคุณเปลี่ยนชื่อฟังก์ชันfooเป็นbarและคนอื่นเพิ่มรหัสใหม่ที่โทรfooก็จะผสานหมดจด แต่สร้างต้นไม้ที่เสียหายดังนั้นคุณอาจต้องการทำความสะอาดส่วนที่เป็นส่วนหนึ่งของการรวมเพื่อหลีกเลี่ยงการกระทำที่หัก)

ความเป็นไปได้สุดท้ายคือมีการผสานที่แท้จริงและมีความขัดแย้ง ในกรณีนี้ Git จะทำเท่าของการผสานเท่าที่จะสามารถและไฟล์ผลิตที่มีเครื่องหมายความขัดแย้ง ( <<<<<<<, =======และ>>>>>>>) ในการคัดลอกการทำงานของคุณ ในดัชนี (หรือที่เรียกว่า "พื้นที่การแสดงละคร" สถานที่ที่จัดเก็บไฟล์git addก่อนที่จะส่งมอบ) คุณจะมี 3 เวอร์ชันของแต่ละไฟล์ที่มีข้อขัดแย้ง มีรุ่นดั้งเดิมของไฟล์จากบรรพบุรุษของทั้งสองสาขาที่คุณกำลังผสานรุ่นจากHEAD(ด้านข้างของคุณผสาน) และรุ่นจากสาขาระยะไกล

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


7
คุณควรทราบว่าgit add --allจะเพิ่มไฟล์ทั้งหมดในที่เก็บดังนั้นอาจเพิ่มไฟล์ได้มากกว่าที่ตั้งใจเว้นแต่.gitignoreรูปแบบของคุณจะอยู่ในสภาพสมบูรณ์ git add -uอาจเหมาะสมกว่าสำหรับสถานการณ์นี้คุณมีโอกาสน้อยที่จะแก้ไขไฟล์ที่ติดตามซึ่งคุณไม่ต้องการเพิ่มในขณะที่แก้ไขการผสาน
CB Bailey

อ๊ะขอโทษ นั่นคือสิ่งที่ฉันหมายถึง. แก้ไขให้ถูกต้องแล้ว
Brian Campbell

1
ขอบคุณสำหรับคำตอบโดยละเอียดของคุณ จริง ๆ แล้วฉันลอง git checkout - สี่และได้รับข้อความแสดงข้อผิดพลาด ไฟล์ที่เป็นปัญหานั้นเป็น dll (เรามีบางอย่างที่เราเก็บซ่อน, อ้างอิงบุคคลที่ 3 เป็นส่วนใหญ่) และฉันต้องการที่จะพูดว่า 'ตกลงสำเนาของฉันเป็นคนที่ฉันต้องการ แต่ข้อผิดพลาดเป็นสิ่งที่ต้องการ ..... ฉันจะเก็บบทความนี้ไว้เป็นข้อมูลอ้างอิงและครั้งต่อไปที่มันเกิดขึ้นลองอีกครั้งและดูว่ามันใช้งานได้หรือไม่หรือฉันสามารถโพสต์ข้อความนั้นได้ ขอขอบคุณอีกครั้ง
Tom DeMille

แต่คำอธิบายของคุณจะล้างข้อมูลให้ฉันมากเกี่ยวกับกระบวนการขอขอบคุณอีกครั้ง ... คำถามติดตาม: มีวิธีใดที่จะทำให้คอมไพล์ลบไฟล์. orig ได้บ้างเมื่อฉันทำการผสานเสร็จแล้ว?
Tom DeMille

2
git checkout --ours .ที่คุณต้องทำ .เป็นสิ่งสำคัญ; ผ่านในชื่อไฟล์ (ในกรณีนี้ทั้งไดเรกทอรี) เลือกระหว่างโหมดการทำงานที่ต่างกันสองโหมดโหมดcheckoutหนึ่งจะสลับสาขาและโหมดที่ย้ายไฟล์จากดัชนีไปยังสำเนาทำงาน ฉันเห็นด้วยมันสับสนมาก คุณยังสามารถทำได้git checkout --ours -- <filename>เพื่อตรวจสอบไฟล์แต่ละไฟล์
Brian Campbell

23

ตรวจสอบให้แน่ใจแหล่งกำเนิดของความขัดแย้ง: ถ้ามันเป็นผลมาจากการที่git mergeดูไบรอันแคมป์เบล 's คำตอบ

แต่ถ้าเป็นผลมาจากการที่git rebaseจะละทิ้งการเปลี่ยนแปลงจากระยะไกลและใช้การเปลี่ยนแปลงในพื้นที่คุณจะต้องทำสิ่งต่อไปนี้

git checkout --theirs -- .

ดู " ทำไมความหมายของ" ours"และ" theirs"ย้อนกลับ" "เพื่อดูว่าoursและtheirsจะสลับระหว่างการ rebase อย่างไร (เนื่องจากมีการเช็คเอาท์ที่สาขาต้นน้ำ )

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.