ฉันจะ 'เขียนทับ' แทนที่จะเป็น 'ผสาน' สาขาในสาขาอื่นใน Git ได้อย่างไร


257

ฉันมีสองสาขาemailและstaging. stagingเป็นรุ่นล่าสุดและฉันไม่ต้องการการเปลี่ยนแปลงเก่าในemailสาขาอีกต่อไปแต่ฉันไม่ต้องการลบ

ดังนั้นฉันต้องการทิ้งเนื้อหาทั้งหมดของstagingลงในemailเพื่อให้พวกเขาทั้งสองชี้ไปที่กระทำเดียวกัน เป็นไปได้ไหม


คำตอบ:


196

คุณสามารถใช้กลยุทธ์การผสาน 'ของเรา':

$ git checkout staging
$ git merge -s ours email # Merge branches, but use our branch head

26
ฉันลองมันแล้วมันจะย้อนกลับไปหาฉัน สิ่งนี้ไม่ได้ถ่ายโอนเนื้อหาของอีเมลไปยังการจัดเตรียมไม่ใช่วิธีอื่นใช่หรือไม่
สูงสุด

27
@ Max ฉันมีความสับสนเหมือนกันและมันทำให้ฉันมีปัญหามาก คุณต้องทำคำสั่งนี้จากสาขาที่ใหม่กว่า (การจัดเตรียม) จากนั้นทำการผสานปกติ / PR ไปยังสาขาเดิมของคุณ (อีเมล)
MrGlass

7
ทำไม;ตอนท้ายของแต่ละคำสั่ง? ฉันไม่ได้ทำ;และดูเหมือนว่าจะทำงานได้ ด้วยคำตอบนี้ไม่สมบูรณ์ขั้นตอนที่สามคือเช็คเอาต์สาขาเก่า (อีเมล) แล้วรวมกับการจัดเตรียมอีกครั้ง
Rosdi Kasim

4
git rebase -s theirs <oldbranc> <newbranch> ทำงานได้ดี (ไม่ว่าคุณจะสาขาไหน) โปรดทราบว่าในการ rebase 'พวกเขา' เป็นจริงสาขาใหม่เพราะ 'ของเรา' เป็นหัวหน้าเรากำลังใช้ความมุ่งมั่นในการ
Rolf

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

99

หากคุณต้องการให้ 'อีเมล' ทั้งสองสาขาและ 'จัดเตรียม' เป็นสาขาเดียวกันคุณสามารถติดแท็กสาขา 'อีเมล' จากนั้นรีเซ็ตสาขา 'อีเมล' เป็น 'จัดเตรียม' หนึ่งรายการ:

$ git checkout email
$ git tag old-email-branch
$ git reset --hard staging

นอกจากนี้คุณยังสามารถรีบูตสาขา 'การจัดเตรียม' ในสาขา 'อีเมล' แต่ผลลัพธ์จะมีการแก้ไขทั้งสองสาขา


1
คุณอาจหมายถึงgit checkout, git checkไม่ได้อยู่เพื่อความรู้ของฉัน
knittl

4
คุณพูดถูกฉันใช้แท็บเสร็จสิ้นคำสั่ง git ที่ฉันเขียน "git check <TAB>" เพื่อเขียน "git checkout" เสมอ! การแก้ไข
Sylvain Defresne

17
git reset ทำลาย repo ของคนอื่น ๆ ที่ลอก repo ของคุณ
Geoffrey De Smet

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

76

ฉันเห็นคำตอบหลายข้อและเป็นขั้นตอนเดียวที่ให้ฉันแก้ไขได้โดยไม่มีข้อขัดแย้งใด ๆ

หากคุณต้องการการเปลี่ยนแปลงทั้งหมดจาก branch_new ใน branch_old ดังนั้น:

git checkout branch_new
git merge -s ours branch_old
git checkout branch_old
git merge branch_new

เมื่อใช้คำสั่งทั้งสี่แล้วคุณสามารถกด branch_old ได้โดยไม่มีปัญหาใด ๆ


5
คำตอบของคุณเหมาะสมกับปัญหาของฉันดีที่สุดเพราะฉันไม่ต้องการรีเซ็ต HEAD เพียงระบุการตั้งค่าสำหรับไฟล์ที่ใหม่กว่าในสาขาที่ใหม่กว่าเมื่อรวมสิ่งต่างๆเข้ากับไฟล์เก่ากว่าและทำงานได้โดยไม่มีปัญหา! +1
เตา

ฉันผลัก branch_new ไปที่รีโมตหลังจาก "การรวมของเรา" และวิธีนี้ใช้ได้สำหรับฉัน ฉันจำเป็นต้องผลักดันหรือไม่ หรือมันจะทำงานได้โดยไม่ต้อง? (ไม่แน่ใจว่ามันจะใช้สาขาท้องถิ่นหรือระยะไกล) ขอบคุณ!
aspergillusOryzae

ทำไมคุณไม่ทำตามด้านล่าง? git checkout branch_old git merge -s พวกเขา branch_new เบาะแสนำมาจากstackoverflow.com/questions/14275856//
Ripu Daman

มันบอกว่าไม่พบกลยุทธ์การผสาน 'ของพวกเขา'
arango_86

ทำงานได้อย่างสมบูรณ์แบบสำหรับฉันมีข้อได้เปรียบที่จะไม่รีเซ็ตสิ่งใดเลย
Romain

68

คำตอบอื่นให้ฉันเบาะแสที่ถูกต้อง แต่พวกเขาไม่ได้ช่วยอย่างสมบูรณ์

นี่คือสิ่งที่ทำงานสำหรับฉัน:

$ git checkout email
$ git tag old-email-branch # This is optional
$ git reset --hard staging
$
$ # Using a custom commit message for the merge below
$ git merge -m 'Merge -s our where _ours_ is the branch staging' -s ours origin/email
$ git push origin email

หากไม่มีขั้นตอนที่สี่ของการรวมเข้ากับกลยุทธ์ของเราการผลักดันจะถือว่าเป็นการอัปเดตที่ไม่ส่งต่ออย่างรวดเร็วและจะถูกปฏิเสธ (โดย GitHub)


นั่นทำให้การรวมข้อความกระทำผิด แต่ใช่มันใช้งานได้ดี
cdunn2001

cdunn2001 ฉันอยากรู้ อะไรคือข้อความรวมที่คุณคาดไว้และสิ่งที่ทำให้เกิดความสับสนกับเรื่องนี้?
Shyam Habarakada

มีข้อความระบุว่า "รวมที่สาขาการติดตามระยะไกล 'ต้นทาง / อีเมล' เข้ากับอีเมล" มันไม่ได้พูดถึงการจัดเตรียม ไม่มีเรื่องใหญ่อะไร merge -m 'This is not my beautiful house.' -s ours origin/emailเพียงแค่แก้ไขการกระทำหรือการใช้งาน
cdunn2001

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

ขั้นตอนที่ 4 กำหนดให้คุณใช้ที่มา / อีเมล แต่ใช้ไม่ได้กับอีเมลท้องถิ่น
Travis Reeder

45

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

git checkout email
git reset --hard staging
git push origin email --force

หมายเหตุ: นี่คือเมื่อคุณจริงๆไม่ต้องการเห็นเนื้อหาในอีเมลอีกครั้ง


1
git push อีเมลต้นทาง - บังคับใช้ไม่ได้สำหรับฉันเนื่องจาก Step2 ออกจากสาขาแยก ดังนั้นหลังจากขั้นตอนที่ 2 นี่คือสิ่งที่ฉันทำ: git รีเซ็ตต้นกำเนิด / อีเมลแล้วกด git
user3505394

2
นี่คือสิ่งที่ถูกถามในคำถาม - "วิธีการเขียนทับแทนที่จะรวม" ควรเป็นคำตอบที่ได้รับการยอมรับ
jozols

17

ฉันต้องการรวมสองสาขาเพื่อให้เนื้อหาทั้งหมดold_branchได้รับการอัปเดตด้วยเนื้อหาจากnew_branch

สำหรับฉันมันใช้งานได้เหมือนมีเสน่ห์:

$ git checkout new_branch
$ git merge -m 'merge message' -s ours origin/old_branch
$ git checkout old_branch
$ git merge new_branch
$ git push origin old_branch

10

เกี่ยวกับ:

git branch -D email
git checkout staging
git checkout -b email
git push origin email --force-with-lease

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

@DavidCosta เหตุใดเซิร์ฟเวอร์จึงถูกปฏิเสธ นี่เป็นสาขาอีเมลลบแบบง่าย & คัดลอกการจัดเตรียมไปยังอีเมล '... ดังนั้นฉันแค่ต้องการทิ้งเนื้อหาทั้งหมดของ' การจัดเตรียม 'ลงใน' อีเมล 'เพื่อให้พวกเขาทั้งสองชี้ไปที่การกระทำเดียวกัน - นั่นคือสิ่งที่เกิดขึ้น ที่นี่
Arek S

