Git 提取拉取请求:解锁熟练程度
Nicola Paolucci
开发人员推广人员
如今,对项目应用修复就像创建克隆一样简单,它会提供项目的完整远程副本供您修改,具体方法是选择您要变更的文件,然后按下编辑并提交修复。
如果您在拉取请求(下文缩写为 PR)的接收端会怎样?使用精美的 Web 用户界面很棒,通常这正是您所需要的。点击按钮进行批准,点击按钮合并,然后就完成了。
但情况并非总是如此!通常需要在本地下载拉取请求 (PR) 中包含的变更,运行一些测试,看看它们在您 IDE 中的样子才能理解所做的事情。
您的同事或贡献者的拉取请求的下载步骤(更明确地说是 fetch
和 checkout
)在概念上很简单,但是如果您知道一些重要的细节和提示,它们就会变得更容易。
我来帮助您更好地理解 git
为您提供的命令行功能,让您能轻松处理来自命令行的拉取请求。
在我们开始之前:用分支名称和状态丰富您的 shell 提示符
我总是感到惊讶,有很多人只有一个裸命令提示符,该提示符没有显示他们所在的 git
分支,或者工作目录中是否有修改/未提交的文件。如果您觉得您就是这样,不妨让我来帮助您,结果肯定会让您大吃一惊!
安装 liquid prompt 这样的提示,它将为您的 git
工作目录的状态提供很好的注释(也支持任何其他 VCS):
(在上面的屏幕截图中,您会看到我的提示提醒我,我在 newbranch
分支上,在跟踪的工作目录文件中添加了 5
行,并且已经删除了 0
行)
相关资料
安装 Git
查看解决方案
了解 Bitbucket Cloud 的 Git
每个人都在同一个存储库中工作
如果您和您的团队在同一个存储库上工作,那么签出拉取请求的流程非常简单:只需 fetch
并 checkout
创建拉取请求的分支即可:
- 获取在共享存储库上发布的所有分支:
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 Data Center)和 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 Data Center)开发人员所指出的那样,我在下面演示的引用被视为 undocumented
和 private
,可能随时变更。
下载所有拉取请求: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,就可以轻松关注同行或贡献者的工作。
分享此文章
下一主题
推荐阅读
将这些资源加入书签,以了解 DevOps 团队的类型,或获取 Atlassian 关于 DevOps 的持续更新。