Git基本操作- 命令 merge - 分支合并、处理冲突

官方帮助文档

$ git help merge
GIT-MERGE(1)                         Git Manual                         GIT-MERGE(1)
NAME
       git-merge - Join two or more development histories together

SYNOPSIS
       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)

DESCRIPTION
       Incorporates changes from the named commits (since the time their histories
       diverged from the current branch) into the current branch. This command is
       used by git pull to incorporate changes from another repository and can be
       used by hand to merge changes from one branch into another.

       Assume the following history exists and the current branch is "master":

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

       Then "git merge topic" will replay the changes made on the topic branch since
       it diverged from master (i.e., E) until its current commit (C) on top of
       master, and record the result in a new commit along with the names of the two
       parent commits and a log message from the user describing the changes.

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

       The second syntax ("git merge --abort") can only be run after the merge has
       resulted in conflicts. git merge --abort will abort the merge process and try
       to reconstruct the pre-merge state. However, if there were uncommitted
       changes when the merge started (and especially if those changes were further
       modified after the merge was started), git merge --abort will in some cases
       be unable to reconstruct the original (pre-merge) changes. Therefore:

       Warning: Running git merge with non-trivial uncommitted changes is
       discouraged: while possible, it may leave you in a state that is hard to back
       out of in the case of a conflict.

       The third syntax ("git merge --continue") can only be run after the merge has
       resulted in conflicts.

OPTIONS
       --commit, --no-commit

Git Merge —— Fast Forward ( 快进到某个分支)

  • master不变,新创建一个分支bugfix,在bugfix分支上修改代码提交commit,完后在master分支上,把master分支上指向bugfix上最新的commit对象,
$ cat .git/HEAD # 我们现在head指向master分支
ref: refs/heads/master
$ git log
commit ef1ab1732d63429bee8a8e8d50adf315eca3a74b (HEAD -> master) # HEAD 指向master
...
$ git checkout -b fix-xxx
切换到一个新分支 'fix-xxx'
$ git branch
* fix-xxx
  master
$ git log
commit ef1ab1732d63429bee8a8e8d50adf315eca3a74b (HEAD -> fix-xxx, master)
$ vim hello.txt
$ git add hello.txt
$ git commit -m 'fix'
[fix-xxx 351ed28] fix
 1 file changed, 1 insertion(+), 1 deletion(-)
$  git log
commit 351ed2832ff8d44d3a9bcd459d2d3c750606637a (HEAD -> fix-xxx)
Author: xxx <xxx.com>
Date:   xxx

    fix
commit ef1ab1732d63429bee8a8e8d50adf315eca3a74b (master)
...
$  git checkout master
切换到分支 'master'
$ git log
commit ef1ab1732d63429bee8a8e8d50adf315eca3a74b (HEAD -> master)
...
$  git merge fix-xxx
Updating ef1ab17..351ed28 # 指针从我们commit的ef1ab17——>351ed28
Fast-forward # 场景
 hello.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
$ git log
commit 351ed2832ff8d44d3a9bcd459d2d3c750606637a (HEAD -> master, fix-xxx)
Author: xxx <xxx.com>
Date:   xxx

    fix
commit ef1ab1732d63429bee8a8e8d50adf315eca3a74b (HEAD -> master)
...
$  tree .git
.git
├── COMMIT_EDITMSG
├── HEAD
├── ORIG_HEAD # merge 之后多出来的,
├── config
├── description
├── hooks
├── index
├── info
│   ├── exclude
│   └── refs
├── logs
│   ├── HEAD
│   └── refs
│       └── heads
│           ├── fix-xxx
│           └── master
├── objects
│   ├── 35
│   │   └── 1ed2832ff8d44d3a9bcd459d2d3c750606637a
│   ├── 56
│   │   └── 00391ce473902576cb284ecb48410ea7c9f308
│   ├── 91
│   │   └── b84d9a6b5b007824972f6f8478e2a2eb662b54
│   ├── info
│   │   ├── commit-graph
│   │   └── packs
│   └── pack
│       ├── pack-0c8c5e08719b5d74e9c03714a71555a9bc1c9632.idx
│       └── pack-0c8c5e08719b5d74e9c03714a71555a9bc1c9632.pack
├── packed-refs
└── refs
    ├── heads
    │   ├── fix-xxx
    │   └── master
    └── tags
