ไม่สามารถผลักดันไปยังสาขาหลังจากรีบูต


131

เราใช้คอมไพล์และมีสาขาหลักและสาขานักพัฒนาซอฟต์แวร์ ฉันต้องเพิ่มฟีเจอร์ใหม่แล้วจึงทำการ rebit to master จากนั้นพุช master ไปที่เซิร์ฟเวอร์ CI

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

คำถาม: หลังจากการรีบูตและการแก้ไขข้อขัดแย้งฉันจะซิงค์สาขานักพัฒนาซอฟต์แวร์ในพื้นที่และระยะไกลได้อย่างไรโดยไม่ต้องสร้างการคอมมิทซ้ำ

ติดตั้ง:

// master branch is the main branch
git checkout master
git checkout -b myNewFeature

// I will work on this at work and at home
git push origin myNewFeature

// work work work on myNewFeature
// master branch has been updated and will conflict with myNewFeature
git pull --rebase origin master

// we have conflicts
// solve conflict
git rebase --continue

//repeat until rebase is complete
git push origin myNewFeature

//ERROR
error: failed to push some refs to 'git@github.com:ariklevy/dropLocker.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

// do what git says and pull
git pull origin myNewFeature

git push origin myNewFeature

// Now I have duplicate commits on the remote branch myNewFeature

แก้ไข

ดังนั้นดูเหมือนว่าสิ่งนี้จะทำลายเวิร์กโฟลว์:

ผู้พัฒนา 1 กำลังทำงานบน myNewFeature developer2 กำลังทำงานบน hisNewFeature ทั้งคู่ใช้ต้นแบบเป็นสาขาหลัก

ผู้พัฒนา 2 ผสาน myNewFeature เข้ากับเขา NewFeature

นักพัฒนา 1 rebases แก้ไขข้อขัดแย้งจากนั้นบังคับให้พุชไปยังสาขาระยะไกลสำหรับ myNewFeature

สองสามวันต่อมาผู้พัฒนา 2 รวม myNewFeature เข้ากับเขาคุณสมบัติใหม่อีกครั้ง

สิ่งนี้จะทำให้ผู้พัฒนารายอื่นเกลียดนักพัฒนาหรือไม่?


ไม่ใช่ทางออก แต่เป็นเพียงความคิด ใครwe? คุณอยู่ในทีมมากกว่าเพียงแค่คุณหรือไม่ theyพูด (คนที่รู้มากกว่าที่ผมทำ) rebaseว่าถ้าคุณแบ่งปันรหัสของคุณมากกว่าที่คุณไม่ควรใช้ ทำไมคุณไม่ทำgit pullและgit merge?
AdamT

ขออภัยเรา = ทีมพัฒนา
แมตต์

1
ดังนั้นใช่อาจไม่ควรรีบูตเมื่อคุณแชร์รหัส ที่อาจทำให้คุณต้องทำสิ่งต่าง ๆ เช่นรายการด้านล่าง ( forceการผลักดัน)
AdamT

โอ้ขอโทษเมื่อพวกเขาพูดrewriting historyว่านั่นคือrebase
AdamT

ในขณะที่เขากล่าวว่าเป็นสาขาการพัฒนาของตัวเองเพื่อที่จะไม่เป็นปัญหาเว้นแต่ว่ามีใครบางคนคาดว่าจะรวมที่มา
Learath2 2

คำตอบ:


93

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

o-----o-----o-----o-----o-----o       master
 \
   o-----o-----o                      devel0
                \
                  o-----o-----o       devel1

จากนั้นเพื่อติดตามข้อมูลล่าสุดจากระยะไกลฉันจะทำสิ่งต่อไปนี้:

 git fetch origin
 git checkout master
 git merge --ff origin/master

