Perbaiki kepala terpisah Git?

1455

Saya melakukan beberapa pekerjaan di repositori saya dan melihat ada file yang memiliki perubahan lokal. Saya tidak ingin mereka lagi jadi saya menghapus file, berpikir saya bisa checkout salinan baru. Saya ingin melakukan yang setara dengan Git

svn up .

Penggunaan git pulltampaknya tidak berhasil. Beberapa pencarian acak menuntun saya ke situs tempat seseorang merekomendasikan untuk melakukannya

git checkout HEAD^ src/

( srcadalah direktori yang berisi file yang dihapus).

Sekarang saya tahu saya memiliki kepala yang terpisah. Saya tidak tahu apa itu. Bagaimana saya bisa membatalkan?

Daniel
sumber
69
git checkout masterakan membuat Anda kembali di cabang utama. Jika Anda ingin menghapus semua perubahan copy pekerjaan, Anda mungkin ingin melakukannya git reset --hard.
Abe Voelker
jika Anda belum berkomitmen Anda bisa melakukannyagit checkout -- src/
musim panas
Coba ini: tautan . Singkatnyacreate temp branch - checkout temp branch - checkout master - delete temp branch
fidev
@AbeVoelker Apa maksud Anda dalam komentar working copy changes? Apakah Anda merujuk pada perubahan yang Anda buat ke file setelah memeriksa komit lain (yaitu, perubahan yang Anda buat saat dalam kondisi head terpisah)?
Minh Tran

Jawaban:

2148

Kepala yang terlepas berarti Anda tidak lagi berada di cabang, Anda telah memeriksa satu komit dalam sejarah (dalam hal ini komit sebelum HEAD, yaitu HEAD ^).

Jika Anda ingin menghapus perubahan yang terkait dengan HEAD yang terlepas

Anda hanya perlu checkout cabang tempat Anda berada, mis

git checkout master

Lain kali Anda telah mengubah file dan ingin mengembalikannya ke status di indeks, jangan hapus file terlebih dahulu, lakukan saja

git checkout -- path/to/foo

Ini akan mengembalikan file foo ke status dalam indeks.

Jika Anda ingin menyimpan perubahan yang terkait dengan HEAD yang terlepas

  1. Jalankan git branch tmp- ini akan menyimpan perubahan Anda di cabang baru yang disebut tmp.
  2. Lari git checkout master
  3. Jika Anda ingin memasukkan perubahan yang Anda buat master, jalankan git merge tmpdari mastercabang. Anda harus berada di mastercabang setelah berlari git checkout master.
ralphtheninja
sumber
6
"Ini akan mengembalikan file foo ke keadaan sebelum kamu membuat perubahan apa pun padanya." -> itu akan mengembalikannya ke keadaan dalam indeks - silakan edit
Mr_and_Mrs_D
88
Mengapa kesalahan ini terjadi sejak awal? Ini adalah salah satu hal yang saya benci untuk git - perilaku yang benar-benar acak di kali. Tidak pernah memiliki masalah dengan Mercurial.
Violet Giraffe
97
@VioletGiraffe Ini bukan kesalahan atau sesuatu yang acak - ini hanyalah keadaan repositori Anda ketika Anda checkout komit sebelumnya. "Kepala Terpisah" berfungsi sebagai peringatan bahwa Anda mungkin juga ingin membuat atau menunjuk ke cabang jika Anda ingin melakukan pekerjaan apa pun dari titik itu. Tetapi jika Anda hanya ingin melihat tag atau komit itu, tidak ada yang salah dengan berada dalam kondisi kepala terpisah.
Neil Neyman
22
Jangan lakukan ini jika Anda berkomitmen pada kepala yang terpisah, lihat jawaban lain. Jika ya, Anda dapat checkout head git sebelumnya diPrevious HEAD position was 7426948...
KCD
9
@VioletGiraffe: Anda memiliki model mental tentang apa yang terjadi berdasarkan Mercurial, tetapi Anda menggunakan Git. Jika Anda tidak mau menyesuaikan model mental Anda agar sesuai dengan model Git, maka segala sesuatu akan terus tampak acak. Ini seperti Anda berjalan di luar dengan kacamata VR menyala, dan Anda pikir Anda menerbangkan pesawat tetapi Anda benar-benar menyeberang jalan. Anda akan tertabrak mobil.
iconoclast
477

