Close

Git 提取拉取请求:解锁熟练程度

Nicola Paolucci 头像
Nicola Paolucci

开发人员推广人员


如今,对项目应用修复就像创建克隆一样简单,它会提供项目的完整远程副本供您修改,选择您要更改的文件,然后按下编辑并提交修复。

如果您在拉取请求(下文缩写为 PR)的接收端会怎样?使用精美的 Web 用户界面很棒,通常这正是您所需要的。点击按钮进行批准,点击按钮合并,然后就完成了。

但情况并非总是如此!通常需要在本地下载拉取请求 (PR) 中包含的变更,运行一些测试,看看它们在您 IDE 中的样子才能理解所做的事情。

您的同事或贡献者的拉取请求的下载步骤(更明确地说是 fetchcheckout)在概念上很简单,但是如果您知道一些重要的细节和提示,它们就会变得更容易。

我来帮助您更好地理解 git 为您提供的命令行功能,让您能轻松处理来自命令行的拉取请求。

在我们开始之前:用分支名称和状态丰富您的 shell 提示符


我总是感到惊讶,有很多人只有一个裸命令提示符,该提示符没有显示他们所在的 git 分支,或者工作目录中是否有修改/未提交的文件。如果您觉得您就是这样,不妨让我来帮助您,结果肯定会让您大吃一惊!

安装 liquid prompt 这样的提示,它将为您的 git 工作目录的状态提供很好的注释(也支持任何其他 VCS):

(在上面的屏幕截图中,您会看到我的提示提醒我,我在 newbranch 分支上,在跟踪的工作目录文件中添加了 5 行,并且已经删除了 0 行)

Git 徽标
相关资料

安装 Git

Bitbucket 徽标
查看解决方案

了解 Bitbucket Cloud 的 Git

每个人都在同一个存储库中工作


如果您和您的团队在同一个存储库上工作,那么签出拉取请求的流程非常简单:只需 fetchcheckout 创建拉取请求的分支即可:

  • 获取在共享存储库上发布的所有分支:
git fetch origin
  • 创建一个本地分支来跟踪您感兴趣的远程分支:
git checkout -b PRJ-1234 origin/PRJ-1234
  • 现在您可以用这个比对合并、测试您的核心了:
git diff main ./run-tests.sh
  • 如果您满意,只需回到 Web 用户界面并提供反馈或直接批准变更即可。

贡献者负责自己的克隆


部分贡献者在不同的克隆中工作时,流程会有变更。在这种情况下,您可以 fetch 提交贡献或功能的远程分支:

  • 先添加贡献者的远程存储库:
git remote add jsmith http://bitbucket.org/jsmith/coolproject.git
  • 先从您的主存储库 origin 收集所有最新更新:
git checkout main git fetch origin git merge main
  • 获取贡献者克隆上发布的所有分支:
git fetch jsmith
  • 创建一个本地分支来跟踪您感兴趣的远程分支:
git checkout -b jsmith-PRJ-1234 jsmith/PRJ-1234
  • 现在您可以用这个比对合并、测试您的核心了:
git diff main ./run-tests.sh

使用拉取请求引用减少工作量


以上方法可行,但有几件事可能会给您带来困扰:

  • 如果您有很多合作者,每个人都有自己的克隆该怎么办?添加他们所有的克隆并单独处理是不切实际的。
  • 如果您连一些克隆都无法访问并且无法查看源分支该怎么办?

上述问题的解决方案是使用某些 git 服务器提供的拉取请求引用。我将要展示的程序由部分 git 服务器支持,并且根据您使用的服务器而略有不同。在下文中,我将介绍如何在 Stash(现在称为 Bitbucket Server)和 Github 上 fetch 所有拉取请求。

别害怕 Refspec

第一个先决条件是熟悉 Refspec。Refspec 很赞,不用害怕。它们是从远程分支到本地引用的简单映射,换句话说,告诉 git“这个远程分支(或这组远程分支)的直接方法应该在本地这个命名空间中映射到这些名称。”

例如,像这样的命令:

git fetch +refs/heads/main:refs/remotes/origin/main

会将您的 origin 远程上的远程分支 main 映射到本地 origin/main,这样您就可以输入:

git checkout origin/main

还要引用那个远程分支。定义中的加号 (+) 表示我们希望 git 更新引用,即使它不是快进。

我们使用它来下载所有拉取请求的方法是映射远程存储库存储 PR HEAD 的方式,并将它们映射到本地命名空间以便于引用。

因此,假设您定义了 origin(或 upstream)远程存储库,以下是要做的事情。

