ฉันจะเปลี่ยนที่เก็บ Git กลับเป็นการคอมมิชชันก่อนหน้าได้อย่างไร


7630

ฉันจะเปลี่ยนจากสถานะปัจจุบันเป็นสแน็ปช็อตที่เกิดขึ้นจากการกระทำบางอย่างได้อย่างไร

ถ้าฉันทำgit logแล้วฉันจะได้ผลลัพธ์ต่อไปนี้:

$ git log
commit a867b4af366350be2e7c21b8de9cc6504678a61b`
Author: Me <me@me.com>
Date:   Thu Nov 4 18:59:41 2010 -0400

blah blah blah...

commit 25eee4caef46ae64aa08e8ab3f988bc917ee1ce4
Author: Me <me@me.com>
Date:   Thu Nov 4 05:13:39 2010 -0400

more blah blah blah...

commit 0766c053c0ea2035e90f504928f8df3c9363b8bd
Author: Me <me@me.com>
Date:   Thu Nov 4 00:55:06 2010 -0400

And yet more blah blah...

commit 0d1d7fc32e5a947fbd92ee598033d85bfc445a50
Author: Me <me@me.com>
Date:   Wed Nov 3 23:56:08 2010 -0400

Yep, more blah blah.

ฉันจะย้อนกลับไปสู่การส่งข้อมูลได้ตั้งแต่วันที่ 3 พฤศจิกายนคือส่งมอบ0d1d7fcอย่างไร



116
นี่คือโพสต์ที่ชัดเจนและทั่วถึงเกี่ยวกับการยกเลิกสิ่งต่าง ๆ ใน git โดยตรงจาก Github
โนบิตะ

3
ที่เกี่ยวข้อง: ย้อนกลับไปที่เก่า Git กระทำใน repo โปรดทราบว่าคำถามนั้นเพิ่มข้อ จำกัด ที่ repo เป็นแบบสาธารณะ

58
ฉันรักคอมไพล์ แต่ความจริงที่ว่ามี 35 คำตอบสำหรับสิ่งที่ควรเรียบง่ายอย่างไม่น่าเชื่อทำให้เกิดปัญหาใหญ่กับคอมไพล์ หรือว่าเป็นเอกสาร
มัฟฟินแมน

2
ภาษา "กับดัก" ในการใช้คำว่าย้อนกลับเป็นความหมายที่เรียกขานเพื่อตั้งค่าไม่ได้ adress แม้ที่นี่ ??? 6594 upvotes ยังไม่ได้ทำการแก้ไขด้วยวิธีนี้เพื่อเน้นความแตกต่าง มันจะไม่สับสนมากขึ้นในการอ้างถึง "การบันทึกไฟล์" ที่นี่พร้อมกับการแสดงออก "กระทำ" ...
RomainValeri

คำตอบ:


9726

ขึ้นอยู่กับความหมายของ "ย้อนกลับ" เป็นอย่างมาก

สลับเป็นการกระทำที่แตกต่างชั่วคราว

หากคุณต้องการกลับไปที่มันชั่วคราวหลอกแล้วกลับมาที่คุณอยู่สิ่งที่คุณต้องทำคือตรวจสอบการกระทำที่ต้องการ:

# This will detach your HEAD, that is, leave you with no branch checked out:
git checkout 0d1d7fc32

หรือถ้าคุณต้องการที่จะมุ่งมั่นในขณะที่คุณอยู่ที่นั่นไปข้างหน้าและสร้างสาขาใหม่ในขณะที่คุณอยู่ที่:

git checkout -b old-state 0d1d7fc32

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

ลบคอมมิทที่ไม่ได้เผยแพร่อย่างหนัก

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

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts, if you've modified things which were
# changed since the commit you reset to.

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

เลิกทำคอมมิทที่เผยแพร่แล้วพร้อมคอมมิตใหม่

ในทางตรงกันข้ามหากคุณเผยแพร่งานคุณอาจไม่ต้องการรีเซ็ตสาขาเนื่องจากเป็นการเขียนประวัติใหม่อย่างมีประสิทธิภาพ ในกรณีนี้คุณสามารถย้อนกลับการกระทำที่แน่นอนได้ ด้วย Git การย้อนกลับมีความหมายที่เฉพาะเจาะจงมาก: สร้างคอมมิชชันด้วย reverse patch เพื่อยกเลิกมัน วิธีนี้คุณจะไม่เขียนประวัติใด ๆ

# This will create three separate revert commits:
git revert a867b4af 25eee4ca 0766c053

# It also takes ranges. This will revert the last two commits:
git revert HEAD~2..HEAD

#Similarly, you can revert a range of commits using commit hashes:
git revert a867b4af..0766c053 

# Reverting a merge commit
git revert -m 1 <merge_commit_sha>

# To get just one, you could use `rebase -i` to squash them afterwards
# Or, you could do it manually (be sure to do this at top level of the repo)
# get your index and work tree into the desired state, without changing HEAD:
git checkout 0d1d7fc32 .

# Then commit. Be sure and write a good message describing what you just did
git commit

git-revertmanpageจริงครอบคลุมจำนวนมากนี้ในรายละเอียดของ อีกประการหนึ่งการเชื่อมโยงที่เป็นประโยชน์ส่วน git-scm.com นี้ถกคอมไพล์ย้อน

หากคุณตัดสินใจว่าคุณไม่ต้องการเปลี่ยนกลับมาใช้งานคุณสามารถเปลี่ยนกลับ (ดังอธิบายที่นี่) หรือรีเซ็ตกลับเป็นก่อนเปลี่ยนกลับ (ดูหัวข้อก่อนหน้า)

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


118
ความคิดเห็นของ @ Rodในgit revert HEAD~3ฐานะที่เป็นวัดที่ดีที่สุดในการย้อนกลับการ3กระทำคือการประชุมที่สำคัญ
ซานเดรียใหม่

19
คุณช่วยเขียนจำนวนทั้งหมดได้ไหม git reset --hard 0d1d7fc32e5a947fbd92ee598033d85bfc445a50
ไลค์

16
@MathiasMadsenStav ใช่แน่นอนคุณสามารถระบุ commits โดย SHA1 แบบเต็มได้ ฉันใช้แฮชตัวย่อเพื่อให้คำตอบอ่านง่ายขึ้นและคุณก็มักจะใช้มันถ้าคุณพิมพ์ออกมา หากคุณกำลังคัดลอกและวางโดยทั้งหมดใช้แฮชแบบเต็ม ดูการระบุการแก้ไขด้วยคำสั่ง man git rev-parseสำหรับคำอธิบายแบบเต็มของวิธีที่คุณสามารถตั้งชื่อการคอมมิชชัน
Cascabel

59
คุณสามารถใช้git revert --no-commit hash1 hash2 ...และหลังจากนี้เพียงแค่กระทำการย้อนกลับทุกครั้งในหนึ่งการกระทำgit commit -m "Message"
Mirko Akov

6
'เผยแพร่' หมายถึงอะไรในบริบทนี้
Howiecamp

1849

คำตอบที่ซับซ้อนและอันตรายมากมายที่นี่ แต่จริงๆแล้วง่าย:

git revert --no-commit 0766c053..HEAD
git commit

สิ่งนี้จะเปลี่ยนทุกสิ่งจาก HEAD กลับไปเป็นแฮชการกระทำซึ่งหมายความว่ามันจะสร้างสถานะการกระทำขึ้นใหม่ในแผนผังการทำงานราวกับว่าทุกการกระทำนับตั้งแต่ที่ได้เดินกลับมา จากนั้นคุณสามารถส่งแผนผังปัจจุบันและสร้างการส่งมอบใหม่ที่เทียบเท่ากับการยอมรับที่คุณ "ย้อนกลับ" เป็น

(การ--no-commitตั้งค่าสถานะอนุญาตให้คอมไพล์ย้อนกลับการคอมมิททั้งหมดในครั้งเดียวมิฉะนั้นคุณจะได้รับข้อความแจ้งให้คอมมิทแต่ละครั้งอยู่ในช่วงทำให้ประวัติของคุณหมดไปด้วยการคอมมิทใหม่ที่ไม่จำเป็น)

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


23
หากคุณต้องการให้คอมมิทส่วนตัว (แทนที่จะคืนค่าทุกอย่างด้วยการคอมมิตครั้งใหญ่) คุณสามารถส่ง--no-editแทนได้--no-commitเพื่อที่คุณจะได้ไม่ต้องแก้ไขข้อความคอมมิชชันสำหรับการพลิกกลับแต่ละครั้ง

87
หากหนึ่งในคอมมิชชันระหว่าง 0766c053..HEAD เป็นการผสานดังนั้นจะมีข้อผิดพลาดเกิดขึ้น (โดยไม่ระบุ -m) สิ่งนี้อาจช่วยให้ผู้ที่พบเจอ: stackoverflow.com/questions/5970889/…
timhc22

7
หากต้องการดู diffs git diff --cachedก่อนที่จะกระทำการใช้งาน
John Erck

21
$ git revert --no-commit 53742ae..HEADผลตอบแทนfatal: empty commit set passed
อเล็กซ์ G

10
@AlexG นั่นเป็นเพราะคุณต้องป้อนแฮชก่อนที่คุณต้องการกลับไป ในกรณีของฉันแฮชเป็นดังนี้: 81bcc9e HEAD{0}; e475924 HEAD{1}, ...(จากgit reflog) และฉันต้องการยกเลิกสิ่งที่ฉันทำ81bcc9eจากนั้นฉันต้องทำgit revert e475924..HEAD
EpicPandaForce

1611

Rogue Coder?

ทำงานด้วยตัวเองและแค่อยากให้มันทำงาน ทำตามคำแนะนำด้านล่างพวกเขาทำงานได้อย่างน่าเชื่อถือสำหรับฉันและอื่น ๆ อีกหลายปี

ทำงานกับคนอื่น ๆ ? Git นั้นซับซ้อน อ่านความคิดเห็นด้านล่างคำตอบนี้ก่อนที่คุณจะทำอะไรที่เป็นผื่น

การคืนค่าสำเนาการทำงานเป็นข้อผูกพันล่าสุด

หากต้องการย้อนกลับไปใช้การคอมมิชชันก่อนหน้าให้ข้ามการเปลี่ยนแปลงใด ๆ :

git reset --hard HEAD

โดยที่ HEAD เป็นหน้าที่สุดท้ายในสาขาปัจจุบันของคุณ

การคืนค่าสำเนาการทำงานเป็นข้อผูกมัดที่เก่ากว่า

หากต้องการย้อนกลับไปใช้การกระทำที่เก่ากว่าการกระทำล่าสุด:

# Resets index to former commit; replace '56e05fced' with your commit code
git reset 56e05fced 

# Moves pointer back to previous HEAD
git reset --soft HEAD@{1}

git commit -m "Revert to 56e05fced"

# Updates working copy to reflect the new commit
git reset --hard

เครดิตไปที่คำถาม Stack Overflow ที่คล้ายกันเปลี่ยนกลับเป็นการกระทำโดยแฮช SHA ใน Git หรือไม่ .


33
ฉันทำอย่างนั้น แต่จากนั้นฉันไม่สามารถคอมมิทและดันไปยังที่เก็บข้อมูลรีโมต ฉันต้องการคำมั่นสัญญาเก่า ๆ ที่เฉพาะเจาะจงเพื่อที่จะได้เป็น HEAD ...
Lennon

7
มันหมายความว่าคุณได้ผลักดันในความมุ่งมั่นที่คุณต้องการคืน มันสามารถสร้างปัญหามากมายสำหรับผู้ที่ตรวจสอบรหัสของคุณและทำงานกับมัน เนื่องจากพวกเขาไม่สามารถใช้ความมุ่งมั่นของคุณได้อย่างราบรื่นเหนือพวกเขา ในกรณีดังกล่าวดีกว่ากลับ git หากคุณเป็นคนเดียวที่ใช้ repo ทำ -f คอมไพล์ผลักดัน ( แต่คิดว่าสองครั้งก่อนที่จะทำนั้น)
vinothkr

6
git reset --hard 56e05fc; git reset --soft HEAD@{1}; git commitผมแค่อยากจะชี้ให้เห็นว่าทางเลือกหนึ่งสำหรับการแก้ปัญหาการรีเซ็ตนุ่มแทนการทำรีเซ็ตผสมครั้งแรกและฮาร์ดรีเซ็ตล่าสุดที่คุณสามารถทำได้จริงการฮาร์ดรีเซ็ตแรกดังนี้

5
@ nuton linus pauling ตัวเองผู้สร้างคอมไพล์วิจารณ์ว่ามันซับซ้อนเกินไป เขาบันทึกไว้ว่าเขา "ตกใจ" คอมไพล์กลายเป็นที่นิยมเพราะความซับซ้อนของมัน
boulder_ruby

5
@boulder_ruby ฉันคิดว่าคุณหมายถึง Linus Torvalds เป็นผู้สร้างคอมไพล์ แต่ฉันคิดว่า Linus Pauling น่าจะยอมรับว่าคอมไพล์นั้นซับซ้อน
Suncat2000

215

ตัวเลือกที่ดีที่สุดสำหรับฉันและคนอื่น ๆ อาจเป็นตัวเลือกการรีเซ็ต Git:

git reset --hard <commidId> && git clean -f

นี่เป็นตัวเลือกที่ดีที่สุดสำหรับฉัน! มันง่ายรวดเร็วและมีประสิทธิภาพ!


** หมายเหตุ: ** ดังที่ได้กล่าวไว้ในความคิดเห็นอย่าทำเช่นนี้หากคุณแบ่งปันสาขาของคุณกับคนอื่น ๆ ที่มีสำเนาสัญญาเก่า

นอกจากนี้จากความคิดเห็นหากคุณต้องการวิธี 'ballzy' น้อยลงคุณสามารถใช้

git clean -i

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

7
I second @ Cupcake เตือน ... ระวังผลที่ตามมา อย่างไรก็ตามโปรดทราบว่าหากความต้องการของคุณคือการทำให้การกระทำเหล่านั้นหายไปจากประวัติศาสตร์ตลอดไปวิธีรีเซ็ต + ล้างนี้จะทำและคุณจะต้องบังคับให้สาขาที่คุณปรับเปลี่ยนกลับไปใช้รีโมตใดก็ได้
ashnazg

5
git clean -f อันตราย
Tisch

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

2
@Ade .. คุณสามารถใช้git push -fธง .. แต่ระวังมันจะแทนที่รีโมท .. ให้แน่ใจว่าคุณรู้ว่าคุณต้องการทำอะไร ..
Pogrindis

176

ก่อนที่จะตอบลองเพิ่มพื้นหลังอธิบายสิ่งนี้HEADคืออะไร

First of all what is HEAD?

HEADเป็นเพียงการอ้างอิงถึงการกระทำปัจจุบัน (ล่าสุด) ในสาขาปัจจุบัน สามารถมีได้เพียงครั้งเดียวHEADในเวลาที่กำหนด (ไม่รวมgit worktree)

เนื้อหาของHEADจะถูกเก็บไว้ภายใน.git/HEADและประกอบด้วย 40 ไบต์ SHA-1 ของการกระทำในปัจจุบัน


detached HEAD

หากคุณไม่ได้อยู่บนล่าสุดกระทำ - ความหมายที่จะชี้ไปก่อนกระทำในประวัติศาสตร์ก็เรียกว่าHEADdetached HEAD

ป้อนคำอธิบายภาพที่นี่

บนบรรทัดคำสั่งจะมีลักษณะเช่นนี้ - SHA-1 แทนชื่อสาขาเนื่องจากHEADไม่ได้ชี้ไปที่ปลายของสาขาปัจจุบัน:

ป้อนคำอธิบายภาพที่นี่


ตัวเลือกบางอย่างเกี่ยวกับวิธีการกู้คืนจาก HEAD เดี่ยว:


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

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

ณ จุดนี้คุณสามารถสร้างสาขาและเริ่มทำงานจากจุดนี้ใน:

# Checkout a given commit.
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# Create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

คุณสามารถใช้reflogเช่นกัน git reflogจะแสดงการเปลี่ยนแปลงใด ๆ ที่มีการปรับปรุงHEADและการตรวจสอบรายการ reflog ที่ต้องการจะตั้งค่าHEADกลับไปที่การกระทำนี้

ทุกครั้งที่มีการแก้ไข HEAD จะมีรายการใหม่ใน reflog

git reflog
git checkout HEAD@{...}

สิ่งนี้จะนำคุณกลับไปสู่การกระทำที่คุณต้องการ

ป้อนคำอธิบายภาพที่นี่


git reset HEAD --hard <commit_id>

"ย้าย" หัวของคุณกลับไปยังการกระทำที่ต้องการ

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts, if you've modified things which were
# changed since the commit you reset to.
  • หมายเหตุ: ( ตั้งแต่ Git 2.7 ) คุณสามารถใช้งานได้git rebase --no-autostashเช่นกัน

คีมานี้แสดงให้เห็นว่าคำสั่งใดทำอะไร ในขณะที่คุณสามารถดูมีการปรับเปลี่ยนreset && checkoutHEAD

ป้อนคำอธิบายภาพที่นี่


6
คำแนะนำที่ยอดเยี่ยมgit reflogคือสิ่งที่ฉันต้องการ
smac89

4
อุ๊ย! ทั้งหมดนี้ดูเหมือนจะซับซ้อนมาก ... ไม่มีคำสั่งง่ายๆที่จะนำคุณย้อนกลับไปในกระบวนการใช่หรือไม่ เช่นเดียวกับการเปลี่ยนจากเวอร์ชั่น 1.1 ในโปรเจ็กต์ของคุณกลับไปเป็นเวอร์ชั่น 1.0? ฉันคาดหวังบางอย่างเช่น: git stepback_one_commit หรืออะไรบางอย่าง ....
Kokodoko

มี: git reset HEAD^--hard`
CodeWizard

3
@ Kokodoko ใช่มันซับซ้อนอย่างน่ากลัว ... และเป็นตัวอย่างที่สมบูรณ์แบบของผู้เชี่ยวชาญด้านการพิจารณาเพียงเล็กน้อยที่มีให้กับผู้ที่เพิ่งเริ่มต้น โปรดอ้างอิงคำตอบของฉันที่นี่และหนังสือที่ฉันแนะนำด้วย Git ไม่ใช่สิ่งที่คุณสามารถรับได้โดยสัญชาตญาณ และฉันก็มั่นใจได้ว่า CodeWizard ไม่ได้ทำเช่นนั้น
ไมค์หนู

145

ถ้าคุณต้องการที่จะ "uncommit" ลบข้อความคอมมิทล่าสุดและทำให้ไฟล์ที่ถูกแก้ไขกลับมาเป็นสถานะเดิมคุณจะต้องใช้คำสั่ง:

git reset --soft HEAD~1
  • --softบ่งชี้ว่าไฟล์ที่ไม่มีข้อผูกมัดควรถูกเก็บไว้เป็นไฟล์ทำงานซึ่งตรงข้ามกับไฟล์--hardที่จะทิ้งไป
  • HEAD~1คือการกระทำครั้งสุดท้าย หากคุณต้องการที่จะย้อนกลับ 3 HEAD~3กระทำคุณสามารถใช้ หากคุณต้องการย้อนกลับไปยังหมายเลขการแก้ไขเฉพาะคุณสามารถทำได้โดยใช้แฮช SHA