Jika Anda telah mengubah file yang tidak ingin hilang, Anda bisa mendorongnya. Saya telah mengkomitnya dalam mode terpisah dan setelah itu Anda dapat pindah ke cabang sementara untuk diintegrasikan kemudian di master.

git commit -m "....."
git branch my-temporary-work
git checkout master
git merge my-temporary-work

Diekstrak dari:

Apa yang harus dilakukan dengan komit dibuat di kepala yang terpisah

Toni Gamez
sumber
27
Saya menemukan ini menjadi solusi yang lebih disukai - terutama jika Anda ingin menyimpan perubahan yang Anda buat ketika Anda memeriksa versi individu.
adswebwork
10
@ adswebwork: Saya setuju. Semua jawaban lain menyarankan kembali ke keadaan sebelumnya dan kehilangan perubahan yang dibuat secara lokal di kondisi kepala terpisah.
Sk8erPeter
6
mengapa tidak git stash? Karena itu adalah hal pertama yang muncul di pikiran saya. membuat cabang baru akan menjadi kerja keras.
musim panas
2
Anda juga bisa git rebase my-temporary-workdan kemudian menghapus cabang git branch -d my-temporary-worksehingga tampak seolah-olah Anda berkomitmen untuk cabang yang tepat di tempat pertama.
Zoltán
@geekay git stashkedengarannya seperti alat yang sempurna untuk kasus ini. Bisakah Anda menulis jawaban dengan langkah-langkah yang disarankan untuk mencapai itu?
Zoltán
157

Solusi tanpa membuat cabang sementara.

Cara keluar ("fix") terlepas dari status HEAD ketika Anda telah mengubah sesuatu dalam mode ini dan, secara opsional, ingin menyimpan perubahan Anda:

  1. Komit perubahan yang ingin Anda pertahankan. Jika Anda ingin mengambil alih salah satu perubahan yang Anda buat dalam status HEAD yang terlepas, lakukan itu. Suka:

    git commit -a -m "your commit message"
    
  2. Buang perubahan yang tidak ingin Anda simpan. Hard reset akan membuang semua perubahan yang tidak dikomit yang Anda buat dalam status HEAD terpisah:

    git reset --hard
    

    (Tanpa ini, langkah 3 akan gagal, mengeluh tentang modifikasi file yang tidak dikomit di HEAD terpisah.)

  3. Lihatlah cabang Anda. Keluar dari status HEAD yang terlepas dengan memeriksa cabang tempat Anda bekerja sebelumnya, misalnya:

    git checkout master
    
  4. Ambil alih komitmen Anda. Anda sekarang dapat mengambil alih komit yang Anda buat dalam keadaan HEAD terpisah dengan memetik ceri, seperti yang ditunjukkan dalam jawaban saya untuk pertanyaan lain .

    git reflog
    git cherry-pick <hash1> <hash2> <hash3> …
    
tanius
sumber
The git reset --hardadalah persis itu yang saya butuhkan, karena saya ingin hulu menjadi sumber dan perubahan lokal harus dihapus.
Markus Zeller
Jawaban yang bagus, ini berhasil bagi saya
MGLondon
130

Kepala terpisah berarti:

  1. Anda tidak lagi di cabang,
  2. Anda telah memeriksa satu komit dalam riwayat

Jika Anda tidak memiliki perubahan: Anda dapat beralih ke master dengan menerapkan perintah berikut

  git checkout master

Jika Anda memiliki perubahan yang ingin Anda pertahankan:

Jika HEAD terlepas, komit berfungsi seperti biasa, kecuali tidak ada cabang bernama yang diperbarui. Untuk mendapatkan cabang master diperbarui dengan perubahan yang dilakukan, buat cabang sementara di tempat Anda berada (dengan cara ini cabang sementara akan memiliki semua perubahan yang dilakukan pada HEAD yang dilepaskan), kemudian beralih ke cabang master dan gabungkan cabang sementara dengan tuan.

git branch  temp
git checkout master
git merge temp
Razan Paul
sumber
2
sempurna, kemudian setelah menghapus temp cabang
Davi Menezes
64

