首页 > 其他分享 >Git:Cherry-Pick 桃色陷阱

Git:Cherry-Pick 桃色陷阱

时间:2023-12-24 23:05:38浏览次数:38  
标签:git cherry Cherry pick Git commit 桃色 txt 分支

以下内容为本人的学习笔记,如需要转载,请声明原文链接 微信公众号「ENG八戒」https://mp.weixin.qq.com/s/J2b130UVF0aPoHM9-U9Uuw

Cherry-Pick 咋一看这名字就很时髦,用来干啥呢?

Cherry-Pick 是什么?

假设在开发某些功能或者修复 bug 的时候把代码 commit 到了错误的分支 A,并且分支 A 最新版本已经覆盖了该 commit。看到这样你不会抓狂?被逼无奈之下,你可能会这样补救一番:

首先,切换到分支 A,找到需要备份的 commit 内容,逐个备份出来,并且保存 commit 描述,然后再切换回将要接收合并的目标工作分支,接着把备份的内容逐个更新到当前分支中,最后再提交新的 commit 并且填上前面保存下来的 commit 描述。

如果更新内容庞大,没有相关指令可以自动化实现上面的操作,全程靠手动操作,那么估计 Ctrl + C/V 都会罢工。

幸运的是,Git 其实提供了这样一个命令 cherry-pick 帮助我们一步实现上面的补救措施。其命令格式是

git cherry-pick <commit-hash>

上面的命令格式中,commit-hash 是在提交 commit 时 git 自动生成的 hash 串,代表每个独一无二的 commit。

Cherry-Pick 用于从其它分支提取某些 commit,并且合并到当前工作分支,同时还会把之前提交的描述也拷贝进来。这样大大简化了拉取其他分支某个 commit 的难度。

为何要用 Cherry-Pick

在多人合作的团队项目中,管理员通常会创建一个主线分支,比如命名为 develop,然后允许各个开发者基于主线分支分叉出特性分支,并在各自特性分支上进行特性功能的开发。在特性分支上,功能开发验证完毕后,开发人员再提交 merge 合并请求,将特性分支合并到主线分支,合并请求由管理员审核通过后才执行具体合并动作。

这里边,在合并分支内容时,有些情况需要分开讨论。

如果,特性分支最终开发完毕,并得到完整的认可,那么可以采用 merge 操作将特性分支新增的所有 commits 都合并到主线分支。

可是,如果在特性分支没有开发完毕又被遗忘很久远的时候,后来想想又需要用到其中的部分更新内容,比如,bug 补丁等,那么这个特性分支里的部分 commit 才是值得被拉取的内容,用 merge 明显不行,应该用 cherry-pick。

既然 cherry-pick 和 merge 都是用于合并 commit,那么区别在哪?

Cherry-Pick 只针对某个分支的某些指定 commit,而不是全部,而 merge 会把被选中分支的所有不同 commit 都拉取过来,这正是 cherry-pick 和 merge 的核心区别所在。

此外,类似合并功能的命令还有 rebase,后边有机会再撩她。

怎么使用 Cherry-Pick

多人开发的团队项目在代码管理上,很多麻烦的操作(例如合并分支代码等)都在类似 Gitlab 的平台上进行,平台能够尽最大限度规范化推行代码的合并。关于 Gitlab 的介绍,可以查看八戒以前写的文章《在局域网搭建一个带 web 操作页面的 git 版本服务器 - Gitlab》。

当然,如果接收合并内容的分支不受管控,完全可以自己在本地通过 git 命令合并或者用集成 git 功能的客户端可视化操作。带有 git 功能的可视化客户端也比较多,例如 TortoiseGit、SourceTree 和各大热门 IDE 等。

接下来选择使用 git 命令来简单做个示例。

准备一个本地代码仓库

$ cd ~
$ mkdir sample && cd sample
$ git init
Initialized empty Git repository in ~/sample/.git/

添加第一个改动,这里创建一个文本文件 index.txt 并写入字符串 index,然后提交到默认分支 master

