Git 学习教程(上) | 青训营笔记

56 阅读7分钟

这是我参与「第五届青训营 」笔记创作活动的第5天

一、背景

为什么学习Git

  • 协同工作
    • 业界绝大多数公司都是基于 Git 进行代码管理,因此 Git 是一个程序员的必备技能
  • 开源社区
    • 目前绝大多数的开源项目都是基于 Git 维护的,参与这些项目的开发都需要使用 Git。

为什么设计这门课程

  • 常见问题
    • 入职后按照文档进行 Git 配置,但是配置后依然拉取代码有问题,缺少自己排查配置的能力
    • 研发流程中进行一些异常操作,不符合研发规范,不清楚保护分支,MR/PR等概念
  • 课程目标
    • 学习 Git 基本命令,并了解原理,在遇到 Git 相关问题时,能自行排查解决
    • 了解研发流程中的基本概念和规范,学会正确的使用Git

二、本堂课重点内容

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

三、详细知识点介绍

1. Git 是什么

1.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.
  • 版本控制是什么?
    • 一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统
  • 为什么需要版本控制
    • 更好的关注变更,了解到每个版本的改动是什么,方便对改动的代码进行检查,预防事故发生
    • 也能够随时切换到不同的版本,回滚误删误改的问题代码
版本控制类型代表性工具解决的问题
本地版本控制RCS本地代码的版本控制
集中式版本控制SVN提供一个远端服务器来维护代码版本,本地不保存代码版本,解决多人协作问题
分布式版本控制Git每个仓库都能记录版本的历史,解决只有一个服务器保存版本的问题

1.1.1 本地版本控制

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

image.png

1.1.2 集中版本控制

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

1.1.3 分布式版本控制

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

image (2).png

1.2 Git 发展历史

  • 作者
    • Linus Torvalds(就是Linux这个项目的作者,同时也是 Git 的作者)
  • 开发原因
    • 怀疑 Linux 团队对 BitKeeper (另一种分布式版本控制系统,专有软件)进行了逆向工程,BitKeeper 不允许 Linux 团队继续无偿使用。因此决定自己开发一个分布式版本控制系统。
  • 开发时间
    • 大概花了两周时间,就完成了 Git 的代码第一个版本,后续 Linux 项目就开始使用Git进行维护

1.2.1 三个典型

  • Github
    • 全球最大的代码托管平台,大部分的开源项目都放在这个平台上。
  • Gitlab
    • 全球最大的开源代码托管平台,项目的所有代码都是开源的,便于在自己的服务器上完成 Gitlab的搭建。
  • Gerrit
    • 由 Google 开发的一个代码托管平台,Android 这个开源项目就托管在Gerrit 之上。

2. Git 的基本使用方式

2.1 Git 基本命令

image (3).png

2.2 常见问题

  1. 为什么我明明配置了Git 配置,但是依然没有办法拉取代码?
  2. 为什么我 Fetch 了远端分支,但是我看本地当前的分支历史还是没有变化?

2.3 Git 目录介绍

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

image.png

2.3.1 Git Config

不同级别的 Git 配置

image (4).png

每个级别的配置可能重复,但是低级别的配置会覆盖高级别的配置

2.3.2 常见 Git 配置

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

image.png

2.4 Git Remote

image.png

image.png

同一个 Origin 设置不同的 Push 和 Fetch URL

image (7).png

2.4.1 HTTP Remote

URL:github.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://{scheme}://{user}:${password}@github.com

2.4.2 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

image.png

2.5 Git Add

image.png

2.6 Git Commit

image.png

2.7 Objects

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

  • Blob
    • 存储文件的内容
  • Tree
    • 存储文件的目录信息
  • Commit
    • 存储提交信息,一个 Commit 可以对应唯一版本的代码

如何把这三个信息串联在一起呢?

image.png

image (8).png

2.8 Refs

image.png

  • Refs 文件存储的内容
    • refs 的内容就是对应的 Commit ID
    • 因此把 ref 当作指针,只想对应的 Commit 来表示当前 Ref 对应的版本 image (9).png
  • 不同种类的 ref
    • refs/heads 前缀表示的是分支,除此之外还有其他种类的 ref,比如 refs/tags 前缀表示的是标签

未完待续....