Skip to content

Instantly share code, notes, and snippets.

Last active May 21, 2016 22:28
Show Gist options
  • Save csandfeld/4983044f51f424a43178936048da57b2 to your computer and use it in GitHub Desktop.
Save csandfeld/4983044f51f424a43178936048da57b2 to your computer and use it in GitHub Desktop.
function Sync-GithubFork {
[Parameter(ValueFromPipeline = $true)]
$Path = (Get-Location)
$Branch = $null
begin {
function Get-GitBranch {
$Current = $false
# Get all branches
$Branch = (git.exe branch)
# If Current switch get only branch with asterisk
if ($Current) {
$Branch = $Branch | Where-Object { $_ -match '^\*' }
# Remove asterisk and whitespace to return only names
$Branch = $Branch | ForEach-Object { $_.Replace('*', '').Trim() }
return $Branch
process {
foreach ($p in $Path) {
Write-Verbose -Message "Checking for Git repository in path: $p"
$IsGitRepo = Test-Path -Path (Join-Path -Path $p -ChildPath '.git') -PathType Container
if ($IsGitRepo) {
Write-Verbose -Message 'Git repository found'
Write-Verbose -Message 'Getting Remote Origin URL for repository'
$RemoteOriginUrl = (git.exe config --get remote.origin.url).Trim()
Write-Verbose -Message "Remote Origin URL: $RemoteOriginUrl"
Write-Verbose -Message 'Checking if it is a GitHub repository'
$IsGitHub = ($RemoteOriginUrl -match '')
if ($IsGitHub) {
Write-Verbose -Message 'It appear to be a GitHub repository'
Write-Verbose -Message 'Getting User and Repository parts from the Remote Origin URL'
$UserAndRepo = [regex]::Match($RemoteOriginUrl, '([^\/.]+\/[^\/.]+)\.git$').Groups[1].Value
Write-Verbose -Message "Github User/Repository: $UserAndRepo"
Write-Verbose 'Getting GitHub Repository REST data'
$RestData = Invoke-RestMethod -Uri "$UserAndRepo"
Write-Verbose -Message 'Checking if GitHub Repository is a fork'
if ($RestData.fork) {
Write-Verbose 'Repository is a fork'
Write-Verbose 'Getting parent repository owner'
$ParentOwner = $RestData.parent.owner.login
Write-Verbose "Parent repository owner: $ParentOwner"
Write-Verbose 'Getting parent repository clone URL'
$ParentCloneUrl = $RestData.parent.clone_url
Write-Verbose "Parent repository clone URL: $ParentCloneUrl"
Write-Verbose 'Getting configured remotes'
$Remotes = (git.exe remote -v)
Write-Verbose 'Building HashTable of configured remotes'
$RemotesHash = @{}
foreach ($Remote in $Remotes) {
$RegEx = [regex]::Match($Remote, '^(.+)\s(.+)\s\((.+)\)$')
$RemotesHash[$RegEx.Groups[1].Value] = $RegEx.Groups[2].Value
Write-Verbose "Checking if $ParentOwner is already configured as remote"
if (-not ($ParentOwner -in $RemotesHash.GetEnumerator().Name)) {
Write-Verbose "Adding $ParentOwner as a remote"
git.exe remote add $ParentOwner $ParentCloneUrl
else {
Write-Verbose "$ParentOwner is already configured as a remote"
Write-Verbose -Message 'Getting local branches'
$LocalBranches = Get-GitBranch
Write-Verbose -Message "Local branches found: [$($LocalBranches -join ', ')]"
Write-Verbose -Message 'Getting current branch'
$CurrentBranch = Get-GitBranch -Current
Write-Verbose -Message "Current branch: $CurrentBranch"
Write-Verbose -Message 'Checking if branches where specified'
if (-not $Branch) {
Write-Verbose -Message "No branch specified defaulting to current branch: $CurrentBranch"
$Branch = $CurrentBranch
Write-Verbose -Message "Performing action: git.exe fetch $ParentOwner"
git.exe fetch $ParentOwner
Write-Verbose -Message 'Loop through branches'
foreach ($b in $Branch) {
Write-Verbose -Message "Processing branch: $b"
Write-Verbose -Message "Verify that branch [$b] match a local branch [$($LocalBranches -join ', ')]"
if ($b -in $LocalBranches) {
Write-Verbose -Message "Verify if branch [$b] is the current branch"
if (-not ($b -eq (Get-GitBranch -Current))) {
Write-Verbose -Message "Branch [$b] is not the current branch"
Write-Verbose -Message "Performing action: git.exe checkout $b"
git.exe checkout $b
Write-Verbose -Message "Performing action: git.exe merge $ParentOwner/$b"
git.exe merge $ParentOwner/$b
Write-Verbose -Message "Performing action: git.exe push origin $b"
git.exe push origin $b
} else {
Write-Warning -Message "Specified branch [$b] is not available in local repository"
} else {
Write-Warning -Message "Remote Origin does not appear to be a fork: $RemoteOriginUrl"
} else {
Write-Warning -Message "This does not appear to be a GitHub repository: $p"
} else {
Write-Warning -Message "This does not appear to be a Git repository: $p"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment