导入 Git 存储库

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

本文介绍如何将现有 Git 存储库从 GitHub、Bitbucket、GitLab 或其他位置导入 Azure DevOps 项目中的新存储库或现有空存储库。

先决条件

  • Azure DevOps 中的组织。 如果尚无组织,可以免费注册一个。 每个组织都包含免费、无限制的专用 Git 存储库。
  • 若要创建或导入存储库,你必须是“项目管理员”安全组的成员,或者将 Git 项目级别的“创建存储库”权限设置为“允许”。 有关详细信息,请参阅设置 Git 存储库权限
  • 若要使用 Azure DevOps“导入存储库”功能,必须具有 TFS 2017 Update 1 或更高版本。
  • 若要使用 TFS 2017 RTM 或更早版本导入存储库,请参阅使用 git CLI 手动导入存储库
  • 如果要使用 az repos 命令,请务必按照 Azure DevOps CLI 入门中的步骤操作。
  • Azure DevOps 中的组织。 如果尚无组织,可以免费注册一个。 每个组织都包含免费、无限制的专用 Git 存储库。
  • 若要创建或导入存储库,你必须是“项目管理员”安全组的成员,或者将 Git 项目级别的“创建存储库”权限设置为“允许”。 有关详细信息,请参阅设置 Git 存储库权限
  • 若要使用 Azure DevOps“导入存储库”功能,必须具有 TFS 2017 Update 1 或更高版本。
  • 若要使用 TFS 2017 RTM 或更早版本导入存储库,请参阅使用 git CLI 手动导入存储库

注意

完成存储库导入后,Azure DevOps 将为该导入的存储库设置默认分支。 如果导入的存储库包含名为 master 的分支,则它会被设置为默认分支,否则导入的存储库的第一个分支(按字母顺序)会被设置为默认分支。

导入到新存储库

  1. 依次选择“存储库”、“文件”。

    查看分支

  2. 在存储库下拉列表中,选择“导入存储库”。

    管理存储库

  3. 如果源存储库公开可用,只需输入源存储库的克隆 URL 和新 Git 存储库的名称。

    如果源存储库是专用存储库,但可以使用基本身份验证(用户名-密码、个人访问令牌等)进行访问,请选择“需要授权”并输入凭据。 不支持 SSH 身份验证,但可以按照使用 git CLI 手动导入存储库中的步骤手动导入使用 SSH 身份验证的存储库。

    导入存储库对话框

导入到现有空存储库

在空 Git 存储库的“文件”页上,选择“导入”并输入克隆 URL。 如果源存储库需要身份验证,则需要提供凭据。

将存储库导入到现有存储库

注意

导入功能禁用提交注释中提到的工作项的自动链接,因为目标项目中的工作项 ID 可能与源项目中的工作项 ID 不同。 可以通过导航到“设置”、“版本控制”,选择存储库并选择“选项”来重新启用提交中提到的工作项的自动链接。 有关将提交与工作项链接的详细信息,请参阅将工作项链接到提交

使用 az repos CLI 手动导入存储库

可以使用 az repos import 将存储库导入 Azure DevOps 项目。

注意

必须先在 Azure DevOps 中创建存储库,然后才能导入 Git 存储库。 此外,创建的存储库必须为空。 若要创建存储库,请参阅在 Azure Repos 中创建 Git 存储库

az repos import create --git-source-url
                       [--detect {false, true}]
                       [--git-service-endpoint-id]
                       [--org]
                       [--project]
                       [--repository]
                       [--requires-authorization]
                       [--subscription]
                       [--user-name]

参数

参数 说明
git-source-url 必需。 要导入的源 git 存储库的 URL。
detect 可选。 自动检测组织。 接受的值:falsetrue
git-service-endpoint-id 可选。 用于连接到外部终结点的服务终结点。
%> Azure DevOps 组织 URL。 可以使用 az devops configure -d organization=<ORG_URL> 配置默认组织。 如果未配置为默认或未通过 git 配置选取,则为必需。示例:https://dev.azure.com/MyOrganizationName/
%> 项目的名称或 ID。 可以使用 az devops configure -d project=<NAME_OR_ID> 配置默认项目。 如果未配置为默认或通过 git 配置进行选取,则为必需。
repository 要在其中创建导入请求的存储库的名称或 ID。
requires-authorization 指示源 git 存储库是否为专用存储库的标志。 如果需要身份验证,则在源存储库上生成身份验证令牌,并将环境变量 AZURE_DEVOPS_EXT_GIT_SOURCE_PASSWORD_OR_PAT 设置为该令牌的值。 然后,导入请求将包括身份验证。
subscription 订阅的名称或 ID。 可以使用 az account set -s <NAME_OR_ID> 配置默认订阅。
user-name 指定 git 存储库何时为专用存储库的用户名。

示例

以下命令将公共存储库 fabrikam-open-source 导入到空的 Git 存储库 fabrikam-open-source 以用于默认配置 az devops configure --defaults organization=https://dev.azure.com/fabrikamprime project="Fabrikam Fiber"

az repos import create --git-source-url https://github.com/fabrikamprime/fabrikam-open-source --repository fabrikam-open-source
{
  "detailedStatus": {
    "allSteps": [
      "Processing request",
      "Analyzing repository objects",
      "Storing objects",
      "Storing index file",
      "Updating references",
      "Import completed successfully"
    ],
    "currentStep": 6,
    "errorMessage": null
  },
  "importRequestId": 8,
  "parameters": {
    "deleteServiceEndpointAfterImportIsDone": null,
    "gitSource": {
      "overwrite": false,
      "url": "https://github.com/fabrikamprime/fabrikam-open-source"
    },
    "serviceEndpointId": null,
    "tfvcSource": null
  },
  "repository": {
    "defaultBranch": null,
    "id": "0f6919cd-a4db-4f34-a73f-2354114a66c4",
    "isDisabled": false,
    "isFork": null,
    "name": "new-empty-repo",
    "parentRepository": null,
    "project": {
      "abbreviation": null,
      "defaultTeamImageUrl": null,
      "description": "Guidance and source control to foster a vibrant ecosystem for Fabrikam Fiber applications and extensions.",
      "id": "56af920d-393b-4236-9a07-24439ccaa85c",
      "lastUpdateTime": "2021-05-24T21:52:14.95Z",
      "name": "Fabrikam Fiber",
      "revision": 438023732,
      "state": "wellFormed",
      "url": "https://dev.azure.com/fabrikamprime/_apis/projects/56af920d-393b-4236-9a07-24439ccaa85c",
      "visibility": "private"
    },
    "remoteUrl": "https://fabrikamprime@dev.azure.com/fabrikamprime/Fabrikam%20Fiber/_git/fabrikam-open-source",
    "size": 12477,
    "sshUrl": "git@ssh.dev.azure.com:v3/kelliott/Fabrikam%20Fiber/new-empty-repo",
    "url": "https://dev.azure.com/fabrikamprime/56af920d-393b-4236-9a07-24439ccaa85c/_apis/git/repositories/0f6919cd-a4db-4f34-a73f-2354114a66c4",
    "validRemoteUrls": null,
    "webUrl": "https://dev.azure.com/fabrikamprime/Fabrikam%20Fiber/_git/fabrikam-open-source"
  },
  "status": "completed",
  "url": "https://dev.azure.com/fabrikamprime/Fabrikam%20Fiber/_apis/git/repositories/0f6919cd-a4db-4f34-a73f-2354114a66c4/importRequests/8"
}

使用 git CLI 手动导入存储库

TFS 2017 Update 1 中引入了导入存储库功能。 如果使用 TFS 2017 RTM 或更早版本,则可以使用以下步骤将存储库手动导入 TFS。 还可以按照以下步骤将存储库手动导入 Azure DevOps Services 存储库,方法是在以下步骤中将 TFS 替换为 Azure Repos。

  1. 使用 bare 选项将源存储库克隆到计算机上的临时文件夹,如以下命令行示例所示,然后导航到存储库的文件夹。 使用 bare 选项进行克隆时,文件夹名称包含 .git 后缀。 在此示例中,https://github.com/contoso/old-contoso-repo.git 是要手动导入的源存储库。

    git clone --bare https://github.com/contoso/old-contoso-repo.git
    cd old-contoso-repo.git
    
  2. 使用 TFS 2017 RTM 创建目标存储库,并记下克隆 URL。 在此示例中,https://dev.azure.com/contoso-ltd/MyFirstProject/_git/new-contoso-repo 是新目标存储库的 URL。

  3. 运行以下命令,将源存储库复制到目标存储库。

    git push --mirror https://dev.azure.com/contoso-ltd/MyFirstProject/_git/new-contoso-repo
    

    警告

    使用 --mirror 将覆盖目标存储库中的所有分支,包括删除不在源存储库中的任何分支。

  4. 如果源存储库具有 LFS 对象,提取这些对象,并将其从源存储库复制到目标存储库。

    git lfs fetch origin --all
    git lfs push --all https://dev.azure.com/contoso-ltd/MyFirstProject/_git/new-contoso-repo
    
  5. 通过运行以下命令删除临时文件夹。

    cd ..
    rm -rf old-contoso-repo.git
    

