Git 技术内幕及团队协作
技术内幕
Git 数据存储模型
Git 内部对象
- Commit 
- Tree 
- Blob 
Git 引用
团队协作
分支策略
- 主线分支开发(Trunk)
- 功能分支部署(Feature)
- 状态分支(Gitlab-flow)
- 计划部署(Git-flow)
如何选择是merge 还是 rebase
- 有用的merge参数 - git merge --no-ff
 “真正”的merge,会产生merge commit。
- git merge --ff-only
 “fast forward” 图形像reabse效果一样。
- git merge --squash
 会将多个commit压缩为一个,然后进行合并。
 
- 其他类似的命令 - git pull=- git fetch+- git merge
- git rebase
 Forward-port local commits to the updated upstream head.
- git cherry-pick
 合并个别提交
 
工作流
在团队协作中使用命令
独自工作下的操作
本地仓库操作
- 创建仓库 git init
- 克隆仓库 git clone
- 查看仓库状态 git status
- 添加文件到暂存区 git add
 几个添加文件到暂存区命令参数:- --all添加所有文件
- --update添加所有已跟踪文件修改到暂存区
- --patch选择文件的部分修改添加到暂存区
 
- 将暂存区文件提交至本地仓库 git commit
- 查看提交历史 git log
 几个查看命令参数:- --graph以提交树的图形化方式展示
- --oneline以简短(只显示消息title)的方式展示
- --no-merges不显示merge提交
 
分支操作
- 查看分支 git branch
 几个查看分支命令参数:- --list列表形式输出
- --all列出所有分支(本地+远程)
- --verbose查看分支详细信息(最新提交hash值)
 
- 更新远程分支 git fetch
- 检出/切换分支 git checkout
 几个检出分支命令参数:- --trace检出且跟踪远程分支
- -b创建检出一个新分支
 
“后悔药”操作
| 撤销场景 | 备注 | 解决方案 | 
|---|---|---|
| 移除所有未被追踪的文件 | 文件未被加入暂存区和提交 | git clean -fd | 
| 撤销工作目录中未暂存的修改 | 修改的文件未被暂存或提交 | git checkout --filename | 
| 撤销所有本地未提交的修改 | 修改的文件已暂存但未提交 | git reset --hard | 
| 撤销本地已暂存但未提交的某个文件 | 某个文件已暂存但未提交 | git reset <filename> | 
| 撤销已提交变更但需要保留回滚日志场景 | 修改文件已提交且发布,工作目录是干净的 | git revert <commit-hash> | 
| 修改非共享/非集成分支提交历史中移除一个单独的提交 | 已本地提交,工作目录干净,未发布 | git rebase --interactive <commit-hash> | 
多人团队协作下的操作
多人团队协作及评审工作流操作
工作流最佳实践
- 使用feature分支而不是在main或master分支上直接提交
- 测试所有提交,不仅仅是main或master分支上的提交
- 对所有提交运行自动化测试,如果运行时间长于5分钟,考虑并行运行这些自动化测试
- 禁止在集成分支(master/develop/stg)上进行rebase操作
- 所有人需要从master/main分支开始且最终目标回到master/main
- 提交信息需要反应意图且符合规范
几个经典案例
- checkout 某个commit 后基于当前提交创建提交,chekout 到其他分支后这个新增commit还可以看到么?
 关键点:分离头指针(detached head)模式,找不到的提交可以通过git reflog找回。
附录
Git 底层命令
git cat-file
- git cat-file -t查看类型
- git cat-file -p查看内容
git hash-object 内容hash值计算
- git hash-object -w <path-to-file>
git update-index 为文件创建一个暂存区
- git update-index --add --cacheinfo 100644 <full-hash> <path-to-file>
git write-tree 将暂存区内容写入树对象
git commit-tree 创建一个提交对象
git update-ref 更新Git引用对象
- git updte-ref ref/heads/<branch_name> <commit_hash>
Git上层命令内幕
- Git add=- git hash-object+- git update index
- Git commit=- git write-tree+- git commit-tree
- Git branch -b <branch_name> <commit_hash>=- git update-ref ref/heads/<branch_name> <commit_hash>
演示实验全过程
- 版本信息
| 1 | ➜ Git-internal git --version | 
- 创建仓库
| 1 | git init test | 