Inilah yang baru saja saya lakukan setelah saya menyadari bahwa saya berada di kepala yang terpisah dan telah membuat beberapa perubahan.

Saya melakukan perubahan.

$ git commit -m "..."
[detached HEAD 1fe56ad] ...

Saya ingat hash (1fe56ad) dari commit. Kemudian saya memeriksa cabang yang seharusnya.

$ git checkout master
Switched to branch 'master'

Akhirnya saya menerapkan perubahan komit ke cabang.

$ git cherry-pick 1fe56ad
[master 0b05f1e] ...

Saya pikir ini sedikit lebih mudah daripada membuat cabang sementara.

Philippe Gerber
sumber
2
Ini seharusnya jawabannya. Ini akan mengembalikan file nuked Anda.
BlindWanderer
2
Ya, ini benar-benar hal paling sederhana untuk dilakukan - cukup sederhana untuk diingat tanpa mencari di web saat itu terjadi. Komit, catat hash, kembali ke cabang yang ingin Anda komit, dan git cherry-pick <hash>.
Mason
Terima kasih atas solusinya. Ini membantu. Bolehkah saya juga menambahkan bahwa saya harus melakukan "git push origin master" sehingga master dan asal / master saya menunjuk ke komit yang sama.
turnip424
1
Ini pada dasarnya adalah jawaban tanius (diposting lebih dari setahun sebelumnya).
Peter Mortensen
Terima kasih pick yang ceria ini, kembalikan perubahan kepala lepas yang terakhir
Omega Cube
55

Jika Anda melakukan beberapa perubahan dan kemudian menyadari bahwa Anda berada di kepala yang terpisah, ada solusi sederhana untuk itu: simpanan -> checkout master -> simpanan pop:

git stash
git checkout master   # Fix the detached head state
git stash pop         # Or for extra safety use 'stash apply' then later 
                      #   after fixing everything do 'stash drop'

Anda akan memiliki perubahan tanpa komitmen dan KEPALA "terlampir" yang normal, seperti tidak ada yang terjadi.

Mojuba
sumber
2
Telah mem-bookmark anak nakal ini - menghemat membuat cabang temp. Berhasil memperlakukan.
Tim Tyler
1
Saya sering berakhir dalam keadaan KEPALA yang terpisah setelah memeriksa submodule git, kemudian mengubahnya. Saya menemukan bahwa ini adalah solusi terbaik dan termudah untuk memperbaiki masalah sehingga saya dapat mempertahankan perubahan saya.
user5359531
1
Ini tidak berfungsi jika Anda telah melakukan perubahan dalam kondisi terpisah?
Danijel
40

Ketika Anda memeriksa komit tertentu git, Anda berakhir dalam keadaan kepala terpisah ... yaitu, copy pekerjaan Anda tidak lagi mencerminkan keadaan referensi yang dinamai (seperti "master"). Ini berguna untuk memeriksa status repositori masa lalu, tetapi bukan yang Anda inginkan jika Anda benar-benar mencoba mengembalikan perubahan.

Jika Anda telah membuat perubahan pada file tertentu dan Anda hanya ingin membuangnya, Anda dapat menggunakan checkoutperintah seperti ini:

git checkout myfile

Ini akan membuang perubahan yang tidak dikomit dan mengembalikan file ke status apa pun yang ada di kepala cabang Anda saat ini. Jika Anda ingin membuang perubahan yang sudah Anda lakukan, Anda mungkin ingin menggunakan resetperintah. Sebagai contoh, ini akan mengatur ulang repositori ke keadaan dari komit sebelumnya, membuang semua perubahan selanjutnya:

git reset --hard HEAD^

Namun, jika Anda berbagi repositori dengan orang lain, a git resetdapat mengganggu (karena menghapus sebagian dari sejarah repositori). Jika Anda sudah berbagi perubahan dengan orang lain, Anda biasanya ingin melihatnya git revertsebagai gantinya, yang menghasilkan "antikomit" - artinya, membuat komit baru yang "membatalkan" perubahan yang dimaksud.

Buku Git memiliki detail lebih lanjut.

