วิธีลบการผูกมัดสองสามอย่างจากสาขาระยะไกลอย่างถาวร


489

ฉันรู้ว่านั่นคือการเขียนประวัติศาสตร์ซึ่งไม่ดียาดาญาดา

แต่จะลบการผูกข้อมูลบางอย่างจากสาขาระยะไกลอย่างถาวรได้อย่างไร


96
ใช่มันแย่จริงๆญาดาญาดา แต่ด้วยเหตุผลบางอย่างฉันต้องชอบมัน
James Morris

44
ฉันรู้ว่านี่โง่ แต่บางครั้งก็เกิดขึ้น - เช่นการเข้าสู่ระบบการทดสอบและการใช้รหัสผ่านแบบข้อความธรรมดาในรหัสของคุณซึ่งเป็นข้อมูลรับรองการเข้าสู่ระบบจริง และ
อ๊ะ

6
ข้อมูลรับรองการเข้าสู่ระบบจริง .. ใช่ทำให้ฉันนึกถึงบางคนโห่ร้อง
สวัสดีจักรวาล


2
ฉันรู้สึกเบื่อหน่ายกับความรู้ทางวิชาการเกี่ยวกับความอันตรายนี้และไม่ควรทำญาดาญาดา มีบางครั้งที่ไกลดีกว่าที่จะลบสิ่งต่าง ๆ จากประวัติคอมไพล์และจัดการกับความขัดแย้ง / ทำลาย devs อื่น ๆ มันง่ายจริงๆ คนที่เพิกเฉยต่อสิ่งนี้อาจไม่เคยทำงานนอกห้องเรียน
บดขยี้

คำตอบ:


368

คุณgit reset --hardสาขาท้องถิ่นของคุณเพื่อลบการเปลี่ยนแปลงจากต้นไม้การทำงานและดัชนีและคุณgit push --forceสาขาท้องถิ่นของคุณแก้ไขไปยังระยะไกล ( โซลูชันอื่น ๆ ที่นี่เกี่ยวข้องกับการลบสาขาระยะไกลและผลักมันอีกครั้ง)

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


ด้วย Git 2.23 (สิงหาคม 2019 เก้าปีต่อมา) git switchคุณจะใช้คำสั่งใหม่
นั่นคือ: (แทนที่ด้วยจำนวนข้อผูกพันที่จะลบ)git switch -C mybranch origin/mybranch~n
n

ที่จะคืนค่าดัชนีและต้นไม้ทำงานเหมือนgit reset --hardจะ


แปลก. รู้สึกเหมือนฉันลองแล้ว เมื่อรวมกับการรีบูต - ทำงานเหมือนมีเสน่ห์ ขอบคุณ
Arnis Lapsa

7
@Arnis: สมบูรณ์แล้ว;) push --forceออกไป
VonC

ฉันใช้BFG Repo-Cleanerเพื่อกำจัดข้อมูลที่สำคัญบางอย่างซึ่งทำให้ฉันมีสาขา "ไม่มีชื่อ" ที่มีไฟล์ต้นฉบับอยู่หลังจากที่รีเซ็ตเป็นไฟล์ล่าสุดที่ต้องการและส่งไปยังแหล่งกำเนิดอย่างสมบูรณ์ทุกอย่าง
ทำได้

โปรดสังเกตว่า URL ของการส่งมอบยังมีชีวิตอยู่ (อย่างน้อยก็ในบางครั้ง) ดังนั้นหากใครบางคนมี URL ของการส่งมอบ (คุณได้ให้ไว้กับพระเจ้าก็รู้ว่าทำไม) พวกเขาจะสามารถเข้าถึงรหัสได้
Mosh Feu

1
@MoshFeu True: git gcไม่ได้ทำงานบ่อยครั้งเพียงพอในด้านระยะไกล ตัวอย่างเช่นใน GitHub: twitter.com/githubhelp/status/387926738161774592?lang=es
VonC

248

