这是我在字节跳动青训营学习的第30天,也是我参加《第六届青训营笔记伴读》的第五篇笔记
1. Git是什么
Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.
Git是一个免费开源的分布式版本控制系统,旨在快速并且高效大的为从大到小的项目那个提供版本管理。
1.1 版本控制是什么
版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统
| 版本控制类型 | 代表性工具 | 解决的问题 |
|---|---|---|
| 本地版本控制 | RCS | 本地代码的版本控制 |
| 集中式版本控制 | SVN | 提供一个远端服务器来维护代码版本,本地不保存代码版本,解决多人协作问题 |
| 分布式版本控制 | Git | 每个仓库都能记录版本历史,解决只有一个服务器保存版本的问题 |
1.1.1 本地版本控制
- 最初的方式:通过本地复制文件夹,来完成版本控制,一般通过不同的文件名来区分版本
- 解决方案:开发了一些本地的版本控制软件,最流行的是RCS
- 基本原理:本地保存所有变更的补丁集,可以理解成就是所有的Diff,通过这些补丁,我们可以计算出每个版本的实际的文件内容
- 缺点:只能在本地使用,无法进行团队合作
1.1.2 集中版本控制
-
基本原理:
- 提供一个远端服务来保存文件,所有用户的提交都提交到该服务器中
- 增量保存每次提交的Diff,如果提交的增量中和远端现存的文件存在冲突,则需要本地提前解决冲突
-
优点:
- 学习简单,容易操作
- 支持二进制文件,对打文件支持更友好
-
缺点:
- 本地不存储版本管理的概念,所有提交都只能连上服务器才可以提交
- 分支上支持的不够好,对于大型项目团队合作比较困难
- 用户本地不保存所有版本二队代码,如果服务端故障容易导致历史版本丢失
1.1.3 分布式版本控制
- 基本原理
- 每个库都有完整的提交历史,可以直接在本地进行代码提交
- 每次提交 记录都是完整的文件快照,而不是记录增量
- 通过push等操作来完成和远端代码的同步
- 优点:
- 分布式开发,每个库都是完整的提交历史,支持本地提交,强调个体
- 分支管理功能强大,方便团队合作,多人协同开发
- 校验和机制保证完整性,一般指添加数据,很少执行删除操作,不容易导致代码丢失
- 缺点:
- 相对SVN更复杂,学习成本更高
- 对于大文件的支持不是很好
1.2 为什么需要版本控制
更好的关注变更,了解到每个版本的改动是什么,方便对改动的代码进行增删改查,预防事故发生,也能够随时切换到不同的版本,回滚误删误改的问题代码
2. Git发展历史
作者: Linus Torvals(就是Linux的作者)
开发原因: BitKeeper怀疑Linux团队对BitKeeper(另一种分布式版本控制系统)进行了逆向工程,因此不允许inux团队继续无偿使用。因此决定自己开发一个分布式版本控制系统
衍生:
- GIthub:全球最大的代码托管平台,大部分的开源项目都在这个平台上
- Gitlab:全球最大的开源代码托管平台,项目所有代码都是开源的,便于在自己的服务器上完成gitlab的搭建
- Gerrit:谷歌开发的一个代码托管平台,Android的开源项目就托管在Gerrit之上
3. Git的基本使用方式
mindmap
Git命令
配置
Git config
Git remote
提交代码
Git add
git commit
远端同步
拉取代码
clone
pull
fetch
推送代码
push
3.1 常见问题
- 为什么明明配置了Git配置,但依然无法拉取代码
- 免密配置没有配
- instead Of 配置没有配,配的ssh免密配置,但是使用的还是http协议访问
- 为什么我Fetch了远端分支,但是我本地当前的分支历史还是没有变化
- Fetch 会把代码拉取到本地的远端分支,但是不会合并到当前分支,所以当前分支历史没有变化
3.2 项目初始化
使用 git init初始化本地仓库
其它参数
- initial-branch 初始化的分支
- bare 创建一个裸仓库(纯git目录,没有工作目录)
- template 可以通过创建模板来创建预先定义好的自定义git目录
3.3 常见Git配置
用户名配置
git config --global user.name "username"git config --global user.email xxx@xxx.com
Git命令别名配置
git config --global alias.cin "commit --amend --no-edit"
修改完后 cin = commit --amend --no-edit
3.4 Git Remote
查看Remote
git remote -v
添加Remote
git remote add origin url
SSH Remote
URL:仓库地址
免密配置
SSH可以通过公私钥的机制,将生成的公钥存在服务端,从而实现免密访问,目前的key的类型有四种,分别是dsa、rsa、ecdsa、ed25519
默认使用的是rsa,由于一些安全问题,现在已经不推荐使用dsa和rsa,优先推荐使用ed25519
ssh-keygen -t ed25519 -C "your_email@example.com"密钥默认存在~/.ssh/idd_ed25519.pub然后把他加到github上
3.5 Refs
分支(branch)
分支一般用于开发阶段,可以不断添加Commit进行迭代
git checkout -b xxx = git branch +git checkout
标签(tag)
标签一般表示的是一个稳定的版本,指向的Commit一般不会变更
通过git tag xxx命令生成tag
附注标签
一种特殊的标签, 可以给标签提供一些额外的信息
git tag -a
修改历史版本
commit --amend通过这个命令可以修改最近一次的commit信息,修改之后commit id会变rebase通过git rebase -i HEAD~3可以实现对最近三个commit的修改:合并,修改,删除filter --branch该命令可以指定删除所有提交中的某个文件或者全局修改邮箱地址等操作
查询悬空object
使用commit --amend修改commit信息后,原先的commit对象并未删除,但同时也没有ref指向他,此时这个commit就悬空了
git fsck --lost-found
删除悬空object
git reflog+git gc --prune =now
GC
通过git gc命令,可以删除一些不需要的object,以及会对object进行一些打包压缩来减少仓库的体积
Reflog
reflog是用于记录操作日志,防止误操作后数据丢失,通过reflog来找到丢失的数据,手动将日志设置为过期
指定时间
git gc --prune =now 指定的是修剪多久之前的对象,默认是两周前
3.6 远端同步
获取
Clone
拉取完整的仓库到本地目录,可以指定分支,深度
Fetch
将远端某些分支最新代码拉取到本地,不会执行merge操作,会修改refs/remote内的分支信息,如果需要和本地代码合并需要手动操作。
Pull
拉取远端某分支,并和本地代码进行合并,操作等同于git fetch + git merge,也可以通过git pull --rebase完成git fetch + git rebase可能存在冲突,需要解决冲突
推送
Push
使用git add将代码添加到暂存区
使用git commit -m "评论"将暂存区文件提交到本地仓库
使用git push origin master将本地仓库的代码推送到远端仓库,origin是Remote时设置的,相当于远端仓库链接的别名
冲突问题
- 如果本地的commit记录和远端的commit历史不一致,则会产生冲突,比如git commit -amend or git rebase都可能导致这个问题
- 如果该分支就自己一个人使用,或者团队内确认过可以修改历史则可以通过 git push origin master -f来完成强制推送,一般不推荐主干分支进行该操作,正常都应该解决冲突后再进行推送
推送规则限制
可以通过保护分支,来配置一些保护规则,防止误操作,或者一些不合规的操作出现,导致代码丢失