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:
- A - B - C (HEAD, master)
dan Anda menyadari bahwa Anda ingin master menunjuk ke B, bukan C, Anda akan menggunakannya git reset B
untuk memindahkannya ke sana:
- A - B (HEAD, master) # - C is still here, but there's no branch pointing to it anymore
Digresi: Ini berbeda dari checkout. Jika Anda menjalankan git checkout B
, Anda akan mendapatkan ini:
- A - B (HEAD) - C (master)
Anda berakhir dalam keadaan KEPALA terpisah. HEAD
, pohon kerja, indeks semua cocok B
, tetapi cabang master tertinggal di C
. Jika Anda membuat komit baru D
pada titik ini, Anda akan mendapatkan ini, yang mungkin bukan yang Anda inginkan:
- A - B - C (master)
\
D (HEAD)
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 komit C
. Itu masih dalam repo, dan Anda dapat menemukannya dengan melihat git reflog show HEAD
atau git 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 sederhana git 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
berarti git 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 menjalankannya reset --hard
.
--mixed
adalah default, yaitu git reset
berarti git 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 muncul changes 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 karena git 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 sebagai git reset --merge
(artinya git 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 berada HEAD
, 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^
dan HEAD~1
) yang Anda sebutkan hanyalah singkatan untuk menentukan komit, tanpa harus menggunakan nama hash seperti 3ebe3f6
. 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 dari HEAD~1
dan berarti orang tua pertama dari komit. HEAD~2
berarti orang tua pertama dari orang tua komit. Pikirkan HEAD~n
sebagai "n melakukan sebelum KEPALA" atau "leluhur generasi ke-8 KEPALA".
HEAD^
(atau HEAD^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).
- The
^
dan ~
operator dapat dirangkai, seperti dalam HEAD~3^2
, orang tua kedua dari nenek moyang generasi ketiga dari HEAD
, HEAD^^2
, induk kedua induk pertama HEAD
, atau bahkan HEAD^^^
, yang setara dengan HEAD~3
.