git cherry-pick和git stash命令详解
git cherry-pick命令
-
定义
- 用于将指定的提交(commit)从一个分支"挑选"并应用到当前分支
- 它复制某个提交的更改(diff),生成一个新的提交,保留原提交的更改内容,但拥有新的提交ID(SHA值)
-
命令
-
git cherry-pick <commit-id>
-
-
核心功能
- 提取单个或多个提交的更改,应用到目标分支
- 不影响分支的整体历史,仅复制指定提交
- 适合修复bug、移植特性或整理提交
-
适用场景
- 需要从一个分支移植一个特定更改到另一个分支时非常有用
-
示例
-
# 假设有以下分支 # main分支有提交A、B、C。 # feature分支从B分叉,包含提交D、E、F。 A---B---C (main)\D---E---F (feature)# 现在将feature分支的提交E(例如一个Bug修复)应用到main,但不想要D或F。 # 首先切换到main分支 git switch main # git checkout main # 然后执行cherry-pick,选择提交E(假设E的SHA值为e123456) # 如果无冲突,Git会在main分支创建一个新提交E',包含E的更改 git cherry-pick e123456# 提交后的结果 A---B---C---E' (main)\D---E---F (feature)# 如果有冲突,提示错误信息,如下 error: could not apply e123456... [commit message]# 手动解决冲突,解决完成后 git add <file># 继续cherry-pick git cherry-pick --continue# 或者放弃cherry-pick git cherry-pick --abort
-
-
批量cherry-pick
-
# 挑选多个提交(如E和F) git cherry-pick e123456 f789012# 或指定范围(从D到F,不包括D) git cherry-pick D..F
-
-
优点
- 精准选择
- 只引入特定提交,避免不需要的更改,灵活性高
- 适合移植bug修复或特定功能
- 独立操作
- 不影响源分支或整体历史,仅在当前分支生成新提交
- 便于协作
- 可快速将关健修复从开发分支应用到生产分支
- 简单直观
- 相比
merge
和rebase
,操作单一,易于理解和执行
- 相比
- 精准选择
-
缺点
- 手动挑选成本高
- 需要知道具体提交的SHA值或范围,手动操作繁琐
- 不适合大量提交的整合
- 冲突处理复杂
- 如果cherry-pick的提交依赖其他未挑选的提交,可能导致冲突或功能不完整
- 冲突需手动解决,多次
cherry-pick
可能重复处理类似冲突
- 历史重复
cherry-pick
生成新提交,可能导致代码重复(若后续合并源分支)- 例如:E’和E可能在在未来合并时造成冲突
- 丢失上下文
- 只复制提交内容,丢失原提交的完整分支上下文,调试或追溯可能困难
- 手动挑选成本高
-
适用场景
- 修复bug
- 将开发分支的bug修复快速应用到生产分支
- 移植特性
- 将特性分支的某些功能引入其他分支(如实验性功能)
- 清理历史
- 挑选关键提交,整理分支历史,结合
rebase
适用
- 挑选关键提交,整理分支历史,结合
- 临时整合
- 在合并整个分支前,测试特定提交的效果
- 修复bug
-
与
merge
和rebase
对比- vs
merge
merge
整合整个分支,保留历史(快进线性或非快进线性)cherry-pick
只选特定提交,适合精细控制
- vs
rebase
rebase
重放整个分支历史,生成线性历史cherry-pick
只重放指定提交,操作更局部
- vs
git stash命令
- 定义
- 用于临时保存工作目录和索引(暂存区)的更改,并将工作目录恢复到最近一次提交的状态(干净状态)
- 它将未提交的更改(包括已跟踪文件的修改和暂存的更改)存储到一个栈(stash stack)中,供后续恢复或应用
- 命令
git stash
- 核心功能
- 保存未提交的更改(工作目录和暂存区)
- 清理工作目录,恢复到最近的提交状态
- 允许稍后恢复或应用保存的更改到当前或其他分支
- 目的
- 避免提交临时更改:在切换分支、拉取代码或执行其他操作时,临时保存未完成的工作
- 保持工作目录干净:确保工作目录无未提交更改,便于git操作(如合并、变基)
- 灵活管理更改:支持多次stash,随时恢复或丢弃
功能与命令
- 保存更改
- 保存工作目录和暂存区的更改到stash栈
- 默认保存已跟踪文件的修改(包括暂存和未暂存更改)
- 恢复工作目录
- 将工作目录和暂存区恢复到最近提交的状态
- 恢复更改
- 将工作目录和暂存区恢复到最近提交的状态
- 恢复更改
- 从stash栈中恢复保存的更改到当前分支
- 管理stash
- 查看、应用、删除或清理stash记录
常用命令
-
保存更改
-
git stash# 默认保存更改,命名为stash@{n}(n为栈索引,从0开始)# 添加描述 git stash push -m 'message'
-
保存未跟踪文件,包含未跟踪文件(如新文件)
-
git stash -u
-
保存所有文件,包含未跟踪和忽略文件。
git stash -a
-
查看stash列表
git stash list# 显示所有stash记录,例如 stash@{0}: WIP on feature: abc1234 Add feature X stash@{1}: On main: def5678 Temp changes
-
应用stash
-
git stash apply # 应用最新stash(stash@{0}),保留stash记录 git stash apply stash@{1}
-
应用并删除stash
-
git stash pop # 应用最新stash并从栈中移除
-
删除stash
-
git stash drop stash@{1} # 删除指定stash
-
清理所有stash
-
git stash clear
-
-
优点
- 灵活性
- 快速保存和恢复未提交更改,无需创建临时提交
- 支持多次stash,管理多个工作状态
- 保持干净
- 清理工作目录,便于切换分支、拉取代码或执行其他git操作
- 非破坏性
- 更改安全存储在stash栈,不会丢失(除非手动清理)
- 跨分支应用
- 可将stash应用到其他分支,适合移植临时更改
- 简单易用
- 命令直观,适合快速上下文切换
- 灵活性
-
缺点
- 管理复杂
- 多个stash可能导致栈混乱,难以记住每个stash的内容
- 默认命令,如stash@{0}不够直观,需手动添加描述
- 冲突风险
- 应用stash时,若当前分支状态不兼容,可能引发冲突,需手动解决
- 未跟踪文件遗漏
- 默认不保存未跟踪文件,需显式使用-u或-a,否则可能遗漏
- 不适合长期存储
- stash设计为临时保存,长期依赖可能导致管理混乱,不如提交或分支
- 调试困难
- stash记录仅保存更改差异,缺乏完整提交上下文,追溯可能不便
- 管理复杂
-
应用场景
- 临时切换分支
- 在开发特性时,需紧急切换到main修复bug,stash保存未完成的工作
- 拉取最新的代码
- 执行
git pull
前,工作目录有未提交更改,stash清理目录以避免冲突
- 执行
- 测试临时更改
- 测试某些修改后想恢复原始状态,stash保存实验性更改
- 移植更改
- 将未提交更改应用到其他分支,类似
cherry-pick
但针对未提交内容
- 将未提交更改应用到其他分支,类似
- 清理提交历史
- 在提交前整理工作目录,stash临时更改,调整后再提交
- 临时切换分支