Git รีเซ็ต - ยากและกดไปยังที่เก็บระยะไกล


199

ฉันมีที่เก็บข้อมูลที่มีข้อผิดพลาดบางอย่าง (D, E และ F สำหรับตัวอย่างนี้)

ABCDEF master และ Origin / master

git reset --hardฉันได้มีการปรับเปลี่ยนพื้นที่เก็บข้อมูลในท้องถิ่นโดยเฉพาะกับ ฉันเอาสาขาก่อนรีเซ็ตดังนั้นตอนนี้ฉันมี repo ที่มีลักษณะ:

A-B-C master  
     \ D-E-F old_master

A-B-C-D-E-F origin/master

ตอนนี้ฉันต้องการบางส่วนของความมุ่งมั่นที่ไม่ดีเหล่านั้นดังนั้นฉันเชอร์รี่เลือกบิตที่ฉันต้องการและสร้างความมุ่งมั่นใหม่ดังนั้นตอนนี้ฉันมีสิ่งต่อไปนี้ในพื้นที่:

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

ตอนนี้ฉันต้องการผลักดันสถานะของกิจการนี้ไปยัง repo ระยะไกล อย่างไรก็ตามเมื่อฉันพยายามทำgit pushGit ให้แปรงฉันอย่างสุภาพ:

$ git push origin +master:master --force  
Total 0 (delta 0), reused 0 (delta 0)  
error: denying non-fast forward refs/heads/master (you should pull first)  
To git@git.example.com:myrepo.git  
! [remote rejected] master -> master (non-fast forward)  
error: failed to push some refs to 'git@git.example.com:myrepo.git'  

ฉันจะรับ repo ระยะไกลเพื่อใช้สถานะปัจจุบันของ repo ท้องถิ่นได้อย่างไร


2
เป็น 'เกือบ' ซ้ำหลาย "ฉันจะผลักดันให้มีการแก้ไขเพิ่มเติมคำถามประวัติศาสตร์" เช่นดูคำตอบที่นี่stackoverflow.com/questions/253055/...
CB เบลีย์

2
นั่นเป็นเรื่องจริงและฉันได้ค้นหาคำตอบ StackOverflow ก่อนโพสต์ อย่างไรก็ตามการค้นหาของฉันมีเพียงคำตอบที่ git push --force แก้ไขปัญหาเท่านั้น ขอบคุณสำหรับการเชื่อมโยงไปยังโพสต์ของคุณ :)
robertpostill

2
คุณจะเร็ว ๆ นี้ (git1.8.5, Q4 2013) จะสามารถที่จะทำgit push -forceอย่างระมัดระวังมากขึ้น
VonC

คำตอบ:


286

หากการบังคับให้กดไม่ช่วย (" git push --force origin" หรือ " git push --force origin master" น่าจะเพียงพอ) อาจหมายความว่าเซิร์ฟเวอร์ระยะไกลปฏิเสธการส่งต่ออย่างรวดเร็วไม่ใช่การส่งผ่านทางตัวแปรรับ.d.dynnonfastForwards (ดูgit config manpage สำหรับคำอธิบาย) หรือ ผ่านการอัพเดท / รับเบ็ดล่วงหน้า

ด้วย Git ที่เก่ากว่าคุณสามารถแก้ไขข้อ จำกัด ดังกล่าวได้โดยการลบ " git push origin :master" (ดูที่ ':' หน้าชื่อสาขา) จากนั้นสร้างgit push origin masterสาขาใหม่ที่กำหนด ""

หากคุณไม่สามารถเปลี่ยนแปลงสิ่งนี้ได้โซลูชันเดียวเท่านั้นที่จะแทนที่การเขียนประวัติใหม่เพื่อสร้างการคืนค่าการเปลี่ยนแปลงใน DEF :

ABCDEF - [(DEF) ^ - 1] หลัก

ABCDEF กำเนิด / ต้นแบบ

2
@ JakubNarębskiขอบคุณ get revert HEAD~Nช่วย Nคือจำนวนการกระทำ ตัวอย่างเช่นหากฉันต้องการการยืนยันก่อนหน้านี้ฉันจะใช้git revert HEAD~1
Maksim Dmitriev

1
และระวังให้ดีคุณจะทำลายเจ้านายท้องถิ่นของคนอื่นด้วยการทำเช่นนี้
Tom Brito

24

เพื่อเติมเต็มคำตอบของ Jakub หากคุณสามารถเข้าถึงเซิร์ฟเวอร์ git ระยะไกลใน ssh คุณสามารถเข้าไปในไดเรกทอรีระยะไกล git และตั้งค่า:

user@remote$ git config receive.denyNonFastforwards false

จากนั้นกลับไปที่ repo ในพื้นที่ของคุณลองอีกครั้งเพื่อทำคอมมิชชันด้วย--force:

user@local$ git push origin +master:master --force

และในที่สุดก็ย้อนกลับการตั้งค่าเซิร์ฟเวอร์ในสถานะป้องกันเดิม:

user@remote$ git config receive.denyNonFastforwards true

ดูเพิ่มเติมที่pete.akeo.ie/2011/02/denying-non-fast-forward-and.htmlเพื่อหาข้อมูลที่เหมาะกับแหล่งข้อมูลนี้
hlovdal

คำแนะนำโดยละเอียดเกี่ยวกับวิธีปิดการใช้งาน denyNonFastForwards ที่viมีให้ในโพสต์ SO นี้: stackoverflow.com/a/43721579/2073804
ron190

2

แทนที่จะแก้ไขสาขา "มาสเตอร์" ของคุณวิธีที่ง่ายกว่าคือการสลับกับ "ปรมาจารย์หลัก" ของคุณโดยเปลี่ยนชื่อสาขา ดูhttps://stackoverflow.com/a/2862606/2321594 วิธีนี้คุณจะไม่ทิ้งร่องรอยการย้อนกลับหลาย ๆ ครั้ง


1

คอมไพล์รีเซ็ตธุรกิจทั้งหมดมองไกลไปที่ซับซ้อนสำหรับฉัน

ดังนั้นฉันจึงทำบางสิ่งบางอย่างตามเส้นเพื่อรับโฟลเดอร์ src ของฉันในสถานะที่ฉันมีข้อผูกมัดไม่กี่ที่ผ่านมา

# reset the local state
git reset <somecommit> --hard 
# copy the relevant part e.g. src (exclude is only needed if you specify .)
tar cvfz /tmp/current.tgz --exclude .git  src
# get the current state of git
git pull
# remove what you don't like anymore
rm -rf src
# restore from the tar file
tar xvfz /tmp/current.tgz
# commit everything back to git
git commit -a
# now you can properly push
git push

วิธีนี้สถานะของกิจการใน src จะถูกเก็บไว้ในไฟล์ tar และ git ถูกบังคับให้ยอมรับสถานะนี้โดยไม่ต้องเล่นซอมากเกินไปโดยทั่วไปไดเรกทอรี src จะถูกแทนที่ด้วยสถานะที่มีหลายคอมมิชชันที่ผ่านมา


0

สำหรับผู้ใช้ GitHub สิ่งนี้ใช้ได้กับฉัน:

  1. ในกฎการป้องกันสาขาใด ๆ ที่คุณต้องการทำการเปลี่ยนแปลงตรวจสอบให้แน่ใจว่าได้เปิดใช้งานการบังคับให้ใช้การพุช
  2. git reset --hard <full_hash_of_commit_to_reset_to>
  3. git push --force

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

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

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