มี "git merge -s ours" รุ่น "หรือไม่?


876

เมื่อผสานหัวข้อหัวข้อ "B" เป็น "A" โดยใช้git mergeฉันได้รับความขัดแย้งบางอย่าง ฉันรู้ว่าความขัดแย้งทั้งหมดสามารถแก้ไขได้โดยใช้เวอร์ชันใน "B"

git merge -s oursฉันรู้ git merge -s theirsแต่สิ่งที่ผมต้องการคือสิ่งที่ต้องการ

ทำไมมันไม่มีอยู่จริง? ฉันจะบรรลุผลลัพธ์เดียวกันหลังจากการผสานที่ขัดแย้งกับgitคำสั่งที่มีอยู่ได้อย่างไร ( git checkoutทุกไฟล์ที่แยกจาก B)

UPDATE: "การแก้ปัญหา" ของการทิ้งอะไรจากสาขา A (การรวมชี้ไปที่ต้นไม้รุ่น B) ไม่ใช่สิ่งที่ฉันกำลังมองหา


1
ดูคำตอบนี้: stackoverflow.com/questions/928646/… - มันเป็นเรื่องเล็กน้อยที่จะเปลี่ยนตัวอย่างเพื่อใช้เวอร์ชัน B แทน A.
Robie Basak

8
ดูดังนั้นคำตอบคำสั่งคอมไพล์สำหรับการทำสาขาหนึ่งเช่นอีกสำหรับทุกวิธีที่เป็นไปในปัจจุบันเพื่อจำลอง git merge -s their
VonC

4
ดังนั้นคุณจึงไม่ได้มองหาgit merge -s theirs(ที่สามารถทำได้อย่างง่ายดายด้วยgit merge -s oursและเป็นสาขาชั่วคราว) เนื่องจาก -s ของเราเพิกเฉยต่อการเปลี่ยนแปลงของการรวมสาขาจาก ...
Nicolò Martini

21
@Torek - ทำ Git devs จริงๆพบว่ามันที่น่ารังเกียจที่จะให้theirsนอกเหนือไปours??? นี่เป็นอาการของหนึ่งในปัญหาระดับสูงด้านวิศวกรรมและการออกแบบใน Git: ความไม่สอดคล้องกัน
jww

3
@jww ปัญหาที่นี่ไม่ได้เกี่ยวกับ "git merge-s ours" ซึ่งเป็นการล่วงละเมิด แต่เกี่ยวกับมันเป็นการต่อต้าน คุณสามารถเห็นได้จากคำถามของ OP ว่าหากมีการเพิ่มคุณสมบัติดังกล่าวเขาจะใช้โดยไม่ได้ตั้งใจเมื่อสิ่งที่เขาต้องการทำจริงๆคือ "git merge -s recursive -X พวกเขา" เป็นเรื่องปกติที่จะต้องการรวมสาขาอื่นเข้ามาแทนที่ความขัดแย้งกับเวอร์ชั่นในสาขาอื่น แต่การเขียนทับสาขาปัจจุบันอย่างสมบูรณ์กับสาขาอื่นโดยสิ้นเชิงการยกเลิกการเปลี่ยนแปลงในปัจจุบันเป็นกรณียกเว้นจริง ๆ
ThomazMoura

คำตอบ:


1019

เพิ่มตัวเลือกในการ-X theirsตัวอย่างเช่น:

git checkout branchA
git merge -X theirs branchB

ทุกอย่างจะรวมกันในวิธีที่ต้องการ

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

การแก้ไขเป็นเรื่องง่าย เพียงรันgit rmด้วยชื่อของไฟล์ใด ๆ ที่ถูกลบ:

git rm {DELETED-FILE-NAME}

หลังจากนั้น-X theirsควรทำงานตามที่คาดไว้

แน่นอนว่าการลบตามจริงด้วยgit rmคำสั่งจะช่วยป้องกันความขัดแย้งเกิดขึ้นตั้งแต่แรก


หมายเหตุ : มีตัวเลือกฟอร์มที่ยาวขึ้น

