Saya telah melihat posting menarik yang menjelaskan tentang seluk-beluk git reset
.
Sayangnya, semakin saya membaca tentang hal itu, semakin saya tidak mengerti sepenuhnya. Saya berasal dari latar belakang SVN dan Git adalah paradigma baru. Saya mudah lincah, tetapi Git jauh lebih teknis.
Saya pikir git reset
dekat hg revert
, tetapi tampaknya ada perbedaan.
Jadi apa yang sebenarnya git reset
dilakukan? Harap sertakan penjelasan terperinci tentang:
- opsi
--hard
,--soft
dan--merge
; - notasi aneh yang Anda gunakan dengan
HEAD
sepertiHEAD^
danHEAD~1
; - kasus penggunaan konkret dan alur kerja;
- konsekuensi pada copy pekerjaan,
HEAD
dan tingkat stres global Anda.
Jawaban:
Secara umum,
git reset
fungsi adalah untuk mengambil cabang saat ini dan mengatur ulang untuk menunjuk ke tempat lain, dan mungkin membawa indeks dan pohon kerja. Lebih konkretnya, jika cabang utama Anda (saat ini check out) adalah seperti ini:dan Anda menyadari bahwa Anda ingin master menunjuk ke B, bukan C, Anda akan menggunakannya
git reset B
untuk memindahkannya ke sana:Digresi: Ini berbeda dari checkout. Jika Anda menjalankan
git checkout B
, Anda akan mendapatkan ini:Anda berakhir dalam keadaan KEPALA terpisah.
HEAD
, pohon kerja, indeks semua cocokB
, tetapi cabang master tertinggal diC
. Jika Anda membuat komit baruD
pada titik ini, Anda akan mendapatkan ini, yang mungkin bukan yang Anda inginkan:Ingat, reset tidak membuat komit, itu hanya memperbarui cabang (yang merupakan pointer ke komit) untuk menunjuk ke komit yang berbeda. Sisanya hanyalah detail dari apa yang terjadi pada indeks dan pohon kerja Anda.
Gunakan kasing
Saya membahas banyak kasus penggunaan utama
git reset
dalam deskripsi saya tentang berbagai opsi di bagian selanjutnya. Ini benar-benar dapat digunakan untuk berbagai hal; benang merahnya adalah bahwa semuanya melibatkan pengaturan ulang cabang, indeks, dan / atau pohon kerja untuk menunjuk / cocok dengan komit yang diberikan.Hal-hal yang harus diperhatikan
--hard
dapat menyebabkan Anda benar-benar kehilangan pekerjaan. Ini memodifikasi pohon kerja Anda.git reset [options] commit
dapat menyebabkan Anda (semacam) kehilangan komitmen. Dalam contoh mainan di atas, kami kehilangan komitC
. Itu masih dalam repo, dan Anda dapat menemukannya dengan melihatgit reflog show HEAD
ataugit reflog show master
, tetapi sebenarnya tidak dapat diakses dari cabang apa pun lagi.Git menghapus komit seperti itu secara permanen setelah 30 hari, tetapi sampai saat itu Anda dapat memulihkan C dengan menunjuk cabang itu lagi (
git checkout C; git branch <new branch name>
).Argumen
Mengutip halaman manual, penggunaan yang paling umum adalah dari formulir
git reset [<commit>] [paths...]
, yang akan mengatur ulang jalur yang diberikan ke negara mereka dari komit yang diberikan. Jika jalur tidak disediakan, seluruh hierarki diatur ulang, dan jika komit tidak disediakan, maka akan dianggap HEAD (komit saat ini). Ini adalah pola umum di seluruh perintah git (misalnya checkout, diff, log, meskipun semantik yang tepat berbeda), jadi seharusnya tidak terlalu mengejutkan.Sebagai contoh,
git reset other-branch path/to/foo
me-reset semua yang ada di path / ke / foo ke statusnya di cabang-lain,git reset -- .
me-reset direktori saat ini ke statusnya di HEAD, dan yang sederhanagit reset
me-reset semuanya ke state-nya di HEAD.Opsi pohon pekerjaan dan indeks utama
Ada empat opsi utama untuk mengontrol apa yang terjadi pada pohon kerja Anda dan indeks selama reset.
Ingat, indeks adalah "area pementasan" git - di situlah segalanya berjalan ketika Anda mengatakan
git add
dalam persiapan untuk berkomitmen.--hard
membuat semuanya sesuai dengan komit yang telah Anda atur ulang. Mungkin ini yang paling mudah dipahami. Semua perubahan lokal Anda akan musnah. Salah satu penggunaan utama adalah membuang pekerjaan Anda tetapi tidak beralih komit:git reset --hard
berartigit reset --hard HEAD
, yaitu jangan mengubah cabang tetapi singkirkan semua perubahan lokal. Yang lain hanya memindahkan cabang dari satu tempat ke tempat lain, dan menjaga pohon indeks / kerja tetap sinkron. Ini adalah salah satu yang benar-benar dapat membuat Anda kehilangan pekerjaan, karena itu memodifikasi pohon pekerjaan Anda. Pastikan Anda ingin membuang pekerjaan lokal sebelum menjalankannyareset --hard
.--mixed
adalah default, yaitugit reset
berartigit reset --mixed
. Ini me-reset indeks, tetapi bukan pohon kerja. Ini berarti semua file Anda utuh, tetapi setiap perbedaan antara komit asli dan yang Anda setel ulang akan muncul sebagai modifikasi lokal (atau file yang tidak dilacak) dengan status git. Gunakan ini ketika Anda menyadari bahwa Anda melakukan beberapa komitmen buruk, tetapi Anda ingin mempertahankan semua pekerjaan yang telah Anda lakukan sehingga Anda dapat memperbaikinya dan berkomitmen kembali. Untuk melakukan komitmen, Anda harus menambahkan file ke indeks lagi (git add ...
).--soft
tidak menyentuh indeks atau pohon kerja. Semua file Anda masih utuh dengan--mixed
, tetapi semua perubahan munculchanges to be committed
dengan status git (mis. Diperiksa saat persiapan untuk melakukan). Gunakan ini ketika Anda menyadari bahwa Anda telah melakukan beberapa komitmen buruk, tetapi pekerjaan itu baik - semua yang perlu Anda lakukan adalah komitmen ulang secara berbeda. Indeks tidak tersentuh, sehingga Anda dapat mengkomit segera jika Anda mau - komit yang dihasilkan akan memiliki semua konten yang sama dengan di mana Anda berada sebelum Anda mengatur ulang.--merge
ditambahkan baru-baru ini, dan dimaksudkan untuk membantu Anda membatalkan penggabungan yang gagal. Ini diperlukan karenagit merge
akan benar-benar membiarkan Anda mencoba penggabungan dengan pohon kerja kotor (satu dengan modifikasi lokal) selama modifikasi tersebut ada di file yang tidak terpengaruh oleh penggabungan.git reset --merge
me-reset indeks (seperti--mixed
- semua perubahan muncul sebagai modifikasi lokal), dan me-reset file yang terpengaruh oleh penggabungan, tetapi membiarkan yang lain sendirian. Mudah-mudahan ini akan mengembalikan semuanya ke keadaan sebelum penggabungan yang buruk. Anda biasanya akan menggunakannya sebagaigit reset --merge
(artinyagit reset --merge HEAD
) karena Anda hanya ingin mengatur ulang penggabungan, tidak benar-benar memindahkan cabang. (HEAD
belum diperbarui, karena penggabungan gagal)Agar lebih konkret, misalkan Anda telah memodifikasi file A dan B, dan Anda mencoba untuk menggabungkan cabang yang memodifikasi file C dan D. Penggabungan gagal karena beberapa alasan, dan Anda memutuskan untuk membatalkannya. Anda menggunakan
git reset --merge
. Ini membawa C dan D kembali ke bagaimana mereka beradaHEAD
, tetapi membiarkan modifikasi Anda untuk A dan B sendirian, karena mereka bukan bagian dari upaya penggabungan.Ingin tahu lebih banyak?
Saya pikir
man git reset
ini benar-benar bagus untuk ini - mungkin Anda perlu sedikit merasakan cara git bekerja agar mereka benar-benar tenggelam. Khususnya, jika Anda meluangkan waktu untuk membacanya dengan cermat, tabel-tabel yang merinci status file dalam indeks dan pohon kerja untuk semua berbagai opsi dan case sangat sangat membantu. (Tapi ya, mereka sangat padat - mereka menyampaikan banyak sekali informasi di atas dalam bentuk yang sangat ringkas.)Notasi aneh
"Notasi aneh" (
HEAD^
danHEAD~1
) yang Anda sebutkan hanyalah singkatan untuk menentukan komit, tanpa harus menggunakan nama hash seperti3ebe3f6
. Itu sepenuhnya didokumentasikan di bagian "menentukan revisi" dari halaman manual untuk git-rev-parse, dengan banyak contoh dan sintaks terkait. Tanda sisipan dan tilde sebenarnya memiliki arti berbeda :HEAD~
kependekan dariHEAD~1
dan berarti orang tua pertama dari komit.HEAD~2
berarti orang tua pertama dari orang tua komit. PikirkanHEAD~n
sebagai "n melakukan sebelum KEPALA" atau "leluhur generasi ke-8 KEPALA".HEAD^
(atauHEAD^1
) juga berarti orang tua pertama dari komit.HEAD^2
berarti induk kedua komit . Ingat, komit gabungan normal memiliki dua orang tua - orang tua pertama adalah komit gabungan, dan orangtua kedua adalah komit yang digabungkan. Secara umum, penggabungan sebenarnya dapat memiliki banyak orang tua secara sewenang-wenang (gurita bergabung).^
dan~
operator dapat dirangkai, seperti dalamHEAD~3^2
, orang tua kedua dari nenek moyang generasi ketiga dariHEAD
,HEAD^^2
, induk kedua induk pertamaHEAD
, atau bahkanHEAD^^^
, yang setara denganHEAD~3
.sumber
Ingatlah bahwa di dalam
git
kamu ada:HEAD
pointer , yang memberitahu Anda apa yang berkomitmen sedang Anda kerjakanDalam meningkatkan urutan bahaya:
--soft
bergerakHEAD
tetapi tidak menyentuh area pementasan atau pohon yang bekerja.--mixed
bergerakHEAD
dan memperbarui area pementasan, tetapi bukan pohon yang berfungsi.--merge
memindahkanHEAD
, mengatur ulang area pementasan, dan mencoba untuk memindahkan semua perubahan di pohon kerja Anda ke pohon kerja baru.--hard
bergerakHEAD
dan menyesuaikan area pementasan Anda dan pohon kerja ke yang baruHEAD
, membuang semuanya.--soft
saat Anda ingin pindah ke komit lain dan menambal sesuatu tanpa "kehilangan tempat Anda". Sangat jarang Anda membutuhkan ini.-
-
Gunakan
--mixed
(yang merupakan default) ketika Anda ingin melihat hal-hal seperti apa di komit lain, tetapi Anda tidak ingin kehilangan perubahan yang sudah Anda miliki.Gunakan
--merge
saat Anda ingin pindah ke tempat baru tetapi sertakan perubahan yang sudah Anda miliki ke pohon kerja.Gunakan
--hard
untuk menghapus semuanya dan memulai daftar baru di komit baru.sumber
reset --merge
. Itu tidak melakukan penggabungan tiga arah. Ini benar-benar hanya untuk mengatur ulang dari gabungan yang bertentangan, seperti yang dijelaskan dalam dokumen. Anda ingin menggunakannyacheckout --merge
untuk melakukan apa yang Anda bicarakan. Jika Anda ingin memindahkan cabang juga, saya pikir satu-satunya cara adalah menindaklanjuti checkout / reset untuk menyeretnya.reset --merge
target apa pun selain (default)HEAD
, karena dalam kasus-kasus selain membatalkan penggabungan yang bertentangan, itu akan membuang informasi yang bisa Anda simpan.git reset
dangit reset -- .
.Posting Reset Demystified di blog Pro Git memberikan penjelasan yang sangat cerdas tentang
git reset
dangit checkout
.Setelah semua diskusi bermanfaat di bagian atas posting itu, penulis mengurangi aturan menjadi tiga langkah sederhana berikut:
sumber
Saat Anda melakukan sesuatu untuk git, pertama-tama Anda harus membuat (menambahkan indeks) perubahan Anda. Ini berarti Anda harus git menambahkan semua file yang ingin Anda sertakan dalam komit ini sebelum git menganggapnya sebagai bagian dari komit. Pertama mari kita melihat-lihat gambar repo git:
jadi, itu sederhana sekarang. Kita harus bekerja di direktori kerja, membuat file, direktori, dan semua. Perubahan ini adalah perubahan yang tidak terlacak. Untuk membuatnya dilacak, kita perlu menambahkannya ke indeks git dengan menggunakan perintah git add . Setelah mereka ditambahkan ke indeks git. Kami sekarang dapat melakukan perubahan ini, jika kami ingin mendorongnya ke git repositori.
Tapi tiba-tiba kami mengetahui sementara berkomitmen bahwa kami memiliki satu file tambahan yang kami tambahkan dalam indeks tidak diperlukan untuk mendorong repositori git. Itu berarti kita tidak ingin file itu di indeks. Sekarang pertanyaannya adalah bagaimana cara menghapus file itu dari indeks git, Karena kita menggunakan git add untuk meletakkannya dalam indeks, apakah logis menggunakan git rm ? Salah! git rm hanya akan menghapus file dan menambahkan penghapusan ke indeks. Jadi apa yang harus dilakukan sekarang:
Menggunakan:-
Ini membersihkan indeks Anda, membuat direktori kerja Anda tidak tersentuh. (cukup unstaging semuanya).
Itu dapat digunakan dengan sejumlah opsi dengannya. Ada tiga opsi utama untuk digunakan dengan git reset: --hard, --soft dan --mixed . Ini memengaruhi apa yang direset di samping pointer HEAD saat Anda mengatur ulang.
Pertama, --hard me-reset segalanya. Direktori Anda saat ini akan persis sama jika Anda telah mengikuti cabang itu selama ini. Direktori kerja dan indeks diubah ke komit itu. Ini adalah versi yang paling sering saya gunakan. git reset --hard adalah sesuatu seperti svn revert .
Selanjutnya, kebalikan total, —soft , tidak mengatur ulang pohon kerja atau indeks. Ini hanya memindahkan pointer HEAD. Ini membuat kondisi Anda saat ini dengan perubahan yang berbeda dari komit yang Anda alihkan di direktori Anda, dan "dipentaskan" untuk melakukan. Jika Anda membuat komit secara lokal tetapi belum mendorong komit ke server git, Anda dapat mengatur ulang ke komit sebelumnya, dan komit kembali dengan pesan komit yang baik.
Akhirnya, --mixed me-reset indeks, tetapi bukan pohon yang berfungsi. Jadi semua perubahan masih ada, tetapi "tidak dipentaskan" dan perlu git add'ed atau git commit -a . kita menggunakan ini kadang-kadang jika kita melakukan lebih dari yang kita maksud dengan git commit -a, kita dapat mencadangkan komit dengan git reset --mixed, tambahkan hal-hal yang ingin kita komit dan hanya komit saja.
Perbedaan antara git revert dan git reset : -
Dengan kata sederhana, git reset adalah perintah untuk "memperbaiki kesalahan yang tidak dikomit" dan git revert adalah perintah untuk "memperbaiki kesalahan yang dilakukan" .
Itu berarti jika kita telah membuat beberapa kesalahan dalam beberapa perubahan dan melakukan dan mendorong hal yang sama ke git repo, maka git revert adalah solusinya. Dan jika seandainya kita telah mengidentifikasi kesalahan yang sama sebelum mendorong / melakukan, kita dapat menggunakan git reset untuk memperbaiki masalah.
Saya harap ini akan membantu Anda untuk menghilangkan kebingungan Anda.
sumber
git reset HEAD
default?--hard
,--soft
atau--mixed
? Jawaban bagus btw.git reset --hard
akan menyebabkan Anda kehilangan beberapa data. Dan ada poin yang bisa salah (walaupun saya tidak 100% yakin ... Masih belajar!): Berbicara tentang--mixed
Anda mengatakan bahwa "kita menggunakan ini kadang-kadang jika kita melakukan lebih dari yang kita maksudkan dengan git commit -a". Apakah maksud Anda: "jika kami melakukan lebih dari yang seharusnyagit stage .
"? Jika Anda benar-benar melakukannya, saya pikir sudah terlambat (seperti yang Anda katakan di akhir, git reset adalah perintah untuk "memperbaiki kesalahan yang tidak dikomit")TL; DR
VERSI YANG LEBIH LAMA
Tapi itu jelas sederhana karena banyak jawaban yang agak bertele-tele. Lebih masuk akal bagi saya untuk membaca
git reset
dalam konteks membatalkan perubahan. Misalnya lihat ini:Dari https://www.atlassian.com/git/tutorials/undoing-changes/git-reset
dan ini
Dari https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting/commit-level-operations
sumber
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
(ataugit 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 dikomitgit reset --mixed A
(ataugit reset A
) dan Anda akan melihat barang-barang B dan C di area 'file tidak dipentaskan' siap dipindahkan ke panggung dan kemudian dilakukangit reset --hard A
dan Anda tidak akan lagi melihat perubahan B dan C di mana saja (seolah-olah tidak pernah ada)sumber
Checkout menunjuk kepala pada komit tertentu.
Setel ulang titik cabang pada komit tertentu. (Cabang adalah pointer ke komit.)
Kebetulan, jika kepala Anda tidak menunjuk ke sebuah komit yang juga ditunjuk oleh cabang maka Anda memiliki kepala yang terpisah.(Ternyata salah. Lihat komentar ...)sumber