# Moving repositories managed by GitLab > 原文:[https://docs.gitlab.com/ee/administration/operations/moving_repositories.html](https://docs.gitlab.com/ee/administration/operations/moving_repositories.html) * [Target directory is empty: use a tar pipe](#target-directory-is-empty-use-a-tar-pipe) * [Tar pipe to another server](#tar-pipe-to-another-server) * [The target directory contains an outdated copy of the repositories: use rsync](#the-target-directory-contains-an-outdated-copy-of-the-repositories-use-rsync) * [Single rsync to another server](#single-rsync-to-another-server) * [Thousands of Git repositories: use one rsync per repository](#thousands-of-git-repositories-use-one-rsync-per-repository) * [Parallel rsync for all repositories known to GitLab](#parallel-rsync-for-all-repositories-known-to-gitlab) * [Parallel rsync only for repositories with recent activity](#parallel-rsync-only-for-repositories-with-recent-activity) # Moving repositories managed by GitLab[](#moving-repositories-managed-by-gitlab "Permalink") 有时,您需要将 GitLab 管理的所有存储库移至另一个文件系统或另一个服务器. 在本文档中,我们将介绍将所有存储库从`/var/opt/gitlab/git-data/repositories` `/mnt/gitlab/repositories`到`/mnt/gitlab/repositories` . 我们将研究三种情况:目标目录为空,目标目录包含版本库的过时副本,以及如何处理数千个版本库. **我们列出的每种方法都可以/将覆盖目标目录`/mnt/gitlab/repositories` . 不要混淆源和目标.** ## Target directory is empty: use a tar pipe[](#target-directory-is-empty-use-a-tar-pipe "Permalink") 如果目标目录`/mnt/gitlab/repositories`为空,则最简单的操作是使用 tar 管道. 此方法的开销很低,并且 tar 几乎总是已安装在系统上. 但是,无法恢复中断的 tar 管道:如果发生这种情况,则必须再次复制所有数据. ``` sudo -u git sh -c 'tar -C /var/opt/gitlab/git-data/repositories -cf - -- . |\ tar -C /mnt/gitlab/repositories -xf -' ``` 如果要查看进度,请用`-xvf`替换`-xf` . ### Tar pipe to another server[](#tar-pipe-to-another-server "Permalink") You can also use a tar pipe to copy data to another server. If your `git` user has SSH access to the new server as `git@newserver`, you can pipe the data through SSH. ``` sudo -u git sh -c 'tar -C /var/opt/gitlab/git-data/repositories -cf - -- . |\ ssh git@newserver tar -C /mnt/gitlab/repositories -xf -' ``` 如果您想在数据通过网络之前进行压缩(这将花费您的 CPU 周期),则可以将`ssh`替换为`ssh -C` . ## The target directory contains an outdated copy of the repositories: use rsync[](#the-target-directory-contains-an-outdated-copy-of-the-repositories-use-rsync "Permalink") 如果目标目录已经包含部分/过时的存储库副本,那么再次用 tar 复制所有数据可能会很浪费. 在这种情况下,最好使用 rsync. 该实用程序已经安装在系统上,也可以通过 apt,yum 等轻松安装. ``` sudo -u git sh -c 'rsync -a --delete /var/opt/gitlab/git-data/repositories/. \ /mnt/gitlab/repositories' ``` `/.` 在上面的命令中非常重要,没有它,您很容易在目标目录中获得错误的目录结构. 如果要查看进度,请用`-av`替换`-a` . ### Single rsync to another server[](#single-rsync-to-another-server "Permalink") 如果源系统上的`git`用户对目标服务器具有 SSH 访问权限,则可以使用 rsync 通过网络发送存储库. ``` sudo -u git sh -c 'rsync -a --delete /var/opt/gitlab/git-data/repositories/. \ git@newserver:/mnt/gitlab/repositories' ``` ## Thousands of Git repositories: use one rsync per repository[](#thousands-of-git-repositories-use-one-rsync-per-repository "Permalink") 每次启动 rsync 作业时,它都必须检查源目录中的所有文件,目标目录中的所有文件,然后确定要复制或不复制哪些文件. 如果源目录或目标目录中包含许多内容,则 rsync 的启动阶段可能会成为您的 GitLab 服务器的负担. 在这种情况下,可以通过将 rsync 的工作分成较小的部分来使 rsync 的工作变得更轻松,并一次同步一个存储库. 除了 rsync 之外,我们还将使用[GNU Parallel](http://www.gnu.org/software/parallel/) . 该实用程序未包含在 GitLab 中,因此您需要使用 apt 或 yum 自己安装. 还要注意,我们在下面使用的 GitLab 脚本是在 GitLab 8.1 中添加的. **此过程不会清理源位置不再存在的目标位置的存储库.** 如果您开始在`/mnt/gitlab/repositories`使用 GitLab 实例,则需要在切换到新的存储库存储目录后运行`gitlab-rake gitlab:cleanup:repos` . ### Parallel rsync for all repositories known to GitLab[](#parallel-rsync-for-all-repositories-known-to-gitlab "Permalink") 这将一次将存储库与 10 个 rsync 进程同步. 我们会跟踪进度,以便在必要时可以重新开始传输. 首先,我们创建一个新目录,由`git`拥有,以保存传输日志. 在开始传输过程之前,我们假定目录为空,并且我们是唯一在其中写入文件的目录. ``` # Omnibus sudo mkdir /var/opt/gitlab/transfer-logs sudo chown git:git /var/opt/gitlab/transfer-logs # Source sudo -u git -H mkdir /home/git/transfer-logs ``` 我们使用要复制的目录列表为该过程添加种子. ``` # Omnibus sudo -u git sh -c 'gitlab-rake gitlab:list_repos > /var/opt/gitlab/transfer-logs/all-repos-$(date +%s).txt' # Source cd /home/git/gitlab sudo -u git -H sh -c 'bundle exec rake gitlab:list_repos > /home/git/transfer-logs/all-repos-$(date +%s).txt' ``` 现在我们可以开始传输了. 下面的命令是幂等的,并且 GNU Parallel 完成的作业数应收敛为零. 如果不是这样,则`all-repos-1234.txt`列出的某些存储库在被复制之前可能已被删除/重命名. ``` # Omnibus sudo -u git sh -c ' cat /var/opt/gitlab/transfer-logs/* | sort | uniq -u |\ /usr/bin/env JOBS=10 \ /opt/gitlab/embedded/service/gitlab-rails/bin/parallel-rsync-repos \ /var/opt/gitlab/transfer-logs/success-$(date +%s).log \ /var/opt/gitlab/git-data/repositories \ /mnt/gitlab/repositories ' # Source cd /home/git/gitlab sudo -u git -H sh -c ' cat /home/git/transfer-logs/* | sort | uniq -u |\ /usr/bin/env JOBS=10 \ bin/parallel-rsync-repos \ /home/git/transfer-logs/success-$(date +%s).log \ /home/git/repositories \ /mnt/gitlab/repositories ` ``` ### Parallel rsync only for repositories with recent activity[](#parallel-rsync-only-for-repositories-with-recent-activity "Permalink") 假设您已经完成了一次在 2015 年 10 月 1 日 12:00 UTC 之后开始的同步. 然后,您可能只想同步*在*那*之后*通过 GitLab 更改的存储库. 您可以使用`SINCE`变量告诉`rake gitlab:list_repos`仅打印具有最近活动的存储库. ``` # Omnibus sudo gitlab-rake gitlab:list_repos SINCE='2015-10-1 12:00 UTC' |\ sudo -u git \ /usr/bin/env JOBS=10 \ /opt/gitlab/embedded/service/gitlab-rails/bin/parallel-rsync-repos \ success-$(date +%s).log \ /var/opt/gitlab/git-data/repositories \ /mnt/gitlab/repositories # Source cd /home/git/gitlab sudo -u git -H bundle exec rake gitlab:list_repos SINCE='2015-10-1 12:00 UTC' |\ sudo -u git -H \ /usr/bin/env JOBS=10 \ bin/parallel-rsync-repos \ success-$(date +%s).log \ /home/git/repositories \ /mnt/gitlab/repositories ```