UpdateGitRepositories.psm1
function Update-GitRepositories { <# .SYNOPSIS Updates all .git repositories at a given path by pulling the latest changes from the main/master branch. .DESCRIPTION Update-GitRepositories searches all directories at the given path (the default path is the path where this command is executed) if the directory contains a git repository (.git folder). If a .git folder is present in the directory, this command will stash any git changes, switch to the main/ master branch, pull the latest changes from git, and revert back to the original git branch the repository was in before moving on to the next repository. .PARAMETER Path The path at which to execute this function at. By default, this value is the current directory. .EXAMPLE Update-GitRepositories .EXAMPLE Update-GitRepositories -Path "C:\Users\Me\repos" .INPUTS String #> [CmdletBinding(SupportsShouldProcess)] param( [ValidateNotNullOrEmpty()] [string]$Path = (Get-Location) ) BEGIN {} PROCESS { # Pulls all folders at the given path that contain a .git folder $GitFolders = @(Get-ChildItem -Path (Get-Location) -Directory | Where-Object {Get-ChildItem -Path ($_ | Select-Object -ExpandProperty FullName) -Directory -Hidden -Filter .git}) $ExecutingDirectory = (Get-Location).Path # Pulls the latest code from git foreach ($Folder in $GitFolders) { # Reset our execution directory Set-Location -LiteralPath $ExecutingDirectory Write-Verbose -Message "Processing $($Folder)" Set-Location -LiteralPath $Folder # Saves our current and main/master branch of the repository $CurrentGitBranch = git branch --show-current $GitMainBranch = git branch | Where-Object { -Not $_.Contains("/") -and ($_.EndsWith("main") -or $_.EndsWith("master")) } # If we cannot find the main branch, skip over this repository if ($NULL -eq $GitMainBranch) { Write-Verbose -Message "Failed to find the main branch, skipping this git repository" continue } # Optionally remove the '*' or ' ' characters to get the true branch name $GitMainBranch = $GitMainBranch -Replace '[* ]', '' $NeedsToGitCheckout = $CurrentGitBranch -ne $GitMainBranch if ($NeedsToGitCheckout -eq $TRUE) { # Switch to our main branch git checkout $GitMainBranch } # Save any pending changes $GitStash = git stash $GitPull = git pull # Short-circuit if we have the latest changes if ($GitPull -eq "Already up to date.") { if ($NeedsToGitCheckout -eq $TRUE) { git checkout $CurrentGitBranch } continue } # Revert pending changes if ($GitStash -ne "No local changes to save") { git stash pop } if ($NeedsToGitCheckout -eq $TRUE) { # Switch back to our existing branch git checkout $CurrentGitBranch } } # Reset our execution directory Set-Location -LiteralPath $ExecutingDirectory } END {} } |