浅谈Git架构和如何避免代码覆盖的事故
Git 不同于 SVN 的地方在于, Git 是分布式的版本管理系统, 所有的客户端和服务器都保存了一份代码, 涉及到仓库仓之间的同步, 所以处理不当极易造成冲突
最直接的方法就是不让新手合并代码
- PR 开发: GitHub 开源项目常用开发方式, 开发者在自己的 仓库 上开发, 完成后提交 PR 给管理员审核合并
- MR 开发: 对代码要求比较严格的公司常用开发方式, 开发者在自己的 分支 上开发, 完成后提交 MR 给管理员审核合并
但是这样每次都要等管理员审核, 不适合敏捷开发的一般团队, 所以 Git 的学习和使用是必不可少的
Git架构
分布式的版本库
Git 本地仓库
Git 本地仓库 + stash 贮藏区
- 使用
git stash
可以将 工作区和暂存区修改的文件 移动到贮藏区, 通常在本地存在不想提交的临时文件的时候 pull 之前使用 - 使用
git stash pop
可以将贮藏区的文件恢复到 工作区和暂存区, 通常在提交之后使用
Git 本地仓库 + stash 贮藏区 + 远程仓库
常用命令
下面只是介绍下常见的开发命令, 其他命令可以参考 Git官方文档: https://git-scm.com/docs
共享分支开发
# 添加到暂存区
git add a.txt
# commit 本地仓库
git commit -m "新增 a.txt"
# 同步远程仓库
git pull origin master:master
# 推送到远程仓库
git push origin master:maser
非共享分支开发
提交到自己的远程分支, 然后提交 MR 合并到 master 分支
# 新建个人开发分支 dev_d
git branch dev_d
# 切换到个人开发分支 dev_d
git checkout dev_d
# 修改代码
# 添加到暂存区
git add a.txt
# commit 本地仓库
git commit -m "新增 a.txt"
# 同步远程仓库 master 副本并 merge 到 dev_d 分支
git pull origin master:master
# 推送本地 dev_d 分支到远程 dev_d 分支
git push origin dev_d:dev_d
在 GitLab 等平台创建 PR 合并 dev_d 到 master 分支, 然后让管理员审核
本地存在不想提交的临时文件
# 将不想提交的代码 stash 到贮藏区
git stash save "临时配置文件a.yaml"
# 同步远程仓库 master 副本并 merge 到 dev_d 分支
git pull origin master:master
# 推送到远程仓库
git push origin master:maser
# 将暂时贮藏的文件恢复
git stash pop
什么时候会发生代码冲突
Git 有 2 种情况会发生代码冲突
- 两个人同时修改了同一个文件的同一行 (比如 张三, 李四同时修改了 a.txt 文件的第一行)
- 修改文件的时候文件名被其他人修改了 (比如 张三修改了 a.txt 文件的第一行, 李四将 a.txt 文件修改为 b.txt(或者删除))
修改了同一个文件的同一行
下面展示一下代码冲突的过程
- 张三创建 a.txt 并且在第一行写入 1, commit 到本地仓库, push 推送到远程
- 李四将同步代码后, 将第一行的 1 修改为 2, commit 到本地仓库, push 到远程
- 张三将第一行修改为 3, commit 到本地, push 到远程
- 张三代码冲突, 拒绝 push
$ git push
To github.com:dengjiawen8955/git-demo.git
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to '[email protected]:dengjiawen8955/git-demo.git'
- 张三 pull 远程代码, 因为代码冲突, 不能自动 Merge
$ git pull
Auto-merging 0928_2/a.txt
CONFLICT (content): Merge conflict in 0928_2/a.txt
Automatic merge failed; fix conflicts and then commit the result.
- 张三手动处理冲突, 可以手动编辑冲突的文件或者使用相关可视化工具
# 查看冲突文件
$ git status
On branch master
Your branch and 'origin/master' have diverged,
and have 1 and 1 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add ..." to mark resolution)
both modified: a.txt
no changes added to commit (use "git add" and/or "git commit -a")
# 处理冲突 (注意, 代码覆盖事故就是在这里发生, 冲突处理覆盖了李四的代码)
$ vim a.txt
# 将处理完的文件添加到暂存区
$ git add a.txt
# 提交到本地仓库
$ git commit -m "处理冲突"
# 推送到远程
$ git push
如果本来 李四提交的代码 2 和 张三提交的代码 3 都应该保留的, 张三却没有保留李四的代码, 那么就会发生代码覆盖事故
正确的结果
2
3
张三合并后的结果
3
修改文件的时候文件名被其他人修改了
原理是类似的, 这里不做赘述了
如何减少失误?
- 了解 Git 的工作原理和基本命令, 知其然知其所以然, 就能减少失误
- 及时提交代码, 更新代码, 避免因为长时间没有同步代码产生过多的冲突文件, 因为在解决冲突的时候初级人员是非常容易出错的
- 熟悉 Git 工具, 比如命令行或 GitTortoise, 避免因为工具不熟悉导致失误
- 本地修改前应该尽可能的避免本地库与远程之间有过多的差异, 本地修改前执行一次 git pull 先把远程更新拉到本地
pull 之前如果有没有提交的文件, 先 stash
git stash git pull git stash pop 如果有冲突解决冲突
出现了代码冲突事故应该怎么做?
如果事故已经发生了, 首先应该查看日志分析原因, 找到出问题的节点撤销操作, 回滚代码
查看日志分析原因
使用命令行或者你熟悉的工具查看分支历史
命令行
#log --graph 结合使用时尤其有用,这个选项添加了一些ASCII字符串来形象地展示你的分支、合并历史
$ git log --pretty=format:"%h %s" --graph
* f3b92cb 解决冲突
|\
| * 3543686 a.txt第一行修改为3
* | 251b3cb a.txt第一行修改为2
|/
* 6a432b2 a.txt第一行新增1
# 使用 git diff 查看修改历史 (找出出问题的节点)
$ git diff f3b92cb 3543686
使用其他工具可以更加方便的可视化查看, 这里不赘述了
找到出问题的节点撤销操作
参考: https://blog.csdn.net/jarvan5...
总结
如果今天的内容你只能记住一件事, 那请记住: 熟悉 Git 工具, 比如命令行或 IDE, 避免因为工具不熟悉导致失误
reference
https://blog.csdn.net/qq_2738...
本文由mdnice多平台发布