$ cat .git/HEAD
ref: refs/heads/master
$ cat .git/ORIG_HEAD
ef1ab1732d63429bee8a8e8d50adf315eca3a74b # merge 之前master指向最新的commit对象
$ cat .git/refs/heads/master
351ed2832ff8d44d3a9bcd459d2d3c750606637a # merge 之后master指向的commit对象
我们可以在这时进行回滚操作
  • Git认为Fast-forward 这种场景很危险,我们需要有回滚操作,也就是撤回当上一个版本

$ git reset ORIG_HEA
重置后取消暂存的变更:
M	hello.txt
$ git log
 # 重新指向 merge 之前指向的commit对象
commit ef1ab1732d63429bee8a8e8d50adf315eca3a74b (HEAD -> master)
$  git status
位于分支 master
尚未暂存以备提交的变更:
  (使用 "git add <文件>..." 更新要提交的内容)
  (使用 "git restore <文件>..." 丢弃工作区的改动)
	修改:     hello.txt

修改尚未加入提交(使用 "git add" 和/或 "git commit -a"# 我们commit回滚到merge之前的master状态,更改会放到工作区中


# 扩展 https://www.cnblogs.com/lfxiao/p/9378763.html

Git Merge —— 3 Way merge

在我们merge之前,已经有人merge过其他分支
修改一样的文件,产生冲突
 git checkout -b fix-xxx2
切换到一个新分支 'fix-xxx2'
$ vim hello.txt
$ git add hello.txt
$ git commit -m 'fix 2'
[fix-xxx2 79c4f6a] fix 2
 1 file changed, 1 insertion(+)
$ git log
commit 79c4f6aede40a7042add2f89fcd80d260041c0a5 (HEAD -> fix-xxx2)
Author: hh <hh@123.com>
Date:   Sun Mar 28 14:25:38 2021 +0800

    fix 2
    
$ tree .git/objects
.git/objects
├── 17
│   └── 8724d997ef9fc1141e797171d682553136edfc
├── 41
│   └── 1b486eb6afe280fb7e26ed1b00b39c11af4462
├── 61
│   └── 5640b3bdc533cc5180a00ebfe8675115aa11ac
├── 79
│   └── c4f6aede40a7042add2f89fcd80d260041c0a5
├── b4
│   └── bfc685e634816f6bad0b51bac882173bc8e54a
├── e4
│   └── 582fa0fc21613231e5bb8bf284a7db9df0937e
├── info
│   ├── commit-graph
│   └── packs
└── pack
    ├── pack-3c257c1a1c5cddbd7adcbbcd0b2eae95178d8e6b.idx
    └── pack-3c257c1a1c5cddbd7adcbbcd0b2eae95178d8e6b.pack

8 directories, 10 files
$ git checkout master
切换到分支 'master'
$ git merge fix-xxx2
更新 ef1ab17..79c4f6a
Fast-forward
 hello.txt | 1 +
 1 file changed, 1 insertion(+)
$ git merge fix-xxx
自动合并 hello.txt
冲突(内容):合并冲突于 hello.txt
自动合并失败,修正冲突然后提交修正的结果。
$ vim hello.txt #处理我们产生的冲突代码
hello git
<<<<<<< HEAD
fix bug
fix bug
=======
fix
>>>>>>> fix-xxx
$ git status
位于分支 master
您有尚未合并的路径。
  (解决冲突并运行 "git commit")
  (使用 "git merge --abort" 终止合并)

未合并的路径:
  (使用 "git add <文件>..." 标记解决方案)
	双方修改:   hello.txt

修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
$ git add hello.txt
$ git status
位于分支 master
所有冲突已解决但您仍处于合并中。
  (使用 "git commit" 结束合并)

要提交的变更:
	修改:     hello.txt

$ git commit -m 'fix merge bug-fix-xxx'
[master c21d1eb] fix merge bug-fix-xxx
$ git log
commit c21d1eb5cba29552302382495fb9dbf9bae66f47 (HEAD -> master) # 处理完冲突后的产生的分支
Merge: 79c4f6a 351ed28
Author: XXX
Date:   XXX

    fix merge bug-fix-xxx

commit 79c4f6aede40a7042add2f89fcd80d260041c0a5 (fix-xxx2) # fix-xxx2没有变化
Author: XXX
Date:   XXX

    fix 2

commit 351ed2832ff8d44d3a9bcd459d2d3c750606637a (fix-xxx) # fix-xxx
Author: XXX
Date:   XXX

    fix
    
commit c21d1eb5cba29552302382495fb9dbf9bae66f47 # merge 之前master最新的commit
...
$ tree .git/objects
.git/objects
├── 17
│   └── 8724d997ef9fc1141e797171d682553136edfc
├── 41
│   └── 1b486eb6afe280fb7e26ed1b00b39c11af4462
├── 61
│   └── 5640b3bdc533cc5180a00ebfe8675115aa11ac
├── 79
│   └── c4f6aede40a7042add2f89fcd80d260041c0a5
├── b4
│   └── bfc685e634816f6bad0b51bac882173bc8e54a
├── c2 # 处理merge冲突后的产生的对象
│   ├── 1d1eb5cba29552302382495fb9dbf9bae66f47 # commit对象
│   └── 7e40a839d857c095dd5e3bda0aaf2a61224cb5 # tree对象
├── c7
│   └── 037c0fda18887223fc27048d5491bd4627471a
├── e4
│   └── 582fa0fc21613231e5bb8bf284a7db9df0937e
├── f9
│   └── 9c1c17a0c67bd6df61ed7fae3e7842b8723105
├── info
│   ├── commit-graph
│   └── packs
└── pack
    ├── pack-3c257c1a1c5cddbd7adcbbcd0b2eae95178d8e6b.idx
    └── pack-3c257c1a1c5cddbd7adcbbcd0b2eae95178d8e6b.pack

11 directories, 14 files
$  git cat-file -t  c21d1e
commit
git cat-file -p c21d1e
tree c27e40a839d857c095dd5e3bda0aaf2a61224cb5
parent 79c4f6aede40a7042add2f89fcd80d260041c0a5 # merge 之前master最新的commit对象
parent 351ed2832ff8d44d3a9bcd459d2d3c750606637a # 所merge的commit对象
author hh <hh@123.com> 1616913093 +0800
committer hh <hh@123.com> 1616913093 +0800

fix merge bug-fix-xxx
$  git cat-file -t  c27e40
tree
$ git cat-file -p c27e40
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391	empty_file.txt
040000 tree c2ed92794640553084dfab1d35c0f468342e02a6	folder1
100644 blob c7037c0fda18887223fc27048d5491bd4627471a	hello.txt
100644 blob 0f7b21a50d13eb924a712a1cb763dca8ef69f6f3	hello_copy.txt
修改不一样的文件,不会产生冲突
#
git checkout fix-xxx
切换到分支 'fix-xxx'
$ vim fix-xxx.txt
$ git add fix-xxx.txt
$ git commit -m 'add fix-xxx'
[fix-xxx 8814570] add fix-xxx
 1 file changed, 1 insertion(+)
 create mode 100644 fix-xxx.txt
$ git checkout master
切换到分支 'master'
$ git checkout fix-xxx2
切换到分支 'fix-xxx2'
$ vim fix-xxx2.txt
$ git add fix-xxx2.txt
$ git status
位于分支 fix-xxx2
要提交的变更:
  (使用 "git restore --staged <文件>..." 以取消暂存)
	新文件:   fix-xxx2.txt

$ git commit -m 'add fix-xxx2'
[fix-xxx2 6048e4f] add fix-xxx2
 1 file changed, 1 insertion(+)
 create mode 100644 fix-xxx2.txt
$ git checkout master
切换到分支 'master'
$ git merge fix-xxx2
# 跳出一个merge commit 的vim界面,我们填写我们的commit message,保存
Merge made by the 'recursive' strategy.
 fix-xxx2.txt | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 fix-xxx2.txt
$ git merge fix-xxx
Merge made by the 'recursive' strategy.
 fix-xxx.txt | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 fix-xxx.txt
$ git log
commit daeef85f655ca2a2f240839edfbbc858b32bce0b (HEAD -> master) # merge commit 
Merge: ac68fc7 8814570
Author: hh <hh@123.com>
Date:   Sun Mar 28 14:49:00 2021 +0800

    Merge branch 'fix-xxx' into master
    fix bug fix xxx

commit ac68fc7a6f26ec18585249989a5023a940bc9974 # merge commit 
Merge: c21d1eb 6048e4f
Author: hh <hh@123.com>
Date:   Sun Mar 28 14:48:42 2021 +0800

    Merge branch 'fix-xxx2' into master

commit 6048e4fc794e7df0192939309d8be0d47ca3f71a (fix-xxx2)
Author: hh <hh@123.com>
Date:   Sun Mar 28 14:48:13 2021 +0800

    add fix-xxx2

commit 88145707b4619e8ada9308178bec3cd54b18f290 (fix-xxx)
Author: hh <hh@123.com>
Date:   Sun Mar 28 14:46:46 2021 +0800

    add fix-xxx

commit c21d1eb5cba29552302382495fb9dbf9bae66f47
Merge: 79c4f6a 351ed28
Author: hh <hh@123.com>
Date:   Sun Mar 28 14:31:33 2021 +0800

    fix merge bug-fix-xxx
# 
tree .git/objects
.git/objects
├── 17
│   └── 8724d997ef9fc1141e797171d682553136edfc
├── 38
│   └── da773d597dd7a0c0f829ebc9435913347bb4ba
├── 41
│   └── 1b486eb6afe280fb7e26ed1b00b39c11af4462
├── 60
│   └── 48e4fc794e7df0192939309d8be0d47ca3f71a
├── 61
│   └── 5640b3bdc533cc5180a00ebfe8675115aa11ac
├── 68
│   └── 0ee446d66eab3822ad022908fc03a08f3979de
├── 79
│   └── c4f6aede40a7042add2f89fcd80d260041c0a5
├── 80
│   └── 2ad127fc8baeb11b1a78fd939b5c1fa20636a1
├── 88
│   └── 145707b4619e8ada9308178bec3cd54b18f290
├── ac
│   ├── 1fb501cc308e056a74e3ede5e30c48ac97d2b6
│   └── 68fc7a6f26ec18585249989a5023a940bc9974
├── b4
│   └── bfc685e634816f6bad0b51bac882173bc8e54a
├── c0
│   └── 9cc07facbad3ad88b6384e0f9529ac2a429f30
├── c2
│   ├── 1d1eb5cba29552302382495fb9dbf9bae66f47
│   └── 7e40a839d857c095dd5e3bda0aaf2a61224cb5
├── c7
│   └── 037c0fda18887223fc27048d5491bd4627471a
├── c8
│   └── 1e07cb60fa336b16995dadcd13e50f9c7f9dd4
├── da
│   └── eef85f655ca2a2f240839edfbbc858b32bce0b
├── e4
│   └── 582fa0fc21613231e5bb8bf284a7db9df0937e
├── f9
│   └── 9c1c17a0c67bd6df61ed7fae3e7842b8723105
├── info
│   ├── commit-graph
│   └── packs
└── pack
    ├── pack-3c257c1a1c5cddbd7adcbbcd0b2eae95178d8e6b.idx
    └── pack-3c257c1a1c5cddbd7adcbbcd0b2eae95178d8e6b.pack

20 directories, 24 files

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值