Bagaimana saya bisa memindahkan HEAD kembali ke lokasi sebelumnya? (Kepala terpisah) & Undo melakukan

179

Di Git, saya mencoba melakukan squash commitdengan menggabungkan cabang lain dan mengatur ulang HEADke tempat sebelumnya melalui:

git reset origin/master

Tapi saya harus keluar dari sini. Bagaimana saya bisa memindahkan HEAD kembali ke lokasi sebelumnya?

Saya memiliki fragmen SHA-1 ( 23b6772) dari commit yang saya perlukan untuk memindahkannya. Bagaimana saya bisa kembali ke komitmen ini?

timpone
sumber
12
KEPALA hanyalah penunjuk ke lokasi Anda saat ini (atau revisi tepatnya). git checkout 23b6772harus dilakukan.
Yaroslav Admin
Kemungkinan duplikat Revert Git repo ke komit sebelumnya
Andrew C
1
@YaroslavAdmin Tidak seharusnya tidak . Memeriksa komit secara langsung adalah alasan mengapa keadaan HEAD terlepas terjadi (karena cabang pelacak jarak jauh tidak dapat diperiksa sendiri dan secara otomatis menunda komit yang mereka tunjukkan ketika Anda mencoba melakukannya seperti OP lakukan) Juga, maaf untuk ahli nujum komentar :-) Saya agak berharap masalah awal sudah terpecahkan ...
RomainValeri

Jawaban:

397

Sebelum menjawab, mari kita tambahkan beberapa latar belakang, menjelaskan apa ini HEAD.

First of all what is HEAD?

HEADhanyalah referensi ke komit saat ini (terbaru) di cabang saat ini.
Hanya ada satu HEADpada waktu tertentu (tidak termasuk git worktree).

Konten HEADdisimpan di dalam .git/HEADdan berisi 40 byte SHA-1 dari komit saat ini.


detached HEAD

Jika Anda tidak menggunakan komit terbaru - artinya HEADmenunjuk komit sebelumnya dalam sejarah, itu disebut detached HEAD.

Masukkan deskripsi gambar di sini

Pada baris perintah, akan terlihat seperti ini - SHA-1 bukan nama cabang karena HEADtidak menunjuk ke ujung cabang saat ini:

Masukkan deskripsi gambar di sini

Masukkan deskripsi gambar di sini


Beberapa opsi tentang cara memulihkan dari HEAD yang terpisah:


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

Ini akan mengecek cabang baru yang menunjuk ke komit yang diinginkan.
Perintah ini akan checkout ke komit yang diberikan.
Pada titik ini, Anda dapat membuat cabang dan mulai bekerja sejak saat ini.

# Checkout a given commit.
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# Create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

Anda selalu dapat menggunakan itu reflogjuga.
git reflog akan menampilkan perubahan apa pun yang memperbarui HEADdan memeriksa entri reflog yang diinginkan akan mengatur HEADkembali komitmen ini.

Setiap kali KEPALA diubah akan ada entri baru di reflog

git reflog
git checkout HEAD@{...}

Ini akan membuat Anda kembali ke komit yang Anda inginkan

Masukkan deskripsi gambar di sini


git reset --hard <commit_id>

"Pindahkan" KEPALA Anda kembali ke komit yang diinginkan.

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts if you've modified things which were
# changed since the commit you reset to.
  • Catatan: ( Karena Git 2.7 ) Anda juga dapat menggunakan itu git rebase --no-autostash.

git revert <sha-1>

"Undo" rentang komit atau komit yang diberikan.
Perintah reset akan "membatalkan" setiap perubahan yang dilakukan pada komit yang diberikan.
Komit baru dengan undo patch akan dilakukan sementara komit asli akan tetap ada dalam sejarah juga.

# Add a new commit with the undo of the original one.
# The <sha-1> can be any commit(s) or commit range
git revert <sha-1>

Skema ini menggambarkan perintah mana melakukan apa.
Seperti yang Anda lihat di sana, reset && checkoutubah HEAD.

Masukkan deskripsi gambar di sini

