
Git 分支与冲突解决探究
Git 分支与冲突解决探究
有一天,你忘记在修改代码前更新代码,直接在你的 dev_zxlm 更新着你所在业务模块的代码,修改完后按流程在自己的分支上 git add + git commit。
殊不知在你更新代码之前,有另外一个人也在 dev_sb 分支修改了同一份文件同一处的代码,并完成了同样的操作,然后将他的代码push上去而且合并到主分支master。
现在,你可能会做出两种操作:
将自己的分支推上去,然后在仓库管理平台进行 Pull Request 提出合并请求;
先将自己的代码更新到 master 分支,再尝试上传;
但是哪种操作都会让你直冒冷汗:我是谁我在哪,我在干什么?下一秒项目负责人和甲方是不是就得给我发消息了……
本文主要探究相关冲突问题的复现和解决方案。
Git 基础命令回顾
git init
初始化仓库git clone
克隆仓库git add
文件更改添加到暂存区git commit
提交暂存区更改的仓库git status
查看工作目录与暂存区文件状态git log
查看提交历史git branch <分支名>
创建新分支git checkout <分支名>
切换到指定分支git merge <要合并的分支名>
将指定分支的更改合并到当前分支git pull
从远程仓库获取更改git push
推送更改到远程仓库
Git 分支相关命令
查看操作单一分支 git branch
查看当前分支:
git branch
查看远程分支:
git branch -r
查看所有分支:
git branch -a
查看分支最后提交:
git branch -v
创建分支:
git branch <分支名>
删除分支:
git branch -d <分支名>
重命名分支:
git branch -m <旧分支名> <新分支名>
切换分支 git checkout
切换分支:
git checkout <分支名>
创建并切换到新分支:
git checkout -b <分支名>
合并分支
git merge <分支名>
:将<分支名>分支合并到当前分支。将两个分支的历史合并在一起,并创建一个新的合并提交。这个合并提交有两个父提交,代表了被合并的分支的历史。git rebase <分支名>
:将当前分支的提交移到<分支名>分支的顶端,然后将<分支名>分支的提交应用到当前分支。它会重写提交历史,使得提交历史更加线性。
两者的区别:
假设有两个分支:feature
分支和 main
分支。
初始状态如下:
main: A---B---C
\
feature: D---E
使用
git merge
:非线性提交历史
运行 git checkout main; git merge feature
:
main: A---B---C---F
\ /
feature: D---E
在这里,feature
分支的提交 D
和 E
被合并到 main
分支上,形成了新的合并提交 F
。这样的提交历史在合并点会有一个分叉,看起来不太线性。
使用
git rebase
:线性提交历史
运行 git checkout feature; git rebase main
:
main: A---B---C
\
feature: D'---E'
在这里,feature
分支的提交 D
和 E
被移到了 main
分支的最新提交 C
的顶端,并创建了新的提交 D'
和 E'
。这样的提交历史更加线性。
Pull Request :如果你使用的是基于 GitHub、GitLab 或 Bitbucket 等平台的协作开发,通常会使用 Pull Request(PR)来进行分支合并。你可以在平台上创建一个 PR,然后选择要合并的分支,进行必要的审核和讨论后,再进行合并操作。
推送拉取分支
git在本地会保存两个版本的仓库,分为本地仓库和远程仓库。
1、本地仓库就是我们平时 add、commit 的那个仓库。
2、远程仓库可以用 git remote -v 查看(这里的远程仓库是保存在本地的远程仓库,等同于另一个版本,不是线上的远程仓库)。
推送分支
git push <远程仓库> <本地分支>
:如git push origin master
会将本地 master 分支推送到线上远程 origin 仓库的 master 分支。推送分支
git push <远程仓库> <本地分支>:<远程分支>
:如git push origin master1:master2
会将本地 master1 分支推送到远程 origin 仓库的 master2 分支拉取分支
git fetch <远程仓库> <远程分支>
:如git fetch origin master
会将远程 origin 仓库的 master 分支更新到本地远程仓库的 origin/master 分支。之后需要手动进行合并操作git merge origin/master
合并到当前分支。拉取分支
git fetch <远程仓库> <远程分支>:<本地分支>
:如git fetch origin master1:master2
会将远程 origin 仓库的 master 分支更新到本地远程仓库的 origin/master1 分支,再将其合并到本地 master2 分支。若不存在master2分支,则新建master2分支。
相当于
git fetch origin master1git merge origin/master1 master2
两个命令
拉取分支
git pull <远程仓库> <远程分支>
相当于
git fetch origin mastergit merge origin/master
注意是合并到当前分支
命令行处理冲突
单一用户合并分支冲突
PS D:\Users\Donnie\Desktop\gitTest> git branch
local_1
local_2
* master
PS D:\Users\Donnie\Desktop\gitTest> git checkout local_1
Switched to branch 'local_1'
# 在这里编辑 README.en.md
PS D:\Users\Donnie\Desktop\gitTest> git add .\README.en.md
PS D:\Users\Donnie\Desktop\gitTest> git commit -m "local1提交"
[local_1 c669b56] local1提交
1 file changed, 1 insertion(+), 1 deletion(-)
PS D:\Users\Donnie\Desktop\gitTest> git checkout local_2
Switched to branch 'local_2'
# 在这里编辑 README.en.md
PS D:\Users\Donnie\Desktop\gitTest> git add .\README.en.md
PS D:\Users\Donnie\Desktop\gitTest> git commit -m "local2提交"
[local_2 870f478] local2提交
1 file changed, 1 insertion(+), 1 deletion(-)
PS D:\Users\Donnie\Desktop\gitTest> git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
PS D:\Users\Donnie\Desktop\gitTest> git merge local_1
Updating b414149..c669b56
Fast-forward
README.en.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
PS D:\Users\Donnie\Desktop\gitTest> git merge local_2
Auto-merging README.en.md
CONFLICT (content): Merge conflict in README.en.md
Automatic merge failed; fix conflicts and then commit the result.
此时,Readme.en.md的冲突处被git修改如下:
<<<<<<< HEAD
Git 分支与冲突解决探究local1
=======
Git 分支与冲突解决探究local2
>>>>>>> local_2
解决办法:在master分支上修改冲突后,再进行git add和git commit;
如果希望将这些更改同步到其他开发分支(例如 dev
分支)上,以保持一致性,可以切换到 dev 分支后再进行 git merge master
或 git rebase master
多用户拉取同一分支冲突
首先我在码云Gitee上新建一个代码仓库;
然后在两台机器上分别使用 git config 配置不同的用户名和邮箱;
在两台机器上分别git clone 这个仓库;
两台机器同一分支(master分支)修改同一文件同一处代码,并且git add git commit;
其中一台机器git push上去,另一台机器git fetch下来,这时再继续git merge origin/master时,会弹出冲突;
在这台机器上解决冲突,之后git add git commit git push;
最后在另外一台机器上git pull,将起冲突的代码更新。
多用户管理多分支冲突
回顾一下开头的情景,我们进行复现:
在local机器上,我在local_1分支对文件进行了修改,先合并到了master分支然后push了上去。
在server机器上,我在dev_server分支上对文件同一处进行了修改,并且已经进行了提交。
情况1. 将自己的分支推上去,然后在仓库管理平台进行 Pull Request 提出合并请求:
git push origin dev_server
Gitee 提示无法自动合并,只能手动合并。
git checkout master
git pull https://gitee.com/donniezfr/gitTest.git dev_server # 出现冲突 解决冲突
git push origin master
情况2.先将自己的代码更新到 master 分支,再尝试上传;
[root@iZ2zeazxy4xlxrrwv9g7qwZ gitTest]# git checkout master
Switched to branch 'master'
Your branch is behind 'origin/master' by 3 commits, and can be fast-forwarded.
(use "git pull" to update your local branch)
[root@iZ2zeazxy4xlxrrwv9g7qwZ gitTest]# git merge dev_server
Updating b414149..41e5200
Fast-forward
README.en.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
上传时,由于在 git push 之前没有进行更新,会出现如下错误提示,需要git pull:
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'https://gitee.com/donniezfr/gitTest.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
那么接下来就尝试 git fetch
git merge
,然后发现冲突,再解决冲突之后再进行上传。
IDEA Git插件
IDEA 的 Git 模块大概是这个样子:
点击左侧蓝色小按钮会进行
git fetch
即拉取远程所有分支。
除此之外,还可以在这里管理Git各个分支:
代码更新
先 Update Project 实现 git pull
;然后 git checkout
到自己的分支,将 master 分支 merge 到自己的分支;或者在自己的分支上 rebase onto master分支:
或者在自己的分支上 rebase onto master 分支。
代码冲突解决
在 merge 或 rebase 时,出现代码冲突会弹出一下窗口:
如果继续点击 Merge,会弹出来代码修改窗口:
窗口分左、中、右三部分,左、右是要合并的代码,中间是合并结果。
左右两部分为只读内容,中间部分是可以修改的,修改好后点击Apply即可。
可以通过点击 “×”(Ignore) 和 箭头(Accept)来实现快捷更改(提示:可以尝试按住Ctrl键);