คำตอบสั้น ๆ
คุณละเว้นข้อเท็จจริงที่ว่าคุณวิ่งgit push
ได้รับข้อผิดพลาดต่อไปนี้จากนั้นจึงดำเนินการต่อgit pull
:
To git@bitbucket.org:username/test1.git
! [rejected] dev -> dev (non-fast-forward)
error: failed to push some refs to 'git@bitbucket.org:username/test1.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
แม้จะมีความพยายามที่จะ Git เป็นประโยชน์คำแนะนำ 'คอมไพล์ดึง' มันน่าจะไม่ใช่สิ่งที่คุณต้องการจะทำ
ถ้าคุณคือ:
- ทำงานกับ "สาขาคุณลักษณะ" หรือ "สาขานักพัฒนา" เพียงอย่างเดียวจากนั้นคุณสามารถเรียกใช้
git push --force
เพื่ออัปเดตระยะไกลโดยใช้การคอมมิตหลังการรีเบสของคุณ ( ตามคำตอบของผู้ใช้ 4405677 )
- การทำงานในสาขากับนักพัฒนาหลายคนในเวลาเดียวกันคุณอาจไม่ควรใช้
git rebase
ตั้งแต่แรก หากต้องการอัปเดตdev
ด้วยการเปลี่ยนแปลงmaster
คุณควรใช้แทนการเรียกใช้git rebase master dev
ให้รันgit merge master
ในขณะที่เปิดdev
( ตามคำตอบของจัสติน )
คำอธิบายที่ยาวขึ้นเล็กน้อย
แต่ละคอมมิตแฮชใน Git ขึ้นอยู่กับปัจจัยหลายประการซึ่งหนึ่งในนั้นคือแฮชของคอมมิตที่มาก่อน
หากคุณเรียงลำดับคอมมิตใหม่คุณจะเปลี่ยนคอมมิตแฮช rebasing (เมื่อมันทำบางอย่าง) จะเปลี่ยนคอมมิตแฮช ด้วยเหตุนี้ผลลัพธ์ของการรันgit rebase master dev
โดยที่dev
ไม่ซิงค์master
จะสร้างคอมมิตใหม่ (และทำให้แฮช) โดยมีเนื้อหาเดียวกันกับที่เปิดอยู่dev
แต่มีคอมมิตที่master
แทรกอยู่ข้างหน้า
คุณสามารถจบลงในสถานการณ์เช่นนี้ได้หลายวิธี ฉันคิดได้สองวิธี:
- คุณสามารถมุ่งมั่นใน
master
สิ่งที่คุณต้องการเป็นพื้นฐานdev
ในการทำงานของคุณ
- คุณสามารถยอมรับ
dev
สิ่งนั้นได้ถูกผลักไปที่รีโมตแล้วซึ่งคุณจะดำเนินการเปลี่ยนแปลงต่อไป (reword commits ข้อความ, เรียงลำดับคอมมิชใหม่, สควอชคอมมิต ฯลฯ )
มาทำความเข้าใจกันดีกว่าว่าเกิดอะไรขึ้น - นี่คือตัวอย่าง:
คุณมีที่เก็บ:
2a2e220 (HEAD, master) C5
ab1bda4 C4
3cb46a9 C3
85f59ab C2
4516164 C1
0e783a3 C0
จากนั้นคุณดำเนินการเปลี่ยนแปลงคอมมิต
git rebase --interactive HEAD~3 # Three commits before where HEAD is pointing
(นี่คือที่ที่คุณจะต้องใช้คำของฉัน: มีหลายวิธีในการเปลี่ยน commits ใน Git ในตัวอย่างนี้ฉันเปลี่ยนเวลาC3
แต่คุณกำลังแทรกคอมมิตใหม่เปลี่ยนข้อความคอมมิตการจัดลำดับคอมมิตใหม่ squashing กระทำร่วมกัน ฯลฯ )
ba7688a (HEAD, master) C5
44085d5 C4
961390d C3
85f59ab C2
4516164 C1
0e783a3 C0
ซึ่งเป็นสิ่งสำคัญที่ต้องสังเกตว่าแฮชคอมมิตแตกต่างกัน นี่เป็นพฤติกรรมที่คาดหวังเนื่องจากคุณได้เปลี่ยนแปลงอะไรบางอย่างเกี่ยวกับพวกเขา ไม่เป็นไร แต่:
การพยายามพุชจะแสดงข้อผิดพลาด (และคำใบ้ว่าคุณควรเรียกใช้git pull
)
$ git push origin master
To git@bitbucket.org:username/test1.git
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'git@bitbucket.org:username/test1.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
หากเราเรียกใช้git pull
เราจะเห็นบันทึกนี้:
7df65f2 (HEAD, master) Merge branch 'master' of bitbucket.org:username/test1
ba7688a C5
44085d5 C4
961390d C3
2a2e220 (origin/master) C5
85f59ab C2
ab1bda4 C4
4516164 C1
3cb46a9 C3
0e783a3 C0
หรือแสดงวิธีอื่น:
และตอนนี้เรามีการคอมมิตซ้ำในเครื่อง ถ้าเราจะเรียกใช้git push
เราจะส่งไปที่เซิร์ฟเวอร์
เพื่อหลีกเลี่ยงการมาถึงขั้นตอนนี้เราสามารถวิ่งได้git push --force
(โดยที่เราวิ่งแทนgit pull
) สิ่งนี้จะส่งความมุ่งมั่นของเรากับแฮชใหม่ไปยังเซิร์ฟเวอร์โดยไม่มีปัญหา ในการแก้ไขปัญหาในขั้นตอนนี้เราสามารถรีเซ็ตกลับไปก่อนที่เราจะวิ่งได้git pull
:
ดูที่ reflog ( git reflog
) เพื่อดูสิ่งที่กระทำกัญชาคือก่อนที่git pull
เราวิ่ง
070e71d HEAD@{1}: pull: Merge made by the 'recursive' strategy.
ba7688a HEAD@{2}: rebase -i (finish): returning to refs/heads/master
ba7688a HEAD@{3}: rebase -i (pick): C5
44085d5 HEAD@{4}: rebase -i (pick): C4
961390d HEAD@{5}: commit (amend): C3
3cb46a9 HEAD@{6}: cherry-pick: fast-forward
85f59ab HEAD@{7}: rebase -i (start): checkout HEAD~~~
2a2e220 HEAD@{8}: rebase -i (finish): returning to refs/heads/master
2a2e220 HEAD@{9}: rebase -i (start): checkout refs/remotes/origin/master
2a2e220 HEAD@{10}: commit: C5
ab1bda4 HEAD@{11}: commit: C4
3cb46a9 HEAD@{12}: commit: C3
85f59ab HEAD@{13}: commit: C2
4516164 HEAD@{14}: commit: C1
0e783a3 HEAD@{15}: commit (initial): C0
ดังกล่าวข้างต้นเราจะเห็นว่าเป็นกระทำเราอยู่ที่ก่อนที่จะใช้ba7688a
git pull
กับที่กระทำกัญชาในมือเราสามารถตั้งค่ากลับไปที่ ( git reset --hard ba7688a
) git push --force
และเรียกใช้แล้ว
และเราทำเสร็จแล้ว
แต่เดี๋ยวก่อนฉันยังคงทำงานพื้นฐานจากการกระทำที่ซ้ำกัน
หากคุณไม่ได้สังเกตเห็นว่าการกระทำซ้ำซ้อนและดำเนินการต่อไปบนยอดการกระทำที่ซ้ำกันแสดงว่าคุณได้สร้างปัญหาให้กับตัวเอง ขนาดของระเบียบเป็นสัดส่วนกับจำนวนคอมมิตที่คุณมีบนยอดซ้ำ
หน้าตาเป็นอย่างไร:
3b959b4 (HEAD, master) C10
8f84379 C9
0110e93 C8
6c4a525 C7
630e7b4 C6
070e71d (origin/master) Merge branch 'master' of bitbucket.org:username/test1
ba7688a C5
44085d5 C4
961390d C3
2a2e220 C5
85f59ab C2
ab1bda4 C4
4516164 C1
3cb46a9 C3
0e783a3 C0
หรือแสดงวิธีอื่น:
ในสถานการณ์นี้เราต้องการลบการคอมมิตที่ซ้ำกันออก แต่ยังคงไว้ซึ่งการคอมมิตที่เรามีอยู่ - เราต้องการให้ C6 ถึง C10 เช่นเดียวกับสิ่งต่างๆส่วนใหญ่มีหลายวิธีในการดำเนินการนี้:
ทั้ง:
- สร้างสาขาใหม่ที่ผ่านมาซ้ำกระทำ1 ,
cherry-pick
แต่ละกระทำ (C6 ผ่าน C10 รวม) เข้าสู่ที่สาขาใหม่และการรักษาที่สาขาใหม่เป็นที่ยอมรับ
- Run
git rebase --interactive $commit
ซึ่ง$commit
เป็นกระทำก่อนที่ทั้งสองกระทำซ้ำ2 ที่นี่เราสามารถลบบรรทัดสำหรับรายการที่ซ้ำกันได้ทันที
1ไม่สำคัญว่าคุณจะเลือกแบบไหนba7688a
หรือ2a2e220
ทำงานได้ดี
285f59ab
ในตัวอย่างมันจะเป็น
TL; DR
ตั้งค่าadvice.pushNonFastForward
เป็นfalse
:
git config --global advice.pushNonFastForward false