Apa perbedaan antara reset git --mixed, --soft, dan --hard?

741

Saya ingin membagi komit dan tidak yakin opsi reset mana yang digunakan.

Saya melihat halaman Dalam bahasa Inggris biasa, apa yang dilakukan "git reset"? , tapi saya sadar saya tidak terlalu mengerti apa itu indeks git atau area pementasan dan karenanya penjelasannya tidak membantu.

Juga, kasus penggunaan untuk --mixeddan --softterlihat sama dengan saya dalam jawaban itu (ketika Anda ingin memperbaiki dan komitmen kembali). Bisakah seseorang memecahnya lebih banyak? Saya sadar --mixedmungkin adalah pilihan untuk pergi, tetapi saya ingin tahu mengapa . Terakhir, bagaimana --hard?

Dapatkah seseorang memberi saya contoh alur kerja tentang bagaimana memilih 3 opsi akan terjadi?

Michael Chinen
sumber
1
Saya akan mengedit jawaban saya pada pertanyaan lain untuk mencoba dan membuatnya sedikit lebih jelas.
Cascabel
@mkarasek jawaban cukup bagus tetapi orang mungkin tertarik melihat pertanyaan ini juga.
brandizzi
3
Catatan untuk diri sendiri: Secara umum , soft: stage everything, mixed: unstage everything, hard: ignore everythinghingga komit saya ulang dari.
user1164937
Lihat juga komentar tambahan Bob Kern tentang ini
ToolmakerSteve
artikel bagus lainnya David Zychdengan penjelasan yang jelas - davidzych.com/difference-between-git-reset-soft-mixed-and-hard
src3369

Jawaban:

1489

Saat Anda memodifikasi file di repositori Anda, perubahan itu awalnya tidak dipentaskan. Untuk mengkomitnya, Anda harus mengaturnya — yaitu, menambahkannya ke indeks — menggunakan git add. Saat Anda membuat komitmen, perubahan yang dilakukan adalah yang telah ditambahkan ke indeks.

git reset perubahan, minimal, di mana cabang saat ini (HEAD ) menunjuk. Perbedaan antara --mixeddan --softapakah indeks Anda juga dimodifikasi atau tidak. Jadi, jika kita berada di cabang masterdengan serangkaian komitmen ini:

- A - B - C (master)

HEADmenunjuk ke Cdan indeks cocok C.

Ketika kami menjalankan git reset --soft B, master(dan dengan demikian HEAD) sekarang menunjuk ke B, tetapi indeks masih memiliki perubahan dariC ; git statusakan menampilkannya seperti yang dipentaskan. Jadi jika kita jalankan git commitpada titik ini, kita akan mendapatkan komit baru dengan perubahan yang sama dengan C.


Oke, jadi mulai dari sini lagi:

- A - B - C (master)

Sekarang mari kita lakukan git reset --mixed B. (Catatan: --mixedadalah opsi default). Sekali lagi, masterdan HEADarahkan ke B, tetapi kali ini indeks juga dimodifikasi agar sesuai B. Jika kita berlari git commitpada titik ini, tidak ada yang akan terjadi sejak indeks cocokHEAD . Kami masih memiliki perubahan di direktori kerja, tetapi karena mereka tidak ada dalam indeks, git statusmenunjukkannya sebagai tidak stage. Untuk mengkomitnya, Anda akan git adddan kemudian melakukan seperti biasa.


Dan akhirnya, --hardsama dengan --mixed(itu mengubah HEADindeks Anda dan), kecuali itu --hardjuga memodifikasi direktori kerja Anda. Jika kami Cmenjalankan dan menjalankan git reset --hard B, maka perubahan yang ditambahkan C, serta perubahan yang tidak dikomit yang Anda miliki, akan dihapus, dan file dalam copy pekerjaan Anda akan cocok dengan komitB . Karena Anda dapat secara permanen kehilangan perubahan dengan cara ini, Anda harus selalu menjalankan git statussebelum melakukan hard reset untuk memastikan direktori kerja Anda bersih atau bahwa Anda baik-baik saja dengan kehilangan perubahan yang tidak dikomit.