หากต้องการใช้งานให้แทนที่:

-X theirs

ด้วย:

--strategy-option=theirs

6
ดูคำตอบอื่น ๆ ด้านล่างสำหรับวิธีแก้ปัญหาที่ดีกว่า (Paul Pladijs) กับคำถามเดิม
Malcolm

204
ควรทราบว่านี่ไม่เหมือนกับ "กลยุทธ์การรวมtheirs" -Xtheirs เป็นกลยุทธ์ที่ตัวเลือกนำไปใช้กับ recursive กลยุทธ์ ซึ่งหมายความว่ากลยุทธ์แบบเรียกซ้ำจะยังคงผสานสิ่งที่ทำได้และจะย้อนกลับไปที่ตรรกะ "ของพวกเขา" ในกรณีที่มีข้อขัดแย้ง ในขณะที่นี่คือสิ่งที่เราต้องการในกรณีส่วนใหญ่เช่นด้านบนนี่ไม่เหมือนกับ "แค่เอาทุกอย่างจากสาขา B อย่างที่เป็นอยู่" เป็นการผสานที่แท้จริงแทน
Timur

2
มันทำงานร่วมกับคำสั่งอื่น ๆ ได้เช่นกัน ฉันเพิ่งทำ 'git cherry-pick sha1 -X พวกเขา' ขอบคุณ!
Max Hohenegger

48
นี่เป็นคำตอบที่แย่มากเพราะมันดูถูก แต่จริง ๆ แล้วผิด "git merge -X พวกเขา" ไม่ได้ทำในสิ่งที่ "git merge -s พวกเขา" จะทำ มันไม่ได้แทนที่สาขาปัจจุบันด้วยเนื้อหาของสาขาที่ผสาน มันชอบการเปลี่ยนแปลง "ของพวกเขา" แต่เฉพาะในกรณีที่มีความขัดแย้ง ดังนั้นการกระทำที่เกิดขึ้นอาจแตกต่างจากสาขา "ของพวกเขา" นี่ไม่ใช่สิ่งที่ผู้โพสต์คำถามมีอยู่ในใจ
Ivan Krivyakov

7
@ user3338098: ใช่คุณพูดถูก ฉันอ่านคำถามอีกครั้งและมันก็ไม่ดีเช่นกัน น่าเสียดายที่สาเหตุของความสับสนไม่ใช่คำตอบและไม่ใช่แม้แต่คำถาม เป็นตัวเลือกการออกแบบของผู้เขียน git เพื่อให้ชื่อเดียวกัน 'ของเรา' กับกลยุทธ์การรวมและตัวเลือกของกลยุทธ์การรวม 'ซ้ำ' ความสับสนในกรณีนี้หลีกเลี่ยงไม่ได้ในทางปฏิบัติ
Ivan Krivyakov

218

โซลูชันที่เป็นไปได้และผ่านการทดสอบสำหรับการรวม branchB เข้ากับ branchA ที่เช็คเอาท์

# in case branchA is not our current branch
git checkout branchA

# make merge commit but without conflicts!!
# the contents of 'ours' will be discarded later
git merge -s ours branchB    

# make temporary branch to merged commit
git branch branchTEMP         

# get contents of working tree and index to the one of branchB
git reset --hard branchB

# reset to our merged commit but 
# keep contents of working tree and index
git reset --soft branchTEMP

# change the contents of the merged commit
# with the contents of branchB
git commit --amend

# get rid off our temporary branch
git branch -D branchTEMP

# verify that the merge commit contains only contents of branchB
git diff HEAD branchB

หากต้องการทำให้เป็นแบบอัตโนมัติคุณสามารถรวมไว้ในสคริปต์โดยใช้ branchA และ branchB เป็นอาร์กิวเมนต์

git merge -s theirs branchBวิธีการแก้ปัญหานี้จะเก็บรักษาผู้ปกครองครั้งแรกและครั้งที่สองของการผสานกระทำเช่นเดียวกับที่คุณคาดหวังของ


ถาม: ทำไมคุณถึงต้องการ branchTEMP คุณทำไม่ได้git reset --soft branchAเหรอ
cdunn2001

