แก้ไขความขัดแย้งผสาน Git เพื่อสนับสนุนการเปลี่ยนแปลงระหว่างการดึง


1225

ฉันจะแก้ไขข้อขัดแย้งของคอมไพล์ในการสนับสนุนการเปลี่ยนแปลงที่ดึงได้อย่างไร

โดยทั่วไปฉันจำเป็นต้องลบการเปลี่ยนแปลงที่ขัดแย้งกันทั้งหมดออกจากแผนผังการทำงานโดยไม่ต้องผ่านความขัดแย้งทั้งหมดด้วย a git mergetoolในขณะที่ทำให้การเปลี่ยนแปลงทั้งหมดปราศจากความขัดแย้ง ควรทำสิ่งนี้ในขณะที่ดึงไม่ใช่หลังจากนั้น


3
สำเนาซ้ำซ้อนที่เป็นไปได้ของgit merge -s ของเรา, เกี่ยวกับ "ของพวกเขา"


3
@DanDascalescu คำตอบที่ยอมรับแล้วไม่มีคำตอบสำหรับคำถามนี้ดังนั้นจึงเห็นได้ชัดว่าไม่ใช่ซ้ำ นอกจากนี้คำถามอื่นนั้นค่อนข้างคลุมเครือ: มันยากมากที่จะบอกสิ่งที่ถูกถาม ทั้งหมดฉันไม่เห็นด้วยกับคุณ คุณมีจุดประสงค์อะไรในเรื่องนี้?
sanmai

2
@sanmai คุณมีสองคำตอบ - และคุณยอมรับหนึ่งในนั้น คุณช่วยอธิบายสิ่งที่คุณคาดหวังไว้ในคำตอบได้ดีขึ้นและคุณต้องการรายละเอียดมากแค่ไหนที่นี่?
Edward Thomson

2
@EdwardThomson ดีจริงผมคิดที่จะให้ชื่อเสียงนี้เป็นคำตอบแรก แต่ถ้าคุณถามผมอาจจะรอและดูว่าคำตอบที่ดีขึ้นมา
sanmai

คำตอบ:


1218
git pull -s recursive -X theirs <remoterepo or other repo>

หรือเพียงแค่สำหรับพื้นที่เก็บข้อมูลเริ่มต้น:

git pull -X theirs

หากคุณอยู่ในสถานะขัดแย้ง ...

git checkout --theirs path/to/file

40
โปรดทราบว่าที่-s recursiveนี่ซ้ำซ้อนเนื่องจากเป็นกลยุทธ์การผสานเริ่มต้น เพื่อให้คุณสามารถลดความซับซ้อนของมันที่เป็นพื้นเทียบเท่ากับgit pull -X theirs git pull --strategy-option theirs

5
ถ้าฉันทำเช่นนี้ฉันจะกลับมาอยู่ในMERGINGสถานะ ฉันสามารถแล้วgit merge --abortลองอีกครั้ง แต่ทุกครั้งที่ฉันพบว่ามีการรวมเกิดขึ้น …ฉันรู้ว่าการคืนเงินถูกผลักไปที่ต้นน้ำของฉัน แต่บางทีนั่นอาจจะทำให้เกิดสิ่งนี้
Benjohn

22
git checkout --theirs path/to/fileโปรดใช้ความระมัดระวังด้วย ใช้ระหว่างการรีบูทและได้ผลลัพธ์ที่ไม่คาดคิด พบคำอธิบายใน doc: โปรดทราบว่าในระหว่างการรีบูต git และ git pull --rebase, เราและพวกมันอาจถูกสับเปลี่ยน; - เราให้รุ่นจากสาขาการเปลี่ยนแปลงจะถูก rebased ไปในขณะที่ - พวกเขาให้รุ่นจากสาขาที่เก็บงานของคุณที่จะถูก rebased
Vuk Djapic

10
โปรดทราบว่าgit checkout --theirs/--ours pathman page ระบุว่าใช้งานได้กับเส้นทางที่ไม่ถูกรวม ดังนั้นหากไม่มีข้อขัดแย้งในเส้นทางก็จะถูกรวมคำสั่งนี้จะไม่ทำอะไรเลย กรณีนี้อาจมีปัญหาเมื่อคุณต้องการตัวอย่างเช่นโฟลเดอร์ย่อยทั้งหมด ดังนั้นในกรณีดังกล่าวมันจะปลอดภัยกว่าหากจะทำgit checkout MERGE_HEAD pathหรือใช้แฮชการกระทำ
fsw

4
git pull -X theirsสร้างคอมมิชชันคอมมิวนิตี้ถ้ามีข้อขัดแย้ง (เช่นถ้าคอมมิชชันอื่นวิ่งgit push -fไปที่รีโมต) git fetch && git reset --hard origin/masterหากคุณไม่ต้องการกระทำผสานทำงานแทน
Dan Dascalescu

985

คุณสามารถใช้ตัวเลือกกลยุทธ์ "พวกเขา" แบบเรียกซ้ำ:

git merge --strategy-option theirs

จากคน :

ours
    This option forces conflicting hunks to be auto-resolved cleanly by 
    favoring our version. Changes from the other tree that do not 
    conflict with our side are reflected to the merge result.

    This should not be confused with the ours merge strategy, which does 
    not even look at what the other tree contains at all. It discards 
    everything the other tree did, declaring our history contains all that
    happened in it.

theirs
    This is opposite of ours.

หมายเหตุ: ดังที่หน้าคนบอกว่าตัวเลือกกลยุทธ์การผสาน "ของเรา" นั้นแตกต่างจากกลยุทธ์การผสาน "ของเรา" มาก


นี่คือคำอธิบายโดยละเอียดเพิ่มเติม: lostechies.com/joshuaflanagan/2010/01/29/…
mPrinC

227
นอกจากนี้ยังgit checkout --theirsใช้งานกับไฟล์ที่ขัดแย้งเดียว
dvd

48
สิ่งนี้ไม่ทำงานหากคุณอยู่ในสถานะแก้ไขข้อขัดแย้งแล้ว ในกรณีที่ผมเชื่อว่าวิธีที่ดีที่สุดในการแก้ปัญหาคือการgit checkout <ref to theirs> -- the/conflicted.file; แล้วgit addการเปลี่ยนแปลงของพวกเขา
ThorSummoner

54
@ThorSummoner ในกรณีนั้นมี git checkout - theirs path / of / file ด้วยวิธีนี้คุณไม่จำเป็นต้องค้นหาแฮชที่ถูกต้องด้วยตนเอง
Ikke

8
@Ikke นั้นโดยทั่วไปควรเป็นคำตอบของตัวเอง (และคำตอบที่ยอมรับได้) ถ้าคุณถามฉัน
ThorSummoner

473

หากคุณอยู่ในสถานะที่ขัดแย้งกันแล้วและคุณต้องการยอมรับสิ่งเหล่านี้ทั้งหมด :

git checkout --theirs .
git add .

หากคุณต้องการทำสิ่งที่ตรงกันข้าม:

git checkout --ours .
git add .

มันค่อนข้างรุนแรงดังนั้นโปรดแน่ใจว่าคุณต้องการล้างทุกอย่างออกไปก่อนที่จะทำเช่นนี้


47
หรือไม่ใช้.และระบุไฟล์แทนจุดที่คุณต้องการชำระเงิน น้อยกว่า "รุนแรง" และสิ่งที่คุณต้องการทำอย่างแน่นอน
manroe

10
สิ่งนี้จะไม่ทำงานหากไฟล์ถูกลบออกจากสาขาอื่น: '<file>' ไม่มีเวอร์ชัน
Japster24

3
จะโหวตมากขึ้นถ้าฉันทำได้กลับมาที่คำตอบนี้ทุกครั้งแล้ว
tarikki

6
ใช้git add -uแทนเพื่อข้ามไฟล์ที่ไม่อยู่ในการควบคุมเวอร์ชัน
Sudipta Basak

3
กรณีตามสมมุติฐาน, การเปลี่ยนแปลงสามไฟล์, หนึ่งที่ขัดแย้งกัน, สองอันที่ไม่มีความขัดแย้ง, วิธีนี้จะใช้การเปลี่ยนแปลงที่ไม่ขัดแย้งกันและแก้ไขการเปลี่ยนแปลงที่ขัดแย้งกับเราหรือไม่? หรือมันจะใช้เวลาเพียงรุ่นของเราไม่สนใจการเปลี่ยนแปลงที่ไม่ขัดแย้งจากพวกเขา?
pedromarce

222

ตกลงดังนั้นลองนึกภาพสถานการณ์ที่ฉันเพิ่งเข้ามา:

คุณลองmergeหรืออาจcherry-pickและคุณหยุด

$ git cherry-pick 1023e24
error: could not apply 1023e24... [Commit Message]
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'

ตอนนี้คุณดูไฟล์ที่ขัดแย้งกันและคุณไม่ต้องการเปลี่ยนแปลง ในกรณีของฉันด้านบนไฟล์มีความขัดแย้งกับ newline ที่ IDE ของฉันเพิ่มโดยอัตโนมัติ หากต้องการยกเลิกการเปลี่ยนแปลงและยอมรับสิ่งที่ต้องการวิธีที่ง่ายที่สุดคือ:

git checkout --theirs path/to/the/conflicted_file.php
git add path/to/the/conflicted_file.php

