Git使用姿势 | 青训营笔记

139 阅读7分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第4篇笔记。

廖兴桔老师在《Git的正确使用姿势与最佳实践》中,详细地讲述了各种代码托管相关知识,对我们正在进行项目作业编写的小组起到了很大的帮助作用,接下来,就让我们复习一下本节课的部分知识点。

为什么要学习Git

  • 协同工作

    业界绝大多数公司都是基于Git进行代码管理,因此Git是一个程序员的必备技能

  • 开源社区

    目前绝大多数的开源项目都是基于Git维护的,参与这些项目的开发都需要使用Git

课程目录

  • 01.Git是什么
    • 介绍版本控制的发展历史,为什么会出现Git
    • 介绍Git的发展历史
  • 02.Git基本使用方式
    • Git的基本命令介绍,如何使用这些命令,以及命令的原理
  • 03.Git研发流程
    • 依托代码管理平台Gitlab/Github/Gerrit介绍我们如何进行代码的开发及团队合作

Git是什么

版本控制

  • Git是什么?

    • Git is a free and open source distributed version control system designed to handle everythingfrom small to very large projects with speed and efficiency.
  • 版本控制是什么?

    • 一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统
  • 为什么需要版本控制?

    • 更好的关注变更,了解到每个版本的改动是什么,方便对改动的代码进行检查,预防事故发生;也能够随时切换到不同的版本,回滚误删误改的问题代码

image.png

本地版本控制

  • 最初的方式
    • 通过本地复制文件夹,来完成版本控制,一般可以通过不同的文件名来区分版本
  • 解决方案
    • 开发了一些本地的版本控制软件,其中最流行的是RCS
  • 基本原理
    • 本地保存所有变更的补丁集,可以理解成就是所有的Diff,通过这些补丁,我们可以计算出每个版本的实际的文件内容
  • 缺点
    • RCS这种本地版本控制存在最致命的缺陷就是只能在本地使用,无法进行团队协作,因此使用的场景非常有限,因此衍生出了集中式版本控制

集中版本控制

代表性工具:SVN

  • 基本原理
    • 提供一个远端服务来保存文件,所有用户的提交都提交到该服务器中
    • 增量保存每次提交的Diff,如果提交的增量中和远端现存的文件存在冲突,则需要本地提前解决冲突
  • 优点:
    • 学习简单,更容易操作
    • 支持二进制文件,对大文件支持更友好
  • 缺点:
    • 本地不存储版本管理的概念,所有提交都只能联上服务器后才可以提交
    • 分支上的支持不够好,对于大型项目团队合作比较困难
    • 用户本地不保存所有版本的代码,如果服务端故障容易导致历史版本的丢失

分布式版本控制

代表性工具:Git

  • 基本原理
    • 每个库都存有完整的提交历史,可以直接在本地进行代码提交
    • 每次提交记录的都是完整的文件快照,而不是记录增量
    • 通过Push 等操作来完成和远端代码的同步
  • 优点
    • 分布式开发,每个库都是完整的提交历史,支持本地提交,强调个体
    • 分支管理功能强大,方便团队合作,多人协同开发
    • 校验和机制保证完整性,一般只添加数据,很少执行删除操作,不容易导致代码丢失
  • 缺点:
    • 相对SVN更复杂,学习成本更高
    • 对于大文件的支持不是特别好(git-lfs工具可以弥补这个功能)

Git的基本使用方式

Git基本命令

  • 配置
    • git config
    • git remote
  • 提交代码
    • git add
    • git commit
  • 远端同步
    • 拉取代码
      • git clone
      • git pull
      • git fetch
    • 推送代码
      • git push

Git目录介绍

  • 项目初始化
    • mkdir study
    • cd study
    • git init
  • 其他参数
    • --initial-branch初始化的分支
    • --bare创建一个裸仓库(纯Git目录,没有工作目录)
    • --template 可以通过模版来创建预先构建好的自定义git目录

Git常见配置

  • 用户名配置
  • lnstead of配置
  • Git命令别名配置
    • git config --global alias.cin "commit --amend --no-edit"

Git Remote

HTTP Remote

URL: https:/lgithub.com/git/git.git

  • 免密配置
    • 内存: git config --global credential.helper 'cache --timeout=3600'
    • 硬盘: git config --global credential.helper "store --file /path/to/credential-file"不指定目录的情况默认是~/ .git-credentials
  • 将密钥信息存在指定文件中
    • 具体格式:${scheme}://${user}:$fpassword}@github.com

SSH Remote

URL: git@github.com:git/git.git

  • 免密配置
    • SSH可以通过公私钥的机制,将生成公钥存放在服务端,从而实现免密访问
    • 目前的 Key的类型四种,分别是dsa、rsa、ecdsa、ed25519 默认使用的是rsa,由于一些安全问题,现在已经不推荐使用dsa和rsa了,优先推荐使用ed25519
    • ssh-keygen -t ed25519 -C“your_email@example.com”密钥默认存在~/.ssh/id_ed25519.pub

Object

commit / tree / blob 在 git里面都统一称为 Object,除此之外还有个tag的 object.

  • Blob
    • 存储文件的内容
  • Tree
    • 存储文件的目录信息
  • Commit
    • 存储提交信息,一个Commit可以对应唯一版本的代码
  • 如何把这三个信息串联在一起呢?

image.png

Ref

  • Ref文件储存的内容
    • refs 的内容就是对应的 Commit ID
    • 因此把ref 当做指针,指向对应的Commit 来表示当前Ref 对应的版本。
  • 不同种类的ref
    • refs/heads前缀表示的是分支,除此之外还有其他种类的 ref,比如refs/tags前缀表示的是标签。
  • Branch
    • git checkout 一b 可以创建一个新分支
    • 分支一般用于开发阶段,是可以不断添加Commit进行迭代的
  • Tag
    • 标签━般表示的是一个稳定版本,指向的Commit一般不会变更
    • 通过git tag命令生成 tag.

追溯历史版本

  • 获取当前版本代码
    • 通过 Ref 指向的 Commit可以获取唯一的代码版本。
  • 获取历史版本代码
    • Commit里面会存有parent commit字段,通过commit 的串联获取历史版本代码。

修改历史版本

  • commit --amend
    • 通过这个命令可以修改最近的一次 commit信息,修改之后commit id会变
  • rebase
    • 通过git rebase -i HEAD~3可以实现对最近三个commit 的修改:1.合并commit
    • 修改具体的commit message
    • 删除某个commit
  • filter --branch
    • 该命令可以指定删除所有提交中的某个文件或者全局修改邮箱地址等操作

Git GC

  • GC
    • 通过git gc命令,可以删除一些不需要的object,以及会对object进行一些打包压缩来减少仓库的体积。
  • Reflog
    • reflog是用于记录操作日志,防止误操作后数据丢失,通过reflog来找到丢失的数据,手动将日志设置为过期。
  • 指定时间
    • git gc prune=now指定的是修剪多久之前的对象,默认是两周前

常见问题

  • 为什么我明明配置了Git配置,但是依然没有办法拉取代码?
    • 免密认证没有配。
    • Instead Of配置没有配,配的 SSH免密配置,但是使用的还是 HTTP协议访问。
  • 为什么我Fetch了远端分支,但是我看本地当前的分支历史还是没有变化?
    • Fetch 会把代码拉取到本地的远端分支,但是并不会合并到当前分支,所以当前分支历史没有变化。