Git Merge+Revert 与 Reset+Cherry-pick 对比
原创2025年5月17日...大约 26 分钟
日常使用 git 开发管理分支非常方便,但是偶尔也会出现一些问题,比如这次就遇到了回滚合并导致后续合并丢失部分内容这样的情况,本文介绍一下如何处理这种情况,分析事故原因。
Merge+Revert 方案在复杂合并和回滚时容易引入副作用,可能导致部分内容被意外撤销;而 Reset+Cherry-pick 方案通过重置和精确挑选提交,能更好地避免这些问题,分支内容更安全、可控。
推荐使用 Reset+Cherry-pick 方案。
方案对比 (简要)
阶段 | 方案一:Merge + Revert | 方案二:Reset + Cherry-pick |
---|---|---|
阶段 1:初始状态 | a: b: 1 2 3 c: 4 5 6 7 8 | a: b: 1 2 3 c: 4 5 6 7 8 |
阶段 2:b 合并 c 并继续开发 | b: 1 2 3 4 5 6 7 8 9 10 | b: 1 2 3 4 5 6 7 8 9 10 |
阶段 3:b 回滚合并, b 继续开发 | b: 1 2 3 9 10 revert(merge c) 差异:此时 revert(merge c) 实际撤销了 4,5,6,7,8 的更改,但 9,10 依然保留。 | b: 1 2 3 9 10 差异:左侧通过 revert 撤销合并,右侧直接 reset 到合并前并 cherry-pick 新提交,避免了 revert 带来的副作用。 |
阶段 4:a 合并 c 的 4,5,6 | a: 4 5 6 | a: 4 5 6 |
阶段 5:a 合并 b | a: 4 5 6 1 2 3 revert(merge c) 9 10 差异:revert(merge c) 也被合并进 a,导致 a 上 4,5,6 的更改被撤销。 | a: 4 5 6 1 2 3 9 10 差异:没有 revert(merge c) 的副作用,a 上 4,5,6 保持不变。 |
最终结果 | a: 4 5 6 1 2 3 revert(merge c) 9 10 a 分支的 4,5,6 被 revert(merge c) 撤销,内容丢失。 | a: 4 5 6 1 2 3 9 10 a 分支完整保留了 4,5,6,没有被撤销,内容安全。 |
上述操作的图形化演示
<style>
body {
font-family: sans-serif;
background: #fafbfc;
margin: 0;
padding: 0 8px;
}
.main-content {
max-width: 1200px;
margin: 0 auto;
background: #fff;
border-radius: 12px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
padding: 24px 12px 40px 12px;
}
h1 {
text-align: center;
margin-bottom: 16px;
}
.compare-table {
width: 100%;
border-collapse: separate;
border-spacing: 0 18px;
}
.compare-table th,
.compare-table td {
vertical-align: top;
padding: 0 12px;
width: 50%;
}
.compare-table th {
font-size: 1.1em;
color: #2196f3;
text-align: center;
padding-bottom: 8px;
}
.stage-title-scheme1 {
font-weight: bold;
font-size: 1.1em;
margin-bottom: 6px;
color: #1976d2;
}
.stage-title-scheme2 {
font-weight: bold;
font-size: 1.1em;
margin-bottom: 6px;
color: #388e3c;
}
.stage-block {
background: #f7fafd;
border-radius: 8px;
padding: 12px 10px 10px 10px;
margin-bottom: 0;
border: 1px solid #e3e8ee;
}
.diff {
background: #fff3e0;
border: 2px solid #ff9800;
border-radius: 8px;
padding: 10px 10px 8px 10px;
margin-top: 8px;
margin-bottom: 0;
}
.final-result {
background: #e3f2fd;
border: 2px solid #2196f3;
border-radius: 8px;
padding: 12px 10px 10px 10px;
margin-top: 8px;
margin-bottom: 0;
}
.commit-node {
display: inline-block;
padding: 3px 8px;
border-radius: 5px;
margin-right: 6px;
font-size: 0.98em;
}
.branch-a-node {
background: #2196f3;
color: #fff;
}
.branch-b-node {
background: #4caf50;
color: #fff;
}
.branch-c-node {
background: #ff9800;
color: #fff;
}
.merged-node-from-c {
background: #ff9800;
color: #fff;
border: 1.5px solid #ff9800;
}
.merged-node-from-b {
background: #4caf50;
color: #fff;
border: 1.5px solid #4caf50;
}
.cherry-picked-commit {
background: #ffebee;
border: 1px solid #ef9a9a;
color: #c62828;
}
.revert {
background: #ffe0b2;
border: 1px solid #ffb300;
color: #b26a00;
}
.strike {
text-decoration: line-through;
color: #888;
background: #e0e0e0 !important;
border: 2px solid #bdbdbd !important;
}
.stage-desc {
color: #888;
font-size: 0.97em;
margin-bottom: 6px;
}
@media (max-width: 900px) {
.compare-table th,
.compare-table td {
display: block;
width: 100%;
}
.compare-table tr {
display: block;
margin-bottom: 32px;
}
}
/* Styles for collapsible sections */
.collapsible-header {
background-color: #f1f1f1;
color: #333;
cursor: pointer;
padding: 16px 12px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 1.1em;
margin-top: 20px;
border-radius: 8px;
transition: background-color 0.3s ease;
border-bottom-right-radius: 8px;
}
.collapsible-header:hover {
background-color: #ddd;
}
.collapsible-content {
padding: 16px 12px;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
background-color: #f9f9f9;
border-left: 1px solid #eee;
border-right: 1px solid #eee;
border-bottom: 1px solid #eee;
border-bottom-left-radius: 8px;
border-bottom-right-radius: 8px;
}
.collapsible-content.active {
max-height: 5000px;
/* Adjust based on expected content height */
}
/* Styles from git_log.html and git_log_chreey_pick.html */
.branch-container {
margin-bottom: 5px;
padding: 6px 0;
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 2px;
}
.branch-label {
background-color: #f9f9f9;
border: 1px solid #eee;
padding: 5px 10px;
margin-bottom: 2px;
display: inline-block;
}
/* .commit-node style is already defined */
/* .branch-a-node, .branch-b-node, .branch-c-node styles are already defined */
.merged-node-from-c {
background-color: #ff9800;
/* Orange - indicating from c */
}
.merged-node-from-b {
background-color: #4caf50;
/* Green - indicating from b */
}
.revert {
background-color: #ffe0b2;
border: 1px solid #ffb300;
color: black;
}
.cherry-picked-commit {
background-color: #ffebee;
border: 1px solid #ef9a9a;
color: black;
}
.branch-commits {
display: flex;
align-items: center;
}
.arrow {
margin-right: 10px;
font-size: 1.2em;
color: #777;
}
.final-a {
background-color: #fce4ec;
border: 1px solid #f48fb1;
}
.strike {
text-decoration: line-through;
color: gray;
}
.strike.branch-a-node,
.strike.branch-b-node,
.strike.branch-c-node,
.strike.merged-node-from-c,
.strike.merged-node-from-b {
background-color: #eee !important;
color: #888;
text-decoration: line-through;
}
.step-description {
margin-top: 10px;
padding-left: 20px;
font-size: 0.9em;
color: #555;
}
.temp-branch-label {
background-color: #e0f2f7;
border: 1px solid #b2ebf2;
padding: 5px 10px;
margin-bottom: 2px;
display: inline-block;
}
/* Existing styles for collapsible sections */
.collapsible-header {
padding: 16px 12px;
}
.collapsible-content.active {
max-height: 5000px;
/* Adjust based on expected content height */
}
</style>
<div class="main-content">
<table class="compare-table">
<tr>
<th>方案一:Merge + Revert</th>
<th>方案二:Reset + Cherry-pick</th>
</tr>
<tr>
<td>
<div class="stage-title stage-title-scheme1">阶段1:初始状态</div>
<div class="stage-block">
<b>a:</b> <br />
<b>b:</b> <span class="commit-node branch-b-node">1</span
><span class="commit-node branch-b-node">2</span
><span class="commit-node branch-b-node">3</span><br />
<b>c:</b> <span class="commit-node branch-c-node">4</span
><span class="commit-node branch-c-node">5</span
><span class="commit-node branch-c-node">6</span
><span class="commit-node branch-c-node">7</span
><span class="commit-node branch-c-node">8</span>
</div>
</td>
<td>
<div class="stage-title stage-title-scheme2">阶段1:初始状态</div>
<div class="stage-block">
<b>a:</b> <br />
<b>b:</b> <span class="commit-node branch-b-node">1</span
><span class="commit-node branch-b-node">2</span
><span class="commit-node branch-b-node">3</span><br />
<b>c:</b> <span class="commit-node branch-c-node">4</span
><span class="commit-node branch-c-node">5</span
><span class="commit-node branch-c-node">6</span
><span class="commit-node branch-c-node">7</span
><span class="commit-node branch-c-node">8</span>
</div>
</td>
</tr>
<tr>
<td>
<div class="stage-title stage-title-scheme1">
阶段2:b 合并 c 并继续开发
</div>
<div class="stage-block">
<b>b:</b> <span class="commit-node branch-b-node">1</span
><span class="commit-node branch-b-node">2</span
><span class="commit-node branch-b-node">3</span
><span class="commit-node merged-node-from-c">4</span
><span class="commit-node merged-node-from-c">5</span
><span class="commit-node merged-node-from-c">6</span
><span class="commit-node merged-node-from-c">7</span
><span class="commit-node merged-node-from-c">8</span
><span class="commit-node branch-b-node">9</span
><span class="commit-node branch-b-node">10</span>
</div>
</td>
<td>
<div class="stage-title stage-title-scheme2">
阶段2:b 合并 c 并继续开发
</div>
<div class="stage-block">
<b>b:</b> <span class="commit-node branch-b-node">1</span
><span class="commit-node branch-b-node">2</span
><span class="commit-node branch-b-node">3</span
><span class="commit-node merged-node-from-c">4</span
><span class="commit-node merged-node-from-c">5</span
><span class="commit-node merged-node-from-c">6</span
><span class="commit-node merged-node-from-c">7</span
><span class="commit-node merged-node-from-c">8</span
><span class="commit-node branch-b-node">9</span
><span class="commit-node branch-b-node">10</span>
</div>
</td>
</tr>
<tr>
<td>
<div class="stage-title stage-title-scheme1">
阶段3:b 回滚合并, b 继续开发
</div>
<div class="stage-block">
<b>b:</b> <span class="commit-node branch-b-node">1</span
><span class="commit-node branch-b-node">2</span>
<span class="commit-node branch-b-node">3</span>
<span class="commit-node strike branch-a-node merged-node-from-c"
>4</span
>
<span class="commit-node strike branch-a-node merged-node-from-c"
>5</span
>
<span class="commit-node strike branch-a-node merged-node-from-c"
>6</span
>
<span class="commit-node strike branch-a-node merged-node-from-c"
>7</span
>
<span class="commit-node strike branch-a-node merged-node-from-c"
>8</span
>
<span class="commit-node branch-b-node">9</span
><span class="commit-node branch-b-node">10</span
><span class="commit-node revert">revert(merge c)</span>
<div class="diff">
差异:<br />此时 revert(merge c) 实际撤销了 4,5,6,7,8 的更改,但
9,10 依然保留。
</div>
</div>
</td>
<td>
<div class="stage-title stage-title-scheme2">
阶段3:b 重置并 cherry-pick
</div>
<div class="stage-block">
<b>b:</b> <span class="commit-node branch-b-node">1</span
><span class="commit-node branch-b-node">2</span
><span class="commit-node branch-b-node">3</span
><span class="commit-node cherry-picked-commit branch-b-node">9</span
><span class="commit-node cherry-picked-commit branch-b-node"
>10</span
>
<div class="diff">
差异:<br />左侧通过 revert 撤销合并,右侧直接 reset 到合并前并
cherry-pick 新提交,避免了 revert 带来的副作用。
</div>
</div>
</td>
</tr>
<tr>
<td>
<div class="stage-title stage-title-scheme1">
阶段4:a 合并 c 的 4,5,6
</div>
<div class="stage-block">
<b>a:</b>
<span class="commit-node branch-a-node merged-node-from-c">4</span
><span class="commit-node branch-a-node merged-node-from-c">5</span
><span class="commit-node branch-a-node merged-node-from-c">6</span>
</div>
</td>
<td>
<div class="stage-title stage-title-scheme2">
阶段4:a 合并 c 的 4,5,6
</div>
<div class="stage-block">
<b>a:</b>
<span class="commit-node branch-a-node merged-node-from-c">4</span
><span class="commit-node branch-a-node merged-node-from-c">5</span
><span class="commit-node branch-a-node merged-node-from-c">6</span>
</div>
</td>
</tr>
<tr>
<td>
<div class="stage-title stage-title-scheme1">阶段5:a 合并 b</div>
<div class="stage-block">
<b>a:</b>
<span class="commit-node branch-a-node merged-node-from-c">4</span
><span class="commit-node branch-a-node merged-node-from-c">5</span
><span class="commit-node branch-a-node merged-node-from-c">6</span
><span class="commit-node branch-a-node merged-node-from-b">1</span
><span class="commit-node branch-a-node merged-node-from-b">2</span
><span class="commit-node branch-a-node merged-node-from-b">3</span>
<span class="commit-node strike branch-a-node merged-node-from-c"
>4</span
>
<span class="commit-node strike branch-a-node merged-node-from-c"
>5</span
>
<span class="commit-node strike branch-a-node merged-node-from-c"
>6</span
>
<span class="commit-node strike branch-a-node merged-node-from-c"
>7</span
>
<span class="commit-node strike branch-a-node merged-node-from-c"
>8</span
><span class="commit-node revert">revert(merge c)</span
><span class="commit-node branch-a-node merged-node-from-b">9</span
><span class="commit-node branch-a-node merged-node-from-b">10</span>
<div class="diff">
差异:<br />revert(merge c) 也被合并进 a,导致 a 上 4,5,6
的更改被撤销。
</div>
</div>
</td>
<td>
<div class="stage-title stage-title-scheme2">阶段5:a 合并 b</div>
<div class="stage-block">
<b>a:</b>
<span class="commit-node branch-a-node merged-node-from-c">4</span
><span class="commit-node branch-a-node merged-node-from-c">5</span
><span class="commit-node branch-a-node merged-node-from-c">6</span
><span class="commit-node branch-a-node merged-node-from-b">1</span
><span class="commit-node branch-a-node merged-node-from-b">2</span
><span class="commit-node branch-a-node merged-node-from-b">3</span
><span
class="commit-node branch-a-node merged-node-from-b cherry-picked-commit"
>9</span
><span
class="commit-node branch-a-node merged-node-from-b cherry-picked-commit"
>10</span
>
<div class="diff">
差异:<br />没有 revert(merge c) 的副作用,a 上 4,5,6 保持不变。
</div>
</div>
</td>
</tr>
<tr>
<td>
<div class="stage-title stage-title-scheme1">最终结果</div>
<div class="final-result">
<b>a:</b>
<span class="commit-node strike branch-a-node merged-node-from-c"
>4</span
><span class="commit-node strike branch-a-node merged-node-from-c"
>5</span
><span class="commit-node strike branch-a-node merged-node-from-c"
>6</span
><span class="commit-node branch-a-node merged-node-from-b">1</span
><span class="commit-node branch-a-node merged-node-from-b">2</span
><span class="commit-node branch-a-node merged-node-from-b">3</span
><span class="commit-node revert">revert(merge c)</span
><span class="commit-node branch-a-node merged-node-from-b">9</span
><span class="commit-node branch-a-node merged-node-from-b">10</span>
<div class="diff">
a 分支的 4,5,6 被 revert(merge c) 撤销,内容丢失。
</div>
</div>
</td>
<td>
<div class="stage-title stage-title-scheme2">最终结果</div>
<div class="final-result">
<b>a:</b>
<span class="commit-node branch-a-node merged-node-from-c">4</span
><span class="commit-node branch-a-node merged-node-from-c">5</span
><span class="commit-node branch-a-node merged-node-from-c">6</span
><span class="commit-node branch-a-node merged-node-from-b">1</span
><span class="commit-node branch-a-node merged-node-from-b">2</span
><span class="commit-node branch-a-node merged-node-from-b">3</span
><span
class="commit-node branch-a-node merged-node-from-b cherry-picked-commit"
>9</span
><span
class="commit-node branch-a-node merged-node-from-b cherry-picked-commit"
>10</span
>
<div class="diff">a 分支完整保留了 4,5,6,没有被撤销,内容安全。</div>
</div>
</td>
</tr>
</table>
</div>
Merge + Revert 详细步骤
<style>
body {
font-family: sans-serif;
background: #fafbfc;
margin: 0;
padding: 0 8px;
}
.main-content {
max-width: 1200px;
margin: 0 auto;
background: #fff;
border-radius: 12px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
padding: 24px 12px 40px 12px;
}
h1 {
text-align: center;
margin-bottom: 16px;
}
.compare-table {
width: 100%;
border-collapse: separate;
border-spacing: 0 18px;
}
.compare-table th,
.compare-table td {
vertical-align: top;
padding: 0 12px;
width: 50%;
}
.compare-table th {
font-size: 1.1em;
color: #2196f3;
text-align: center;
padding-bottom: 8px;
}
.stage-title-scheme1 {
font-weight: bold;
font-size: 1.1em;
margin-bottom: 6px;
color: #1976d2;
}
.stage-title-scheme2 {
font-weight: bold;
font-size: 1.1em;
margin-bottom: 6px;
color: #388e3c;
}
.stage-block {
background: #f7fafd;
border-radius: 8px;
padding: 12px 10px 10px 10px;
margin-bottom: 0;
border: 1px solid #e3e8ee;
}
.diff {
background: #fff3e0;
border: 2px solid #ff9800;
border-radius: 8px;
padding: 10px 10px 8px 10px;
margin-top: 8px;
margin-bottom: 0;
}
.final-result {
background: #e3f2fd;
border: 2px solid #2196f3;
border-radius: 8px;
padding: 12px 10px 10px 10px;
margin-top: 8px;
margin-bottom: 0;
}
.commit-node {
display: inline-block;
padding: 3px 8px;
border-radius: 5px;
margin-right: 6px;
font-size: 0.98em;
}
.branch-a-node {
background: #2196f3;
color: #fff;
}
.branch-b-node {
background: #4caf50;
color: #fff;
}
.branch-c-node {
background: #ff9800;
color: #fff;
}
.merged-node-from-c {
background: #ff9800;
color: #fff;
border: 1.5px solid #ff9800;
}
.merged-node-from-b {
background: #4caf50;
color: #fff;
border: 1.5px solid #4caf50;
}
.cherry-picked-commit {
background: #ffebee;
border: 1px solid #ef9a9a;
color: #c62828;
}
.revert {
background: #ffe0b2;
border: 1px solid #ffb300;
color: #b26a00;
}
.strike {
text-decoration: line-through;
color: #888;
background: #e0e0e0 !important;
border: 2px solid #bdbdbd !important;
}
.stage-desc {
color: #888;
font-size: 0.97em;
margin-bottom: 6px;
}
@media (max-width: 900px) {
.compare-table th,
.compare-table td {
display: block;
width: 100%;
}
.compare-table tr {
display: block;
margin-bottom: 32px;
}
}
.collapsible-header {
background-color: #f1f1f1;
color: #333;
cursor: pointer;
padding: 16px 12px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 1.1em;
margin-top: 20px;
border-radius: 8px;
transition: background-color 0.3s ease;
border-bottom-right-radius: 8px;
}
.collapsible-header:hover {
background-color: #ddd;
}
.collapsible-content {
padding: 16px 12px;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
background-color: #f9f9f9;
border-left: 1px solid #eee;
border-right: 1px solid #eee;
border-bottom: 1px solid #eee;
border-bottom-left-radius: 8px;
border-bottom-right-radius: 8px;
}
.collapsible-content.active {
max-height: 5000px;
}
.branch-container {
margin-bottom: 5px;
padding: 6px 0;
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 2px;
}
.branch-label {
background-color: #f9f9f9;
border: 1px solid #eee;
padding: 5px 10px;
margin-bottom: 2px;
display: inline-block;
}
.merged-node-from-c {
background-color: #ff9800;
}
.merged-node-from-b {
background-color: #4caf50;
}
.revert {
background-color: #ffe0b2;
border: 1px solid #ffb300;
color: black;
}
.cherry-picked-commit {
background-color: #ffebee;
border: 1px solid #ef9a9a;
color: black;
}
.branch-commits {
display: flex;
align-items: center;
}
.arrow {
margin-right: 10px;
font-size: 1.2em;
color: #777;
}
.final-a {
background-color: #fce4ec;
border: 1px solid #f48fb1;
}
.strike {
text-decoration: line-through;
color: gray;
}
.strike.branch-a-node,
.strike.branch-b-node,
.strike.branch-c-node,
.strike.merged-node-from-c,
.strike.merged-node-from-b {
background-color: #eee !important;
color: #888;
text-decoration: line-through;
}
.step-description {
margin-top: 10px;
padding-left: 20px;
font-size: 0.9em;
color: #555;
}
.temp-branch-label {
background-color: #e0f2f7;
border: 1px solid #b2ebf2;
padding: 5px 10px;
margin-bottom: 2px;
display: inline-block;
}
.collapsible-header {
padding: 16px 12px;
}
.collapsible-content.active {
max-height: 5000px;
}
</style>
<!-- Detailed Steps Section -->
<div>
<!-- Content from git_log.html body -->
<div id="stage1-colored" class="branch-container">
<h2>阶段 1: a, b, c 分支初始状态</h2>
<div class="branch-container">
<div class="branch-label">分支 a</div>
<div id="a1-colored" class="branch-commits"></div>
</div>
<div class="branch-container">
<div class="branch-label">分支 b</div>
<div id="b1-colored" class="branch-commits">
<span class="commit-node branch-b-node">1</span>
<span class="commit-node branch-b-node">2</span>
<span class="commit-node branch-b-node">3</span>
</div>
</div>
<div class="branch-container">
<div class="branch-label">分支 c</div>
<div id="c1-colored" class="branch-commits">
<span class="commit-node branch-c-node">4</span>
<span class="commit-node branch-c-node">5</span>
<span class="commit-node branch-c-node">6</span>
<span class="commit-node branch-c-node">7</span>
<span class="commit-node branch-c-node">8</span>
</div>
</div>
<p>(初始状态,a 为空,b 有 1, 2, 3,c 有 4, 5, 6, 7, 8)</p>
</div>
<div id="stage2-colored" class="branch-container">
<h2>阶段 2: b 合并 c</h2>
<div class="branch-container">
<div class="branch-label">分支 b</div>
<div id="b2-colored" class="branch-commits">
<span class="commit-node branch-b-node">1</span>
<span class="commit-node branch-b-node">2</span>
<span class="commit-node branch-b-node">3</span>
<span class="commit-node merged-node-from-c">4</span>
<span class="commit-node merged-node-from-c">5</span>
<span class="commit-node merged-node-from-c">6</span>
<span class="commit-node merged-node-from-c">7</span>
<span class="commit-node merged-node-from-c">8</span>
</div>
</div>
<div class="branch-container">
<div class="branch-label">分支 c (不变)</div>
<div id="c2-colored" class="branch-commits">
<span class="commit-node branch-c-node">4</span>
<span class="commit-node branch-c-node">5</span>
<span class="commit-node branch-c-node">6</span>
<span class="commit-node branch-c-node">7</span>
<span class="commit-node branch-c-node">8</span>
</div>
</div>
<div class="branch-container">
<div class="branch-label">分支 a (不变)</div>
<div id="a2-colored" class="branch-commits"></div>
</div>
<p>(b 合并 c,来自 c 的提交颜色为橙色)</p>
</div>
<div id="stage3-colored" class="branch-container">
<h2>阶段 3: b 回滚合并, b 继续开发</h2>
<div class="branch-container">
<div class="branch-label">分支 b</div>
<div id="b3-colored" class="branch-commits">
<span class="commit-node branch-b-node">1</span>
<span class="commit-node branch-b-node">2</span>
<span class="commit-node branch-b-node">3</span>
<span class="commit-node strike branch-a-node merged-node-from-c"
>4</span
>
<span class="commit-node strike branch-a-node merged-node-from-c"
>5</span
>
<span class="commit-node strike branch-a-node merged-node-from-c"
>6</span
>
<span class="commit-node strike branch-a-node merged-node-from-c"
>7</span
>
<span class="commit-node strike branch-a-node merged-node-from-c"
>8</span
>
<span class="commit-node branch-b-node">9</span>
<span class="commit-node branch-b-node">10</span>
<span class="commit-node revert">revert(merge c)</span>
</div>
</div>
<div class="branch-container">
<div class="branch-label">分支 c (不变)</div>
<div id="c3-colored" class="branch-commits">
<span class="commit-node branch-c-node">4</span>
<span class="commit-node branch-c-node">5</span>
<span class="commit-node branch-c-node">6</span>
<span class="commit-node branch-c-node">7</span>
<span class="commit-node branch-c-node">8</span>
</div>
</div>
<div class="branch-container">
<div class="branch-label">分支 a (不变)</div>
<div id="a3-colored" class="branch-commits"></div>
</div>
<p>(b 回滚合并 c 后继续开发)</p>
</div>
<div id="stage4-colored" class="branch-container">
<h2>阶段 4: a 合并 c 的 4, 5, 6</h2>
<div class="branch-container">
<div class="branch-label">分支 a</div>
<div id="a4-colored" class="branch-commits">
<span class="commit-node branch-a-node merged-node-from-c">4</span>
<span class="commit-node branch-a-node merged-node-from-c">5</span>
<span class="commit-node branch-a-node merged-node-from-c">6</span>
</div>
</div>
<div class="branch-container">
<div class="branch-label">分支 b (不变)</div>
<div id="b4-colored" class="branch-commits">
<span class="commit-node branch-b-node">1</span>
<span class="commit-node branch-b-node">2</span>
<span class="commit-node branch-b-node">3</span>
<span class="commit-node strike branch-a-node merged-node-from-c"
>4</span
>
<span class="commit-node strike branch-a-node merged-node-from-c"
>5</span
>
<span class="commit-node strike branch-a-node merged-node-from-c"
>6</span
>
<span class="commit-node strike branch-a-node merged-node-from-c"
>7</span
>
<span class="commit-node strike branch-a-node merged-node-from-c"
>8</span
>
<span class="commit-node revert">revert(merge c)</span>
<span class="commit-node branch-b-node">9</span>
<span class="commit-node branch-b-node">10</span>
</div>
</div>
<div class="branch-container">
<div class="branch-label">分支 c (不变)</div>
<div id="c4-colored" class="branch-commits">
<span class="commit-node branch-c-node">4</span>
<span class="commit-node branch-c-node">5</span>
<span class="commit-node branch-c-node">6</span>
<span class="commit-node branch-c-node">7</span>
<span class="commit-node branch-c-node">8</span>
</div>
</div>
<p>(a 合并 c 的部分提交,颜色为橙色)</p>
</div>
<div id="stage5-colored" class="branch-container">
<h2>阶段 5: a 合并 b</h2>
<div class="branch-container">
<div class="branch-label">分支 a (合并 b 后)</div>
<div id="a5-colored" class="branch-commits">
<span class="commit-node branch-a-node merged-node-from-c">4</span>
<span class="commit-node branch-a-node merged-node-from-c">5</span>
<span class="commit-node branch-a-node merged-node-from-c">6</span>
<span class="commit-node branch-a-node merged-node-from-b">1</span>
<span class="commit-node branch-a-node merged-node-from-b">2</span>
<span class="commit-node branch-a-node merged-node-from-b">3</span>
<span class="commit-node strike branch-a-node merged-node-from-c"
>4</span
>
<span class="commit-node strike branch-a-node merged-node-from-c"
>5</span
>
<span class="commit-node strike branch-a-node merged-node-from-c"
>6</span
>
<span class="commit-node strike branch-a-node merged-node-from-c"
>7</span
>
<span class="commit-node strike branch-a-node merged-node-from-c"
>8</span
>
<span class="commit-node revert">revert(merge c)</span>
<span class="commit-node branch-a-node merged-node-from-b">9</span>
<span class="commit-node branch-a-node merged-node-from-b">10</span>
</div>
</div>
<div class="branch-container">
<div class="branch-label">分支 b (不变)</div>
<div id="b5-colored" class="branch-commits">
<span class="commit-node branch-b-node">1</span>
<span class="commit-node branch-b-node">2</span>
<span class="commit-node branch-b-node">3</span>
<span class="commit-node strike branch-a-node merged-node-from-c"
>4</span
>
<span class="commit-node strike branch-a-node merged-node-from-c"
>5</span
>
<span class="commit-node strike branch-a-node merged-node-from-c"
>6</span
>
<span class="commit-node strike branch-a-node merged-node-from-c"
>7</span
>
<span class="commit-node strike branch-a-node merged-node-from-c"
>8</span
>
<span class="commit-node revert">revert(merge c)</span>
<span class="commit-node branch-b-node">9</span>
<span class="commit-node branch-b-node">10</span>
</div>
</div>
<div class="branch-container">
<div class="branch-label">分支 c (不变)</div>
<div id="c5-colored" class="branch-commits">
<span class="commit-node branch-c-node">4</span>
<span class="commit-node branch-c-node">5</span>
<span class="commit-node branch-c-node">6</span>
<span class="commit-node branch-c-node">7</span>
<span class="commit-node branch-c-node">8</span>
</div>
</div>
<p>(a 合并 b,来自 b 的提交颜色为绿色)</p>
</div>
<div id="stage6-colored" class="branch-container">
<h2>阶段 6: a 分支最终状态 (体现 revert 效果)</h2>
<div class="branch-container">
<div class="branch-label final-a">分支 a (最终状态)</div>
<div id="a6-colored" class="branch-commits">
<span class="commit-node strike branch-a-node merged-node-from-c"
>4</span
>
<span class="commit-node strike branch-a-node merged-node-from-c"
>5</span
>
<span class="commit-node strike branch-a-node merged-node-from-c"
>6</span
>
<span class="commit-node branch-a-node merged-node-from-b">1</span>
<span class="commit-node branch-a-node merged-node-from-b">2</span>
<span class="commit-node branch-a-node merged-node-from-b">3</span>
<span class="commit-node revert">revert(merge c)</span>
<span class="commit-node branch-a-node merged-node-from-b">9</span>
<span class="commit-node branch-a-node merged-node-from-b">10</span>
</div>
</div>
<div class="branch-container">
<div class="branch-label">分支 b</div>
<div id="b6-colored" class="branch-commits">
<span class="commit-node branch-b-node">1</span>
<span class="commit-node branch-b-node">2</span>
<span class="commit-node branch-b-node">3</span>
<span class="commit-node revert">revert(merge c)</span>
<span class="commit-node branch-b-node">9</span>
<span class="commit-node branch-b-node">10</span>
</div>
</div>
<div class="branch-container">
<div class="branch-label">分支 c</div>
<div id="c6-colored" class="branch-commits">
<span class="commit-node branch-c-node">4</span>
<span class="commit-node branch-c-node">5</span>
<span class="commit-node branch-c-node">6</span>
<span class="commit-node branch-c-node">7</span>
<span class="commit-node branch-c-node">8</span>
</div>
</div>
<p>注意:被 revert 的来自 c 的提交在 a 分支上显示为删除线。</p>
</div>
</div>
Reset + Cherry-pick 详细步骤
<style>
body{font-family:sans-serif;background:#fafbfc;margin:0;padding:0 8px}.main-content{max-width:1200px;margin:0 auto;background:#fff;border-radius:12px;box-shadow:0 2px 12px rgba(0,0,0,0.04);padding:24px 12px 40px 12px}h1{text-align:center;margin-bottom:16px}.compare-table{width:100%;border-collapse:separate;border-spacing:0 18px}.compare-table th,.compare-table td{vertical-align:top;padding:0 12px;width:50%}.compare-table th{font-size:1.1em;color:#2196f3;text-align:center;padding-bottom:8px}.stage-title-scheme1{font-weight:bold;font-size:1.1em;margin-bottom:6px;color:#1976d2}.stage-title-scheme2{font-weight:bold;font-size:1.1em;margin-bottom:6px;color:#388e3c}.stage-block{background:#f7fafd;border-radius:8px;padding:12px 10px 10px 10px;margin-bottom:0;border:1px solid #e3e8ee}.diff{background:#fff3e0;border:2px solid #ff9800;border-radius:8px;padding:10px 10px 8px 10px;margin-top:8px;margin-bottom:0}.final-result{background:#e3f2fd;border:2px solid #2196f3;border-radius:8px;padding:12px 10px 10px 10px;margin-top:8px;margin-bottom:0}.commit-node{display:inline-block;padding:3px 8px;border-radius:5px;margin-right:6px;font-size:0.98em}.branch-a-node{background:#2196f3;color:#fff}.branch-b-node{background:#4caf50;color:#fff}.branch-c-node{background:#ff9800;color:#fff}.merged-node-from-c{background:#ff9800;color:#fff;border:1.5px solid #ff9800}.merged-node-from-b{background:#4caf50;color:#fff;border:1.5px solid #4caf50}.cherry-picked-commit{background:#ffebee;border:1px solid #ef9a9a;color:#c62828}.revert{background:#ffe0b2;border:1px solid #ffb300;color:#b26a00}.strike{text-decoration:line-through;color:#888;background:#e0e0e0 !important;border:2px solid #bdbdbd !important}.stage-desc{color:#888;font-size:0.97em;margin-bottom:6px}@media (max-width:900px){.compare-table th,.compare-table td{display:block;width:100%}.compare-table tr{display:block;margin-bottom:32px}}.collapsible-header{background-color:#f1f1f1;color:#333;cursor:pointer;padding:16px 12px;width:100%;border:none;text-align:left;outline:none;font-size:1.1em;margin-top:20px;border-radius:8px;transition:background-color 0.3s ease;border-bottom-right-radius:8px}.collapsible-header:hover{background-color:#ddd}.collapsible-content{padding:16px 12px;max-height:0;overflow:hidden;transition:max-height 0.2s ease-out;background-color:#f9f9f9;border-left:1px solid #eee;border-right:1px solid #eee;border-bottom:1px solid #eee;border-bottom-left-radius:8px;border-bottom-right-radius:8px}.collapsible-content.active{max-height:5000px}.branch-container{margin-bottom:5px;padding:6px 0;display:flex;flex-direction:column;align-items:flex-start;gap:2px}.branch-label{background-color:#f9f9f9;border:1px solid #eee;padding:5px 10px;margin-bottom:2px;display:inline-block}.merged-node-from-c{background-color:#ff9800}.merged-node-from-b{background-color:#4caf50}.revert{background-color:#ffe0b2;border:1px solid #ffb300;color:black}.cherry-picked-commit{background-color:#ffebee;border:1px solid #ef9a9a;color:black}.branch-commits{display:flex;align-items:center}.arrow{margin-right:10px;font-size:1.2em;color:#777}.final-a{background-color:#fce4ec;border:1px solid #f48fb1}.strike{text-decoration:line-through;color:gray}.strike.branch-a-node,.strike.branch-b-node,.strike.branch-c-node,.strike.merged-node-from-c,.strike.merged-node-from-b{background-color:#eee !important;color:#888;text-decoration:line-through}.step-description{margin-top:10px;padding-left:20px;font-size:0.9em;color:#555}.temp-branch-label{background-color:#e0f2f7;border:1px solid #b2ebf2;padding:5px 10px;margin-bottom:2px;display:inline-block}.collapsible-header{padding:16px 12px}.collapsible-content.active{max-height:5000px}</style>
<div >
<!-- Content from git_log_chreey_pick.html body -->
<div id="stage1-reset-graphic" class="branch-container">
<h2>阶段 1: 初始状态</h2>
<div class="branch-container">
<div class="branch-label">分支 a</div>
<div id="a1-reset-graphic" class="branch-commits"></div>
</div>
<div class="branch-container">
<div class="branch-label">分支 b</div>
<div id="b1-reset-graphic" class="branch-commits">
<span class="commit-node branch-b-node">1</span>
<span class="commit-node branch-b-node">2</span>
<span class="commit-node branch-b-node">3</span>
</div>
</div>
<div class="branch-container">
<div class="branch-label">分支 c</div>
<div id="c1-reset-graphic" class="branch-commits">
<span class="commit-node branch-c-node">4</span>
<span class="commit-node branch-c-node">5</span>
<span class="commit-node branch-c-node">6</span>
<span class="commit-node branch-c-node">7</span>
<span class="commit-node branch-c-node">8</span>
</div>
</div>
<p>(初始状态)</p>
</div>
<div id="stage2-reset-graphic" class="branch-container">
<h2>阶段 2: b 合并 c,并继续开发</h2>
<div class="branch-container">
<div class="branch-label">分支 b</div>
<div id="b2-reset-graphic" class="branch-commits">
<span class="commit-node branch-b-node">1</span>
<span class="commit-node branch-b-node">2</span>
<span class="commit-node branch-b-node">3</span>
<span class="commit-node merged-node-from-c">4</span>
<span class="commit-node merged-node-from-c">5</span>
<span class="commit-node merged-node-from-c">6</span>
<span class="commit-node merged-node-from-c">7</span>
<span class="commit-node merged-node-from-c">8</span>
<span class="commit-node branch-b-node">9</span>
<span class="commit-node branch-b-node">10</span>
</div>
</div>
<div class="branch-container">
<div class="branch-label">分支 c (不变)</div>
<div id="c2-reset-graphic" class="branch-commits">
<span class="commit-node branch-c-node">4</span>
<span class="commit-node branch-c-node">5</span>
<span class="commit-node branch-c-node">6</span>
<span class="commit-node branch-c-node">7</span>
<span class="commit-node branch-c-node">8</span>
</div>
</div>
<div class="branch-container">
<div class="branch-label">分支 a (不变)</div>
<div id="a2-reset-graphic" class="branch-commits"></div>
</div>
<p>(b 合并了 c,之后又有提交 9 和 10)</p>
</div>
<div id="stage3-reset-detailed" class="branch-container">
<h2>阶段 3: b 重置和 Cherry-pick (带备份)</h2>
<div class="branch-label">分支 b (reset 和 Cherry-pick)</div>
<ol>
<li><strong>备份 b 分支:</strong> <code>git checkout -b temp_b</code> (当前在 b 分支时)
<div class="branch-container">
<div class="temp-branch-label">临时分支 temp_b (备份)</div>
<div id="temp_b-reset-detailed" class="branch-commits">
<span class="commit-node branch-b-node">1</span>
<span class="commit-node branch-b-node">2</span>
<span class="commit-node branch-b-node">3</span>
<span class="commit-node merged-node-from-c">4</span>
<span class="commit-node merged-node-from-c">5</span>
<span class="commit-node merged-node-from-c">6</span>
<span class="commit-node merged-node-from-c">7</span>
<span class="commit-node merged-node-from-c">8</span>
<span class="commit-node branch-b-node">9</span>
<span class="commit-node branch-b-node">10</span>
</div>
</div>
</li>
<li><strong>切换回 b:</strong> <code>git checkout b</code>
<div class="branch-container">
<div class="branch-label">分支 b (当前)</div>
<div id="b3a-reset-detailed" class="branch-commits">
<span class="commit-node branch-b-node">1</span>
<span class="commit-node branch-b-node">2</span>
<span class="commit-node branch-b-node">3</span>
<span class="commit-node merged-node-from-c">4</span>
<span class="commit-node merged-node-from-c">5</span>
<span class="commit-node merged-node-from-c">6</span>
<span class="commit-node merged-node-from-c">7</span>
<span class="commit-node merged-node-from-c">8</span>
<span class="commit-node branch-b-node">9</span>
<span class="commit-node branch-b-node">10</span>
</div>
</div>
</li>
<li><strong>重置 b 到合并前:</strong> <code>git reset --hard <b_before_merge_c_hash></code> (假设 `
<b_before_merge_c_hash>` 是提交 3)
<div class="branch-container">
<div class="branch-label">分支 b (reset 后)</div>
<div id="b3b-reset-detailed" class="branch-commits">
<span class="commit-node branch-b-node">1</span>
<span class="commit-node branch-b-node">2</span>
<span class="commit-node branch-b-node">3</span>
</div>
</div>
</li>
<li><strong>Cherry-pick 提交 9 和 10:</strong>
<code>git cherry-pick <hash_of_9></code><br>
<code>git cherry-pick <hash_of_10></code><br>
<code>或者批量操作git cherry-pick <merge_commit_hash>^..<latest_b_hash></code>
<div class="branch-container">
<div class="branch-label">分支 b (cherry-pick 后)</div>
<div id="b3c-reset-detailed" class="branch-commits">
<span class="commit-node branch-b-node">1</span>
<span class="commit-node branch-b-node">2</span>
<span class="commit-node branch-b-node">3</span>
<span class="commit-node cherry-picked-commit branch-b-node">9</span>
<span class="commit-node cherry-picked-commit branch-b-node">10</span>
</div>
</div>
</li>
</ol>
<div class="branch-container">
<div class="branch-label">分支 c (不变)</div>
<div id="c3-reset-detailed" class="branch-commits">
<span class="commit-node branch-c-node">4</span>
<span class="commit-node branch-c-node">5</span>
<span class="commit-node branch-c-node">6</span>
<span class="commit-node branch-c-node">7</span>
<span class="commit-node branch-c-node">8</span>
</div>
</div>
<div class="branch-container">
<div class="branch-label">分支 a (不变)</div>
<div id="a3-reset-detailed" class="branch-commits"></div>
</div>
<p>(b 重置并 cherry-pick 完成,temp_b 作为备份)</p>
</div>
<div id="stage4-reset-graphic" class="branch-container">
<h2>阶段 4: a 合并 c 的 4, 5, 6</h2>
<div class="branch-container">
<div class="branch-label">分支 a</div>
<div id="a4-reset-graphic" class="branch-commits">
<span class="commit-node branch-a-node merged-node-from-c">4</span>
<span class="commit-node branch-a-node merged-node-from-c">5</span>
<span class="commit-node branch-a-node merged-node-from-c">6</span>
</div>
</div>
<div class="branch-container">
<div class="branch-label">分支 b (状态如阶段 3 结束)</div>
<div id="b4-reset-graphic" class="branch-commits">
<span class="commit-node branch-b-node">1</span>
<span class="commit-node branch-b-node">2</span>
<span class="commit-node branch-b-node">3</span>
<span class="commit-node cherry-picked-commit branch-b-node">9</span>
<span class="commit-node cherry-picked-commit branch-b-node">10</span>
</div>
</div>
<div class="branch-container">
<div class="branch-label">分支 c (不变)</div>
<div id="c4-reset-graphic" class="branch-commits">
<span class="commit-node branch-c-node">4</span>
<span class="commit-node branch-c-node">5</span>
<span class="commit-node branch-c-node">6</span>
<span class="commit-node branch-c-node">7</span>
<span class="commit-node branch-c-node">8</span>
</div>
</div>
<p>(a 合并了 c 的部分提交)</p>
</div>
<div id="stage5-reset-graphic" class="branch-container">
<h2>阶段 5: a 合并 b</h2>
<div class="branch-container">
<div class="branch-label">分支 a (合并 b 后)</div>
<div id="a5-reset-graphic" class="branch-commits">
<span class="commit-node branch-a-node merged-node-from-c">4</span>
<span class="commit-node branch-a-node merged-node-from-c">5</span>
<span class="commit-node branch-a-node merged-node-from-c">6</span>
<span class="commit-node branch-a-node merged-node-from-b">1</span>
<span class="commit-node branch-a-node merged-node-from-b">2</span>
<span class="commit-node branch-a-node merged-node-from-b">3</span>
<span class="commit-node branch-a-node merged-node-from-b cherry-picked-commit">9</span>
<span class="commit-node branch-a-node merged-node-from-b cherry-picked-commit">10</span>
</div>
</div>
<div class="branch-container">
<div class="branch-label">分支 b (不变)</div>
<div id="b5-reset-graphic" class="branch-commits">
<span class="commit-node branch-b-node">1</span>
<span class="commit-node branch-b-node">2</span>
<span class="commit-node branch-b-node">3</span>
<span class="commit-node cherry-picked-commit branch-b-node">9</span>
<span class="commit-node cherry-picked-commit branch-b-node">10</span>
</div>
</div>
<div class="branch-container">
<div class="branch-label">分支 c (不变)</div>
<div id="c5-reset-graphic" class="branch-commits">
<span class="commit-node branch-c-node">4</span>
<span class="commit-node branch-c-node">5</span>
<span class="commit-node branch-c-node">6</span>
<span class="commit-node branch-c-node">7</span>
<span class="commit-node branch-c-node">8</span>
</div>
</div>
<p>(a 合并了 b)</p>
</div>
<div id="stage6-reset-graphic" class="branch-container">
<h2>阶段 6: a 分支最终状态</h2>
<div class="branch-container">
<div class="branch-label final-a">分支 a (最终状态)</div>
<div id="a6-reset-graphic" class="branch-commits">
<span class="commit-node branch-a-node merged-node-from-c">4</span>
<span class="commit-node branch-a-node merged-node-from-c">5</span>
<span class="commit-node branch-a-node merged-node-from-c">6</span>
<span class="commit-node branch-a-node merged-node-from-b">1</span>
<span class="commit-node branch-a-node merged-node-from-b">2</span>
<span class="commit-node branch-a-node merged-node-from-b">3</span>
<span class="commit-node branch-a-node merged-node-from-b cherry-picked-commit">9</span>
<span class="commit-node branch-a-node merged-node-from-b cherry-picked-commit">10</span>
</div>
</div>
<div class="branch-container">
<div class="branch-label">分支 b</div>
<div id="b6-reset-graphic" class="branch-commits">
<span class="commit-node branch-b-node">1</span>
<span class="commit-node branch-b-node">2</span>
<span class="commit-node branch-b-node">3</span>
<span class="commit-node cherry-picked-commit branch-b-node">9</span>
<span class="commit-node cherry-picked-commit branch-b-node">10</span>
</div>
</div>
<div class="branch-container">
<div class="branch-label">分支 c</div>
<div id="c6-reset-graphic" class="branch-commits">
<span class="commit-node branch-c-node">4</span>
<span class="commit-node branch-c-node">5</span>
<span class="commit-node branch-c-node">6</span>
<span class="commit-node branch-c-node">7</span>
<span class="commit-node branch-c-node">8</span>
</div>
</div>
<p>(最终,a 包含了来自 c 的 4, 5, 6 和来自 b 的 1, 2, 3, 9, 10)</p>
</div>
</div>
文章标题:《Git Merge+Revert 与 Reset+Cherry-pick 对比》
本文作者: JI,XIAOYONG
发布时间: 2025/05/17 13:33:19 UTC+8
更新时间: 2025/05/17 13:33:19 UTC+8
本文地址: https://jixiaoyong.github.io/blog/posts/d7356eaa.html
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 许可协议。转载请注明出处!