Dan akhirnya, visualisasi: masukkan deskripsi gambar di sini

mkarasek
sumber
45
Dengan kata lain, --soft membuang komit terakhir, --mix membuang komit terakhir dan tambahkan, --hard membuang komit terakhir, tambahkan dan perubahan apa pun yang Anda buat pada kode yang sama dengan git checkout KEPALA
James Wang
11
@eventualEntropy Anda dapat memulihkan perubahan yang dilakukan dengan reflog; perubahan yang tidak dikomit yang dihapus dengannya reset --hardhilang selamanya.
mkarasek
2
@Robert Tidak Juga; --mixedmengubah indeks Anda tetapi tidak direktori kerja Anda, jadi modifikasi lokal apa pun tidak terpengaruh.
mkarasek
3
Mungkin bermanfaat untuk orang-orang visual yang menggunakan git pada terminal dengan warna: 1.'git reset --soft A 'dan Anda akan melihat barang B dan C berwarna hijau (dipentaskan) 2.'git reset --mixed A' dan Anda akan lihat item B dan C berwarna merah (tidak dipentaskan) 3.'git reset --hard A 'dan Anda tidak akan lagi melihat perubahan B dan C di mana saja (akan seolah-olah tidak pernah ada)
timhc22
2
@ user1933930 1 dan 3 akan meninggalkan Anda - A - B - C′, di mana C ′ berisi perubahan yang sama seperti C (dengan cap waktu yang berbeda dan mungkin melakukan pesan). 2 dan 4 akan meninggalkan Anda - A - D, di mana D berisi perubahan gabungan B dan C.
mkarasek
216

Secara sederhana:

  • --soft: perubahan tidak berkomitmen , perubahan dibiarkan bertahap ( indeks ).
  • --mixed (default) : uncommit + unstage changes, perubahan dibiarkan dalam pohon kerja .
  • --hard: uncommit + unstage + delete changes, tidak ada yang tersisa.
Mo Ali
sumber
8
jawaban terbaik karena jawabannya menggunakan istilah teknis untuk memberikan jawaban lengkap yang juga paling ringkas
Trevor Boyd Smith
1
Ketika saya telah melakukan file (tidak dicubit) dan saya memiliki file yang belum dilacak yang baru dibuat, kemudian git reset --hard tidak melakukan apa-apa? Hanya ketika saya mem-stage file yang tidak dilacak, itu menghapusnya dari direktori kerja saya.
Michael
1
@Nikhil Bisakah Anda menjelaskan di mana jawaban ini salah?
Ned Batchelder
1
@NedBatchelder Tidak satu pun dari poin ini yang benar: Seperti uncommit tidak pernah terjadi ketika perintah ini digunakan.
Nikhil
1
@Nikhil Mungkin yang Anda maksud adalah bahwa komit asli masih ada, yang benar. Tetapi cabang telah diubah sehingga komit tidak lagi menjadi bagian dari cabang. Apakah kita sepakat tentang itu?
Ned Batchelder
69

Perlu diketahui, ini adalah penjelasan yang disederhanakan yang dimaksudkan sebagai langkah pertama untuk memahami fungsi yang rumit ini.

Semoga bermanfaat bagi pelajar visual yang ingin memvisualisasikan seperti apa keadaan proyek mereka setelah masing-masing perintah ini:


Bagi mereka yang menggunakan Terminal dengan warna dihidupkan (git config --global color.ui auto):

git reset --soft A dan Anda akan melihat barang B dan C berwarna hijau (dipentaskan dan siap untuk dikomit)

git reset --mixed A(atau git reset A) dan Anda akan melihat barang B dan C berwarna merah (tidak dipentaskan dan siap dipentaskan (hijau) dan kemudian dikomit)

