Git指南
Git指南
零、目的
- 掌握各类场景下如何更好使用Git。
- 减少因为代码提交问题带来的生产环境问题。
一、了解[[Git]]
- 什么是Git? 1. 一款分布式版本管理系统 2. 优点:分布式、性能、版本的文件完整性 1. 分布式,可以让你在本地提交代码(对于SVN而言没有网络就无法提交代码,在家也能愉快地写代码); 2. 性能,对于我们的一般项目而言,你感受不到合并时性能的差别(与SVN比较); 3. 版本的文件完整性:git背后设计理念是快照思想。
- Git概念 1. 仓库(repository) 1. 用于代码版本管理 2. 一个git仓库管理了三棵“树”,分别是 1. Working Directory(工作目录) 2. Index(暂存区) 3. HEAD(本地仓库) 3. 大多数时候你通过编辑器只能对工作目录操作,操作其他两个“树”(区域)必须使用git命令才可以。 2. 分支(branch) 1. 用于并行独立开发,更方便管理不同开发任务的进度
- Git常用命令 1. git add 2. git commit 3. git push 4. git pull 5. git branch 6. git switch 7. git restore
二、最常见的一种使用场景
陈主管说他已经开发好了整个架构,需要我去把几个功能实现一下,并提交到dev分支让他方便Review。
- 基本流程
1. 先从远程服务器把代码拉到本地:
git clone http://197.68.6.70/demo-project
2. 此时你拥有的是主干master分支的代码,我们需要切换到dev分支进行开发: 1.git fetch --all
2.git switch --track origin/dev
3. 在工作目录写代码 4. 提交变更的文件到暂存区:git add <somefile>
5. 提交文件到本地仓库:git commit -m "xxx"
6. 把我的代码推送到远程仓库(同步):git push
三、最佳实践——Git里的后悔药
- 我提交到暂存区的代码搞错了:
git restore -S <files or dir>
(在使用IDEA时,这个场景不太会出现,因为IDEA往往是把add 和 commit的操作会合并成一个处理) - 我提交到本地仓库的代码搞错了:
1. 最近的一个commit:
git reset -mixed HEAD~1
2. 历史中的一个commit: 1. 使用git reset --mixed <commit_id>
,然后重新提交正确的代码( ❗从最新commit到指定commit的代码都需要重新提交) 2. 使用git revert <commit_id>
,这个操作近似于自己重新提交代码 - 我提交到远程仓库的代码搞错了: 1. 只有一个建议:请写出正确的代码,重新提交!所以,请在每次push之前谨慎!
四、最佳实践——与他人同步
- 我想把别人在dev分支上开发的代码同步下来看看:
git pull --rebase
或者git pull
(前者会让你的commit log更加清爽一些,没有一些额外的merge commit log) - 如果你开发的分支和多人一同开发,建议每天进行一次
git pull --rebase
与git push
五、最佳实践——我的改动比较大
- 建议自己拉一个分支进行开发
git switch -c <new_branch_name>
。 - 开发结束后,先把主开发分支合并到你的分支:
git merge dev
- 没问题后再把你的分支合并到主开发分支:
git switch dev
,git merge <new_branch_name>
六、其他
- ⭐准备上线前
1. 和上一个版本代码对比(
git diff release master
),确认release分支是正确的需要上线的代码 2. 使用Jenkins对release分支进行自动打包与部署,在工作空间获取上线代码包(禁止本地打包) - 上线完成后 1. 在gitlab上提交release合并至master分支的merge request,由技术经理确认合并; 2. 对最新的master分支进行tag,方便反查源码;
七、几个原则
强制
- 禁止
git push -f
- 禁止
git push master
建议
- 建议分支命名:master、release、dev、dev_xx 1. master分支为线上正在运行的代码;不允许手动提交;只能通过页面的merge request进行代码合并;每次上完线后把分支(release)代码合并到master 2. release为测试环境对应的代码,jenkins均从该分支进行自动构建与部署 3. dev,以及其他分支为开发分支,较为自由。
- 减少对
git checkout
的使用,已经拆分为git switch
和git restore
- 不要把二进制文件放到git仓库中进行版本管理
八、实现方式之数据结构
在Git当中,
// 一个文件就是字节数组
type blob = array<byte>
// 一个目录包含文件或者其他目录
type tree = map<string, tree | blob>
// 一个commit包含它的父节点,原始信息,顶级目录(快)
type commit = struct {
parents: array<commit>
author: string
message: string
snapshot: tree
}
// 文件、目录、commit最终都以object类型进行存储
type object = blob | tree | commit
这样看起来,每一次修改文件并提交git仓库后,都会新建一个blob对象,并作为新的快照内部的文件使用,因此,git仓库存储空间可能会越来越大,特别是对于那些二进制文件(非文本文件,难以压缩)。这时候可以通过git gc
进行git仓库压缩,这里面的算法大家可以自己去探索一下。根据我的经验,能大概缩小到原本的1/3~1/2。
九、参考
Cheatsheet
- 一个可视化的Git Cheatsheet
- Gitlab官方Cheatsheet
- https://github.com/k88hudson/git-flight-rules
- Git - 高级合并 (git-scm.com)
原理学习
- 为什么你应该使用 Git 进行版本控制 - 面向信仰编程 (draveness.me)
- Pro Git 中文版(第二版)
- Version Control (Git) · the missing semester of your cs education (mit.edu)
Some code
git clone
git branch --track dev origin/dev
git checkout dev
git add & git commit
git push
Merge Request (MR)
git restore -S <files or dir>
git reset -mixed HEAD~1
git reset --mixed <commit_id>
git revert <commit_id>
git pull --rebase
git pull
git checkout -b <branch_name>
...
git merge dev
git stash
git stash pop
最后修改于 2022-01-03