web-dev-qa-db-fra.com

Comment trouver le commit Git qui a introduit une chaîne dans n'importe quelle branche?

Je veux être capable de trouver une certaine chaîne qui a été introduite dans n'importe quelle livraison dans n'importe quelle branche, comment puis-je faire cela? J'ai trouvé quelque chose (que j'ai modifié pour Win32), mais git whatchanged ne semble pas s'intéresser aux différentes branches (ignore le morceau py3k, il ne s'agit que d'un correctif d'alimentation de ligne msys/Win)

git whatchanged -- <file> | \
grep "^commit " | \
python -c "exec(\"import sys,msvcrt,os\nmsvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)\nfor l in sys.stdin: print(l.split()[1])\")" | \
xargs -i% git show Origin % -- <file>

Peu importe si votre solution est lente.

358
Jonas Byström

Tu peux faire:

git log -S <whatever> --source --all

Pour rechercher tous les validations qui ont ajouté ou supprimé la chaîne fixe whatever. Le paramètre --all signifie commencer à partir de chaque branche et --source signifie indiquer laquelle de ces branches a conduit à la recherche de cette validation. Il est souvent utile d’ajouter -p pour montrer les correctifs que chacune de ces commits introduirait.

Les versions de git depuis la version 1.7.4 ont également une option similaire -G, qui prend une expression régulière . Cela a en fait une sémantique différente (et un peu plus évidente), expliquée dans cet article de Junio ​​Hamano .

Comme thameera le souligne dans les commentaires, vous devez mettre des guillemets autour du terme de recherche s'il contient des espaces ou d'autres caractères spéciaux, par exemple:

git log -S 'hello world' --source --all
git log -S "dude, where's my car?" --source --all

Voici un exemple d'utilisation de -G pour rechercher les occurrences de function foo() {:

git log -G "^(\s)*function foo[(][)](\s)*{$" --source --all
610
Mark Longair

- reverse est également utile car vous voulez le premier commit qui a fait le changement:

git log --all -p --reverse --source -S 'needle'

Ainsi, les anciens commits apparaîtront en premier.

La réponse de Mark Longair est excellente, mais j’ai trouvé cette version plus simple qui fonctionnait pour moi.

git log -S whatever
17
Steven Penny

Déconner avec les mêmes réponses:

$ git config --global alias.find '!git log --color -p -S '
  • ! est nécessaire car, d'une autre manière, git ne passe pas correctement l'argument à -S. Voir cette réponse
  • - couleur et - p permet d'afficher exactement "ce qui a changé"

Maintenant tu peux faire

$ git find <whatever>

ou

$ git find <whatever> --all
$ git find <whatever> master develop
16
albfan
git log -S"string_to_search" # options like --source --reverse --all etc

Faites attention à ne pas utiliser d'espaces entre S et "string_to_search". Dans certaines configurations (git 1.7.1), vous obtiendrez une erreur du type:

fatal: ambiguous argument 'string_to_search': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions
6
ribamar

Bien que cela ne réponde pas directement à votre question, je pense que cela pourrait être une bonne solution pour vous à l'avenir. J'ai vu une partie de mon code, ce qui était mauvais. Je ne savais pas qui l'avait écrit ni quand. Je pouvais voir toutes les modifications du fichier, mais il était clair que le code avait été déplacé d'un fichier à un autre. Je voulais trouver qui l'a réellement ajouté en premier lieu.

Pour ce faire, j'ai utilisé Git bisect , qui m'a rapidement permis de trouver le pécheur.

J'ai exécuté git bisect start puis git bisect bad, car la révision extraite présentait le problème. Comme je ne savais pas quand le problème se produirait, j'ai ciblé le premier commit pour le "bon", git bisect good <initial sha>.

Ensuite, j'ai juste continué à chercher dans le dépôt le mauvais code. Quand je l'ai trouvé, j'ai lancé git bisect bad, et quand ce n'était pas là: git bisect good.

En ~ 11 étapes, j'avais couvert environ 1 000 commits et trouvé le commet exact, où le problème avait été introduit. Plutôt bien.

2
Eldamir

Pas sûr de savoir pourquoi la réponse acceptée ne fonctionne pas dans mon environnement, enfin je lance la commande ci-dessous pour obtenir ce dont j'ai besoin

git log --pretty=format:"%h - %an, %ar : %s"|grep "STRING"
1
BMW