การยกเลิกการ 'git push'


591

นี่คือสิ่งที่ฉันทำในสาขาที่ควรจะเป็นของฉัน...

% git rebase master
First, rewinding head to replay your work on top of it...
Fast-forwarded alpha-0.3.0 to master.
% git status
# On branch alpha-0.3.0
# Your branch is ahead of 'origin/alpha-0.3.0' by 53 commits.
#
nothing to commit (working directory clean)
% git push
Fetching remote heads...
  refs/
  refs/heads/
  refs/tags/
  refs/remotes/
'refs/heads/master': up-to-date
updating 'refs/heads/alpha-0.3.0'
  from cc4b63bebb6e6dd04407f8788938244b78c50285
  to   83c9191dea88d146400853af5eb7555f252001b0
    done
'refs/heads/unstable': up-to-date
Updating remote server info

นั่นเป็นข้อผิดพลาดทั้งหมดที่ฉันรู้ในภายหลัง ฉันต้องการยกเลิกกระบวนการทั้งหมดนี้และเปลี่ยนสาขาอัลฟา -0.0.0 กลับไปเป็นเหมือนเดิม

ฉันควรทำอย่างไรดี?


stackoverflow นี้โพสต์อาจ? stackoverflow.com/questions/134882/undoing-a-git-rebase
Steen

4
มันไม่ได้เป็นสถานการณ์เดียวกันจริง ๆ การเลิกทำการ rebase เป็นสถานการณ์จำลองของที่เก็บข้อมูลในพื้นที่การยกเลิกการพุชแบบ Git นั้นเกี่ยวข้องกับที่เก็บข้อมูลระยะไกล
CB Bailey

สตีน - คุณพูดถูก - ฉันน่าจะมี ฉันคิดว่าพื้นที่เก็บข้อมูลที่มีความสุขซึ่งการดึงทั้งหมดเป็นงานของผู้ดูแลระบบมากขึ้นและเป็นของที่นี่โดยที่คอมไพล์ฝั่งไคลเอ็นต์ทั่วไปเป็นคำถามสแต็คโอเวอร์โฟลว์
Cyrus

ชี้แจงอย่างรวดเร็ว - ฉันเดาว่าถ้าคุณอ้างถึงคอมไพล์คอมไพล์ด้วยค่าแฮชบางส่วนคอมไพล์จะสมมติว่าคุณกำลังพูดถึงคอมมิชชันที่แฮชเริ่มต้นด้วยสตริงนั้น?
Gershom

คำตอบ:


943

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

จากนั้นคุณต้อง 'บังคับ' ผลักดันการอ้างอิงเก่า

git push -f origin last_known_good_commit:branch_name

หรือในกรณีของคุณ

git push -f origin cc4b63bebb6:alpha-0.3.0

คุณอาจreceive.denyNonFastForwardsตั้งค่าในที่เก็บระยะไกล หากเป็นกรณีนี้คุณจะได้รับข้อผิดพลาดซึ่งรวมถึงวลี[remote rejected]นั้น

ในสถานการณ์นี้คุณจะต้องลบและสร้างสาขาใหม่

git push origin :alpha-0.3.0
git push origin cc4b63bebb6:refs/heads/alpha-0.3.0

หากไม่ได้ผล - อาจเป็นเพราะคุณได้receive.denyDeletesตั้งค่าไว้คุณจะต้องเข้าใช้ที่เก็บข้อมูลโดยตรง ในพื้นที่เก็บข้อมูลระยะไกลจากนั้นคุณต้องทำอะไรบางอย่างเช่นคำสั่งการประปาต่อไปนี้

git update-ref refs/heads/alpha-0.3.0 cc4b63bebb6 83c9191dea8

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

139
สำหรับการอ้างอิงอย่างรวดเร็วบรรทัดแรกที่นี่คือgit push -f origin last_known_good_commit:branch_name
philfreo

5
git push -f กำเนิด cc4b63bebb6: alpha-0.3.0 => อันนี้ช่วยฉันได้เลยหมายเหตุ alpha-0.3.0 เป็นชื่อสาขาและ cc4b63bebb6 เป็นรหัสยืนยันที่เราต้องการเปลี่ยนกลับไปเป็น ดังนั้นหลังจากดำเนินการคำสั่งนี้เราจะอยู่ใน cc4b63bebb6 กระทำ ID
kumar

22
วิธีนี้เป็นอันตรายอย่างยิ่งหากคุณทำงานใน repo ที่ใช้ร่วมกัน ตามแนวทางปฏิบัติที่ดีที่สุดความมุ่งมั่นทั้งหมดที่ผลักดันไปยังธุรกรรมซื้อคืนระยะไกลที่ใช้ร่วมกันควรถูกพิจารณาว่า 'ไม่เปลี่ยนรูป' ใช้ 'git revert' แทน: kernel.org/pub/software/scm/git/docs/…
Saboosh

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

