Como grep diffs ou conteúdo do Git commit para uma determinada palavra?

622

Em um repositório de código Git, quero listar todos os commits que contêm uma determinada palavra. Eu tentei isso

git log -p | grep --context=4 "word"

mas não necessariamente devolve o nome do arquivo (a menos que esteja a menos de 5 linhas da palavra que eu procurei. Também tentei

git grep "word"

mas me fornece apenas os arquivos presentes e não o histórico.

Como pesquiso o histórico inteiro para poder acompanhar as alterações em uma palavra específica? Pretendo pesquisar na minha base de código por ocorrências de palavras para rastrear alterações (pesquisar no histórico de arquivos).

Jesper Rønn-Jensen
fonte

Respostas:

906

Se você deseja encontrar todos os commits nos quais a mensagem de commit contém uma determinada palavra, use

$ git log --grep=word

Se você deseja encontrar todos os commits em que "word" foi adicionada ou removida no conteúdo do arquivo (para ser mais exato: onde o número de ocorrências de "word" foi alterado), ou seja, pesquise o conteúdo de commit , use a chamada 'picareta' com

$ git log -Sword

No git moderno também há

$ git log -Gword

procurar diferenças cuja linha adicionada ou removida corresponda à "palavra" (também confirmar o conteúdo ).

Observe que, -Gpor padrão, aceita uma regex, enquanto -Saceita uma string, mas pode ser modificado para aceitar regexes usando o --pickaxe-regex.

Para ilustrar a diferença entre -S<regex> --pickaxe-regexe -G<regex>, considere uma confirmação com o seguinte diff no mesmo arquivo:

+    return !regexec(regexp, two->ptr, 1, &regmatch, 0);
...
-    hit = !regexec(regexp, mf2.ptr, 1, &regmatch, 0);

Enquanto git log -G"regexec\(regexp"mostrará esse commit, git log -S"regexec\(regexp" --pickaxe-regexnão será (porque o número de ocorrências dessa string não mudou).


Com o Git 2.25.1 (fevereiro de 2020), a documentação é esclarecida em torno dessas regexes.

Veja commit 9299f84 (06 fev 2020) por Martin Ågren (``) .
(Mesclado por Junio ​​C Hamano - gitster- na confirmação 0d11410 , 12 de fevereiro de 2020)

diff-options.txt: evite sobrecarga "regex" no exemplo

Reportado por: Adam Dinwoodie
Assinado por: Martin Ågren
Analisado por: Taylor Blau

Quando exemplificamos a diferença entre -Ge -S(usando --pickaxe-regex), fazemos isso usando um exemplo diff e git diffinvocação envolvendo "regexec", "regexp", "regmatch", ...

O exemplo está correto, mas podemos facilitar o desembaraço, evitando escrever "regex. *", A menos que seja realmente necessário expor nosso argumento.

Use algumas palavras inventadas e não regulares.

A git diffdocumentação agora inclui:

Para ilustrar a diferença entre -S<regex> --pickaxe-regexe -G<regex>, considere uma confirmação com o seguinte diff no mesmo arquivo:

+    return frotz(nitfol, two->ptr, 1, 0);
...
-    hit = frotz(nitfol, mf2.ptr, 1, 0);

Enquanto git log -G"frotz\(nitfol"mostrará esse commit, git log -S"frotz\(nitfol" --pickaxe-regexnão será (porque o número de ocorrências dessa string não mudou).

Jakub Narębski
fonte
3
@TankorSmash -S<string>Procure diferenças que introduzam ou removem uma instância de <string>. -G<string>Procure diferenças cuja linha adicionada ou removida corresponda ao <regex> fornecido.
M-ric
1
@ m-ric Oh, eu vejo, uma instância de string única, versus uma linha inteira! Graças
TankorSmash
3
@ m-ric, @TankorSmash: A diferença é que -S<string>é mais rápido, porque só verifica se o número de ocorrências foi <string>alterado, enquanto as -G<string>pesquisas adicionaram e removeram a linha em todas as diferenças de confirmação.
Jakub Narębski 5/11
3
Se você precisar pesquisar palavras com espaço no meio git log --grep="my words",.
MEM
4
@MEM, --grepé diferente de -Se -G. Você pode citar a string para cada um desses argumentos.
Acumenus 12/08/2014
255

git logA picareta de encontrará confirmações com alterações, incluindo "palavra" com git log -Sword

u0b34a0f6ae
fonte
60
Isto não é totalmente preciso. -S <string> Procure diferenças que introduzam ou removem uma instância de <string>. Observe que isso é diferente da string que simplesmente aparece na saída diff;
tymtam
4
Embora essa seja geralmente a resposta certa, diminuí a votação apenas para incentivar outras pessoas a lerem essa resposta ( stackoverflow.com/a/1340245/586983 ), que possui três maneiras diferentes e explica suas sutilezas.
precisa saber é o seguinte
18
Poxa! Eu não acho que esse seja um bom motivo para recusar uma resposta correta ... você não estava confiante em incluir o link em um comentário seria um incentivo suficiente?
Deborah
@jakeonrails, essa resposta deveria ter sido uma edição desta (mais antiga), para que não tenhamos essas duplicatas irritantes. Mas as pessoas querem apenas a reputação, em vez de uma página de respostas limpas.
Iulian Onofrei 06/02/19
22

Após muita experimentação, posso recomendar o seguinte, que mostra confirmações que introduzem ou removem linhas que contêm um determinado regexp e exibe as alterações de texto em cada uma, com cores mostrando as palavras adicionadas e removidas.

git log --pickaxe-regex -p --color-words -S "<regexp to search for>"

Demora um pouco para correr embora ... ;-)

