private/Install-SoftwareGitForWindows.ps1
|
function Install-SoftwareGitForWindows { <# .SYNOPSIS Installs Git for Windows and configures global Git identity .DESCRIPTION Installs Git for Windows with winget when git.exe is unavailable, refreshes the current process environment, and configures global user.email and user.name values. When identity values are omitted, the function prompts for missing values and offers to change existing values. NonInteractive suppresses those identity prompts. WhatIf and Confirm apply to the installation and global identity changes. .PARAMETER UserEmail Specifies the value for global Git user.email. When omitted, the function may prompt for a value or retain the existing setting. .PARAMETER UserName Specifies the value for global Git user.name. When omitted, the function may prompt for a value or retain the existing setting. .PARAMETER ForceIdentityUpdate Prompts for omitted identity values even when the corresponding global settings exist. .PARAMETER NonInteractive Suppresses identity prompts. Omitted values remain unchanged unless supplied through UserEmail or UserName. Explicit parameter values can still be applied. .EXAMPLE PS> Install-SoftwareGitForWindows Installs Git when needed and interactively completes global identity configuration. .EXAMPLE PS> Install-SoftwareGitForWindows -UserEmail 'you@example.com' -UserName 'Your Name' -NonInteractive Installs Git when needed and sets both identity values without identity prompts. .EXAMPLE PS> Install-SoftwareGitForWindows -ForceIdentityUpdate Prompts for omitted identity values even when global values already exist. .INPUTS None. This function does not accept pipeline input. .OUTPUTS System.String. Returns native winget output when Git is installed. System.Management.Automation.PSCustomObject. Returns the Git version, installation status, final identity values, and winget command path. .NOTES Author: David Segura Company: Recast Software Version: 1.0.0 Date: 2026-08-28 Requires Windows and winget. This function persistently changes the current user's global Git configuration when identity updates are approved. Change Summary: - Added installation and interactive global identity configuration. #> [CmdletBinding(SupportsShouldProcess = $true)] [OutputType([pscustomobject])] param ( [Parameter()] [string]$UserEmail, [Parameter()] [string]$UserName, [Parameter()] [switch]$ForceIdentityUpdate, [Parameter()] [switch]$NonInteractive ) if (-not $IsWindows) { throw "[$(Get-Date -Format s)] [$($MyInvocation.MyCommand.Name)] Install-SoftwareGitForWindows is supported only on Windows." } $winget = Get-Command -Name 'winget' -ErrorAction SilentlyContinue if (-not $winget) { throw "[$(Get-Date -Format s)] [$($MyInvocation.MyCommand.Name)] winget is required but was not found. Install App Installer from Microsoft Store and try again." } $gitCommand = Get-Command -Name 'git' -ErrorAction SilentlyContinue $wasInstalled = $false if (-not $gitCommand) { if (-not $PSCmdlet.ShouldProcess('Git for Windows', 'Install with winget')) { return [pscustomobject]@{ GitVersion = $null WasInstalled = $false UserEmail = $null UserName = $null WingetCommand = $winget.Source } } Write-Host "[$(Get-Date -Format s)] Git for Windows is not installed. Installing with winget..." -ForegroundColor DarkGray & $winget.Source install --id 'Git.Git' -e -h --accept-source-agreements --accept-package-agreements if ($LASTEXITCODE -ne 0) { throw "[$(Get-Date -Format s)] [$($MyInvocation.MyCommand.Name)] Git for Windows installation failed with exit code $LASTEXITCODE." } Update-OSDeploySessionEnvironment $gitCommand = Get-Command -Name 'git' -ErrorAction SilentlyContinue if (-not $gitCommand) { $fallbackGitPath = Join-Path -Path ${env:ProgramFiles} -ChildPath 'Git\cmd\git.exe' if (Test-Path -Path $fallbackGitPath) { $gitCommand = Get-Command -Name $fallbackGitPath -ErrorAction SilentlyContinue } } if (-not $gitCommand) { throw "[$(Get-Date -Format s)] [$($MyInvocation.MyCommand.Name)] Git was installed but git.exe was not found in PATH. Open a new PowerShell session and run the command again." } $wasInstalled = $true } else { $installedVersion = & $gitCommand.Source --version Write-Host "[$(Get-Date -Format s)] Git is already installed: $installedVersion" -ForegroundColor Green } $currentEmail = ((& $gitCommand.Source config --global user.email 2>$null) -join '').Trim() $currentName = ((& $gitCommand.Source config --global user.name 2>$null) -join '').Trim() if ($WhatIfPreference) { $finalVersion = (& $gitCommand.Source --version).Trim() return [pscustomobject]@{ GitVersion = $finalVersion WasInstalled = $wasInstalled UserEmail = $currentEmail UserName = $currentName WingetCommand = $winget.Source } } if (-not $PSCmdlet.ShouldProcess('global Git identity', 'Configure user.email and user.name')) { $finalVersion = (& $gitCommand.Source --version).Trim() return [pscustomobject]@{ GitVersion = $finalVersion WasInstalled = $wasInstalled UserEmail = $currentEmail UserName = $currentName WingetCommand = $winget.Source } } if (-not $UserEmail) { if ([string]::IsNullOrWhiteSpace($currentEmail) -or $ForceIdentityUpdate) { $UserEmail = Read-Host 'Enter your Git email address' } elseif (-not $NonInteractive) { Write-Host "[$(Get-Date -Format s)] Current git user.email: $currentEmail" -ForegroundColor DarkGray $changeEmail = Read-Host 'Do you want to change it? (y/n)' if ($changeEmail -match '^(y|yes)$') { $UserEmail = Read-Host 'Enter your new Git email address' } } else { Write-Verbose "[$($MyInvocation.MyCommand.Name)] NonInteractive: keeping existing git user.email: $currentEmail" } } if (-not $UserName) { if ([string]::IsNullOrWhiteSpace($currentName) -or $ForceIdentityUpdate) { $UserName = Read-Host 'Enter your Git user name' } elseif (-not $NonInteractive) { Write-Host "[$(Get-Date -Format s)] Current git user.name: $currentName" -ForegroundColor DarkGray $changeName = Read-Host 'Do you want to change it? (y/n)' if ($changeName -match '^(y|yes)$') { $UserName = Read-Host 'Enter your new Git user name' } } else { Write-Verbose "[$($MyInvocation.MyCommand.Name)] NonInteractive: keeping existing git user.name: $currentName" } } if (-not [string]::IsNullOrWhiteSpace($UserEmail)) { if ($PSCmdlet.ShouldProcess('git global user.email', "Set to $UserEmail")) { & $gitCommand.Source config --global user.email "$UserEmail" Write-Host "[$(Get-Date -Format s)] Set git user.email to $UserEmail" -ForegroundColor Green } } if (-not [string]::IsNullOrWhiteSpace($UserName)) { if ($PSCmdlet.ShouldProcess('git global user.name', "Set to $UserName")) { & $gitCommand.Source config --global user.name "$UserName" Write-Host "[$(Get-Date -Format s)] Set git user.name to $UserName" -ForegroundColor Green } } $finalEmail = (& $gitCommand.Source config --global user.email).Trim() $finalName = (& $gitCommand.Source config --global user.name).Trim() $finalVersion = (& $gitCommand.Source --version).Trim() Write-Host "[$(Get-Date -Format s)] " Write-Host "[$(Get-Date -Format s)] Your global Git identity is now:" -ForegroundColor Cyan Write-Host "[$(Get-Date -Format s)] Name : $finalName" -ForegroundColor White Write-Host "[$(Get-Date -Format s)] Email: $finalEmail" -ForegroundColor White [pscustomobject]@{ GitVersion = $finalVersion WasInstalled = $wasInstalled UserEmail = $finalEmail UserName = $finalName WingetCommand = $winget.Source } } |