การสนทนานี้ (เพื่อเขียนทับเวอร์ชันที่เข้ามากับเวอร์ชันของคุณ) คือ

git checkout --ours path/to/the/conflicted_file.php
git add path/to/the/conflicted_file.php

น่าแปลกที่ฉันไม่สามารถหาคำตอบนี้ได้อย่างง่ายดายบนอินเทอร์เน็ต


15
โปรดทราบว่าหากมีการดำเนินการgit statusระหว่างcheckoutและaddไฟล์ยังคงแสดงเป็น "ทั้งแก้ไข"
อธิการ

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

2
ฉันทำสิ่งนี้ git reset --hard แล้ว git pull [remote server name] [branch name] -Xtheirs(ยกเลิกการรวมแล้วดึงสิ่งใหม่ที่ด้านบนของสิ่งที่ฉัน) - ไม่แน่ใจว่าสิ่งที่คุณต้องการ
ssaltman

38

git pull -X theirsคำตอบอาจสร้างผสานน่าเกลียดกระทำหรือออก

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

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

git fetch && git reset --hard origin/master

มันทำงานยังไง? git fetchไม่git pullแต่ไม่มีการผสาน จากนั้นgit reset --hardทำให้แผนภูมิการทำงานของคุณตรงกับคำสั่งสุดท้าย การเปลี่ยนแปลงในระบบของคุณกับไฟล์ใน repo ทั้งหมดจะถูกยกเลิกแต่ไฟล์ในเครื่องใหม่จะถูกทิ้งไว้ตามลำพัง


1
+1 - git fetch && git reset --hard {remote}/{branch}เป็นสิ่งที่แก้ไขปัญหาของฉัน ฉันต้องทิ้งการเปลี่ยนแปลงของตัวเองอย่างสมบูรณ์ในความโปรดปรานของ "พวกเขา" สถานะของสาขา แต่git pull -X theirsสำลักในบางไฟล์ที่ย้าย / เปลี่ยนชื่อ ขอบคุณ!
Ivaylo Slavov

23

หลังจากคอมไพล์ผสานหากคุณได้รับความขัดแย้งและคุณต้องการอย่างใดอย่างหนึ่งหรือของพวกเขา

git checkout --theirs .
git checkout --ours .

ฉันจะทำสิ่งนี้บนฐานข้อมูลที่ขัดแย้งกันได้อย่างไร ด้านบนใช้งานได้ในระดับไฟล์โดยไม่ต้องมีไฟล์ที่ขัดแย้งกันซึ่งอาจมีไฟล์ที่ขัดแย้งกัน
Jani

21

หากต้องการแก้ไขข้อขัดแย้งทั้งหมดกับเวอร์ชันในสาขาเฉพาะ:

git diff --name-only --diff-filter=U | xargs git checkout ${branchName}

ดังนั้นหากคุณอยู่ในสถานะผสานแล้วและคุณต้องการเก็บเวอร์ชันหลักของไฟล์ที่ขัดแย้งกัน:

git diff --name-only --diff-filter=U | xargs git checkout master

และสำหรับคนที่ใช้ windows ที่ไม่สามารถใช้ pipe xargs แปลได้อย่างไร
tsemer

มันจะไม่ข้ามการเปลี่ยนแปลงของคุณอย่างสมบูรณ์? แม้แต่คนที่ไม่ได้อยู่ในความขัดแย้ง?
Valentin Heinitz

นี่คือสิ่งที่ฉันทำ น่าเสียดายที่ในภายหลังนั้นต้องการคำสั่งa git cherry-pick --continue หรือgit commit --allow-emptyคำสั่งเพื่อยอมรับการเปลี่ยนแปลงเหล่านี้และดูเหมือนว่าจะไม่มีระบบใด ๆ ที่ต้องใช้คำสั่งซึ่งจะทำให้เกิดความเจ็บปวดโดยอัตโนมัติ ขณะนี้ฉันกำลังแก้ปัญหานี้โดยการทดสอบการมีอยู่ของ.git/COMMIT_EDITMSGไฟล์ แต่ดูเหมือนว่าแฮ็คและเปราะและฉันยังไม่มั่นใจว่ามันใช้งานได้
Konrad Rudolph

สิ่งนี้ดีหมายความว่าถ้าคุณแก้ไขบางส่วน (และทำgit add) ด้วยตนเองคุณสามารถแก้ไขส่วนที่เหลือด้วยวิธีนี้ได้ git checkout --ours/ git checkout --theirsมีประโยชน์เช่นกัน
rcoup

18

โปรดอย่าว่าบางครั้งสิ่งนี้จะไม่ทำงาน :

git checkout - พา ธ / ไปยัง / ไฟล์

หรือ

git checkout - พา ธ / ไปยัง / ไฟล์ของพวกเขา

