Bagaimana saya bisa mencari file atau direktori cabang Git?

323

Di Git, bagaimana saya bisa mencari file atau direktori dengan jalan di sejumlah cabang?

Saya telah menulis sesuatu di cabang, tetapi saya tidak ingat yang mana. Sekarang saya perlu menemukannya.

Klarifikasi : Saya sedang mencari file yang saya buat di salah satu cabang saya. Saya ingin menemukannya melalui jalur, dan bukan dengan isinya, karena saya tidak ingat apa isinya.

Peeja
sumber
Saya tidak jelas tentang pertanyaan itu. Apakah file ini di cabang yang sekarang dihapus? Apakah file dihapus?
Abizern

Jawaban:

444

git log+ git branchakan menemukannya untuk Anda:

% git log --all -- somefile

commit 55d2069a092e07c56a6b4d321509ba7620664c63
Author: Dustin Sallings <[email protected]>
Date:   Tue Dec 16 14:16:22 2008 -0800

    added somefile


% git branch -a --contains 55d2069
  otherbranch

Mendukung globbing juga:

% git log --all -- '**/my_file.png'

Kutipan tunggal diperlukan (setidaknya jika menggunakan Bash shell) sehingga shell melewati pola glob untuk git tidak berubah, alih-alih meluaskannya (seperti halnya dengan Unix find).

Dustin
sumber
2
Ini berfungsi jika Anda tahu jalur yang tepat untuk somefile: jika Anda perlu pencarian regex atas jalur / nama file, misalnya, maka Anda dapat menggunakan jawaban ididak.
ShreevatsaR
70
Mendukung globbing, juga:git log --all -- **/my_file.png
webmat
3
Saya menggunakan ini untuk masalah yang sedikit berbeda. Saya mencoba menemukan semua file * .sql yang telah saya komit ke cabang tertentu. Jadi saya menggunakan git log --grep='branch' --author='me' -- *.sql. Bekerja seperti pesona. git versi 1.7.11.1
thepriebe
1
Catatan yang gitkmendukung globbing juga. Itu jawaban yang sangat bagus @webmat! Jika Anda ingin melihat di mana itu telah dihapus / dibuat / etc, Anda dapat menggunakan git log --all --stat -- **/my_file.png, dengan cara itu Anda tidak perlu menebak jika Anda memeriksanya dari komit yang menghapusnya.
eacousineau
1
@webmat: Saya mengambil kebebasan untuk menambahkan informasi Anda tentang globbing ke jawabannya. Terima kasih telah menyebutkannya!
sleske
65

git ls-tree mungkin membantu. Untuk mencari di semua cabang yang ada:

for branch in `git for-each-ref --format="%(refname)" refs/heads`; do
  echo $branch :; git ls-tree -r --name-only $branch | grep '<foo>'
done

Keuntungan dari ini adalah Anda juga dapat mencari dengan ekspresi reguler untuk nama file.

ididak
sumber
3
Beberapa komentar mudah-mudahan bermanfaat: (a) Anda mungkin ingin menambahkan "-r" ke "git ls-tree" sehingga ia akan menemukan file bahkan jika itu dalam subdirektori. (B) Alternatif yang mungkin lebih rapi untuk baris pertama adalah menggunakan "git untuk-masing-masing ref", misalnya "untuk cabang di git for-each-ref --format="%(refname)" refs/heads; do" (c) "git ls-tree --name-only" akan membuat output lebih rapi (D) mungkin perlu menunjukkan dalam jawaban Anda bahwa ada keuntungan dari ini atas solusi Dustin, yaitu bahwa Anda tidak perlu tahu persis nama file - Anda dapat mencari dengan ekspresi reguler yang cocok dengan bagian mana pun dari jalan
Mark Longair
9
Saya membungkus ini dalam sebuah skrip sehingga Anda dapat menjalankan "gitfind.sh <regex>"; the gist
Handyman5
3
Perhatikan bahwa ini hanya akan mencari di cabang lokal . Untuk mencari cabang pelacakan jarak jauh, gunakan refs/remotessebagai ganti refs/heads. Untuk mencari semuanya (cabang lokal, cabang dan tag pelacak jarak jauh), cukup gunakan refs/.
sleske
19