$ echo index>index.txt
$ git add .
$ git commit -m "add index file"
[master (root-commit) e423b8c] add index file
 1 file changed, 1 insertion(+)
 create mode 100644 index.txt
$ git status
On branch master
nothing to commit, working tree clean

再准备两个特性分支 A 和 B

$ git branch A
$ git branch B
$ git branch
  A
  B
* master

git branch 命令只会创建新分支,但不会切换。

切换到特性分支 B 开始特性开发,这里为演示起见单纯创建一个文件 feature.txt 并写入字符串 feature,然后将工程更新提交到当前分支 B

$ git switch B
Switched to branch 'B'
$ echo feature>feature.txt
$ ll
total 2
-rw-r--r-- 1 Administrator 197121 8 Nov  8 19:22 feature.txt
-rw-r--r-- 1 Administrator 197121 6 Nov  8 19:10 index.txt
$ git add .
$ git commit -m "create feature"
[B a827145] create feature
 1 file changed, 1 insertion(+)
 create mode 100644 feature.txt
$ git log --oneline
a827145 (HEAD -> B) create feature
e423b8c (master, A) add index file

可以看到本地工作目录,在只有 index.txt 文件的基础上,多了个 feature.txt 文件。

除了 git switch 可以切换分支,还有 git checkout 也可,两者作用基本一样,但是建议统一使用 switch,避免记忆负担。

使用 git log 查看当前分支的提交日志,后边的选项 --oneline 会将日志信息简化到一行,方便查看提交记录比较多的情况。

当特性开发到这个阶段时,突然发现工程代码其实有个 bug,自己发现---高兴坏了。既然分支 B 和 分支 A 都是从主线分支分叉而来,那么分支 A 的代码中也会存在同样的 bug。

着手修复分支 B 的 bug,这里简单起见只是创建一个文件 fix.txt 并写入字符串 fix,然后提交更新到仓库

$ echo fix>fix.txt
$ git add .
$ git commit -m "fix bug"
[B 797dfa4] fix bug
 1 file changed, 1 insertion(+)
 create mode 100644 fix.txt
$ git log --oneline
797dfa4 (HEAD -> B) fix bug
a827145 create feature
e423b8c (master, A) add index file

那么怎么把分支 B 里刚刚修复的 bug 更新应用到分支 A 中呢?如果使用 merge 合并,那么分支 B 中还未开发完成的特性功能也会被一起同步到分支 A 中,这样不是我们想要的结果,于是可以针对某些已提交的 commit 执行 git cherry-pick。

在执行 cherry-pick 时需要已提交 commit 的 hash。从上面分支 B 的提交日志可以找到这串 hash

...
797dfa4 (HEAD -> B) fix bug
...

797dfa4 就是我们需要的 commit hash,虽然它不是一串完整的 hash,但是 git 只对比前面一部分就够了。

切换到分支 A 中,然后 cherry-pick

$ git switch A
Switched to branch 'A'
$ git log --oneline
e423b8c (HEAD -> A, master) add index file
$ git cherry-pick 797dfa4
[A e27c778] fix bug
 Date: Wed Nov 8 19:48:36 2023 +0800
 1 file changed, 1 insertion(+)
 create mode 100644 fix.txt
 $ ll
total 2
-rw-r--r-- 1 Administrator 197121 4 Nov  8 20:01 fix.txt
-rw-r--r-- 1 Administrator 197121 6 Nov  8 19:10 index.txt
$ git log --oneline
e27c778 (HEAD -> A) fix bug
e423b8c (master) add index file

可以看到执行 git cherry-pick 后,本地目录下也有了 fix.txt 文件,也即是分支 B 中做了修复 bug 的更新内容已经同步到分支 A 中,合并结果成功。

陷阱

上面的合并过程是很理想化的顺利,但是现实往往有些棘手。

比如,在分支 B 中,如果当时开发特性功能时刚好修改了有几行主线分支的原有代码,而修复 bug 时同样改动了这几行代码,那么在 cherry-pick 时有极大可能会出现合并冲突,导致合并失败,这时需要手动再处理冲突的代码段,保留符合修复 bug 意图的代码。

