Exotic Git Snippets
posted in dev-setup on • by Wouter Van Schandevijl • • last updated onSome git commands and scripts that come in handy from time to time.
Splitting Repositories
You start with a small project. It grows over time as you add more and more features. And then, at some point, you realize one of these features should actually have been a separate repository because it provides functionality that can be useful in multiple contexts.
So far I moved the files and did a git init
. At this point, I was always sad
because well, I lost the history of the feature. Not only less
commits for my Github statistics but I also lost git blame
so it could no longer
tell me why a particular algorithm was written the way it was.
Turns out git allows you to have your cake and eat it too!
# DEPRECATED!!
git filter-branch --prune-empty --subdirectory-filter src master
These days you get a deprecation warning when using filter-branch
and are pointed to a third party package instead:
newren/git-filter-repo : Quickly rewrite git repository history (filter-branch replacement)
# Requires git >= 2.24.0 and Python >= 3.5
pip3 install git-filter-repo
git filter-repo -h
git filter-repo --path src --subdirectory-filter src
Locking out package-lock.json
These days each npm install
makes a git diff
on frontend projects a real drag.
Page upon page of uninteresting changes.
git diff -- ':!*package-lock.json' ':!*yarn.lock'
Or as a ~/.gitconfig
alias:
df = "!f() { git diff --ignore-all-space -- $1 ':(exclude)*yarn.lock' ':!**package-lock.json'; }; f"
Important note: If you use the git df
alias, git df package-lock.json
will never show anything.
You’ll have to use plain old git diff
for checking the excluded files!
Deleting merged branches
Locally:
~/.gitconfig
aliases. (develop|master)
: Do not delete these branches even if merged with current branch.
merged-branches = !git branch --merged | egrep -v \"(\\*| ) (develop|master)\" | xargs -n 1
dm = !git merged-branches git branch -d
Remote:
Somehow a CI server always seems to be amassing feature branches. A simple cleanup script to the rescue!
Replace name-committer
(author filter) and origin
(remote filter) and add as a ~/.gitconfig
alias:
my-merged-remote-branches = !git for-each-ref --format='%(authorname):%(refname)' | egrep \"name-committer\" | egrep \"refs/remotes\" | sed -e \"s/^.*:refs\\/remotes\\/origin\\//:/\"
Followed by PowerShell:
git my-merged-remote-branches | % { git push --no-verify origin $_ }
Filename case renaming
Pesky Windows.
Also note the core.ignorecase
configuration value.
git mv -f OldFileNameCase newfilenamecase
Remapping remote urls
When the remote url changes for all your repositories.
$paths = Get-ChildItem "c:\git-repos" | ? { $_.PSIsContainer }
foreach ($path in $paths) {
$gitPath = Join-Path $path.FullName "\.git"
if (Test-Path -Path $gitPath -PathType Container) {
Write-Host $path.FullName " -> " $gitPath
$url = "https://new-base-url.com/$($path.Name)"
Write-Host "Remap to $url"
Push-Location $path.FullName
git remote set-url origin $url
Write-Host " "
Pop-Location
}
}
Create PR in browser
From your current branch.
function Create-PullRequest() {
$baseUrl = git remote get-url origin
if ($baseUrl -match 'github.com') {
$urlTemplate += "{base-url}/compare/{target-branch}...{source-branch}"
} else {
$urlTemplate += "{base-url}/pullrequestcreate?sourceRef={source-branch}&targetRef={target-branch}"
}
$sourceBranch = git rev-parse --abbrev-ref HEAD
# $targetBranch = "develop"
$targetBranch = "master"
git push -u origin $sourceBranch
start $urlTemplate.Replace("{base-url}", $baseUrl).Replace("{source-branch}", [uri]::EscapeDataString($sourceBranch)).Replace("{target-branch}", $targetBranch)
}
Set-Alias pr Create-PullRequest
Other blog posts
- 5 June 2024 : git filter-repo and Create-PullRequest for Github
- 30 December 2019 : PS scripts to remap remote urls & create a PR