Meskipun respons ididak cukup keren, dan Handyman5 menyediakan skrip untuk menggunakannya, saya merasa sedikit terbatas untuk menggunakan pendekatan itu.

Kadang-kadang Anda perlu mencari sesuatu yang dapat muncul / menghilang seiring waktu, jadi mengapa tidak mencari yang melakukan semua komitmen? Selain itu, terkadang Anda membutuhkan respons verbal, dan di waktu lain hanya melakukan kecocokan. Berikut adalah dua versi dari opsi tersebut. Letakkan skrip ini di jalur Anda:

git-find-file

for branch in $(git rev-list --all)
do
  if (git ls-tree -r --name-only $branch | grep --quiet "$1")
  then
     echo $branch
  fi
done

git-find-file-verbose

for branch in $(git rev-list --all)
do
  git ls-tree -r --name-only $branch | grep "$1" | sed 's/^/'$branch': /'
done

Sekarang kamu bisa melakukannya

$ git find-file <regex>
sha1
sha2

$ git find-file-verbose <regex>
sha1: path/to/<regex>/searched
sha1: path/to/another/<regex>/in/same/sha
sha2: path/to/other/<regex>/in/other/sha

Melihat bahwa menggunakan getopt Anda dapat memodifikasi skrip tersebut untuk mencari alternatif semua komit, ref, ref / head, telah verbose, dll.

$ git find-file <regex>
$ git find-file --verbose <regex>
$ git find-file --verbose --decorated --color <regex>

Periksa https://github.com/albfan/git-find-file untuk kemungkinan implementasi.

Albfan
sumber
Apakah maksud Anda "Sekarang Anda dapat melakukan git-find-file <regex>"? Saya berhasil, terima kasih!
Elijah Lynn
1
Saya pribadi merasa jauh lebih berguna untuk menggunakan $ (cabang git | cut -c 3-) daripada $ (daftar rev git - semua). Saya tidak peduli tentang menemukan banyak komitmen, saya peduli tentang cabang bernama.
Campadrenalin
Saya juga mengubah skrip untuk menggunakan $ (git branch | cut -c 3-) karena perulangan semua komit terlalu lambat.
i4h
Melihat semua keributan saya hal layak untuk membuat repo untuk ini. github.com/albfan/git-find-file . Saya telah membuka beberapa masalah, merasa bebas untuk mengajukan lebih banyak atau mengirim PR untuk itu.
Albfan
1
@umblric menginstal script on path bekerja di luar kotak, itu fitur git
albfan
10

Anda dapat menggunakan gitk --alldan mencari komit "menyentuh jalur" dan jalur yang Anda minati.

Greg Hewgill
sumber
3
Seperti yang dinyatakan, gunakan gitk --all, lalu di View | Tampilan baru, aktifkan Semua Cabang. Kemudian atur kriteria pencarian Anda: nama file (dengan kartu liar) di bidang kedua dari belakang. Akhirnya: OK.
MikeW
8

Salin & tempel ini untuk digunakan git find-file SEARCHPATTERN

Mencetak semua cabang yang dicari:

git config --global alias.find-file '!for branch in `git for-each-ref --format="%(refname)" refs/heads`; do echo "${branch}:"; git ls-tree -r --name-only $branch | nl -bn -w3 | grep "$1"; done; :'

Cetak hanya cabang dengan hasil:

git config --global alias.find-file '!for branch in $(git for-each-ref --format="%(refname)" refs/heads); do if git ls-tree -r --name-only $branch | grep "$1" > /dev/null; then  echo "${branch}:"; git ls-tree -r --name-only $branch | nl -bn -w3 | grep "$1"; fi; done; :'

Perintah ini akan menambahkan beberapa skrip shell minimal langsung ke Anda ~/.gitconfigsebagai git alias global yang .

lumbric
sumber
itu hanya mencari di cabang utama
Nasif Imtiaz Ohi
Itu mencari di semua cabang lokal
Leonardo Herrera