侧边栏壁纸
博主头像
★街角晚灯★ 博主等级

博观而约取 厚积而薄发

  • 累计撰写 469 篇文章
  • 累计创建 185 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

git cherry-pick 教程

WinJay
2024-10-25 / 0 评论 / 0 点赞 / 48 阅读 / 0 字 / 正在检测是否收录...

git cherry-pick 教程

img

对于多分支的代码库,将代码从一个分支转移到另一个分支是常见需求。

这时分两种情况。一种情况是,你需要另一个分支的所有代码变动,那么就采用合并(git merge)。另一种情况是,你只需要部分代码变动(某几个提交),这时可以采用 Cherry pick。

概述

git cherry-pick可以理解为挑拣提交,它会获取某一个分支的单笔提交,并作为一个新的提交引入到你当前分支上。 当我们需要在本地合入其他分支的提交时,如果我们不想对整个分支进行合并,而是只想将某一次提交合入到本地当前分支上,那么就要使用git cherry-pick了。

一、基本用法

git cherry-pick命令的作用,就是将指定的提交(commit)应用于其他分支。

$ git cherry-pick <commitHash>

上面命令就会将指定的提交commitHash,应用于当前分支。这会在当前分支产生一个新的提交,当然它们的哈希值会不一样。

举例来说,代码仓库有MainFeature两个分支。

    a - b - c - d        Main
          \
            e - f - g     Feature

现在将提交f应用到Main分支。

# 切换到 Main 分支
$ git checkout main

# Cherry pick 操作
$ git cherry-pick f

上面的操作完成以后,代码库就变成了下面的样子。

    a - b - c - d - f       Main
          \
            e - f - g         Feature

从上面可以看到,Main分支的末尾增加了一个提交f

git cherry-pick命令的参数,不一定是提交的哈希值,分支名也是可以的,表示转移该分支的最新提交。

$ git cherry-pick feature

上面代码表示将feature分支的最近一次提交,转移到当前分支。

二、转移多个提交

Cherry pick 支持一次转移多个提交。

$ git cherry-pick <HashA<HashB>

上面的命令将 A 和 B 两个提交应用到当前分支。这会在当前分支生成两个对应的新提交。

如果想要转移一系列的连续提交,可以使用下面的简便语法。

$ git cherry-pick A..B 

上面的命令可以转移从 A 到 B 的所有提交。它们必须按照正确的顺序放置:提交 A 必须早于提交 B,否则命令将失败,但不会报错。

注意,使用上面的命令,提交 A 将不会包含在 Cherry pick 中。如果要包含提交 A,可以使用下面的语法。

$ git cherry-pick A^..B 

三、配置项

git cherry-pick命令的常用配置项如下。

(1)-e--edit

打开外部编辑器,编辑提交信息。

(2)-n--no-commit

只更新工作区和暂存区,不产生新的提交。

(3)-x

在提交信息的末尾追加一行(cherry picked from commit ...),方便以后查到这个提交是如何产生的。

(4)-s--signoff

在提交信息的末尾追加一行操作者的签名,表示是谁进行了这个操作。

(5)-m parent-number--mainline parent-number

如果原始提交是一个合并节点,来自于两个分支的合并,那么 Cherry pick 默认将失败,因为它不知道应该采用哪个分支的代码变动。

-m配置项告诉 Git,应该采用哪个分支的变动。它的参数parent-number是一个从1开始的整数,代表原始提交的父分支编号。

$ git cherry-pick -m 1 <commitHash>

上面命令表示,Cherry pick 采用提交commitHash来自编号1的父分支的变动。

一般来说,1号父分支是接受变动的分支(the branch being merged into),2号父分支是作为变动来源的分支(the branch being merged from)。

四、代码冲突

如果操作过程中发生代码冲突,Cherry pick 会停下来,让用户决定如何继续操作。

(1)--continue

用户解决代码冲突后,第一步将修改的文件重新加入暂存区(git add .),第二步使用下面的命令,让 Cherry pick 过程继续执行。

$ git cherry-pick --continue

(2)--abort

发生代码冲突后,放弃合并,回到操作前的样子。

(3)--quit

发生代码冲突后,退出 Cherry pick,但是不回到操作前的样子。

五、转移到另一个代码库

Cherry pick 也支持转移另一个代码库的提交,方法是先将该库加为远程仓库。

$ git remote add target git://gitUrl

上面命令添加了一个远程仓库target

然后,将远程代码抓取到本地。

$ git fetch target

上面命令将远程代码仓库抓取到本地。

接着,检查一下要从远程仓库转移的提交,获取它的哈希值。

$ git log target/master

最后,使用git cherry-pick命令转移提交。

$ git cherry-pick <commitHash>

git cherry-pick commitid

在本地仓库中,有两个分支:isc和dev,我们先来查看各个分支的提交:

切换ISC分支

image-20250115102607227

# 切换到isc分支
git checkout isc
切换到分支 'isc'
您的分支与上游分支 'origin/isc' 一致。

# 查看最近三次提交
git log --oneline -3
2e59f8b (HEAD -> isc, origin/isc) + #0; Add  File...
4f4824c + #0; # 隐藏Nginx版本号和操作系统信息...
33e0b1a + #0; Modify ISC Branch Files...
(END)

image-20250115102449150

切换Dev分支

image-20250115102914100

# 切换到dev分支
git checkout dev 
切换到分支 'dev'
您的分支与上游分支 'origin/dev' 一致。


# 查看最近三次提交
git log --oneline -3
3b0e97a (HEAD -> dev, origin/dev) + #0; # 隐藏Nginx版本号和操作系统信息...
2c8c33a + #0; Modify Dev Branch Files...
43c6a84 + #0; Modify Dev Branch Files...
(END)

image-20250115102745367

合并提交

现在,我想要将isc分支上的最后一次提交内容"2e59f8b"合入到dev分支上,则可以使用git cherry-pick命令:

git cherry-pick 2e59f8b

image-20250115103523166

git push origin dev

image-20250115103629607

将Main分支的提交合并到ISC

git cherry-pick 94d0bf8

image-20250115110226271

image-20250115110651635

cherry-pick时,没有成功自动提交,存在冲突时参考:

image-20250116173512094

 /Users/LitSoft/001.Git/002.LitSoft/GuoMi-AutoDemploy   git cherry-pick 744f232f
自动合并 MySQL/InitDB/algorithm_serv.sql
冲突(内容):合并冲突于 MySQL/InitDB/algorithm_serv.sql
错误:不能应用 744f232... ^ #0; Update Admin Password.
提示: 解决所有冲突之后,用 "git add/rm <路径规格>" 标记它们,
提示: 然后执行 "git cherry-pick --continue"。您也可以执行
提示: "git cherry-pick --skip" 命令跳过这个提交。如果想要终止执行并回到
提示: 执行 "git cherry-pick" 之前的状态,执行 "git cherry-pick --abort"。
提示: Disable this message with "git config advice.mergeConflict false"
 /Users/LitSoft/001.Git/002.LitSoft/GuoMi-AutoDemploy  dev | cherry 


$ git cherry-pick 2555c6e
error: could not apply 2555c6e... [Description]:branch2 commit 2
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'

cherry-pick时,没有成功自动提交,这说明存在冲突,因此首先需要解决冲突,解决冲突后需要git commit手动进行提交:

$ git commit 
[branch1 790f431] [Description]:branch2 commit 2
 Date: Fri Jul 13 18:36:44 2018 +0800
 1 file changed, 1 insertion(+)
 create mode 100644 only-for-branch2.txt


或者git add .后直接使用git cherry-pick --continue继续。

image-20250116174110637

现在查看提交信息:

git log --oneline -3

c4d3f82 (HEAD -> dev, origin/dev) ^ #0; Update Admin Password.
f3e75d0 + #0; Add Server Licence Folder & Health Check ...
1ddf93a * #0; Modify Some Files.
(END)

image-20250116174241187

Main分支上的最后一次提交成功合入到了dev分支上。

以上就是git cherry-pick的基本用法,如果没有出现冲突,该命令将自动提交。


Git 合并到main分支

vim Deployment.sh
git status 
位于分支 dev
您的分支与上游分支 'origin/dev' 一致。

尚未暂存以备提交的变更:
  (使用 "git add <文件>..." 更新要提交的内容)
  (使用 "git restore <文件>..." 丢弃工作区的改动)
	修改:     Deployment.sh

修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
git add .    
git commit -m "+ #0; 前端包修改IP逻辑严谨处理."   
[dev 33a6a61] + #0; 前端包修改IP逻辑严谨处理.
 1 file changed, 11 insertions(+), 5 deletions(-)

git push                                                
枚举对象中: 5, 完成.
对象计数中: 100% (5/5), 完成.
使用 8 个线程进行压缩
压缩对象中: 100% (3/3), 完成.
写入对象中: 100% (3/3), 609 字节 | 609.00 KiB/s, 完成.
总共 3(差异 2),复用 0(差异 0),包复用 0(来自  0 个包)
remote:
remote: View merge request for dev:
remote:   http://git.litsoft.com.cn/IC/24040004/Server/AutomatedDeployment/-/merge_requests/1
remote:
To https://git.litsoft.com.cn/IC/24040004/Server/AutomatedDeployment.git
   ee6ab87..33a6a61  dev -> dev