165

ฉันเชื่อว่าคุณสามารถทำได้เช่นกัน:

git checkout alpha-0.3.0
git reset --hard cc4b63bebb6
git push origin +alpha-0.3.0

วิธีนี้คล้ายกับวิธีสุดท้ายยกเว้นคุณไม่จำเป็นต้องเข้าไปยุ่งกับ repo ทางไกล


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

3
+1 สำหรับคำตอบนี้ที่ช่วยฉันออกมาจริงๆ ฉันต้องการเพิ่ม (และทำให้ทุกอย่างชัดเจน) ว่ารหัสการกระทำ (ซึ่งมาหลังจาก--hardพารามิเตอร์ "") ควรเป็นรหัสของสิ่งที่คุณต้องการตั้งค่าสาขาของคุณ
Michael Dautermann

1
เขียนประวัติใหม่อีกครั้ง ... ใครก็ตามที่สามารถดึงการเปลี่ยนแปลงได้ฉันมั่นใจว่าพวกเขาทำgit reset --hard [commit_id]อย่างนั้นดังนั้นเราจึงไม่ยุ่งกับการต่อเนื่องของเวลาว่าง
แบบฟอร์มชีวิตมนุษย์ต่างดาว

9
+ สำหรับใน "ต้นกำเนิด push git + alpha-0.3.0" คืออะไร
jpierson

1
@jpierson +บังคับให้เกิดการกดเช่นเดียวกับ-f(แต่แตกต่างกันเล็กน้อย: stackoverflow.com/a/25937833/1757149 ) หากไม่มีคุณลองgit push origin alpha-0.3.0กดจะล้มเหลว: Updates were rejected because the tip of your current branch is behind.
A__

106

git revert อันตรายน้อยกว่าวิธีที่แนะนำบางประการที่นี่:

prompt> git revert 35f6af6f77f116ef922e3d75bc80a4a466f92650
[master 71738a9] Revert "Issue #482 - Fixed bug."
 4 files changed, 30 insertions(+), 42 deletions(-)
prompt> git status
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
#
nothing to commit (working directory clean)
prompt>

แทนที่ 35f6af6f77f116ef922e3d75bc80a4a466f92650 ด้วยความรับผิดชอบของคุณเอง


2
ฉันจะสร้าง ID 35f6af6f77f116ef922e3d75bc80a4a466f92650 ID ได้อย่างไร คำตอบนี้จะดีกว่าถ้าคุณสามารถอธิบายได้
Volomike

2
@Volomike (และ devog Googling แห่งอนาคต) คำถามนี้อธิบายหลายวิธีในการรับมัน: การควบคุมเวอร์ชันและคำถามแฮชใน SO
Jaime

นี่คือคำตอบที่ถูกต้องเพราะด้วย "การรีเซ็ต git" คุณไม่ควรกด (อัปเดตถูกปฏิเสธเนื่องจากส่วนปลายของสาขาปัจจุบันของคุณอยู่หลังสำเนาระยะไกล) หรือคุณต้องบังคับให้ดึงซึ่งไม่สะอาดจริงๆ
โทมัส Decaux

สิ่งนี้ได้ผลสำหรับฉัน อย่างไรก็ตามโปรดระวังเพราะการเปลี่ยนกลับจะเป็นการเปลี่ยนแปลงในไฟล์ภายในเครื่องของคุณ
user1941537

ฉันเลือกใช้สำหรับวิธีการนี้หลายครั้ง แต่ยังผมใช้คอมไพล์ rebase -i <รหัสก่อนสุดท้ายที่ดีกระทำ> การทำ rebase โต้ตอบและประวัติความเป็นมาทำความสะอาดตามที่แนะนำที่นี่stackoverflow.com/questions/5189560/...
Ernesto Allely

35

โซลูชันที่ได้รับการยอมรับ (จาก @charles bailey) เป็นสิ่งที่อันตรายอย่างยิ่งหากคุณทำงานใน repo ที่แชร์

ตามแนวทางปฏิบัติที่ดีที่สุดความมุ่งมั่นทั้งหมดที่ผลักดันไปยังธุรกรรมซื้อคืนระยะไกลที่ใช้ร่วมกันควรถูกพิจารณาว่า 'ไม่เปลี่ยนรูป' ใช้ 'git revert' แทน: http://www.kernel.org/pub/software/scm/git/docs/user-manual.html#fixing-mistakes

https://git-scm.com/book/be/v2/Git-Basics-Undoing-Things


คำแนะนำที่คุณสั่งจ่ายคืออะไร ดูเหมือนว่าคุณจะมีลิงก์เก่า ๆ เท่านั้น
jww

32

วิธีที่จะทำโดยไม่สูญเสียการเปลี่ยนแปลงที่คุณต้องการ:

git reset cc4b63b 
git stash
git push -f origin alpha-0.3.0
git stash pop

จากนั้นคุณสามารถเลือกไฟล์ที่คุณต้องการผลักดัน


19

อีกวิธีในการทำสิ่งนี้:

  1. สร้างสาขาอื่น
  2. ชำระเงินการกระทำก่อนหน้านี้ในสาขานั้นโดยใช้ "git checkout"
  3. ผลักดันสาขาใหม่
  4. ลบสาขาเก่าและกดลบ (ใช้git push origin --delete <branch_name>)
  5. เปลี่ยนชื่อสาขาใหม่เป็นสาขาเก่า
  6. ผลักดันอีกครั้ง

2
อันนี้ดูเหมือนเป็นทางออกที่แท้จริงเมื่อคุณทำผิดไปแล้วใน repo
Illarion Kovalchuk

17
git push origin +7f6d03:master

วิธีนี้จะเปลี่ยน repo ของคุณกลับไปเป็นหมายเลขการส่ง


2
นี่คือคำตอบที่ตรงไปตรงมามากที่สุด คุณเป็นตัวช่วยชีวิต
Ekundayo Blessing Funminiyi

2
จำไว้ว่าจะไม่รีเซ็ตไฟล์ภายในเครื่องของคุณ
K-Gun

11

เลิกทำการรีเซ็ตคอมมิทหลายคอม - ฮาร์ด 0ad5a7a6 (เพียงให้แฮชการคอมมิชชัน SHA1)

เลิกทำการกระทำล่าสุด

git reset - ฮาร์ด HEAD ~ 1 (การเปลี่ยนแปลงการคอมมิทล่าสุดจะถูกลบ) git reset - ซอฟท์ HEAD ~ 1 (การเปลี่ยนแปลงการคอมมิทล่าสุดจะพร้อมใช้งานในรูปแบบการแก้ไขในท้องถิ่นที่ไม่ธรรมดา)


9

สถานการณ์ที่ 1 : หากคุณต้องการยกเลิกการคอมมิชชันล่าสุดบอกว่า 8123b7e04b3 ด้านล่างคือคำสั่ง (นี่ใช้งานได้สำหรับฉัน):

git push origin +8123b7e04b3^:<branch_name>

ผลลัพธ์มีลักษณะดังนี้:

Total 0 (delta 0), reused 0 (delta 0)
To https://testlocation/code.git
 + 8123b7e...92bc500 8123b7e04b3^ -> master (forced update)

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

git reset --hard 8123b7e04b3

เอาท์พุท:

HEAD is now at cc6206c Comment_that_was_entered_for_commit

ข้อมูลเพิ่มเติมที่นี่: https://github.com/blog/2019-how-to-undo-almost-anything-with-git


สถานการณ์ที่ 1 ควรคำตอบที่ได้รับการยอมรับเนื่องจากคำถามไม่ได้ระบุว่าจะคอมมิทที่จะลบ คำตอบที่ยอมรับจะลบการกระทำครั้งสุดท้ายเท่านั้น คำตอบนี้จะลบการกระทำใด ๆ
Dominic Cerisano

0

คำตอบที่มีอยู่นั้นดีและถูกต้องอย่างไรก็ตามจะทำอย่างไรถ้าคุณต้องการเลิกทำpushแต่:

  1. คุณต้องการรักษาคอมมิทไว้ในเครื่องหรือคุณต้องการเก็บการเปลี่ยนแปลงที่ไม่มีข้อผูกมัด
  2. คุณไม่รู้ว่าคุณแค่ผลักไปกี่คน

ใช้คำสั่งนี้เพื่อยกเลิกการเปลี่ยนแปลงการอ้างอิง:

git push -f origin refs/remotes/origin/<branch>@{1}:<branch>

-2

หากคุณต้องการเพิกเฉยการกระทำครั้งสุดท้ายที่คุณเพิ่งผลักในสาขาระยะไกล: สิ่งนี้จะไม่ลบการกระทำ แต่เพียงเพิกเฉยโดยการย้ายตัวชี้ git ไปที่การส่งก่อนหน้าอ้างอิงโดย HEAD ^ หรือ HEAD ^ 1

git push origin +HEAD^:branch

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

git revert <SHA-1>
git push origin branch

1
ใช่! สิ่งนี้ทำงานเหมือนมีเสน่ห์เมื่อทำงานกับ GitHub ขอบคุณ
cukabeka

คำถามเกี่ยวกับ "push" จากนั้นจะเกี่ยวข้องกับสาขาระยะไกล ไม่ต้องย้าย HEAD โดยประมาณหนึ่งคอมมิชชันซึ่งหมายถึงการไม่สนใจการกระทำล่าสุดที่ผลักดันทำเช่นนี้: git push origin + HEAD ^: your_branch
mkebri
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.