我想向您寻求有关 git 的帮助以及如何将推送拆分为较小的推送。我没有 git 经验,所以我需要帮助。
我的问题是我无法将大于 5GB 的推送发送到 Azure DevOps,这就是我需要拆分推送的原因。
我有很大的推动力,因为我正在尝试通过删除二进制文件来减少存储库。
我按照以下步骤操作
git clone --bare --mirror
我使用
git-filter-repo
来减少存储库大小。
之后
git reflog expire --expire=now --all
git repack -a -d --depth=250 --window=250 --max-pack-size=2g
存储库完美缩减,包大小不超过2GB。它对推动没有帮助。 因为当我推动我的改变时
git push origin --force --mirror --prune
我收到尺寸错误。
我找到了计算提交的解决方案,但它并没有像我想象的那样工作。首先它引发了我在镜像 git 上的错误。如果我从配置中取消设置镜像标志,我不知道我是否更改了错误的方法。 确实,所创建的代码“有效”,但它删除了一些分支。我需要可以为所有分支推送所有内容的解决方案。
失败后,我发现了另一个代码,但我担心它只推送一个分支(我是我错了)。此代码还需要取消设置镜像标志。
# Split a repository into batches to avoid `pack exceeds maximum allowed size` on git push
REMOTE=origin
BRANCH=$(git rev-parse --abbrev-ref HEAD)
BATCH_SIZE=500
# check if the branch exists on the remote
if git show-ref --quiet --verify refs/remotes/$REMOTE/$BRANCH; then
# if so, only push the commits that are not on the remote already
range=$REMOTE/$BRANCH..HEAD
else
# else push all the commits
range=HEAD
fi
# count the number of commits to push
n=$(git log --first-parent --format=format:x $range | wc -l)
# push each batch
for i in $(seq $n -$BATCH_SIZE 1); do
# get the hash of the commit to push
h=$(git log --first-parent --reverse --format=format:%H --skip $i -n1)
echo "Pushing $h..."
git push $REMOTE $h:refs/heads/$BRANCH
done
# push the final partial batch
git push $REMOTE HEAD:refs/heads/$BRANCH`
请您确认一下这段代码是否满足我的需要。这意味着推送将低于 5GB,并且推送我的所有分支仅通过 filter-repo 减少?
谢谢您的帮助
我在脚本中使用了两次拆分推送。首先将存储库备份到新的存储库。第二个用于从 git filter-repo 推送更改的提交。我提取并重写了我的备份脚本并添加到此处作为解决方案。
[string] $RepositoryFolderPathForBareCloneBAK = "C:\Repositories\bare_clone"
[string] $RepositoryHttpsURL = "URLToRepository"
[string] $BackupRepositoryHttpsURL = "URLToBackupRepository"
[string] $remoteName = "origin"
[int] $maxPushSizeInMB = (5 * 1024) # 5GB - Azure DevOps limit for one Push
[int] $splitPushCommitsCount = 100
[boolean] $splitPush = $false
$ALocation = Get-Location
if ($null -ne (Test-Path $RepositoryFolderPathForBareCloneBAK)) {
write-host "Remove directory $RepositoryFolderPathForBareCloneBAK" -ForegroundColor Green
$null = Remove-Item $RepositoryFolderPathForBareCloneBAK -Recurse -Force -ErrorAction Stop | Out-Null
}
write-host "Clone bare repository from $RepositoryHttpsURL to $RepositoryFolderPathForBareCloneBAK" -ForegroundColor Green
git clone --bare --mirror $RepositoryHttpsURL $RepositoryFolderPathForBareCloneBAK
write-host "Backup repository" -ForegroundColor Magenta
write-host "Switch to folder $RepositoryFolderPathForBareCloneBAK" -ForegroundColor green
Set-Location $RepositoryFolderPathForBareCloneBAK -ErrorAction Stop
$doSplitPush = $splitPush #Split push if it is forced
if (!($doSplitPush)) {
# check if repository is lower than limit if not do split push
write-host "git count-objects -vH" -ForegroundColor Green
$gitCountResult = (git count-objects -vH)
$splitRegEx = "^(?<Name>[^\s-]+(-[^\s-]+)*):\s*(?<Value>\d+\.?\d*)\s*(?<Measure>\S+)?$"
$repositorySize = 0
$gitCountResult | ForEach-Object {
write-host $_ -ForegroundColor Green
if ($_ -match $splitRegEx) {
if ($matches['Name'] -eq 'size-pack') {
if ("$($matches['Measure'])" -ne '') {
if (($matches['Measure']) -eq 'bytes') {
$repositorySize = ([math]::Round((([float]($matches['Value'])) / 1024 / 1024)))
}
elseif (($matches['Measure']) -eq 'KiB') {
$repositorySize = ([math]::Round(([float]($matches['Value']) / 1024)))
}
elseif (($matches['Measure']) -eq 'MiB') {
$repositorySize = ([float]($matches['Value']))
}
elseif (($matches['Measure']) -eq 'GiB') {
$repositorySize = (([float]($matches['Value'])) * 1024)
}
else {
$repositorySize = ([float]($matches['Value']))
}
}
}
}
}
$doSplitPush = ($repositorySize -ge $maxPushSizeInMB)
}
if (!($doSplitPush)) {
write-host "Push all to remote repository" -ForegroundColor Magenta
write-host "git push --mirror $BackupRepositoryHttpsURL" -ForegroundColor Green
git push --mirror $BackupRepositoryHttpsURL
}
else {
write-host "Splited git pushes to remote repository. Push per $($splitPushCommitsCount) commits" -ForegroundColor Magenta
if ((git config remote.origin.mirror) -eq "true") {
write-host "git config --unset remote.origin.mirror" -ForegroundColor Green
git config --unset remote.origin.mirror
}
# Split a repository into batches to avoid `pack exceeds maximum allowed size` on git push
$REMOTE = $remoteName
$NewREMOTE = "new_$($remoteName)"
$BATCH_SIZE = $splitPushCommitsCount
write-host "Get list of remotes" -ForegroundColor green
$Remotes = git remote -v
if ($Remotes) {
$RemoteExtists = ($null -ne ($Remotes | Where-Object { $_.IndexOf($BackupRepositoryHttpsURL) -ne -1 } ))
if (!$RemoteExtists) {
if ($null -ne ($Remotes | Where-Object { $_.IndexOf($NewREMOTE) -ne -1 } )) {
write-host "Set existing remote $($NewREMOTE) for $($BackupRepositoryHttpsURL)" -ForegroundColor green
git remote set-url "$NewREMOTE" "$BackupRepositoryHttpsURL" | Out-Null
}
else {
write-host "Add remote $NewREMOTE for $BackupRepositoryHttpsURL" -ForegroundColor green
git remote add "$NewREMOTE" "$BackupRepositoryHttpsURL" | Out-Null
}
}
}
git for-each-ref --format="%(refname)" --sort='authordate' | ForEach-Object {
if ($_.IndexOf("refs/heads/") -ne -1) {
$BRANCH = $_.Replace("refs/heads/", '')
write-host "Pushing branch $($BRANCH)" -ForegroundColor yellow
write-host "Switch $BRANCH" -ForegroundColor green
write-host "git symbolic-ref HEAD $($_)" -ForegroundColor green
git symbolic-ref HEAD $_ | Out-Null
# check if the branch exists on the remote
if ($null -ne (git show-ref --quiet --verify "refs/remotes/$($NewREMOTE)/$($BRANCH)")) {
# check if the branch exists on the remote
$range = "$($NewREMOTE)/$($BRANCH)..HEAD"
}
else {
# else push all the commits
$range = "HEAD"
}
write-host "Range $($range)" -ForegroundColor green
# count the number of commits to push
$n = (git log --first-parent --format="format:x $range").Length
write-Host "Count of commits to push $($n)" -ForegroundColor green
if ($n -gt 0) {
$loopCount = [int] [Math]::Truncate($n / $BATCH_SIZE)
# push each batch
for ($i = 1; $i -le $loopCount; $i++) {
$h = git log --first-parent --reverse --format=format:%H --skip ($n - ($i * $BATCH_SIZE)) -n1
write-Host "Skip commits $(($n - ($i * $BATCH_SIZE))) to $($h)" -ForegroundColor green
Write-Host "Pushing $($NewREMOTE) --force $($h):refs/heads/$($BRANCH)"
git push "$($NewREMOTE)" --force "$($h):refs/heads/$($BRANCH)"
}
# push last batch
Write-Host "Pushing $($NewREMOTE)" --force "HEAD:refs/heads/$($BRANCH)"
git push "$($NewREMOTE)" --force "HEAD:refs/heads/$($BRANCH)"
}
else {
write-host "Skiped push no commits" -ForegroundColor Yellow
}
}
}
write-host "git push $NewREMOTE --force 'refs/tags/*'" -ForegroundColor Green
git push $NewREMOTE --force 'refs/tags/*'
write-host "git push $NewREMOTE --force 'refs/replace/*'" -ForegroundColor Green
git push $NewREMOTE --force 'refs/replace/*'
}
Set-Location $ALocation
if (Test-Path -Path $RepositoryFolderPathForBareCloneBAK) {
write-host "Remove directory $RepositoryFolderPathForBareCloneBAK" -ForegroundColor Green
$null = Remove-Item $RepositoryFolderPathForBareCloneBAK -Recurse -Force -ErrorAction Stop | Out-Null
}