git reset --hard A dan Anda tidak akan lagi melihat perubahan B dan C di mana saja (seolah-olah tidak pernah ada)


Atau bagi mereka yang menggunakan program GUI seperti 'Tower' atau 'SourceTree'

git reset --soft A dan Anda akan melihat barang B dan C di area 'file bertahap' siap untuk dikomit

git reset --mixed A(atau git reset A) dan Anda akan melihat barang-barang B dan C di area 'file tidak dipentaskan' siap dipindahkan ke panggung dan kemudian dilakukan

git reset --hard A dan Anda tidak akan lagi melihat perubahan B dan C di mana saja (seolah-olah tidak pernah ada)

timhc22
sumber
1
Ini menyesatkan, paling-paling: jawaban Anda dibaca seolah-olah git resethanya mengubah tampilan git statuskeluaran.
jub0bs
3
Saya mengerti maksud Anda, tetapi tidak setuju karena sebagai pembelajar visual, melihat bagaimana proyek saya 'terlihat' setelah menggunakan 3 perintah akhirnya membantu saya memahami apa yang mereka lakukan!
timhc22
Saya melihatnya sebagai ide 'git for dummies' untuk membantu orang memahami apa yang sebenarnya terjadi. Dapatkah Anda memikirkan bagaimana hal itu dapat ditingkatkan agar tidak menyesatkan
timhc22
8
Tidak, kami tidak perlu mengubah jawaban ini. Ini menyediakan "lembar contekan" yang berguna. Pikirkan tentang itu: lunak = hijau, campuran = merah, keras = tidak ada (berarti hilang)! Mudah diingat! Bagi para pemula yang bahkan tidak mengerti apa arti warna sebenarnya, mereka tahu terlalu sedikit tentang git, dan mereka akan mengambil pelajaran sulit di jalan, dan itu BUKAN kesalahan @unegma! BTW, saya baru saja memperbarui jawaban ini untuk mengatasi downvote sebelumnya. Kerja bagus, @unegma!
RayLuo
5
Ini berfungsi sebagai ringkasan tambahan yang bagus untuk lebih memahami pekerjaan batin ketika saya membacanya di tempat lain. Terima kasih!
spex
24

Semua jawaban yang lain yang besar, tapi saya merasa terbaik untuk memahami mereka dengan mogok file ke dalam tiga kategori: unstaged, staged, commit:

  • --hard harus mudah dimengerti, itu mengembalikan segalanya
  • --mixed (default) :
    1. unstagedfile: jangan diubah
    2. staged file: pindah ke unstaged
    3. commit file: pindah ke unstaged
  • --soft:
    1. unstagedfile: jangan diubah
    2. stagedfile: jangan diubah
    3. commit file: pindah ke staged

Singkatnya:

  • --softOpsi akan memindahkan semuanya (kecuali unstagedfile) kestaging area
  • --mixed Opsi akan memindahkan semuanya unstaged area
Hansen W
sumber
22

Berikut adalah penjelasan dasar untuk pengguna TortoiseGit:

git reset --soft dan --mixed biarkan file Anda tidak tersentuh.

git reset --hardsebenarnya mengubah file Anda agar sesuai dengan komit yang Anda atur ulang.

Dalam TortoiseGit, Konsep indeks sangat disembunyikan oleh GUI. Ketika Anda memodifikasi file, Anda tidak perlu menjalankan git adduntuk menambahkan perubahan ke area / indeks staging. Ketika hanya berurusan dengan modifikasi file yang ada yang tidak mengubah nama file, git reset --softdan --mixeditu sama! Anda hanya akan melihat perbedaan jika Anda menambahkan file baru atau mengganti nama file. Dalam hal ini, jika Anda menjalankan git reset --mixed, Anda harus menambahkan kembali file Anda dari daftar File Bukan Versi .

James Lawruk
sumber
Jawaban ini sangat tidak jelas mengenai perbedaan antara lunak dan campuran. dan bahkan meremehkan dalam menyatakannya. Jawaban berikut ini lebih jelas tentang itu. stackoverflow.com/questions/2530060/…
barlop
2
Sebagai pengguna Github Desktop yang juga memiliki perilaku yang sama, jawaban ini memberi saya beberapa alasan mengapa saya terus bingung --mixeddan --soft.
Chen Li Yong
20

Dalam kasus ini saya suka visual yang mudah-mudahan bisa menjelaskan ini:

git reset --[hard/mixed/soft] :

masukkan deskripsi gambar di sini

Jadi masing-masing efek lingkup berbeda

  1. Sulit => WorkingDir + Indeks + KEPALA
  2. Campuran => Indeks + KEPALA
  3. Soft => HEAD saja (indeks dan direktori kerja tidak berubah).
Tomer Ben David
sumber
15

Tiga jenis penyesalan

Banyak jawaban yang ada sepertinya tidak menjawab pertanyaan yang sebenarnya. Mereka adalah tentang apa yang dilakukan perintah, bukan tentang apa yang Anda (pengguna) inginkan - use case . Tapi itu yang ditanyakan OP!

Mungkin lebih bermanfaat untuk menuliskan deskripsi dalam hal apa tepatnya yang Anda sesali pada saat Anda memberi git resetperintah. Katakanlah kita punya ini:

A - B - C - D <- HEAD

Berikut adalah beberapa kemungkinan penyesalan dan apa yang harus dilakukan tentang mereka:

1. Saya menyesal bahwa B, C, dan D tidak satu komit.

git reset --soft A. Saya sekarang dapat langsung melakukan dan presto, semua perubahan sejak A adalah satu komit.

2. Saya menyesal bahwa B, C, dan D bukan sepuluh komitmen.

git reset --mixed A. Komit hilang dan indeks kembali pada A, tetapi area kerja masih terlihat seperti setelah D. Jadi sekarang saya dapat menambahkan-dan-komit dalam pengelompokan yang berbeda.

3. Saya menyesal bahwa B, C, dan D terjadi pada cabang ini ; Saya berharap saya bercabang setelah A dan mereka terjadi di cabang lain.

Buat cabang baru otherbranch, lalu git reset --hard A. Cabang saat ini sekarang berakhir pada A, denganotherbranch berasal dari itu.

(Tentu saja Anda juga bisa menggunakan hard reset karena Anda berharap B, C, dan D tidak pernah terjadi sama sekali.)

matt
sumber
5

Anda tidak perlu memaksakan diri untuk mengingat perbedaan di antara mereka. Pikirkan bagaimana Anda benar-benar membuat komit.

1. Buat beberapa perubahan.

2.git tambahkan.

3.gc -m "Saya Melakukan Sesuatu"

Lembut, Campur dan Keras adalah cara yang memungkinkan Anda untuk menghentikan operasi yang Anda lakukan dari 3 menjadi 1.

Lembut "pura-pura" untuk tidak pernah melihat Anda melakukan "gc -m".

Campur "pura-pura" untuk tidak pernah melihat Anda melakukan "git add."

Sulit "pura-pura" untuk tidak pernah melihat Anda telah membuat perubahan file.

qinmu2127
sumber
4

Sebelum masuk ke tiga opsi ini, seseorang harus memahami 3 hal.

1) Sejarah / KEPALA

2) Tahap / indeks

3) Direktori kerja

reset --soft: Riwayat berubah, KEPALA berubah, Direktori kerja tidak berubah.

reset - dicampur: Sejarah berubah, KEPALA berubah, Direktori kerja berubah dengan data tidak bertahap.

reset --hard: Riwayat berubah, KEPALA berubah, Direktori kerja diubah dengan data yang hilang.

Selalu aman untuk menggunakan Git --soft. Seseorang harus menggunakan opsi lain dalam persyaratan yang kompleks.

Suresh Sharma
sumber
3

Ada sejumlah jawaban di sini dengan kesalahpahaman tentang git reset --soft. Meskipun ada kondisi khusus di mana git reset --softhanya akan berubah HEAD(mulai dari keadaan kepala terpisah), biasanya (dan untuk penggunaan yang dimaksudkan), itu memindahkan referensi cabang yang saat ini Anda periksa. Tentu saja tidak dapat melakukan ini jika Anda tidak memiliki cabang diperiksa (maka kondisi khusus di mana git reset --softhanya akan berubah HEAD).

Saya menemukan ini sebagai cara terbaik untuk dipikirkan git reset. Anda tidak hanya bergerak HEAD( semuanya melakukan itu ), Anda juga memindahkan ref cabang , misalnya master,. Ini mirip dengan apa yang terjadi ketika Anda menjalankan git commit(cabang saat ini bergerak bersama HEAD), kecuali alih-alih membuat (dan pindah ke) komit baru , Anda pindah ke komit sebelumnya .

Inilah intinya reset , mengubah cabang menjadi sesuatu selain dari komit baru, bukan berubah HEAD. Anda dapat melihat ini dalam contoh dokumentasi:

Batalkan komit, menjadikannya cabang topik

          $ git branch topic/wip     (1)
          $ git reset --hard HEAD~3  (2)
          $ git checkout topic/wip   (3)
  1. Anda telah membuat beberapa komitmen, tetapi sadarilah bahwa itu terlalu dini untuk berada di cabang "tuan". Anda ingin terus memoles mereka di cabang topik, jadi buatlah cabang "topik / penghapusan" dari HEAD saat ini.
  2. Putar ulang cabang master untuk menyingkirkan ketiga komitmen tersebut.
  3. Beralih ke cabang "topic / wip" dan tetap bekerja.

Apa gunanya rangkaian perintah ini? Anda ingin memindahkan cabang , di sinimaster , jadi saat Anda mastercheck out, Anda larigit reset .

Jawaban pilihan teratas di sini umumnya baik, tetapi saya pikir saya akan menambahkan ini untuk memperbaiki beberapa jawaban dengan kesalahpahaman.

Ubah cabang Anda

git reset --soft <ref>: mengatur ulang penunjuk cabang untuk cabang yang saat ini diperiksa ke komit pada referensi yang ditentukan <ref>,. File dalam direktori dan indeks kerja Anda tidak berubah. Berkomitmen dari tahap ini akan membawa Anda kembali ke tempat Anda sebelumnyagit reset perintah.

Ubah indeks Anda juga

git reset --mixed <ref>

atau setara

git reset <ref>:

Apakah yang --softdilakukan DAN juga mengatur ulang indeks agar sesuai dengan komit pada referensi yang ditentukan. Sementara git reset --soft HEADtidak melakukan apa-apa (karena dikatakan memindahkan cabang yang diperiksa ke cabang yang diperiksa) git reset --mixed HEAD,, atau yang setaragit reset HEAD , adalah perintah yang umum dan berguna karena mengatur ulang indeks ke keadaan komit terakhir Anda.

Ubah direktori kerja Anda juga

git reset --hard <ref>: melakukan apa yang --mixeddilakukan DAN juga menimpa direktori kerja Anda. Perintah ini mirip dengan git checkout <ref>, kecuali bahwa (dan ini adalah poin penting tentang reset) semua bentuk git resetgerakan yang HEADditunjuk oleh ref cabang .

Catatan tentang "perintah ini dan itu menggerakkan HEAD":

Tidak berguna untuk mengatakan perintah memindahkan file HEAD. Perintah apa pun yang mengubah posisi Anda di riwayat komit Anda akan memindahkan perintah HEAD. Itulah yang HEAD adalah , pointer ke mana pun Anda berada. HEADadalah Anda , dan akan bergerak kapan pun Anda melakukannya.

