Skip to content

Instantly share code, notes, and snippets.

@JeffMill
Last active April 22, 2025 17:30
Show Gist options
  • Save JeffMill/d0b141c24bce7e724456c6832c949c1d to your computer and use it in GitHub Desktop.
Save JeffMill/d0b141c24bce7e724456c6832c949c1d to your computer and use it in GitHub Desktop.
gitgrepblame: Combination of "git grep" and "git blame".
<#
.SYNOPSIS
Combination of "git grep" and "git blame".
#>
function gitgrepblame {
Param([Parameter(Mandatory)][string]$Query)
# grep "--null" uses null separators, blame "-c" uses tab separators.
git.exe --no-pager grep --null --line-number $Query `
| Select-String -Pattern '(?<Filename>[^\0]+)\0(?<Line>[1-9][0-9]*)\0\s*(?<Text>.+)' `
| Select-Object -ExpandProperty Matches `
| ForEach-Object {
$filename = $_.Groups['Filename'].Value
$lineno = [int]$_.Groups['Line'].Value
# $line = $_.Groups['Text'].Value
git.exe --no-pager blame -c --show-name --show-number -L "$lineno,$lineno" -- $filename `
| Select-String -Pattern '(?<Hash>[0-9a-fA-F]+)\t\(\s*(?<Author>.+)\t(?<Date>.+)\t\s*(?<Line>[1-9][0-9]*)\)\s*(?<Text>.+)' `
| Select-Object -ExpandProperty Matches `
| ForEach-Object {
[PSCustomObject]@{
Hash = $_.Groups['Hash'].Value
Author = $_.Groups['Author'].Value
# DateTime cast will convert to local time.
Date = [DateTime]$_.Groups['Date'].Value
Path = $filename
Line = [int]$_.Groups['Line'].Value
Text = $_.Groups['Text'].Value
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment