git的进阶指南(git cherry-pick)

Posted by 杨青波 on 2021-02-01

git cherry-pick

关于 git cherry-pick 的含义和适用场景

cherry-pick的简介

cherry-pick (捡樱桃),顾名思义:是在一堆樱桃(commit)中挑选出自己想要的樱桃(commit)。

cherry-pick的功能

cherry-pick 的功能:在某一个分支中的commit中选出一个或多个commit提交到另一个分支。

cherry-pick的使用场景

cherry-pick 的使用场景: 比如我们从master分支切出来一个feature分支用于开发新的功能,而在开发这个新功能的时候顺便改了几个bug,相信这种顺便改bug的情景应该很常见吧,哈哈哈。这就有个问题了,我们现在并没有打算把这个feature给合进master分支,但是我们希望把我们顺手改的几个bug给合进master里面,这时候我们就可以使用cherry-pick将指定的commit给提交到master分支中去。

cherry-pick的副作用(个人理解)

使用cherry-pick 会在两个分支提交相同的内容,但是生成不同的commitId,这样在后续进行merge分支的时候,对于cherry-pick提交的commit内容依然会在PR中展示出来,给人带来疑惑(两个分支都有这段代码,但是PR中还是会存在这段代码,这就是commitId不同导致的)。
所以cherry-pick 只适用于commit已经混乱了,无法生成一个纯净的PR时使用,它不应该被大范围的使用,或者代替PR的功能之类的。

git cherry-pick 文档介绍

学习git推荐这个教程(图文详细),可能比官网更容易理解

git cherry-pick 简介

git cherry-pick is a powerful command that enables arbitrary Git commits to be picked by reference and appended to the current working HEAD. Cherry picking is the act of picking a commit from a branch and applying it to another. git cherry-pick can be useful for undoing changes. For example, say a commit is accidently made to the wrong branch. You can switch to the correct branch and cherry-pick the commit to where it should belong.
git cherry-pick 是一个强大的命令,它允许引用任意Git提交将其提交到当前分支HEAD上。Cherry picking 是将commit从一个分支应用到另一个分支的操作。git cherry-pick 对撤销更改很有用。比如:一个commit意外提交到错误的分支,你可以使用cherry-pick将这个commit提交到正确的分支上。

git cherry-pick 使用场景

git cherry-pick is a useful tool but not always a best practice. Cherry picking can cause duplicate commits and many scenarios where cherry picking would work, traditional merges are preferred instead. With that said git cherry-pick is a handy tool for a few scenarios…
git cherry-pick是一个有用的工具,但并不总是最佳实践。cherry-pick会导致重复提交,并且在很多情况下cherry-pick会起作用,然而传统的merge还是更合适。有了这个,git cherry-pick在某些情况下是一个方便的工具…

  • 团队合作

Often times a team will find individual members working in or around the same code. Maybe a new product feature has a backend and frontend component. There may be some shared code between to two product sectors. Maybe the backend developer creates a data structure that the frontend will also need to utilize. The frontend developer could use git cherry-pick to pick the commit in which this hypothetical data structure was created. This pick would enable the frontend developer to continue progress on their side of the project.
通常一个团队会发现在相同代码中或周围工作的单个成员。也许新产品功能具有后端和前端组件。两个产品部门之间可能存在一些共享代码。后端开发人员可能会创建前端也需要利用的数据结构。前端开发人员可以使用git cherry-pick来选择在其中创建此假设数据结构的提交。这种选择将使前端开发人员能够继续他们的项目进度。

比如多团队开发同一个大项目,他们从某一个模板项目中fork出来进行特化开发,当模板更新后可以直接git cherry pick对应的commitId就可以了。

  • bug快速修复

When a bug is discovered it is important to deliver a fix to end users as quickly as possible. For an example scenario,say a developer has started work on a new feature. During that new feature development they identify a pre-existing bug. The developer creates an explicit commit patching this bug. This new patch commit can be cherry-picked directly to the master branch to fix the bug before it effects more users.
发现错误后,尽快将修补程序提供给最终用户非常重要。对于一个示例场景,例如开发人员已开始着手一项新功能。在进行新功能开发时,他们会识别出先前存在的错误。开发人员创建了一个明确的提交来修补此错误。可以将新提交的补丁直接挑选到master分支上,以在影响更多用户之前修复该错误。

  • 撤销更改并恢复丢失的提交

Sometimes a feature branch may go stale and not get merged into master. Sometimes a pull request might get closed without merging. Git never loses those commits and through commands like git log and git reflog they can be found and cherry picked back to life.
有时,功能分支可能会过时并且无法合并到master中。有时,拉取请求可能会在不合并的情况下关闭。 Git从不丢失那些提交,通过git log和git reflog之类的命令,它们可以被找到,并且重拾生命。

示例演示

以下我创建一个新的仓库用于演示cherry-pick的使用场景:https://github.com/Liaomessi/git-advanced-guide
如果你是一个git新手的话,可以跟着下面的步骤走,你一定会有所收获,并对cherry-pick有所理解

  1. 首先,我们fork这个 https://github.com/Liaomessi/git-advanced-guide 这个仓库,可以看到我们的github已经有了这个仓库
    git fork https://github.com/Liaomessi/git-advanced-guide

  2. 然后我们按照传统(git)惯例,git clone下来这个仓库,这时这个仓库有两个分支 main、feature
    git clone https://github.com/Liaomessi/git-advanced-guide ${这里填你自己fork过来的仓库}

  3. 我们切换到feature分支,新建文件feature.md
    添加一行内容:this is feature1, 然后git commit -m 'add feature1',
    再添加一行内容: this is feature2, 然后git commit -m 'add feature2',
    这里我们已经在feature分支提交了两次代码,然后假设我们突然发现main分支的代码有问题,然后顺手就在当前分支把main分支的bug给修了后又开心的写我们的新feature。下面我们模拟这个场景:

  4. 在main.md文件中添加一行内容:this is bug fix, 然后git commit -m 'fix bug1'

  5. 修完bug我们接着写新feature,再在feature.md添加一行内容:this is feature3,然后git commit -m 'add feature3'
    好家伙,我大意了,没有切出一个新分支去修bug,给我把commit搞混乱了,当时流眼泪了,捂着胯,说年轻人你不讲git。
    查看commit日志,git log --oneline现在我们feature分支中有了以下四个commit

  1. git checkout main切换分支到main,git cherry-pick 3819196,再git push就将fix bug1这个commit提交到main分支了。

  2. 可能在开发中由于commit的内容不纯净会导致冲突,和正常merge代码一样解决冲突在commit就行了。

总结

git cherry-pick 是一个方便且强大的命令,在有些场景下挺有用。但是不应该使用 git cherry-pick 去替代 git merge 和 git rebase。使用 git cherry-pick 需要借助 git log 查找对应的提交。



支付宝打赏 微信打赏

赞赏一下