En utilisant Git, comment puis-je rechercher une chaîne dans toutes les branches?

170

En utilisant Git, comment puis-je rechercher dans tous les fichiers de toutes les branches locales une chaîne donnée?

Spécifique à GitHub: est-il possible d'effectuer la recherche ci-dessus dans toutes les branches de GitHub? (Il y a plusieurs branches distantes sur mon référentiel GitHub distant que je n'aurais idéalement pas à supprimer pour cette recherche ...)

Ivar
la source
1
git-grep est peut-être ce que vous recherchez, mais je ne suis pas encore sûr des options dont vous auriez besoin ...
johnny

Réponses:

170

Vous pouvez le faire sur un référentiel Git:

git grep "string/regexp" $(git rev-list --all)

La recherche avancée GitHub a une capacité de recherche de code:

La recherche de code examinera tout le code hébergé publiquement sur GitHub. Vous pouvez également filtrer par:

  • la langue: language:
  • le nom du référentiel (y compris le nom d'utilisateur): repo:
  • le chemin du fichier: path:
manojlds
la source
Cela me cause un défaut de segmentation. Pourrait être tortoisegitmerge (Windows), cependant.
bean5
6
Ce n'est vraiment pas la meilleure façon de procéder. Il ne contrôle pas la quantité de références git qui sont passées git grep .... Regardez les autres réponses, elles sont bien meilleures que celle-ci même si elle est marquée comme réponse acceptée!
slm
1
ce serait génial si vous pouvez ajouter un exemple pour vos filtres, par exemple path:, parce que la documentation en un coup d'œil ne semble pas claire où appliquer ce filtre, je suppose qu'il est avant les guillemets dans votre exemple de requête?
blamb
3
comment puis-je lister uniquement le nom de la branche. Actuellement, il répertorie tous les hachages contenant la chaîne.
harryfeng
4
La recherche Github se fait uniquement sur la branche principale . De help.github.com/articles/searching-code : "Seule la branche par défaut est indexée pour la recherche de code. Dans la plupart des cas, ce sera la branche principale."
RedPanda
124

Si vous utilisez la commande @manojlds Git grep et obtenez une erreur:

-bash: /usr/bin/git: Argument list too long" 

alors vous devriez utiliser xargs :

git rev-list --all | xargs git grep "string/regexp"

Voir également Comment grep (recherche) du code commis dans l'historique Git

brûlure d'estomac
la source
En outre, cela semble être plus compatible avec d'autres types de consoles comme Fishshell
Daniel
1
Merci!!! en utilisant ZSH et cela a fonctionné tandis que la commande @manojlds a donné l'erreur que vous avez mentionnée! Mais attention, cela peut prendre TRES longtemps pour un gros repo avec une longue histoire.
lacostenycoder
54

Dans de nombreux cas, git rev-list --allpeut renvoyer un grand nombre de commits, ce qui prend une éternité à analyser. Si vous, au lieu de rechercher dans chaque commit sur chaque branche de l'historique de votre référentiel, vous souhaitez simplement rechercher toutes les astuces de branche, vous pouvez le remplacer par git show-ref --heads. Donc au total:

git grep "string" `git show-ref --heads`

ou:

git show-ref --heads | xargs git grep "string"

Conseil: vous pouvez écrire la sortie dans un fichier pour l'afficher dans un éditeur:

nano ~/history.txt
git show-ref --heads | xargs git grep "search string here" >> ~/history.txt
Zitrax
la source
6
git show-ref --headsrépertorie le hachage et le nom de la référence afin qu'il (2e ligne) recherche deux fois. c'est git show-ref --heads | cut -d' ' -f2mieux car il ne listera que les noms de référence.
hIpPy
4
Je ne peux pas croire combien de fois cette question a été posée et répondue, mais vous êtes le seul à avoir la bonne réponse.
Sammitch le
1
git show-ref --heads -srenvoie uniquement le hachage SHA1. De plus, s'il y a plusieurs branches pointant vers le même commit, vous aurez des doublons. Vous pouvez les supprimer avec sort -u, comme çagit show-ref --heads -s | sort -u | xargs git grep ...
Steve
Voici la fonction que j'ai ajoutée à mon bashrc. J'espère que ça aide quelqu'un:function gsearch { git grep $1 $(git show-ref --heads) | grep "refs/heads" | grep $1 } # last grep to keep grep color highlight
AFP_555
Cela devrait être la réponse acceptée. La greffe d'une chaîne dans toutes les branches mais uniquement pour le dernier contenu est un cas d'utilisation très courant.
dr_
21

Il y a quelques problèmes avec les solutions énumérées ici (même acceptées).

Vous n'avez pas besoin de lister tous les hachages car vous obtiendrez des doublons. En outre, cela prend plus de temps.

Il s'appuie sur cela où vous pouvez rechercher une chaîne "test -f /"sur plusieurs branches masteret devcomme

git grep "test -f /" master dev

qui est identique à

printf "master\ndev" | xargs git grep "test -f /"

Alors voilà.

Cela trouve les hachages pour le bout de toutes les branches locales et ne recherche que dans ces commits:

git branch -v --no-abbrev | awk -F' *' '{print $3}' | xargs git grep "string/regexp"

Si vous avez également besoin de rechercher dans les branches distantes, ajoutez -a:

git branch -a -v --no-abbrev | awk -F' *' '{print $3}' | xargs git grep "string/regexp"

Plus loin:

# Search in local branches
git branch | cut -c3- | xargs git grep "string"

# Search in remote branches
git branch -r | cut -c3- | xargs git grep "string"

# Search in all (local and remote) branches
git branch -a | cut -c3- | cut -d' ' -f 1 | xargs git grep "string"

# Search in branches, and tags
git show-ref | grep -v "refs/stash" | cut -d' ' -f2 | xargs git grep "string"
hippie
la source
5
au moins pour la recherche dans toutes les branches devrait être: git branch -a | cut -c3- | cut -d' ' -f 1 | xargs git grep "string" ou elle échouera avec le ->symbole dans la liste des fichiers, qui indique la relation entre les branches locales et distantes
Ilya Sheershoff
7

Vous pouvez essayer ceci:

git log -Sxxxx  # Search all commits
git log -Sxxxx  --branches[=<pattern>]   # Search branches
Victor Choy
la source
1
Dans toutes les branches:git log --all -s"search_string"
Tim Kuipers