Git 的正确打开方式 | 青训营

98 阅读12分钟

学习Git后能收获什么?

  1. 学习基本的Git 命令了解其原理,遇到Git的相关问题时,能自行排查解决
  2. 学习研发流程中正确的流程和规范,正确使用Git

Git 是什么?

  Git是一种分布式版本控制系统,用于跟踪代码的修改、管理和协作开发。它可以记录文件的修改历史,并允许多人合作开发同一个项目,通过分支管理系统可以进行代码的并行开发和合并。Git具有快速、高效和灵活的特性,广泛应用于软件开发领域。

  介绍版本控制的发展历史,为什么会出现Git

  介绍Git 的发展历史?

  引用官方Git文档中的部分词.“version control system" 版本控制系统

  他是什么?记录一个或若干文件的变化,以便于在出错时可以及时的回滚,也方便于将来查询特定版本的修订情况

我们为什么要学习Git?

  1. 协同工作

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

  2. 开源社区

    目前大多数开源项目都是由Git维护的,参加这些项目开发需要使用Git

那么问题来了,我们怎么实现版本控制呢?

目前来说版本控制有三种方法,分别是

  1. 本地版本控制

    最初方式:

    本地复制文件夹,完成版本控制,通过不同的文件名来区分版本。当然这种最初的方式在现在的毕业论文当中

    • 毕业论文.doc
    • 毕业论文改1.doc
    • 毕业论文改2.doc
    • 毕业论文完成版.doc
    • 毕业论文最终版.doc
    • 毕业论文最最终版.doc
    • 毕业论文最终终极版.doc
    • 毕业论文绝对不改版1.doc
    • 毕业论文绝对不改版2.doc
    • 毕业论文打死不改版.doc
    • 遗书.doc

    这种便是很常见的本地版本控制,这种方法效果很明显,你做了多少个版本(doge,以及你入土的心路历程。

    好处就是这种方法简单快捷,无脑操作,备注可以直观体现在文件名上面。

    缺点也非常明显

    • 首先本地的版本控制只能保存在本地,无法进行多人的协作 (eg: 腾讯文档 飞书)使用场景特别局限
    • 特别容易犯错,要是不小心覆盖错了文件,没有任何后悔药可以食用
    • 如果项目文件特别大的时候,保存在本地的多个副本进行版本控制费时费力。

    这种方式的解决方案:开发了一些本地的版本控制软件——RCS,大多都是采用某种简单的数据库来记录文件的历次更新差异。

    原理:在硬盘上保存补丁集(补丁是指文件修订前后的变化);通过应用所有的补丁,可以重新计算出各个版本的文件内容。

  2. 集中式版本控制

    上面的例子大家已经熟悉了,这时候就有人提出解决办法,如果用一个远程服务器来保存所有人的文件不就可以了。因此集中版本控制便诞生而出

    • 代表性工具——SVN

    • 原理:

      1.提供一个远程的服务器来保存文件,所有用户的提交都保存到该服务器中

      2.对于不同用户提交的增量文件 Diff ,需要本地自行协商上传哪一份文件作为云服务器的存储版本

    • 优点:

      1.适用于一些游戏美术团队的素材,因为其支持二进制文件,对大文件的支持更好 2.学习简单,更易于操作。只要会上传文件就行。

    • 缺点:

      1.本地不存储版本管理的概念,所有提交只能连上服务器才能提交 2.分支的支持不够好,对于大型项目团队合作比较困难 3.用户本地不保存所有版本的代码,如果服务器发生故障容易导致历史版本的丢失

  3. 分布式版本控制

    • 代表性工具——Git

    • 原理:

      1.每个库都有完整提交历史 2.每次提交记录都是由完整的文件快照,而不是记录增量(不推荐提交大文件) 3.通过 Push 操作完成和远端代码的同步

    • 优点:

      1.分布式开发,每个库都是完整的提交历史,支持本地提交,强调个体 2.分支管理功能强大,方便团队合作,多人协同开发 3.效验和机制保证完整性,一般只添加数据,很少执行删除操作,不容易导致代码丢失

    • 缺点:

      1.相对于SVN更复杂,学习成本更高,命令操作更多 2.对于大文件的支持不佳,可通过 git-lfs​​​ 工具弥补这个功能

    • 与SVN的不同之处

image-20230812183757-omdf5p2.png

  1. Git 发展历史

    Linus Torvalds 同时也是 Linux 作者

    开发时间:只花了俩周时间

    基于 Git 的平台

    • Github 全球最大的代码托管平台,大部分的开源项目都可以放到这个平台
    • Gitlab 全球最大开源代码托管平台,定制化高,项目所有代码都是开源的,便于在自己的服务器上完成 Gitlab 的搭建
    • Gerrit 由 Google 开发的一个代码托管平台,主要对Android的开源项目支持较好-安卓多仓
  2. Git的基本使用方式

    在之前我们介绍了 GIt 的前世今生,现在我们需要了解 Git 的一些基本命令,才能更好的让 Git 为我们所用

    Mac 默认就可以直接使用 Win 安装 Gitbash

    分为三部分

    • 配置

      git config

      git remote

    • 提交代码

      git add

      git commit

    • 远端同步

      • 拉取代码

        clone

        pull

        fetch

      • 推送代码

        push

  3. 明明配置好 Git ,为什么还是拉取不了代码?

    没有配置密钥,无法拉取,配置权限

  4. Fetch 远端分支,为什么没有在本地历史中出现?

  5. Git 项目初始化

    mkdir study​​

    cd study​​ 进入 study 这个文件夹

    git init​​ 把这个目录变成git可以管理的仓库

    其他参数

    --initial-branch 初始化的分支

    --bare 创建一个罗仓库 (纯 Git 目录)

    --template 通过模板构建预先创建好的系统目录

    执行 tree <folder> /f​​ 命令查看文件夹及其内部文件情况 Git 目录

    卷 SYS 的文件夹 PATH 列表
    卷序列号为 D4D8-5401
    C:\USERS\xxx\DEMO\.GIT
    │  config /
    │  description
    │  HEAD
    │
    ├─hooks
    │      applypatch-msg.sample
    │      commit-msg.sample
    │      fsmonitor-watchman.sample
    │      post-update.sample
    │      pre-applypatch.sample
    │      pre-commit.sample
    │      pre-merge-commit.sample
    │      pre-push.sample
    │      pre-rebase.sample
    │      pre-receive.sample
    │      prepare-commit-msg.sample
    │      push-to-checkout.sample
    │      update.sample
    │
    ├─info
    │      exclude
    │
    ├─objects
    │  ├─info
    │  └─pack
    └─refs 
        ├─heads
        └─tags
    

    like this Windows下打开文件夹默认为空,不可见。

    Git config

    不同级别的 Git 配置

    --global

    --system

    --local

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

    常见的Git 配置

    在开始使用 Git 前,你需要自报家门,让别人知道你是谁,因此需要先进行用户名的配置

    用户名配置

    git config --global user.name "example"
    git config --global user.email name1@example.mail.com`
    

    Instead of 配置

    git config --global url.git@github.com:.insteadOf https://github.com​​ HTTP 和 SSH 协议之间的转换

    Git 命令别名的配置

    git cpmfig --global alias.cin "commit --amend --no-edit"​​

    这里的 alias​​ 可以简单理解为配置别名的缩写 使用了以上命令 即可使用 cin​​ 代替 commit --amend --no-edit​​

    Git Remote

    git remote -v​ 使用这个命令查看 Remote ,默认是没有的,需要我们自行配置

    我们需要添加 Remote ,可以使用 HTTP 或 SSH,用到这行命令 git remote add origin_http example.com​​ 之后再执行查看 Remote的命令就会发现多出了俩个值

    origin_http     example.com (fetch)
    origin_http     example.com (push)
    

    此时我们查看 .git 文件夹内的 config 文件,会发现结尾多出了刚才添加的 Remote 配置

    [remote "origin_http"]
    	url = example.com
    	fetch = +refs/heads/*:refs/remotes/origin_http/*
    

    如果不小心输入错误,我们可以在命令后添加 -h​​ 的参数,查看帮助命令,学习如果删除 Remote 即 git remote -h​​ ,受限于篇幅,不完整贴出运行结果

    同一个 Origin 设置 不同的 Push 和 Fetch URL ,例如我们 Fork 项目时 可能会用到

    HTTP Remote

    需要我们进行免密配置,以免每次登录都需要输入

    免密配置俩种方式

    1. 内存

    2. 硬盘

      将秘银信息存在指定的文件当中

    通常来说,不考虑采用这种方式来连接远端操作,不安全

    SSH Remote

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

    免密配置

    目前的Key 的类型有四种,分别是 dsa 、rsa、ecdsa、ed25519

    默认使用的时 rsa ,但是由于一些安全问题,现在已经不在推荐使用 dsa 和 rsa (部分 Windows 系统层面禁止使用) ,优先推荐使用 ed25519

    使用命令 ssh-keygen -t ed25519 -C "your_email@example.com"​​ 密钥默认存在 ~/.ssh/id_ed25519.pub

    在运行命令时会出现以下信息 Enter file in which to save the key (C:\Users\xxx/.ssh/id_ed25519):​​ 直接 Enter 即可 这里的目录也是上面 ~ 省略的上级文件夹

    Overwrite(y/n)?​​ 直接 输入 y 后回车 打开系统中 .pub​​ 后缀的公钥文件,将里面的内容复制到代码托管平台 SSH配置部分即可

  6. Git Add

    首先,我们要知道 git add​ 的命令目的是将文件作出的修改从工作区添加到暂存区

    使用 git add .​ 命令可以通配添加所有修改变化,正常格式为 git add 单个文件名|通配符

    git cat-file -p <object>​​ 即可查看object 目录内包含的加密文件信息 先执行 tree​​ 命令查看所有文件夹内文件

    需要注意!

    • 命令里 <object>​​ 由 文件夹名 + 文件名组成

      eg:以下是 tree​​ 命令执行后的部分结果, 根据执行结果这里的<object>​​ 实际是 012a517ca74b3dc7a35ca7c70a782138840d0469

      │├─objects
      │  ├─01
      │  │      2a517ca74b3dc7a35ca7c70a782138840d0469
      
    • 知道了object后便可以使用 cat-file​​ 来查看加密后的文件了,组合成完整命令便可以查看

    • 如果在执行时出现以下类似的错误,可能不只限定于 git add​​ 命令报错。

      fatal: not a git repository (or any of the parent directories): .git
      

      如有这样的提示,代表你可能进入到了一个错误的文件夹,其文件夹内没有 .git​​ 子文件夹,使用 cd​​ 命令进入到当初使用 git init​​的文件夹即可。

  7. Git status

    使用 git status​ 命令查看 Git 状态 可能输出以下结果,代表没有任何文件需要提交

    说明我们在最近一次提交之后,没有做任何改动,是一个 "working tree clean",翻译过来就是干净的工作目录。

    On branch test #test为你所在分支的名称,一般为master
    nothing to commit, working tree clean
    
  8. Git commit

    聊完了 Git add 我们就要知道 Git commit 实际上就是让处于暂存区的修改真正的提交到本地仓库中

    通常我们习惯于使用 git commit -m "your text"​​ 来提交,"your text"​​ 可以填写你对这一版本的注释,每提交一次就是完成了一次的版本管理

    如果你没有在commit 命令后 -m <comment>​​ 选项,Git 会尝试为你打开一个编辑器以填写提交信息。 如果 Git 在你对它的配置中找不到相关信息,默认会打开 vim。屏幕中会出现以下输出信息:

    # Please enter the commit message for your changes. Lines starting
    # with '#' will be ignored, and an empty message aborts the commit.
    # On branch master
    # Changes to be committed:
    #   (use "git reset HEAD <file>..." to unstage)
    #
    # modified:   hello.php
    #
    ~
    ~
    ".git/COMMIT_EDITMSG" 9L, 257C
    

    PS:此时的界面 为 Vim 编辑器 可直接在开头加上本次commit 的备注,:wq​ 即可保存配置并退出

  • 当然你也可以使用 git commit -m "your text"​​ 来提交,通常会输出类似下图的信息 第二行输出多少文件改变,并给出具体的文件修改树

    [master 258742d] add file
     6 files changed, 217 insertions(+)
     create mode 100644 wwwroot/Program.cs
     create mode 100644 wwwroot/Startup.cs
     create mode 100644 wwwroot/WeatherForecast.cs
     create mode 100644 wwwroot/appsettings.json
     create mode 100644 wwwroot/redme.txt
     create mode 100644 wwwroot/tools.getquicker.cn.csproj
    
  1. git log

    git log​ 可以查看 commit​ 的记录

    commit 258742d75cc3f748bb4042e8afd87c74ed1af040 (HEAD -> master)
    Author: Petercode <Petercode1129@gmail.com>
    Date:   Sat Aug 12 17:51:10 2023 +0800
    
        add file
    
    commit 5967d5b954e59163b0f3828b685ed196d4e86d26
    Author: Petercode <Petercode1129@gmail.com>
    Date:   Mon Aug 7 23:25:20 2023 +0800
    
        nice try
        fatal: Not a valid object name
    

Objects

  commit / tree / blob 在git里面都统一称为 Object

  1. 通过commit 寻找到 Tree 信息,每个 Commit 都会存储到对应的 tree id
  2. 通过tree 存储的信息,获取到对应的目录树信息
  3. 从tree中获得 blob id 通过blob id 获取对应的文件内容

Refs

  运行 tree​ 命令以下为截取的refs文件夹内的文件情况

└─refs
    ├─heads
    │      master
    │
    └─tags

  我们使用 git checkout -b test​ 创建一个 test 的分支,再次使用 tree​ 命令

└─refs
    ├─heads
    │      master
    │      test
    │
    └─tags

  Refs 文件中存储的内容 就是对应 的 Commit ID

  因此把 ref 当作指针,指向对应的 commit 来表示对应的 Ref 版本。

  而不同种类的 ref refs / heads 前缀表示的是分支,除此之外还有其他种类的 ref