4
@ cdunn2001: อย่างใดฉันคิดในสิ่งเดียวกัน แต่ไม่ โปรดทราบว่าgit reset --hardการเปลี่ยนแปลงที่กระทำbranchAชี้ไปที่
Tsuyoshi Ito

5
ขอโทษที่ถามคำถามโง่ ๆ แต่ทำไมวิธีนี้ถึงดีกว่า -xtheirs อะไรคือข้อดี / ข้อเสีย
chrispepper1989

9
@ chrispepper1989 -x พวกเขามีผลต่อความขัดแย้งเท่านั้นหากก้อนใหญ่ของเราสามารถนำไปใช้ได้อย่างหมดจดก็จะได้รับการรวมเข้าด้วยกัน ในกรณีนี้ดังที่แสดงโดยคำสั่งสุดท้ายเราได้รับการผสานที่เหมือนกันอย่างสมบูรณ์กับ branchB โดยไม่คำนึงว่าจะมีความขัดแย้งหรือไม่
UncleZeiv

2
@ UncleZeiv ขอบคุณสำหรับคำอธิบายดังนั้นโดยพื้นฐานแล้วการทำ "ของพวกเขา" จะทำให้การเปลี่ยนแปลงที่ไม่ขัดแย้งกันและไฟล์ทำให้เกิดรหัส int ที่ไม่เหมือนกับรหัสที่ดึงมา
chrispepper1989

89

รุ่นเก่าของ git อนุญาตให้คุณใช้กลยุทธ์การผสาน "พวกเขา":

git pull --strategy=theirs remote_branch

แต่สิ่งนี้ได้ถูกลบไปแล้วตามที่อธิบายไว้ในข้อความนี้โดยJunio ​​Hamano (ผู้ดูแล Git) ดังที่ระบุไว้ในลิงค์แทนคุณจะทำสิ่งนี้:

git fetch origin
git reset --hard origin

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


7
ฉันไม่เข้าใจคำอธิบายของ Junio ​​Hamano เลย วิธีgit reset --hard originแก้ปัญหาสำหรับการผสานสไตล์ของพวกเขาคืออะไร? หากฉันต้องการรวม BranchB เข้ากับ BranchA (เช่นในคำตอบของ Alan W. Smith) ฉันจะใช้resetวิธีนี้ได้อย่างไร
James McMahon

3
@James McMahon: ประเด็นของ Junio ​​C Hamano ไม่ได้git reset --hardเป็นการผสาน "สไตล์ของพวกเขา" แน่นอนgit reset --hardไม่สร้างการรวมผสานหรือการกระทำใด ๆ สำหรับเรื่องนั้น ประเด็นของเขาคือเราไม่ควรใช้การผสานเพื่อแทนที่สิ่งใดก็ตามใน HEAD ด้วยอย่างอื่น ฉันไม่จำเป็นต้องเห็นด้วย
Tsuyoshi Ito

11
มันเป็นความอัปยศที่theirsถูกลบออกเพราะเหตุผลไม่สมบูรณ์ มันล้มเหลวในการอนุญาตให้อินสแตนซ์เหล่านั้นซึ่งรหัสนั้นดีเพียงแค่ว่า upstream นั้นได้รับการบำรุงรักษาบนพื้นฐานทางปรัชญาที่แตกต่างกันดังนั้นในแง่นั้นก็คือ 'เลวร้าย' ดังนั้นเราจึงต้องการให้ทันกับ upstream แต่ ในขณะเดียวกันก็รักษารหัสที่ดี 'แก้ไข' [git & msysgit มีบางส่วนของ 'ความขัดแย้ง' นี้เพราะปรัชญาของแพลตฟอร์มเป้าหมายที่แตกต่างกัน]
Philip Oakley