นี่เป็นคำสั่งที่มีประโยชน์อย่างยิ่งในสถานการณ์ที่คุณยอมรับสิ่งผิดและคุณต้องการยกเลิกการกระทำครั้งสุดท้าย

ที่มา: http://nakkaya.com/2009/09/24/git-delete-last-commit/


3
นุ่มและเบา: ปลอดความเสี่ยงหากคุณไม่ได้ผลักงาน
nilsM

124

คุณสามารถทำได้โดยใช้สองคำสั่งต่อไปนี้:

git reset --hard [previous Commit SHA id here]
git push origin [branch Name] -f

มันจะลบ Git ก่อนหน้าของคุณ

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

git reset --soft [previous Commit SHA id here]

จากนั้นจะบันทึกการเปลี่ยนแปลงของคุณ


2
ฉันพยายาม 1/2 คำตอบโหลในโพสต์นี้จนกว่าฉันจะไปถึง .. คนอื่น ๆ ทั้งหมดการตั้งค่า git ของฉันให้ฉันข้อผิดพลาดเมื่อพยายามที่จะผลักดัน คำตอบนี้ใช้ได้ ขอบคุณ!
Gene Bo

รายละเอียดอย่างหนึ่งสำหรับฉันคือฉันสูญเสียความแตกต่าง .. ซึ่งฉันอยากจะดูว่าฉันได้ทำอะไรไปแล้วในความมุ่งมั่นที่ไม่ได้ผล ดังนั้นครั้งต่อไปฉันจะบันทึกข้อมูลนั้นก่อนที่จะออกคำสั่งรีเซ็ตนี้
Gene Bo

1
นี่เป็นวิธีเดียวที่ฉันจะยกเลิกการรวมที่ไม่ดีการย้อนกลับไม่ทำงานในกรณีนั้น ขอบคุณ!
Dave Cole

คำตอบที่ดีที่สุด ขอบคุณ
Imran Pollob

คำตอบที่ดีที่สุดขอบคุณ
user1394

114

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

git add . && git checkout master -f

คำอธิบายสั้น:

  • จะไม่สร้างกระทำใด ๆ ที่เป็นgit revertไม่
  • มันจะไม่ถอดหัวของคุณเหมือนที่git checkout <commithashcode>ทำ
  • มันจะแทนที่การเปลี่ยนแปลงในพื้นที่ทั้งหมดของคุณและลบไฟล์ที่เพิ่มทั้งหมดตั้งแต่การส่งครั้งล่าสุดในสาขา
  • มันใช้งานได้กับชื่อสาขาเท่านั้นดังนั้นคุณสามารถเปลี่ยนกลับเป็นการกระทำล่าสุดในสาขาด้วยวิธีนี้

ฉันพบวิธีที่สะดวกและง่ายกว่ามากในการบรรลุผลลัพธ์ข้างต้น:

git add . && git reset --hard HEAD

ที่ HEAD ชี้ไปที่การกระทำล่าสุดที่สาขาปัจจุบันของคุณ

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


83

ตกลงกลับไปที่การคอมมิชชันก่อนหน้าใน Git นั้นค่อนข้างง่าย ...

ย้อนกลับโดยไม่ทำการเปลี่ยนแปลง:

git reset --hard <commit>

ย้อนกลับด้วยการเปลี่ยนแปลง:

git reset --soft <commit>

คำอธิบาย: การใช้git resetคุณสามารถรีเซ็ตเป็นสถานะเฉพาะ เป็นเรื่องปกติที่จะใช้กับแฮชการกระทำตามที่คุณเห็นด้านบน

แต่เมื่อคุณเห็นความแตกต่างคือการใช้ค่าสถานะสองค่า--softและ--hardตามค่าเริ่มต้นgit resetโดยใช้--softค่าสถานะ แต่เป็นวิธีปฏิบัติที่ดีที่ใช้ค่าสถานะฉันอธิบายแต่ละค่าสถานะ:


--อ่อนนุ่ม

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


--hard

ระวังด้วยธงนี้ จะรีเซ็ตแผนผังการทำงานและการเปลี่ยนแปลงทั้งหมดในไฟล์ที่ถูกติดตามและทั้งหมดจะหายไป!


ฉันยังสร้างภาพด้านล่างที่อาจเกิดขึ้นในชีวิตจริงที่ทำงานกับ Git:

Git รีเซ็ตเป็นคอมมิชชัน



70

สมมติว่าคุณกำลังพูดถึงอาจารย์และสาขานั้น (ที่กล่าวว่านี่อาจเป็นสาขาการทำงานที่คุณเกี่ยวข้อง):

# Reset local master branch to November 3rd commit ID
git reset --hard 0d1d7fc32e5a947fbd92ee598033d85bfc445a50

# Reset remote master branch to November 3rd commit ID
git push -f origin 0d1d7fc32e5a947fbd92ee598033d85bfc445a50:master

ฉันพบคำตอบจากในโพสต์บล็อก (ตอนนี้ไม่มีแล้ว)

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

ดีกว่าที่จะใช้ย้อนกลับ (ดูคำตอบอื่น ๆ ) กว่าการตั้งค่าใหม่ หากคุณเป็นทีมชายคนหนึ่งก็คงไม่เป็นไร


6
คำตอบนี้แตกต่างจากจำนวนของผู้อื่นอย่างไร
Matsmath

นั่นเป็นโชคร้าย ฉันส่งอีเมลบล็อกเกอร์ - หวังว่าเขาจะยังมีมันอยู่
markreyes


2
ไวยากรณ์การพุชหายไปจากคำแนะนำอื่น ๆ ส่วนใหญ่เกี่ยวกับวิธีแก้ไขปัญหานี้ ใช้งานได้ดีมาก
jpa57

61

สมมติว่าคุณมีข้อผูกพันต่อไปนี้ในไฟล์ข้อความชื่อ~/commits-to-revert.txt(ฉันเคยgit log --pretty=onelineได้รับ)

fe60adeba6436ed8f4cc5f5c0b20df7ac9d93219
0c27ecfdab3cbb08a448659aa61764ad80533a1b
f85007f35a23a7f29fa14b3b47c8b2ef3803d542
e9ec660ba9c06317888f901e3a5ad833d4963283
6a80768d44ccc2107ce410c4e28c7147b382cd8f
9cf6c21f5adfac3732c76c1194bbe6a330fb83e3
fff2336bf8690fbfb2b4890a96549dc58bf548a5
1f7082f3f52880cb49bc37c40531fc478823b4f5
e9b317d36a9d1db88bd34831a32de327244df36a
f6ea0e7208cf22fba17952fb162a01afb26de806
137a681351037a2204f088a8d8f0db6e1f9179ca

สร้างBash shell script เพื่อย้อนกลับแต่ละสคริปต์:

#!/bin/bash
cd /path/to/working/copy
for i in `cat ~/commits-to-revert.txt`
do
    git revert $i --no-commit
done

สิ่งนี้จะเปลี่ยนทุกสิ่งกลับสู่สถานะก่อนหน้ารวมถึงการสร้างไฟล์และไดเรกทอรีและการลบส่งไปยังสาขาของคุณและคุณเก็บประวัติไว้ แต่คุณได้เปลี่ยนกลับเป็นโครงสร้างไฟล์เดียวกัน ทำไม Git ถึงไม่มีตัวgit revert --to <hash>ฉันเลย


41
คุณสามารถทำgit revert HEAD~3เพื่อลบการกระทำ 3 ครั้งล่าสุด
Rod

25
@Rod - ไม่นั่นไม่ถูกต้อง คำสั่งนั้นจะย้อนกลับการกระทำที่เป็นปู่ย่าตายายที่สามของ HEAD (ไม่ใช่การคอมมิทสามครั้งล่าสุด)
kflorence

1
@ kflorence ตกลงขอบคุณสำหรับข้อมูล จะgit revert -n master~3..master~1ทำงานอย่างไร (เท่าที่เห็นจากkernel.org/pub/software/scm/git/docs/git-revert.html )
Rod

3
@Rod - ฟังดูแล้วใช่ว่าจะเป็นไวยากรณ์ที่น่าเกลียดใช่ไหม ฉันพบการตรวจสอบคำมั่นสัญญาที่ฉันต้องการที่จะ "เปลี่ยนกลับ" เป็นและยอมรับว่าใช้งานง่ายขึ้น
kflorence

7
มีวิธีที่ง่ายกว่าในการทำเช่นนี้มากกว่าสคริปต์แบบนี้เพียงใช้git revert --no-commit <start>..<end>เพราะgit revertยอมรับช่วงการยอมรับใน Git เวอร์ชันใหม่ (หรือทั้งหมด?) โปรดทราบว่าจุดเริ่มต้นของช่วงไม่รวมอยู่ในการย้อนกลับ

58

ทางเลือกเพิ่มเติมสำหรับโซลูชั่นของ Jefromi

โซลูชั่นของ Jefromiนั้นดีที่สุดและคุณควรใช้มันอย่างแน่นอน อย่างไรก็ตามเพื่อความสมบูรณ์ฉันยังต้องการแสดงโซลูชันทางเลือกอื่น ๆ เหล่านี้ที่สามารถใช้เพื่อย้อนกลับการกระทำ (ในแง่ที่คุณสร้างการส่งมอบใหม่ที่ยกเลิกการเปลี่ยนแปลงการกระทำก่อนหน้าเช่นเดียวกับที่git revertทำ)

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

ทางเลือก 1: รีเซ็ตฮาร์ดและซอฟต์

นี่เป็นวิธีแก้ไขปัญหาของ Charles Bailey ที่ปรับเปลี่ยนเล็กน้อยเพื่อเปลี่ยนกลับไปใช้การแฮช SHA ใน Git หรือไม่ :

# Reset the index to the desired commit
git reset --hard <commit>

# Move the branch pointer back to the previous HEAD
git reset --soft HEAD@{1}

# Commit the changes
git commit -m "Revert to <commit>"

สิ่งนี้ใช้งานได้จริงโดยใช้ความจริงที่ว่าซอฟต์รีเซ็ตจะออกจากสถานะการคอมมิชชันก่อนหน้าในดัชนี / พื้นที่การแสดงซึ่งคุณสามารถคอมมิทได้

ทางเลือกที่ 2: ลบทรีปัจจุบันและแทนที่ด้วยอันใหม่

โซลูชันนี้มาจากโซลูชันของ svick ถึง Checkout การคอมมิชชันเก่าและทำการคอมมิทใหม่ :

git rm -r .
git checkout <commit> .
git commit

เช่นเดียวกันกับทางเลือก # 1 สิ่งนี้จะสร้างสถานะ<commit>ในสำเนาการทำงานปัจจุบัน มันเป็นสิ่งจำเป็นที่ต้องทำgit rmเพราะเป็นครั้งแรกจะไม่ลบไฟล์ที่ได้รับเพิ่มตั้งแต่git checkout<commit>


เกี่ยวกับทางเลือกที่ 1 คำถามด่วนหนึ่งข้อ: เมื่อทำเช่นนั้นเราจะไม่หลุดลอยระหว่างการทำใช่มั้ย
Bogac

2
@Bogac - จุดบ่งบอกถึงพา ธ ของไฟล์ในกรณีนี้คือไดเรกทอรีปัจจุบันดังนั้นจึงสันนิษฐานว่าคุณกำลังเรียกใช้จากรูทของสำเนาการทำงานของคุณ
Tom

คำเตือนซ้ำแล้วซ้ำอีกหลายครั้งในคำตอบ แต่อาจมีคนเพิ่มว่าทำไมสิ่งเหล่านี้จึงไม่ใช่วิธีที่ดีที่สุด - เปรียบเทียบgit revert HEAD~2..HEADกับโซลูชันที่เชื่อมโยงของ @ Cascabel (@ Jefromi) ฉันไม่เห็นปัญหา
Joshua Goldberg

55

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

git reset HEAD~1

ดังนั้นไม่จำเป็นต้องผูกรหัสและอื่น ๆ :)


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

1
@malhal นั่นเป็นเพราะคุณมีการเปลี่ยนแปลงที่ไม่ธรรมดา ซ่อน / รีเซ็ตพวกเขาแล้วมันจะทำงานโดยไม่มีข้อผิดพลาดนั้น
พอล Walczewski

39

มีคำสั่ง (ไม่ใช่ส่วนหนึ่งของ core Git แต่อยู่ในแพ็คเกจgit-extras ) โดยเฉพาะสำหรับการคืนค่าและการแสดงสถานะคอมมิชชันเก่า:

git back

ตามหน้า manมันสามารถใช้เช่น:

# Remove the latest three commits
git back 3

38

วิธีที่ดีที่สุดคือ:

git reset --hard <commidId> && git push --force

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

ระวังด้วย--forceแฟล็กจะลบการคอมมิตที่ตามมาทั้งหมดหลังจากการคอมมิตที่เลือกโดยไม่มีตัวเลือกในการกู้คืน


3
ทำงานเหมือนมีเสน่ห์!
Gaurav Gupta

ฉัน downvoted เพราะผมไม่เห็นว่าคำตอบของคุณให้ข้อมูลใหม่ ๆ ไม่ได้รับอยู่แล้วในตัวอย่างstackoverflow.com/a/37145089/1723886 , stackoverflow.com/a/27438379/1723886หรือstackoverflow.com/a/48756719/1723886 ในความเป็นจริงความมุ่งมั่นส่วนใหญ่แล้วพูดถึงการรีเซ็ต git - ฮาร์ดและอื่น ๆ อีกมากมายพูดถึงการใช้ - บังคับหรือ -f เพื่อผลักดัน
Alex Telon

มันทำงานได้ด้วยคำสั่งเดียวที่ชัดเจนและเรียบง่าย คุณมีอิสระที่จะโหวตคำตอบของฉันถ้าคุณไม่ชอบ
david.t_92

1
ตัวเลือกอื่นที่ควรพิจารณาสำหรับอนาคตคือการแนะนำการแก้ไขคำตอบก่อนหน้าหรือเพิ่มความคิดเห็นที่บอกว่า 'สามารถทำได้ในหนึ่งบรรทัดโดยใช้ &&' เช่น ด้วยวิธีนี้ทุกคนจึงสามารถเห็นคำตอบที่ดีขึ้นได้ในที่เดียว
Alex Telon

36

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

git push -f ...

git pushและไม่เพียง แต่


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

3
บางครั้งนี่คือสิ่งที่คุณต้องการ ตัวอย่าง: ส่งและส่งหลายรายการไปยังสาขาที่ไม่ถูกต้อง (สาขา A) หลังจากเก็บเชอร์รี่ไปที่สาขา B ฉันต้องการลบการกระทำเหล่านี้ออกจากสาขา A ฉันไม่ต้องการเปลี่ยนกลับเนื่องจากการเปลี่ยนกลับจะนำไปใช้ในภายหลังเมื่อมีการรวมสาขา A และ B เข้าด้วยกัน ทำการรีเซ็ต - ฮาร์ด <commitId> ในสาขา A แล้วตามด้วยการกดแรงจะลบการกระทำเหล่านี้ออกจากสาขาในขณะที่รักษาพวกมันไว้ในสาขา B ฉันสามารถหนีไปได้เพราะฉันรู้ว่าไม่มีใครกำลังพัฒนาในสาขา A
Doug R

ขอบคุณ! ฉันไม่สามารถหาวิธีที่จะให้สาขาระยะไกลจับคู่กับสาขาในท้องที่ของฉันได้
Mido

32

คุณสามารถทำตามขั้นตอนเริ่มต้นทั้งหมดเหล่านี้ด้วยตนเองและกลับไปที่ที่เก็บ Git

  1. ดึงที่เก็บเวอร์ชันล่าสุดของคุณจาก Bitbucket โดยใช้git pull --allคำสั่ง

  2. เรียกใช้คำสั่งบันทึก Git ด้วย-n 4จากเทอร์มินัลของคุณ จำนวนหลังจากที่-nกำหนดจำนวนของการกระทำในบันทึกเริ่มต้นจากการกระทำล่าสุดในประวัติศาสตร์ท้องถิ่นของคุณ

    $ git log -n 4
    
  3. รีเซ็ตส่วนหัวของที่เก็บประวัติของคุณโดยใช้git reset --hard HEAD~Nที่ N คือจำนวนการคอมมิทที่คุณต้องการจะนำกลับมา ในตัวอย่างต่อไปนี้ส่วนหัวจะถูกตั้งค่าหนึ่งคอมมิตกลับไปเป็นคอมมิชชันสุดท้ายในประวัติที่เก็บ:

  4. ผลักดันการเปลี่ยนแปลงไปยังที่เก็บ Git โดยใช้git push --forceเพื่อบังคับผลักดันการเปลี่ยนแปลง

ถ้าคุณต้องการที่เก็บ Git เพื่อกระทำก่อนหน้านี้:

git pull --all
git reset --hard HEAD~1
git push --force


28

เลือกการกระทำที่คุณต้องการและตรวจสอบโดย

git show HEAD
git show HEAD~1
git show HEAD~2 

จนกว่าคุณจะได้รับความมุ่งมั่นที่จำเป็น ในการทำให้ HEAD ชี้ไปที่สิ่งนั้นให้ทำ

git reset --hard HEAD~1

หรือgit reset --hard HEAD~2อะไรก็ตาม


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

2
นอกจากนี้เพื่อจะชัดเจนเทียบเท่ากับเพียงแค่ใช้git show HEAD git log HEAD -1

25

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


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


  1. คัดลอกไดเรกทอรีทั้งหมดและเรียกมันอย่างอื่นเช่น "โครงการของฉัน - คัดลอก" สมมติว่าไฟล์ที่เก็บ git ของคุณ ("repo") อยู่ภายใต้ไดเรกทอรี "my project" (ตำแหน่งเริ่มต้นสำหรับพวกเขาภายใต้ไดเรกทอรีที่ชื่อว่า ".git") คุณจะได้คัดลอกทั้งไฟล์งานและไฟล์ repo ของคุณ

  2. ทำสิ่งนี้ในไดเรกทอรี "โครงการของฉัน":

    .../my project $ git reset --hard [first-4-letters&numbers-of-commit's-SHA]
    

สิ่งนี้จะส่งคืนสถานะของ repo ภายใต้ "โครงการของฉัน" เป็นสิ่งที่คุณทำเมื่อกระทำ ("ส่ง" หมายถึงสแน็ปช็อตของไฟล์ทำงานของคุณ) กระทำทั้งหมดตั้งแต่นั้นจะหายไปตลอดกาลภายใต้ "โครงการของฉัน" แต่ ... พวกเขาจะยังคงอยู่ใน repo ภายใต้ "โครงการของฉัน - คัดลอก" ตั้งแต่คุณคัดลอกทุกไฟล์เหล่านั้น - รวมทั้งคนที่อยู่ภายใต้ ... / คอมไพล์. /

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

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

Git เป็นการสร้างที่ยอดเยี่ยม แต่ไม่มีใครสามารถ "หยิบมันขึ้นมาได้": ผู้ที่พยายามอธิบายให้ไกลเกินไปมักจะสมมติความรู้เดิมของ VCS อื่น ๆ [ระบบควบคุมเวอร์ชัน] และเจาะลึกเกินไป เร็วเกินไปและก่ออาชญากรรมอื่น ๆ เช่นการใช้คำที่ใช้แทนกันได้สำหรับ "การตรวจสอบ" - ในลักษณะที่บางครั้งการคำนวณเกือบจะทำให้สับสนสำหรับผู้เริ่มต้น

เพื่อช่วยให้คุณเครียดมากขึ้นเรียนรู้จากรอยแผลเป็นของฉัน คุณต้องสวยมากต้องอ่านหนังสือเกี่ยวกับ Git - ฉันอยากแนะนำให้"การควบคุมเวอร์ชันกับ Git" ทำมันเร็วกว่าในภายหลัง หากคุณทำเช่นนั้นโปรดจำไว้ว่าความซับซ้อนของ Git ส่วนใหญ่มาจากการแตกแขนงจากนั้นทำการ remerging: คุณสามารถข้ามส่วนเหล่านั้นในหนังสือเล่มใดก็ได้ จากคำถามของคุณมีเหตุผลที่คนควรจะทำให้ไม่เห็นคุณกับวิทยาศาสตร์ไม่มี

โดยเฉพาะอย่างยิ่งถ้าเช่นนี้เป็นสถานการณ์ที่สิ้นหวังและคุณเป็นมือใหม่กับ Git!

PS: หนึ่งความคิดอื่น ๆ : มันเป็นจริง (ตอนนี้) ค่อนข้างง่ายที่จะเก็บ repo Git ในไดเรกทอรีอื่นนอกเหนือจากที่มีไฟล์การทำงาน นี่หมายความว่าคุณไม่ต้องคัดลอกพื้นที่เก็บข้อมูล Git ทั้งหมดโดยใช้วิธีแก้ไขที่รวดเร็วและสกปรก ดูคำตอบโดยการทอดโดยใช้ที่นี่--separate-git-dir ได้รับคำเตือนแม้ว่า: หากคุณมีพื้นที่เก็บข้อมูล "ไดเรกทอรีแยก" ซึ่งคุณไม่ได้คัดลอกและคุณทำการฮาร์ดรีเซ็ตเวอร์ชันทั้งหมดที่ตามมาหลังจากการรีเซ็ตจะหายไปตลอดไปเว้นแต่คุณจะมีอย่างที่ควร สำรองที่เก็บของคุณเป็นประจำโดยเฉพาะอย่างยิ่งกับ Cloud (เช่นGoogle Drive ) ในที่อื่น ๆ

ในเรื่องของการ "สำรองข้อมูลไปยังระบบคลาวด์" นี้ขั้นตอนต่อไปคือการเปิดบัญชี (ฟรีแน่นอน) กับ GitHub หรือ (ดีขึ้นในมุมมองของฉัน) GitLab จากนั้นคุณสามารถทำgit pushคำสั่งเพื่อทำให้ Cloud repo เป็นปัจจุบัน "ถูกต้อง" แต่อีกครั้งการพูดคุยเกี่ยวกับเรื่องนี้อาจเร็วเกินไป


23

นี่เป็นอีกวิธีหนึ่งในการรีเซ็ตการกระทำล่าสุดโดยตรง

git stash
git stash clear

เป็นการล้างการเปลี่ยนแปลงทั้งหมดที่คุณทำตั้งแต่การกระทำครั้งสุดท้าย

PS: มันมีปัญหาเล็กน้อย มันยังลบสิ่งที่คุณเพิ่งเก็บการเปลี่ยนแปลงที่ซ่อนไว้ล่าสุด ซึ่งฉันเดาในกรณีส่วนใหญ่ไม่ควรสำคัญ


หมายเหตุ: ไฟล์ใหม่ที่ไม่ได้เพิ่มในดัชนีจะไม่ถูก stashed คุณได้เพิ่มพวกเขาเกินไปหรือลบด้วยตนเอง
andreyro

เหตุใดจึงต้องล้างข้อมูลสะสม นอกจากจะเป็นวิธีแก้ปัญหาแล้วยังเป็นอันตราย การอ่านประโยคแรกของคำถามทำให้โมฆะการแก้ปัญหาทันที (ซึ่งอาจเป็นประโยชน์เฉพาะในการรีเซ็ตเป็น LAST commit)
RomainValeri

22

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

git add -A .
git reset --hard HEAD

เพิ่งgit reset --hard HEADจะกำจัดการปรับเปลี่ยน แต่จะไม่กำจัดไฟล์ "ใหม่" ในกรณีของพวกเขาพวกเขาตั้งใจลากโฟลเดอร์สำคัญบางแห่งไปโดยบังเอิญและไฟล์ทั้งหมดเหล่านั้นถูกถือว่าเป็นไฟล์ใหม่โดย Git ดังนั้น a reset --hardจึงไม่สามารถแก้ไขได้ โดยการเรียกใช้git add -A .ล่วงหน้าจะมีการติดตามพวกเขาทั้งหมดอย่างชัดเจนด้วยคอมไพล์เพื่อล้างออกด้วยการรีเซ็ต


21

หากต้องการให้การเปลี่ยนแปลงจากการกระทำก่อนหน้าไปที่ HEAD และย้ายไปยังการกระทำก่อนหน้าให้ทำ:

git reset <SHA>

หากไม่ต้องการการเปลี่ยนแปลงจากการกระทำก่อนหน้านี้ต่อ HEAD และเพียงยกเลิกการเปลี่ยนแปลงทั้งหมดให้ทำ:

git reset --hard <SHA>

20

ฉันเชื่อว่าบางคนอาจมาถึงคำถามนี้ที่ต้องการทราบวิธีย้อนกลับการเปลี่ยนแปลงที่ทำไว้ในเจ้านายของพวกเขา - นั่นคือทิ้งทุกอย่างแล้วกลับไปที่จุดเริ่มต้น / ต้นแบบซึ่งในกรณีนี้ให้ทำดังนี้

git reset --hard origin/master

/superuser/273172/how-to-reset-master-to-origin-master


18

ย้อนกลับเป็นคำสั่งในการย้อนกลับการกระทำ

git revert <commit1> <commit2> 

ตัวอย่าง:

git revert 2h3h23233

สามารถรับช่วงจาก HEAD ได้ด้านล่าง ที่นี่ 1 พูดว่า "ย้อนกลับการกระทำครั้งสุดท้าย"

git revert HEAD~1..HEAD

แล้วทำ git push


14

ลองรีเซ็ตการกระทำที่ต้องการ -

git reset <COMMIT_ID>

(เพื่อตรวจสอบการใช้ COMMIT_ID git log)

การดำเนินการนี้จะรีเซ็ตไฟล์ที่ถูกเปลี่ยนทั้งหมดเป็นสถานะไม่ถูกเพิ่ม

ตอนนี้คุณสามารถcheckoutยกเลิกการเพิ่มไฟล์ได้ทั้งหมด

git checkout .

ตรวจสอบgit logเพื่อยืนยันการเปลี่ยนแปลงของคุณ

UPDATE

หากคุณมีเพียงคนเดียวและกระทำใน repo ของคุณลอง

git update-ref -d HEAD


13

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

คุณต้องนำการพัฒนาออกจากจุดเริ่มต้นก่อน :

git push origin :develop (note the colon)

จากนั้นคุณต้องพัฒนาให้อยู่ในสถานะที่คุณต้องการให้ฉันถือว่าแฮชคอมมิชชันคือ EFGHIJK:

git reset --hard EFGHIJK

สุดท้ายผลักดันการพัฒนาอีกครั้ง:

git push origin develop

13

ข้อควรระวัง! คำสั่งนี้อาจทำให้เกิดการสูญเสียประวัติการกระทำหากผู้ใช้ใส่ผิดกระทำผิดพลาด สำรองข้อมูลคอมไพล์ของคุณไว้ที่อื่นเสมอในกรณีที่คุณทำผิดพลาดกว่าคุณจะปลอดภัยกว่านิดหน่อย :)

ฉันมีปัญหาที่คล้ายกันและต้องการย้อนกลับไปใช้การยอมรับก่อนหน้านี้ Hardในกรณีของฉันฉันไม่ได้สนใจที่จะให้กระทำใหม่เพราะฉะนั้นผมใช้

นี่คือวิธีที่ฉันทำ:

git reset --hard CommitId && git clean -f

สิ่งนี้จะเปลี่ยนกลับไปที่ที่เก็บในเครื่องและที่นี่หลังจากใช้git push -fจะอัปเดตที่เก็บระยะไกล

git push -f

13

ในGitKrakenคุณสามารถทำได้:

  1. คลิกขวาที่การคอมมิตที่คุณต้องการรีเซ็ตเลือก: รีเซ็ตเป็นคอมมิชชัน / ฮาร์ด :

    ป้อนคำอธิบายภาพที่นี่

  2. คลิกขวาที่การส่งมอบอีกครั้งเลือก: ชื่อสาขาปัจจุบัน / พุช :

    ป้อนคำอธิบายภาพที่นี่

  3. คลิกที่Force Push :

    ป้อนคำอธิบายภาพที่นี่

Obs : คุณต้องระวังเพราะประวัติการกระทำหลังจากการฮาร์ดรีเซ็ตหายไปและการกระทำนี้กลับไม่ได้ คุณต้องแน่ใจในสิ่งที่คุณทำ


11

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

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