git冲突相关

00 前言

某日接到新任务:优化git代码提交流程,解决冲突

给出的指导方向为:个人fork项目提交后,再合并

01 解决前提:撤销修改类

良好的参考链接

所有在合并的时候出现冲突(conflict)的时候,都可以使用git merge --abort 命令,你的合并操作就会被安全的撤销。

1.1 回退版本

~ git reset --hard HEAD ~ 注意!--hard 命令会删除所有文件本地改动,并将本地副本恢复到上次提交之后的版本(HEAD)

git reset --hard 2be18d9 此命令用于重置你当前的 HEAD 分支到一个特定旧的版本(2be18d9),也被称作 “回滚(rolling back)” 到旧的版本
注意!此命令会删除所有文件本地改动
可替换为--keep本地保留更改回退到版本之后的所有改动

重置示意图

1.2 撤销已提交的改动

除了上面的reset命令之外,还可以使用revert 撤销某个之前的提交。

但是这个命令并不是删除那个提交,相反的,它是恢复那个提交的改动,这只是看起来像是撤销而已。这个操作实际上会自动产生一个新的提交

git revert 2b504be 此处2b504be为C2的版本号,在C3处回退版本到C2,变成新版本C4

撤销改动示意图

1.3 简单退出合并

git merge --abort 来简单地退出合并,退回到commit版本

1.4 查看合并情况

可以通过git log -3 --graph --stat 通过可视化查看合并与分支关系图

02 冲突发生的情况

冲突发生的情况有以下3种

2.1 本地版本旧于远程版本(origin)

也就是远程分支比本地多出一个提交(D),(也就是本地无commit提交,但是可以有文件改动)

多出一个提交D

这时候直接通过git pull 就可以把本地master更新为远程master

更新master

此时可以用git fetch origin 更新本地的远程分支(origin/master)

然后使用git diff master origin/master 进行查看本地的master分支和本地的远程分支(origin/master)的区别

命令为:

1
2
3
git fetch origin    # 更新本地的远程分支(origin/master)
git diff master origin/master # 比对差别
git pull # 同步

以下为a/2.txt本地master的2.txt文件和远程b/2.txt的区别,多了内容+11

更新fetch和diff

2.2 本地版本和远程版本均多出一个提交,但无冲突

也就是从C节点克隆到本地库多出了E提交,但是在此之前有人在远程C节点后提交了D

无冲突版本

此时可以直接pull而不会产生冲突,并且将本地和远程库都指向最新版本D`

最新提交D`

此时如果你不更新本地库直接进行push会报以下错误提示:

错误提示

通过git status可以看到本地库的状态:Your branch is ahead of ‘origin/master’ by 1 commit.

查看status状态

命令为:

1
2
3
4
git add SOME_DOCUMENT   # 添加提交文件
git commit -m 'SOME_COMMENT' # 添加commit提交
git pull # 同步本地库到远程库
git push origin master # 推送到远程库

2.3 最关键的来了,有冲突的时候

唯一的解决办法就是查看冲突的地方,然后手工解决

如下一个场景,甲A和乙B同时维护一个README.md表,这个表写了详情,是从后面直接添加上去的

场景如下

这时候如果本地库A和本地库B都同时增加了一个4,工具D,这样两个已经提交的分支的相同文件相同位置的的不同操作进行了合并,就会产生冲突。

这里举个例子,当本地库A新增了内容4,工具D 本地库A,以及本地库B在 同一行 新增了内容4,工具D 本地库B ,这时候产生了冲突

此时进行pull 操作会报错:

1
2
3
4
5
error: Your local changes to the following files would be overwritten by merge:
README.md
Please commit your changes or stash them before you merge.
Aborting
Updating 9b5e3f2..ba0e98c

此时最好的操作就是通过diff或者status命令查看冲突,并手动解决

命令为:

1
2
3
4
5
6
7
git fetch origin    # 更新本地的远程origin分支

git add . # 添加提交文件
git commit -m 'SOME_COMMENT' # 添加commit提交
git diff master origin/master # 查看本地master分支和远程master分支的区别

# 手动解决冲突

效果图如下:

查看差别
查看差别

此时需要解决冲突

03 软件设置

推荐参考链接

那么如何解决冲突?

打开一个比较原始的文件编辑器来清理这些冲突看起来是可行的,但是这样并不简单。使用一个专门的合并工具可以使这个操作变得更容易

3.1 diffmerge

我们使用diffmerge进行可视化比对 下载地址

然后进行一些设置设置链接

1,首先将diffmerge目录加入环境变量
2,复制sgdm.exe文件复制一份,名字改成diffmerge.exe
3,输入以下代码:

1
2
3
4
5
6
7
8


git config --global diff.tool diffmerge
git config --global difftool.diffmerge.cmd 'sgdm "$LOCAL" "$REMOTE"'
git config --global merge.tool diffmerge
git config --global mergetool.diffmerge.cmd 'diffmerge --merge --result="$MERGED" "$LOCAL" "$(if test -f "$BASE"; then echo "$BASE"; else echo "$LOCAL"; fi)" "$REMOTE"'
git config --global mergetool.diffmerge.trustExitCode true
git config --global mergetool.keepBackup false

使用git mergetool即可打开diffmerge工具


坑点1:编码问题
使用默认的编码打开会出现编码问题,设置成 UTF-8 即可
参考设置链接


4 解决冲突

现在我们尝试进行冲突合并

4.1 设置冲突

首先设置冲突,在README.md的第一行改一改,让这个文件产生冲突

冲突文件

4.2 查看冲突

首先提交(commit)一下各个分支

1
2
3
4
5
6
7

git add . # 添加摁键
git commit -m 'SOME_COMMENT' # Master提交
git checkout ttt # 切换分支
git commit -m 'SOME_COMMENT' # ttt分支提交
git checkout master # 切换回master分支
git merge ttt # 合并分支

这时候就会出现冲突了,截图如下:

冲突截图

4.3 工具使用

到了这一步我们就使用git mergetool进入冲突解决界面,这里可以看到说有一个冲突

冲突解决界面

我们可以知道本地有三个界面:一个Local,一个Base和一个Remote

其中Local是当前分支(master),Remote是合并分支(ttt),而中间Base是可以修改的地方,并且是修改后最终的版本

界面对比

4.4 修改后续

我们对文件进行修改后,直接关闭窗口,会提示是否保存,点YES

退出界面

4.5 提交

我们保存后,mergetool会自动帮我们add,我们直接加个commit 然后merge就可以了

结束界面

1
2
3
git commit -m 'SOME_COMMENT'    # 跳过了add 步骤,可以直接commit
git merge ttt # 合并分支
git push origin master

然后我们查看一下是否更改成功

master分支
ttt分支

05 实际应用

上面说了这么多,实际应用应该怎么样呢?

通过新建分支进行merge到本地master,然后再push到远程origin是比较好的方法

保持本地的master分支和远程的origin分支一致是比较好的选择

解决冲突,这里解决冲突比较好的办法是修改NEW_BRANCH_NAME分支,而不是操作本地master分支

解决完冲突后,就可以把NEW_BRANCH_NAME分支合并到master分支

具体命令为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
git branch NEW_BRANCH_NAME  # 新建一个名为NEW_BRANCH_NAME的分支
git checkout NEW_BRANCH_NAME # 切换到NEW_BRANCH_NAME分支
git add . # 添加文件
git commit -m 'SOME_COMMENT' # 提交一个节点
git checkout master # 切换回master分支
git pull # 更新本地分支
git merge NEW_BRANCH_NAME # 合并分支

# 此处有可能遇到冲突

git push origin NEW_BRANCH_NAME # 方法1:推送NEW_BRANCH_NAME到远程
git push origin master # 方法2:推送master到远程


git diff NEW_BRANCH_NAME origin/msater # 查看本地NEW_BRANCH_NAME分支和远程master分支的区别

06 遇到冲突了怎么办?

方法1: 把本地的分支推送到远程后联系管理员帮助进行解决
方法2: 按照上面的方法进行自行解决


-------------本文结束  感谢您的阅读-------------