1
มันก็หายไปกรณีการใช้งานที่ฉันติดอยู่ตอนนี้ที่ฉันแบ่งปันสาขากับคนอื่นและเราทั้งคู่เกิดการผลักดันการเปลี่ยนแปลง (ในไฟล์ต่าง ๆ ) ในเวลาเดียวกัน ดังนั้นฉันจึงต้องการปิดบังเวอร์ชั่นเก่าทั้งหมดที่ฉันมีในพื้นที่และใช้เวอร์ชันใหม่กว่าของเขาแทน เขาต้องการทำแบบเดียวกันกับไฟล์ที่ฉันอัพเดต ไม่มีอะไรให้ 'รีเซ็ต' และวิธีการเช็คเอาต์แต่ละไฟล์นั้นไม่สามารถใช้งานได้จริงเมื่อมันถึง 20 ไฟล์
szeitlin

2
ฉันไม่เข้าใจปรัชญาจริงๆ ฉันเพิ่งใช้theirsเพราะฉันบังเอิญเปลี่ยนไฟล์บางไฟล์ในสองกิ่งแยกกันและต้องการยกเลิกการเปลี่ยนแปลงไฟล์หนึ่งโดยไม่ต้องทำด้วยตนเองทุกไฟล์
sudo

65

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

ลองผสานและใช้ B เพื่อหาข้อขัดแย้ง

นี่ไม่ใช่ "รุ่นของพวกเขาสำหรับgit merge -s ours" แต่ "รุ่นของพวกเขาสำหรับgit merge -X ours" (ซึ่งสั้นสำหรับgit merge -s recursive -X ours):

git checkout branchA
# also uses -s recursive implicitly
git merge -X theirs branchB

นี่คือคำตอบของอลันดับเบิลยู. สมิ ธทำ

ใช้เนื้อหาจาก B เท่านั้น

นี้จะสร้างการผสานการกระทำของทั้งสองสาขา แต่เหลือใช้จากการเปลี่ยนแปลงทั้งหมดbranchAและเพียง branchBแต่ช่วยให้เนื้อหาจาก

# Get the content you want to keep.
# If you want to keep branchB at the current commit, you can add --detached,
# else it will be advanced to the merge commit in the next step.
git checkout branchB

# Do the merge an keep current (our) content from branchB we just checked out.
git merge -s ours branchA

# Set branchA to current commit and check it out.
git checkout -B branchA

โปรดทราบว่าการผสานกระทำของพ่อแม่เป็นครั้งแรกในขณะนี้คือที่มาจากและมีเพียงสองคือจากbranchB branchAนี่คือตัวอย่างคำตอบของ Gandalf458ไม่

ใช้เนื้อหาจาก B เท่านั้นและรักษาลำดับหลักที่ถูกต้อง

นี่คือ "รุ่นสำหรับgit merge -s ours" ที่แท้จริง มันมีเนื้อหาเช่นเดียวกับในตัวเลือกก่อน (เช่นเดียวที่จากbranchB) แต่คำสั่งของพ่อแม่ผู้ปกครองที่ถูกต้องคือผู้ปกครองครั้งแรกที่มาจากและครั้งที่สองจากbranchAbranchB

git checkout branchA

# Do a merge commit. The content of this commit does not matter,
# so use a strategy that never fails.
# Note: This advances branchA.
git merge -s ours branchB

# Change working tree and index to desired content.
# --detach ensures branchB will not move when doing the reset in the next step.
git checkout --detach branchB

# Move HEAD to branchA without changing contents of working tree and index.
git reset --soft branchA

# 'attach' HEAD to branchA.
# This ensures branchA will move when doing 'commit --amend'.
git checkout branchA

# Change content of merge commit to current index (i.e. content of branchB).
git commit --amend -C HEAD

นี่คือสิ่งที่คำตอบของ Paul Pladijsทำ (โดยไม่จำเป็นต้องมีสาขาชั่วคราว)


รุ่นที่สะอาดกว่าของตัวเลือก 3:git checkout branchA; git merge -s ours --no-commit branchB; git read-tree -um @ branchB; git commit
jthill

