Git Merge

名称

git-merge - 将两个或多个开发历史合并到一起

语法

git merge [-n] [--stat] [--no-commit] [--squash] [--[no-]edit]
        [--no-verify] [-s <strategy>] [-X <strategy-option>] [-S[<keyid>]]
        [--[no-]allow-unrelated-histories]
        [--[no-]rerere-autoupdate] [-m <msg>] [-F <file>] [<commit>…]
git merge (--continue | --abort | --quit)

将来自命名提交的更改(自其历史记录与当前分支分离以来)合并到当前分支。这个命令被git pull 用来合并来自另一个存储库的更改,并且可以手动使用将来自一个分支的更改合并到另一个分支中。

假设存在以下历史记录并且当前分支是“master”:

A---B---C topic
       /
  D---E---F---G master

然后“git merge topic”将重放在topic分支上所做的更改,因为它从master(即E)分叉,直到其当前提交(C)在master之上,并将结果记录在新提交中,同时记录两个父提交的名称和来自用户的描述更改的日志消息

A---B---C topic
     /         \
D---E---F---G---H master

第二种语法("git merge --abort")只能在合并导致冲突后运行。git merge --abort将中止合并过程并尝试重建合并前的状态。但是,如果合并开始时有未提交的更改(特别是如果这些更改在合并开始后被进一步修改),git merge --abort在某些情况下将无法重建原始(合并前)更改。因此:

警告:不鼓励使用非平凡的未提交更改运行git merge :虽然可能,但它可能会使您处于冲突情况下难以退出的状态。

第三种语法(“git merge --continue”)只能在合并导致冲突后运行。

合并场景(方式)

快进合并

当从当前分支尖端到目标分支存在线性路径时,可能会发生快进合并。与“实际”合并分支不同,Git 整合历史所需要做的就是将当前分支尖端移动(即“快进”)到目标分支尖端。这有效地结合了历史,因为从目标分支可到达的所有提交现在都可以通过当前分支获得。例如,一些特征的快进合并main 如下所示:

git merge request 命令 git merge -i_历史记录

三路合并

但是,如果分支已经发散,则无法进行快进合并。当目标分支没有线性路径时,Git 只能通过 3 路合并将它们组合起来。3 路合并使用专用提交将两个历史记录联系在一起。命名来自 Git 使用三个提交来生成合并提交的事实:两个分支提示和它们的共同祖先。

git merge request 命令 git merge -i_git_02

演示

## 从master新建两个分支用来测试
git checkout -b topic2 && echo '测试快进合并' >test1.txt  && git  commit -am '测试快进合并'  && git checkout  master
git checkout -b topic3  && echo '测试三路合并' >test1.txt  && git  commit -am '测试三路合并'  && git checkout  master
## 查看当前提交历史,topic2,topic3都比master分支多了一个提交
* cde1c6ab6a8a3a0d1f6a7b868f907ab503bcbf24 (topic3) 测试三路合并
| * d29dc13bd2caa4f339476ecd5be80dc216c79d08 (topic2) 测试快进合并
|/
* 601d2c6ea43a57dc3eaa57b4ee2de3fd65278db7 (HEAD -> master) G
* 1962fcbe9ba5ac266c586d76b960a295d8f73e75 F
* 409ece9f3350c5e8b99683b801fd93737ec99c2c E
* 9987861614208f3dcbc6ef6047ed30661af508d1 D

##  此时将topic2分支合并到master时就会使用Fast-forward方式,
$ git  merge topic2 
Updating 601d2c6..d29dc13
Fast-forward
 test1.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

$ git log master topic2 topic3   --graph   --pretty=oneline 
* cde1c6ab6a8a3a0d1f6a7b868f907ab503bcbf24 (topic3) 测试三路合并
| * d29dc13bd2caa4f339476ecd5be80dc216c79d08 (HEAD -> master, topic2) 测试快进合并
|/
* 601d2c6ea43a57dc3eaa57b4ee2de3fd65278db7 G
* 1962fcbe9ba5ac266c586d76b960a295d8f73e75 F
* 409ece9f3350c5e8b99683b801fd93737ec99c2c E

##   三路合并测试 
$  git merge topic3
Auto-merging test1.txt
CONFLICT (content): Merge conflict in test1.txt
Automatic merge failed; fix conflicts and then commit the result.
## 查看文件内容
$ cat test1.txt 
<<<<<<< HEAD
测试快进合并
=======
测试三路合并
>>>>>>> topic3

解决冲突

## 此时看仓库状态 发现有没有处理的冲突
user@NAME MINGW64 /d/VSCode/testUpdateIndex (master|MERGING)
$ git status 
On branch master
You have unmerged paths.
  (fix conflicts and run "git commit")        
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
        both modified:   test1.txt
##  根据提示,使用git add <file> 来标记文件已经解决冲突(如果你真的已经手动解决了冲突的话)
$ git add test1.txt 
user@NAME MINGW64 /d/VSCode/testUpdateIndex (master|MERGING)
$ git status 
On branch master
All conflicts fixed but you are still merging.
  (use "git commit" to conclude merge)        

Changes to be committed:
        modified:   test1.txt

冲突的呈现

当 Git 在合并过程中遇到冲突时,它会编辑受影响文件的内容,并使用视觉指示器标记冲突内容的两侧。这些视觉标记是:<<<<<<<、======= 和 >>>>>>>。在合并期间在项目中搜索这些指标以找到需要解决冲突的地方很有帮助。

<<<<<<< HEAD
测试快进合并
=======
测试三路合并
>>>>>>> topic3

一般来说,标记之前的内容=======是接收分支(master),之后的部分是合并分支(topic3)。