Git/GitHub 分支调查与 cherry-pick 实战:只保留需要的提交
前言
在使用 GitHub 管理代码时,有时会遇到这样的情况:
本地 Git 工具中显示当前位于某个 branch,但在 GitHub 仓库页面中却找不到这个 branch。进一步确认后发现,这个 branch 只是本地分支,并没有 push 到 GitHub 远程仓库。
本篇文章将围绕一次真实问题,整理 Git 分支调查、远程确认、提交差异确认、cherry-pick、删除本地分支等常用操作。
文章分为三部分:
-
一览:本文涉及的 Git command 索引
-
详细指引:各命令的用途与简单示例
-
真实案例:只保留 docs 提交,丢弃 Java 25 分支修改
一、Git command 一览
| Command | 大致功能 | 基本语法 |
|---|---|---|
git remote -v |
查看当前本地仓库绑定的远程仓库地址 | git remote -v |
git status |
查看当前工作区状态 | git status |
git status -sb |
用简洁格式查看当前分支与状态 | git status -sb |
git branch |
查看本地分支列表 | git branch |
git branch -a |
查看本地分支和远程分支 | git branch -a |
git branch -vv |
查看本地分支及其追踪的远程分支 | git branch -vv |
git ls-remote --heads origin <branch> |
直接确认远程仓库是否存在某个 branch | git ls-remote --heads origin branch-name |
git log --oneline --decorate --graph |
以简洁图形方式查看提交历史 | git log --oneline --decorate --graph |
git log main..<branch> |
查看某 branch 中有、但 main 中没有的提交 | git log --oneline --decorate --graph main..branch-name |
git diff --name-status main...<branch> |
查看某 branch 与 main 的文件差异 | git diff --name-status main...branch-name |
git diff main...<branch> |
查看某 branch 与 main 的详细内容差异 | git diff main...branch-name |
git switch <branch> |
切换到指定 branch | git switch main |
git pull origin main |
从远程 main 拉取最新内容 | git pull origin main |
git cherry-pick <commit-id> |
只把某一个提交应用到当前分支 | git cherry-pick eacc603 |
git push origin main |
将本地 main 推送到 GitHub 远程 main | git push origin main |
git branch -d <branch> |
删除已经合并的本地分支 | git branch -d branch-name |
git branch -D <branch> |
强制删除本地分支 | git branch -D branch-name |
二、详细指引
1. 查看当前本地仓库绑定的 GitHub 仓库
git remote -v
这个命令用于确认当前本地项目连接的是哪个远程仓库。
示例输出:
origin https://github.com/user/project.git (fetch)
origin https://github.com/user/project.git (push)
其中:
-
origin是远程仓库的默认名称 -
(fetch)表示拉取代码时使用的地址 -
(push)表示推送代码时使用的地址
当本地分支和 GitHub 页面显示不一致时,首先应该确认自己正在看的 GitHub 仓库是否就是当前项目绑定的远程仓库。
2. 查看当前工作区状态
git status
该命令用于确认当前分支、是否存在未提交修改、是否有文件处于 staged 状态等。
简洁版命令:
git status -sb
示例:
## main...origin/main
表示当前在 main 分支,并且该分支正在追踪 origin/main。
在执行切换分支、删除分支、cherry-pick 等操作之前,建议先执行一次 git status,避免未提交内容被误操作影响。
3. 查看本地分支
git branch
示例:
* appmod/java-upgrade-20260419141900
main
其中 * 表示当前所在分支。
上面的例子表示当前本地有两个分支:
-
appmod/java-upgrade-20260419141900 -
main
当前位于:
appmod/java-upgrade-20260419141900
4. 查看本地分支与远程分支的追踪关系
git branch -vv
示例:
* appmod/java-upgrade-20260419141900 eacc603 2026-06-T1 补充了文档
main 281fc04 [origin/main] Prepared backend and frontend frameworks
这里可以看出:
main [origin/main]
表示本地 main 正在追踪远程的 origin/main。
而:
appmod/java-upgrade-20260419141900
后面没有 [origin/xxx],说明这个分支只是本地分支,并没有绑定远程分支。
这就是为什么 GitHub 网页中看不到这个 branch。
5. 查看所有本地与远程分支
git branch -a
该命令会显示本地分支和远程分支。
示例:
* appmod/java-upgrade-20260419141900
main
remotes/origin/main
如果没有看到:
remotes/origin/appmod/java-upgrade-20260419141900
说明远程仓库中没有这个 branch。
6. 直接确认远程仓库是否存在某个 branch
git ls-remote --heads origin appmod/java-upgrade-20260419141900
如果远程仓库中存在该 branch,会显示类似:
eacc603... refs/heads/appmod/java-upgrade-20260419141900
如果没有任何输出,说明 GitHub 远程仓库中不存在这个 branch。
7. 查看某 branch 比 main 多了哪些提交
git log --oneline --decorate --graph main..appmod/java-upgrade-20260419141900
这个命令的含义是:
查看 appmod/java-upgrade-20260419141900 中存在、但 main 中不存在的提交。
示例:
* eacc603 2026-06-T1 补充了文档
* a12b345 Upgrade Java version to 25
这说明该 branch 比 main 多了两个提交:
-
一个 docs 文档提交
-
一个 Java 版本升级提交
8. 查看两个 branch 之间的文件差异
只看文件名和变更状态:
git diff --name-status main...appmod/java-upgrade-20260419141900
示例:
M pom.xml
A docs/project-roadmap.md
A docs/task-board.md
含义:
-
M:Modified,文件被修改 -
A:Added,文件被新增 -
D:Deleted,文件被删除
查看详细差异:
git diff main...appmod/java-upgrade-20260419141900
查看该 branch 相对于 main 分支分叉点之后产生的文件差异,适合用来确认“如果把这个 branch 合入 main,会带来哪些文件变化”。
9. 切换 branch
git switch main
该命令会切换到 main 分支。
注意:
切换分支后,工作目录中的文件内容会变成目标分支对应的状态。
例如:
当前 branch 是 Java 25 版本,切换回 main 后,如果 main 仍然是 Java 17,那么项目文件会回到 Java 17 的状态。
10. 拉取远程 main 的最新内容
git pull origin main
在向 main 合并或 cherry-pick 之前,建议先拉取远程最新内容,避免本地 main 落后于 GitHub 上的 main。
11. 只把某一个 commit 带到当前分支
git cherry-pick <commit-id>
示例:
git cherry-pick eacc603
该命令的含义是:
把 eacc603 这个提交应用到当前所在分支。
例如当前在 main 分支,执行:
git cherry-pick eacc603
就会把 eacc603 对应的修改带到 main,但不会把同一个 branch 上的其他提交一起带过来。
这非常适合以下场景:
-
一个 branch 里有多个提交
-
其中只有部分提交有价值
-
不想 merge 整个 branch
-
只想保留某个特定提交
12. 推送 main 到 GitHub
git push origin main
当本地 main 已经包含需要的修改后,可以使用这个命令将内容推送到 GitHub 远程仓库。
13. 删除本地分支
普通删除:
git branch -d appmod/java-upgrade-20260419141900
如果该分支没有被合并,Git 可能会拒绝删除。
强制删除:
git branch -D appmod/java-upgrade-20260419141900
-D 表示强制删除本地分支。
在确认需要的提交已经保存到 main 后,可以使用 -D 删除无价值的本地分支。
三、真实案例:保留 docs,删除 Java 25 分支
1. 问题背景
本地 Git GUI 中显示当前 branch 是:
appmod/java-upgrade-20260419141900
但是在 GitHub 仓库的 Branches 页面中,只能看到:
main
没有看到:
appmod/java-upgrade-20260419141900
于是需要确认这个 branch 到底是什么状态。
2. 先确认远程仓库
执行:
git remote -v
确认当前本地项目绑定的 GitHub 仓库是正确的。
3. 确认 branch 是本地分支
执行:
git branch -vv
输出类似:
* appmod/java-upgrade-20260419141900 eacc603 2026-06-T1 补充了文档
main 281fc04 [origin/main] Prepared backend and frontend frameworks
可以看到:
main [origin/main]
说明 main 绑定了远程 origin/main。
但是:
appmod/java-upgrade-20260419141900
后面没有 [origin/...]。
因此可以判断:
该 branch 是本地分支,没有 push 到 GitHub 远程仓库。
4. 进一步分析 branch 内容
该 branch 中包含 Java 25 相关修改,而 main 中使用的是 Java 17。
目标是:
-
保留
main的 Java 17 版本 -
不要 Java 25 修改
-
但是保留该 branch 中已经写好的 docs 文档
-
最后删除这个本地 branch
进一步确认后发现:
Java 25 修改和 docs 文档修改是两次不同的 commit。
这时不适合直接 merge 整个 branch。
因为 merge 会把 Java 25 修改也带入 main。
更合适的做法是:
只 cherry-pick docs 对应的 commit。
5. 查看 branch 比 main 多了哪些 commit
执行:
git log --oneline --decorate --graph main..appmod/java-upgrade-20260419141900
示例输出:
eacc603 2026-06-T1 补充了文档
a12b345 Upgrade Java version to 25
这里假设:
eacc603
是 docs 文档提交。
而:
a12b345
是 Java 25 版本修改提交。
6. 切换回 main
执行:
git switch main
此时本地文件夹内容会回到 main 分支状态。
也就是说,Java 版本会回到 main 中的 Java 17。
7. 拉取远程 main 最新内容
执行:
git pull --ff-only origin main
git pull origin main 在某些情况下可能产生 merge commit。
而 --ff-only 表示只允许快进更新,如果本地 main 和远程 main 发生分叉,Git 会停止并报错,不会自动制造新的 merge commit。
8. 只 cherry-pick docs 提交
执行:
git cherry-pick eacc603
这会把 docs 提交应用到当前的 main 分支。
如果 docs commit 依赖前一个 Java 25 commit,或者 docs commit 本身也修改了 Java 版本相关文件,那么 cherry-pick 后仍可能产生冲突或带入不需要的修改。
结果是:
-
docs 文档被带入
main -
Java 25 修改不会被带入
main
9. 推送 main 到 GitHub
执行:
git push origin main
这样 GitHub 上的 main 就会包含 docs 文档。
10. 删除本地 Java 25 分支
确认当前已经在 main:
git branch
输出中应该显示:
* main
appmod/java-upgrade-20260419141900
然后删除本地分支:
git branch -D appmod/java-upgrade-20260419141900
因为这个 branch 没有完整合并到 main,所以使用 -D 强制删除。
*删除前请确认目标 commit 已经 cherry-pick 到 main,并且 main 已经 push 成功。
11. 最终结果
最终状态:
-
GitHub 远程仓库中仍然只有
main -
本地无价值的 Java 25 branch 被删除
-
main保持 Java 17 -
docs 文档被保存到
main -
不需要的 Java 25 修改没有进入
main
总结
本次问题的关键点不是“GitHub 上为什么没有这个 branch”,而是先区分:
-
本地分支
-
远程分支
-
本地分支是否追踪远程分支
当确认 branch 只是本地分支后,还需要进一步确认该 branch 中的 commit 内容。
如果一个 branch 里只有部分提交有价值,不应该直接 merge 整个 branch。
更合适的方法是使用:
git cherry-pick <commit-id>
只把需要的 commit 带入目标分支。
本次处理流程可以总结为:
git remote -v
git branch -vv
git log --oneline --decorate --graph main..appmod/java-upgrade-20260419141900
git switch main
git pull --ff-only origin main
git cherry-pick eacc603
git push origin main
git branch -D appmod/java-upgrade-20260419141900
这套流程适合用于:
-
本地 branch 没有 push 到 GitHub
-
branch 中混入了不想保留的修改
-
只想保留某个 commit
-
想删除无价值的本地分支
更多推荐



所有评论(0)