Git 的正确使用姿势 | 青训营笔记

154 阅读6分钟

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

本文主要介绍了Git的类型和由来发展,主要介绍了git中常用的命令及其使用的方式,并对git目录里的refs,config,objects进行了详细的介绍,对理解git的本质有一定的帮助

Git 是什么

版本控制

版本控制即一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统;协助开发者更好的关注变更,了解每个版本的改动,方便对改动的代码进行检查,预防事故发送;也能随时切换到不同的版本,回滚误删误改的问题代码

本地版本控制

  • 依托于本地磁盘进行版本控制(RCS) 集中式版本控制
  • 存在一个统一的远端服务器,用于版本控制,本地不存储版本控制(SVN) 分布式版本控制
  • 每个库都拥有所有的版本控制信息,远端服务器用于不同库之间进行版本信息同步(Git)

发展历史

最初版由 Liunx 创始人 Linus Torvalds 花两周时间开发而成,主要是为了用于 Linux 项目的维护

衍生平台

除此之外,还有 bitbucket, Coding, 码云 等一系列平台

Git 命令基本使用方式和原理

项目初始化

git init

  • --inital-branch 初始化的分支
  • --bare 创建一个裸仓库(纯git目录,没有工作目录)
  • --template 可以通过模板来创建预先构建好的自定义git目录

image.png

  • HEAD:表示所指向的当前目录
  • config:当前目录的配置
  • objects:相关文件信息
  • refs:分支信息

工作区和暂存区

image.png

Git 配置

Git Config

Git 配置,分成global,system,local三个级别的基本配置,每个级别的配置可能重复,但低级别的配置会覆盖高级别的配置

image.png

  • 用户名配置
git config --global user.name "xxx"
git config --global user.email "xxx@xxx.com"
  • Instead of 配置(替换源类型:ssh转https等)
git config --global url.git@github.com:.insteadOf https://github.com
  • Git命令别名配置
git config --global alias.cin "commit -- amend --no-edit"

Git Remote

Git Remote 配置,分成 SSH 和 HTTP 两种协议实现,不同协议有不同的免密配置方式

  • 查看remote
git remote -v
  • 添加remote
git remote add origin_ssh git@github.com:git/git.git
git remote add origin_http https://github.com/git/git.git
  • 同一个origin设置不同的Push和Fetch URL
git add origin git@github.com:git/git
git remote set-url --add --push origin git@github.com:MY_REPOSITY/git

image.png

HTTP Remote
  • 免密配置 内存:git config --global credential.helper 'cache --timeout=3600'

硬盘:git config --global credential.helper 'store --file /path/to/credential-file' (不指定目录的情况默认是~/.git-credential)

将密钥信息存在指定文件中,具体格式为:${scheme}://${user}:${password}@github.com

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

生成后读取公钥便可在GitHub等仓库上进行配置处理

代码提交

  • Git Add 将代码从工作区提交到暂存区
  • Git Commit 将暂存区代码提交到 Git 存储,commit后会生成后续的commit object
  • 追溯历史版本 可以通过git log查看最新的commit id image.png
  • 修改历史版本
    1. commit --amend 通过这个命令可以修改最近的一次 commit 信息,修改之后 commit id 会变
    2. rebase 通过 git rebase -i HEAD~3 可以实现对最近三个 commit 的修改:
      1. 合并 commit
      2. 修改具体的 commit message
      3. 删除某个 commit
    3. filter --branch 该命令可以指定删除所有提交中的某个文件或者全局修改邮箱地址等操作

Git 存储基本概念

完整Git视图

image.png

Ref

Ref内容

Ref文件存储的内容就是对应的Commit ID,因此把ref当作指针,指向对应的Commit id就是当前Ref对应的版本 image.png

Ref种类

refs/heads前缀表示的是分支,除此之外还有其他种类的ref,比如refs/tags前缀表示的是标签

  • Branch 仓库分支 git checkout -b 可以创建一个新分支,分支一般用于开发阶段,是可以不断添加Commit进行迭代
  • Tag 仓库标签 通过git tag命令生成tag,标签一般表示的是一个稳定版本,指向的Commit一般不会变更

通过git tag -a v.xxx -m "add feature"新建附注标签,此时会新建tag类型的object

Object

commit、tree、blob在git中都统一称为object,除此之外还有个tag的object

  • Blob 存储文件内容信息
  • Tree 存储目录树信息
  • Commit 存储提交信息,一个commit可以对应唯一版本的代码
  • Tag 存储附注标签信息
commit、tree、blob关联

当进行commit处理的时候,会在objects文件夹中生成对应commit、tree、blob对象 image.png

Git GC

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

代码同步

  • Git Clone 将代码从远端拉取到本地,可以指定分支和深度

  • Git Fetch 将远端某些分支最新代码拉取到本地,不会执行merge操作,会修改refs/remote内的分支信息,如果需要和本地代码合并需要手动操作

  • Git Pull 将远端仓库代码同步到本地仓库,并和本地代码进行合并,操作等同于git fetch + git merge,也可以通过git pull --rebase完成git fetch + git rebase操作。可能存在冲突,需要解决冲突

  • Git Push 将本地代码同步到远端仓库,一般使用git push origin master命令即可完成

冲突问题:

  1. 如果本地的 commit 记录和远端的 commit 历史不一致,则会产生冲突,比如 git commit --amend or gitrebase 都有可能导致这个问题。
  2. 如果该分支就自己一个人使用,或者团队内确认过可以修改历史则可以通过 git push origin master -f 来完成强制推送,一般不推荐主干分支进行该操作,正常都应该解决冲突后再进行推送。
  • Git Merge
  1. Fast-Forward:不会产生以恶搞merge节点,合并后保持一个线性历史,如果target分支有了更新,则需要通过rebase操作更新source branch后才可以合入
  • 命令:git merge 目标分支 --ff-only image.png
  1. Three-Way Merge:三方合并,会产生一个新的merge节点
  • 命令: git merge 目标分支 --no-ff

image.png