De Novo
sumber
2
"Memindahkan ref cabang": poin bagus. Saya harus memperbarui stackoverflow.com/a/5203843/6309 .
VonC
1

Jawaban singkat dalam konteks apa 3 opsi digunakan:

Untuk menyimpan perubahan saat ini dalam kode tetapi untuk menulis ulang riwayat komit:

  • soft: Anda dapat mengkomit semuanya sekaligus dan membuat komit baru dengan deskripsi baru (jika Anda menggunakan torotise git atau sebagian besar GUI lainnya, ini yang digunakan, karena Anda masih dapat mencentang file mana yang Anda inginkan dalam komit dan membuat banyak melakukan itu dengan file yang berbeda. Dalam Sourcetree semua file akan dipentaskan untuk komit.)
  • mixed: Anda harus menambahkan masing-masing file lagi ke indeks sebelum Anda membuat komitmen (di Sourcetree semua file yang diubah tidak akan dipentaskan)

Untuk benar-benar kehilangan perubahan dalam kode juga:

  • hard: Anda tidak hanya menulis ulang riwayat tetapi juga kehilangan semua perubahan sampai ke titik yang Anda atur ulang
Nickpick
sumber
Saya tidak mendapatkan lunak dan campuran dalam hal ini. Jika Anda harus berkomitmen, lalu apa yang dikembalikan? apakah Anda melakukan pengembalian, atau memperbarui perubahan (jadi kembali ke keadaan semula?)
John Little
Menyetujui kembali perubahan. Tidak akan ada komit terbalik.
Nickpick
1

Perbedaan mendasar antara berbagai opsi perintah git reset adalah seperti di bawah ini.

  • --soft: Hanya menyetel ulang HEAD ke komit yang Anda pilih. Bekerja pada dasarnya sama dengan checkout git tetapi tidak membuat status kepala terpisah.
  • --mixed (opsi default): Mereset HEAD ke komit yang Anda pilih di riwayat dan membatalkan perubahan dalam indeks.
  • --hard: Mengembalikan HEAD ke komit yang Anda pilih di kedua riwayat, membatalkan perubahan dalam indeks, dan membatalkan perubahan di direktori kerja Anda.
Wisnu Abhyankar
sumber
1

--soft: Memberitahu Git untuk menyetel ulang HEAD ke komit lain, jadi indeks dan direktori kerja tidak akan diubah dengan cara apa pun. Semua file yang diubah antara KEPALA asli dan komit akan dipentaskan.

--mixed: Sama seperti soft, ini akan mengatur ulang HEAD ke komit lain. Ini juga akan mengatur ulang indeks agar sesuai dengan itu sementara direktori kerja tidak akan disentuh. Semua perubahan akan tetap di direktori kerja dan muncul sebagai diubah, tetapi tidak dipentaskan.

--hard: Ini me-reset segalanya - me-reset HEAD kembali ke komit lain, me-reset indeks untuk mencocokkannya, dan me-reset direktori kerja untuk mencocokkannya juga.

Perbedaan utama antara --mixeddan --softapakah indeks Anda juga dimodifikasi. Periksa lebih lanjut tentang ini di sini .

Nesha Zoric
sumber
0

Jawaban mkarasek luar biasa, dalam istilah sederhana dapat kita katakan ...

  • git reset --soft : mengatur HEAD ke komit yang dimaksudkan tetapi pertahankan perubahan Anda dari komitmen terakhir
  • git reset --mixed : sama dengan git reset --soft tetapi satu-satunya perbedaan adalah un stage perubahan Anda dari komit terakhir
  • git reset --hard: setel Anda HEADdi komit yang Anda tentukan dan setel ulang semua perubahan Anda dari komit terakhir termasuk perubahan komit.
Vivek Maru
sumber