เพิ่งทราบที่จะใช้last_working_commit_idเมื่อคืนค่าการกระทำที่ไม่ทำงาน

git reset --hard <last_working_commit_id>

ดังนั้นเราจะต้องไม่รีเซ็ตเป็นสิ่งcommit_idที่เราไม่ต้องการ

จากนั้นแน่นอนว่าเราจะต้องผลักดันไปยังสาขาระยะไกล:

git push --force

10
คำตอบที่สมบูรณ์แบบสง่างามและง่ายที่สุด ฉันเพิ่งเปลี่ยนกลับไปเป็น stabe ล่าสุดที่ฉันต้องการทั้งในระยะไกลและในพื้นที่
lauWM

2
นี่ทำให้ฉันสูญเสียการเปลี่ยนแปลงในท้องถิ่นด้วย ฉันไม่ได้คาดหวังสิ่งนั้น แต่ดีกว่ายอมรับรหัสผ่านส่วนบุคคลของคุณเพื่อทำงาน repo
Airwavezx

3
คุณสามารถบันทึกการเปลี่ยนแปลงในท้องถิ่นของคุณได้ด้วย git stash .... สร้างบางสิ่ง .... และ git stash pop (การเปลี่ยนแปลงในเครื่องของคุณกลับมาแล้ว)
MonTea

สิ่งนี้ทำให้ฉันมีข้อผิดพลาดในขณะที่ "ระยะไกล: ข้อผิดพลาด: การปฏิเสธ refs / heads / master แบบไม่ส่งต่ออย่างรวดเร็ว (คุณควรดึงก่อน)"
Saurabhcdt

@ Airwavezx นั่นคือสิ่งที่git reset --hardควรจะทำ
ลุค

146

สำคัญ: ตรวจสอบให้แน่ใจว่าคุณระบุสาขาใดใน "git push -f" หรือคุณอาจแก้ไขสาขาอื่นโดยไม่ตั้งใจ! [*]

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

  1. ย้อนกลับการกระทำแบบเต็ม
  2. ลบการส่งครั้งล่าสุด
  3. ลบการคอมมิทจากรายการ

1 ย้อนกลับการกระทำแบบเต็ม

git revert dd61ab23

2 ลบการคอมมิทล่าสุด

git push <<remote>> +dd61ab23^:<<BRANCH_NAME_HERE>>

หรือหากสาขามีให้บริการในท้องถิ่น

git reset HEAD^ --hard
git push <<remote>> -f

โดยที่ + dd61 ... คือการแฮชและการคอมไพล์ของคุณตีความ x ^ เป็นพาเรนต์ของ x และ + เป็นการบังคับที่ไม่ใช่การกดอย่างรวดเร็ว

3 ลบการกระทำออกจากรายการ

git rebase -i dd61ab23^

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

git rebase --continue
git push <remote_repo> <remote_branch> -f

5
ตรวจสอบให้แน่ใจว่าคุณระบุว่าสาขาใดใน "git push <remote_repo> <remote_branch> -f" หรือคุณอาจแก้ไขสาขาอื่นโดยไม่ได้ตั้งใจ!
ไนเจลเชอริแดน - สมิ ธ

ขั้นตอนที่ 1 และ 2 ทำงานและตอบคำถามเดิม (อย่าเรียกใช้ขั้นตอนที่ 3)
Saad Benbouzid

นี่เป็นตัวเลือกสำหรับสถานการณ์ต่าง ๆ ไม่ใช่ขั้นตอนที่ต้องดำเนินการ ในกรณีของฉัน rebase เชิงโต้ตอบ (ตัวเลือก 3) ทำสิ่งที่ฉันกำลังมองหา
Steve Blackwell

ฉันต้องทำขั้นตอนที่ 3 ทำไมคุณไม่ควรใช้ @Saad นี้ โชคดีที่ <<remote>> ของฉันเป็นเพียง 'ต้นกำเนิด' เริ่มต้นและ <remote_branch> ค่าเริ่มต้น 'ต้นแบบ'
Bart

