วิธีแก้ไขข้อขัดแย้งใน Git


4765

ฉันจะแก้ไขข้อขัดแย้งใน Git ได้อย่างไร


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

4
คุณสามารถกำหนดค่าเครื่องมือผสาน (kdiff3 jebaird.com/2013/07/08/… ) แล้วใช้ git mergetool เมื่อคุณทำงานในทีมนักพัฒนาซอฟต์แวร์ขนาดใหญ่คุณจะพบกับความขัดแย้งในการผสาน
เกรดี้ G คูเปอร์

อย่าลืมว่าคุณสามารถลดความขัดแย้งส่วนใหญ่ได้ด้วยการรวมการดาวน์สตรีมอย่างสม่ำเสมอ!
Ant P


8
คำถามที่น่าสนใจ: ถามในปี 2008 เปิด 100% จบลงโดยไม่มีคำใบ้เกี่ยวกับสิ่งที่มันเป็นเรื่องจริง (มันเป็นเรื่องเกี่ยวกับ GUI หรือไม่เกี่ยวกับคำสั่ง git หรือไม่เกี่ยวกับความหมาย? เกี่ยวกับการผลัก / ดึงหรือ 30 คำตอบทั้งหมดของพวกเขา (เท่าที่แสดงภาพรวมอย่างรวดเร็ว) มากขึ้นหรือน้อยลงที่เกิดขึ้นเกี่ยวกับ diff3 และเครื่องมือผสานที่แตกต่างกันไม่มีใครยอมรับ คำตอบที่ได้รับคะแนนสูงสุดกล่าวถึงคำสั่งที่ไม่สามารถใช้งานได้กับการgitติดตั้งเริ่มต้น ได้รับการจัดการเพื่อเข้าสู่หน้าเริ่มต้นของ SE สำหรับฉันในวันนี้ปี 2017 ด้วยจำนวนการดู 1.3 ล้านครั้งและมีการโหวตหลายพันครั้ง มโนหร
AnoE

คำตอบ:


2911

ลอง: git mergetool

มันเปิด GUI ที่ทำขั้นตอนให้คุณผ่านความขัดแย้งแต่ละครั้งและคุณจะต้องเลือกวิธีการรวม บางครั้งต้องมีการแก้ไขด้วยมือเล็กน้อยหลังจากนั้น แต่โดยปกติจะเพียงพอด้วยตัวเอง มันดีกว่าทำทุกอย่างด้วยมืออย่างแน่นอน

ตามความคิดเห็น @JoshGlover:

คำสั่ง

ไม่จำเป็นต้องเปิด GUI เว้นแต่คุณจะติดตั้ง วิ่งgit mergetoolให้ฉันส่งผลให้มีvimdiffการใช้ คุณสามารถติดตั้งเครื่องมือดังต่อไปนี้จะใช้มันแทน: meld, opendiff, kdiff3, tkdiff, xxdiff, tortoisemerge, gvimdiff, diffuse, ecmerge, p4merge, araxis, ,vimdiffemerge

ด้านล่างเป็นขั้นตอนตัวอย่างที่ใช้vimdiffสำหรับแก้ไขข้อขัดแย้งในการผสาน ตามลิงค์นี้

ขั้นตอนที่ 1 : เรียกใช้คำสั่งต่อไปนี้ในเทอร์มินัลของคุณ

git config merge.tool vimdiff
git config merge.conflictstyle diff3
git config mergetool.prompt false

สิ่งนี้จะตั้ง vimdiff เป็นเครื่องมือผสานเริ่มต้น

ขั้นตอนที่ 2 : เรียกใช้คำสั่งต่อไปนี้ในเทอร์มินัล

git mergetool

ขั้นตอนที่ 3 : คุณจะเห็นการแสดง vimdiff ในรูปแบบดังต่อไปนี้

  ╔═══════╦══════╦════════╗
  ║       ║      ║        ║
  ║ LOCAL ║ BASE ║ REMOTE ║
  ║       ║      ║        ║
  ╠═══════╩══════╩════════╣
  ║                       ║
  ║        MERGED         ║
  ║                       ║
  ╚═══════════════════════╝

4 มุมมองเหล่านี้คือ

LOCAL - นี่คือไฟล์จากสาขาปัจจุบัน

BASE - บรรพบุรุษร่วมกันไฟล์ที่ตรวจสอบก่อนการเปลี่ยนแปลงทั้งสอง

REMOTE - ไฟล์ที่คุณรวมเข้ากับสาขาของคุณ

รวมแล้ว - ผสานผลลัพธ์นี่คือสิ่งที่ได้รับการบันทึกใน repo

คุณสามารถนำทางระหว่างมุมมองเหล่านี้โดยใช้+ctrl wคุณโดยตรงสามารถเข้าถึงมุมมองที่ผสานการใช้ctrl+ ตามด้วยwj

ข้อมูลเพิ่มเติมเกี่ยวกับระบบนำทาง vimdiff ที่นี่และที่นี่

ขั้นตอนที่ 4 คุณสามารถแก้ไขมุมมอง MERGED ได้ด้วยวิธีต่อไปนี้

หากคุณต้องการรับการเปลี่ยนแปลงจาก REMOTE

:diffg RE  

หากคุณต้องการรับการเปลี่ยนแปลงจาก BASE

:diffg BA  

หากคุณต้องการรับการเปลี่ยนแปลงจาก LOCAL

:diffg LO 

ขั้นตอนที่ 5 บันทึกออกกระทำและทำความสะอาด

:wqa บันทึกและออกจาก vi

git commit -m "message"

git clean ลบไฟล์พิเศษ (เช่น * .orig) ที่สร้างโดยเครื่องมือ diff


54
FYI คุณสามารถใช้git mergetool -yเพื่อบันทึกการกดแป้นบางครั้งหากคุณรวมไฟล์จำนวนมากในคราวเดียว
davr

373
ก็ไม่จำเป็นต้องเปิด GUI จนกว่าคุณจะติดตั้ง วิ่งgit mergetoolให้ฉันส่งผลให้มีvimdiffการใช้ คุณสามารถติดตั้งหนึ่งในเครื่องมือต่อไปนี้เพื่อใช้แทน: meld opendiff kdiff3 tkdiff xxdiff tortoisemerge gvimdiff diffuse ecmerge p4merge araxis vimdiff emerge.
Josh Glover

31
จุดดีจอช ในอูบุนตูฉันได้รับโชคที่ดีที่สุดจากการผสมผสานการแสดงผลสามทางที่ผสานกันนั้นไม่เลว บน OSX คอมไพล์เลือกค่าเริ่มต้นที่ดี
Peter Burns

18
สิ่งนี้เปิด KDiff3 ซึ่งฉันไม่รู้วิธีใช้อย่างแน่นอน
David Murdoch

7
คุณยังสามารถใช้ Beyond Compare 3 ได้ทันที ( git mergetool -t bc3)
AzP

1703

นี่เป็นกรณีการใช้งานที่น่าจะเป็นจากด้านบน:

คุณจะดึงการเปลี่ยนแปลงบางอย่าง แต่อ๊ะคุณยังไม่ทันสมัย:

git fetch origin
git pull origin master

From ssh://gitosis@example.com:22/projectname
 * branch            master     -> FETCH_HEAD
Updating a030c3a..ee25213
error: Entry 'filename.c' not uptodate. Cannot merge.

ดังนั้นคุณจะได้รับข้อมูลที่เป็นปัจจุบันและลองอีกครั้ง แต่มีข้อขัดแย้ง:

git add filename.c
git commit -m "made some wild and crazy changes"
git pull origin master

From ssh://gitosis@example.com:22/projectname
 * branch            master     -> FETCH_HEAD
Auto-merging filename.c
CONFLICT (content): Merge conflict in filename.c
Automatic merge failed; fix conflicts and then commit the result.

ดังนั้นคุณตัดสินใจที่จะดูการเปลี่ยนแปลง:

git mergetool

โอ้ฉันต้นน้ำเปลี่ยนแปลงบางสิ่ง แต่เพื่อใช้การเปลี่ยนแปลงของฉัน ... ไม่ ... การเปลี่ยนแปลงของพวกเขา ...

git checkout --ours filename.c
git checkout --theirs filename.c
git add filename.c
git commit -m "using theirs"

จากนั้นเราลองเป็นครั้งสุดท้าย

git pull origin master

From ssh://gitosis@example.com:22/projectname
 * branch            master     -> FETCH_HEAD
Already up-to-date.

Ta-da!


19
สิ่งนี้มีประโยชน์มากเพราะฉันมีข้อผิดพลาดในการรวมไฟล์ไบนารี (สินทรัพย์ศิลปะ) และการรวมไฟล์เหล่านั้นดูเหมือนจะล้มเหลวเสมอดังนั้นฉันต้องเขียนทับไฟล์ใหม่เสมอและไม่ใช่ "ผสาน"
petrocket

188
ระวัง! ความหมายของ - เราและ - พวกเขากลับกัน --ours == ระยะไกล - theirs == local ดูgit merge --help
mmell

57
ในกรณีของฉันฉันยืนยันว่า --theirs = repository ระยะไกล --ours = ที่เก็บในเครื่องของฉันเอง มันตรงกันข้ามกับความคิดเห็นของ @mmell
Aryo

24
@mmell เฉพาะเมื่อมีการรีบูต ดูthis question
Navin

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

736

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

นี่คือเคล็ดลับ:

เคล็ดลับหนึ่ง

สิ่งที่ดีที่สุดที่ฉันพบคือใช้สไตล์การผสานการผสาน "diff3":

git config merge.conflictstyle diff3

สิ่งนี้จะสร้างเครื่องหมายความขัดแย้งเช่นนี้:

<<<<<<<
Changes made on the branch that is being merged into. In most cases,
this is the branch that I have currently checked out (i.e. HEAD).
|||||||
The common ancestor version.
=======
Changes made on the branch that is being merged in. This is often a 
feature/topic branch.
>>>>>>>

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

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

หากความขัดแย้งนั้นยาวกว่านี้ฉันจะตัดและวางแต่ละส่วนในสามส่วนออกเป็นสามไฟล์แยกกันเช่น "ของฉัน", "ทั่วไป" และ "ของพวกเขา"

จากนั้นฉันสามารถเรียกใช้คำสั่งต่อไปนี้เพื่อดู hunks ต่างสองที่ทำให้เกิดความขัดแย้ง:

diff common mine
diff common theirs

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

เคล็ดลับที่สอง

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

git log --merge -p <name of file>

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

เคล็ดลับสาม

ตรวจสอบการเปลี่ยนแปลงของคุณด้วยเครื่องมืออัตโนมัติ

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

เคล็ดลับสี่

วางแผนล่วงหน้า; สื่อสารกับเพื่อนร่วมงาน

การวางแผนล่วงหน้าและตระหนักถึงสิ่งที่คนอื่นกำลังทำอยู่สามารถช่วยป้องกันไม่ให้เกิดข้อขัดแย้งในการรวมและ / หรือช่วยแก้ไขปัญหาก่อนหน้า - ในขณะที่รายละเอียดยังคงสดใหม่อยู่ในใจ

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

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

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

เคล็ดลับห้า

หากคุณไม่แน่ใจในการรวมอย่าบังคับมัน

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

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


6
ตัวเลือก diff3 เป็นคุณสมบัติที่ยอดเยี่ยมสำหรับการรวมเข้าด้วยกัน GUI เดียวที่ฉันเจอที่แสดงว่าเป็นของ Perforce p4mergeซึ่งสามารถติดตั้งและใช้แยกต่างหากจากเครื่องมืออื่น ๆ ของ Perforce (ซึ่งฉันไม่ได้ใช้ แต่ได้ยินเรื่องร้องเรียน)
alxndr

3
หลังจากพยายามรีบูตซึ่งส่งผลให้เกิดข้อขัดแย้งในการผสาน: บันทึก $ git --merge -p build.xml ผลลัพธ์: ถึงแก่ความตาย: - ผสานโดยไม่มี MERGE_HEAD
Ed Randall

จะเกิดอะไรขึ้นถ้าฉันมีการเปลี่ยนแปลงหนึ่งไฟล์จาก branch1 และการลบไฟล์นั้นใน branch2 ฉันจะแก้ไขข้อขัดแย้งที่ผสานได้อย่างไร มีวิธีใช้ git ที่ฉันสามารถรวมพวกเขาโดยการเปลี่ยนแปลงสาขาหนึ่งหรือไม่
ฮั

git config merge.conflictstyle diff3- ขอบคุณครับ นี่เป็นสิ่งที่น่าอัศจรรย์และทำให้ฉันเป็นอิสระจากการพยายามหา (และจ่ายเงินดอลลาร์) สำหรับ GUI ที่ผสานกันทั้ง 3 วิธี IMO นี้จะดีกว่าเพราะมันแสดงบรรพบุรุษร่วมกันเช่นเดียวกับท้องถิ่น / ระยะไกลและแสดงสายบันทึกการกระทำล่าสุดซึ่ง (AFAIK) ไม่มี GUI ทำ คอมมิทจะช่วยให้คุณระบุรหัสที่เป็นสาขาได้อย่างแน่นอน
ffxsam

ฉันได้พบว่าบางครั้งความขัดแย้งของ diff3 นั้นส่งผลให้นักล่าที่แตกต่างกันมากซึ่งส่วนใหญ่เหมือนกัน น่าเสียดายที่ฉันไม่มี reproducer ที่ฉันสามารถใช้สำหรับรายงานข้อผิดพลาด แต่ถ้าคุณประสบปัญหานี้คุณอาจลองปิดตัวเลือกนี้ชั่วคราว
Dave Abrahams

348
  1. ระบุว่าไฟล์ใดมีข้อขัดแย้ง (Git ควรบอกคุณนี้)

  2. เปิดแต่ละไฟล์และตรวจสอบความแตกต่าง Git แบ่งเขตพวกมันออก หวังว่ามันจะเห็นได้ชัดว่าแต่ละรุ่นของบล็อกที่จะเก็บ คุณอาจต้องพูดคุยกับผู้พัฒนาเพื่อนที่มุ่งมั่นที่จะรหัส

  3. เมื่อคุณแก้ไขข้อขัดแย้งในไฟล์git add the_fileแล้ว

  4. เมื่อคุณแก้ไขข้อขัดแย้งทั้งหมดแล้วให้ทำgit rebase --continueหรืออะไรก็ตามที่ Git สั่งให้ทำเมื่อคุณทำเสร็จ


38
@Justin คิดว่า Git เป็นเนื้อหาการติดตามมากกว่าการติดตามไฟล์ จากนั้นจึงง่ายที่จะเห็นว่าเนื้อหาที่คุณอัปเดตไม่ได้อยู่ในที่เก็บและจำเป็นต้องเพิ่ม วิธีคิดนี้ยังอธิบายว่าทำไม Git ถึงไม่ติดตามโฟลเดอร์ว่าง: แม้ว่ามันจะเป็นไฟล์เทคนิค แต่ก็ไม่มีเนื้อหาที่จะติดตาม
Gareth

7
มีเนื้อหาเกิดขึ้นมีความขัดแย้งเกิดขึ้นเนื่องจากมีเนื้อหาในเวอร์ชัน 2 ดังนั้น "git add" จึงไม่ถูกต้อง และจะไม่ทำงาน (เพิ่มคอมไพล์คอมไพล์คอมมิชชัน) ถ้าคุณต้องการคอมมิทเพียงไฟล์เดียวหลังจากความขัดแย้งได้รับการแก้ไข ("ร้ายแรง: ไม่สามารถคอมมิทบางส่วนระหว่างการผสาน")
Dainius

1
ใช่เทคนิคนี้ตอบคำถามที่ถาม แต่ไม่ใช่คำตอบที่ใช้งานได้ในความคิดของฉันขอโทษ อะไรคือจุดของการทำสาขาหนึ่งเดียวกับอื่นได้หรือไม่ แน่นอนการรวมจะมีความขัดแย้ง ..
พฤหัสบดีที่

5
Thulfir: ใครพูดอะไรเกี่ยวกับการทำให้สาขาหนึ่งเหมือนกัน? มีสถานการณ์ต่าง ๆ ที่คุณต้องการผสานโดยไม่ต้อง "ทำให้สาขาหนึ่งเหมือนกัน" หนึ่งคือเมื่อคุณทำกับสาขาการพัฒนาและต้องการรวมการเปลี่ยนแปลงในสาขาหลัก; หลังจากนี้สาขาการพัฒนาสามารถลบได้ อีกหนึ่งคือเมื่อคุณต้องการที่จะลดสาขาการพัฒนาของคุณเพื่อความสะดวกในที่สุดผสานสุดท้ายในต้นแบบ
Teemu Leisti

4
@JustinGrant git addไฟล์ลำดับขั้นในดัชนี; มันไม่ได้เพิ่มอะไรในที่เก็บ git commitเพิ่มสิ่งต่าง ๆ ไปยังที่เก็บ การใช้งานนี้เหมาะสมสำหรับการผสาน - การผสานจะทำการเปลี่ยนแปลงทั้งหมดที่สามารถผสานได้โดยอัตโนมัติ เป็นความรับผิดชอบของคุณในการรวมส่วนที่เหลือของการเปลี่ยนแปลงและเพิ่มสิ่งเหล่านั้นในดัชนีเมื่อคุณทำเสร็จแล้ว
Mark E. Haase

105

ตรวจสอบคำตอบในคำถาม Stack Overflow ยกเลิกการรวมใน Gitโดยเฉพาะคำตอบของ Charles Baileyซึ่งแสดงวิธีดูไฟล์เวอร์ชันต่างๆที่มีปัญหาตัวอย่างเช่น

# Common base version of the file.
git show :1:some_file.cpp

# 'Ours' version of the file.
git show :2:some_file.cpp

# 'Theirs' version of the file.
git show :3:some_file.cpp

ตรวจสอบตัวเลือก "-m" เพื่อ "git checkout -m" - ช่วยให้คุณสามารถแยกแมลงวันที่แตกต่างออกไปในพื้นที่ทำงานของคุณได้
qneill

สิ่งนี้ช่วยฉัน การดูแต่ละไฟล์แยกกันทำให้ฉันจำสิ่งที่ฉันกำลังจะทำในแต่ละสาขา จากนั้นฉันสามารถตัดสินใจเลือก
Rohmer

99

การรวมความขัดแย้งเกิดขึ้นเมื่อทำการเปลี่ยนแปลงไฟล์ในเวลาเดียวกัน นี่คือวิธีแก้ปัญหา

git CLI

ต่อไปนี้เป็นขั้นตอนง่าย ๆ ที่ควรทำเมื่อคุณเข้าสู่สถานะขัดแย้ง:

  1. บันทึกรายการไฟล์ที่ขัดแย้งด้วย: git status(ใต้Unmerged pathsหัวข้อ)
  2. แก้ไขข้อขัดแย้งแยกกันสำหรับแต่ละไฟล์โดยใช้วิธีใดวิธีหนึ่งต่อไปนี้:

    • ใช้ GUI เพื่อแก้ไขข้อขัดแย้ง: git mergetool(วิธีที่ง่ายที่สุด)

    • หากต้องการยอมรับรีโมต / เวอร์ชันอื่นให้ใช้: git checkout --theirs path/file. การดำเนินการนี้จะปฏิเสธการเปลี่ยนแปลงในท้องถิ่นที่คุณทำกับไฟล์นั้น

    • หากต้องการยอมรับรุ่นท้องถิ่น / ของเราให้ใช้: git checkout --ours path/file

      อย่างไรก็ตามคุณต้องระวังเนื่องจากการเปลี่ยนแปลงระยะไกลที่เกิดจากความขัดแย้งด้วยเหตุผลบางประการ

      ที่เกี่ยวข้อง: ความหมายที่แม่นยำของ "ของเรา" และ "ของพวกเขา" ในคอมไพล์คืออะไร?

    • แก้ไขไฟล์ขัดแย้งด้วยตนเองและมองหาการป้องกันรหัสระหว่าง<<<<</ แล้วเลือกรุ่นทั้งจากด้านบนหรือด้านล่าง>>>>> =====ดู: การนำเสนอความขัดแย้งกันอย่างไร

    • เส้นทางและชื่อแฟ้มความขัดแย้งสามารถแก้ไขได้โดย/git addgit rm

  3. git statusสุดท้ายตรวจสอบไฟล์ที่พร้อมสำหรับการกระทำโดยใช้:

    หากคุณยังมีไฟล์ใด ๆ ภายใต้Unmerged paths, และคุณไม่แก้ปัญหาความขัดแย้งด้วยตนเองแล้วให้ Git git add path/fileรู้ว่าคุณแก้ไขได้โดย:

  4. หากความขัดแย้งทั้งหมดได้รับการแก้ไขเรียบร้อยแล้วให้ยอมรับการเปลี่ยนแปลงโดย: git commit -aและผลักดันไปยังระยะไกลตามปกติ

ดูเพิ่มเติม: การแก้ไขข้อขัดแย้งการผสานจากบรรทัดคำสั่งที่ GitHub

สำหรับการกวดวิชาปฏิบัติตรวจสอบ: สถานการณ์ 5 - แก้ไขความขัดแย้งโดยการผสาน Katacoda

DiffMerge

ฉันใช้DiffMergeสำเร็จซึ่งสามารถเปรียบเทียบและผสานไฟล์บน Windows, macOS และ Linux / Unix ได้

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

DiffMerge

แหล่งรูปภาพ: DiffMerge (ภาพหน้าจอ Linux)

เพียงดาวน์โหลดและเรียกใช้ใน repo เป็น:

git mergetool -t diffmerge .

MacOS

ใน macOS คุณสามารถติดตั้งผ่าน:

brew install caskroom/cask/brew-cask
brew cask install diffmerge

และอาจ (ถ้าไม่ได้ระบุไว้) คุณต้องใช้ wrapper แบบพิเศษต่อไปนี้วางไว้ใน PATH ของคุณ (เช่น/usr/bin):

#!/bin/sh
DIFFMERGE_PATH=/Applications/DiffMerge.app
DIFFMERGE_EXE=${DIFFMERGE_PATH}/Contents/MacOS/DiffMerge
exec ${DIFFMERGE_EXE} --nosplash "$@"

จากนั้นคุณสามารถใช้แป้นพิมพ์ลัดต่อไปนี้:

  • - Alt- Up/ Downเพื่อข้ามไปยังการเปลี่ยนแปลงก่อนหน้า / ถัดไป
  • - Alt- Left/ Rightเพื่อยอมรับการเปลี่ยนแปลงจากทางซ้ายหรือขวา

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


79

หากคุณกำลังทำกระทำเล็ก ๆ git log --mergeบ่อยแล้วเริ่มต้นด้วยการมองหาที่กระทำความเห็นด้วย จากนั้นgit diffจะแสดงความขัดแย้ง

สำหรับความขัดแย้งที่มีมากกว่าสองสามบรรทัดจะง่ายกว่าที่จะเห็นสิ่งที่เกิดขึ้นในเครื่องมือ GUI ภายนอก ฉันชอบ opendiff - Git ยังรองรับ vimdiff, gvimdiff, kdiff3, tkdiff, meld, xxdiff, โผล่ออกมาจากกล่องและคุณสามารถติดตั้งอื่น ๆ : git config merge.tool "your.tool"จะตั้งค่าเครื่องมือที่คุณเลือกและgit mergetoolหลังจากการรวมที่ล้มเหลวจะแสดงความแตกต่างในบริบท

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


8
การใช้ "git add" เป็นเคล็ดลับที่แท้จริงที่นี่ คุณอาจไม่ต้องการกระทำ (บางทีคุณต้องการซ่อน) แต่คุณต้องทำ "git add" เพื่อทำการผสานให้เสร็จสมบูรณ์ ฉันคิดว่า mergetool ทำการเพิ่มให้คุณ (แม้ว่ามันจะไม่ได้อยู่ใน manpage) แต่ถ้าคุณทำ merge ด้วยตนเองคุณต้องใช้ "git add" เพื่อทำให้เสร็จสมบูรณ์ (แม้ว่าคุณจะไม่ต้องการคอมมิท)
สูงศักดิ์

47

ดูวิธีการนำเสนอความขัดแย้งหรือในgit mergeเอกสารGit เพื่อทำความเข้าใจว่าเครื่องหมายความขัดแย้งผสานคืออะไร

นอกจากนี้ส่วนวิธีแก้ไขข้อขัดแย้งยังอธิบายถึงวิธีแก้ไขข้อขัดแย้ง:

หลังจากเห็นความขัดแย้งคุณสามารถทำได้สองสิ่ง:

  • ตัดสินใจที่จะไม่รวม การล้างข้อมูลที่คุณต้องการเพียงอย่างเดียวคือการรีเซ็ตไฟล์ดัชนีเป็นคอมมิชชันHEADเพื่อย้อนกลับ 2. และทำความสะอาดการเปลี่ยนแปลงแผนผังการทำงานที่ทำโดย 2 และ 3 git merge --abortสามารถใช้สำหรับสิ่งนี้

  • แก้ไขข้อขัดแย้ง Git จะทำเครื่องหมายข้อขัดแย้งในแผนผังการทำงาน แก้ไขไฟล์เป็นรูปร่างและgit addพวกเขาไปยังดัชนี ใช้git commitเพื่อปิดการจัดการ

คุณสามารถแก้ไขข้อขัดแย้งด้วยเครื่องมือต่าง ๆ :

  • ใช้ mergetool git mergetoolเพื่อเปิดใช้งานกราฟิก mergetool ซึ่งจะทำงานให้คุณผ่านการผสาน

  • ดูความแตกต่าง git diffจะแสดงความต่างสามทางเน้นการเปลี่ยนแปลงจากทั้งสองHEADและMERGE_HEADรุ่น

  • ดูความแตกต่างจากแต่ละสาขา git log --merge -p <path>จะแสดงต่างกันก่อนสำหรับHEADเวอร์ชันและMERGE_HEADเวอร์ชันนั้น

  • ดูต้นฉบับ git show :1:filenameแสดงบรรพบุรุษร่วมกันgit show :2:filenameแสดงHEADรุ่นและgit show :3:filenameแสดงMERGE_HEADรุ่น

นอกจากนี้คุณยังสามารถอ่านเกี่ยวกับเครื่องหมายผสานความขัดแย้งและวิธีการแก้ไขปัญหาในโปร Gitส่วนหนังสือความขัดแย้งผสานพื้นฐาน


42

ฉันต้องการเวอร์ชั่นเต็มหรือต้องการตรวจสอบการเปลี่ยนแปลงรายบุคคลและตัดสินใจเลือกแต่ละข้อ

ยอมรับเวอร์ชั่นของฉันหรือของพวกเขาอย่างเต็มที่ :

ยอมรับรุ่นของฉัน (ท้องถิ่นของเรา):

git checkout --ours -- <filename>
git add <filename>              # Marks conflict as resolved
git commit -m "merged bla bla"  # An "empty" commit

ยอมรับรุ่นของพวกเขา (ระยะไกลพวกเขา):

git checkout --theirs -- <filename>
git add <filename>
git commit -m "merged bla bla"

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

git merge --strategy-option ours

หรือ

git merge --strategy-option theirs

ตรวจสอบการเปลี่ยนแปลงทั้งหมดและยอมรับเป็นรายบุคคล

  1. git mergetool
  2. ตรวจสอบการเปลี่ยนแปลงและยอมรับทั้งสองเวอร์ชันสำหรับแต่ละเวอร์ชัน
  3. git add <filename>
  4. git commit -m "merged bla bla"

เริ่มต้นmergetoolการทำงานในบรรทัดคำสั่ง วิธีใช้ mergetool บรรทัดคำสั่งควรเป็นคำถามแยกต่างหาก

คุณยังสามารถติดตั้งเครื่องมือแสดงผลสำหรับสิ่งนี้เช่นmeldและเรียกใช้

git mergetool -t meld

มันจะเปิดรุ่นในประเทศ (ของเรา), "ฐาน" หรือ "ผสาน" รุ่น (ผลปัจจุบันของการผสาน) และรุ่นระยะไกล (ของพวกเขา) บันทึกเวอร์ชันที่ผสานเมื่อเสร็จแล้วให้เรียกใช้git mergetool -t meldอีกครั้งจนกว่าคุณจะได้รับ "ไม่ต้องรวมไฟล์" จากนั้นไปที่ขั้นตอนที่ 3 และ 4


คำสั่งนี้: git checkout - theirs - <filename> เปลี่ยนไฟล์ทั้งหมดเป็นไฟล์ไม่ใช่แค่ <filename>
Donato

ที่จริงฉันผิด อัปเดตไฟล์ที่ระบุนี้เท่านั้น
Donato

40

สำหรับผู้ใช้Emacที่ต้องการแก้ไขความขัดแย้งแบบกึ่งรวมด้วยตนเอง:

git diff --name-status --diff-filter=U

แสดงไฟล์ทั้งหมดที่ต้องมีการแก้ไขข้อขัดแย้ง

เปิดแต่ละไฟล์เหล่านี้ทีละไฟล์หรือทั้งหมดพร้อมกันโดย:

emacs $(git diff --name-only --diff-filter=U)

เมื่อไปที่บัฟเฟอร์ที่ต้องการแก้ไขใน Emacs ให้พิมพ์

ALT+x vc-resolve-conflicts

สิ่งนี้จะเปิดบัฟเฟอร์สามตัว (ของฉัน, ของพวกเขาและบัฟเฟอร์ที่ส่งออก) นำทางโดยการกด 'n' (ภูมิภาคถัดไป), 'p' (ภูมิภาคที่เหนือกว่า) กด 'a' และ 'b' เพื่อคัดลอกเหมืองหรือภูมิภาคของพวกเขาไปยังบัฟเฟอร์ผลลัพธ์ตามลำดับ และ / หรือแก้ไขบัฟเฟอร์เอาต์พุตโดยตรง

เมื่อเสร็จแล้ว: กด 'q' Emacs ถามคุณว่าคุณต้องการบันทึกบัฟเฟอร์นี้หรือไม่: ใช่ หลังจากทำบัฟเฟอร์เสร็จแล้วให้ทำเครื่องหมายตามที่ได้รับการแก้ไขโดยเรียกใช้จากอาชญากร:

git add FILENAME

เมื่อเสร็จแล้วกับบัฟเฟอร์ทุกประเภท

git commit

เพื่อสิ้นสุดการผสาน


33

โบนัส:

ในการพูดถึงการดึง / ดึง / ผสานในคำตอบข้างต้นฉันต้องการแบ่งปันเคล็ดลับที่น่าสนใจและมีประสิทธิผล

git pull --rebase

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

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

ในกรณีที่มีข้อขัดแย้งเพียงใช้

git mergetool
git add conflict_file
git rebase --continue

ค้นหารายละเอียดได้ที่: http://gitolite.com/git-pull--rebase


32

เพียงแค่ถ้าคุณรู้ดีว่าการเปลี่ยนแปลงในที่เก็บหนึ่งไม่สำคัญและต้องการแก้ไขการเปลี่ยนแปลงทั้งหมดในที่เก็บอื่นให้ใช้:

git checkout . --ours

เพื่อแก้ไขการเปลี่ยนแปลงในความโปรดปรานของที่เก็บของคุณหรือ

git checkout . --theirs

เพื่อแก้ปัญหาการเปลี่ยนแปลงในความโปรดปรานของอื่น ๆ หรือพื้นที่เก็บข้อมูลหลัก

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

git mergetool -t p4merge

และหลังจากเสร็จสิ้นไฟล์คุณจะต้องบันทึกและปิดดังนั้นไฟล์ถัดไปจะเปิด


2
ชำระเงินคอมไพล์ - พวกเขา แก้ปัญหาของฉันขอบคุณ
Ramesh Chand

ถ้าคุณต้องการที่จะแก้ไขข้อขัดแย้งด้วยตนเองลองเปิดโฟลเดอร์ในรหัส Visual Studio มันทำเครื่องหมายไฟล์ที่มีความขัดแย้งและสีเส้นขัดแย้งภายในทุก ๆ คน
Mohamed Selim

31

โปรดทำตามขั้นตอนต่อไปนี้เพื่อแก้ไขข้อขัดแย้งใน Git:

  1. ตรวจสอบสถานะ Git: สถานะ git

  2. รับ patchset: git fetch (ชำระเงิน patch ที่ถูกต้องจาก Git ของคุณ)

  3. ชำระเงินสาขาในประเทศ (temp1 ในตัวอย่างของฉันที่นี่): git checkout -b temp1

  4. ดึงเนื้อหาล่าสุดจากต้นแบบ: git pull --rebase master ต้นแบบ

  5. เริ่มต้น mergetool และตรวจสอบข้อขัดแย้งและแก้ไข ... และตรวจสอบการเปลี่ยนแปลงในสาขาระยะไกลกับสาขาปัจจุบันของคุณ: git mergetool

  6. ตรวจสอบสถานะอีกครั้ง: สถานะ git

  7. ลบไฟล์ที่ไม่ต้องการที่สร้างในเครื่องโดย mergetool โดยปกติแล้ว mergetool จะสร้างไฟล์พิเศษด้วยนามสกุล *. orig โปรดลบไฟล์นั้นเนื่องจากเป็นเพียงไฟล์ที่ซ้ำกันและแก้ไขการเปลี่ยนแปลงในเครื่องและเพิ่มไฟล์เวอร์ชั่นที่ถูกต้อง git เพิ่ม #your_changed_correct_files

  8. ตรวจสอบสถานะอีกครั้ง: สถานะ git

  9. ยอมรับการเปลี่ยนแปลงในคอมมิท id เดียวกัน (หลีกเลี่ยงชุดแพทช์แยกใหม่): git commit - แก้ไข

  10. กดไปที่สาขาหลัก: git push (ไปยังที่เก็บ Git ของคุณ)


28

มี 3 ขั้นตอนคือ

  1. ค้นหาไฟล์ที่ทำให้เกิดความขัดแย้งโดยคำสั่ง

    git status
    
  2. ตรวจสอบไฟล์ที่คุณจะพบความขัดแย้งที่ทำเครื่องหมายว่า

    <<<<<<<<head
    blablabla
    
  3. เปลี่ยนเป็นวิธีที่คุณต้องการจากนั้นส่งด้วยคำสั่ง

    git add solved_conflicts_files
    git commit -m 'merge msg'
    

ทำงานให้ฉัน! ขอบคุณ!
Nuwan Jayawardene

คุณต้องให้ความสนใจหากทำเช่นนี้ระหว่างการรีบูต คุณควรใช้การรีคอมไพล์ git - หยุดแทนที่จะคอมไพล์คอมไพล์
Samuel Dauzon

27

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

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

ฉันได้ติดนิสัย 2 สิ่งเพื่อหลีกเลี่ยงสิ่งนี้

แทน:

git add .
git commit -m"some msg"

ซึ่งมีสองข้อเสีย -

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

ดังนั้นแทนที่จะทำ:

git add file,file2,file3...
git commit # Then type the files in the editor and save-quit.

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

[อัพเดท - เมื่อเวลาผ่านไปฉันได้เปลี่ยนไปเป็น:

git status # Make sure I know whats going on
git add .
git commit # Then use the editor

]

นอกจากนี้ (และเกี่ยวข้องกับสถานการณ์ของคุณมากขึ้น) ฉันพยายามหลีกเลี่ยง:

git pull

หรือ

git pull origin master.

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

แต่ฉันพยายามทำ

git checkout master
git fetch   
git rebase --hard origin/master # or whatever branch I want.

คุณอาจพบว่ามีประโยชน์:

สาขา git, fork, fetch, ผสาน, rebase และ clone อะไรคือความแตกต่าง


เฮ้ฉันเข้าใจคำตอบของคุณ แต่เนื่องจากฉันใหม่กับความขัดแย้งผสาน github ฉันคิดว่ามีบางสิ่งที่ขาดหายไป เกิดอะไรขึ้นกับการปรับเปลี่ยนในท้องถิ่นของคุณเมื่อคุณทำgit checkout masterและ git fetch และ git rebase --hard origin/master
Suhaib

ฉันเชื่อว่าคุณควรเพิ่มรายละเอียดเพิ่มเติมเกี่ยวกับสิ่งที่ต้องทำ อีกตัวอย่างที่ทำให้ฉันสับสนคุณพูดถึงคำตอบของคุณ: เราทำgit add .มันจะช่วยแก้ไขการปรับเปลี่ยนในพื้นที่ของเราเพื่อให้เราสามารถติดตามได้git checkout masterหรือไม่? หรือพวกเขาทั้งสองสถานการณ์ที่แตกต่างกันอย่างไร
Suhaib

$ git rebase --hard origin/master b5a30cc159ba8dd error: unknown option การใช้งานของ@MichaelDurrant hard: git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] [<upstream>] [<branch>] หรือ: git rebase [-i] [ ตัวเลือก] [--exec <cmd>] [--onto <newbase>] - รูท [<branch>] หรือ: git rebase - ยกเลิก | --abort | --skip | - edit-todo `
likejudo

24

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

(Code not in Conflict)
>>>>>>>>>>>
(first alternative for conflict starts here)
Multiple code lines here
===========
(second alternative for conflict starts here)
Multiple code lines here too    
<<<<<<<<<<<
(Code not in conflict here)

เลือกหนึ่งในตัวเลือกหรือการรวมกันของทั้งสองอย่างในแบบที่คุณต้องการให้รหัสใหม่ในขณะที่ลบเครื่องหมายเท่ากับและวงเล็บเหลี่ยม

git commit -a -m "commit message"
git push origin master

17
git log --merge -p [[--] path]

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

สิ่งที่ฉันทำเพื่อแก้ไขปัญหานี้คือเปิดสองบรรทัดคำสั่งและในการทำงานครั้งเดียว

git log ..$MERGED_IN_BRANCH --pretty=full -p [path]

และอื่น ๆ

git log $MERGED_IN_BRANCH.. --pretty=full -p [path]

แทนที่$MERGED_IN_BRANCHด้วยสาขาที่ฉันผสานและ[path]ด้วยไฟล์ที่ขัดแย้งกัน คำสั่งนี้จะบันทึกการคอมมิททั้งหมดในรูปแบบแพตช์ระหว่าง ( ..) สองคอมมิท หากคุณเว้นว่างด้านใดด้านหนึ่งเหมือนในคำสั่งด้านบนคอมไพล์จะใช้โดยอัตโนมัติHEAD(สาขาที่คุณกำลังรวมอยู่ในกรณีนี้)

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


16

การใช้ patience

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

หากคุณเปลี่ยนการเยื้องของโปรแกรมเช่นบางครั้งกลยุทธ์การผสาน Git เริ่มต้นจะจับคู่วงเล็บปีกกาเดี่ยว{ซึ่งเป็นของฟังก์ชันที่แตกต่างกัน นี่คือหลีกเลี่ยงด้วยpatience:

git merge -s recursive -X patience other-branch

จากเอกสาร:

With this option, merge-recursive spends a little extra time to avoid 
mismerges that sometimes occur due to unimportant matching lines 
(e.g., braces from distinct functions). Use this when the branches to 
be merged have diverged wildly.

เปรียบเทียบกับบรรพบุรุษร่วมกัน

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

git diff $(git merge-base <our-branch> <their-branch>) <their-branch>

โดยปกติคุณต้องการเห็นการเปลี่ยนแปลงสำหรับไฟล์เฉพาะ:

git diff $(git merge-base <our-branch> <their-branch>) <their-branch> <file>

ในกรณีของฉันการทำเช่นนี้ไม่สามารถแก้ไขข้อขัดแย้งในการรวมได้เนื่องจากเหตุผลบางประการมันทำให้มีบรรทัดการกำหนดค่าซ้ำกันในโครงการ C # แม้ว่ามันจะเป็นมิตรมากกว่าไฟล์ทั้งหมดที่ฉันเคยมีมาก่อน
Mathijs Segers

15

ตั้งแต่วันที่ 12 ธันวาคม 2559 คุณสามารถรวมสาขาและแก้ไขข้อขัดแย้งใน github.com

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

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

ป้อนคำอธิบายรูปภาพที่นี่


นี่ไม่ได้ถามเกี่ยวกับ GitHub ดังนั้นฉันจึงลงคะแนนในสิ่งที่ฉันคิดว่าเป็นคำตอบที่แย่มาก
mschuett

1
@mschuett ถูกต้องคำถามคือ "วิธีแก้ไขข้อขัดแย้งในคอมไพล์" ไม่ใช่ "วิธีแก้ไขข้อขัดแย้งใน gitub" มีความแตกต่างและมีคนจำนวนมากเกินไปที่คิดว่าคอมไพล์และ GitHub เป็นสิ่งเดียวกันดังนั้นสิ่งใดก็ตามที่เผยแพร่ความรู้สึกนั้นผิด
Patrick Mevzek

15

ถ้าคุณต้องการผสานจาก branch (test) ถึง master คุณสามารถทำตามขั้นตอนเหล่านี้:

ขั้นตอนที่ 1 : ไปที่สาขา

git checkout test

ขั้นตอนที่ 2 :

git pull --rebase origin master

ขั้นตอนที่ 3 : หากมีข้อขัดแย้งให้ไปที่ไฟล์เหล่านี้เพื่อแก้ไข

ขั้นตอนที่ 4 : เพิ่มการเปลี่ยนแปลงเหล่านี้

git add #your_changes_files

ขั้นตอนที่ 5 :

git rebase --continue

ขั้นตอนที่ 6 : หากยังมีข้อขัดแย้งให้กลับไปที่ขั้นตอนที่ 3 อีกครั้ง หากไม่มีข้อขัดแย้งให้ทำดังนี้:

git push origin +test

ขั้นตอนที่ 7 : จากนั้นไม่มีข้อขัดแย้งระหว่างการทดสอบและปริญญาโท คุณสามารถใช้การผสานโดยตรง


13

ฉันทำตามขั้นตอนด้านล่างเสมอเพื่อหลีกเลี่ยงความขัดแย้ง

  • git checkout master (มาที่สาขาหลัก)
  • git pull (อัพเดทเจ้านายของคุณเพื่อรับรหัสล่าสุด)
  • git checkout -b mybranch (ชำระเงินสาขาใหม่และเริ่มทำงานกับสาขานั้นเพื่อให้เจ้านายของคุณอยู่ด้านบนของลำตัวเสมอ)
  • คอมไพล์เพิ่ม และคอมไพล์ยอมรับและ git push (ในสาขาท้องถิ่นของคุณหลังจากการเปลี่ยนแปลงของคุณ)
  • git checkout master (กลับมาที่ master ของคุณ)

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


12

การรวมความขัดแย้งอาจเกิดขึ้นได้ในสถานการณ์ต่าง ๆ :

  • เมื่อเรียกใช้ "git fetch" แล้ว "git merge"
  • เมื่อเรียกใช้ "git fetch" แล้ว "git rebase"
  • เมื่อใช้งาน "git pull" (ซึ่งจริงๆแล้วเท่ากับหนึ่งในเงื่อนไขที่กล่าวถึงข้างต้น)
  • เมื่อเรียกใช้ "git stash pop"
  • เมื่อคุณใช้งานแพทช์คอมไพล์ (คอมมิทที่ส่งออกไปยังไฟล์ที่จะถ่ายโอนเช่นอีเมล)

คุณต้องติดตั้งเครื่องมือผสานที่เข้ากันได้กับ Git เพื่อแก้ไขข้อขัดแย้ง ฉันใช้ KDiff3 เป็นการส่วนตัวและฉันคิดว่ามันดีและมีประโยชน์ คุณสามารถดาวน์โหลดเวอร์ชั่น Windows ได้ที่นี่:

https://sourceforge.net/projects/kdiff3/files/

BTW ถ้าคุณติดตั้ง Git Extensions จะมีตัวเลือกในวิซาร์ดการตั้งค่าเพื่อติดตั้ง Kdiff3

จากนั้นตั้งค่า git configs เพื่อใช้ Kdiff เป็น mergetool:

$ git config --global --add merge.tool kdiff3
$ git config --global --add mergetool.kdiff3.path "C:/Program Files/KDiff3/kdiff3.exe"
$ git config --global --add mergetool.kdiff3.trustExitCode false

$ git config --global --add diff.guitool kdiff3
$ git config --global --add difftool.kdiff3.path "C:/Program Files/KDiff3/kdiff3.exe"
$ git config --global --add difftool.kdiff3.trustExitCode false

(อย่าลืมแทนที่เส้นทางด้วยเส้นทางที่แท้จริงของไฟล์ Kdiff exe)

จากนั้นทุกครั้งที่คุณพบข้อขัดแย้งผสานคุณเพียงแค่เรียกใช้คำสั่งนี้:

$git mergetool

จากนั้นจะเปิด Kdiff3 และพยายามแก้ไขข้อขัดแย้งการผสานโดยอัตโนมัติ ความขัดแย้งส่วนใหญ่จะแก้ไขได้เองและคุณต้องแก้ไขส่วนที่เหลือด้วยตนเอง

นี่คือลักษณะของ Kdiff3:

ป้อนคำอธิบายภาพที่นี่

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

หากต้องการตรวจสอบว่าการรวมทุกอย่างสำเร็จหรือไม่เพียงรันคำสั่ง mergetool อีกครั้งคุณควรได้ผลลัพธ์นี้:

$git mergetool
No files need merging

8

คำตอบนี้คือการเพิ่มทางเลือกสำหรับผู้ใช้ VIM เช่นฉันที่ต้องการทำทุกอย่างภายในโปรแกรมแก้ไข


TL; DR

ป้อนคำอธิบายรูปภาพที่นี่


Tpope ขึ้นมาด้วยปลั๊กอินที่ดีสำหรับเป็นกลุ่มที่เรียกว่าผู้ลี้ภัย เมื่อติดตั้งแล้วคุณสามารถเรียกใช้:Gstatusเพื่อตรวจสอบไฟล์ที่มีข้อขัดแย้งและ:Gdiffเปิด Git ได้ 3 วิธี

เมื่อรวมเข้าด้วยกัน 3 วิธีผู้ลี้ภัยจะช่วยให้คุณได้รับการเปลี่ยนแปลงของสาขาใด ๆ ที่คุณรวมเข้าด้วยกันในรูปแบบต่อไปนี้:

  • :diffget //2รับการเปลี่ยนแปลงจากสาขาดั้งเดิม ( HEAD ):
  • :diffget //3รับการเปลี่ยนแปลงจากการรวมสาขา:

เมื่อคุณเสร็จสิ้นการผสานไฟล์พิมพ์:Gwriteในบัฟเฟอร์ที่ผสาน Vimcasts เปิดตัววิดีโอยอดเยี่ยมที่อธิบายรายละเอียดขั้นตอนนี้


6

Gitlense สำหรับรหัส VS

คุณสามารถลองGitlenseสำหรับรหัส VS คุณสมบัติที่สำคัญคือ:

3. แก้ไขข้อขัดแย้งได้อย่างง่ายดาย

ฉันชอบคุณสมบัตินี้อยู่แล้ว:

ป้อนคำอธิบายรูปภาพที่นี่

2. ตำหนิบรรทัดปัจจุบัน

ป้อนคำอธิบายรูปภาพที่นี่

3. Gutter Blame

ป้อนคำอธิบายรูปภาพที่นี่

4. ตำหนิแถบสถานะ

ป้อนคำอธิบายรูปภาพที่นี่

และมีคุณสมบัติมากมายที่คุณสามารถตรวจสอบได้ที่นี่


5

git fetch
git ชำระเงินสาขา
git rebase master ของคุณ

ในขั้นตอนนี้คุณจะพยายามแก้ไขข้อขัดแย้งโดยใช้ IDE ที่คุณต้องการ

คุณสามารถไปที่ลิงค์นี้เพื่อตรวจสอบโฮเพื่อแก้ไขข้อขัดแย้งในไฟล์
https://help.github.com/articles/resolving-a-merge-conflict-using-the-command-line/

git เพิ่ม
git rebase - ยุติ
git commit - แก้ไข
แหล่งที่มา push git HEAD: refs / drafts / master (push เหมือนร่าง)

ตอนนี้ทุกอย่างเรียบร้อยดีและคุณจะพบว่าคุณมีความมุ่งมั่นในการเป็น Gerrit

ฉันหวังว่าสิ่งนี้จะช่วยให้ทุกคนที่เกี่ยวข้องกับปัญหานี้


3

ลองใช้ Visual Studio Code เพื่อทำการแก้ไขหากคุณยังไม่มี สิ่งที่ทำคือหลังจากที่คุณลองผสาน (และทำให้เกิดความขัดแย้งในการรวม) โค้ด. VS จะตรวจจับความขัดแย้งที่ผสานโดยอัตโนมัติ

มันสามารถช่วยคุณได้เป็นอย่างดีโดยการแสดงการเปลี่ยนแปลงที่เกิดขึ้นกับต้นฉบับและคุณควรยอมรับ incomingหรือ

current change(หมายถึงต้นฉบับดั้งเดิมก่อนรวม) '

มันช่วยฉันและมันก็ใช้ได้กับคุณเช่นกัน!

PS: มันจะทำงานเฉพาะในกรณีที่คุณได้กำหนดค่าคอมไพล์ด้วยรหัสและรหัส Visual Studio ของคุณ


2

วิธีที่ปลอดภัยกว่าในการแก้ไขข้อขัดแย้งคือการใช้git-mediate (วิธีแก้ปัญหาทั่วไปที่แนะนำในที่นี้คือข้อผิดพลาดที่ค่อนข้างง่าย)

ดูโพสต์นี้สำหรับคำแนะนำเบื้องต้นเกี่ยวกับวิธีใช้งาน


2

สำหรับผู้ที่ใช้ Visual Studio (2015 ในกรณีของฉัน)

  1. ปิดโครงการของคุณใน VS โดยเฉพาะอย่างยิ่งในโครงการขนาดใหญ่ VS มีแนวโน้มที่จะออกนอกลู่นอกทางเมื่อรวมกับการใช้ UI

  2. ทำการผสานในพร้อมท์คำสั่ง

    git checkout target_branch

    คอมไพล์ผสาน source_branch

  3. จากนั้นเปิดโครงการใน VS และไปที่ Team Explorer -> Branch ขณะนี้มีข้อความแจ้งว่ากำลังดำเนินการผสานและไฟล์ที่ขัดแย้งกันอยู่ในรายการด้านล่างข้อความ

  4. คลิกไฟล์ที่ขัดแย้งและคุณจะมีตัวเลือกในการผสานเปรียบเทียบใช้แหล่งที่มาใช้เป้าหมาย เครื่องมือผสานใน VS นั้นใช้งานง่ายมาก


ฉันใช้ VS Code 2017 ในโครงการขนาดใหญ่มากและไม่จำเป็นต้องปิดโครงการ มันจัดการได้ค่อนข้างดี :)
protoEvangelion

2

หากคุณใช้ intelliJ เป็น IDE ลองผสานพาเรนต์เข้ากับสาขาของคุณด้วย

git checkout <localbranch>
git merge origin/<remotebranch>

มันจะแสดงความขัดแย้งทั้งหมดเช่นนี้

A_MBPro: ทดสอบต้นกำเนิดรวม $ sit / รวมอัตโนมัติ src / ทดสอบ / java / com /.../ TestClass.java ความขัดแย้ง (เนื้อหา): ผสานความขัดแย้งใน src / ทดสอบ / java / com /.../ TestClass.java

ตอนนี้โปรดทราบว่าไฟล์ TestClass.java จะแสดงเป็นสีแดงใน intelliJ นอกจากนี้สถานะ git จะปรากฏขึ้น

Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified:   src/test/java/com/.../TestClass.java

เปิดไฟล์ใน intelliJ มันจะมีส่วนด้วย

  <<<<<<< HEAD
    public void testMethod() {
    }
    =======
    public void testMethod() { ...
    }
    >>>>>>> origin/<remotebranch>

ที่ HEAD คือการเปลี่ยนแปลงในสาขาท้องถิ่นของคุณและที่มา / คือการเปลี่ยนแปลงจากสาขาระยะไกล ที่นี่เก็บสิ่งที่คุณต้องการและลบสิ่งที่คุณไม่ต้องการหลังจากนั้นขั้นตอนปกติควรทำ นั่นคือ

   git add TestClass.java
   git commit -m "commit message"
   git push

2

ฉันใช้รหัสภาพของ Microsoft เพื่อแก้ไขข้อขัดแย้ง มันใช้ง่ายมาก ฉันเปิดโครงการของฉันในพื้นที่ทำงาน มันตรวจจับและไฮไลท์ข้อขัดแย้งนอกจากนี้ยังมีตัวเลือก GUI เพื่อเลือกการเปลี่ยนแปลงใด ๆ ที่ฉันต้องการจาก HEAD หรือขาเข้า ป้อนคำอธิบายรูปภาพที่นี่

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