4 Git多人单分支集成协作时的常见场景

场景:模拟两个人维护同一个Git分支。

先在Github仓库里基于 master 创建一个新的分支 feature/add_git_cmds ,点击Create branch即可:

创建成功后,回到本地,在本地拉取两个库,模拟两个人开发。

别忘了给两个人设置不同的user~

我们先看一下Git仓库的全局配置( --global ):

我们让git_learning_A使用默认的全局用户配置,给git_learning_B设置局部用户配置( --local ,优先级高于全局配置):

(配置可参考1 Git基础--03|使用git之前需要做的最小配置

最后在两个本地仓库里,都基于远端feature/add_git_cmds 分支创建相关联的本地分支。

命令: git checkout -b feature/add_git_cmds origin/feature/add_git_cmds ,该命令会基于后面的远端分支创建名为前者的本地分支,跟踪远端分支,并切换到新建的分支上来。

在两个本地仓库上都进行同样的操作。

至此,模拟了两个人同一仓库的同一分支上开发的场景,接下来针对5种情况一一进行试验🧪吧!

34 | 不同人修改了不同文件如何处理?

结论先行:直接merge即可。

git_learning_A:修改readme.md文件,并推送到远端。

git push 很顺利。

查看远端仓库:

查看提交记录的作者,对应git_learning_A使用的全局用户配置:


git_learning_B:修改另一个文件xxx/css.x,推送之前需要先拉取,再尝试推送。

先修改文件,假设直接推送,看看会发生什么?

前面的步骤和git_learning_A的类似,但是在 git push 时发生了意外,是不是似曾相识?报错和上一章中提到的一模一样:3 Git与GitHub的简单同步--33|把本地仓库同步到GitHub

❌: git push -f 强行推送。

✅:先拉取,再合并,再推送。

git fetch

可以看到最新commit的hash值从d7d648a更新到了192a3b3。

在分支说明上发现当前分支和远端分支的状态为:ahead 1(本地有更新我没有推送到远端), behind 1(远端有更新我没有合入到本地),那么先进行合入。

git merge origin/feature/add_git_cmds

执行后会弹出commit信息的编辑,默认即可,或适当添加说明。

:wq 保存退出,可以看到merge成功以及修改的记录。

蓝线可以看到目前ahead 2,也就本地多了两个commit,还没有推送到远端;

红框即ahead的2条commit记录。

这时候查看本地的readme.md和xxx/css.x文件,都是修改后的样子,接下来直接push即可。

git push

推送成功!不同人在不同文件上进行协同办公还是很方便的,所以协同办公时以这种方式进行是不是很高效呢?再看看其他情况吧~

35 | 不同人修改了同文件的不同区域如何处理?

结论先行:直接merge即可。

⚠️:先创造有不同区域的环境,在任一仓库的readme.md文件中添加多行,再推送,两个仓库保持同步。readme.md文件修改如下:

因为上一节中的文件都是1行,无法做到修改不同区域。


git_learning_A:修改readme.md的第4行,直接推送。


git_learning_B:修改readme.md的第7行,先pull,再推送。

git pull 过程中,弹出commit信息的编辑后, :wq 保存退出,即合并成功。

⚠️:这里直接pull会提示,没有明确的pull策略是不推荐的。

1)可以手动配置pull的默认策略

2)或者在 git pull 命令后加入选项,如 --rebase--no-rebase--ff-only

3)或者使用 git fetch 后,再选择合并策略


这时候查看本地的readme.md文件,符合预期,接下来直接push即可:

这种方式下的协同办公也是比较顺利的,Git有能力自动进行合并~

36 | 不同人修改了同文件的同一区域如何处理?

结论先行:在merge时会出现冲突,需要自行解决。

git_learning_A:修改readme.md的第1行,直接推送。

⚠️:别忘了先进行 git pull ,因为刚才git_learning_B做的更新还没有同步。


git_learning_B:同样修改readme.md的第1行,先pull,手动解决冲突,再推送。

这次我们 git pull 带了选项 --no-rebase ,表示通过merge的方式进行拉取。

紧接着, 产生冲突了,需要我们自己解决冲突,再进行提交。

vim readme.md ,打开产生冲突的文件 :

产生冲突的位置有明显的标记,HEAD与=之间代表本地的代码,hash值与=之间代表合入的代码。

我们需要修改这部分代码,并删去这些特殊标记,可以这样修改:(实际开发中,记得和相关人员交流后再进行修改❗️)

:wq 保存退出后,通过 git status 查看仓库状态:

红框中,上者表示进行合并;下者则表示取消合并,回到合并前的状态。

这里我们实践一下上者。⚠️:此时修改还在工作区,我们需要先添加到暂存区,再提交。

先进行添加和提交,再进行推送:

PS: -am 包含了添加和提交两个操作。


这次我们发现Git没有那么智能,也不需要那么智能,因为它肯定不知道谁的代码应该被保留。

37 | 同时变更了文件名和文件内容如何处理?

结论先行:直接merge即可。

git_learning_A:修改xxx/css.x的文件名为xxx/css2.x。

还记得 git mv 命令吗?可跳转1 Git基础--06|给文件重命名的简便方法回顾。


git_learning_B:修改xxx/css.x中的内容(并不知道文件名已经修改)。

Cool~Git可以自动解决这样的问题。查看合并情况:

可以看到不仅文件名修改过来了,文件里的修改也被保留了。

本质上,这里修改的是同文件的不同区域~

38 | 把同一文件改成了不同的文件名如何处理?

结论先行:在merge时会出现冲突,需要自行解决。

git_learning_A:修改xxx/css2.x的文件名为xxx/cssA.x。


git_learning_B:修改xxx/css2.x的文件名为xxx/cssB.x。(并不知道文件名已经修改)。

发生冲突了~

查看文件情况:

可以看到Git的做法是同时保留了两个修改了文件名的文件,并且两个文件的内容没有区别。

通过 git status 也很清晰的告诉了我们文件名变更的情况,以及可以怎么做。

git rm 不需要的文件, git add 最后决定要的文件,提交,推送,即可!

看了这几种场景下的Git协同办公,是不是对解决冲突不再恐惧了呢?