Bagaimana menemukan file yang dihapus dalam riwayat komit proyek?

1275

Sekali waktu, ada file di proyek saya yang sekarang ingin saya dapatkan.

Masalahnya adalah: Saya tidak tahu kapan saya menghapusnya dan di jalur mana itu.

Bagaimana saya bisa menemukan komit file ini ketika ada?

Pedro Rolo
sumber
Pertanyaan serupa di sini: stackoverflow.com/questions/7093602/…
eckes
3
Kemungkinan duplikat Find ketika sebuah file dihapus di Git
Dan Dascalescu
13
Jawaban di sini lebih bermanfaat bagi saya daripada jawaban di duplikat .
Felipe Alvarez
5
setuju ... terlepas dari duplikat ... mereka tidak muncul dalam pencarian Google .... yang ini ... saya harap kita akan berhenti membuang waktu mengejar duplikat ... hanya waktu dan algoritma google yang akan katakan pertanyaan mana yang terbaik.
Tim Boland

Jawaban:

1601

Jika Anda tidak tahu jalur yang tepat yang dapat Anda gunakan

git log --all --full-history -- "**/thefile.*"

Jika Anda tahu path tempat file itu berada, Anda dapat melakukan ini:

git log --all --full-history -- <path-to-file>

Ini akan menampilkan daftar commit di semua cabang yang menyentuh file itu. Kemudian, Anda dapat menemukan versi file yang Anda inginkan, dan menampilkannya dengan ...

git show <SHA> -- <path-to-file>

Atau kembalikan ke copy pekerjaan Anda dengan:

git checkout <SHA>^ -- <path-to-file>

Perhatikan simbol tanda kurir ( ^), yang mendapatkan checkout sebelum yang diidentifikasi, karena pada saat <SHA>melakukan file dihapus, kita perlu melihat komit sebelumnya untuk mendapatkan konten file yang dihapus itu

Amber
sumber
2
Coba gunakan jalur relatif alih-alih jalur absolut (jika belum).
Amber
63
Bagaimana jika Anda tidak tahu jalan yang sebenarnya? Yang Anda tahu adalah nama file?
priestc
17
@PedroMorteRolo tidak git log -- <path>akan memiliki output ketika Anda berada di cabang di mana file tidak pernah ada. Anda harus selalu menggunakan git log --all -- <path>, untuk memastikan Anda tidak ketinggalan perubahan yang terjadi di cabang lain. Perintah git log -- <path>ini bisa sangat berbahaya jika Anda memiliki lebih dari satu cabang dan cenderung melupakan jalur dan cabang (seperti saya) dan juga berbahaya jika Anda bekerja dengan pengembang lain.
Hobs
4
@Amber, pertimbangkan untuk menambahkan --all(terima kasih Philip ) ke git logjawaban Anda , sehingga orang tidak ketinggalan perubahan dan file di cabang lain. Itu akan menyelamatkan orang-orang pelupa seperti saya banyak kesedihan.
Hobs
3
Seperti yang dinyatakan dalam jawaban di bawah ini, mengembalikan file seharusnya git checkout <SHA>^ -- <path-to-file>(perhatikan simbol ^), karena pada saat <SHA> komit file dihapus, kita perlu melihat komit sebelumnya untuk mendapatkan konten file yang dihapus
kipelovets
393

Dapatkan daftar file yang dihapus dan salin path lengkap dari file yang dihapus

git log --diff-filter=D --summary | grep delete

Jalankan perintah berikutnya untuk menemukan id komit dari komit itu dan salin id komit

git log --all -- FILEPATH

Tampilkan perbedaan dari file yang dihapus

git show COMMIT_ID -- FILE_PATH

Ingat, Anda dapat menulis output ke file menggunakan >like

git show COMMIT_ID -- FILE_PATH > deleted.diff
Fatih Acet
sumber
1
Meskipun saya menemukan jalan dengan bantuan langkah pertama, langkah kedua melempar kesalahan ini: unknown revision or path not in the working tree.
jvannistelrooy
6
Untuk melihat hash komit bersama dengan penghapusan, Anda dapat melakukannyagit log --diff-filter=D --summary | grep -E 'delete|^commit\s+\S+'
Chris Middleton
1
Langkah 2 tidak menghasilkan apa-apa. Adakah ide mengapa hal itu bisa terjadi? Nama file saya benar.
Denis Kniazhev
2
Untuk menemukan menggabungkan ketiganya menjadi satu fungsi, tambahkan ini ke .bashrc atau .zshrc Anda: git-grep-latest(){ result_path=$(git log --diff-filter=D --summary | grep $1 | head -1 | awk '{print $4;}'); latest_commit=$(git log --all -- $result_path | head -1 | awk '{print $2;}'); git show $latest_commit -- $result_path; }dan sekarang Anda bisa melakukannya:git-grep-latest some_text
randomor
1
@TylerJones Anda dapat memberi makan apa saja dengan linux menggunakan pipa - google linux pipes.. Anda akan menyukainya.
John Hunt
37

Tidak dapat mengedit respons yang diterima sehingga menambahkannya sebagai jawaban di sini,

untuk mengembalikan file di git, gunakan yang berikut (perhatikan tanda '^' tepat setelah SHA)

git checkout <SHA>^ -- /path/to/file
Akshay Agarwal
sumber
Saya tidak mengerti mengapa Anda menginginkan ^. File tersebut DI komit dengan SHA itu ... mengapa Anda ingin berjalan kembali komit lain dari sana?
Tony K.
19
Ada dalam komit dengan sha itu sebagai "dihapus" yang berarti masih belum ada. Anda harus pergi ke komit sebelum itu untuk benar-benar mendapatkannya kembali.
tandrewnichols
6
@tandrewnichols yang hanya berarti bahwa Anda menggunakan komit yang salah SHA - Anda ingin komit untuk versi file yang Anda inginkan ... yang mungkin bukan versi di mana file tersebut dihapus.
Amber
6
@Amber dan komit yang Anda inginkan kemungkinan yang paling baru sebelum dihapus, maka jawaban ini.
Sam Holder
1
@AlexR: <SHA>~1harus bekerja sama tanpa perlu membungkusnya dengan tanda kutip.
CodeManX
37

Misalkan Anda ingin memulihkan file yang dipanggil MyFile, tetapi tidak pasti lintasannya (atau ekstensi, dalam hal ini):

Prelim .: Hindari kebingungan dengan melangkah ke root git

Proyek nontrivial dapat memiliki banyak direktori dengan nama yang mirip atau identik.

> cd <project-root>
  1. Temukan jalur lengkap

    git log --diff-filter = D --summary | grep delete | grep MyFile

    delete mode 100644 full/path/to/MyFile.js

full/path/to/MyFile.js adalah jalur & file yang Anda cari.

  1. Tentukan semua komit yang memengaruhi file itu

    git log --oneline --follow - full / path / ke / MyFile.js

    bd8374c Some helpful commit message

    ba8d20e Another prior commit message affecting that file

    cfea812 The first message for a commit in which that file appeared.

  2. Periksa file

Jika Anda memilih komit yang pertama kali terdaftar (yang terakhir secara kronologis, di sini bd8374c), file tidak akan ditemukan, karena sudah dihapus di komit itu.

> git checkout bd8374c -- full/path/to/MyFile.js

`error: pathspec 'full/path/to/MyFile.js' did not match any file(s) known to git.`

Cukup pilih komit sebelumnya (tambahkan tanda sisipan):

> git checkout bd8374c^ -- full/path/to/MyFile.js
Calaf
sumber
3
Ini jauh lebih jelas daripada jawaban yang diterima
Pouyan Khodabakhsh
untuk windows console (cmd), gunakan find bukannya grep pada langkah 2: git log --diff-filter=D --summary | find "delete" | find "MyFile"Dan step3, perhatikan tanda kutip di sekitar hash:git checkout "bd8374c^" -- full/path/to/MyFile.js
user5542121
30

@Amber memberikan jawaban yang benar! Hanya satu tambahan lagi, jika Anda tidak tahu jalur pasti dari file tersebut, Anda dapat menggunakan wildcard! Ini berhasil untuk saya.

git log --all -- **/thefile.*
Petur Subev
sumber
4
@PedroMorteRolo Hmm. Saya tidak tahu bagaimana perasaan saya tentang menyalin jawaban yang sudah ada ke yang terpilih: / Jawaban ini berguna juga sendiri; upvote mungkin sudah cukup?
Clément
1
Ini tidak menemukan file jika berada di root proyek (diuji di Cygwin).
cepat
19

Di bawah ini adalah perintah sederhana, di mana pengguna dev atau git dapat meneruskan nama file yang dihapus dari direktori root repositori dan mendapatkan sejarah:

git log --diff-filter=D --summary | grep filename | awk '{print $4; exit}' | xargs git log --all -- 

Jika ada yang dapat meningkatkan perintah, silakan lakukan.

Jason
sumber
1
Keren terima kasih! Sepertinya file saya tidak pernah ada sama sekali, tapi itu masalah yang terpisah dan jauh lebih
pastikan Anda menjalankan ini dari direktori root repositori jika file Anda tampaknya 'hilang'
samaspin
Terima kasih @samaspin memperbarui jawabannya.
Jason
18

Coba gunakan salah satu pemirsa, seperti gitksehingga Anda dapat menelusuri sejarah untuk menemukan file yang setengah diingat itu. (gunakan gitk --alljika diperlukan untuk semua cabang)

Philip Oakley
sumber
4
Itu --allpilihan adalah penting untuk kedua jawaban Anda dan jawaban yang diterima.
Hobs
3
Menjelajahi sejarah akan menghabiskan banyak waktu untuk sebagian besar proyek.
mikemaccana
5

Ringkasan:

  1. Langkah 1

Anda mencari path lengkap file Anda dalam sejarah file yang dihapus git log --diff-filter=D --summary | grep filename

  1. Langkah 2

Anda mengembalikan file Anda dari komit sebelum dihapus

restore () {
  filepath="$@"
  last_commit=$(git log --all --full-history -- $filepath | grep commit | head -1 | awk '{print $2; exit}')
  echo "Restoring file from commit before $last_commit"
  git checkout $last_commit^ -- $filepath
}

restore my/file_path
srghma
sumber
0

Inilah solusi saya:

git log --all --full-history --oneline -- <RELATIVE_FILE_PATH>
git checkout <COMMIT_SHA>^ -- <RELATIVE_FILE_PATH>
Antonio Petricca
sumber