-
后端开发的一周
- 周一
- 产品功能演示:针对上个迭代开发的功能进行演示
- 反思会:反思上个迭代的不足
- PM和UED准备明天要规划的需求列表
- 周二
- Grooming会议(需求规划会议)
- 针对backlog积累的需求,PO和PM分别阐述各个需求的价值
- Scrum Master和架构师确认需求中包含的技术任务
- 最终会议确定下个迭代要做的需求,并给你安排10个需求
- 周三
- 之前开发的需求需要上线,提交一个发布车票
- 对其他人提交的上线工单进行Code Review
- 修复代码缺陷
- 周四
- 发布日——之前提交车票的部分功能要在今天发布
- 发布过程中发现监控出现异常,马上终止发布,定位问题原因
- 发现是自己的代码有问题,需要进行回滚和修复
- 周五
- Planning会议
- 发现下个迭代只能完成8个需求,按照优先级把2个需求移出迭代
- 将8个需求的工作量进行评估
- 把8个需求各自的开发和上线时间进行排期
- 周一
-
Git
-
代码托管、代码智能、代码分析、持续集成、Cloud IDE
-
版本控制——RCS、SVN、Git
-
集中式版本控制——SVN
- 基本原理
- 提供一个远端服务来保存文件,所有用户的提交都提交到该服务器中
- 增量保存每次提交的Diff,如果提交的增量和远端现存的文件存在冲突,则需要本地提前解决冲突
- 优点:学习简单、操作简单、支持二进制文件、对大文件支持更友好
- 缺点
- 本地不存储版本管理的概念,所有提交都只能连上服务器后才可以提交
- 分支上的支持不够好,对于大型项目团队合作比较困难
- 用户本地不保存所有版本的代码,如果服务端故障容易导致历史版本的丢失
- 基本原理
-
分布式版本控制——Git
- 基本原理
- 每个库都存有完整的提交历史,可以直接在本地进行代码提交
- 每次提交记录的都是完整的文件快照,而不是记录增量
- 通过Push等操作来完成和远端代码的同步
- 优点
- 分布式开发,每个库都是完整的提交历史,支持本地提交,强调个体
- 分支管理功能强大,方便团队合作,多人协同开发
- 校验和机制保证完整性,一般只添加数据,很少执行删除操作,不容易导致代码丢失
- 缺点
- 相对SVN更复杂,学习成本更高
- 对于大文件的支持不是特别好(git-lfs工具可以弥补这个功能)
- 基本原理
-
Github、Gitlab、Gerrit
-
Git基本命令
-
项目初始化
mkdir study cd study git initgit init其他参数:
- --initial-branch 初始化的分支
- --bare 创建一个裸仓库(纯Git目录,没有工作目录)
- --template 可以通过模板来创建预先构建好的自定义git目录
-
Git Config
-
每个级别的配置可能重复,但是低级别的配置会覆盖高级别的配置(system>global>local)
- --global:~/.gitconfig
- --system:/etc/gitconfig
- --local:.git/config
-
用户名配置
git config --global user.name "lixubin" git config --global user.email lixubin@163.com -
Instead of配置
git config --global url.git@github.com:.insteadOf https://github.com/ -
Git命令别名配置
git config --global alias.cin "commit --amend --no-edit"
-
-
Git Remote
-
查看Remote
git remote -v -
添加Remote
git remote add origin_ssh git@github.com:git/git.git git remote add origin_http https://github.com/git/git.git -
同一个Origin设置不同的Push和Fetch URL
git remote add origin_ssh git@github.com:git/git.git git remote set-url --add --push origin git@github.com:my_repo/git/git.git
-
-
HTTP Remote
免密配置
-
内存
git config --global credential.helper 'cache --timeout=3600' -
硬盘
git config --global credential.helper "store --file /path/to/credential-file"不指定目录的情况默认是~/.git-credentials
-
将密钥信息存在指定文件中
具体格式:{user}:${password}@github.com
-
-
SSH Remote
免密配置:SSH通过公私钥的机制,将生成公钥存放在服务端(默认RSA、推荐使用ED25519)
ssh-keygen -t ed25519 -C "lixubin@163.com"密钥默认存在~/.ssh/id_ed25519.pub
-
Git Add
touch readme.md git status git add . //将readme.md上传到暂存区 git status tree .git.git文件目录中objects目录下会生成一个新文件
-
Git Commit
git commit -m "add readme".git文件目录中objects目录下同样会生成新文件
-
-
Objects
commit / tree / blob 在git里面都统一称为Object,除此之外还有个tag的object
-
Blob:存储文件的内容
-
Tree:存储文件的目录信息
-
Commit:存储提交信息,一个Commit可以对应唯一版本的代码
通过Commit信息查看Tree ID,通过Tree信息查看对应的Blob ID,通过Blob信息获取具体的文件内容
-
-
Refs
-
refs的内容就是对应的Commit ID,表示当前Ref对应的版本
-
refs/heads前缀表示分支,refs/tags前缀表示标签
-
Branch:git checkout -b可以创建一个新分支,一般用于开发阶段,可以不断添加Commit进行迭代
-
Tag:git tag v0.0.1可以创建一个tag,标签一般表示的是一个稳定版本,指向的Commit一般不会变更
-
-
Annotation Tag
-
附注标签:一种特殊的Tag,可以给Tag提供一些额外的信息
-
该命令创建附注标签,会生成tag的object
git tag -a v0.0.2 -m "add feature 1" -
-
追溯历史版本
-
获取当前版本代码
通过Ref指向的Commit可以获取唯一的代码版本
-
获取历史版本代码
Commit里会存有parent commit字段,通过commit的串联获取历史版本代码
-
修改历史版本
-
commit --amend
该命令可以修改最近的一次commit信息,修改之后commit id会变
-
rebase
通过git rebase -i HEAD~3 可以实现对最近三个commit的修改:
- 合并commit
- 修改具体的commit message
- 删除某个commit
-
filter --branch
该命令可以指定删除所有提交中的某个文件或者全局修改邮箱地址等操作
-
-
该命令可以查找悬空的Object(没有ref指向的object)
git fsck --lost-found -
Git GC
-
GC
通过git gc命令,可以删除一些不需要的object,以及会对object进行一些打包压缩来减少仓库的体积
-
Reflog
用于记录操作日志,防止误操作后数据丢失,通过reflog来找到丢失的数据,手动将日志设置为过期
git reflog expire --expire=now --all -
指定时间
指定的是修剪多久之前的对象,默认是两周前
git gc prune=now
-
-
Git Clone & Pull & Fetch
-
Clone
拉取完整的仓库到本地目录,可以指定分支、深度
-
Fetch(推荐)
将远端某些分支最新代码拉取到本地,不会执行merge操作,会修改refs/remote内的分支信息,如果需要和本地代码合并需要手动操作
-
Pull
拉取远端某分支,并和本地代码进行合并,等同于git fetch+git merge,也可以通过git pull --rebase完成git fetch+git rebase操作(可能存在冲突,需要解决冲突)
-
-
Git Push
git push origin master //将本地代码同步至远端-
冲突问题
- 如果本地commit记录与远端commit历史不一致,则会产生冲突,比如git commit --amend or git rebase都可能导致这个问题
- 如果该分支就自己一个人使用,或者团队确认过可以修改历史则可以通过git push origin master --f来完成强制推送,一般不推荐主干分支进行该操作,正常都应该解决冲突后再进行推送
-
推送规则限制
可以配置一些保护规则,防止误操作,或者一些不合规的操作出现,导致代码丢失
-
-
常见问题
- 为什么我明明配置了Git配置,但是依然没有办法拉取代码?
- 免密认证没有配置
- Instead Of配置没有配,配的SSH免密配置,但是使用的还是HTTP协议访问
- 为什么我Fetch了远端分支,但是我看本地当前的分支历史还是没有变化?
- Fetch会把代码拉取到本地的远端分支,但是并不会合并到当前分支,所以当前分支历史没有变化
- 为什么我明明配置了Git配置,但是依然没有办法拉取代码?
-
不同的工作流(集中式、分支管理)
-
集中式工作流
- 只依托于master分支进行研发活动
- 工作方式
- 获取远端master代码
- 直接在master分支完成修改
- 提交前拉取最新的master代码和本地代码进行合并(使用rebase),如果有冲突需要解决冲突
- 提交本地代码到master
- Gerrit
- 优点
- 提供强制的代码评审机制,保证代码的质量
- 提供更丰富的权限功能,可以针对分支做细粒度的权限管控
- 保证master的历史整洁性
- Aosp(Android Open Source Project)多仓的场景支持更好
- 缺点
- 开发人员较多的情况下,更容易出现冲突
- 对于多分支的支持较差,想要区分多个版本的线上代码时,更容易出现问题
- 一般只有管理员才能创建仓库,比较难以在项目之间形成代码复用,比如类似的fork操作就不支持
- 优点
-
分支管理工作流
-
GitFlow
- 包含五种类型的分支
- Master:主干分支
- Develop:开发分支
- Feature:特性分支
- Release:发布分支
- Hotfix:热修复分支
- 优点:如果能按照定义的标准严格执行,代码会很清晰,并且很难出现混乱
- 缺点:流程过于复杂,上线的节奏会比较慢,研发容易不按照标准执行,出现混乱
- 包含五种类型的分支
-
Github Flow
- 只有一个主干分支,基于Pull Request往主干分支中提交代码
- 团队合作的方式
- owner创建好仓库后,其他用户通过Fork的方式来创建自己的仓库,并在fork的仓库上进行开发
- owner创建好仓库后,统一给团队内成员分配权限,直接在同一个仓库内进行开发
-
Gitlab Flow
-
原则:upstream first上游优先
只有在上游分支采纳的代码才可以进入到下游分支,一般上游分支就是master
-
-
-
代码合并
-
Fast-Forward
不会产生一个merge节点,合并后保持一个线性历史
-
Three-Way Merge(--no-ff)
三方合并,会产生一个新的merge节点
-
-
常见问题
-
在Gerrit平台上使用Merge的方式合入代码。
Gerrit是集中式工作流,不推荐使用Merge方式合入代码,应该是在主干分支开发后,直接Push。
-
不了解保护分支、Code Review、CI等概念,研发流程不规范。
保护分支:防止用户直接向主干分支提交代码,必须通过PR来进行合入。
Code Review、CI:都是在合入前的检查策略,Code Review是人工进行检查,CI则是通过一些定制化的脚本来进行一些校验。
-
代码历史混乱,代码合并方式不清晰。
不理解Fast Forward和Three Way Merge的区别,本地代码更新频繁地使用Three Way的方式,导致生成过多的Merge节点,使提交历史变得复杂不清晰。
-
-