Create release package from git tag with Powershell In my deployment I need to generate a zip file from a git repo. I have the basic work done with how to pull the latest tag and create the zip file. I ended wanting to update the files that are pulled down to have the last modified of the last commit instead of when I just checked them out.

# Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
param(
    [string] $tag = "",
    [string] $gitURI = "https://github.com/jquery/jquery.git",
    [string] $checkForNewTagsOnly = "Y" #if yes then it will exit if the folder already exists
)
$Currentlocation = "C:\_Builds"
New-Item -ItemType Directory -Force -Path $Currentlocation

Set-Location $Currentlocation
if( $checkForNewTagsOnly -eq "Y"){
    git clone $gitURI --depth 1 master --single-branch
    Set-Location $Currentlocation\master
    git fetch --tags
    $tag = git describe --tags $(git rev-list --tags --max-count=1)
    $tag = $tag|split-path -leaf
}

if([string]::IsNullOrWhiteSpace($tag)){($tag = Read-Host "Enter the tag")}

if( $checkForNewTagsOnly -eq "Y" -and (Test-path $Currentlocation\$tag)){
    Write-Host "$tag already exists, nothing to do"
    exit
}

New-Item -ItemType Directory -Force -Path $Currentlocation
If (Test-path $Currentlocation\$tag) {Remove-item $Currentlocation\$tag}

Set-Location $Currentlocation
git clone $gitURI --recurse-submodules --single-branch --shallow-submodules --branch $tag $tag
Set-Location $Currentlocation\$tag

Write-Host "$tag checked out, running clean up on $Currentlocation"
Get-ChildItem -filter *test* -Directory -recurse -force | remove-item -force -recurse

$ToDelete = "*.gitignore","*.gitattributes","*.gitmodules"
FOREACH ($Item IN $ToDelete) {
    FOREACH ($File IN (Get-ChildItem -recurse | Where-Object {$_.name -like "$Item"})) {
        $FullName = $File.FullName
        Write-Host "Deleting $FullName" -ForegroundColor Green
        Remove-Item $File.FullName
    }
}

Write-Host "fixing the file dates, since git doesn't keep the dates, let's update it the last commit date"
FOREACH ($File IN (Get-ChildItem -recurse)) {
    $FullName = $File.FullName
    $lastModifiedDate = git log -1 --date=short --format=%cd "$FullName"
    $File.LastWriteTime = $lastModifiedDate
    $File.CreationTime = $lastModifiedDate
}

Get-ChildItem -Include .git -recurse -force | remove-item -force -recurse

Write-Host "$tag cleaned, creating zip file"
If (Test-path $Currentlocation\$tag.zip) {Remove-item $Currentlocation\$tag.zip}

Compress-Archive -Path $Currentlocation\$tag -DestinationPath $Currentlocation\$tag.zip

Write-Host "Good Job, the package is created $tag.zip"
You should put [CmdletBinding()] before the param block. This gives you some nice features.

I changed $checkForNewTagsOnly to be of type switch rather than string. You can call the script like this MyScript -checkForNewTagsOnly or MyScript -checkForNewTagsOnly:$false. I think that is better because otherwise how are people supposed to know to supply a "Y" as a parameter?

I made the tag parameter mandatory (Mandatory=$true) so that you won't need to check for it later.

By the way, I think you should start these parameters start with a capital letter. That is the convention.

[CmdletBinding()]
param(
    [Parameter(Mandatory=$true, HelpMessage="Enter the tag.")]
    [string] $tag,
    [string] $gitURI = "https://github.com/jquery/jquery.git",
    [switch] $checkForNewTagsOnly = $true #if yes then it will exit if the folder already exists
)




We use $checkForNewTagsOnly like this now that it is a boolean:

if ($checkForNewTagsOnly) {
    # ...
}




We can get rid of this line altogether now that tag is mandatory:

if([string]::IsNullOrWhiteSpace($tag)){($tag = Read-Host "Enter the tag")}




It's generally better to use Write-Output rather than Write-Host because you can't pipe Write-Host output. You couldn't for instance write it to a log. 

Write-Host "$tag checked out, running clean up on $Currentlocation"




Please be consistent with your formatting. Why do you have FOREACH in caps? I find the inconsistency of your formatting in general to be extremely triggering to my OCD. It's best to stick to conventional formatting. That makes it easier for people to read.

FOREACH ($Item IN $ToDelete) {
    FOREACH ($File IN (Get-ChildItem -recurse | Where-Object {$_.name -like "$Item"})) {




-Filter is faster than -Include. I don't know if that's an issue here or not, but it's something to be aware of. You used -Filter earlier, by the way.

Get-ChildItem -Include .git -recurse -force | remove-item -force -recurse