Apa perbedaan antara "reset git" dan "checkout git"?

440

Saya selalu memikirkan git resetdan git checkoutsama, dalam arti bahwa keduanya membawa proyek kembali ke komitmen tertentu. Namun, saya merasa mereka tidak bisa persis sama, karena itu akan berlebihan. Apa perbedaan yang sebenarnya antara keduanya? Saya agak bingung, karena svn hanya svn coperlu mengembalikan komit.

TAMBAH

VonC dan Charles menjelaskan perbedaan antara git resetdan git checkoutsangat baik. Pemahaman saya saat ini adalah bahwa git resetmengembalikan semua perubahan kembali ke komit tertentu, sedangkan git checkoutkurang lebih mempersiapkan cabang. Saya menemukan dua diagram berikut cukup berguna untuk sampai pada pemahaman ini:

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

TAMBAH 3

Dari http://think-like-a-git.net/sections/rebase-from-the-ground-up/using-git-cherry-pick-to-simulate-git-rebase.html , checkout dan reset dapat ditiru rebase itu.

masukkan deskripsi gambar di sini

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

masukkan deskripsi gambar di sini

prosseek
sumber
Re: "Apakah itu salah atau terlalu disederhanakan?" Ya, diagram pertama itu menyesatkan mengenai perbedaan antara checkout dan reset. (Mungkin OK untuk -- filesvarian; Saya tidak yakin.) Diagram yang membuatnya tampak seperti perbedaan utama adalah apakah mereka mempengaruhi indeks atau WD. Lihat jawaban saya tentang itu. Diagram 2 dan 3 sangat membantu untuk melihat perbedaan nyata. Diagram ke-4 dan ke-5 berguna untuk memeriksa apakah Anda memahami apa yang dilakukan perintah-perintah ini, tetapi tidak akan benar-benar membantu Anda sampai di sana.
LarsH
Saya menemukan bagian "Lihat" dari "Git Tools Reset Demystified" untuk memberikan ringkasan yang paling membantu.
Josiah Yoder
1
prosseek: Jika Anda setuju dengan @LarsH bahwa diagram pertama menyesatkan, dapatkah Anda menghapusnya?
Josiah Yoder
Harap dicatat bahwa checkout dan reset hanya meniru bagian ke-2 rebase, dan langkah-langkah tambahan (disediakan dalam think-like-a-git.netartikel yang ditautkan ) diperlukan untuk mencegah hilangnya data.
cowlinator

Jawaban:

198
  • git resetsecara khusus tentang memperbarui indeks , memindahkan HEAD.
  • git checkoutadalah tentang memperbarui pohon kerja (ke indeks atau pohon yang ditentukan). Ini akan memperbarui KEPALA hanya jika Anda checkout cabang (jika tidak, Anda berakhir dengan KEPALA terpisah ).
    (sebenarnya, dengan Git 2.23 Q3 2019, ini akan git restore, belum tentu git checkout)

Sebagai perbandingan, karena svn tidak memiliki indeks, hanya pohon yang berfungsi, svn checkoutakan menyalin revisi yang diberikan pada direktori terpisah.
Setara lebih dekat untuk git checkoutakan:

  • svn update (jika Anda berada di cabang yang sama, artinya URL SVN yang sama)
  • svn switch (jika Anda checkout misalnya cabang yang sama, tetapi dari URL repo SVN lain)

Ketiga modifikasi pohon mereka yang bekerja ( svn checkout, update, switch) hanya memiliki satu perintah dalam git: git checkout.
Tetapi karena git juga memiliki gagasan tentang indeks ("area pementasan" antara repo dan pohon yang bekerja), Anda juga memilikinya git reset.


Thinkeye menyebutkan dalam komentarnya artikel " Reset Demystified ".

Misalnya, jika kita memiliki dua cabang, ' master' dan ' develop' menunjuk pada komit yang berbeda, dan kita saat ini sedang ' develop' (jadi HEAD menunjuk ke sana) dan kita jalankan git reset master, ' develop' itu sendiri sekarang akan menunjuk ke komit yang sama dengan yang ' master'tidak.

Di sisi lain, jika kita malah berlari git checkout master, ' develop' tidak akan bergerak, HEADitu sendiri akan. HEADsekarang akan menunjuk ke ' master'.

Jadi, dalam kedua kasus kami bergerak HEADke titik untuk berkomitmen A, tetapi bagaimana kami melakukannya sangat berbeda. resetakan memindahkan HEADtitik cabang ke, checkout bergerak HEADsendiri untuk menunjuk ke cabang lain.

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

Namun pada poin-poin tersebut:

LarsH menambahkan dalam komentar :

Namun, paragraf pertama dari jawaban ini menyesatkan: " git checkout... akan memperbarui KEPALA hanya jika Anda checkout cabang (jika tidak, Anda berakhir dengan KEPALA terpisah)".
Tidak benar: git checkoutakan memperbarui KEPALA bahkan jika Anda checkout komit yang bukan cabang (dan ya, Anda berakhir dengan KEPALA terpisah, tetapi masih diperbarui).

git checkout a839e8f updates HEAD to point to commit a839e8f.

De Novo setuju dalam komentar :

@ LarsH benar.
Peluru kedua memiliki kesalahpahaman tentang apa yang ada di HEAD akan memperbarui HEAD hanya jika Anda checkout cabang.
KEPALA pergi ke manapun Anda berada, seperti bayangan.
Memeriksa beberapa referensi non-cabang (mis., Tag), atau komit langsung, akan memindahkan HEAD. Kepala yang terlepas tidak berarti Anda telah terlepas dari KEPALA, itu berarti kepala terlepas dari referensi cabang, yang dapat Anda lihat dari, misalnya git log --pretty=format:"%d" -1,.

  • Status kepala yang dilampirkan akan dimulai dengan (HEAD ->,
  • terlepas masih akan ditampilkan (HEAD, tetapi tidak akan memiliki panah ke ref cabang.
VONC
sumber
7
Saya akan mengatakan itu git resetadalah tentang memodifikasi "label" cabang dan secara opsional memperbarui indeks atau pohon kerja sebagai efek samping. git checkoutadalah tentang memperbarui pohon kerja dan beralih cabang "terpilih" saat ini HEAD.
Mikko Rantalainen
2
@MikkoRantalainen tidak. git reset100% tentang HEAD. Ia bekerja bahkan dalam mode HEAD yang terlepas ( stackoverflow.com/a/3965714/6309 ), artinya di mana tidak ada cabang (!). git checkout juga berfungsi dalam mode HEAD terpisah, atau dapat digunakan untuk checkout SHA1 dalam mode HEAD terpisah: sekali lagi tidak ada cabang yang terlibat dalam kasus itu.
VonC
3
Bacaan lebih lanjut untuk semua jiwa yang hilang yang dikirim ke sini oleh mesin pencari, saya pikir itu layak: git-scm.com/blog/2011/07/11/reset.html
Thinkeye
2
@Thinkeye referensi yang bagus. Saya telah memasukkannya, bersama dengan ekstrak yang relevan, dalam jawaban untuk lebih banyak visibilitas.
VonC
2
Penjelasan dari Reset Demystified sangat bagus. Namun, paragraf pertama dari jawaban ini menyesatkan: "git checkout ... akan memperbarui HEAD hanya jika Anda checkout cabang (jika tidak, Anda berakhir dengan HEAD yang terlepas)". Tidak benar ... checkout git akan memperbarui KEPALA bahkan jika Anda checkout komit yang bukan cabang (dan ya, Anda berakhir dengan KEPALA terpisah, tetapi masih diperbarui). Mungkin saya salah paham apa yang Anda maksud dengan "pembaruan"? git checkout a839e8fmemperbarui KEPALA untuk menunjuk untuk melakukan a839e8f.
LarsH
67

Dalam bentuknya yang paling sederhana, resetreset indeks tanpa menyentuh pohon yang bekerja, sementara checkoutmengubah pohon yang bekerja tanpa menyentuh indeks.

Atur ulang indeks untuk mencocokkan HEAD, pohon yang bekerja dibiarkan sendirian:

git reset

Secara konseptual, ini memeriksa indeks ke pohon kerja. Agar benar-benar melakukan apa pun yang harus Anda gunakan -funtuk memaksanya untuk menimpa perubahan lokal. Ini adalah fitur keselamatan untuk memastikan bahwa bentuk "tidak ada argumen" tidak merusak:

git checkout

Setelah Anda mulai menambahkan parameter memang benar bahwa ada beberapa tumpang tindih.

checkoutbiasanya digunakan dengan cabang, tag atau komit. Dalam hal ini akan mereset HEADdan indeks ke komit yang diberikan serta melakukan checkout dari indeks ke pohon kerja.

Juga, jika Anda memasok --hardke resetAnda dapat meminta resetuntuk menimpa pohon kerja serta mengatur ulang indeks.

Jika Anda saat ini memiliki cabang yang diperiksa, ada perbedaan penting antara resetdan checkoutketika Anda memasok cabang alternatif atau komit. resetakan mengubah cabang saat ini ke titik di komit yang dipilih sedangkan checkoutakan meninggalkan cabang saat ini tetapi akan checkout cabang yang disediakan atau komit sebagai gantinya.

Bentuk lain dari resetdan commitmelibatkan jalur penyediaan.

Jika Anda memberikan jalur kepada resetAnda tidak dapat menyediakan --harddan resethanya akan mengubah versi indeks dari jalur yang disediakan ke versi di komit yang disediakan (atau HEADjika Anda tidak menentukan komit).

Jika Anda menyediakan jalur untuk checkout, seperti resetitu akan memperbarui versi indeks dari jalur yang disediakan untuk mencocokkan komit yang disediakan (atau HEAD) tetapi itu akan selalu checkout versi indeks dari jalur yang disediakan ke pohon kerja.

CB Bailey
sumber
2
Tidak benar untuk mengatakan bahwa "checkout" tidak mengubah indeks: itu mengubah ketika digunakan untuk pergi dari cabang ke yang lain.
wiki1000
Dalam bentuknya yang paling sederhana, reset me-reset indeks tanpa menyentuh pohon yang berfungsi, sementara checkout mengubah pohon yang bekerja tanpa menyentuh indeks. : Betapa membingungkannya itu: |
Aditya Gupta
41

Satu kasus penggunaan sederhana ketika mengembalikan perubahan:
1. Gunakan reset jika Anda ingin membatalkan pementasan file yang dimodifikasi.
2. Gunakan checkout jika Anda ingin membuang perubahan pada file yang tidak dipentaskan.

John Doe
sumber
1
Jawaban sempurna. Terima kasih.
user358591
11

Perbedaan utama dalam singkatnya adalah bahwa reset memindahkan referensi cabang saat ini , sementara checkouttidak (itu bergerak KEPALA).

Seperti yang dijelaskan buku Pro Git di bawah Reset Demystified ,

Hal pertama yang resetakan dilakukan adalah memindahkan apa yang HEAD tunjuk . Ini tidak sama dengan mengubah KEPALA itu sendiri (yang checkoutartinya); reset memindahkan cabang yang ditunjuk KEPALA. Ini berarti jika KEPALA diatur ke mastercabang (yaitu Anda saat ini di mastercabang), menjalankan git reset 9e5e6a4akan mulai dengan membuat mastertitik ke 9e5e6a4. [penekanan ditambahkan]

Lihat juga jawaban VonC untuk kutipan teks dan diagram yang sangat membantu dari artikel yang sama, yang tidak akan saya tiru di sini.

Tentu saja ada lebih banyak rincian tentang apa efek checkoutdan resetdapat memiliki pada indeks dan pohon bekerja, tergantung pada apa parameter yang digunakan. Mungkin ada banyak persamaan dan perbedaan antara kedua perintah. Tetapi seperti yang saya lihat, perbedaan yang paling penting adalah apakah mereka memindahkan ujung cabang saat ini.

Lars
sumber
2
Umpan balik yang bagus, selain jawaban saya yang lebih lama. +1
VonC
2

Dua perintah (reset dan checkout) sangat berbeda.

checkout X TIDAK reset --hard X

Jika X adalah nama cabang, checkout Xakan mengubah cabang saat reset --hard Xini sementara tidak.

wiki1000
sumber
2
Tetapi jika X adalah file atau folder, maka keduanya sama.
Ted Bigham
1

mnemonik singkat:

git reset HEAD           :             index = HEAD
git checkout             : file_tree = index
git reset --hard HEAD    : file_tree = index = HEAD
Филя Усков
sumber