git cherry-pick
74

# Git 高级操作:如何将特定提交从一个远程仓库“移植”到另一个

在日常开发中,我们有时会遇到这样的场景:一个本地 Git 项目关联了两个远程仓库 A 和 B。在开发过程中,我们可能长期将代码推送到远程仓库 B。但随着时间推移,出于项目管理、团队协作或代码整合的需要,我们可能希望转而基于远程仓库 A 进行开发,甚至需要将远程仓库 B 中的某些特定提交(commits)“移植”到远程仓库 A 上。

此时git cherry-pick 命令就成为了我们的得力助手。

---

什么是 git cherry-pick?

git cherry-pick 的作用是“挑选”一个或多个**已存在的提交(commit)**,并将其应用到**当前所在的分支**上。

它会为每个被挑选的提交**创建一个新的提交**,这个新提交的内容会与原提交完全一致,但其提交 ID(SHA 值)和提交时间将是新的。

**核心思想:** 精准地“复制”你想要的某段历史修改,而不必合并整个分支。

---

操作步骤详解

假设你的情况是:

* **本地仓库:** 你的项目文件夹。

* **远程仓库 A:** 例如,名为 origin,是你的主要开发仓库。

* **远程仓库 B:** 例如,名为 another_remote,你从这里获取一些提交。

第一步:检查本地仓库状态并切换目标分支

在进行任何可能修改 Git 历史的操作之前,务必确保你的工作区是干净的,并且你处于正确的目分支。

1. **检查工作区是否干净:**

```bash

git status

```

* 如果命令行显示 nothing to commit, working tree clean,说明你的工作区是干净的,可以继续。

* 如果存在未提交的更改,你需要先将其处理:

* 使用 git add .git commit -m "保存当前工作" 来提交这些更改。

* 或者使用 git stash 命令将当前更改暂时存起来(后续可以用 git stash pop 恢复)。

2. **切换到你想应用提交的目标分支(通常是远程仓库 A 对应的分支):**

假设你想将代码移植到 main 分支。

```bash

git branch # 查看当前所有的本地分支,带有星号(*)的是你当前所在的分支。

git checkout main # 如果你不在 main 分支,请切换到 main 分支。

```

第二步:添加并更新远程仓库 B 的信息

如果你的本地仓库还没有关联远程仓库 B,你需要先添加它。否则,直接更新其信息。

1. **添加远程仓库 B (如果未添加过):**

假设远程仓库 B 的 URL 是 https://github.com/user/repo_B.git,我们给它一个本地别名 another_remote

```bash

git remote add another_remote [https://github.com/user/repo_B.git](https://github.com/user/repo_B.git)

```

* 你可以通过 git remote -v 命令来查看所有已配置的远程仓库及其 URL。

2. **从远程仓库 B 拉取最新提交信息:**

这一步是为了确保你的本地 Git 知道远程仓库 B 的所有最新提交历史,但**不会将代码合并到你当前的分支**。

```bash

git fetch another_remote

```

现在another_remote 上的所有分支和提交历史都会同步到你的本地 Git 数据库中,你可以查看这些提交,它们通常以 another_remote/分支名 的形式存在。

第三步:查找并选择要“挑选”的提交

你需要找到你想要从远程仓库 B 中“挑选”出来并应用到当前分支上的那些提交的 **SHA 值**(或称 Commit ID)。

1. **查看远程仓库 B 特定分支的提交历史:**

假设你想从 another_remote 仓库的 feature-branch 分支中选择提交。

```bash

git log another_remote/feature-branch

```

这会显示 another_remote/feature-branch 分支上所有的提交历史,从最新到最旧。

**示例输出:**

commit abcdef1234567890abcdef1234567890abcdef (HEAD -> another_remote/feature-branch)
Author: User B <userb@example.com>
Date: Mon Jun 10 10:00:00 2024 +0800
feat: Add new user profile page # 这是你想挑选的第一个提交
commit 1234567890abcdef1234567890abcdef123456
Author: User B <userb@example.com>
Date: Sun Jun 9 15:30:00 2024 +0800
fix: Resolve login issue # 这是你想挑选的第二个提交