@jthill: ในขณะที่รุ่นของคุณมีความกระชับมากกว่านั้นก็ยังใช้คำสั่งระดับต่ำ ("ประปา") read-treeว่าผู้ใช้ git เฉลี่ยอาจไม่ได้ใช้ (อย่างน้อยฉันไม่ได้ ;-)) การแก้ปัญหาในคำตอบนั้นใช้เฉพาะคำสั่งระดับสูง ("พอร์ซเลน") ที่ผู้ใช้คอมไพล์ส่วนใหญ่ควรรู้ ฉันชอบพวกเขา แต่ขอบคุณสำหรับเวอร์ชันของคุณ!
siegi

คุณสามารถอธิบายขั้นตอนที่สองถึงขั้นสุดท้าย (เช็คเอาต์ branchA) ได้หรือไม่ ดูเหมือนว่าไม่ควรอยู่ที่นั่น
แพทริค

@ แพทริกขั้นตอนนี้เป็นสิ่งจำเป็น หากคุณข้ามไปคุณจะได้รับการกระทำแบบเดียวกัน แต่คุณจะไม่มีสาขาที่ชี้ไปที่การกระทำนี้ ดังนั้นทันทีที่คุณเปลี่ยนไปใช้การคอมมิชชัน / แบรนช์การคอมมิทที่คุณทำด้วยคำสั่งสุดท้าย ( …commit --amend…) จะกลายเป็น "หลงทาง" ฉันวางแผนที่จะเพิ่มคำอธิบายกราฟิกให้กับคำตอบนี้ทันทีที่ฉันมีเวลาทำ… ;-)
siegi

62

ฉันใช้คำตอบจาก Paul Pladijs ตั้งแต่ตอนนี้ ฉันพบคุณสามารถทำการผสาน "ปกติ" เกิดข้อขัดแย้งขึ้นได้ดังนั้นคุณจึงทำได้

git checkout --theirs <file>

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

git merge <branch> -s theirs

อย่างไรก็ตามความพยายามนั้นยิ่งใหญ่กว่าการผสานกลยุทธ์! (สิ่งนี้ทดสอบกับ git เวอร์ชั่น 1.8.0)


1
จะดีถ้ารายการของไฟล์สามารถเรียกคืนได้ ตัวอย่างเช่นgit ls-files --modified | xargs git addฉันต้องการทำเช่นนี้เพื่อเพิ่มทั้งสองด้านผสาน: /
andho

จริง ๆ แล้วคอมไพล์คืนค่าที่เพิ่มลงในไฟล์ทั้งสองข้างด้วยgit ls-files --modifiedดังนั้นฉันเดาว่านี่เป็นวิธีแก้ปัญหาที่ทำงานได้
andho

1
ขอขอบคุณที่เพิ่มสิ่งนี้ด้วย บ่อยกว่านั้นไม่จำเป็นต้องใช้บนฐานแบบไฟล์ต่อไฟล์ นอกจากนี้สถานะ git ยังแสดง "Unmerged Paths" ที่ด้านล่างสุด ในการรับรายการเส้นทางที่ไม่ได้รับการแก้ไขฉันใช้นามแฝงนี้:git config --global alias.unresolved '!git status --short|egrep "^([DAU])\1"'
Melvyn

ความหมายของ-Xอะไรและอะไรคือความแตกต่างระหว่าง-Xและ-s? ไม่พบเอกสารใด ๆ
Lei Yang


13

เมื่อผสานหัวข้อหัวข้อ "B" ใน "A" โดยใช้ git merge ฉันได้รับความขัดแย้งบางอย่าง ฉันรู้ว่าความขัดแย้งทั้งหมดสามารถแก้ไขได้โดยใช้เวอร์ชันใน "B"

ฉันตระหนักถึงการคอมไพล์ผสานของเรา แต่สิ่งที่ฉันต้องการคือการรวมคอมไพล์> - ของพวกเขา

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

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

git checkout Branch
git merge master -s ours

จากนั้นชำระเงินหลักและรวมสาขาของคุณในนั้น (มันจะเป็นไปอย่างราบรื่นในขณะนี้):

git checkout master
git merge Branch

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

มันใช้งานได้ดีมากขอบคุณ
Kodie Grantham


8

เมื่อต้องการผสานอย่างถูกต้องซึ่งรับเฉพาะอินพุตจากสาขาที่คุณกำลังผสานคุณสามารถทำได้

git merge --strategy=ours ref-to-be-merged

git diff --binary ref-to-be-merged | git apply --reverse --index

git commit --amend

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

มันเล่นได้ไม่ดีนักกับ submodules


-R ทำอะไรที่นี่
P. Myer Nore

วิธีนี้ทำให้คุณสูญเสียประวัติของไฟล์ "ย้ายและเปลี่ยนแปลง" ฉันถูกไหม?
elysch

1
-R คือ - ย้อนกลับฉันได้อัพเดตคำตอบเพื่อให้สามารถจัดทำเอกสารด้วยตนเองได้มากขึ้น
Elijah Lynn

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

7

ทำไมมันไม่มีอยู่จริง?

ในขณะที่ฉันพูดถึงใน " คำสั่ง git สำหรับการทำให้สาขาเหมือนกัน " วิธีการจำลองgit merge -s theirsโปรดทราบว่า Git 2.15 (ไตรมาสที่ 4 ปี 2560) มีความชัดเจนมากขึ้น:

เอกสารสำหรับ ' -X<option>' สำหรับการรวมถูกเขียนเข้าใจผิดเพื่อแนะนำว่า " -s theirs" มีอยู่ซึ่งไม่ใช่ในกรณีนี้

ดูกระทำ c25d98b (25 กันยายน 2017) โดยJunio C Hamano (gitster )
(รวมโดยJunio C Hamano - gitster-ในการกระทำ 4da3e23 , 28 กันยายน 2017)

ผสานกลยุทธ์: หลีกเลี่ยงการบอกเป็นนัยว่า "-s theirs " อยู่

คำอธิบายของ-Xoursตัวเลือกการผสานมีหมายเหตุเกี่ยวกับบิดามารดาที่บอกผู้อ่านว่ามันแตกต่างจาก-s oursซึ่งถูกต้อง แต่คำอธิบายของ-Xtheirsสิ่งต่อไปนี้จะพูดอย่างไร้ความปราณีว่า "นี่เป็นสิ่งที่ตรงกันข้ามours" ทำให้ผู้อ่านรู้สึกผิด จะได้รับการเตือนว่ามันแตกต่างกันมาก-s theirsซึ่งในความเป็นจริงไม่ได้มีอยู่จริง

-Xtheirsเป็นตัวเลือกกลยุทธ์ที่ใช้กับกลยุทธ์แบบเรียกซ้ำ ซึ่งหมายความว่ากลยุทธ์แบบเรียกซ้ำจะยังคงผสานสิ่งที่ทำได้และจะย้อนกลับไปที่theirsตรรกะ "" ในกรณีที่เกิดข้อขัดแย้ง

อภิปรายความตรงหรือไม่ของที่theirsกลยุทธ์การผสานถูกนำกลับมาเมื่อเร็ว ๆ นี้ในเรื่องนี้กันยายน 2017 หัวข้อ
มันรับทราบหัวข้อเก่า (2008)

กล่าวโดยสรุปการสนทนาก่อนหน้านี้สามารถสรุปได้ว่า "เราไม่ต้องการ ' -s theirs' เพราะมันส่งเสริมขั้นตอนการทำงานที่ผิด"

มันกล่าวถึงนามแฝง:

mtheirs = !sh -c 'git merge -s ours --no-commit $1 && git read-tree -m -u $1' -

Yaroslav Halchenko พยายามสนับสนุนอีกครั้งสำหรับกลยุทธ์นั้นแต่ Junio ​​C. Hamano กล่าวเสริมว่า :

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

เมื่อคุณตัดสินใจว่าประวัติของพวกเขาคือการฉีดยาคุณต้องการที่จะปฏิบัติต่อสายการพัฒนาของคุณในฐานะสาขาย่อยและทำการผสานในทิศทางนั้นนั่นคือผู้ปกครองคนแรกของการรวมที่เกิดขึ้นนั้นกระทำในประวัติของพวกเขาและครั้งที่สอง parent เป็นประวัติเลวร้ายสุดท้ายของคุณ ดังนั้นคุณจะต้องใช้ " checkout their-history && merge -s ours your-history" เพื่อรักษาความเป็นพ่อแม่คนแรกเอาไว้

