git cherry-pick和git stash命令详解

git cherry-pick命令

  • 定义

    • 用于将指定的提交(commit)从一个分支"挑选"并应用到当前分支
    • 它复制某个提交的更改(diff),生成一个新的提交,保留原提交的更改内容,但拥有新的提交ID(SHA值)
  • 命令

    shell 复制代码
    git cherry-pick <commit-id>
  • 核心功能

    • 提取单个或多个提交的更改,应用到目标分支
    • 不影响分支的整体历史,仅复制指定提交
      • 适合修复bug、移植特性或整理提交
  • 适用场景

    • 需要从一个分支移植一个特定更改到另一个分支时非常有用
  • 示例

    shell 复制代码
    # 假设有以下分支
    # 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

    shell 复制代码
    # 挑选多个提交(如E和F)
    git cherry-pick e123456 f789012
    
    # 或指定范围(从D到F,不包括D)
    git cherry-pick D..F
  • 优点

    • 精准选择
      • 只引入特定提交,避免不需要的更改,灵活性高
      • 适合移植bug修复或特定功能
    • 独立操作
      • 不影响源分支或整体历史,仅在当前分支生成新提交
    • 便于协作
      • 可快速将关健修复从开发分支应用到生产分支
    • 简单直观
      • 相比mergerebase,操作单一,易于理解和执行
  • 缺点

    • 手动挑选成本高
      • 需要知道具体提交的SHA值或范围,手动操作繁琐
      • 不适合大量提交的整合
    • 冲突处理复杂
      • 如果cherry-pick的提交依赖其他未挑选的提交,可能导致冲突或功能不完整
      • 冲突需手动解决,多次cherry-pick可能重复处理类似冲突
    • 历史重复
      • cherry-pick生成新提交,可能导致代码重复(若后续合并源分支)
      • 例如:E'和E可能在在未来合并时造成冲突
    • 丢失上下文
      • 只复制提交内容,丢失原提交的完整分支上下文,调试或追溯可能困难
  • 适用场景

    • 修复bug
      • 将开发分支的bug修复快速应用到生产分支
    • 移植特性
      • 将特性分支的某些功能引入其他分支(如实验性功能)
    • 清理历史
      • 挑选关键提交,整理分支历史,结合rebase适用
    • 临时整合
      • 在合并整个分支前,测试特定提交的效果
  • mergerebase对比

    • vs merge
      • merge整合整个分支,保留历史(快进线性或非快进线性)
      • cherry-pick只选特定提交,适合精细控制
    • vs rebase
      • rebase重放整个分支历史,生成线性历史
      • cherry-pick只重放指定提交,操作更局部

git stash命令

  • 定义
    • 用于临时保存工作目录和索引(暂存区)的更改,并将工作目录恢复到最近一次提交的状态(干净状态)
    • 它将未提交的更改(包括已跟踪文件的修改和暂存的更改)存储到一个栈(stash stack)中,供后续恢复或应用
  • 命令
    • git stash
  • 核心功能
    • 保存未提交的更改(工作目录和暂存区)
    • 清理工作目录,恢复到最近的提交状态
    • 允许稍后恢复或应用保存的更改到当前或其他分支
  • 目的
    • 避免提交临时更改:在切换分支、拉取代码或执行其他操作时,临时保存未完成的工作
    • 保持工作目录干净:确保工作目录无未提交更改,便于git操作(如合并、变基)
    • 灵活管理更改:支持多次stash,随时恢复或丢弃

功能与命令

  • 保存更改
    • 保存工作目录和暂存区的更改到stash栈
    • 默认保存已跟踪文件的修改(包括暂存和未暂存更改)
  • 恢复工作目录
    • 将工作目录和暂存区恢复到最近提交的状态
  • 恢复更改
    • 将工作目录和暂存区恢复到最近提交的状态
  • 恢复更改
    • 从stash栈中恢复保存的更改到当前分支
  • 管理stash
    • 查看、应用、删除或清理stash记录

常用命令

  • 保存更改

    shell 复制代码
    git stash
    
    # 默认保存更改,命名为stash@{n}(n为栈索引,从0开始)
    
    # 添加描述
    git stash push -m 'message'
    • 保存未跟踪文件,包含未跟踪文件(如新文件)

    shell 复制代码
    git stash -u
    • 保存所有文件,包含未跟踪和忽略文件。

      shell 复制代码
      git stash -a
    • 查看stash列表

      shell 复制代码
      git stash list
      
      # 显示所有stash记录,例如
      stash@{0}: WIP on feature: abc1234 Add feature X
      stash@{1}: On main: def5678 Temp changes
    • 应用stash

    shell 复制代码
    git stash apply
    # 应用最新stash(stash@{0}),保留stash记录
    git stash apply stash@{1}
    • 应用并删除stash

    shell 复制代码
    git stash pop
    # 应用最新stash并从栈中移除
    • 删除stash

    shell 复制代码
    git stash drop stash@{1}
    # 删除指定stash
    • 清理所有stash

    shell 复制代码
    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临时更改,调整后再提交
相关推荐
abcnull23 分钟前
github中main与master,master无法合并到main
git·github
养意6 小时前
git提交代码和解决冲突修复bug
git·bug
码农黛兮_4619 小时前
Git 常用命令大全
git
一弓虽19 小时前
git 学习
git·学习
疯狂的沙粒1 天前
如何通过git命令查看项目连接的仓库地址?
大数据·git·elasticsearch
qq_254617771 天前
Gerrit+repo管理git仓库,如果本地有新分支不能执行repo sync来同步远程所有修改,会报错
git
π大星星️1 天前
Git分布式版本控制工具
分布式·git
kingbal1 天前
IDEA:配置 Git 需要完成 Git 路径设置、账号认证以及仓库关联三个主要步骤
git·idea
司徒小夜2 天前
处理git没做修改,但是文件显示变更的情况
git
m0_749317522 天前
vscode里如何用git
ide·git·vscode