อะไรคือความแตกต่างระหว่าง“ รีเซ็ต git” และ“ เช็คเอาต์ git”?


440

ฉันคิดถึงgit resetและgit checkoutเหมือนเดิมเสมอในแง่ที่ว่าทั้งสองนำโครงการกลับสู่การกระทำที่เฉพาะเจาะจง อย่างไรก็ตามฉันรู้สึกว่าพวกเขาไม่สามารถเหมือนกันอย่างแน่นอนซึ่งจะซ้ำซ้อน ความแตกต่างที่แท้จริงระหว่างสองคืออะไร ฉันสับสนเล็กน้อยเนื่องจาก svn มีเพียงsvn coการย้อนกลับการกระทำ

ADDED

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

http://a.imageshack.us/img651/1559/86421927.png http://a.imageshack.us/img801/1986/resetr.png

เพิ่ม 3

จากhttp://think-like-a-git.net/sections/rebase-from-the-ground-up/using-git-cherry-pick-to-simulate-git-rebase.html การชำระเงินและการรีเซ็ตสามารถเลียนแบบได้ rebase

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

git checkout bar 
git reset --hard newbar 
git branch -d newbar 

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



Re: "มันผิดหรือง่ายเกินไป?" ใช่แผนภาพแรกนั้นทำให้เข้าใจผิดเกี่ยวกับความแตกต่างระหว่างการชำระเงินและการรีเซ็ต (มันอาจจะโอเคเกี่ยวกับชุด-- filesรูปแบบ: ฉันไม่แน่ใจ) แผนภาพนั้นทำให้ดูเหมือนความแตกต่างหลักคือว่าพวกเขาส่งผลกระทบต่อดัชนีหรือ WD ดูคำตอบของฉันเกี่ยวกับเรื่องนั้น ไดอะแกรมที่ 2 และ 3 มีประโยชน์มากสำหรับการเห็นความแตกต่างที่แท้จริง แผนภาพที่ 4 และ 5 มีประโยชน์ในการตรวจสอบว่าคุณเข้าใจสิ่งที่คำสั่งเหล่านี้ทำ แต่จะไม่ช่วยให้คุณไปถึงที่นั่นจริงๆ
LarsH

ฉันพบส่วน"ตรวจสอบ"ของ "เครื่องมือรีเซ็ต Git Demystified" เพื่อให้ข้อมูลสรุปที่เป็นประโยชน์ที่สุด
Josiah Yoder

1
prosseek: หากคุณเห็นด้วยกับ @LarsH ว่าไดอะแกรมแรกนั้นทำให้เข้าใจผิดคุณสามารถลบออกได้ไหม
Josiah Yoder

โปรดทราบว่าการเช็คเอาต์และรีเซ็ตจะเลียนแบบส่วนที่ 2 ของการรีบูตเท่านั้นและthink-like-a-git.netจำเป็นต้องมีขั้นตอนเพิ่มเติม (ให้ไว้ในบทความที่เชื่อมโยง) เพื่อป้องกันการสูญหายของข้อมูล
cowlinator

คำตอบ:


198
  • git resetเป็นเรื่องเกี่ยวกับการอัพเดตดัชนีโดยเฉพาะการย้าย HEAD
  • git checkoutเกี่ยวกับการอัพเดตแผนผังการทำงาน (เป็นดัชนีหรือแผนผังที่ระบุ) มันจะอัปเดต HEAD เฉพาะเมื่อคุณชำระเงินที่สาขา (หากไม่ใช่คุณจะได้รับHEAD ที่แยกออกมา )
    (อันที่จริงแล้วด้วย Git 2.23 ไตรมาสที่ 3 ปี 2019 สิ่งนี้จะgit restoreไม่จำเป็นgit checkout)

โดยการเปรียบเทียบเนื่องจาก svn ไม่มีดัชนีมีเพียงแผนผังการทำงานเท่านั้นที่svn checkoutจะคัดลอกการแก้ไขที่กำหนดในไดเรกทอรีแยก
ยิ่งใกล้git checkoutจะ:

  • svn update (หากคุณอยู่ในสาขาเดียวกันหมายถึง URL SVN เดียวกัน)
  • svn switch (ถ้าคุณชำระเงินสำหรับอินสแตนซ์สาขาเดียวกัน แต่มาจาก URL repo SVN อื่น)

ทุกคนทำงานสามการปรับเปลี่ยนต้นไม้ ( svn checkout, update, switch) git checkoutมีเพียงหนึ่งคำสั่งในการคอมไพล์:
แต่เนื่องจากคอมไพล์ยังมีแนวคิดของดัชนี (นั่นคือ "พื้นที่จัดเตรียม" ระหว่าง repo และแผนผังการทำงาน) คุณก็มีgit resetเช่นกัน


Thinkeyeกล่าวถึงในความคิดเห็นของบทความ " รีเซ็ต Demystified "

ตัวอย่างเช่นหากเรามีสองสาขา ' master' และ ' develop' ชี้ไปที่การกระทำที่แตกต่างกันและขณะนี้เราอยู่ที่ ' develop' (ดังนั้นหัวหน้าจึงชี้ไปที่มัน) และเราเรียกใช้git reset master' develop' ตัวเองจะชี้ไปที่การกระทำเดียวกัน ' master' ทำ.

ในทางกลับกันถ้าเราวิ่งแทนgit checkout master' develop' จะไม่เคลื่อนไหวHEADตัวเองจะทำ HEADตอนนี้จะชี้ไปที่ ' master'

ดังนั้นในทั้งสองกรณีเรากำลังHEADจะชี้ไปที่กระทำAแต่วิธีการที่เราทำนั้นแตกต่างกันมาก resetจะย้ายHEADคะแนนของสาขาไปที่เช็คเอาต์จะย้ายHEADไปที่สาขาอื่น

http://git-scm.com/images/reset/reset-checkout.png

ในประเด็นเหล่านั้นแม้ว่า:

LarsHเพิ่มในความคิดเห็น :

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

git checkout a839e8f updates HEAD to point to commit a839e8f.

De Novoเห็นด้วยในความคิดเห็น :

@ LarsH ถูกต้อง
สัญลักษณ์แสดงหัวข้อย่อยที่สองมีความเข้าใจผิดเกี่ยวกับสิ่งที่อยู่ในหัวจะปรับปรุงหัวเมื่อคุณชำระเงินสาขา
หัวไปทุกที่ที่คุณอยู่เช่นเงา
การตรวจสอบการอ้างอิงที่ไม่ใช่สาขา (เช่นแท็ก) หรือการกระทำโดยตรงจะย้าย HEAD git log --pretty=format:"%d" -1หัวเดี่ยวไม่ได้หมายความว่าคุณได้ออกจากหัวก็หมายความว่าศีรษะถูกถอดออกจากโทษสาขาซึ่งคุณสามารถดูจากตัวอย่างเช่น

  • หัวที่แนบมารัฐจะเริ่มต้นด้วย(HEAD ->,
  • แยกออกจะยังคงแสดง(HEADแต่จะไม่มีลูกศรไปที่การอ้างอิงสาขา

7
ฉันจะบอกว่าgit resetเป็นเรื่องเกี่ยวกับการปรับเปลี่ยน "ฉลาก" ของสาขาและเลือกที่จะอัปเดตดัชนีหรือแผนผังการทำงานเป็นผลข้างเคียง git checkoutเป็นเรื่องเกี่ยวกับการอัปเดตแผนผังการทำงานและการสลับในขณะนี้ "เลือก" สาขา ( HEAD)
Mikko Rantalainen

2
@MikkoRantalainen ไม่ git resetเป็น 100% HEADเกี่ยวกับ มันทำงานได้แม้ในโหมด HEAD ที่แยกออกมา ( stackoverflow.com/a/3965714/6309 ) ซึ่งหมายถึงที่ที่ไม่มีสาขา (!) git checkout ยังทำงานในโหมด HEAD ที่แยกออกมาหรือสามารถใช้ในการเช็กเอาต์ SHA1 ในโหมด HEAD ที่แยกออกมา: ไม่มีสาขาเกี่ยวข้องในกรณีนั้นอีก
VonC

3
อ่านเพิ่มเติมสำหรับวิญญาณที่หลงหายทั้งหมดที่ส่งมาที่นี่โดยเครื่องมือค้นหาฉันคิดว่ามันคุ้มค่า: git-scm.com/blog/2011/07/11/reset.html
Thinkeye

2
@Thinkeye อ้างอิงที่ดี ฉันได้รวมไว้พร้อมกับสารสกัดที่เกี่ยวข้องในคำตอบสำหรับการมองเห็นเพิ่มเติม
VonC

2
คำอธิบายจากรีเซ็ต Demystified นั้นยอดเยี่ยม ย่อหน้าแรกของคำตอบนี้แม้ว่าจะทำให้เข้าใจผิด: "การชำระเงิน git ... จะอัปเดต HEAD เฉพาะเมื่อคุณชำระเงินสาขา (ถ้าไม่ใช่คุณจะจบด้วย HEAD ที่แยกออก)" ไม่เป็นความจริง ... การชำระเงิน git จะอัปเดต HEAD แม้ว่าคุณจะชำระเงินการกระทำที่ไม่ใช่สาขา (และใช่คุณท้ายด้วย HEAD ที่แยกออกมา แต่ก็ยังได้รับการอัปเดต) บางทีฉันอาจเข้าใจผิดว่าคุณหมายถึงอะไรโดย "อัพเดท"? git checkout a839e8fHEAD a839e8fการปรับปรุงไปยังจุดที่จะกระทำ
LarsH

67

ในรูปแบบที่ง่ายที่สุดresetรีเซ็ตดัชนีโดยไม่ต้องสัมผัสแผนผังการทำงานในขณะที่checkoutเปลี่ยนแผนผังการทำงานโดยไม่ต้องสัมผัสดัชนี

รีเซ็ตดัชนีเพื่อให้ตรงกับHEADทรีที่ทำงานอยู่คนเดียว:

git reset

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

git checkout

เมื่อคุณเริ่มเพิ่มพารามิเตอร์มันเป็นความจริงว่ามีบางอย่างทับซ้อนกัน

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

นอกจากนี้หากคุณ--hardให้resetคุณสามารถขอresetให้เขียนทับแผนผังการทำงานรวมถึงการรีเซ็ตดัชนี

หากปัจจุบันคุณมีสาขาที่ตรวจสอบออกมีความแตกต่างที่สำคัญระหว่างresetและcheckoutเมื่อคุณจัดหาสาขาอื่นหรือกระทำ resetจะเปลี่ยนสาขาปัจจุบันให้ชี้ไปที่การกระทำที่เลือกขณะที่checkoutจะออกจากสาขาปัจจุบันเพียงอย่างเดียว แต่จะชำระเงินที่สาขาที่ให้มาหรือกระทำแทน

รูปแบบอื่น ๆresetและcommitเกี่ยวข้องกับเส้นทางการจัดหา

หากคุณระบุเส้นทางไปยังresetคุณไม่สามารถจัดหาได้--hardและresetจะเปลี่ยนเฉพาะรุ่นดัชนีของเส้นทางที่ให้มาเป็นเวอร์ชันในการส่งที่มอบให้ (หรือHEADถ้าคุณไม่ระบุการส่งมอบ)

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


2
มันไม่จริงที่จะบอกว่า "เช็คเอาต์" ไม่เปลี่ยนดัชนี: มันเปลี่ยนไปเมื่อใช้เพื่อเปลี่ยนจากสาขาหนึ่งไปยังอีกสาขาหนึ่ง
wiki1000

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

41

กรณีการใช้งานอย่างง่ายหนึ่งกรณีเมื่อคืนค่าการเปลี่ยนแปลง:
1. ใช้การรีเซ็ตหากคุณต้องการเลิกทำการจัดเตรียมไฟล์ที่ถูกแก้ไข
2. ใช้การชำระเงินถ้าคุณต้องการยกเลิกการเปลี่ยนแปลงไฟล์ / s


1
คำตอบที่สมบูรณ์แบบ ขอบคุณ.
358591

11

ความแตกต่างที่สำคัญในสรุปคือการreset ย้ายอ้างอิงสาขาปัจจุบันในขณะที่checkoutไม่ได้ (มันย้ายหัว)

ในฐานะที่เป็นหนังสือ Pro Git อธิบายภายใต้การรีเซ็ต Demystified ,

สิ่งแรกที่resetจะทำคือจุดย้ายสิ่งที่มุ่งหน้าไปยัง สิ่งนี้ไม่เหมือนกับการเปลี่ยน HEAD เอง (ซึ่งเป็นสิ่งที่checkoutทำ); reset ย้ายสาขาที่ HEAD ชี้ไป ซึ่งหมายความว่าถ้าหัวถูกตั้งค่าเป็นmasterสาขา (เช่นคุณกำลังในmasterสาขา) วิ่งgit reset 9e5e6a4จะเริ่มต้นด้วยการชี้ไปที่master 9e5e6a4[เน้นเพิ่ม]

ดูคำตอบของ VonC สำหรับข้อความที่เป็นประโยชน์และแผนภาพที่ตัดตอนมาจากบทความเดียวกันซึ่งฉันจะไม่ทำซ้ำที่นี่

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


2
ข้อเสนอแนะที่ดีนอกเหนือจากคำตอบเก่าของฉัน +1
VonC

2

คำสั่งสองคำสั่ง (รีเซ็ตและเช็คเอาต์) แตกต่างอย่างสิ้นเชิง

checkout X ไม่ใช่ reset --hard X

ถ้า X เป็นชื่อสาขา checkout Xจะเปลี่ยนสาขาปัจจุบันในขณะที่reset --hard Xจะไม่


2
แต่ถ้า X เป็นไฟล์หรือโฟลเดอร์แสดงว่ามันเหมือนกัน
Ted Bigham

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