Làm cách nào tôi có thể tìm kiếm các nhánh Git cho một tệp hoặc thư mục?


323

Trong Git, làm cách nào tôi có thể tìm kiếm tệp hoặc thư mục theo đường dẫn qua một số nhánh?

Tôi đã viết một cái gì đó trong một chi nhánh, nhưng tôi không nhớ cái nào. Bây giờ tôi cần tìm nó.

Làm rõ : Tôi đang tìm một tập tin mà tôi đã tạo trên một trong các chi nhánh của mình. Tôi muốn tìm nó theo đường dẫn chứ không phải theo nội dung của nó vì tôi không nhớ nội dung đó là gì.


Tôi không rõ về câu hỏi. Có phải tập tin này trong một chi nhánh hiện đã bị xóa? Tập tin đã bị xóa?
Abizern

Câu trả lời:


444

git log+ git branchsẽ tìm nó cho bạn:

% git log --all -- somefile

commit 55d2069a092e07c56a6b4d321509ba7620664c63
Author: Dustin Sallings <dustin@spy.net>
Date:   Tue Dec 16 14:16:22 2008 -0800

    added somefile


% git branch -a --contains 55d2069
  otherbranch

Hỗ trợ toàn cầu, quá:

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

Các trích dẫn đơn là cần thiết (ít nhất là nếu sử dụng shell Bash) để shell chuyển mẫu hình cầu sang git không thay đổi, thay vì mở rộng nó (giống như với Unix find).


2
Điều này hoạt động nếu bạn biết đường dẫn chính xác đến somefile: nếu bạn cần tìm kiếm regex qua đường dẫn / tên tệp, chẳng hạn, thì bạn có thể sử dụng câu trả lời của ididak.
ShreevatsaR

70
Cũng hỗ trợ toàn cầu:git log --all -- **/my_file.png
webmat

3
Tôi đã sử dụng điều này cho một vấn đề hơi khác nhau. Tôi đã cố gắng tìm tất cả các tệp * .sql mà tôi đã cam kết với một chi nhánh cụ thể. Vì vậy, tôi đã sử dụng git log --grep='branch' --author='me' -- *.sql. Làm việc như người ở. phiên bản git 1.7.11.1
thepriebe

1
Lưu ý rằng cũng gitkhỗ trợ toàn cầu. Đó là một câu trả lời tuyệt vời @webmat! Nếu bạn muốn xem nó đã bị xóa / tạo / v.v., bạn có thể sử dụng git log --all --stat -- **/my_file.png, theo cách đó bạn sẽ không phải đoán nếu bạn đang kiểm tra nó từ một cam kết đã xóa nó.
eacousineau

1
@webmat: Tôi đã tự do thêm thông tin của bạn về Globing vào câu trả lời. Cảm ơn đã đề cập đến nó!
sleske

65

git ls-cây có thể giúp đỡ. Để tìm kiếm trên tất cả các chi nhánh hiện có:

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

Ưu điểm của việc này là bạn cũng có thể tìm kiếm với các biểu thức thông thường cho tên tệp.


3
Một vài ý kiến ​​hữu ích hy vọng: (a) Bạn có thể muốn thêm "-r" vào "git ls-tree" để nó sẽ tìm thấy tệp ngay cả khi nó nằm trong thư mục con. (b) Một thay thế có lẽ gọn gàng hơn cho dòng đầu tiên sẽ là sử dụng "git for-every ref", ví dụ "cho nhánh trong git for-each-ref --format="%(refname)" refs/heads; do" (c) "git ls-tree - only-only" sẽ làm cho đầu ra gọn gàng hơn (d) có thể đáng để chỉ ra trong câu trả lời của bạn rằng có một lợi thế của giải pháp này đối với giải pháp của Dustin, cụ thể là bạn không cần biết chính xác tên tệp - bạn có thể tìm kiếm bằng biểu thức chính quy khớp với bất kỳ phần nào của đường dẫn
Mark Longair

9
Tôi đã gói nó trong một tập lệnh để bạn có thể chạy "gitfind.sh <regex>"; ý chính là gist.github.com/62d981890eccb48a99dc
Handyman5

3
Lưu ý rằng điều này sẽ chỉ tìm kiếm trên các chi nhánh địa phương . Để tìm kiếm các nhánh theo dõi từ xa, sử dụng refs/remotesthay vì refs/heads. Để tìm kiếm mọi thứ (chi nhánh địa phương, chi nhánh và thẻ theo dõi từ xa), chỉ cần sử dụng refs/.
sleske

19

Mặc dù phản hồi của ididak khá tuyệt và Handyman5 cung cấp một tập lệnh để sử dụng nó, tôi thấy nó hơi bị hạn chế khi sử dụng phương pháp đó.

Đôi khi bạn cần tìm kiếm thứ gì đó có thể xuất hiện / biến mất theo thời gian, vậy tại sao không tìm kiếm chống lại tất cả các cam kết? Bên cạnh đó, đôi khi bạn cần một phản hồi dài dòng và những lần khác chỉ cam kết khớp. Đây là hai phiên bản của những lựa chọn đó. Đặt các tập lệnh này trên đường dẫn của bạn:

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

Bây giờ bạn có thể làm

$ 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

Xem rằng bằng cách sử dụng getopt, bạn có thể sửa đổi tập lệnh đó để thay thế tìm kiếm tất cả các xác nhận, refs, refs / Heads, verbose, v.v.

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

Thanh toán https://github.com/albfan/git-find-file để triển khai có thể.


Ý của bạn là "Bây giờ bạn có thể thực hiện git-find-file <regex>"? Tôi đã làm cho nó hoạt động, cảm ơn bạn!
Elijah Lynn

1
Cá nhân tôi thấy hữu ích hơn nhiều khi sử dụng $ (git chi nhánh | cut -c 3-) thay vì $ (git rev-list --all). Tôi không quan tâm đến việc tìm kiếm một loạt các cam kết, tôi quan tâm đến các chi nhánh được đặt tên.
Campadrenalin

Tôi cũng đã thay đổi các tập lệnh để sử dụng $ (git Branch | cut -c 3-) vì vòng lặp trên tất cả các lần xác nhận quá chậm.
i4h

Nhìn thấy tất cả những điều phiền phức tôi có giá trị để tạo ra một repo cho điều này. github.com/albfan/git-find-file . Tôi đã mở một số vấn đề, thoải mái đề xuất thêm hoặc gửi PR cho nó.
albfan

1
@lumbric cài đặt tập lệnh trên đường dẫn hoạt động ra khỏi hộp, tính năng git của nó
albfan

10

Bạn có thể sử dụng gitk --allvà tìm kiếm các xác nhận "đường dẫn chạm" và tên đường dẫn bạn quan tâm.


3
Như đã nêu, sử dụng gitk --all, sau đó trong View | Chế độ xem mới, kích hoạt Tất cả các Chi nhánh. Sau đó, đặt tiêu chí tìm kiếm của bạn: tên tệp (có thẻ hoang dã) trong trường áp chót. Cuối cùng: OK.
MikeW

8

Sao chép và dán cái này để sử dụng git find-file SEARCHPATTERN

In tất cả các chi nhánh được tìm kiếm:

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; :'

Chỉ in các chi nhánh có kết quả:

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; :'

Những lệnh này sẽ thêm một số kịch bản shell tối thiểu trực tiếp đến bạn ~/.gitconfignhư git bí danh toàn cầu .


nó chỉ tìm kiếm trong nhánh chính
Nasif Imtiaz Ohi 20/03/19

Nó tìm kiếm trong tất cả các chi nhánh địa phương
Leonardo Herrera

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.