<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>分支管理 on Grayson 博客 :smile:</title><link>https://blog.grayson.work/zh-cn/tags/%E5%88%86%E6%94%AF%E7%AE%A1%E7%90%86/</link><description>Recent content in 分支管理 on Grayson 博客 :smile:</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><copyright>blog.grayson.work</copyright><lastBuildDate>Fri, 26 Jun 2026 17:30:00 +0800</lastBuildDate><atom:link href="https://blog.grayson.work/zh-cn/tags/%E5%88%86%E6%94%AF%E7%AE%A1%E7%90%86/index.xml" rel="self" type="application/rss+xml"/><item><title>一文看懂 git cherry-pick -m 1：如何摘取一个合并提交</title><link>https://blog.grayson.work/zh-cn/p/git-cherry-pick-merge-commit/</link><pubDate>Fri, 26 Jun 2026 17:30:00 +0800</pubDate><guid>https://blog.grayson.work/zh-cn/p/git-cherry-pick-merge-commit/</guid><description>&lt;h2 id="为什么需要--m-1"&gt;为什么需要 &lt;code&gt;-m 1&lt;/code&gt;
&lt;/h2&gt;&lt;p&gt;直接 cherry-pick 一个合并提交会失败：它有两个父提交，Git 不知道该拿哪一个来比较。&lt;code&gt;-m 1&lt;/code&gt; 的作用，就是告诉 Git“以第一个父提交（通常是主线）为基准”。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; git cherry-pick 8865ad0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;error: commit 8865ad060c1c64fbc3c0196e12302b1d96e8bf30 is a merge but no -m option was given.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;fatal: cherry-pick failed
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;最常见的场景是：功能分支 &lt;code&gt;feature&lt;/code&gt; 已经通过一个合并提交进入 &lt;code&gt;main&lt;/code&gt;，现在要把同一个功能补到维护中的 &lt;code&gt;release&lt;/code&gt; 分支，而 &lt;code&gt;main&lt;/code&gt; 上的其他提交不能跟过去。&lt;/p&gt;
&lt;p&gt;逐个 cherry-pick &lt;code&gt;feature&lt;/code&gt; 上的提交也能做到，但提交一多就很繁琐，而且合并时手动解决过的冲突不会被带上。直接摘取那个合并提交，一条命令就能拿到功能的完整改动。&lt;/p&gt;
&lt;h2 id="核心概念合并提交有两个父提交"&gt;核心概念：合并提交有两个父提交
&lt;/h2&gt;&lt;p&gt;普通提交只有一个父提交，合并提交有两个：&lt;strong&gt;parent 1&lt;/strong&gt; 是执行合并时所在的分支，&lt;strong&gt;parent 2&lt;/strong&gt; 是被合进来的分支。&lt;/p&gt;
&lt;p&gt;在 &lt;code&gt;main&lt;/code&gt; 上执行 &lt;code&gt;git merge feature&lt;/code&gt; 时，&lt;code&gt;main&lt;/code&gt; 当时的最新提交成为 parent 1，&lt;code&gt;feature&lt;/code&gt; 的最新提交成为 parent 2。在 GitHub、GitLab 上用“创建合并提交”的方式合并 PR 也是同样的顺序：目标分支在前。&lt;/p&gt;
&lt;figure class="cpm-fig"&gt;
&lt;style&gt;
.cpm-fig{margin:1.5em 0;text-align:center}
.cpm-fig svg{width:100%;max-width:640px;height:auto;--cpm-p1:#2563eb;--cpm-p2:#b45309;--cpm-ink:var(--card-text-color-main);--cpm-muted:var(--card-text-color-secondary);--cpm-bg:var(--card-background)}
:root[data-scheme="dark"] .cpm-fig svg{--cpm-p1:#60a5fa;--cpm-p2:#fbbf24}
.cpm-fig figcaption{margin-top:.6em;font-size:.9em;color:var(--card-text-color-secondary)}
.cpm-node{fill:var(--cpm-bg);stroke:var(--cpm-ink);stroke-width:2}
.cpm-edge{fill:none;stroke:var(--cpm-muted);stroke-width:2}
.cpm-panel{fill:none;stroke:var(--cpm-muted);stroke-opacity:.4}
.cpm-box{fill:var(--cpm-bg);stroke:var(--cpm-ink);stroke-width:1.5}
.cpm-t,.cpm-h,.cpm-f,.cpm-m,.cpm-r,.cpm-lbl{text-anchor:middle;dominant-baseline:central}
.cpm-t{fill:var(--cpm-ink);font-size:16px;font-weight:700}
.cpm-s{font-size:12px}
.cpm-h{font-size:15px;font-weight:700}
.cpm-f{fill:var(--cpm-ink);font-size:13px;font-family:var(--code-font-family,ui-monospace,monospace)}
.cpm-lbl{fill:var(--cpm-muted);font-size:13px;font-family:var(--code-font-family,ui-monospace,monospace)}
.cpm-m{fill:var(--cpm-muted);font-size:13px}
.cpm-r{font-size:16px;font-weight:700;font-family:var(--code-font-family,ui-monospace,monospace)}
.cpm-ah{fill:var(--cpm-muted)}
.cpm-e1,.cpm-b1{stroke:var(--cpm-p1);stroke-width:2.5}
.cpm-e2,.cpm-b2{stroke:var(--cpm-p2);stroke-width:2.5}
.cpm-c1{fill:var(--cpm-p1)}
.cpm-c2{fill:var(--cpm-p2)}
.cpm-bold{font-weight:700}
&lt;/style&gt;
&lt;svg viewBox="0 0 640 240" role="img" aria-labelledby="cpm-g1-t" xmlns="http://www.w3.org/2000/svg"&gt;
&lt;title id="cpm-g1-t"&gt;合并提交 M 的两个父提交：C 是 parent 1，B 是 parent 2&lt;/title&gt;
&lt;defs&gt;
&lt;marker id="cpm-g1-a" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="10" markerHeight="10" markerUnits="userSpaceOnUse" orient="auto"&gt;&lt;path class="cpm-ah" d="M0,0 L10,5 L0,10 z"/&gt;&lt;/marker&gt;
&lt;marker id="cpm-g1-a1" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="11" markerHeight="11" markerUnits="userSpaceOnUse" orient="auto"&gt;&lt;path class="cpm-c1" d="M0,0 L10,5 L0,10 z"/&gt;&lt;/marker&gt;
&lt;marker id="cpm-g1-a2" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="11" markerHeight="11" markerUnits="userSpaceOnUse" orient="auto"&gt;&lt;path class="cpm-c2" d="M0,0 L10,5 L0,10 z"/&gt;&lt;/marker&gt;
&lt;/defs&gt;
&lt;line class="cpm-edge" x1="77" y1="155" x2="202" y2="80" marker-end="url(#cpm-g1-a)"/&gt;
&lt;line class="cpm-edge" x1="240" y1="70" x2="339" y2="70" marker-end="url(#cpm-g1-a)"/&gt;
&lt;line class="cpm-edge" x1="80" y1="165" x2="269" y2="165" marker-end="url(#cpm-g1-a)"/&gt;
&lt;line class="cpm-edge cpm-e1" x1="310" y1="165" x2="499" y2="165" marker-end="url(#cpm-g1-a1)"/&gt;
&lt;line class="cpm-edge cpm-e2" x1="377" y1="80" x2="502" y2="154" marker-end="url(#cpm-g1-a2)"/&gt;
&lt;circle class="cpm-node" cx="60" cy="165" r="20"/&gt;&lt;text class="cpm-t cpm-s" x="60" y="165"&gt;init&lt;/text&gt;
&lt;circle class="cpm-node" cx="220" cy="70" r="20"/&gt;&lt;text class="cpm-t" x="220" y="70"&gt;A&lt;/text&gt;
&lt;circle class="cpm-node cpm-b2" cx="360" cy="70" r="20"/&gt;&lt;text class="cpm-t" x="360" y="70"&gt;B&lt;/text&gt;
&lt;circle class="cpm-node cpm-b1" cx="290" cy="165" r="20"/&gt;&lt;text class="cpm-t" x="290" y="165"&gt;C&lt;/text&gt;
&lt;circle class="cpm-node" cx="520" cy="165" r="22" style="stroke-width:3"/&gt;&lt;text class="cpm-t" x="520" y="165"&gt;M&lt;/text&gt;
&lt;text class="cpm-h cpm-c1" x="404" y="150"&gt;parent 1&lt;/text&gt;
&lt;text class="cpm-h cpm-c2" x="478" y="100"&gt;parent 2&lt;/text&gt;
&lt;text class="cpm-lbl" x="60" y="203"&gt;release&lt;/text&gt;
&lt;text class="cpm-lbl" x="360" y="36"&gt;feature&lt;/text&gt;
&lt;text class="cpm-lbl" x="572" y="165"&gt;main&lt;/text&gt;
&lt;text class="cpm-m" x="600" y="226"&gt;时间 →&lt;/text&gt;
&lt;/svg&gt;
&lt;figcaption&gt;箭头沿时间方向画出：两条彩色箭头进入 M，分别来自 C（parent 1）和 B（parent 2）。&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;想确认顺序，看 &lt;code&gt;git log -1 &amp;lt;sha&amp;gt;&lt;/code&gt; 输出里的 &lt;code&gt;Merge:&lt;/code&gt; 行即可，写在前面的就是 parent 1：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; git log -1 8865ad0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;commit 8865ad060c1c64fbc3c0196e12302b1d96e8bf30
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;Merge: 06233b4 d9b8793
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;Author: Demo &amp;lt;demo@example.com&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;Date: Fri Jun 26 17:56:50 2026 +0800
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; M: merge feature
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;也可以用 &lt;code&gt;git rev-parse &amp;lt;sha&amp;gt;^1 &amp;lt;sha&amp;gt;^2&lt;/code&gt; 分别打印两个父提交：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; git rev-parse 8865ad0^1 8865ad0^2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;06233b41967aea22699e607028a268615027526c
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;d9b87938de6bd17532f3156c05e7cfd0b475a787
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="-m-1-与--m-2-分别算出了什么"&gt;&lt;code&gt;-m 1&lt;/code&gt; 与 &lt;code&gt;-m 2&lt;/code&gt; 分别算出了什么
&lt;/h2&gt;&lt;p&gt;cherry-pick 的本质，是把“某个提交相对其父提交的差异”应用到当前分支。&lt;code&gt;-m&lt;/code&gt;（全称 &lt;code&gt;--mainline&lt;/code&gt;）只是在两个父提交里选一个作为基准，选谁就带走另一侧的改动。&lt;/p&gt;
&lt;figure class="cpm-fig"&gt;
&lt;svg viewBox="0 0 640 290" role="img" aria-labelledby="cpm-g2-t" xmlns="http://www.w3.org/2000/svg"&gt;
&lt;title id="cpm-g2-t"&gt;-m 1 拿 C 和 M 比，差异是 login.txt；-m 2 拿 B 和 M 比，差异是 README.md&lt;/title&gt;
&lt;defs&gt;
&lt;marker id="cpm-g2-a" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="10" markerHeight="10" markerUnits="userSpaceOnUse" orient="auto"&gt;&lt;path class="cpm-ah" d="M0,0 L10,5 L0,10 z"/&gt;&lt;/marker&gt;
&lt;/defs&gt;
&lt;rect class="cpm-panel" x="6" y="6" width="306" height="278" rx="10"/&gt;
&lt;text class="cpm-h cpm-c1" x="159" y="34"&gt;-m 1：以 parent 1（C）为基准&lt;/text&gt;
&lt;rect class="cpm-box cpm-b1" x="26" y="58" width="112" height="112" rx="8"/&gt;
&lt;text class="cpm-t" x="82" y="80"&gt;C&lt;/text&gt;
&lt;text class="cpm-f" x="82" y="110"&gt;app.txt&lt;/text&gt;
&lt;text class="cpm-f" x="82" y="132"&gt;README.md&lt;/text&gt;
&lt;text class="cpm-m" x="159" y="98"&gt;差异&lt;/text&gt;
&lt;line class="cpm-edge" x1="142" y1="114" x2="176" y2="114" marker-end="url(#cpm-g2-a)"/&gt;
&lt;rect class="cpm-box" x="180" y="58" width="112" height="112" rx="8"/&gt;
&lt;text class="cpm-t" x="236" y="80"&gt;M&lt;/text&gt;
&lt;text class="cpm-f" x="236" y="110"&gt;app.txt&lt;/text&gt;
&lt;text class="cpm-f" x="236" y="132"&gt;README.md&lt;/text&gt;
&lt;text class="cpm-f cpm-c1 cpm-bold" x="236" y="154"&gt;+ login.txt&lt;/text&gt;
&lt;text class="cpm-m" x="159" y="204"&gt;带到当前分支的是&lt;/text&gt;
&lt;text class="cpm-r cpm-c1" x="159" y="230"&gt;+ login.txt&lt;/text&gt;
&lt;text class="cpm-m" x="159" y="256"&gt;feature 的改动（A、B）&lt;/text&gt;
&lt;rect class="cpm-panel" x="328" y="6" width="306" height="278" rx="10"/&gt;
&lt;text class="cpm-h cpm-c2" x="481" y="34"&gt;-m 2：以 parent 2（B）为基准&lt;/text&gt;
&lt;rect class="cpm-box cpm-b2" x="348" y="58" width="112" height="112" rx="8"/&gt;
&lt;text class="cpm-t" x="404" y="80"&gt;B&lt;/text&gt;
&lt;text class="cpm-f" x="404" y="110"&gt;app.txt&lt;/text&gt;
&lt;text class="cpm-f" x="404" y="132"&gt;login.txt&lt;/text&gt;
&lt;text class="cpm-m" x="481" y="98"&gt;差异&lt;/text&gt;
&lt;line class="cpm-edge" x1="464" y1="114" x2="498" y2="114" marker-end="url(#cpm-g2-a)"/&gt;
&lt;rect class="cpm-box" x="502" y="58" width="112" height="112" rx="8"/&gt;
&lt;text class="cpm-t" x="558" y="80"&gt;M&lt;/text&gt;
&lt;text class="cpm-f" x="558" y="110"&gt;app.txt&lt;/text&gt;
&lt;text class="cpm-f" x="558" y="132"&gt;login.txt&lt;/text&gt;
&lt;text class="cpm-f cpm-c2 cpm-bold" x="558" y="154"&gt;+ README.md&lt;/text&gt;
&lt;text class="cpm-m" x="481" y="204"&gt;带到当前分支的是&lt;/text&gt;
&lt;text class="cpm-r cpm-c2" x="481" y="230"&gt;+ README.md&lt;/text&gt;
&lt;text class="cpm-m" x="481" y="256"&gt;main 侧的改动（C）&lt;/text&gt;
&lt;/svg&gt;
&lt;figcaption&gt;左边是常用的 -m 1：拿 C 和 M 比，差出来的正是 feature 带来的改动。&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;选项&lt;/th&gt;
&lt;th&gt;基准&lt;/th&gt;
&lt;th&gt;计算的差异&lt;/th&gt;
&lt;th&gt;带到当前分支的内容&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-m 1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;parent 1（C，main 侧）&lt;/td&gt;
&lt;td&gt;C → M&lt;/td&gt;
&lt;td&gt;feature 的全部改动（A、B，以及合并时的冲突解决）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-m 2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;parent 2（B，feature 侧）&lt;/td&gt;
&lt;td&gt;B → M&lt;/td&gt;
&lt;td&gt;main 在 feature 分出之后的改动（C）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;在“把已合并的功能搬到另一个分支”这类场景里，几乎总是用 &lt;code&gt;-m 1&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id="动手实验搭一个示例仓库"&gt;动手实验：搭一个示例仓库
&lt;/h2&gt;&lt;p&gt;下面的命令可以直接复制运行，它会造出上文的仓库：&lt;code&gt;release&lt;/code&gt; 停在 &lt;code&gt;init&lt;/code&gt;，&lt;code&gt;feature&lt;/code&gt; 有两个提交，&lt;code&gt;main&lt;/code&gt; 另有一个无关提交，最后用合并提交 M 把 &lt;code&gt;feature&lt;/code&gt; 合进 &lt;code&gt;main&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;分四步来，每一步之后都用 &lt;code&gt;git log --oneline --graph --all&lt;/code&gt; 看一眼提交图。下面是实际输出（你自己运行时 SHA 会不同）。&lt;/p&gt;
&lt;h3 id="第-1-步初始提交切出-release"&gt;第 1 步：初始提交，切出 release
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git init -b main demo &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; demo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;v1&amp;#34;&lt;/span&gt; &amp;gt; app.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git add app.txt &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git commit -m &lt;span class="s2"&gt;&amp;#34;init&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 从这里切出 release 分支（之后不再动它）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git branch release
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; git log --oneline --graph --all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;* f643d1c (HEAD -&amp;gt; main, release) init
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;此时只有一个提交，&lt;code&gt;main&lt;/code&gt; 和 &lt;code&gt;release&lt;/code&gt; 都指向它。&lt;/p&gt;
&lt;h3 id="第-2-步feature-分支上做两个提交"&gt;第 2 步：feature 分支上做两个提交
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git checkout -b feature
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;login&amp;#34;&lt;/span&gt; &amp;gt; login.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git add login.txt &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git commit -m &lt;span class="s2"&gt;&amp;#34;A: add login&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;logout&amp;#34;&lt;/span&gt; &amp;gt;&amp;gt; login.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git commit -am &lt;span class="s2"&gt;&amp;#34;B: add logout&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; git log --oneline --graph --all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;* d9b8793 (HEAD -&amp;gt; feature) B: add logout
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;* f7858bc A: add login
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;* f643d1c (release, main) init
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;feature&lt;/code&gt; 往前走了两步，&lt;code&gt;main&lt;/code&gt; 和 &lt;code&gt;release&lt;/code&gt; 还留在 &lt;code&gt;init&lt;/code&gt;。&lt;/p&gt;
&lt;h3 id="第-3-步main-上另有一个无关提交"&gt;第 3 步：main 上另有一个无关提交
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git checkout main
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;readme&amp;#34;&lt;/span&gt; &amp;gt; README.md
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git add README.md &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git commit -m &lt;span class="s2"&gt;&amp;#34;C: add readme&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; git log --oneline --graph --all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;* d9b8793 (feature) B: add logout
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;* f7858bc A: add login
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;| * 06233b4 (HEAD -&amp;gt; main) C: add readme
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;|/
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;* f643d1c (release) init
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;历史在 &lt;code&gt;init&lt;/code&gt; 之后分了叉：一侧是 &lt;code&gt;feature&lt;/code&gt; 的 A、B，另一侧是 &lt;code&gt;main&lt;/code&gt; 的 C。&lt;/p&gt;
&lt;h3 id="第-4-步用合并提交把-feature-合进-main"&gt;第 4 步：用合并提交把 feature 合进 main
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git merge --no-ff feature -m &lt;span class="s2"&gt;&amp;#34;M: merge feature&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;--no-ff&lt;/code&gt; 保证一定会生成合并提交。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; git merge --no-ff feature -m &lt;span class="s2"&gt;&amp;#34;M: merge feature&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;Merge made by the &amp;#39;ort&amp;#39; strategy.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; login.txt | 2 ++
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; 1 file changed, 2 insertions(+)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; create mode 100644 login.txt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; git log --oneline --graph --all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;* 8865ad0 (HEAD -&amp;gt; main) M: merge feature
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;|\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;| * d9b8793 (feature) B: add logout
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;| * f7858bc A: add login
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;* | 06233b4 C: add readme
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;|/
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;* f643d1c (release) init
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;M（&lt;code&gt;8865ad0&lt;/code&gt;）有两条线进来：竖直的那条来自 C（&lt;code&gt;06233b4&lt;/code&gt;，parent 1），右边那条来自 B（&lt;code&gt;d9b8793&lt;/code&gt;，parent 2）。这正是前面 &lt;code&gt;Merge: 06233b4 d9b8793&lt;/code&gt; 的顺序。&lt;/p&gt;
&lt;h2 id="执行-cherry-pick-并验证"&gt;执行 cherry-pick 并验证
&lt;/h2&gt;&lt;p&gt;切到 &lt;code&gt;release&lt;/code&gt;，用 &lt;code&gt;-m 1&lt;/code&gt; 摘取 M。&lt;code&gt;main&lt;/code&gt; 此刻正指向 M，所以直接写分支名也可以：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git checkout release
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git cherry-pick -m &lt;span class="m"&gt;1&lt;/span&gt; main &lt;span class="c1"&gt;# 等价于 git cherry-pick -m 1 8865ad0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;在终端里执行并验证，实际输出如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; git checkout release
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;Switched to branch &amp;#39;release&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; git cherry-pick -m &lt;span class="m"&gt;1&lt;/span&gt; main
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;[release 20de01d] M: merge feature
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; Date: Fri Jun 26 17:56:50 2026 +0800
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; 1 file changed, 2 insertions(+)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; create mode 100644 login.txt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;app.txt login.txt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; git log --oneline --graph --all
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;* 8865ad0 (main) M: merge feature
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;|\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;| * d9b8793 (feature) B: add logout
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;| * f7858bc A: add login
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;* | 06233b4 C: add readme
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;|/
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;| * 20de01d (HEAD -&amp;gt; release) M: merge feature
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;|/
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;* f643d1c init
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; git log -1 --format&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;%h parents: %p&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;20de01d parents: f643d1c
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;release&lt;/code&gt; 拿到了 &lt;code&gt;feature&lt;/code&gt; 的 &lt;code&gt;login.txt&lt;/code&gt;，而 &lt;code&gt;main&lt;/code&gt; 上的 &lt;code&gt;README.md&lt;/code&gt; 没有跟过来。注意新生成的 &lt;code&gt;20de01d&lt;/code&gt; 是一个普通的单父提交（父提交只有 &lt;code&gt;f643d1c&lt;/code&gt;），不是合并提交，只是沿用了 M 的提交信息。&lt;/p&gt;
&lt;h2 id="对比实验换成--m-2-会怎样"&gt;对比实验：换成 &lt;code&gt;-m 2&lt;/code&gt; 会怎样
&lt;/h2&gt;&lt;p&gt;换成 &lt;code&gt;-m 2&lt;/code&gt;，拿到的反而是 &lt;code&gt;main&lt;/code&gt; 侧的 &lt;code&gt;README.md&lt;/code&gt;，&lt;code&gt;feature&lt;/code&gt; 的改动一个也没有。从 &lt;code&gt;init&lt;/code&gt; 新开一个分支试试：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git checkout -b release-m2 release~1 &lt;span class="c1"&gt;# 回到 cherry-pick 之前的 init&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git cherry-pick -m &lt;span class="m"&gt;2&lt;/span&gt; main
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; git checkout -b release-m2 release~1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;Switched to a new branch &amp;#39;release-m2&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; git cherry-pick -m &lt;span class="m"&gt;2&lt;/span&gt; main
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;[release-m2 220b106] M: merge feature
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; Date: Fri Jun 26 17:56:50 2026 +0800
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; 1 file changed, 1 insertion(+)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; create mode 100644 README.md
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; ls
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;README.md app.txt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;原因是基准换成了 B：B 已经包含 &lt;code&gt;login.txt&lt;/code&gt;，所以 B → M 的差异只剩 C 引入的 &lt;code&gt;README.md&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-m 2&lt;/code&gt; 并非没有用。如果有人先在 &lt;code&gt;feature&lt;/code&gt; 上执行 &lt;code&gt;git merge main&lt;/code&gt;，再把 &lt;code&gt;main&lt;/code&gt; 快进到这个合并，父提交顺序就反了过来，这时要用 &lt;code&gt;-m 2&lt;/code&gt; 才能拿到 &lt;code&gt;feature&lt;/code&gt; 的改动。&lt;/p&gt;
&lt;h2 id="常见坑与最佳实践"&gt;常见坑与最佳实践
&lt;/h2&gt;&lt;p&gt;最大的坑是想当然地认为 parent 1 就是主线，动手前先确认父提交顺序，其余问题都好处理。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;先看顺序再动手。&lt;/strong&gt; 用 &lt;code&gt;git log -1 &amp;lt;sha&amp;gt;&lt;/code&gt; 的 &lt;code&gt;Merge:&lt;/code&gt; 行确认哪个是 parent 1，尤其是别人做的合并。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;加上 &lt;code&gt;-x&lt;/code&gt; 记录来源。&lt;/strong&gt; &lt;code&gt;git cherry-pick -x -m 1 &amp;lt;sha&amp;gt;&lt;/code&gt; 会在提交信息末尾追加 &lt;code&gt;(cherry picked from commit ...)&lt;/code&gt;，日后排查时一眼就能找到出处。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;遇到冲突照常处理。&lt;/strong&gt; 修改冲突文件后 &lt;code&gt;git add&lt;/code&gt;，再 &lt;code&gt;git cherry-pick --continue&lt;/code&gt;；想放弃就 &lt;code&gt;git cherry-pick --abort&lt;/code&gt;，分支会回到操作前的状态。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;之后再合并要留意。&lt;/strong&gt; cherry-pick 生成的是新 SHA，Git 并不记得这些改动已经在 &lt;code&gt;release&lt;/code&gt; 里。以后若把 &lt;code&gt;feature&lt;/code&gt; 或 &lt;code&gt;main&lt;/code&gt; 再合进 &lt;code&gt;release&lt;/code&gt;，完全相同的改动通常能自动合并，但 &lt;code&gt;feature&lt;/code&gt; 之后又改过的地方可能出现冲突。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;撤销的方式不同。&lt;/strong&gt; cherry-pick 出来的是普通提交，&lt;code&gt;git revert &amp;lt;新 sha&amp;gt;&lt;/code&gt; 即可；如果要撤销原始的合并提交 M，则同样需要 &lt;code&gt;git revert -m 1 M&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;批量摘取时可以统一加 &lt;code&gt;-m 1&lt;/code&gt;。&lt;/strong&gt; 从 Git 2.21 起，&lt;code&gt;-m&lt;/code&gt; 也能用在普通提交上，所以一个混有合并提交的范围可以用一条命令处理。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;加上 &lt;code&gt;-x&lt;/code&gt; 之后，提交信息的最后一行会记下来源合并提交的完整 SHA：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git checkout -b release-x release~1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git cherry-pick -x -m &lt;span class="m"&gt;1&lt;/span&gt; main
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-console" data-lang="console"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gp"&gt;$&lt;/span&gt; git log -1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;commit bd76f2d148bac366ad55b388915292d25daead59
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;Author: Demo &amp;lt;demo@example.com&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt;Date: Fri Jun 26 17:56:50 2026 +0800
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; M: merge feature
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="go"&gt; (cherry picked from commit 8865ad060c1c64fbc3c0196e12302b1d96e8bf30)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="速查表"&gt;速查表
&lt;/h2&gt;&lt;p&gt;一句话记住：&lt;strong&gt;&lt;code&gt;-m N&lt;/code&gt; 选第 N 个父提交当基准，带走的是另一侧的改动；搬运已合并的功能，用 &lt;code&gt;-m 1&lt;/code&gt;。&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;命令&lt;/th&gt;
&lt;th&gt;作用&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git cherry-pick -m 1 &amp;lt;M&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;把 M 相对 parent 1 的差异（被合入分支的改动）应用到当前分支&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git cherry-pick -m 2 &amp;lt;M&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;把 M 相对 parent 2 的差异（主线一侧的改动）应用到当前分支&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git cherry-pick -x -m 1 &amp;lt;M&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;同上，并在提交信息里记录来源 SHA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git log -1 &amp;lt;M&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;查看 &lt;code&gt;Merge:&lt;/code&gt; 行，确认父提交顺序&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git rev-parse &amp;lt;M&amp;gt;^1 &amp;lt;M&amp;gt;^2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;分别打印 parent 1 和 parent 2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git cherry-pick --continue&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;解决冲突并 &lt;code&gt;git add&lt;/code&gt; 后继续&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git cherry-pick --abort&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;放弃本次 cherry-pick，回到操作前&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git revert -m 1 &amp;lt;M&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;撤销整个合并带来的改动&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</description></item></channel></rss>