ฉันทำเช่นนี้ด้วยเหตุผลสองประการ. ก่อนอื่นเพราะช่วยให้ฉันเห็นว่ามีการเปลี่ยนแปลงระยะไกลโดยไม่จำเป็นต้องเปลี่ยนจากสาขาผู้พัฒนาของฉันหรือไม่ ประการที่สองมันเป็นกลไกด้านความปลอดภัยเพื่อให้แน่ใจว่าฉันจะไม่เขียนทับการเปลี่ยนแปลงใด ๆ นอกจากนี้หากฉันไม่สามารถผสานไปข้างหน้าอย่างรวดเร็วไปยังสาขาหลักซึ่งหมายความว่ามีใครบางคนได้ทำการรีโมตต้นแบบระยะไกล (ซึ่งพวกเขาจำเป็นต้องถูกเฆี่ยนอย่างรุนแรง) หรือฉันตั้งใจที่จะเป็นผู้เชี่ยวชาญและต้องการทำความสะอาดจุดสิ้นสุดของฉัน

จากนั้นเมื่อรีโมทมีการเปลี่ยนแปลงและฉันได้ส่งต่อไปยังล่าสุดอย่างรวดเร็วฉันจะรีบูตเครื่อง:

git checkout devel0
git rebase master
git push -f origin devel0

นักพัฒนาคนอื่นรู้ว่าพวกเขาจะต้องลดการพัฒนาของพวกเขาออกจากล่าสุด:

git fetch <remote>
git checkout devel1
git rebase <remote>/devel0

ซึ่งส่งผลในประวัติศาสตร์ที่สะอาดกว่ามาก:

o-----o                                 master
       \
         o-----o-----o                  devel0
                      \
                        o-----o-----o   devel1

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

นอกจากนี้ดูเหมือนว่านักพัฒนาซอฟต์แวร์รายอื่น ๆ อาจจะทุ่มเทให้กับสาขาพัฒนาของคุณ คุณยืนยันเรื่องนี้ได้ไหม

masterเวลาเท่านั้นที่จะผสานคือเมื่อสาขาหัวข้อของคุณพร้อมที่จะเป็นที่ยอมรับใน

เมื่อทราบด้าน หากนักพัฒนาหลายคนมุ่งมั่นที่จะเก็บที่เดียวกันคุณควรพิจารณามีสาขาที่มีชื่อเพื่อแยกความแตกต่างระหว่างนักพัฒนา devel สาขา ตัวอย่างเช่น:

git branch 'my-name/devel-branch'

ดังนั้นหัวข้อนักพัฒนาทั้งหมดจะอยู่ในชุดที่ซ้อนกันของตัวเอง


1
"ดูเหมือนว่านักพัฒนาคนอื่น ๆ อาจจะทำสิ่งต่าง ๆ กับสาขา devel ของคุณคุณสามารถยืนยันสิ่งนี้ได้หรือไม่" ใช่แล้วพวกเขาคือ ...
Matt

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

@ Matt ใช่ปัญหาทั้งสองนี้จะทำให้ขั้นตอนการทำงานของคุณแย่ลงจริง ๆ สำหรับคนแรกฉันจะสื่อสารกับนักพัฒนาคนอื่น ๆ ว่ามีเพียงเจ้าของเท่านั้นที่สามารถมอบสิทธิ์ให้กับสาขาที่มีชื่อ (เช่น 'matt / devel') IMHO ไม่มีนักพัฒนาสองคนที่ควรจะผูกพันกับสาขาเดียวกันอย่างไรก็ตาม เพียงสร้างความสับสน สำหรับภายหลังการรีบูทและการบังคับให้ดันควรทำให้ตำแหน่งทั้งสองเป็นปัจจุบัน
Trevor Norris

คำตอบที่ดี ฉันมีคำถามด้านทำไมคุณถึงใช้--forceธงเมื่อคุณทำgit push -f origin devel0?
โนบิตะ

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

50

คุณต้องบังคับให้มีการผลักดันในขณะที่คุณย้ายคอมมิชชันต่อไปลงที่ git ของบรรทัดนั้นคาดว่าคุณจะเพิ่มคอมมิทที่ปลายของสาขา git push -f origin myNewFeatureจะแก้ไขปัญหาของคุณ

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


1
ฉันพบว่านี่เป็นวิธีที่ดีที่สุดในการดูแลเวิร์กโฟลว์
Syed Priom

1
ขอบคุณเพื่อน ฉันใช้คำสั่งนี้เพื่อบังคับให้สาขาในพื้นที่ที่ถูก rebased ของฉันไปยังสาขาระยะไกลเดียวกัน
wei

11
การใช้git push --force-with-leaseปลอดภัยกว่าการใช้git push --force

