การย้อนกลับพื้นที่เก็บข้อมูลคอมไพล์ในพื้นที่และระยะไกลโดย 1 กระทำ


188

ฉันได้อ่านโพสต์ที่คล้ายกันในหัวข้อนี้และไม่สามารถใช้ชีวิตได้อย่างถูกต้อง

ฉันเช็คอินประมาณ 1,000 ไฟล์ที่ฉันไม่ต้องการและฉันก็ไม่จำเป็นต้องผ่าน 1by1 และลบทั้งหมดออกจาก repo

  • ฉันมีmasterสาขาระยะไกล
  • ฉันมีmasterสาขาท้องถิ่น

พวกเขาทั้งสองมีการแก้ไขเดียวกัน

ฉันต้องการย้อนกลับรีโมตของฉันด้วย 1 คอมมิท

บอกว่าประวัติศาสตร์ของฉันบนมีmaster ฉันต้องการที่จะย้อนกลับไปยังท้องถิ่นของฉัน จากนั้นดันไปที่รีโมตเพื่อแฮชปัจจุบันของฉันจะเป็น D ทั้งแบบรีโมตและโลคัล A--B--C--D--E
D

ฉันมีปัญหาในการทำเช่นนี้
ฉันใช้ Git Tower แต่ก็สบายใจกับบรรทัดคำสั่ง ความช่วยเหลือใด ๆ

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


ฉันได้อัปเดตคำตอบของฉันเป็น "เลิกทำการเปลี่ยนแปลงการกระทำก่อนหน้าโดยไม่ใช้การฮาร์ดรีเซ็ต"
VonC

3
ใช้git revertสำหรับการทำโดยไม่ต้องรีเซ็ตฮาร์ดและโดยไม่รบกวนผู้ใช้
user562374


การย้อนกลับรีโมทเป็นสิ่งที่ท้อแท้ แต่ถ้านั่นคือสิ่งที่คุณต้องการทำให้ทำ มีหลายวิธีในการทำเช่นนั้น แต่ผลลัพธ์จะเหมือนกันในฝั่งเซิร์ฟเวอร์
FelipeC

คำตอบ:


307

หากยังไม่มีใครดึง repo ระยะไกลของคุณคุณสามารถเปลี่ยน HEAD สาขาของคุณและบังคับให้กดไปที่ repo ระยะไกล:

git reset --hard HEAD^ 
git push -f 

(หรือหากคุณเข้าถึงรีโมตรีโมตโดยตรงคุณสามารถเปลี่ยนการอ้างอิง HEAD แม้ว่าจะเป็น repo เปล่า )

หมายเหตุตามที่แสดงความคิดเห็นโดยเทคโนโลยีต่างด้าวในความคิดเห็นด้านล่างบน Windows (เซสชัน CMD) คุณจะต้อง^^:

git reset --hard HEAD^^
git push -f 

อัปเดตตั้งแต่ปี 2011:
การใช้git push --force-with-lease( ที่ฉันนำเสนอที่นี่เปิดตัวในปี 2013 ด้วย Git 1.8.5) นั้นปลอดภัยกว่า

ดูคำตอบของSchwernสำหรับภาพประกอบ


เกิดอะไรขึ้นถ้าใครบางคนได้ดึง repo แล้ว? ฉันจะทำอย่างไร

จากนั้นฉันจะแนะนำสิ่งที่ไม่ได้เขียนประวัติศาสตร์:

  • git revert การกระทำล่าสุดของคุณในเครื่อง
  • ผลักดัน 'ย้อนกลับ' git revertสร้างขึ้นโดย

1
เกิดอะไรขึ้นถ้าใครบางคนได้ดึง repo แล้ว? ฉันจะทำอย่างไร
Jamis Charles

1
@gwho สร้างสาขาหรือไม่ ไม่ย้ายหัวของสาขา แต่คุณยังอยู่ในสาขาเดียวกัน อย่างไรก็ตามเนื่องจากการกดไม่ใช่การส่งต่อที่เร็วอีกต่อไปใช่คุณต้องบังคับการกดนั้น
VonC

1
มีวิธีที่จะรู้หรือไม่ถ้ามีคนดึง repo
Pinkerton

4
ใน Windows อักขระ ^ ใช้สำหรับการต่อเนื่องบรรทัดและเพื่อหลีกเลี่ยงอักขระทำให้คำสั่ง: รีเซ็ต git - ฮาร์ด HEAD ^^
Alien Technology