注意:正如几位 Stash(现在称为 Bitbucket Server)开发人员所指出的那样,我在下面演示的引用为 undocumentedprivate,可能随时变更。

下载所有拉取请求:Stash

  • 克隆存储库。
  • 在本地克隆您的克隆:
git clone git@stash.atlassian.com:durdn/tis.git
  • 上游原始存储库添加为 upstream 存储库。
git remote add upstream git@stash.atlassian.com:tpettersen/tis.git
  • 从 'upstream' 维护者那里获取最新的 HEAD
git fetch upstream
  • 添加 refspec,它将远程拉取请求 head 映射到本地 pr 命名空间。您可以用一个 config 命令来完成:
git config --add remote.origin.fetch '+refs/pull-requests/*/from:refs/remotes/origin/pr/*'
  • 如果您看一下 .git/config,会发现 fetch 条目变成:
[remote "upstream"]
    url = git@stash.atlassian.com:docker/libswarm.git
    fetch = +refs/heads/*:refs/remotes/upstream/*
    fetch = +refs/pull-requests/*/from:refs/remotes/upstream/pr/*
  • 现在您可以轻松 fetch 所有拉取请求分支了:
$ git fetch upstream

remote: Counting objects: 417, done.
remote: Compressing objects: 100% (274/274), done.
remote: Total 417 (delta 226), reused 277 (delta 128)
Receiving objects: 100% (417/417), 105.28 KiB | 0 bytes/s, done.
Resolving deltas: 100% (226/226), done.

From stash.atlassian.com:docker/libswarm
 * [new ref]         refs/pull-requests/10/from-> upstream/pr/10
 [...]
 * [new ref]         refs/pull-requests/100/from -> upstream/pr/100
 * [new ref]         refs/pull-requests/101/from -> upstream/pr/101
 [...]
 * [new ref]         refs/pull-requests/109/from -> upstream/pr/109
 * [new ref]         refs/pull-requests/110/from -> upstream/pr/110
 [...]
  • 现在要切换到特定的拉取请求,您只需:
git checkout pr/102

下载所有拉取请求:Github

如果克隆或上游在 Github 上,则其工作原理与上面完全相同,但 config 命令变更为:

 git config --add remote.origin.fetch '+refs/pull//head:refs/remotes/origin/pr/'

还有 .git/config 中的远程存储库将变更为包含额外的 fetch 配置,用于将 PR head 映射到名为 pr 的本地命名空间:

[remote "upstream"] url = git@github.com:docker/libswarm.git fetch = +refs/heads/*:refs/remotes/upstream/* fetch = +refs/pull/*/head:refs/remotes/upstream/pr/*

使用 refs 获取单个拉取请求

如果您不想在 .git/config 中设置 fetch 条目,只想快速得到一个拉取请求,只需一个命令就可以:

  • Stash 中查看单个 PR:
git fetch refs/pull-requests/your-pr-number/from:local-branch-name
  • 在 Github 上查看单个 PR:
git fetch refs/pull/your-pr-number/head:local-branch-name

如果您发现自己经常使用上述方法,您可以通过创建 git 别名来简化流程:

# For Stash
git config alias.spr '!sh -c "git fetch origin pull-requests/${1}/from:pr/${1}" -'

# For Github
git config alias.gpr '!sh -c "git fetch origin pull/${1}/head:pr/${1}" -'

配置好这个别名后,我们可以用一个简单的(谢谢 inuit)来获取拉取请求:

总结


希望您觉得这个有用!最后,只要您创建几个简单的别名或在 .git/config 中添加正确的 refspec,就可以轻松关注同行或贡献者的工作。您可以在 Twitter 上 @durdn@AtlDevtools 提出任何问题,我们很乐意为您提供解答。

Nicola Paolucci

Nicola is an all-round hacker who loves exploring and teaching bleeding edge technologies. He writes and talks about Git, development workflows, code collaboration and more recently about Docker. Prior to his current role as Developer Instigator at Atlassian he led software teams, built crowd sourcing applications for geo-spacial data, worked on huge e-commerce deployments. Little known facts about Nicola: he gesticulates a lot while speaking (being Italian), lives in Amsterdam and rides a Ducati.


分享此文章

推荐阅读

将这些资源加入书签,以了解 DevOps 团队的类型,或获取 Atlassian 关于 DevOps 的持续更新。

人们通过满是工具的墙进行协作

Bitbucket 博客

Devops 示意图

DevOps 学习路径

与 Atlassian 专家一起进行 Den 功能演示

Bitbucket Cloud 与 Atlassian Open DevOps 如何协同工作

注册以获取我们的 DevOps 新闻资讯

Thank you for signing up