git push --force-with-lease origin HEAD- สมมติว่าสาขาเป้าหมายของคุณได้รับการชำระเงินแล้ว
Lucaci Sergiu

31

สิ่งสำคัญที่ต้องจำไว้ที่นี่คือสิ่งที่ดึงและ rebase กำลังทำอยู่เบื้องหลัง

การดึงโดยทั่วไปจะทำสองสิ่ง: ดึงข้อมูลและผสาน เมื่อคุณรวม --rebase มันจะทำการรีบูตแทนการผสาน

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

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

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

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

git push -f origin newfeature

หรือในบางกรณีผู้ดูแลระบบของคุณอาจลบความสามารถในการบังคับดังนั้นคุณต้องลบและสร้างใหม่:

git push origin :newfeature
git push origin newfeature

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

โปรดจำไว้ว่าคุณสามารถเลือกใช้ GC ของ git ได้ตลอดเวลาโดยใช้ประโยชน์จาก:

git reflog

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


ตัวเลือกลบและสร้างใหม่ทำงานได้ดีสำหรับฉัน ไม่อนุญาตให้มีการบังคับใช้กับ repo ของฉัน!
Simon Holmes

2

คุณจำเป็นต้องทำการผลักดันเช่น git push -f origin myNewFeature

โอ้และคุณควรทำให้แน่ใจว่าคนอื่นจะไม่ยึดฐานสาขา dev ของคุณ - โดยปกติคุณไม่ควรเผยแพร่สาขาที่คุณเขียนประวัติเลย วิธีหนึ่งจะใช้ชื่อสาขาที่ชอบwip/myNewFeatureแล้วพูดถึงว่าwipสาขาจะถูกreb่าไปเป็นหลักในบางครั้ง


การใช้git push --force-with-leaseปลอดภัยกว่าการใช้git push --force

@MrCholo ผู้ใช้จะไม่เริ่มใช้สิ่งนี้จนกว่า git จะเพิ่มตัวเลือกสั้น ๆ สำหรับมันเหมือน-fเป็นการบังคับแบบธรรมดา :)
ThiefMaster

ใช่ฉันใช้มันในสคริปต์อัตโนมัติโท

2

คำตอบทั่วไปที่ได้รับแล้ว - ใช้git push -f origin myNewFeatureเมื่อผลักดันการเปลี่ยนแปลงที่ถูกปฏิเสธ - เป็นจุดเริ่มต้นที่ดี ฉันกำลังเขียนคำตอบนี้เพื่อแก้ไขการแก้ไขว่าเวิร์กโฟลว์ของคุณจะทำลายหรือไม่

หากเราสมมติว่าคุณกำลังจะใช้git pull --rebase ...(หรือการเปลี่ยนแปลงบางอย่างในนั้น) ตามด้วยการบังคับให้ไปยังสาขาระยะไกลสิ่งที่แบ่งเวิร์กโฟลว์ในตัวอย่างของคุณคือ developer2 กำลังผสานmyNewFeatureเข้าhisNewFeatureด้วยกัน มันสมเหตุสมผลแล้วที่จะสามารถลดสาขาฟีเจอร์ของคุณเองได้ตราบใดที่ไม่มีใครทำงานในสาขานั้นดังนั้นคุณต้องมีกฎในการกำหนดเขตแดนสาขา

คุณสามารถหลีกเลี่ยงสิ่งนี้ได้โดยการก) สร้างกฎที่คุณรวมเข้าด้วยกันmasterหรือ b) สร้างdevelopสาขาแบบรวมซึ่งคุณใช้myNewFeatureสาขาของคุณเองและสร้างกฎที่คุณรวมเข้าdevelopด้วยกัน masterจะถูกสงวนไว้สำหรับเหตุการณ์สำคัญหรือการเผยแพร่เท่านั้น (หรืออื่น ๆ ที่คุณต้องการตั้งค่า) และdevelopจะเป็นที่ที่คุณกดแต่ละคุณลักษณะเมื่อพร้อมที่จะรวมเข้ากับสาขาคุณลักษณะอื่น ๆ

ฉันเชื่อว่าสิ่งนี้ถือได้ว่าเป็นขั้นตอนการทำงานที่เรียบง่ายของ Gitflow


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