Git push ถูกปฏิเสธหลังจากการรีบูทของฟีเจอร์


918

ตกลงฉันคิดว่านี่เป็นสถานการณ์คอมไพล์อย่างง่ายฉันจะพลาดอะไรไป

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

A--B--C------F--G  (master)
       \    
        D--E  (feature)

ฉันไม่มีปัญหาในgit push origin masterการmasterอัปเดตรีโมตและไม่มีgit push origin feature(เมื่อเปิดfeature) เพื่อรักษาการสำรองข้อมูลระยะไกลสำหรับfeatureงานของฉัน จนถึงตอนนี้เราก็ยังดี

แต่ตอนนี้ผมอยากจะ rebase featureที่ด้านบนของF--Gกระทำบนต้นแบบดังนั้นฉันและgit checkout feature git rebase masterยังคงดีอยู่. ตอนนี้เรามี:

A--B--C------F--G  (master)
                 \
                  D'--E'  (feature)

ปัญหา:ทันทีที่ฉันต้องการสำรองfeatureกิ่งที่ถูกรีบาวด์ใหม่git push origin feature, การกดจะถูกปฏิเสธเนื่องจากต้นไม้มีการเปลี่ยนแปลงเนื่องจากการรีบูท git push --force origin featureนี้สามารถแก้ไขได้เฉพาะกับ

ฉันเกลียดการใช้--forceโดยไม่แน่ใจว่าฉันต้องการมัน ดังนั้นฉันต้องการมันหรือไม่? การรีบูตจำเป็นต้องบอกเป็นนัยว่าสิ่งต่อไปpushควรเป็นจริง--forceหรือไม่?

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

คำตอบ:


681

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

Z--X--R         <- origin/some-branch (can be fast-forwarded to Y commit)
       \        
        T--Y    <- some-branch

เมื่อคุณทำคอมมิชชันgit rebaseD และ E จะใช้กับฐานใหม่และคอมมิชชันใหม่จะถูกสร้างขึ้น นั่นหมายความว่าหลังจากการรีบูทคุณมีสิ่งที่ต้องการ:

A--B--C------F--G--D'--E'   <- feature-branch
       \  
        D--E                <- origin/feature-branch

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

และสิ่งที่--forceตัวเลือกทำก็เพียงแค่เพิกเฉยต่อสถานะของสาขาระยะไกลและตั้งค่าเป็นความมุ่งมั่นที่คุณกำลังผลักดันเข้าไป ดังนั้นgit push --force origin feature-branchเพียงแค่แทนที่ท้องถิ่นorigin/feature-branchfeature-branch

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


67
ความจริงแล้วการดึงและการรวมสาขาดั้งเดิมของฟีเจอร์ลงในที่ถูกรีบูตแล้วจะช่วยลดความคิดทั้งหมดของการรีบูต
KL-7

24
บางทีฉันอาจจะไม่เข้าใจคุณอย่างถูกต้อง แต่ถ้าคุณดึงฟีเจอร์แบรนช์มันลงบนกิ่งใหม่คุณไม่สามารถผลักมันกลับมาโดยไม่บังคับเพราะเวอร์ชั่นรีโมตของฟีเจอร์แบรนช์ไม่สามารถส่งต่อไปยังที่ใหม่ได้อย่างรวดเร็ว (ปฏิเสธใหม่) เวอร์ชันสาขาคุณลักษณะ นั่นคือสิ่งที่ OP อธิบายไว้ในคำถามของเขา หากหลังจากรีบูต แต่ก่อนที่จะผลักดันคุณทำเช่นgit pull feature-branchนี้การดึงนี้จะสร้างการผสานใหม่ (โดยการรวมสาขาฟีเจอร์รีโมตและเวอร์ชันโลคัล) ดังนั้นทั้งคุณจะได้รับการผสานไม่จำเป็นหลังจาก rebasing --forceหรือคุณผลักดันด้วย
KL-7

6
อ่าฉันคิดว่าฉันเข้าใจแล้ว คุณกำลังอธิบายวิธีการเช่นเดียวกับในคำตอบของ Mark Longair แต่มันจะสร้างความผูกพันผสาน มันอาจจะมีประโยชน์ในบางกรณี แต่ฉันใช้ rebase ส่วนใหญ่ในสาขาคุณลักษณะของฉันเอง (จึงpush --forceไม่ใช่ปัญหา) เพื่อเก็บประวัติการกระทำเชิงเส้นโดยไม่รวมการกระทำใด ๆ เลย
KL-7

