浅谈Git架构和如何避免代码覆盖的事故

浅谈Git架构和如何避免代码覆盖的事故

Git 不同于 SVN 的地方在于, Git 是分布式的版本管理系统, 所有的客户端和服务器都保存了一份代码, 涉及到仓库仓之间的同步, 所以处理不当极易造成冲突

最直接的方法就是不让新手合并代码

  • PR 开发: GitHub 开源项目常用开发方式, 开发者在自己的 仓库 上开发, 完成后提交 PR 给管理员审核合并
  • MR 开发: 对代码要求比较严格的公司常用开发方式, 开发者在自己的 分支 上开发, 完成后提交 MR 给管理员审核合并

但是这样每次都要等管理员审核, 不适合敏捷开发的一般团队, 所以 Git 的学习和使用是必不可少的

Git架构

分布式的版本库

分布式的版本库

Git 本地仓库

Git本地的 3 个工作区

Git 本地仓库 + stash 贮藏区

Git本地的 3 个工作区 + stash 贮藏区

  • 使用 git stash 可以将 工作区和暂存区修改的文件 移动到贮藏区, 通常在本地存在不想提交的临时文件的时候 pull 之前使用
  • 使用 git stash pop 可以将贮藏区的文件恢复到 工作区和暂存区, 通常在提交之后使用

Git 本地仓库 + stash 贮藏区 + 远程仓库

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:master

非共享分支开发

提交到自己的远程分支, 然后提交 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 分支, 然后让管理员审核

创建PR

本地存在不想提交的临时文件

# 将不想提交的代码 stash 到贮藏区
git stash save "临时配置文件a.yaml"
# 同步远程仓库 master 副本并 merge 到 dev_d 分支
git pull origin master:master
# 推送到远程仓库
git push origin master:master
# 将暂时贮藏的文件恢复
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 'git@github.com: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 <file>..." 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

修改文件的时候文件名被其他人修改了

原理是类似的, 这里不做赘述了

如何减少失误?

  1. 了解 Git 的工作原理和基本命令, 知其然知其所以然, 就能减少失误

  2. 及时提交代码, 更新代码, 避免因为长时间没有同步代码产生过多的冲突文件, 因为在解决冲突的时候初级人员是非常容易出错的

  3. 熟悉 Git 工具, 比如命令行或 GitTortoise, 避免因为工具不熟悉导致失误

  4. 本地修改前应该尽可能的避免本地库与远程之间有过多的差异, 本地修改前执行一次 git pull 先把远程更新拉到本地

  5. 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/article/details/114028765

总结

如果今天的内容你只能记住一件事, 那请记住: 熟悉 Git 工具, 比如命令行或 IDE, 避免因为工具不熟悉导致失误

reference

https://blog.csdn.net/qq_27384769/article/details/80421279

https://git-scm.com/docs

本文由mdnice多平台发布

posted @ 2022-09-30 11:19  邓嘉文Jarvan  阅读(218)  评论(0编辑  收藏  举报