Skip to content

Instantly share code, notes, and snippets.

View mmodrow's full-sized avatar

Marc A. Modrow mmodrow

  • Bremen, Germany
View GitHub Profile
@mmodrow
mmodrow / git_workshop.md
Last active February 10, 2026 15:32
Git Plumbing to the Metal Workshop

Introduction

While most users see the directory that contains their code as their "repository" that's not technically true... That's what git calls the "working copy" and from git's perspective it is no more that a device for the user to make the handling of the "real" repository, which lives in the .git directory next to your code, more intuitive.

Besides the working copy users usually interact with the "porcellain"-commands with their repository; read "user interface outside of the wall". These are your git commit, git checkout, git rebase, etc. But they are merely a façade! They in turn talk to git using the "plumbing"-commands; read "technical foundation behind the wall, that acually gets stuff done!" Here we enter the realm of commands like git hash-object, git mktree, etc.

Just like most "users" of a bathroom will only interact with faucets, tubs, sinks & toilet bowls, they all are worth nothing without all the piping, valves, isolation, sink traps etc. which usually either work on thei

@mmodrow
mmodrow / Remove-ExitRotationFlags.ps1
Created January 9, 2026 21:46
Removes Metadata (Exit) Rotation from jpeg files using exiftool
gci *.jp*g | ForEach-Object{ & '..\exiftool-13.45_32\exiftool().exe' -Orientation=1 -n $_.FullName}
@mmodrow
mmodrow / Rotate-ImagesInPlace.ps1
Created January 9, 2026 21:45
Rotates images in Place using image magick
gci *.jp*g | ForEach-Object{ magick mogrify -rotate 90 $_.FullName}
@mmodrow
mmodrow / find-duplicates.ps1
Created January 8, 2026 14:19
Identify files with duplicate content and remove all but one (or perform some other action on the dupe sets)
$groupedDuplicates = Get-ChildItem -Recurse -File `
| Group-Object -Property Length `
| Where-Object { $_.Count -gt 1 } `
| ForEach-Object { $_.Group } `
| Get-FileHash `
| Group-Object -Property Hash `
| Where-Object { $_.Count -gt 1 } `
| ForEach-Object { $_.Group } `
| Group-Object -Property hash
git fsck --lost-found | grep "^dangling commit" | sed "s/^dangling commit //g" | xargs git show -s --oneline
@mmodrow
mmodrow / Set-GitCommitDate.ps1
Last active June 13, 2025 19:01
Manually set current git commit date
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[datetime]
$dateTime
)
$dateString = $dateTime.ToString("yyyy-MM-ddTHH:mm:ss")
git commit --amend --date=$dateString --no-edit --reset-author
@mmodrow
mmodrow / Remove-Trailing5Seconds.ps1
Created April 24, 2024 04:43
Removes the last 5 seconds from all mp4 files in the directory using ffmpeg and stores them in an adjacent directory.
$videos = Get-ChildItem *.mp4
foreach ($video in $videos) {
$duration = [float](ffprobe -i $video.fullName -show_entries format=duration -v quiet -of csv="p=0")
ffmpeg -i $video.fullName -ss 0 -to ($duration - 5) (Join-Path "..\trimmed" ($video.name))
}
@mmodrow
mmodrow / ConvertTo-SilentVideo.ps1
Last active March 26, 2024 19:55
Use FFMpeg to strip (unusable) Audio from video files
$videos = @(Get-ChildItem *.avi | Where-Object { -not $_.name.contains("_h264") -and -not $_.name.contains("_noAudio") })
$total = $videos.count
$current = 1
foreach ($video in $videos) {
$silentVideoName = $video.basename + "_noAudio_h264.mp4"
Write-Progress -Status "Stripping Audio and recoding video to h.264." -PercentComplete ($current / $total * 100) -Activity "Writing file $current of $total."
if ( -not (Test-Path $silentVideoName )) {
Write-Host ("Converting " + $silentVideo.name + " to " + $silentVideoName + ".")
ffmpeg -i $video.name -an -c:v libx264 -hide_banner -v warning $silentVideoName
@mmodrow
mmodrow / Remove-SilentVideoWithStatic.ps
Created March 26, 2024 17:56
Remove Video that had no (proper) audio and was stripped by ConvertTo-SilentVideo.ps1
$silentVideos = Get-ChildItem *.mp4 -Include @("*_noAudio*", "*_h264*") | Where-Object { $_.length -gt 0 }
foreach ($silentVideo in $silentVideos) {
$silentVideoName = ($silentVideo.basename.replace("_noAudio", "").replace("_h264", "")) + ".avi"
if (Test-Path($silentVideoName)) {
Write-Host ( "removing " + $silentVideoName)
Remove-Item $silentVideoName
}
}
@mmodrow
mmodrow / Export-DenormalizedTrelloCardData.ps1
Created March 14, 2024 06:52
Transform a single card from a Trello Board Export to denormalized JSON
[CmdletBinding()]
param (
[string]
$jsonImportPath,
[string]
$jsonExportPath,
[string]
$cardName
)
$trelloData = Get-Content $jsonImportPath -Encoding UTF8 | ConvertFrom-Json