11
ปัญหาของ“ แรงผลักดัน” คือคุณสามารถ“ หลวมสิ่ง” (แน่นอนก่อนหน้านี้) สิ่งที่ตามปกติไม่ควรเป็นไปได้ในระบบควบคุมเวอร์ชันใด ๆ ➪ด้วยเหตุผลนั้นอย่างน้อยสาขาหนึ่งควรมี การตั้งค่าที่ไม่ยอมรับแรงกดเพื่อจำกัดความเสียหายที่อาจเกิดขึ้น (ตั้งชื่ออย่างใดอย่างหนึ่งต่อไปนี้: พนักงานไม่พอใจ / ถูกไล่ออก, เป็นคนโง่, เหนื่อย & ทำงานหนักเกินไป 'การตัดสินใจ' ... )
Frank Nocke

13
--force-with-leaseเป็น @hardev แนะนำคือตัวเลือกที่ดี
augustorsouza

465

แทนที่จะใช้ -f หรือ --force นักพัฒนาควรใช้

--force-with-lease

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


33
คำอธิบายที่ดี git push --force-with-leaseช่วยฉันมัดไว้
ckib16

5
นี่เป็นความคิดเห็นที่มีประโยชน์ แต่ไม่ใช่คำตอบสำหรับคำถาม
Dallin

4
นี่คือคำตอบการรีบูตไปที่ต้นแบบ / พัฒนาสร้างปัญหานี่คือเหตุผลที่ว่า --force-with-lease มีอยู่จริง
Tamir Daniely

3
นี่ควรเป็นคำตอบที่ยอมรับได้ แก้ไขปัญหาที่อธิบายไว้อย่างชัดเจน - บังคับให้กดโดยไม่ต้องบังคับถ้ามีคนอื่นทำในขณะเดียวกัน
Luzian

3
ฉันคิดว่าทั้งคำตอบที่ได้รับการยอมรับและอันนี้ตอบคำถาม คำตอบที่ยอมรับได้อธิบายว่าทำไมคุณต้องบังคับ และสิ่งนี้อธิบายว่าทำไมถึง--force-with-leaseจัดการกับความกังวลในการใช้งาน--force
Jeff Appareti

47

ฉันจะใช้แทน "checkout -b" และง่ายต่อการเข้าใจ

git checkout myFeature
git rebase master
git push origin --delete myFeature
git push origin myFeature

เมื่อคุณลบคุณจะป้องกันไม่ให้ดันออกจากสาขาที่มีรหัส SHA อื่น ฉันกำลังลบเฉพาะสาขาระยะไกลในกรณีนี้


6
วิธีนี้ใช้งานได้ดีโดยเฉพาะหากทีมของคุณมีตะขอคอมไพล์ซึ่งปฏิเสธคำสั่ง git push -force ทั้งหมด
Ryan Thames

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

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

19

ทางออกหนึ่งในการนี้คือการทำในสิ่งที่ msysgit ของการผสาน rebasingสคริปต์ไม่ - หลังจาก rebase ที่ผสานในหัวเก่าด้วยfeature -s oursคุณจบลงด้วยกราฟการกระทำ:

A--B--C------F--G (master)
       \         \
        \         D'--E' (feature)
         \           /
          \       --
           \    /
            D--E (old-feature)

... และความfeatureมุ่งมั่นของคุณจะเป็นไปอย่างรวดเร็ว

กล่าวอีกนัยหนึ่งคุณสามารถทำได้:

git checkout feature
git branch old-feature
git rebase master
git merge -s ours old-feature
git push origin feature

(ไม่ได้ทดสอบ แต่ฉันคิดว่ามันถูกต้อง ... )


26
ฉันเชื่อว่าสาเหตุที่พบบ่อยที่สุดสำหรับการใช้งานgit rebase(แทนที่จะรวมmasterกลับเข้าไปในสาขาคุณลักษณะของคุณ) คือการสร้างประวัติที่มุ่งมั่นเชิงเส้นที่สะอาด ด้วยวิธีการของคุณก่อให้เกิดประวัติศาสตร์ยิ่งเลวร้ายลง และเมื่อการรีบูตสร้างคอมมิทใหม่โดยไม่อ้างอิงถึงเวอร์ชันก่อนหน้าของพวกเขาฉันไม่แน่ใจด้วยซ้ำว่าผลลัพธ์ของการผสานนี้จะเพียงพอ
KL-7

6
@ KL-7: จุดทั้งหมดของmerge -s oursมันคือการเพิ่มการอ้างอิงผู้ปกครองไปยังรุ่นก่อนหน้านี้ แน่นอนว่าประวัติศาสตร์ดูไม่สะอาด แต่ผู้ถามดูเหมือนจะใส่ใจเป็นพิเศษโดยต้องบังคับให้ต้องผลักดันfeatureกิ่งไม้ หากคุณต้องการที่จะรีบูตมันเป็นมากกว่าหนึ่งหรือน้อยกว่า :) โดยทั่วไปผมคิดว่ามันน่าสนใจว่าโครงการ msysgit ไม่นี้ ....
มาร์ค Longair

@ KL-7: โดยบังเอิญฉันได้ +1 คำตอบของคุณซึ่งเป็นคำตอบที่ถูกต้องชัดเจน - ฉันแค่คิดว่ามันน่าสนใจเช่นกัน
Mark Longair

มันเป็นเรื่องที่น่าสนใจอย่างน้อยสำหรับฉัน ขอบคุณ. ฉันเคยเห็นoursกลยุทธ์มาก่อน แต่ฉันคิดว่ามันใช้ได้กับสถานการณ์ความขัดแย้งเท่านั้นโดยการแก้ไขโดยอัตโนมัติโดยใช้การเปลี่ยนแปลงในสาขาของเรา มันกลับกลายเป็นว่าทำงานแตกต่างกัน และการทำงานในลักษณะนั้นมันมีประโยชน์มากถ้าคุณต้องการเวอร์ชั่นที่ถูกรีบูท (เช่นสำหรับ repo ผู้ดูแลเพื่อนำไปใช้อย่างหมดจดmaster) แต่ต้องการหลีกเลี่ยงการใช้แรงผลักดัน (ถ้ามี ppl อื่น ๆ มากมายด้วยเหตุผลบางอย่าง
KL-7

15

มันอาจจะใช่หรือไม่ใช่ในกรณีที่มีนักพัฒนาเพียงคนเดียวในสาขานี้นั่นคือตอนนี้ (หลังจากการ rebase) ไม่สอดคล้องกับที่มา / คุณสมบัติ

ดังนั้นฉันขอแนะนำให้ใช้ลำดับต่อไปนี้:

git rebase master
git checkout -b feature_branch_2
git push origin feature_branch_2

ใช่สาขาใหม่นี้ควรแก้ปัญหานี้โดยไม่ต้อง - แรงซึ่งฉันคิดว่าโดยทั่วไปแล้วเป็นข้อเสียเปรียบหลัก ๆ


3
ขออภัยที่จะพูด แต่:„ สร้างสาขา "เพื่อหลีกเลี่ยงการบังคับใช้มากกว่าเดิมที่มีอยู่ไม่ได้ช่วยให้นักพัฒนาคุณลักษณะโดดเดี่ยว" (ที่สามารถแทนที่) หรือหลายคนทำงานในสาขาฟีเจอร์ (ต้องการสื่อสารสาขานั้น "เพิ่ม" และบอก เพื่อย้ายไปคน) - มันเหมือนกับการกำหนดเวอร์ชันด้วยตนเอง (“ thesis_00.doc, thesis_01.doc, ... ”), ภายในระบบการกำหนดเวอร์ชัน ...
Frank Nocke

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

1
@ แฟรงกี้ครึ่งจริงจากประสบการณ์ของฉัน สำหรับนักพัฒนาที่อ้างว้างใช่เพียงแค่แรงผลักดันนั้นง่ายพอ แต่เป็นนิสัยที่อาจกัดคุณในภายหลัง + มี dev ใหม่เข้าร่วมหรือไม่ หรืออาจเป็นระบบ CI บางอย่างที่ไม่ได้ใช้ - ฮาร์ดรีเซ็ต? สำหรับทีมที่ทำงานร่วมกันฉันคิดว่าการสื่อสารชื่อสาขาใหม่นั้นง่ายพอนี่สามารถเขียนสคริปต์ได้อย่างง่ายดายเช่นกัน + สำหรับทีมฉันขอแนะนำให้ลดระดับในพื้นที่หรือเมื่อสาขาพร้อมสำหรับการผสานไม่ใช่ในระหว่างวันต่อวัน การคอมมิทพิเศษมีปัญหาน้อยกว่าการจัดการกับความขัดแย้ง rebase / merge
JAR.JAR.beans

@Grasant สำหรับ PR อีกครั้งฉันคิดว่านี่เป็นสิ่งที่ผิดในการรีบูทฉันต้องการเห็นการแก้ไข PR rebase (สควอช) ควรเกิดขึ้นในภายหลังโดยเป็นส่วนหนึ่งของการผสานเป็นหลักและเมื่อ PR เสร็จสิ้นแล้วและพร้อม (ไม่จำเป็นต้องเปิด PR ใหม่)
JAR.JAR.beans

13

วิธีหลีกเลี่ยงการใช้แรงผลักดันของฉันคือการสร้างสาขาใหม่และทำงานอย่างต่อเนื่องในสาขาใหม่นั้นและหลังจากที่มีความมั่นคงแล้วให้ลบสาขาเก่าที่ถูกปฏิเสธ:

  • รีสาขาที่เช็คเอาต์ในเครื่อง
  • การแตกแขนงจากกิ่งที่ถูกปฏิเสธไปยังสาขาใหม่
  • ผลักสาขานั้นเป็นสาขาใหม่ไปยังระยะไกล และลบสาขาเก่าบนรีโมท

1
ทำไมไม่รักตัวเลือกนี้ แน่นอนว่าเป็นสิ่งที่สะอาดเรียบง่ายที่สุดปลอดภัยที่สุด
cdmo

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

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

2
@Nabi นั่นคือสิ่งที่ --force-with-lease ทำยกเว้นว่ามันยังตรวจสอบว่าไม่มีการยอมรับใหม่ที่ไม่ใช่ของคุณ
Tamir Daniely

12

อื่น ๆ ได้ตอบคำถามของคุณ หากคุณรีบูทสาขาคุณจะต้องบังคับให้ดันสาขานั้น

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

โดยทั่วไป rebase จะทำงานได้ดีสำหรับการจัดการสาขาในท้องถิ่น การจัดการสาขาระยะไกลทำงานได้ดีที่สุดกับการรวมที่ชัดเจน (--no-ff)

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


5
คุณช่วยเพิ่มตัวอย่างได้ไหม
Thermech

8

ผิดปกติกับคืออะไรgit merge masterในfeatureสาขา? สิ่งนี้จะรักษางานที่คุณมีในขณะที่แยกออกจากสาขาการฉีด

A--B--C------F--G
       \         \
        D--E------H

แก้ไข:อ่าขอโทษที่ไม่ได้อ่านคำชี้แจงปัญหาของคุณ rebaseคุณจะต้องมีผลบังคับใช้ในขณะที่คุณดำเนินการ คำสั่งทั้งหมดที่แก้ไขประวัติจะต้องมี--forceอาร์กิวเมนต์ นี่คือความล้มเหลวที่จะป้องกันไม่ให้คุณสูญเสียงาน (เก่าDและEจะหายไป)

ดังนั้นคุณจึงทำสิ่งgit rebaseที่ทำให้ต้นไม้ดูเหมือน (แม้ว่าซ่อนอยู่บางส่วนDและEไม่อยู่ในสาขาที่มีชื่อ):

A--B--C------F--G
       \         \
        D--E      D'--E'

ดังนั้นเมื่อพยายามที่จะผลักดันใหม่featureสาขา (ที่มีD'และE'ในนั้น) คุณจะสูญเสียและDE


3
มันไม่มีอะไรผิดปกติและฉันรู้ว่ามันใช้ได้ มันไม่ใช่สิ่งที่ฉันต้องการ อย่างที่ฉันพูดคำถามนี้มีแนวคิดมากกว่าเชิงปฏิบัติ
Yuval Adam

4

สำหรับฉันทำตามขั้นตอนง่าย ๆ ใช้งานได้:

1. git checkout myFeature
2. git rebase master
3. git push --force-with-lease
4. git branch -f master HEAD
5. git checkout master
6. git pull

หลังจากทำทั้งหมดข้างต้นเราสามารถลบ myFeature branch ได้ด้วยคำสั่งดังต่อไปนี้:

git push origin --delete myFeature

3

งานต่อไปนี้สำหรับฉัน:

git push -f origin branch_name

และจะไม่ลบรหัสใด ๆ ของฉัน

แต่ถ้าคุณต้องการหลีกเลี่ยงปัญหานี้คุณสามารถทำสิ่งต่อไปนี้:

git checkout master
git pull --rebase
git checkout -b new_branch_name

จากนั้นคุณสามารถเลือกเชอร์รี่ทั้งหมดที่คุณให้ไว้กับสาขาใหม่ git cherry-pick COMMIT ID แล้วดันสาขาใหม่ของคุณ


5
-fเป็นนามแฝง--forceซึ่งเป็นคำถามที่พยายามหลีกเลี่ยงหากเป็นไปได้
epochengine

1

เนื่องจาก OP เข้าใจปัญหาเพียงมองหาโซลูชันที่ดีกว่า ...

วิธีนี้เกี่ยวกับการปฏิบัติเป็นอย่างไร

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

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

อาจมีชื่อรูปแบบสำหรับวิธีนี้แล้ว

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