30

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

git reset --hard HEAD~3

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

git push --force

ขอแสดงความยินดี! ทุกอย่างเสร็จเรียบร้อย!

หมายเหตุบางส่วน:

คุณสามารถดึงรหัสยืนยันที่ต้องการได้

git log

จากนั้นคุณสามารถแทนที่HEAD~Nด้วย<desired-commit-id>สิ่งนี้:

git reset --hard <desired-commit-id>

หากคุณต้องการที่จะให้มีการเปลี่ยนแปลงในระบบไฟล์และเพียงแค่ปรับเปลี่ยนดัชนี (กระทำประวัติศาสตร์) ใช้ธงเช่น--soft git reset --soft HEAD~3จากนั้นคุณมีโอกาสตรวจสอบการเปลี่ยนแปลงล่าสุดของคุณและเก็บหรือลบทั้งหมดหรือบางส่วน ในกรณีหลัง runnig แสดงไฟล์ที่เปลี่ยนแปลงตั้งแต่git status <desired-commit-id>หากคุณใช้--hardตัวเลือกgit statusจะแจ้งให้คุณทราบว่าสาขาในพื้นที่ของคุณเหมือนกับสาขาระยะไกล หากคุณไม่ได้ใช้--hardหรือโหมดเริ่มต้นจะใช้ที่อยู่--soft --mixedในโหมดนี้git help resetพูดว่า:

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


10

นี่อาจจะสายเกินไป แต่สิ่งที่ช่วยฉันคือตัวเลือก 'นิวเคลียร์' ที่ฟังดูเจ๋ง โดยทั่วไปการใช้คำสั่งfilter-branchคุณสามารถลบไฟล์หรือเปลี่ยนแปลงบางอย่างในไฟล์จำนวนมากตลอดประวัติศาสตร์ git ของคุณ

มันจะมีการอธิบายที่ดีที่สุดที่นี่


9
ไม่สายเกินไป อาจจะกลายเป็นประโยชน์สำหรับคนพเนจรอยู่กับปัญหาที่คล้ายกัน :)
อานิส Lapsa

9

ลดความซับซ้อนจากคำตอบของ pctroll คล้ายกับโพสต์บล็อกนี้

# look up the commit id in git log or on github, e.g. 42480f3, then do
git checkout master
git checkout your_branch
git revert 42480f3
# a text editor will open, close it with ctrl+x (editor dependent)
git push origin your_branch
# or replace origin with your remote

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

1
ได้ผลสำหรับฉันเช่นกัน แต่ฉันมีคำถามเดียวกันกับรอยยิ้มฉันไม่ต้องการให้ใครเห็นความมุ่งมั่น / ความเคารพของฉันในประวัติศาสตร์ .. ฉันจะลบมันได้อย่างไร?
Roberto Rodriguez

4

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

จากสาขาที่ออกเดินทางในท้องถิ่นของคุณ:

git log

คัดลอกแฮชการกระทำที่คุณต้องการให้สาขาอยู่และออกจากบันทึก git

git checkout theHashYouJustCopied
git checkout -b your_new_awesome_branch

ตอนนี้คุณมีสาขาใหม่ในแบบที่คุณต้องการ

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

git checkout the_errant_branch
git log

คัดลอกแฮชการกระทำของคอมมิตที่คุณต้องการดึงเข้าสู่สาขาที่ดีและออกจากบันทึกการคอมไพล์

git checkout your_new_awesome_branch
git cherry-pick theHashYouJustCopied

ตบหลังตัวเอง


ง่ายมากและใครสนใจถ้าคุณมีสาขาที่ตายขา? สร้างสาขาใหม่และทำมันให้สำเร็จ!
Andrew Fox

นี่คือคำตอบที่ยอดเยี่ยมอย่างแท้จริง ฉันดีใจที่ฉันทำสิ่งนี้แทนที่จะทำหน้าที่เก็บเชอร์รี่หรือจัดการสาขาระยะไกล
Magnilex

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