CharlesW
fonte
2
Este é um dos melhores até agora, obrigado. Sugestão: a lista apenas os resultados sem paginação, quer preceder o comando com GIT_PAGER=catou anexá-lo com| cat
Zack Morris
Especificar um caminho ou arquivo seria muito mais rápidogit log --pickaxe-regex -p --color-words -S "<regexp to search for>" <file or fiepath>
Fangxing
10

Você pode tentar o seguinte comando:

git log --patch --color=always | less +/searching_string

ou usando grepda seguinte maneira:

git rev-list --all | GIT_PAGER=cat xargs git grep 'search_string'

Execute este comando no diretório pai no qual você deseja pesquisar.

kenorb
fonte
2
Eu gosto desse método porque os commits que estou vendo têm centenas de linhas de alterações não relacionadas, e só estou interessado nos patches reais que envolvem a palavra que estou procurando. Para obter cores, use git log --patch --color=always | less +/searching_string.
Radon Rosborough 16/10
9

Mais uma maneira / sintaxe para fazer isso é: git log -S "word"
Assim, você pode pesquisar por exemplogit log -S "with whitespaces and stuff @/#ü !"

1u
fonte
1

O vim-fugitivo é versátil para esse tipo de exame no Vim.

Use :Ggreppara fazer isso. Para obter mais informações, você pode instalar o vim-fugitive e procurar o turorial por :help Grep. E este episódio: explorar a história de um repositório git o guiará a fazer tudo isso.

Lerner Zhang
fonte
1

Para usar o conector booleano na expressão regular:

git log --grep '[0-9]*\|[a-z]*'

Essa expressão regular procura pela expressão regular [0-9] * ou [az] * nas mensagens de confirmação.

Reudismam
fonte
-1

Se você deseja pesquisar dados confidenciais para removê-los do seu histórico do git (que é a razão pela qual eu cheguei aqui), existem ferramentas para isso. Github como uma página de ajuda dedicada para esse problema .

Aqui está a essência do artigo:

O BFG Repo-Cleaner é uma alternativa mais rápida e simples ao git filter-branch para remover dados indesejados. Por exemplo, para remover seu arquivo com dados confidenciais e deixar sua confirmação mais recente intocada), execute:

bfg --delete-files YOUR-FILE-WITH-SENSITIVE-DATA

Para substituir todo o texto listado em passwords.txt, onde quer que ele possa ser encontrado no histórico do seu repositório, execute:

bfg --replace-text passwords.txt

Consulte a documentação do BFG Repo-Cleaner para obter instruções completas de uso e download.

edelans
fonte
Você pode querer adicionar esta resposta para stackoverflow.com/questions/872565/... em vez de aqui
lacostenycoder