1
@AlienTechnology โดยใช้ Powershell บน windows 10 ฉันต้องพิมพ์reset --hard HEAD^และไม่reset --hard HEAD^^รีเซ็ตการส่งมอบครั้งล่าสุด
Gaspacchio

58

ตั้งค่าสาขาท้องถิ่นหนึ่งการแก้ไขกลับ ( HEAD^หมายถึงหนึ่งการแก้ไขกลับ):

git reset --hard HEAD^

ผลักดันการเปลี่ยนแปลงเพื่อกำเนิด:

git push --force

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

ทำมันด้วย--forceบอกคอมไพล์ให้เขียนทับHEADใน repo ระยะไกลโดยไม่เคารพความก้าวหน้าใด ๆ ที่นั่น


1
ฉันไม่แนะนำให้เรียกการคืนนี้เนื่องจากเป็นคำเฉพาะที่มีความหมายแตกต่างกันมากในคอมไพล์
Cascabel

@Jefromi: ขอบคุณสำหรับคำใบ้ แก้ไข
eckes

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

ระวัง! สะสมการเปลี่ยนแปลงที่ไม่ผูกมัดของคุณหรือทำให้มันหายไป
Nosov Pavel

มันเท่ห์มาก ดังนั้นสิ่งนี้หมายความว่าเมื่อเราทำgit push origin masterGit สามารถสร้างการส่งคำสั่งใหม่ที่ระยะไกลได้เพราะสาขาในพื้นที่นั้นล่วงหน้าอย่างน้อยหนึ่งครั้ง นอกจากนี้หลังจะต้องแตกต่างอย่างมีนัยสำคัญจากสิ่งที่หัวที่ repo ระยะไกลชี้ไปที่?
MadPhysicist

18

หากคุณต้องการเปลี่ยนกลับใช้การยอมรับครั้งล่าสุด:

ขั้นตอนที่ 1:

ตรวจสอบข้อผูกพันในพื้นที่ของคุณด้วยข้อความ

$ git log

ขั้นตอนที่ 2:

ลบการคอมมิทครั้งล่าสุดโดยไม่รีเซ็ตการเปลี่ยนแปลงจากสาขาโลคัล (หรือต้นแบบ)

$ git reset HEAD^

หรือถ้าคุณไม่ต้องการยอมรับไฟล์และอัพเดตล่าสุด

$ git reset HEAD^ --hard

ขั้นตอนที่ 3:

เราสามารถอัปเดตไฟล์และรหัสและอีกครั้งจำเป็นต้องกดด้วยแรงที่จะลบการกระทำก่อนหน้า มันจะทำให้การกระทำใหม่

$ git push origin branch -f

แค่นั้นแหละ!


นั่นไม่ใช่การคืนค่าคอมมิชชัน แต่เป็นการแทนที่ กรุณาอย่าสับสนเรา git สามเณรโดยการใช้คำธรรมดา
Suncat2000

7

โดยการป้อนคำสั่งร้องคุณสามารถดูประวัติการคอมไพล์ของคุณ -

บันทึก $ git

สมมติว่าประวัติของคุณในสาขานั้นเป็นเช่น - commit_A, commit_B, commit_C, commit_D โดยที่ commit_D เป็นคอมมิทล่าสุดและนี่คือตำแหน่งที่ HEAD ยังคงอยู่ ตอนนี้หากต้องการลบการกระทำล่าสุดออกจากโลคัลและรีโมตคุณต้องทำดังต่อไปนี้:

ขั้นตอนที่ 1: ลบการกระทำครั้งสุดท้ายในพื้นที่โดย -

$ git reset - ฮาร์ด HEAD ~

สิ่งนี้จะเปลี่ยนค่าคอมมิชชัน HEAD เป็น commit_C

ขั้นตอนที่ 2: ผลักดันการเปลี่ยนแปลงของคุณเพื่อให้ HEAD ใหม่มุ่งสู่ระยะไกล

$ git push กำเนิด + HEAD

คำสั่งนี้จะลบการส่งข้อมูลล่าสุดจากระยะไกล

PS คำสั่งนี้ได้รับการทดสอบบน Mac OSX และควรทำงานกับระบบปฏิบัติการอื่นเช่นกัน (ไม่อ้างสิทธิ์เกี่ยวกับระบบปฏิบัติการอื่น)



3

นี่คือขั้นตอนการอัปเดตที่ปลอดภัยยิ่งขึ้น

git reset --hard HEAD^ 
git push --force-with-lease

git push -fจะเป็นการแทนที่พื้นที่เก็บข้อมูลระยะไกลด้วยการเปลี่ยนแปลงของคุณเอง หากคนอื่นผลักดันการเปลี่ยนแปลงพวกเขาจะหายไป git push --force-with-leaseจะผลักดันการรีบูตของคุณหากที่เก็บเป็นอย่างที่คุณคาดหวัง หากคนอื่นผลักดันคุณไปแล้วจะล้มเหลว

ดู - บังคับว่าเป็นอันตราย เข้าใจคอมไพล์ของแรงที่มีสัญญาเช่า

ผมขอแนะนำให้ aliasing repush = push --force-with-leaseนี้เป็น

เกิดอะไรขึ้นถ้าใครบางคนได้ดึง repo แล้ว? ฉันจะทำอย่างไร

git pull --rebase=mergesบอกพวกเขาให้ แทนgit fetch originและgit merge origin/masterมันจะและgit fetch origin git rebase -r origin/masterนี้จะเขียนการเปลี่ยนแปลงใด ๆ ในท้องถิ่นของตนจะอยู่ด้านบนของปรับฐานใหม่master จะรักษาการผสานใด ๆ ที่พวกเขาอาจทำorigin/master-r

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

[pull]
        rebase = merges

1
ตกลงและโหวตขึ้น เพื่อป้องกันของฉันคำตอบ 2011 เก่าของฉันถูกเขียนเมื่อสองปีก่อนการแนะนำ--force-with-leaseตัวเลือก
VonC

ฉันคิดว่าฉันทำแล้ว (เมื่อวานนี้): stackoverflow.com/posts/4647362/revisions
VonC

1

ฉันแก้ไขปัญหาเช่นเดียวกับคุณด้วยคำสั่งนี้:

git reset --hard HEAD^
git push -f <remote> <local branch>:<remote branch> 

0

หากคุณเข้าถึง repo ระยะไกลโดยตรงคุณสามารถใช้:

git reset --soft HEAD^

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

ฉันจะยกเลิกการคอมมิตล่าสุดในที่เก็บคอมไพล์เปล่าได้อย่างไร?



0

วิธีการรีเซ็ตหัวและการย้อนกลับไปสู่การคอมมิชชันก่อนหน้านั้นผ่านไปแล้ว

$ git reset HEAD^ --hard
$ git push <branchname> -f

แต่บางครั้งอาจไม่เป็นที่ยอมรับในสาขาระยะไกล:

To ssh:<git repo>
 ! [rejected]        develop -> develop (non-fast-forward)
error: failed to push some refs to 'ssh:<git repo>'
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 revert HEAD
git push <remote branch>

ใช้งานได้ดี

หมายเหตุ: จำหากgit push -f <force>ล้มเหลวแล้วคุณพยายามที่จะย้อนกลับ ทำมาก่อนเพื่อให้ระยะไกลและท้องถิ่นอยู่ในซิงค์แล้วลองgit pull ตรวจสอบเพื่อให้แน่ใจว่ารีโมทและโลคัลอยู่ในจุดเดียวกันกับ SHA1 เดียวกันgit revert
git log

git revert 
A --> B --> C -->D
A--> B --> C --> D --> ^D(taking out the changes and committing reverted diffs)

0

กับเจ้านายท้องถิ่น

git reflog
-- this will list all last commit
  e.g Head@{0} -- wrong push
      Head@{1} -- correct push  
git checkout Head@{1} .
  -- this will reset your last modified files

git status 
git commit -m "reverted to last best"
git push origin/master

ไม่ต้องกังวลหากคนอื่นดึงหรือไม่

ทำ!


0

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

git push origin +origin/master~:master

สิ่งนี้ใช้ไวยากรณ์ต่อไปนี้:

git push <remote> <refspec>

ที่นี่<remote>คือoriginและ<refspec>มีโครงสร้างต่อไปนี้:

+origin/master~:master

git-push(1)รายละเอียดสามารถพบได้ใน วิธีการก่อนหน้านี้+"บังคับให้กดการอ้างอิงนี้" และส่วนอื่นหมายถึง "จากorigin/master~ไปยังmaster(จากระยะไกลorigin)" ไม่ยากเลยที่จะรู้ว่านั่นorigin/master~คือสิ่งสุดท้ายที่กระทำก่อนหน้าorigin/masterใช่ไหม?



0

คุณยังสามารถทำสิ่งนี้:

git reset --hard <commit-hash>
git push -f origin master

และให้ทุกคนที่ได้รับการอัปเดตที่ไม่ดีล่าสุด:

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