Pertama, mari kita perjelas apa itu HEAD dan apa artinya ketika itu dilepaskan.
HEAD adalah nama simbolis untuk komit yang sedang diperiksa. Ketika KEPALA tidak terlepas (situasi "normal" 1 : Anda memiliki cabang diperiksa), KEPALA sebenarnya menunjuk ke "ref" cabang dan cabang menunjuk ke komit. Dengan demikian, KEPALA “dilampirkan” ke cabang. Saat Anda membuat komit baru, cabang yang ditunjuk HEAD diperbarui untuk menunjukkan komit baru. KEPALA mengikuti secara otomatis karena hanya menunjuk ke cabang.
git symbolic-ref HEAD
hasil refs/heads/master
Cabang bernama "master" diperiksa.
git rev-parse refs/heads/master
yield 17a02998078923f2d62811326d130de991d1a95a
Komit adalah ujung atau "kepala" saat ini dari cabang master.
git rev-parse HEAD
juga menghasilkan 17a02998078923f2d62811326d130de991d1a95a
Ini adalah apa artinya menjadi "ref simbolik". Itu menunjuk ke suatu objek melalui beberapa referensi lain.
(Rujukan simbol pada awalnya diimplementasikan sebagai tautan simbolik, tetapi kemudian diubah menjadi file biasa dengan interpretasi ekstra sehingga dapat digunakan pada platform yang tidak memiliki symlink.)
Kami memiliki HEAD
→ refs/heads/master
→17a02998078923f2d62811326d130de991d1a95a
Ketika HEAD dilepaskan, itu menunjuk langsung ke sebuah komit — bukannya secara tidak langsung menunjuk satu melalui cabang. Anda dapat menganggap KEPALA lepas sebagai cabang yang tidak disebutkan namanya.
git symbolic-ref HEAD
gagal dengan fatal: ref HEAD is not a symbolic ref
git rev-parse HEAD
imbal hasil 17a02998078923f2d62811326d130de991d1a95a
Karena ini bukan referensi simbolis, ia harus menunjuk langsung ke komit itu sendiri.
Kami punya HEAD
→17a02998078923f2d62811326d130de991d1a95a
Yang penting untuk diingat dengan HEAD terpisah adalah bahwa jika komit itu menunjuk sebaliknya direferensikan (tidak ada referensi lain yang bisa mencapainya), maka itu akan menjadi "menggantung" ketika Anda checkout beberapa komit lainnya. Akhirnya, komitmen yang menggantung seperti itu akan dipangkas melalui proses pengumpulan sampah (secara default, mereka disimpan setidaknya selama 2 minggu dan dapat disimpan lebih lama dengan direferensikan oleh reflog HEAD).
1
Tidak apa-apa untuk melakukan pekerjaan "normal" dengan KEPALA terpisah, Anda hanya perlu melacak apa yang Anda lakukan untuk menghindari memancing sejarah yang hilang dari reflog.
Langkah menengah rebase interaktif dilakukan dengan KEPALA terpisah (sebagian untuk menghindari mencemari reflog cabang aktif). Jika Anda menyelesaikan operasi rebase penuh, itu akan memperbarui cabang asli Anda dengan hasil kumulatif operasi rebase dan pasang kembali HEAD ke cabang asli. Dugaan saya adalah bahwa Anda tidak pernah sepenuhnya menyelesaikan proses rebase; ini akan membuat Anda dengan KEPALA lepas yang menunjuk ke komit yang baru saja diproses oleh operasi rebase.
Untuk pulih dari situasi Anda, Anda harus membuat cabang yang menunjuk ke komit yang saat ini ditunjuk oleh KEPALA Anda yang terlepas:
git branch temp
git checkout temp
(dua perintah ini dapat disingkat git checkout -b temp
)
Ini akan memasang kembali KEPALA Anda ke temp
cabang baru .
Selanjutnya, Anda harus membandingkan komit saat ini (dan riwayatnya) dengan cabang normal tempat Anda diharapkan bekerja:
git log --graph --decorate --pretty=oneline --abbrev-commit master origin/master temp
git diff master temp
git diff origin/master temp
(Anda mungkin ingin bereksperimen dengan opsi log: tambahkan -p
, tinggalkan --pretty=…
untuk melihat seluruh pesan log, dll.)
Jika temp
cabang baru Anda terlihat bagus, Anda mungkin ingin memperbarui (misalnya) master
untuk mengarahkannya:
git branch -f master temp
git checkout master
(dua perintah ini dapat disingkat git checkout -B master temp
)
Anda kemudian dapat menghapus cabang sementara:
git branch -d temp
Akhirnya, Anda mungkin ingin mendorong sejarah yang dibangun kembali:
git push origin master
Anda mungkin perlu menambahkan --force
ke akhir perintah ini untuk mendorong jika cabang jauh tidak dapat "fast-forwarded" ke komit baru (yaitu Anda menjatuhkan, atau menulis ulang beberapa komit yang ada, atau menulis ulang sedikit sejarah).
Jika Anda berada di tengah-tengah operasi rebase, Anda mungkin harus membersihkannya. Anda dapat memeriksa apakah rebase sedang dalam proses dengan mencari direktori .git/rebase-merge/
. Anda dapat secara manual membersihkan rebase yang sedang berlangsung dengan hanya menghapus direktori itu (mis. Jika Anda tidak lagi mengingat tujuan dan konteks operasi rebase aktif). Biasanya Anda akan menggunakan git rebase --abort
, tetapi itu melakukan beberapa pengaturan ulang ekstra yang mungkin ingin Anda hindari (memindahkan HEAD kembali ke cabang asli dan mengatur ulang kembali ke komit asli, yang akan membatalkan beberapa pekerjaan yang kami lakukan di atas).