07-git合并冲突场景

1,573 阅读6分钟

1. 文件内容冲突

在 Git 中,当两个分支都修改了同一文件的同一部分时,会发生合并冲突。解决合并冲突的一般步骤如下:

  1. 查看冲突: 当你执行 git merge 或者 git pull 合并分支时,Git 会告诉你发生了冲突,它会显示哪些文件发生了冲突。例如:

    Auto-merging file.txt
    CONFLICT (content): Merge conflict in file.txt
    Automatic merge failed; fix conflicts and then commit the result.
    
  2. 编辑文件: 打开冲突的文件,你会看到类似以下的内容:

    <<<<<<< HEAD
    // 你的修改
    =======
    // 合并到当前分支的其他分支的修改
    >>>>>>> branch-name
    
    • <<<<<<< HEAD======= 之间是当前分支(合并到其中的分支)的修改。
    • =======>>>>>>> branch-name 之间是另一个分支的修改。
  3. 解决冲突: 手动选择你想要的修改,或者根据需要将两者结合,删除 Git 添加的特殊标记(<<<<<<<=======>>>>>>>)。修改后的文件应该看起来像是你期望的最终状态。

    例如,修复后可能是这样的:

    // 你的修改
    // 合并到当前分支的其他分支的修改
    
  4. 标记冲突为已解决: 保存文件后,使用 git add 命令将文件标记为已解决冲突的状态:

    git add file.txt
    
  5. 完成合并: 继续进行合并操作:

    git merge --continue
    

    或者,如果你使用 git merge 命令合并分支,可以直接提交合并结果:

    git commit -m "解决了文件 file.txt 的合并冲突"
    
  6. 确认合并: 确认合并没有其他冲突:

    git status
    

2. 指定如何处理分叉(divergent)的分支

当执行 git pull 命令时,如果本地分支和远程分支的提交历史发生了分叉,会出现 fatal: Need to specify how to reconcile divergent branches 错误。这时 Git 需要你指定如何处理分叉(divergent)的分支。

2.1 分支历史分叉场景

在多人协作或者本地和远程同时提交时,以下情况可能会导致分支历史发生分叉:

  • 多个开发者在同一个分支上工作,并提交了不同的修改,导致分支历史发生分叉。
  • 你在本地做了一些修改并提交了,同时其他人或者你在别的地方也对远程分支进行了提交。

2.2 报错信息解释

执行 git pull 命令时,会出现以下提示:

hint: You have divergent branches and need to specify how to reconcile them.
hint: You can do so by running one of the following commands sometime before
hint: your next pull:
hint:
hint:   git config pull.rebase false  # merge
hint:   git config pull.rebase true   # rebase
hint:   git config pull.ff only       # fast-forward only
hint:
hint: You can replace "git config" with "git config --global" to set a default
hint: preference for all repositories. You can also pass --rebase, --no-rebase,
hint: or --ff-only on the command line to override the configured default per
hint: invocation.
fatal: Need to specify how to reconcile divergent branches.

2.3 解决方法

要解决这个问题,你需要指定 git pull 的合并策略,这里我们选择--no-rebase策略(其它模式的使用方式也大同小异):

# 通过设置 `git pull` 的 `--no-rebase` 参数,使用传统的合并方式来处理分叉的分支历史。
git pull --no-rebase

# 或者设置默认的合并策略为 merge,并执行 git pull
git config pull.rebase false
git pull

冲突解决

如果合并过程中出现冲突,需要手动解决冲突后再提交解决方案:

# 解决冲突
git add <resolved-files>
git commit

# 继续合并操作
git pull

2.4 分支合并策略介绍

以下是一些常见的分支合并策略:

  1. git pull --no-rebase:使用传统的合并方式(merge),将远程分支的变更合并到本地分支。

  2. git pull --rebase:本地提交变基到远程分支上,重新应用本地的提交历史,使提交历史更加干净直观。

  3. git config pull.rebase false:设置默认的合并策略为 merge 合并。

  4. git config pull.rebase true:设置默认的合并策略为 rebase 变基。

  5. git config pull.ff only:设置默认的合并策略为只允许快进合并(fast-forward only)。

3. 拒绝合并不相关的历史记录

fatal: refusing to merge unrelated histories 这个错误通常发生在尝试合并两个没有共同祖先的分支或仓库时。这种情况通常出现在以下几种情况下:

  1. 全新的仓库

    • 本地仓库是全新创建的,没有任何提交历史。
    • 远程仓库是已经存在并且有提交历史的。
  2. 两个仓库的提交历史毫无关联

    • 本地仓库和远程仓库的提交历史完全不同,没有共同的提交记录。

解决方法

要解决这个问题,你可以通过下面的步骤来处理:

1. 允许合并无关的历史

如果你确信你的本地仓库和远程仓库确实没有共同的提交历史,并且希望合并它们,可以使用 --allow-unrelated-histories 选项来允许合并无关的历史:

git pull origin main --allow-unrelated-histories

或者先拉取再合并:

git fetch origin
git merge origin/main --allow-unrelated-histories

这会允许 Git 合并两个没有共同祖先的分支或仓库。

2. 合并远程分支并指定合并策略

如果 --allow-unrelated-histories 选项仍然无法解决问题,你可以尝试手动指定合并策略来解决冲突:

git pull origin main --rebase

或者使用传统的合并方式:

git pull origin main --no-rebase

3. 初始化本地仓库后再尝试合并

有时候,如果本地仓库是新创建的,可以尝试先进行一次初始化提交,然后再合并远程分支:

git init
git add .
git commit -m "Initial commit"
git pull origin main

4. 强制拉取并合并(慎用)

如果你确定要丢弃本地或者远程的提交历史,可以使用强制合并的方式:

git pull origin main --allow-unrelated-histories --force

注意:强制合并可能会导致数据丢失,因此应该谨慎使用。

5. 初始化仓库并克隆

如果你的本地仓库是全新的,并且远程仓库有提交历史,一个更好的方法是先克隆远程仓库:

git clone <remote_repository_url>

这样会自动设置好远程仓库并进行初始拉取,避免了可能的历史无关合并问题。

git系列文章

01-git常用命令汇总

02-git config介绍

03-git工作区、暂存区、版本库介绍

04-git log命令介绍

05-git关联远程仓库

06-git分支管理策略

07-git合并冲突

07-git合并冲突场景

08-git配置多个ssh密钥