Skip to content

Instantly share code, notes, and snippets.

@ploegert
Last active August 12, 2021 18:24
Show Gist options
  • Save ploegert/157deaa276b15b5cb9d92e966c562723 to your computer and use it in GitHub Desktop.
Save ploegert/157deaa276b15b5cb9d92e966c562723 to your computer and use it in GitHub Desktop.
Merge two Git Repos into destination repo
function Write-Log {
param([Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)][AllowEmptyString()][string]$Message)
Write-Verbose -Verbose ("[{0:s}] {1}`r`n" -f (get-date), $Message)
}
function Write-VLog {
param([Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)][AllowEmptyString()][string]$Message)
Write-Verbose ("[{0:s}] {1}`r`n" -f (get-date), $Message)
}
function Write-Info {
param([Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)][AllowEmptyString()][string]$Message)
Write-host ("INFO: [{0:s}] {1}`r" -f (get-date), $Message) -fore cyan
}
function Write-Warn {
param([Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)][AllowEmptyString()][string]$Message)
Write-warning ("[{0:s}] {1}`r" -f (get-date), $Message)
}
function Write-Success {
param([Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)][AllowEmptyString()][string]$Message)
Write-host ("SUCC: [{0:s}] {1}`r" -f (get-date), $Message) -fore green
}
function Write-Fail {
param([Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)][AllowEmptyString()][string]$Message)
Write-host ("SUCC: [{0:s}] {1}`r" -f (get-date), $Message) -fore green
}
function get-caller {
[cmdletbinding()]
param()
process{ return ((Get-PSCallStack)[1].Command) }
}
[System.Reflection.Assembly]::LoadWithPartialName("System.Web")
function Format-UriWithCredentials($url, $username, $password)
{
$uri = New-Object "System.Uri" $url
$url = $uri.Scheme + "://"
if (-not [string]::IsNullOrEmpty($username)) {
$url = $url + [System.Web.HttpUtility]::UrlEncode($username)
if (-not [string]::IsNullOrEmpty($password)) {
$url = $url + ":" + [System.Web.HttpUtility]::UrlEncode($password)
}
$url = $url + "@"
} elseif (-not [string]::IsNullOrEmpty($uri.UserInfo)) {
$url = $uri.UserInfo + "@"
}
$url = $url + $uri.Host + $uri.PathAndQuery
return $url
}
function Test-LastExit($cmd)
{
if ($LastExitCode -ne 0) {
write-Fail "$cmd failed with exit code: $LastExitCode"
}
}
#======================================================================================================================
# Business Logic Functions
function Invoke-cmd($uri)
{
write-success " URI: $uri"
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $global:user,$global:token)))
$ret = Invoke-RestMethod -Uri $uri -Method Get -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)} -Verbose
return $ret
}
function Get-VSTSRepos($baseurl)
{
write-info "[Get-VSTSRepos] Getting a list of Repos..."
$apiversion = "1.0"
$uri = ("{0}/_apis/git/repositories?api-version={1}" -f $baseurl, $apiversion);
$ret = Invoke-cmd($uri)
if (!($ret.value))
{
write-warn " [Get-VSTSRepos] There are no repos that were found"
}
else {
$numfound = $ret.value.count
write-info "`t[Get-VSTSRepos] There were $numfound repos found"
}
return $ret.value
}
#1. get all remote branches
#2. select only names of the branches #>
#3. Output the Name of the branch
Function git-GetAllRemoteBranches ($proj="origin")
{
. $GitExe branch -r | % { $_ -Match "$proj\/(?'name'\S+)" } `
| % { Out-Null; $matches['name'] }
}
Function git-CheckoutAllBranches ($proj="origin")
{
git-GetAllRemoteBranches -proj $proj | % {
write-info "Processing Branch: $_"
. $GitExe checkout $_
#. $GitExe branch --track $_
. $GitExe pull --allow-unrelated-histories $proj $_
#. $GitExe pull origin/$_
}
}
#======================================================================================================================
# VSTS Commands
$user = "NAME"
$user_email = "EMAIL ADDRESS"
$src1_name = "NAME_OF_REPO1"
$src1_repo = "https://ADOInstance.visualstudio.com/PROJECT1/_git/NAME_OF_REPO1"
$src2_name = "NAME_OF_REPO2"
$src2_repo = "https://ADOInstance.visualstudio.com/PROJECT1/_git/NAME_OF_REPO2"
$dst_name = "DST_REPO_NAME"
$dst_repo = "https://ADOInstance.visualstudio.com/PROJECT1/_git/DST_REPO_NAME"
$GitExe = "Git"
cd C:\git
#SRC: https://www.alexkras.com/git-merg-two-or-more-repositories-and-keeping-history/
# Create new repo locally
## All the repos will be merged here.
mkdir $dst_name
set-location $dst_name
#. $GitExe clone $GitHttpsUrl
Write-Info "[$gitRepoName] initializing repository"
. $GitExe init
#vim Readme.md # Or any other dummy file, just to get git rolling.
git add .
git commit -m 'Init'
git status -s
#Update user name and email, if needed:
git config user.name $user
git config user.email $user_email
#vim .git/config # Optional to see/check the config
#Test-LastExit ". $GitExe init"
# We might have already run before, so we need to reset the origin
. $GitExe remote remove origin
# Process to move one repo
## Repeat the following steps for every repo you want to combine.
. $GitExe remote add $src1_name $src1_repo
. $GitExe fetch --all
git-CheckoutAllBranches $src1_name
$branch = "master"
Write-Info "[$gitRepoName] Check out branch $branch"
. $GitExe checkout $branch
. $GitExe reset --hard master
git status -s
git branch -a
# . $GitExe remote add origin $src1_repo
# . $GitExe fetch origin
# . $GitExe pull --allow-unrelated-histories $src1_name master
# . $GitExe pull --all
# . $GitExe status -s
# Write-Info "[$gitRepoName] Fetching remote repository"
# #. $GitExe fetch origin
# . $GitExe fetch --all
# git-CheckoutAllBranches "DV.PolicyService"
# Test-LastExit ". $GitExe fetch origin"
# Write-Info "[$gitRepoName] Check out branch $branch"
# . $GitExe reset --hard master
# Test-LastExit ". $GitExe reset --hard"
## At this point, changes from that repo should be you your master branch.
#mkdir build
#mkdir build\jenkins\app
#mkdir config\app
#mkdir config\docker
#mkdir config\helm
#mkdir config\infra
#mdkir deploy\servicefabric
#mkdir deploy\chef
#mkdir deploy\docker
#mkdir deploy\terraform
#mkdir docs
#mkdir src
#--------------------------------------------------
# Clean up directory structure
##Move files around into a sub-directory or however you want to organize things. Commit your changes when done.
git add .
git commit -m "Moved folders for $src1_name into the new structure"
git status -s
git remote add $src2_name $src2_repo
git pull --allow-unrelated-histories $src2_name master
## Commit
git commit -m "Merged repos for: $src1_name & $src2_name"
git status -s
#--------------------------------------------------
# Clean up old remotes and delete repos
## Now that the merge is down, there is no longer a need for old remotes to be there.
git remote -v
git remote remove $src1_name
git remote remove $src2_name
git remote remove origin
#vim .git/config # All remotes can be delete from here too
#--------------------------------------------------
# Save it all to the CLoud!
git remote add origin $dst_repo
git branch --set-upstream-to=origin/master master
git push --set-upstream origin master
git push -u origin --all --force # pushes _ALL_ branches in one go
git push -u origin --tags --force # pushes _ALL_ tags in one go
#--------------------------------------------------
# Final clean up
## Make sure upstream branch is set up properly
git branch --set-upstream-to=origin/master master
## Purge old branches
git fetch -p
## Diff with master, should be the same already
git diff origin/master
## For good measure
git push
git pull
## Run git garbage collection, just for fun
git gc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment