This script will check for GPO's modified in the last day and then only export the data if changes have been made.  This will keep the number of backups and files down to the minimun needed.
This script will create GPO Reports to track changes and backup the GPO's so you can easily locate changes that have been made and recover.
Below is a list of the files created from this script:
<#
Name: GPOBackup.ps1
This script will check for GPO's modified in the last day and then only export the data if changes have been made.  This will keep the number of backups and files down to the minimun needed.
This script will create GPO Reports to track changes and backup the GPO's so you can easily locate changes that have been made and recover.
Below is a list of the files created from this script:
    <Year>-<Month>-<Date>-<Hour>-<Minuite>-<Domain>.zip                      - This contains a backup of all your GPO's the folder is create with the name for each GPO for easy Recovery or viewing
    <Year>-<Month>-<Date>-<Hour>-<Minuite>-<Domain>-GPOChanges.csv           - This file contains the Changed GPO Information like Name, ID, Owner, Domain, Creation Time, & Modified Time.
    <Year>-<Month>-<Date>-<Hour>-<Minuite>-<Domain>-GPOList.csv              - This file contains GPO Information like Name, ID, Owner, Domain, Creation Time, & Modified Time.
    <Year>-<Month>-<Date>-<Hour>-<Minuite>-<Domain>-GPOReport.csv            - This file Contains GPO Information like Name, Links, Revision Number, & Security Filtering
    <Year>-<Month>-<Date>-<Hour>-<Minuite>-<Domain>-GPOReport.xml            - This a backup of all the GPO's in a single file incase you need to look for a setting and do not know which GPO it is on.
    <Year>-<Month>-<Date>-<Hour>-<Minuite>-<Domain>-UnlinkedGPOReport.csv    - This file Contains GPO Information like Name, ID, Status, Creation Time, & Modified Time

This script was based off of one from Microsoft to backup GPO's by name, I have added more as the need and to make things simplier when backup up GPO's
Michael Patterson
scripts@mwpatterson.com
Revision History
    2017-08-18 - Initial Release
    2017-08-18 - Added and change/notes for drive mapping incase user was mapping to the full path of the folder
    2017-08-18 - Added Changed GPO Report and eMail Notification for GPO's that changed
    2017-08-25 - Added Unlinked GPO Report
    2017-08-31 - Changed Location for Variables to start of Script, Code Cleanup & Formatting
    2017-12-08 - Added moving to sub folder for yearto keep clutter down, could take it down to mmonth as well by changing $year from "yyyy" to "yyyy-MM"
    2017-12-27 - Cleanup
    2018-01-31 - Added check to not send emails
    2019-01-02 - Changed Text color and added message abount which GPO it was backing up incase it gives an error on backup
    2019-01-10 - Added PolicyDefinition Folder Backup
    2019-01-10 - Cleanup
Thanks for others on here that I have pulled parts from to make a more comprehensive script
This script is for backups.  To restore you can do the following steps
    Extract the zip file to a location for use
    Open GPMC
    Right Click Group Policy Objects
    Select Manage Backups
    Change Folder to the extracted zip file location and select the folder for the GPO you wish to restore, with the browse button
    Select on the GPO and click restore 