@ArekS สามารถขอได้จากฝั่งเซิร์ฟเวอร์หากสาขาถูกตั้งค่าเป็น "ป้องกัน" เช่นใน GitLab ปัญหาคือถ้าคนอื่นได้รับสาขาของเขาจากอีเมลก่อนการดำเนินการนี้และจากนั้นพยายามที่จะผลักดันการอ้างอิงไม่ตรงกันอีกต่อไป (เพราะบางคนมุ่งมั่นที่หายไปเพียง)
เดวิดคอสตา

1
ฉันแก้ไขต้นฉบับจาก --force to --force-with-lease ซึ่งทำเคล็ดลับในลักษณะที่ไม่ทำลายล้าง
frandroid

1
นี่เป็นวิธีที่ดีที่สุดถ้าคุณต้องการที่จะระเบิดสาขาและเริ่มทำความสะอาดจากสาขาที่มา
เชน

6

คำตอบอื่น ๆ ดูไม่สมบูรณ์
ฉันลองด้านล่างเต็มแล้วและใช้งานได้ดี

หมายเหตุ:
1. ทำสำเนาที่เก็บของคุณก่อนที่คุณจะลองด้านล่างเพื่อให้ปลอดภัย

รายละเอียด:
1. การพัฒนาทั้งหมดเกิดขึ้นในสาขา dev
2. สาขาqa เป็นเพียงสำเนาเดียวกันของ dev
3. เวลารหัส dev จำเป็นต้องย้าย / เขียนทับไปยังสาขา qa

ดังนั้นเราต้องเขียนทับ qa branch จาก dev dev

ตอนที่ 1:
ด้วยคำสั่งด้านล่าง qa เก่าได้รับการอัพเดตเป็น dev ใหม่กว่า:

git checkout dev
git merge -s ours qa
git checkout qa
git merge dev
git push

ความคิดเห็นอัตโนมัติสำหรับการกดครั้งสุดท้ายให้ด้านล่าง:

// Output:
//  *<MYNAME> Merge branch 'qa' into dev,*  

ความคิดเห็นนี้ดูย้อนกลับเพราะลำดับข้างต้นก็ดูย้อนกลับ

ส่วนที่ 2:

ด้านล่างเป็นสิ่งที่คาดไม่ถึงการที่คนท้องถิ่นมุ่งมั่นในการพัฒนาสิ่งที่ไม่จำเป็น
ดังนั้นเราต้องทิ้งและทำให้ผู้พัฒนาไม่มีใครแตะต้อง

git checkout dev

// Output:
//  Switched to branch 'dev'  
//  Your branch is ahead of 'origin/dev' by 15 commits.  
//  (use "git push" to publish your local commits)


git reset --hard origin/dev  

//  Now we threw away the unexpected commits

ตอนที่ 3:
ตรวจสอบทุกอย่างตามที่คาดไว้:

git status  

// Output:
//  *On branch dev  
//  Your branch is up-to-date with 'origin/dev'.  
//  nothing to commit, working tree clean*  

นั่นคือทั้งหมดที่
1. qa เก่าถูกเขียนทับโดยรหัสสาขา dev ใหม่
2. local is clean (แหล่งกำเนิดระยะไกล / dev ไม่มีการแตะต้อง)


6

วิธีที่ง่ายที่สุดที่จะทำ:

//the branch you want to overwrite
git checkout email 

//reset to the new branch
git reset --hard origin/staging

// push to remote
git push -f

ตอนนี้สาขาอีเมลและการจัดเตรียมเหมือนกัน


2
คำเตือน: สิ่งนี้จะลบการผูกมัดทั้งหมดในemailสาขา มันเหมือนกับการลบemailสาขาและสร้างใหม่ที่หัวstagingสาขา
Cameron Hudson

2
git checkout email
git merge -m "Making email same as staging disregarding any conflicts from email in the process" -s recursive -X theirs staging

1
คำตอบนี้จะชัดเจนกว่าสำหรับฉันถ้าความคิดเห็นถูกแยกออกจากความคิดเห็นที่ถูกรวมในคำสั่ง อธิบายสั้น ๆ ว่า -X ทำอะไรและมีผลต่อการรวมนี้อย่างไร ขอบคุณ ทำให้ฉันดูมันขึ้น :)
noelicus

@ noelicus ขอบคุณสำหรับความคิดเห็นและคุณพูดถูก ฉันอาจแก้ไขคำตอบในอนาคต
Willa

0

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

git checkout new -b tmp
git merge -s ours old -m 'irrelevant'
git checkout old
git merge --squash tmp
git branch -D tmp
#do any other stuff you want
git add -A; git commit -m 'foo' #commit (or however you like)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.