这种冲突,在 merge 操作中也很常见,原因基本类似。

所以说,cherry-pick 虽然很强大,但不是万能的,不要过度使用,使用时应该谨慎。

一般在 merge 合并操作能满足使用需求的情况下,优先建议使用 Merge,而不是 cherry-pick,只有在两个分支不是可以完全合并的前提下,再考虑使用 cherry-pick。因为 cherry-pick 在设计时就是为了解决某些指定 commit 的合并,而非全部。

这就是 cherry-pick 的桃色陷阱,你说呢?

标签:git,cherry,Cherry,pick,Git,commit,桃色,txt,分支
From: https://blog.51cto.com/englyf/8957150

相关文章

  • docker-compose gitlab
    version:'3'services:gitlab:image:'yrzr/gitlab-ce-arm64v8:latest'restart:unless-stoppedhostname:'test.gitlab.com'environment:TZ:'Asia/Shanghai'GITLAB_OMNIBUS_CONFIG:|......
  • git安装(Windows)
    首先进入官网——https://git-scm.com/download选择Windows,根据自己电脑情况选择需要的版本(我是64位)点击安装 --------------------这里不知道为什么在官网没有下载下来,所以从网盘下载的:https://blog.csdn.net/weixin_50212044/article/details/131433207下好之后......
  • 几种高级的git技巧
    加快gitcommit的速度使用git保存代码快照时,通常的流程是:gitadd.gitcommit-m"whatwasthat"gitpushoriginmaster但是commit命令的-a选项可以省略掉gitadd这一步,即:gitcommit-m"whatwasthat"-agitpushoriginmaster并且,利用git提供的别......
  • Tekton gitlab CI/CD 实例
    环境介绍gitlab地址gitlab:http://192.168.174.108:8080/root/spring-boot-helloWorldTask说明1.git-clone:克隆项目的源代码2.build-to-package:代码测试、构建和打包3.generate-build-id:生成BuildID4.image-build-and-push:镜像构建(和推送)5.deploy-to-cluster:将新......
  • 18. git fetch origin但是我远端没有这个分支啊 ,我只有master分支
     如果你执行了gitfetchorigin,但是远程仓库并没有origin分支,这是正常的。这个命令会从远程仓库(通常命名为"origin")中获取所有分支和标签的最新信息,而不仅仅是origin分支。在Git中,origin通常是默认的远程仓库名称,而不是一个分支的名称。如果你只有master分支,gitfetch......
  • Github Copilot生成代码和单元测试并执行
    ChatGPTPrompts整理总结 最近一直在学习ChatGPTPrompt的编写技巧,做了一些验证和整理,分享给大家ActasaLinuxTerminal英文PromptIwantyoutoactasalinuxterminal.Iwilltypecommandsandyouwillreplywithwhattheterminalshouldshow.Iwantyouto......
  • [分布式] Git详细安装与配置
    作者:丶布布✨Git简介Git是目前世界上最先进的分布式版本控制系统(没有之一)。那什么是版本控制系统?如果你用MicrosoftWord写过长篇大论,那你一定有这样的经历:想删除一个段落,又怕将来想恢复找不回来怎么办?有办法,先把当前文件“另存为……”一个新的Word文件,再接着改,改到一定程度,再“......
  • [插件使用] SwitchHosts自动更新Github Hosts文件
    作者:丶布布......
  • [Git Error] failed to push some refs to “××××.git”
    1.问题描述:在将本地仓库内容推送至远程仓库Github时出现以下错误。Togithub.com:LeowenHungry/Loewen-TestRepository.git![rejected]main->main(non-fast-forward)error:failedtopushsomerefsto'github.com:LeowenHungry/Loewen-TestRepository.git'hint:......
  • [Git] 使用过程中的常见错误及解决方式
    作者:丶布布一、SSLcertificateproblem:unabletogetlocalissuercertificate问题:当我从GitHub上克隆gitclone一个项目到本地的时候,系统出现了如下提示:SSLcertificateproblem:unabletogetlocalissuercertificate原因:这里其实是电脑没有安装对应的ca证书,所以无法通......