larsks
sumber
1
Seperti yang saya katakan di jawaban @ ralphtheninja, git checkout path/to/foobisa bertentangan dengan git checkout some-branch, jadi akan lebih baik digunakan git checkout -- path/to/foountuk menghindari konflik ini.
Diego Lago
30

KEPALA ada di pointer, dan sebagai hasilnya itu menunjuk - langsung atau tidak langsung - ke komit tertentu:

  HEAD Terlampir berarti terpasang ke beberapa cabang (yaitu menunjuk ke cabang). HEAD
terlepas berarti bahwa ia tidak dilampirkan ke cabang mana pun, yaitu menunjuk langsung ke beberapa komit.

masukkan deskripsi gambar di sini

Dengan kata lain:

  • Jika menunjuk ke komit secara langsung , KEPALA terlepas .
  • Jika menunjuk ke komit secara tidak langsung , (yaitu menunjuk ke cabang, yang pada gilirannya menunjuk ke komit), HEAD dilampirkan .

Untuk lebih memahami situasi dengan HEAD yang terpasang / terlepas, mari tunjukkan langkah-langkah yang mengarah ke quadruplet gambar di atas.

Kita mulai dengan keadaan repositori yang sama (gambar di semua kuadran adalah sama):

masukkan deskripsi gambar di sini


Sekarang kami ingin melakukan git checkout- dengan target berbeda di masing-masing gambar (perintah di atasnya redup untuk menekankan bahwa kami hanya akan menerapkan perintah itu):

masukkan deskripsi gambar di sini


Ini adalah situasi setelah melakukan perintah-perintah itu:

masukkan deskripsi gambar di sini

Seperti yang Anda lihat, poin KEPALA ke sasaran dari git checkoutperintah - ke cabang (pertama 3 gambar dari quadruplet), atau (langsung) ke komit (gambar terakhir dari quadruplet yang).

Isi direktori kerja juga diubah, agar sesuai dengan komit yang sesuai (snapshot), yaitu dengan komit menunjuk (langsung atau tidak langsung) oleh HEAD.


Jadi kita sekarang berada dalam situasi yang sama seperti pada awal jawaban ini:

masukkan deskripsi gambar di sini

MarianD
sumber
6
Tidak membacanya, tetapi memilih gambar-gambar cantik yang Anda buat;).
Carlo Wood
@Carlo, terima kasih!
MarianD
22

Karena "kondisi kepala terpisah" membuat Anda menggunakan temp temp, gunakan saja git checkout -yang menempatkan Anda pada cabang terakhir yang Anda gunakan .

Mike
sumber
1
hati-hati, Anda akan kehilangan komitmen yang Anda buat saat berada di kondisi kepala yang terpisah.
Ajak6
@ Ajak6 Kamu tidak kehilangan komitmen itu. Mereka masih tersedia melalui git reflogdan dapat diambil alih ke cabang baru atau melalui git cherry-pickcabang yang sudah ada. Lihat pertanyaan ini .
tanius
7

Untuk lebih memperjelas jawaban @Philippe Gerber, ini dia:

git cherry-pick

Sebelumnya cherry-pick, a git checkout masterdiperlukan dalam kasus ini. Selain itu, hanya dibutuhkan dengan commitin detached head.

Timo
sumber
6

Tambahan

Jika cabang yang ingin Anda kembalikan adalah checkout terakhir yang Anda buat, Anda bisa menggunakannya checkout @{-1}. Ini akan membawa Anda kembali ke checkout sebelumnya.

Lebih lanjut, Anda bisa menggunakan perintah ini dengan, misalnya, git global --config alias.prevsehingga Anda hanya perlu mengetik git prevuntuk beralih kembali ke checkout sebelumnya.

David Brower
sumber
4

