ไม่เกี่ยวข้องจริงๆคำตอบนี้ แต่ฉันคลองgit pull
ที่เพิ่งวิ่งตามมาด้วยgit fetch
git merge
คุณกำลังทำการผสานสามครั้งซึ่งจะทำให้ Git ของคุณเรียกใช้การดำเนินการดึงข้อมูลสามครั้งเมื่อการดึงข้อมูลเพียงครั้งเดียวคือทั้งหมดที่คุณต้องการ ดังนั้น:
git fetch origin # update all our origin/* remote-tracking branches
git checkout demo # if needed -- your example assumes you're on it
git merge origin/demo # if needed -- see below
git checkout master
git merge origin/master
git merge -X theirs demo # but see below
git push origin master # again, see below
การควบคุมการผสานที่ยุ่งยากที่สุด
git merge -X theirs
ส่วนที่น่าสนใจมากที่สุดคือที่นี่ ในฐานะที่เป็นroot545 ตั้งข้อสังเกตที่-X
ตัวเลือกจะถูกส่งผ่านไปยังกลยุทธ์การผสานและทั้งสองเริ่มต้นrecursive
กลยุทธ์และทางเลือกที่resolve
จะใช้กลยุทธ์-X ours
หรือ-X theirs
(หนึ่งหรืออื่น ๆ แต่ไม่ใช่ทั้งสอง) อย่างไรก็ตามเพื่อให้เข้าใจว่าพวกเขาทำอะไรคุณต้องรู้ว่า Git ค้นหาและปฏิบัติต่อผสานความขัดแย้งได้อย่างไร
ความขัดแย้งในการผสานอาจเกิดขึ้นภายในไฟล์1บางไฟล์เมื่อเวอร์ชันพื้นฐานแตกต่างจากทั้งเวอร์ชันปัจจุบัน (หรือที่เรียกว่าโลคัล, HEAD หรือ--ours
) และเวอร์ชันอื่น (เรียกอีกอย่างว่ารีโมตหรือ--theirs
) ของไฟล์เดียวกันนั้น นั่นคือการผสานได้ระบุการแก้ไขสามครั้ง (สามข้อผูกพัน): ฐานของเราและของพวกเขา เวอร์ชัน "ฐาน" มาจากฐานการผสานระหว่างคอมมิตของเราและคอมมิตดังที่พบในกราฟคอมมิต (สำหรับข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้โปรดดูโพสต์ StackOverflow อื่น ๆ ) จากนั้น Git ได้พบการเปลี่ยนแปลง 2 ชุด: "สิ่งที่เราทำ" และ "สิ่งที่พวกเขาทำ" การเปลี่ยนแปลงเหล่านี้ (โดยทั่วไป) จะพบในทีละบรรทัดโดยเป็นข้อความเท่านั้นพื้นฐาน. Git ไม่มีความเข้าใจอย่างแท้จริงเกี่ยวกับเนื้อหาของไฟล์ เป็นเพียงการเปรียบเทียบข้อความแต่ละบรรทัด
การเปลี่ยนแปลงเหล่านี้คือสิ่งที่คุณเห็นในgit diff
ผลลัพธ์และเช่นเคยมีบริบทด้วยเช่นกัน เป็นไปได้ว่าสิ่งที่เราเปลี่ยนแปลงนั้นอยู่คนละบรรทัดกับสิ่งที่เปลี่ยนแปลงเพื่อให้ดูเหมือนว่าการเปลี่ยนแปลงจะไม่ชนกัน แต่บริบทก็เปลี่ยนไปเช่นกัน (เช่นเนื่องจากการเปลี่ยนแปลงของเราอยู่ใกล้กับด้านบนหรือด้านล่างของไฟล์ เพื่อให้ไฟล์หมดในเวอร์ชันของเรา แต่ในไฟล์นั้นพวกเขาได้เพิ่มข้อความเพิ่มเติมที่ด้านบนหรือด้านล่าง)
หากการเปลี่ยนแปลงเกิดขึ้นในบรรทัดที่แตกต่างกันตัวอย่างเช่นเราเปลี่ยนcolor
เป็นcolour
บรรทัดที่ 17 และเปลี่ยนfred
เป็นbarney
บรรทัด 71 ดังนั้นจะไม่มีข้อขัดแย้ง Git เพียงแค่ทำการเปลี่ยนแปลงทั้งสองอย่าง หากการเปลี่ยนแปลงเกิดขึ้นในบรรทัดเดียวกัน แต่เป็นการเปลี่ยนแปลงที่เหมือนกัน Git จะใช้สำเนาการเปลี่ยนแปลง 1 ชุด เฉพาะในกรณีที่การเปลี่ยนแปลงอยู่ในบรรทัดเดียวกัน แต่เป็นการเปลี่ยนแปลงที่แตกต่างกันหรือกรณีพิเศษของบริบทรบกวนคุณจะได้รับการแก้ไข / แก้ไขความขัดแย้ง
-X ours
และ-X theirs
ตัวเลือกบอก Git วิธีการแก้ปัญหาความขัดแย้งนี้โดยการเลือกเพียงหนึ่งในสองการเปลี่ยนแปลง: เราหรือพวกเขา ตั้งแต่คุณบอกว่าคุณกำลังผสานdemo
(พวกเขา) ลงในmaster
(ของเรา) และต้องการการเปลี่ยนแปลงจากที่คุณต้องการdemo
-X theirs
-X
อย่างไรก็ตามการสมัครโดยสุ่มสี่สุ่มห้าเป็นสิ่งที่อันตราย เพียงเพราะการเปลี่ยนแปลงของเราไม่ขัดแย้งกันทีละบรรทัดไม่ได้หมายความว่าการเปลี่ยนแปลงของเราจะไม่ขัดแย้งกัน! ตัวอย่างคลาสสิกหนึ่งเกิดขึ้นในภาษาที่มีการประกาศตัวแปร เวอร์ชันพื้นฐานอาจประกาศตัวแปรที่ไม่ได้ใช้:
int i;
ในเวอร์ชันของเราเราจะลบตัวแปรที่ไม่ได้ใช้เพื่อให้คำเตือนของคอมไพเลอร์หายไปและในเวอร์ชันของพวกเขาจะเพิ่มลูปในภายหลังโดยใช้i
เป็นตัวนับลูป หากเรารวมการเปลี่ยนแปลงทั้งสองเข้าด้วยกันโค้ดผลลัพธ์จะไม่คอมไพล์อีกต่อไป -X
ตัวเลือกที่ช่วยไม่ได้ที่นี่ตั้งแต่การเปลี่ยนแปลงที่อยู่บนเส้นที่แตกต่างกัน
หากคุณมีชุดทดสอบอัตโนมัติสิ่งที่สำคัญที่สุดที่ต้องทำคือเรียกใช้การทดสอบหลังจากรวมเข้าด้วยกัน คุณสามารถทำสิ่งนี้ได้หลังจากตกลงและแก้ไขในภายหลังหากจำเป็น หรือคุณสามารถทำมันก่อนที่จะกระทำโดยการเพิ่ม--no-commit
กับgit merge
คำสั่ง เราจะฝากรายละเอียดทั้งหมดนี้ไว้ในโพสต์อื่น ๆ
1นอกจากนี้คุณยังอาจได้รับความขัดแย้งเกี่ยวกับการดำเนินการ "ทั้งไฟล์" เช่นบางทีเราแก้ไขการสะกดคำในไฟล์ (เพื่อให้เรามีการเปลี่ยนแปลง) และลบไฟล์ทั้งหมด (เพื่อให้มี ลบ). Git จะไม่แก้ไขข้อขัดแย้งเหล่านี้ด้วยตัวเองโดยไม่คำนึงถึง-X
ข้อโต้แย้ง
ทำการผสานน้อยลงและ / หรือผสานและ / หรือใช้ rebase อย่างชาญฉลาด
มีสามการผสานในลำดับคำสั่งของเราทั้งสอง ประการแรกคือการนำorigin/demo
เข้าสู่ท้องถิ่นdemo
(ของคุณใช้git pull
ซึ่งหาก Git ของคุณเก่ามากจะไม่สามารถอัปเดตได้origin/demo
แต่จะให้ผลลัพธ์ที่เหมือนกัน) ประการที่สองคือการนำorigin/master
เข้าmaster
มา
มันไม่ชัดเจนกับผมที่มีการปรับปรุงและdemo
/ หรือ master
หากคุณเขียนโค้ดของคุณเองในdemo
สาขาของคุณเองและคนอื่น ๆ กำลังเขียนโค้ดและผลักดันไปยังdemo
สาขาorigin
นั้นการผสานขั้นแรกนี้อาจมีข้อขัดแย้งหรือทำให้เกิดการผสานจริง บ่อยกว่านั้นควรใช้ rebase แทนการผสานเพื่อรวมงาน (ยอมรับว่าเป็นเรื่องของรสนิยมและความคิดเห็น) ในกรณีนี้คุณอาจต้องการใช้git rebase
แทน ในทางกลับกันถ้าคุณไม่เคยทำอะไรด้วยตัวเองคุณก็demo
ไม่จำเป็นต้องมีdemo
สาขา หรือหากคุณต้องการทำสิ่งนี้โดยอัตโนมัติ แต่สามารถตรวจสอบอย่างรอบคอบเมื่อมีการกระทำที่ทั้งคุณและคนอื่นสร้างขึ้นคุณอาจต้องการใช้git merge --ff-only origin/demo
: สิ่งนี้จะส่งต่ออย่างรวดเร็วของคุณdemo
เพื่อให้ตรงกับการอัปเดตorigin/demo
หากเป็นไปได้และจะล้มเหลวทันทีหากไม่ได้ (ณ จุดนี้คุณสามารถตรวจสอบการเปลี่ยนแปลงทั้งสองชุดและเลือกการผสานจริงหรือฐานใหม่ตามความเหมาะสม)
นี้ตรรกะเดียวกันกับmaster
ถึงแม้ว่าคุณจะกำลังทำผสานบน เพื่อให้คุณแน่นอนจะต้องมีmaster
master
อย่างไรก็ตามแม้ว่าคุณจะชอบที่คุณต้องการให้การผสานล้มเหลวหากไม่สามารถทำได้เป็นการไม่ผสานไปข้างหน้าอย่างรวดเร็วดังนั้นสิ่งนี้ก็ควรจะเป็นgit merge --ff-only origin/master
เช่นกัน
demo
พูดเถอะว่าคุณไม่เคยทำกระทำของคุณเองบน ในกรณีนี้เราสามารถทิ้งชื่อdemo
ทั้งหมดได้:
git fetch origin # update origin/*
git checkout master
git merge --ff-only origin/master || die "cannot fast-forward our master"
git merge -X theirs origin/demo || die "complex merge conflict"
git push origin master
หากคุณกำลังทำdemo
สาขาของคุณเองสิ่งนี้ไม่เป็นประโยชน์ คุณอาจเก็บการผสานที่มีอยู่ไว้ (แต่อาจเพิ่ม--ff-only
ขึ้นอยู่กับพฤติกรรมที่คุณต้องการ) หรือเปลี่ยนเป็นการทำ rebase โปรดทราบว่าทั้งสามวิธีอาจล้มเหลว: การผสานอาจล้มเหลวโดยมีข้อขัดแย้งการผสาน--ff-only
อาจไม่สามารถกรอไปข้างหน้าได้และการ rebase อาจล้มเหลวด้วยความขัดแย้ง (โดยพื้นฐานแล้ว rebase ทำงานโดยการเลือกเชอร์รี่ซึ่งใช้การผสาน เครื่องจักรและด้วยเหตุนี้อาจได้รับความขัดแย้งในการผสาน)
git push -f origin master