引言

在参与开源项目或团队协作时,我们通常会从一个开发分支(如 devdevelop)拉取一个特性分支进行开发,完成功能或 Bug 修复后,向主分支(如 mainmaster)提交 Pull Request (PR)。一旦 PR 被合并,我们的修改就进入了主分支。

然而,有时我们希望将 PR 的内容也同步回我们的开发分支(例如 dev 分支),以便本地开发环境保持最新,或者将该修改作为后续开发的基础。本文将详细介绍如何使用 Git 的 cherry-pick 命令来实现这一目标,并分享我在实际操作中遇到的问题及解决方案。

什么是 git cherry-pick

git cherry-pick 命令的作用是将一个或多个现有提交应用到当前分支。它会复制指定提交的更改,并在当前分支上创建一个新的提交。这与 git mergegit rebase 不同,cherry-pick 只挑选特定的提交,而不是合并整个分支的历史。

适用场景:

  • 将其他分支的单个或少量提交合并到当前分支。
  • 将已合并到主分支的 PR 提交,同步回开发分支。
  • 从一个特性分支中挑选出部分提交,应用到另一个特性分支。

操作步骤:将 PR 提交同步到 dev 分支

假设您已经将 fix-page-cover 分支上的 Bug 修复提交到了官方仓库,并且现在希望将这个修复也应用到您的本地 dev 分支。

1. 确认当前分支

首先,确保您当前位于目标分支,即您希望应用 PR 提交的分支(例如 dev)。

1
2
3
4
5
# 查看当前分支
git branch

# 如果不在 dev 分支,切换到 dev
git checkout dev

2. 查找 PR 提交的 SHA 值

您需要找到包含您 PR 内容的那个提交的 SHA 值。如果您是在一个专门的特性分支上完成的 PR,那么这个提交通常是该特性分支的最后一个提交。

1
2
3
# 查看 fix-page-cover 分支的提交历史
# 找到包含 PR 内容的提交(通常是您为 PR 编写的 commit message)
git log --oneline fix-page-cover

例如,您可能会看到类似这样的输出:
8ae23cf Fix: Display cover images for categories and tags pages
这里的 8ae23cf 就是您需要的提交 SHA 值。

3. 执行 git cherry-pick

现在,在您的 dev 分支上执行 cherry-pick 命令,将找到的提交应用过来。

1
2
3
# 在 dev 分支上执行
git cherry-pick <提交的 SHA 值>
# 例如:git cherry-pick 8ae23cf

如果一切顺利,Git 会将该提交的更改应用到您的 dev 分支,并创建一个新的提交。

常见问题及排查

cherry-pick 过程中,您可能会遇到一些问题。

问题场景 1:git log 提示“有歧义的参数”或“路径未匹配任何 git 已知文件”

问题描述:当您尝试使用 git log --oneline <branch> <file_path> 这样的命令来查找特定文件的提交历史时,Git 可能会报错。

排查与解决:这是因为在 Git 命令中同时指定分支和文件路径时,需要使用 -- 来明确分隔它们,以消除歧义。

  • 解决方案:在文件路径前添加 --
    1
    git log --oneline fix-page-cover -- themes/butterfly/layout/includes/header/index.pug
    如果您不确定具体的文件路径,或者只想查看整个分支的提交历史,可以直接使用 git log --oneline <branch>

问题场景 2:git cherry-pick 提示“无文件要提交,干净的工作区” / “空提交”

问题描述:在执行 git cherry-pick 后,Git 提示“无文件要提交,干净的工作区”,并说明这是一个“空提交”。

排查与解决:这表明您当前分支的工作区已经包含了要 cherry-pick 的提交所引入的所有修改。Git 发现当前分支的文件内容与目标提交的修改是相同的,因此没有实际的更改需要应用,从而生成了一个空提交。

  • 解决方案:由于没有实际的修改,您可以直接跳过这个空提交,结束 cherry-pick 进程。
    1
    git cherry-pick --skip
    这通常意味着您之前已经通过其他方式(例如手动复制粘贴,或者更早的 cherry-pick 操作)将这些修改应用到了当前分支。

问题场景 3:git push 提示“无效引用:upstream/dev”

问题描述:当您尝试从 upstream 远程仓库检出文件时(例如 git checkout upstream/dev -- <file>),Git 提示“无效引用:upstream/dev”。

排查与解决:这表明您的本地仓库还没有从 upstream 远程仓库抓取最新的分支信息。

  • 解决方案:先执行 git fetch upstream 命令,将 upstream 远程仓库的所有分支信息同步到本地。
    1
    git fetch upstream
    然后再次尝试 git checkout upstream/dev -- <file>

问题场景 4:git push 提示“无法推送一些引用到…” (例如 error: 源引用规格 dev 没有匹配)

问题描述:在主仓库执行 git push 时,提示与分支引用相关的错误。

排查与解决:这通常是因为您本地仓库的当前分支与远程仓库的期望分支不匹配,或者远程仓库没有您尝试推送的那个分支。

  • 解决方案
    1. 确认当前分支:使用 git branch 确认您当前所在的分支。
    2. 确认远程仓库的分支结构:使用 git remote show origin 查看 origin 远程仓库的 HEAD 分支和已跟踪的分支。
    3. 匹配推送目标:确保您 git push 的本地分支与远程目标分支是匹配的。例如,如果您的主仓库默认分支是 main,而您尝试推送到 dev,就会报错。您需要将 git push origin dev 修改为 git push origin main(或您实际的主分支名)。
    4. 第一次推送新分支:如果您是第一次将本地分支推送到远程,需要使用 -u 参数设置上游跟踪:git push -u origin <branch_name>

总结

git cherry-pick 是一个非常实用的 Git 命令,可以帮助我们在复杂的协作流程中精确地管理提交。通过本文的介绍,您应该能够掌握如何将 Pull Request 的提交内容同步到开发分支,并解决过程中可能遇到的一些常见 Git 问题。熟练运用这些 Git 技巧,将使您的开发流程更加顺畅高效。