Panduan Kode
sumber
Jika Anda tidak menggunakan komit terbaru - artinya HEAD menunjuk komit sebelumnya dalam sejarah yang disebut HEAD terlepas kecuali komit sebelumnya dalam sejarah adalah ujung cabang yang berbeda. Dalam pengalaman saya, Anda bisa mengatakan bahwa Anda terlepas jika KEPALA tidak menunjuk komit yang juga ditunjuk oleh cabang mana pun. Ini tidak berlaku untuk tag.
Tim
Anda bisa berada di KEPALA terpisah dan pada saat yang sama memiliki cabang dengan komit yang sama dengan KEPALA cabang ini. Saya tidak mengerti komentar Anda
CodeWizard
3
Saya memiliki masalah dengan penggunaan markup kode sebaris untuk judul :)
jub0bs
Tidak dapat menemukan cara yang lebih baik untuk menekankannya. merasa bebas untuk mengedit. Anda lebih dari disambut
CodeWizard
22

Melakukan

git reset 23b6772

Untuk melihat apakah Anda berada di posisi yang tepat:

git status

Anda akan melihat sesuatu

Pada master cabang Cabang Anda berada di belakang 'asal / master' sebanyak 17 komit, dan dapat diteruskan dengan cepat.

Kemudian tulis ulang riwayat di remote Anda untuk mencerminkan perubahan:

git push --force-with-lease // a useful command @oktober mentions in comments
aneh
sumber
1
JADILAH CAUTIOUS dengan git push --force. Dalam banyak situasi itu akan membuat Anda menjadi orang yang paling tidak populer di tim untuk sementara waktu ....
Kay V
untuk menambah catatan di atas, saya baru saja menemukan kutipan ini di about.gitlab.com/blog/2014/11/26/keeping-your-code-protected dan harus menambahkannya: "Satu perintah push-force git tunggal dapat dengan mudah merusak hari bagi banyak orang: [186 Jenkins] repositori memiliki kepala cabang mereka mundur untuk menunjuk ke komit yang lebih lama, dan akibatnya komit yang lebih baru salah tempat setelah git-push yang buruk. " --sangat pengembang tidak populer ....
Kay V
2
@KayV melihat git push --force-with-lease(artikel Thoughtbot: thoughtbot.com/blog/git-push-force-with- please )
oktober
1
Bendera yang berguna, @oktober, dan artikel yang bagus. Terima kasih telah menambahkannya di sini dan mem-ping saya tentang hal itu.
Kay V
1
Terima kasih! ini membantu saya membatalkan penggabungan yang buruk. karena gabungan tidak bereaksi dengan cara yang sama dengan revertkomitmen, saya mendapati diri saya dalam situasi yang sangat sulit. force-with-leasememberi saya kepercayaan diri untuk menulis ulang sejarah git dari cabang tanpa mempengaruhi pekerjaan orang lain. bravo!
anon58192932
11

Solusi tercepat yang mungkin (hanya 1 langkah)

Menggunakan git checkout -

Kamu akan lihat Switched to branch <branch_name>. Konfirmasikan itu cabang yang Anda inginkan.


Penjelasan singkat: perintah ini akan memindahkan HEAD kembali ke posisi terakhirnya. Lihat catatan tentang hasil di akhir jawaban ini.


Mnemonic: pendekatan ini sangat mirip dengan menggunakan cd -untuk kembali ke direktori yang Anda kunjungi sebelumnya. Sintaks dan kasus yang berlaku adalah kecocokan yang cukup baik (misalnya, berguna ketika Anda benar-benar ingin HEAD kembali ke tempat sebelumnya).


Solusi yang lebih metodis (2 langkah, tapi mudah diingat)

Pendekatan cepat memecahkan pertanyaan OP. Tetapi bagaimana jika situasi Anda sedikit berbeda: katakanlah Anda telah memulai ulang Bash kemudian menemukan diri Anda dengan KEPALA terlepas. Dalam hal ini, berikut adalah 2 langkah sederhana, mudah diingat.

1. Pilih cabang yang Anda butuhkan

Menggunakan git branch -v

Anda melihat daftar cabang lokal yang ada. Ambil nama cabang yang sesuai dengan kebutuhan Anda.

2. Pindahkan KEPALA untuk itu

Menggunakan git checkout <branch_name>

Kamu akan lihat Switched to branch <branch_name>. Keberhasilan!


Hasil

Dengan metode mana pun, sekarang Anda dapat terus menambahkan dan melakukan pekerjaan Anda seperti sebelumnya: perubahan Anda berikutnya akan dilacak <branch_name>.

Perhatikan bahwa keduanya git checkout -dan git checkout <branch_name>akan memberikan instruksi tambahan jika Anda telah melakukan perubahan saat HEAD dilepaskan.

Kay V
sumber
Ini tidak berfungsi karena jika saya lakukan (dengan asumsi bahwa 8acc968 adalah HEAD ~ 2) git checkout 8acc968maka git branch -vada MyBranchdalam daftar di bawah ini ... tetapi kemudian git checkout MyBranchmenghapus komentar saya.
Amuliar
Hai @amuliar - git checkout 8acc968akan memeriksa komit, bukan cabang. Jika MyBranchmemiliki komitmen yang Anda inginkan, coba git checkout MyBranch. Jika tidak berisi perubahan dalam komit 8acc968, Anda harus menggabungkan perubahan itu setelah memeriksa cabang.
Kay V
Terima kasih atas jawabannya! Saya git checkoutmelihat komit sebelumnya dan ingin kembali ke komit terbaru. Tetapi tanpa hash komit terbaru, saya cukup banyak tersesat. Solusi ini sangat cocok untuk situasi saya!
zyy
4

Pertanyaannya dapat dibaca sebagai:

Saya dalam keadaan terpisah dengan HEADdi 23b6772dan mengetik git reset origin/master(karena saya ingin squash). Sekarang saya sudah berubah pikiran, bagaimana saya bisa kembali HEADmenjadi 23b6772?

Jawaban langsungnya adalah: git reset 23b6772

Tetapi saya menjawab pertanyaan ini karena saya bosan mengetik (menyalin & menempel) melakukan hash atau singkatannya setiap kali saya ingin referensi sebelumnya HEADdan Googling untuk melihat apakah ada jenis steno.

Ternyata ada!

git reset -(atau dalam kasus saya git cherry-pick -)

Yang kebetulan sama cd -dengan kembali ke direktori saat ini di * nix! Jadi hore, saya belajar dua hal dengan satu batu.

antak
sumber
0

Ketika Anda menjalankan perintah git checkout commit_idmaka HEAD terlepas dari 13ca5593d(say commit-id)dan cabang akan tersedia lagi.

Pindah kembali ke lokasi sebelumnya jalankan langkah perintah bijak -

  1. git pull origin branch_name (katakanlah tuan)
  2. git checkout branch_name
  3. git pull origin branch_name

Anda akan kembali ke lokasi sebelumnya dengan komit yang diperbarui dari repositori jarak jauh.

Deepak Kumar
sumber
0

Hari ini, saya keliru memeriksa sebuah komit dan mulai mengerjakannya, membuat beberapa komit pada status HEAD lepas. Kemudian saya mendorong ke cabang jauh menggunakan perintah berikut:

git push origin HEAD: <My-remote-branch>

Kemudian

git checkout <My-remote-branch>

Kemudian

git pull

Saya akhirnya mendapatkan semua perubahan di cabang saya yang saya buat di HEAD lepas.

Zaid Mirza
sumber
0

Ini mungkin bukan solusi teknis, tetapi berhasil. (jika ada anggota tim Anda yang memiliki cabang yang sama di lokal)

Mari kita asumsikan nama cabang Anda sebagai branch-xxx .

Langkah-langkah untuk Memecahkan:

  • Jangan lakukan pembaruan atau tarik - tidak ada
  • Cukup buat cabang baru ( branch-yyy ) dari branch-xxx di mesinnya
  • Itu saja, semua perubahan Anda yang ada akan berada di cabang baru ini ( branch-yyy ). Anda dapat melanjutkan pekerjaan Anda dengan cabang ini.

Catatan: Sekali lagi, ini bukan solusi teknis, tetapi pasti akan membantu.

Sathish Kumar
sumber