每个提交都由一个长串的十六进制字符开头,这就是它的 *SHA 值**。你通常只需要复制前 7-10 位左右就足够了,Git 能自动识别完整的提交。

* 仔细阅读提交信息feat: Add new user profile pagefix: Resolve login issue 等),找到你真正想要“挑选”的那些提交的 SHA 值。

第四步:执行 git cherry-pick 命令

现在,我们将选中的提交应用到你当前所在的分支(例如 main)上。

1. **挑选单个提交:**

[commit_sha] 替换为你刚刚复制的提交 SHA 值。

```bash

git cherry-pick [commit_sha]

```

* **示例:** git cherry-pick abcdef123

* 执行成功后,Git 会自动在你当前分支的顶部创建一个新的提交,其内容和被挑选的提交完全相同。

2. **挑选多个提交(按顺序):**

如果你需要挑选多个提交,并且这些提交之间存在依赖关系(例如,后面一个提交是基于前一个提交的改动),你应该按照它们在**原始历史记录中从旧到新**的顺序来挑选。

```bash

git cherry-pick [commit_sha_older] [commit_sha_newer] ...

```

* **示例:** git cherry-pick 1234567 abcdef123 (先挑选较旧的 1234567,再挑选较新的 abcdef123

3. **处理冲突:**

* **非常重要:** 在 cherry-pick 过程中,如果被挑选的提交与你当前分支上的代码存在冲突(即两者修改了同一文件的同一部分),Git 会暂停操作,并报告冲突。

* **解决冲突的步骤:**

1. Git 会在冲突文件中标记出冲突的部分(通常用 <<<<<<<, =======, >>>>>>> 这样的特殊符号)。

2. 使用你的代码编辑器(如 VS Code)手动编辑这些文件,根据需求选择你想要保留的代码。

3. 解决所有冲突后,保存文件。

4. 使用 git add . 命令将解决冲突后的文件标记为已解决。

5. 最后,继续 cherry-pick 过程:

```bash

git cherry-pick --continue

```

如果你想放弃当前的 cherry-pick 操作,可以使用:

```bash

git cherry-pick --abort

```

这将撤销 cherry-pick 的所有更改,并回到 cherry-pick 命令执行之前的状态。

第五步:推送更改到远程仓库 A

当所有的 cherry-pick 操作都成功完成,并且你已经解决了所有冲突后,你的本地分支(例如 main)现在就包含了从远程仓库 B 移植过来的新提交。最后一步是将这些更改推送到你的主要远程仓库 A origin)。

1. **可选:再次查看本地日志确认新提交:**

```bash

git log

```

你会看到新挑选的提交现在已经存在于你本地分支的历史记录中。

2. **推送到远程仓库 A:**

```bash

git push origin main

```

* origin 是你的远程仓库 A 在本地的别名。

* main 是你要推送的本地分支名称。

---

**重要提示:**

git cherry-pick 会为每个挑选的提交创建一个*新的提交**,这意味着这些新提交的 SHA 值与原始提交的 SHA 值是不同的。这会改变历史记录。

cherry-pick 最适合用于移植*少量、独立**的提交。如果你需要合并大量的提交,或者需要保持完整的历史链git mergegit rebase 可能是更合适的选择(但这两种操作的学习曲线相对更陡峭,且 rebase 会改写历史,需谨慎使用)。

在进行任何可能修改 Git 历史的操作之前,务必养成*备份**或者在**独立的功能分支**上进行操作的良好习惯,以防万一。

希望这份详细的教程能帮助你更好地理解和使用 git cherry-pick

git cherry-pick
https://zdbxll.cn/archives/git-cherry-pick-shi-yong
作者
Administrator
发布于
更新于
许可