将 git 推送拆分到 Azure DevOps

问题描述 投票:0回答:1

我想向您寻求有关 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 azure-devops
1个回答
0
投票

我在脚本中使用了两次拆分推送。首先将存储库备份到新的存储库。第二个用于从 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
    }
© www.soinside.com 2019 - 2024. All rights reserved.