#>
#Clear Screen
Clear-Host
#Send Email
#$sendEmail = "Yes"
$sendEmail = "No"
#Move GPOBackup off of System
#$moveBackups = "Yes"
$moveBackups = "No"
#Set Share Location - Used for Direct Share Access
$useShare = "Yes"
$year = get-date -Format "yyyy"
$shareLocation = "\\Server.local\Share\Folder\GPO"
$shareLocation = $shareLocation + "\" + $year
#Set Network Location - Used when Mapping a Drive
#$useShare = "No"
$year = get-date -Format "yyyy"
#$networkDrive = "\\Server.local\Share\Folder"
$networkDrive = "\\Server.local\Share\Folder\GPO"
$networkDrive = $networkDrive + "\" + $year
#Set Drive Letter - Used when Mapping a Drive
$driveLetter = "Z"
#Set Folder Location - Used when Mapping a Drive - Needed if not directly mapping directly to full path
$folderLocation = "GPO"
#Combine Network Drive and Folder Location - Used when Mapping a Drive
if ($useShare -eq "No") {
    $shareLocation = $driveLetter +":\" +$folderLocation #Used if not directly mapping directly to full path
    #$shareLocation = $driveLetter +":\" #Used if directly mapping directly to path
}
#Get Account to copy with - Used when Mapping a Drive
if ($useShare -eq "No") {
    $user = Read-Host "Enter User Name" -AsString
    $pwd = Read-Host "Enter Password" -AsSecureString
    $mycreds = New-Object System.Management.Automation.PSCredential ($User, $Pwd)
}
#Set Domain
#$domain = $env:USERDNSDOMAIN #Full Domain Name
#$domain = $env:USERDOMAIN #Short Domain Name
#Get Date & Backup Locations
$date = get-date -Format "yyyy-MM-dd-HH-mm"
$backupRoot = "C:\" #Can use another drive if available
$backupFolder = "GPOBackupByName\"
$backupFolderPath = $backupRoot + $backupFolder
#$backupFileName = $date + "-" + $domain
$backupFileName = $date + "-" + $env:USERDNSDOMAIN #Full Domain Name
#$backupFileName = $date + "-" + $env:USERDOMAIN #Short Domain Name
#$backupPath = $backupRoot + $backupFolder + $date + "-" + $domain
$backupPath = $backupFolderPath + $backupFileName
#Configure Email notification recipient
$email1 = "user1@test.local"
#$email2 = "user2@test.local"
#Email Function
#function send_email ($exportPath, $email)
function send_email ()
{
    $today = Get-Date
    $today = $today.ToString("dddd MMMM-dd-yyyy hh:mm tt")
    $SmtpClient = new-object system.net.mail.smtpClient
    $mailmessage = New-Object system.net.mail.mailmessage
    #$SmtpClient.Host = "outlook.office365.com"
    #$SmtpClient.Port = "587"
    #$SmtpClient.EnableSsl = "True"
    #$SmtpClient.Credentials = New-Object System.Net.NetworkCredential("User", "Password");
    $SmtpClient.Host = "<SMTP Relay Server>"
    $SmtpClient.Port = "25"
    $mailmessage.from = "Sender <sender@test.local>"
    $mailmessage.To.add($email1)
    #$mailmessage.To.add($email2)
    $mailmessage.Subject = "PLEASE READ: GPO's have been changed."
    $mailmessage.IsBodyHtml = $true
    #$mailmessage.Attachments.Add($emailFile)
    $mailmessage.Attachments.Add($backupFolderPath +$backupFileName +"-GPOChanges.csv")
    $mailmessage.Body = @"
<!--<strong>GPO's have been Changed in $domain</strong><br />-->
GPO's have been changed in <span style="background-color:yellow;color:black;"><strong>$domain</strong></span>.<br /> <br />
Generated on : $today<br /><br />
<br /></font></h5>
"@
 $smtpclient.Send($mailmessage)
}
#Check if GPO Changes in last Day, Exit if no changes made in last day
$modifiedGPOs  = @(Get-GPO -All | Where-Object {$_.ModificationTime -ge $(Get-Date).AddDays(-1)}).count
If ($modifiedGPOs -eq "0") {
    Write-Host "`n`tNo Changes in last Day" -Fore Green
    Exit   #Exit if no changes made in last day
}
#Verify GPO BackupFolder
if ((Test-Path $backupFolderPath) -eq $false) {
    New-Item -Path $backupFolderPath -ItemType directory
}
#Generate List of changes
Write-Host "`n`tPlease Wait - Creating GPO Email Report" -Fore Yellow
Get-GPO -All | Where-Object {$_.ModificationTime -ge $(Get-Date).AddDays(-1)} | Export-csv $backupPath-GPOChanges.csv -NoTypeInformation
#Send email Notification
if ($sendEmail -eq "Yes") {
    Write-Host "`tPlease Wait - Sending Email Report" -Fore Yellow
    send_email
}
#Export GPO List
Write-Host "`tPlease Wait - Creating GPO List" -Fore Yellow
Get-GPO -All | Export-csv $backupPath-GPOList.csv -NoTypeInformation
#Export GPO Report
Write-Host "`tPlease Wait - Creating GPO Report" -Fore Yellow
Get-GPOReport -All -ReportType xml -Path $backupPath-GPOReport.xml
#Export GPO Properties Report
Write-Host "`tPlease Wait - Creating GPO Properties Report" -Fore Yellow
$GPOList = (Get-Gpo -All).DisplayName
$colGPOLinks = @()
foreach ($GPOItem in $GPOList){
    [xml]$gpocontent =  Get-GPOReport $GPOItem -ReportType xml
    $LinksPaths = $gpocontent.GPO.LinksTo | Where-Object{$_.Enabled -eq $True} | ForEach-Object{$_.SOMPath}
    $Wmi = Get-GPO $GPOItem | Select-Object WmiFilter
    $CreatedTime = $gpocontent.GPO.CreatedTime
    $ModifiedTime = $gpocontent.GPO.ModifiedTime
    $CompVerDir = $gpocontent.GPO.Computer.VersionDirectory
    $CompVerSys = $gpocontent.GPO.Computer.VersionSysvol
    $CompEnabled = $gpocontent.GPO.Computer.Enabled
    $UserVerDir = $gpocontent.GPO.User.VersionDirectory
    $UserVerSys = $gpocontent.GPO.User.VersionSysvol
    $UserEnabled = $gpocontent.GPO.User.Enabled
    $SecurityFilter = ((Get-GPPermissions -Name $GPOItem -All | Where-Object{$_.Permission -eq "GpoApply"}).Trustee | Where-Object{$_.SidType -ne "Unknown"}).name -Join ','
    foreach ($LinksPath in $LinksPaths){
        $objGPOLinks = New-Object System.Object
        $objGPOLinks | Add-Member -type noteproperty -name GPOName -value $GPOItem
        $objGPOLinks | Add-Member -type noteproperty -name LinksPath -value $LinksPath
        $objGPOLinks | Add-Member -type noteproperty -name WmiFilter -value ($wmi.WmiFilter).Name
        $objGPOLinks | Add-Member -type noteproperty -name CreatedTime -value $CreatedTime
        $objGPOLinks | Add-Member -type noteproperty -name ModifiedTime -value $ModifiedTime
        $objGPOLinks | Add-Member -type noteproperty -name ComputerRevisionsAD -value $CompVerDir
        $objGPOLinks | Add-Member -type noteproperty -name ComputerRevisionsSYSVOL -value $CompVerSys
        $objGPOLinks | Add-Member -type noteproperty -name UserRevisionsAD -value $UserVerDir
        $objGPOLinks | Add-Member -type noteproperty -name UserRevisionsSYSVOL -value $UserVerSys
        $objGPOLinks | Add-Member -type noteproperty -name ComputerSettingsEnabled -value $CompEnabled
        $objGPOLinks | Add-Member -type noteproperty -name UserSettingsEnabled -value $UserEnabled
        $objGPOLinks | Add-Member -type noteproperty -name SecurityFilter -value $SecurityFilter
        $colGPOLinks += $objGPOLinks
    }
}
$colGPOLinks | sort-object GPOName, LinksPath | Export-Csv -Delimiter ',' -Path $backupPath-GPOReport.csv -NoTypeInformation
#Export Unlinke GPO Report
Write-Host "`tPlease Wait - Creating Unlinked GPO Properties Report" -Fore Yellow
function IsNotLinked($xmldata){
    If ($xmldata.GPO.LinksTo -eq $null) {
        Return $true
    }
    Return $false
}
$unlinkedGPOs = @()
Get-GPO -All | ForEach-Object { $gpo = $_ ; $_ | Get-GPOReport -ReportType xml | ForEach-Object { If(IsNotLinked([xml]$_)){$unlinkedGPOs += $gpo} }}
If ($unlinkedGPOs.Count -eq 0) {
    Write-Host "`tNo Unlinked GPO's Found" -Fore Green
}
Else{
    $unlinkedGPOs | Sort-Object GpoStatus,DisplayName | Select-Object DisplayName,ID,GpoStatus,CreationTime,ModificationTime | Export-Csv -Delimiter ',' -Path $backupPath-UnlinkedGPOReport.csv -NoTypeInformation
}
#Verify GPO BackupPath
Write-Host "`tPlease Wait - Creating Backup Directory" -Fore Yellow
if ((Test-Path $backupPath) -eq $false) {
    New-Item -Path $backupPath -ItemType directory
}
#Backup GPOs into named folders
Write-Host "`tPlease Wait - Backing up GPO's" -Fore Yellow
$allGPOs =get-gpo -all
foreach ($gpo in $allGPOs) {
    Write-Host "`t`tProcessing GPO" $gpo.displayname -Fore Yellow
    #}
    $foldername= join-path $backupPath ($gpo.displayname.Replace(" ","_") + "_{" +$gpo.Id + "}")
        if ((Test-Path $foldername) -eq $false) {
            New-Item -Path $foldername -ItemType directory
        }
    Backup-GPO -Name $gpo.displayname -Path $foldername
}
#Backup PolicyDefinition Folder
Write-Host "`tPlease Wait - Backing up PolicyDefinition Folder" -Fore Yellow
$policydefinitionSource = "\\" + $env:USERDOMAIN + "\SYSVOL\" + $env:USERDNSDOMAIN + "\Policies\PolicyDefinitions"
Copy-Item -Path $policydefinitionSource -Recurse -Destination $backupPath -Container
#Compress Folders
Write-Host "`tPlease Wait - Creating ZIP File" -Fore Yellow
#PowerShell 5.0
#Compress-Archive -Path $backupPath -DestinationPath $backupPath+".zip"
#PowerShell 2.0-4.x
$source = $backupPath
$destination = $backupPath+".zip"
If (Test-path $destination) {
    Remove-item $destination
}
Add-Type -assembly "system.io.compression.filesystem"
[io.compression.zipfile]::CreateFromDirectory($Source, $destination)
#Delete GPO Backup Folder
#Write-Output "`tPlease Wait - Deleting GPO Backup Folder"
Write-Host "`tPlease Wait - Deleting GPO Backup Folder" -Fore Yellow
Remove-item -Path $backupPath -Recurse -Force -ErrorAction SilentlyContinue
#Complete if not moving off of System
if ($moveBackups -eq "No") {
    #Write-Output "`tGPO Backup - Complete"
    Write-Host "`tGPO Backup - Complete" -Fore Yellow
    Exit
}
#Map Network Drive
if ($useShare -eq "No") {
    #Net Use $driveLetter $networkDrive /User:$user $pwd
    New-PSDrive -Name $driveLetter -PSProvider FileSystem -Root $networkDrive -Credential $mycreds
}
#Move GPO Backups to Network Folder
Write-Output "Please Wait - Moving GPO Backup Files to Network Backup Folder"
Get-ChildItem $backupFolderPath -Recurse | Move-Item -Destination $shareLocation
Write-Output "Please Wait - Completed Moving GPO Backup Files to Network Backup Folder"
#Disconnect Network Drive
#if ($useShare -eq "No") {
#    Net Use $driveLetter /D
#}
#Completed Script
Write-Output "GPO Backup - Complete"