image-20241217133931496

要将 dev 分支上的 Deployment.sh 文件合并到 main 分支,可以按照以下步骤操作:

1. 切换到 main 分支

首先,确保你当前在 main 分支上。如果不在 main 分支,执行以下命令切换过去:

git checkout main

2. 拉取最新的远程 main 分支更新

为了确保你的 main 分支是最新的,先从远程拉取最新的变更:

git pull origin main

3. 合并 dev 分支到 main 分支

现在,从 dev 分支合并最新的改动到 main

git merge dev

4. 解决冲突(如果有)

如果在合并过程中出现冲突,Git 会提示你解决冲突。手动编辑冲突文件,解决冲突后,执行以下命令标记冲突已解决:

git add <冲突的文件>
git merge --continue

5. 提交合并结果

如果没有冲突或者解决了冲突,可以提交合并:

git commit -m "Merge dev into main"

6. 推送到远程 main 分支

最后,将合并后的 main 分支推送到远程仓库:

git push origin main

完成后,dev 分支上的改动将成功合并到 main 分支,并且已将更新推送到远程仓库。

除了 git merge,还可以通过以下几种方式将 dev 分支的更改合并到 main 分支:

1. 使用 git rebase

git rebase 允许你将 dev 分支的提交“放到” main 分支上。与 merge 不同,rebase 会让提交历史更加线性。

步骤:

  1. 切换到 main 分支:

    git checkout main
    
  2. 拉取最新的 main 分支:

    git pull origin main
    
  3. 执行 rebase,将 dev 分支的提交添加到 main 分支的历史上:

    git rebase dev
    
  4. 解决冲突(如果有):
    如果出现冲突,Git 会提示解决冲突。解决完冲突后,使用以下命令继续 rebase:

    git add <解决冲突的文件>
    git rebase --continue
    
  5. 推送合并后的 main 分支:

    git push origin main
    

rebase 会将 dev 分支上的提交应用到 main 分支的后面,形成一个更加直线的历史。


2. 使用 git cherry-pick

如果只想将 dev 分支上的**特定**提交合并到 main 分支,而不是所有提交,可以使用 git cherry-pick

步骤:

  1. 切换到 main 分支:

    git checkout main
    
  2. 拉取最新的 main 分支:

    git pull origin main
    
  3. 使用 git log 找到你想 cherry-pick 的提交哈希值(例如 33a6a61)。然后使用以下命令将该提交应用到 main 分支:

    git cherry-pick 33a6a61
    

    这会将 dev 分支上的**特定**提交合并到 main 分支。

  4. 解决冲突(如果有):
    如果出现冲突,Git 会提示解决冲突。解决完冲突后,继续执行:

    git add <解决冲突的文件>
    git cherry-pick --continue
    
  5. 推送合并后的 main 分支:

    git push origin main
    

cherry-pick 允许你**选择性地将某些提交**合并到目标分支。


3. 使用 git pull--rebase

也可以通过 git pull --rebasemain 分支上拉取 dev 分支的提交,等价于一种简化的 rebase 操作。

步骤:

  1. 切换到 main 分支:

    git checkout main
    
  2. 拉取并执行 rebase 操作:

    git pull origin dev --rebase
    
  3. 解决冲突(如果有):
    解决完冲突后,继续执行:

    git add <解决冲突的文件>
    git rebase --continue
    
  4. 推送到远程:

    git push origin main
    

git pull --rebase 会将 dev 分支的提交 rebase 到当前分支,使提交历史更加简洁。


4. 使用 git reset(强制回退)

如果想直接将 main 分支的内容回退并且覆盖为 dev 分支的内容,可以使用 git reset。但是这是一种强制性操作,通常不推荐在多人协作的项目中使用,因为它会改变历史记录。

步骤:

  1. 切换到 main 分支:

    git checkout main
    
  2. 拉取最新的 main 分支:

    git pull origin main
    
  3. 使用 git reset 来将 main 分支回退到 dev 分支的状态:

    git reset --hard dev
    
  4. 强制推送 main 分支(小心使用!):

    git push origin main --force
    

这种方法会重写 main 分支的历史,直接用 dev 分支的内容覆盖 main 分支。


总结:

  • git merge:常用的合并方法,保留所有历史记录。
  • git rebase:将 dev 分支的提交平滑地应用到 main 分支,历史更简洁。
  • git cherry-pick:选择性地将某些提交应用到 main 分支。
  • git reset:覆盖 main 分支,直接用 dev 的内容替代(谨慎使用)。

根据需求和工作流,选择最适合的方法。

0
Git
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区