ฉันทำสิ่งนี้แทนโดยสมมติว่าHEAD เป็นของเราและMERGE_HEAD เป็นของพวกเขา

git checkout HEAD -- path/to/file

หรือ:

git checkout MERGE_HEAD -- path/to/file

หลังจากที่เราทำเช่นนี้และเราดี:

git add .

ถ้าคุณต้องการที่จะเข้าใจมากขึ้นดูโพสต์ที่ยอดเยี่ยมของการเจาะที่นี่: git checkout - เราไม่ได้ลบไฟล์ออกจากรายการไฟล์ที่ไม่ได้ถูกแยกทิ้ง


12

ผู้ใช้ IDE รหัส VS (รวม Git):

หากคุณต้องการยอมรับการเปลี่ยนแปลงขาเข้าทั้งหมดในไฟล์ข้อขัดแย้งให้ทำตามขั้นตอนต่อไปนี้

1. Go to command palette - Ctrl + Shift + P
2. Select the option - Merge Conflict: Accept All Incoming

ในทำนองเดียวกันคุณสามารถทำได้สำหรับตัวเลือกอื่น ๆ เช่นยอมรับทั้งหมดทั้งสองยอมรับทั้งหมดปัจจุบัน ฯลฯ


2
ดูเหมือนว่าจะใช้งานได้กับไฟล์เดียวไม่ใช่ไฟล์ทั้งหมดที่มีข้อขัดแย้ง
Yoryo

1

ฉันมีnext-versionสาขายาวที่เต็มไปด้วยการลบไฟล์ที่มีการเปลี่ยนแปลงจำนวนdevelopมากไฟล์ที่เพิ่มในที่ต่าง ๆ ทั้งสองสาขา ฯลฯ

ฉันต้องการที่จะนำเนื้อหาทั้งหมดของnext-versionสาขามาdevelopรวมไว้ในที่เดียวที่รวมเข้าด้วยกัน

การรวมกันของคำสั่งข้างต้นที่ทำงานสำหรับฉันคือ:

git merge -X theirs next-version
# lots of files left that were modified on develop but deleted on next-version
git checkout next-version .
# files removed, now add the deletions to the commit
git add .
# still have files that were added on develop; in my case they are all in web/
git rm -r web

ไม่ใช่คำตอบใหม่เพียงการรวมบิตจากคำตอบมากมายเพื่อให้มั่นใจว่าคุณอาจต้องการคำตอบทั้งหมดเหล่านี้


1

หากคุณอยู่ในสถานะขัดแย้งกันแล้วและไม่ต้องการที่จะเช็คเอาต์เส้นทางทีละคน คุณอาจลอง

git merge --abort
git pull -X theirs

-1

จากhttps://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging

โดยทั่วไปจะทำการผสานปลอม มันจะบันทึกการผสานใหม่ที่กระทำกับทั้งสองสาขาในฐานะผู้ปกครอง แต่จะไม่ได้ดูที่สาขาที่คุณกำลังรวมเข้าด้วยกันมันจะบันทึกเป็นผลจากการผสานรหัสที่แน่นอนในสาขาปัจจุบันของคุณ

$ git merge -s ours mundo

ผสานโดยกลยุทธ์ 'ของเรา'

$ git diff HEAD HEAD~

คุณสามารถเห็นได้ว่าไม่มีความแตกต่างระหว่างสาขาที่เราเปิดและผลลัพธ์ของการรวม

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

สถานการณ์ที่ฉันพบว่ามีประโยชน์ถ้าฉันต้องการให้เจ้านายสะท้อนการเปลี่ยนแปลงของหัวข้อหัวข้อใหม่ ฉันสังเกตเห็นว่า -Xtheirs ไม่รวมกันโดยไม่มีข้อขัดแย้งในบางสถานการณ์ ... เช่น

$ git merge -Xtheirs topicFoo 

CONFLICT (modify/delete): js/search.js deleted in HEAD and modified in topicFoo. Version topicFoo of js/search.js left in tree.

ในกรณีนี้วิธีแก้ปัญหาที่ฉันพบคือ

$ git checkout topicFoo

จาก topicFoo แรกผสานในต้นแบบโดยใช้กลยุทธ์ -s ของเรานี้จะสร้างการกระทำปลอมที่เป็นเพียงสถานะของ topicFoo $ git ผสาน - อาจารย์ของเรา

ตรวจสอบการรวมที่สร้างไว้

$ git log

ตอนนี้เช็คเอาท์สาขาหลัก

$ git checkout master

ผสานสาขาหัวข้อกลับ แต่คราวนี้ใช้กลยุทธ์แบบเรียกซ้ำ -Xtheirs ตอนนี้จะนำเสนอคุณด้วยสาขาหลักที่มีสถานะของ topicFoo

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