常见问题

虽然大多数情况下导入会成功,但以下情况可能会导致问题。

如果源存储库支持双因素身份验证,会怎么样?

导入服务使用 REST API 来验证和触发导入,无法直接处理需要双因素身份验证的存储库。 GitHubAzure DevOps Services 等大多数 Git 托管提供程序都支持可以提供给导入服务的个人令牌。

如果源存储库不支持 multi_ack,会怎么样?

导入服务在导入过程中使用 Git 协议的 multi_ack 功能。 如果源存储库不提供此功能,则导入服务可能无法从给定源进行导入。 创建导入请求时或正在进行导入时,可能会发生此故障。

是否可以从以前版本的 Team Foundation Server 导入?

如果源 Git 存储库的 TFS 版本早于 TFS 2017 RTM,则导入将失败。 发生这种情况的原因是最新的 Azure DevOps Services/TFS 与 TFS 2017 RTM 之前版本之间的协定不匹配。

是否可以使用基于 MSA 的凭据?

很遗憾,基于 MSA(Microsoft 帐户,以前是 Live ID)的凭据将不起作用。 导入服务依赖于基本身份验证来与源存储库通信。 如果使用的用户名/密码不是基本身份验证,则身份验证将失败,导入也将失败。 检查使用的用户名/密码是否是基本身份验证的一种方法是尝试使用以下格式使用 Git 克隆存储库

git clone https://<<username>>:<<password>>@<<remaining clone Url>>

是否可以从 TFVC 导入?

可以将代码从现有 TFVC 存储库迁移到同一帐户中的新 Git 存储库。 虽然迁移到 Git 有很多好处,但对于大型 TFVC 存储库和团队来说,这是一个复杂的过程。 TFVC 等集中式版本控制系统在基本方面与 Git 有所不同。 切换涉及的不仅仅是学习新命令。 这是一项中断性变更,需要仔细规划。 有关详细信息,请参阅从 TFVC 导入到 Git

如果源存储库包含 Git LFS 对象,会怎么样?

Git 导入不会导入 Git LFS 对象。

可以使用以下步骤移动 LFS 对象:

  • 使用导入存储库功能将存储库导入 Azure DevOps。 这会将所有 Git 对象从源复制到 Azure DevOps(这也会导入 LFS 指针,这些指针是 Git 对象,而不是 LFS 文件)

若要移动 LFS 文件(需要同一框中的 Git.exe 和 LFS 客户端以及对源存储库和目标存储库的访问权限)

  • 将导入的存储库从 Azure DevOps 克隆到本地系统,克隆将正常工作,但在签出 LFS 文件时会失败
  • 将源存储库添加为远程库(例如“源”)
  • 执行 git lfs fetch source --all(这会将源中的所有 LFS 文件引入到本地存储库)
  • 假设目标 VSTS 存储库是“目标”远程库
  • 执行 git lfs push target --all

如果源以后发生更改,我是否可以导入更新?

导入服务最初用于导入整个存储库。 若要镜像以后的更改,需要存储库的本地克隆,并将远程库设置为源和目标。

可以使用以下命令同步更改。 我们将 Azure Repos 导入视为 origin,将原始存储库视为 upstream

git clone --bare <Azure-Repos-clone-URL>.git
cd <name-of-repo>
git remote add --mirror=fetch upstream <original-repo-URL>
git fetch upstream --tags
git push origin --all

后续步骤