Bagaimana saya bisa memulihkan komit yang hilang di Git?

Jawaban:

589

git reflogadalah temanmu Temukan komit yang Anda inginkan berada di daftar itu dan Anda dapat mengatur ulang untuk itu (misalnya git reset --hard e870e41:).

(Jika Anda tidak melakukan perubahan Anda ... Anda mungkin dalam kesulitan - lakukan lebih awal, dan sering lakukan!)

Amber
sumber
5
Lihatlah git log HEAD@{1}. Jika itu terlihat seperti serangkaian komit yang tepat, maka Anda bisa git reset HEAD@{1}.
Amber
4
Hanya jika kode dipentaskan (menggunakan git add), mereka disimpan dalam git dan dapat ditemukan kembali dengan mudah menggunakan perintah seperti git fsck --lost-found.
Landys
2
Tanpa sengaja menjatuhkan komit yang seharusnya saya simpan ketika rebasing. Ini benar-benar menyelamatkan saya dari mengulang beberapa jam kerja.
menyanyi
27
Ini menyelamatkan hidupku.
Lutaaya Huzaifah Idris
6
Ini menyelamatkan kewarasan saya: D
Frank Fajardo
120

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 bisa 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 dalam 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 && checkoutmodifikasi HEAD.

Masukkan deskripsi gambar di sini

Panduan Kode
sumber
2
Anda seorang pahlawan, tuan
dylanh724
4
Itu baru saja menyelamatkan saya dari banyak jam kerja. Saya menggunakan "git reflog --date = iso" untuk melihat tanggal / waktu untuk setiap entri karena saya tidak bisa memastikan tanpa cap waktu.
MetalMikester
1
bagi saya, dalam git reset --hard <commit_id>, menghapus HEADberhasil! +1 untuk representasi grafis !!.
reverie_ss
Hanya untuk menyebutkan: jika Anda tahu nama cabang: git reflog <branchname>bisa sangat berguna, karena Anda melihat perubahan hanya satu cabang.
Markus Schreiber
35

Cara lain untuk mendapatkan komit yang dihapus adalah dengan git fsckperintah.

git fsck --lost-found

Ini akan menampilkan sesuatu seperti pada baris terakhir:

dangling commit xyz

Kami dapat memeriksa bahwa itu adalah komit yang sama menggunakan reflogseperti yang disarankan dalam jawaban lain. Sekarang kita bisa melakukangit merge

git merge xyz

Catatan:
Kita tidak bisa mendapatkan komit kembali dengan fsckjika kita sudah menjalankan git gcperintah yang akan menghapus referensi ke komit menggantung.

Atri
sumber
3
Ini adalah satu-satunya jawaban yang berfungsi jika Anda belum menunjuk komit yang dimaksud, seperti ketika Anda mengambil cabang dan kemudian secara tidak sengaja mengatur ulang cabang itu di tempat lain.
TamaMcGlinn