在日常的开发工作中,经常需要将分支上的代码合并到主分支。无论是代码评审通过后的合并,还是在开发过程中同步主分支的更新,合并代码都是必不可少的操作。两种常见的合并方式是 <font style="color:rgb(0, 128, 255);">merge</font><font style="color:rgb(0, 128, 255);">rebase</font>,它们各有优缺点,选择哪种方式需要根据具体情况来决定。

Merge 和 Rebase 的区别

Merge

<font style="color:rgb(0, 128, 255);">merge</font> 是将两个分支的历史记录合并在一起,产生一个新的合并提交(merge commit)。它的好处是保留了完整的历史记录,所有的提交顺序和分支点都清晰可见。

示例:
  1. # 切换到目标分支
  2. git checkout main
  3. # 合并 feature 分支到 main
  4. git merge feature

合并后的历史记录可能如下所示:

  1. * d3adb33 (HEAD -> main) Merge branch 'feature' into 'main'
  2. |\
  3. | * 1a2b3c4 (feature) Feature commit 2
  4. | * 5d6e7f8 Feature commit 1
  5. * | 8a9b0c1 Main commit 2
  6. * | 2d3e4f5 Main commit 1

Rebase

<font style="color:rgb(0, 128, 255);">rebase</font> 是将一个分支的所有提交移到另一个分支的最前面,重写提交历史。这样可以使历史记录更简洁,线性化的提交历史看起来更干净。

示例:
  1. # 切换到 feature 分支
  2. git checkout feature
  3. # 变基到 main 分支
  4. git rebase main

变基后的历史记录可能如下所示:

  1. * 1a2b3c4 (HEAD -> feature) Feature commit 2
  2. * 5d6e7f8 Feature commit 1
  3. * 8a9b0c1 (main) Main commit 2
  4. * 2d3e4f5 Main commit 1

何时使用 Merge

1、保留完整的历史记录

当需要保留分支开发的完整历史记录时,使用 <font style="color:rgb(0, 128, 255);">merge</font> 是一个不错的选择。它可以清晰地显示出哪些工作是在分支上进行的,哪些是在主分支上进行的。

2、解决复杂冲突

当两个分支之间有复杂冲突时,<font style="color:rgb(0, 128, 255);">merge</font> 可以更容易地解决冲突,因为它会创建一个新的合并提交,在合并过程中进行冲突解决。

何时使用 Rebase

1、保持历史记录整洁

如果希望提交历史看起来更干净、更线性,<font style="color:rgb(0, 128, 255);">rebase</font> 是更好的选择。它可以避免多余的合并提交,使历史记录更易读。

2、在个人分支上工作

在个人分支上工作时,可以频繁使用 <font style="color:rgb(0, 128, 255);">rebase</font> 来保持分支与主分支同步,而不引入多余的合并提交。

具体示例:解决冲突

假设有以下情况:
  • 主分支 <font style="color:rgb(0, 128, 255);">main</font> 上有两个提交
  • 功能分支 <font style="color:rgb(0, 128, 255);">feature</font> 上有两个提交

使用 Merge 解决冲突

  1. 切换到主分支并合并功能分支:
  1. git checkout main
  2. git merge feature
  1. 如果存在冲突,Git 会提示你手动解决冲突。打开冲突文件,进行手动修改,然后标记冲突已解决:
  1. # 编辑冲突文件并解决冲突
  2. nano conflicted_file.java
  3. # 标记冲突已解决
  4. git add conflicted_file.java
  1. 完成合并:
  1. git commit -m "Resolved conflicts and merged feature branch"

使用 Rebase 解决冲突

  1. 切换到功能分支并进行变基:
  1. git checkout feature
  2. git rebase main
  1. 如果存在冲突,Git 会暂停变基并提示你手动解决冲突。打开冲突文件,进行手动修改,然后标记冲突已解决:
  1. # 编辑冲突文件并解决冲突
  2. nano conflicted_file.java
  3. # 标记冲突已解决
  4. git add conflicted_file.java
  1. 继续变基:
  1. git rebase --continue

代码示例:实现简单的加法函数并合并冲突

假设有以下代码文件 <font style="color:rgb(0, 128, 255);">math_utils.java</font> 主分支上的代码:
  1. public class MathUtils {
  2. public static int add(int a, int b) {
  3. return a + b;
  4. }
  5. }
功能分支上的代码:
  1. public class MathUtils {
  2. // 新增方法:加法并打印结果
  3. public static int addAndPrint(int a, int b) {
  4. int result = a + b;
  5. System.out.println("Result: " + result);
  6. return result;
  7. }
  8. }
合并过程中可能会产生冲突,因为两个分支都修改了同一个文件。使用 <font style="color:rgb(0, 128, 255);">merge</font><font style="color:rgb(0, 128, 255);">rebase</font> 解决冲突的方法类似,以下是使用 <font style="color:rgb(0, 128, 255);">merge</font> 解决冲突的步骤:
  1. 切换到主分支并合并功能分支:
  1. git checkout main
  2. git merge feature
  1. 解决冲突:
  1. public class MathUtils {
  2. public static int add(int a, int b) {
  3. return a + b;
  4. }
  5. // 新增方法:加法并打印结果
  6. public static int addAndPrint(int a, int b) {
  7. int result = a + b;
  8. System.out.println("Result: " + result);
  9. return result;
  10. }
  11. }
  1. 标记冲突已解决并完成合并:
  1. git add math_utils.java
  2. git commit -m "Resolved conflicts and merged feature branch"
总之,选择 <font style="color:rgb(0, 128, 255);">merge</font> 还是 <font style="color:rgb(0, 128, 255);">rebase</font> 取决于具体的情境和需求。如果需要保留完整的历史记录并且更容易解决复杂冲突,<font style="color:rgb(0, 128, 255);">merge</font> 是更好的选择;如果希望历史记录更整洁且在线性开发过程中工作,<font style="color:rgb(0, 128, 255);">rebase</font> 则更合适。每种方法都有其优点和适用场景,熟练掌握并根据实际情况选择最合适的方法,是高效进行代码合并的关键。