และ ณ จุดนั้นการใช้ " -s ours" ไม่ใช่วิธีแก้ปัญหาอีกต่อไปสำหรับการขาด " -s theirs"
มันเป็นส่วนหนึ่งที่เหมาะสมของความหมายที่ต้องการเช่นจากมุมมองของผู้รอดชีวิตสายประวัติศาสตร์ที่ยอมรับ, คุณต้องการที่จะรักษาสิ่งที่มันไม่เป็นโมฆะว่าสายอื่น ๆ ของประวัติศาสตร์ได้

Junio ​​เสริมความเห็นโดยMike Beaton :

git merge -s ours <their-ref>ได้อย่างมีประสิทธิภาพกล่าวว่า 'การทำเครื่องหมายที่ทำขึ้น<their-ref>ในสาขาของพวกเขาเป็นความมุ่งมั่นที่จะละเว้นอย่างถาวร'; และเรื่องนี้เพราะถ้าคุณต่อมาผสานจากรัฐในภายหลังสาขาของพวกเขาเปลี่ยนแปลงในภายหลังของพวกเขาจะถูกนำเข้ามาโดยไม่มีการเปลี่ยนแปลงละเว้นเคยถูกนำเข้ามาใน


1
นี่เป็นคำตอบที่มีประโยชน์ แต่ก็ไม่ได้พูดถึงประเด็นสำคัญเพียงจุดเดียวที่ฉันเพิ่งเข้าใจจากคำตอบของ Junio ​​C. Hamano: git merge -s ours <their-ref>บอกว่า 'เครื่องหมายที่ทำขึ้นเพื่อ <their-ref> ในคอมมิชชันของพวกเขา '; และเรื่องนี้เพราะถ้าคุณรวมจากรัฐในภายหลังของสาขาของพวกเขาการเปลี่ยนแปลงในภายหลังของพวกเขาจะถูกนำเข้ามาโดยไม่มีการเปลี่ยนแปลงที่ไม่เคยถูกนำเข้ามา
MikeBeaton

1
@ MikeBeaton ขอบคุณ ฉันได้รวมความคิดเห็นของคุณไว้ในคำตอบเพื่อให้มองเห็นได้ชัดเจนขึ้น
VonC

5

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

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

(แก้ไข: ว้าวฉันจัดการผิดก่อนหน้านี้ได้ไหม)

git update-ref HEAD $(
        git commit-tree -m 'completely superseding with branchB content' \
                        -p HEAD -p branchB    branchB:
)
git reset --hard

3

อันนี้ใช้คำสั่ง git plumbing read-tree แต่ทำให้เวิร์กโฟลว์โดยรวมสั้นลง

git checkout <base-branch>

git merge --no-commit -s ours <their-branch>
git read-tree -u --reset <their-branch>
git commit

# Check your work!
git diff <their-branch>

0

สิ่งนี้จะรวม newBranch ของคุณใน baseBranch ที่มีอยู่

git checkout <baseBranch> // this will checkout baseBranch
git merge -s ours <newBranch> // this will simple merge newBranch in baseBranch
git rm -rf . // this will remove all non references files from baseBranch (deleted in newBranch)
git checkout newBranch -- . //this will replace all conflicted files in baseBranch

ฉันขอแนะนำให้เพิ่มgit commit --amendในตอนท้ายของตัวอย่างของคุณหรือผู้ใช้อาจเห็นการรวมการกระทำด้วยgit logและถือว่าการดำเนินการเสร็จสมบูรณ์
Michael R

0

ฉันคิดว่าสิ่งที่คุณต้องการคือ:

git checkout -B mergeBranch branchB
git merge -s ours branchA
git checkout branchA
git merge mergeBranch
git branch -D mergeBranch

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


0

เทียบเท่า (ซึ่งเก็บคำสั่งพาเรนต์) เป็น 'git merge -s branchb'

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