Berada di "kepala terpisah" berarti bahwa KEPALA mengacu pada komit tertentu yang tidak disebutkan namanya (sebagai lawan dari cabang bernama) (lih: https://git-scm.com/docs/git-checkout bagian Kepala terpisah ) Kepala terpisah

Untuk memperbaiki masalah, Anda hanya perlu memilih cabang yang dipilih sebelumnya oleh

git checkout @{-1}

Menepuk. ANDRIA
sumber
2

Ketika Anda berada dalam situasi kepala terpisah dan membuat file baru, pertama pastikan bahwa file-file baru ini ditambahkan ke indeks, misalnya dengan:

git add .

Tetapi jika Anda hanya mengubah atau menghapus file yang ada, Anda dapat menambahkan (-a) dan melakukan dengan pesan (-m) secara bersamaan melalui:

git commit -a -m "my adjustment message"

Kemudian Anda cukup membuat cabang baru dengan status Anda saat ini dengan:

git checkout -b new_branch_name

Anda akan memiliki cabang baru dan semua penyesuaian Anda akan ada di cabang baru itu. Anda kemudian dapat terus mendorong ke remote dan / atau checkout / pull / merge sesuka hati.

DZet
sumber
1

Git mengatakan kepada saya bagaimana melakukannya.

jika Anda mengetik:

git checkout <some-commit_number>

Simpan status

git add .
git commit -m "some message"

Kemudian:

 git push origin HEAD:<name-of-remote-branch>
Sterling Diaz
sumber
1

Saya ingin menjaga perubahan saya jadi, saya hanya memperbaiki ini melakukan ...

git add .
git commit -m "Title" -m "Description"
(so i have a commit now example: 123abc)
git checkout YOURCURRENTBRANCH
git merge 123abc
git push TOYOURCURRENTBRANCH

itu bekerja untuk saya

CRLZXO
sumber
1

Biasanya HEADmenunjuk ke cabang. Ketika itu tidak menunjuk ke cabang sebaliknya ketika menunjuk ke hash komit seperti 69e51itu berarti Anda memiliki KEPALA terpisah. Anda harus menunjuk dua cabang untuk memperbaiki masalah. Anda dapat melakukan dua hal untuk memperbaikinya.

  1. git checkout other_branch // Tidak mungkin ketika Anda membutuhkan kode di komit itu hash
  2. buat cabang baru dan arahkan hash komit ke cabang yang baru dibuat.

KEPALA harus menunjuk ke cabang, bukan hash komit adalah aturan emas.

Krishnadas PC
sumber
ini sebabnya saya memiliki kesalahan ini. Saya memeriksa revisi dan kemudian memeriksa kembali ke revisi saat ini / terbaru alih-alih memeriksa ke cabang, yang akan memasang kepala dengan benar. Terima kasih untuk bantuannya.
Rahul Thakur
1

Kepala terpisah berarti Anda belum memeriksa cabang Anda dengan benar atau Anda baru saja memeriksa satu komit.

Jika Anda mengalami masalah seperti itu, pertama-tama simpanan perubahan lokal Anda sehingga Anda tidak akan kehilangan perubahan Anda.

Setelah itu ... checkout cabang yang Anda inginkan menggunakan perintah:

Katakanlah Anda ingin cabang MyOriginalBranch:

git checkout -b asal beberapaNama / MyOriginalBranch

Dhirendra Gautam
sumber
1

Anda mungkin melakukannya git reset --hard origin/your-branch .

Coba saja git checkout your-branch

Johnny Cage
sumber
0
git pull origin master

bekerja untukku. Itu hanya tentang memberi nama jarak jauh dan cabang secara eksplisit.

Amjedonline
sumber
0

Dalam kasus saya, saya lari git status dan saya melihat bahwa saya memiliki beberapa file yang tidak terlacak pada direktori kerja saya.

Saya hanya perlu membersihkannya (karena saya tidak membutuhkannya) untuk menjalankan rebase yang ingin saya lakukan.

falsarella
sumber
0

Ini berfungsi untuk saya, Ini akan menugaskan cabang baru untuk kepala terpisah:

git checkout new_branch_name detached_head_garbage_name

Alok Gupta
sumber
0

KEPALA yang terlepas berarti bahwa Anda saat ini tidak berada di cabang mana pun. Jika Anda ingin MENJAGA perubahan Anda saat ini dan cukup membuat cabang baru, inilah yang Anda lakukan:

git commit -m "your commit message"
git checkout -b new_branch

Setelah itu, Anda berpotensi ingin menggabungkan cabang baru ini dengan cabang lain. Selalu membantu adalah perintah git "seekor anjing" :

git log --all --decorate --oneline --graph
gebbissimo
sumber