Wie kann ich Git-Zweige nach einer Datei oder einem Verzeichnis durchsuchen?

323

Wie kann ich in Git nach einer Datei oder einem Verzeichnis über einen Pfad in mehreren Zweigen suchen?

Ich habe etwas in einer Filiale geschrieben, aber ich weiß nicht mehr, welche. Jetzt muss ich es finden.

Erläuterung : Ich suche nach einer Datei, die ich in einem meiner Zweige erstellt habe. Ich würde es gerne nach Pfad und nicht nach Inhalt finden, da ich mich nicht daran erinnere, was der Inhalt ist.

Peeja
quelle
Die Frage ist mir unklar. Befand sich diese Datei in einem Zweig, der jetzt gelöscht wird? Wurde die Datei gelöscht?
Abizern

Antworten:

444

git log+ git branchwird es für Sie finden:

% 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

Unterstützt auch das Globbing:

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

Die einfachen Anführungszeichen sind erforderlich (zumindest bei Verwendung der Bash-Shell), damit die Shell das Glob-Muster unverändert an git übergibt, anstatt es zu erweitern (genau wie bei Unix find).

Dustin
quelle
2
Dies funktioniert, wenn Sie den genauen Pfad kennen somefile: Wenn Sie beispielsweise eine Regex-Suche über den Pfad / Dateinamen benötigen, können Sie die Antwort von ididak verwenden.
ShreevatsaR
70
Unterstützt auch git log --all -- **/my_file.png
Globbing
3
Ich habe dies für ein etwas anderes Problem verwendet. Ich habe versucht, alle * .sql-Dateien zu finden, die ich für einen bestimmten Zweig festgelegt hatte. Also habe ich benutzt git log --grep='branch' --author='me' -- *.sql. Lief wie am Schnürchen. Git Version 1.7.11.1
Thepriebe
1
Beachten Sie, dass dies gitkauch das Globbing unterstützt. Das ist eine hervorragende Antwort @webmat! Wenn Sie sehen möchten, wo es gelöscht / erstellt / usw. wurde, können Sie es verwenden git log --all --stat -- **/my_file.png. Auf diese Weise müssen Sie nicht raten, ob Sie es aus einem Commit auschecken, der es gelöscht hat.
eacousineau
1
@webmat: Ich habe mir erlaubt, Ihre Informationen zum Globbing zur Antwort hinzuzufügen. Danke, dass du es erwähnt hast!
Sleske
65

git ls-tree könnte helfen. So suchen Sie in allen vorhandenen Filialen:

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

Dies hat den Vorteil, dass Sie auch mit regulären Ausdrücken nach dem Dateinamen suchen können.

ididak
quelle
3
Einige hoffentlich hilfreiche Kommentare: (a) Sie möchten wahrscheinlich "-r" zu "git ls-tree" hinzufügen, damit die Datei auch dann gefunden wird, wenn sie sich in einem Unterverzeichnis befindet. (b) Eine vielleicht sauberere Alternative zur ersten Zeile wäre die Verwendung von "git für jede Referenz", z. B. "für die Verzweigung in git for-each-ref --format="%(refname)" refs/heads; do". (c) "git ls-tree --name-only" macht die Ausgabe aufgeräumter (d) In Ihrer Antwort sollte darauf hingewiesen werden, dass dies gegenüber Dustins Lösung von Vorteil ist, nämlich dass Sie den Dateinamen nicht genau kennen müssen. Sie können nach regulären Ausdrücken suchen, die mit einem beliebigen Teil des Pfads übereinstimmen
Mark Longair
9
Ich habe dies in ein Skript eingepackt, damit Sie "gitfind.sh <regex>" ausführen können. Das Wesentliche ist gist.github.com/62d981890eccb48a99dc
Handyman5
3
Beachten Sie, dass dies nur über lokale Zweige hinweg sucht . Verwenden Sie refs/remotesanstelle von Remote-Tracking-Zweigen anstelle von refs/heads. Verwenden Sie einfach, um alles zu durchsuchen (lokale Zweige, Fernverfolgungszweige und Tags) refs/.
Sleske
19

Obwohl die Antwort von ididak ziemlich cool ist und Handyman5 ein Skript zur Verwendung bereitstellt, fand ich es ein wenig eingeschränkt, diesen Ansatz zu verwenden.

Manchmal müssen Sie nach etwas suchen, das im Laufe der Zeit erscheinen / verschwinden kann. Warum also nicht nach allen Commits suchen? Außerdem benötigen Sie manchmal eine ausführliche Antwort und manchmal nur Übereinstimmungen. Hier sind zwei Versionen dieser Optionen. Fügen Sie diese Skripte in Ihren Pfad ein:

Git-Find-Datei

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

Jetzt können Sie tun

$ 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

Stellen Sie sicher, dass Sie mit getopt das Skript so ändern können, dass abwechselnd alle Commits, Refs, Refs / Heads durchsucht werden.

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

Überprüfen Sie https://github.com/albfan/git-find-file auf eine mögliche Implementierung.

Albfan
quelle
Meinten Sie "Jetzt können Sie git-find-file <regex> machen"? Ich habe es geschafft, danke!
Elijah Lynn
1
Ich persönlich finde es viel nützlicher, $ (git branch | cut -c 3-) anstelle von $ (git rev-list --all) zu verwenden. Es ist mir egal, ob ich eine Reihe von Commits finde, ich kümmere mich um benannte Zweige.
Campadrenalin
Ich habe auch die Skripte geändert, um $ (git branch | cut -c 3-) zu verwenden, da die Schleife über alle Commits viel zu langsam war.
i4h
Angesichts der ganzen Aufregung, die ich mache, lohnt es sich, ein Repo dafür zu erstellen. github.com/albfan/git-find-file . Ich habe einige Probleme offen, kann gerne mehr vorschlagen oder PR dafür senden.
Albfan
1
@ Lumbric Installation Skript auf Pfad funktioniert sofort, es ist eine Git-Funktion
Albfan
10

Sie können gitk --allCommits "berührende Pfade" und den Pfadnamen, an dem Sie interessiert sind, verwenden und suchen.

Greg Hewgill
quelle
3
Verwenden Sie wie angegeben gitk --all und dann in Ansicht | Neue Ansicht, Alle Zweige aktivieren. Legen Sie dann Ihre Suchkriterien fest: Dateinamen (mit Platzhaltern) im vorletzten Feld. Endlich: OK.
MikeW
8

Kopieren Sie diese und fügen Sie sie ein, um sie zu verwenden git find-file SEARCHPATTERN

Alle gesuchten Zweige drucken:

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

Drucken Sie nur Zweige mit Ergebnissen:

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

Diese Befehle werden einige minimale Shell - Skripte direkt auf Ihrem hinzufügen ~/.gitconfigals global git alias .

lumbrisch
quelle
es wird nur in der Hauptniederlassung gesucht
Nasif Imtiaz Ohi
Es sucht in allen lokalen Filialen
Leonardo Herrera