!!! ตรวจสอบให้แน่ใจว่าคุณอยู่ในสภาพที่สะอาด !!!

ทำการผสาน:

git commit-tree -m "take theirs" -p HEAD -p branchB 'branchB^{tree}'
git reset --hard 36daf519952 # is the output of the prev command

เราทำอะไร เราได้สร้างความมุ่งมั่นใหม่ที่พ่อแม่สองคนของเราและพวกเขาและ contnet ของการกระทำคือ branchB - พวกเขา

หลังจากรวม:ป้อนคำอธิบายรูปภาพที่นี่

อย่างแม่นยำมากขึ้น:

git commit-tree -m "take theirs" -p HEAD -p 'SOURCE^{commit}' 'SOURCE^{tree}'

0

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

แก้ไข. gitconfig ของคุณและเพิ่มรายการต่อไปนี้:

[alias]
    mergetheirs = "!git merge -s ours \"$1\" && git branch temp_THEIRS && git reset --hard \"$1\" && git reset --soft temp_THEIRS && git commit --amend && git branch -D temp_THEIRS"

จากนั้นคุณสามารถ "คอมไพล์ผสาน - ของพวกเขา A" โดยการเรียกใช้:

git checkout B (optional, just making sure we're on branch B)
git mergetheirs A

-1

ฉันเพิ่งต้องการทำสิ่งนี้สำหรับที่เก็บสองแห่งที่แบ่งเป็นประวัติทั่วไป ฉันเริ่มต้นด้วย:

  • Org/repository1 master
  • Org/repository2 master

ฉันต้องการให้การเปลี่ยนแปลงทั้งหมดrepository2 masterถูกนำไปใช้repository1 masterโดยยอมรับการเปลี่ยนแปลงทั้งหมดที่ที่เก็บ 2 จะทำ ในแง่ของ git นี่ควรเป็นกลยุทธ์ที่เรียกว่า-s theirsแต่มันไม่มีอยู่จริง ระวังเพราะ-X theirsตั้งชื่อเหมือนว่ามันจะเป็นสิ่งที่คุณต้องการ แต่มันก็ไม่เหมือนกัน

วิธีที่ผมแก้ปัญหานี้คือการไปและทำให้สาขาใหม่repository2 repo1-mergeในสาขานั้นฉันวิ่งgit pull git@gitlab.com:Org/repository1 -s oursและผสานเข้ากันได้ดีโดยไม่มีปัญหา จากนั้นฉันก็ผลักไปที่รีโมท

แล้วฉันจะกลับไปและทำให้สาขาใหม่repository1 repo2-mergeในสาขานั้นฉันทำงานgit pull git@gitlab.com:Org/repository2 repo1-mergeซึ่งจะเสร็จสมบูรณ์เมื่อมีปัญหา

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


-2

วิธีที่ง่ายและใช้งานง่าย (ในความคิดของฉัน) วิธีการสองขั้นตอนในการทำคือ

git checkout branchB .
git commit -m "Picked up the content from branchB"

ติดตามโดย

git merge -s ours branchB

(ซึ่งทำเครื่องหมายทั้งสองสาขาว่าถูกผสาน)

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

วิธีการนี้ทำให้ชัดเจนจากบันทึกการแก้ไขหลังจากนั้นสิ่งที่ทำ - และสิ่งที่ตั้งใจไว้


สิ่งนี้อาจถูกต้องสำหรับคำถามต้นฉบับอย่างไรก็ตาม OP ได้อัปเดตคำถามในปี 2008 ในลักษณะที่คำตอบนี้ไม่ถูกต้อง
user3338098

1
@ user3338098 ใช่สงสารเช่นที่พวกเขาได้ใส่ชื่อที่ทำให้เข้าใจผิดและเพียงแค่ตบการปรับปรุงเพื่อให้ไม่สามารถมองเห็นในตอนท้ายของร่างกายคำถาม .... เพราะคำตอบนี้ไม่คำตอบที่ถูกต้องคำถามชื่อ
RomainValeri

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