Lazy loaded image
学习笔记
📑Git 使用指北
字数 7913阅读时长 20 分钟
2022-3-2
2026-1-7
type
status
date
slug
summary
tags
category
icon
password
😀
前言: 这是一篇学习笔记,记录Git的基本使用
 
notion image

一、Git 基础

0. 准备

安装zsh(辅助工具)
安装zsh的目的是为了后面安装oh-my-zsh,非必须
安装 oh-my-zsh(辅助工具)
oh-my-zsh是zsh的一个主题,可以在我们输入Git命令时更好的提示 ,非必须

1. Git 基础配置

1. Git配置

安装完Git后还不能立即使用,必须得给它必要的配置。Git 提供了一个叫做 git config 的工具,专门用来配置或读取相应的工作环境变量。
这些环境变量,决定了 Git 在各个环节的具体工作方式和行为。这些变量可以存放在以下三个不同的地方:
  • /etc/gitconfig 文件:系统中对所有用户都普遍适用的配置。若使用 git config 时用 -system 选项,读写的就是这个文件。
  • ~/.gitconfig 文件:用户目录下的配置文件只适用于该用户。若使用 git config 时用 -global 选项,读写的就是这个文件。
  • 当前项目的 Git 目录中的配置文件(也就是工作目录中的 .git/config 文件):这里的配置仅仅针对当前项目有效。每一个级别的配置都会覆盖上层的相同配置,所以 .git/config 里的配置会覆盖 /etc/gitconfig 中的同名变量。
优先级顺序:当前项目的Git 目录中的配置文件 > global > system
用户信息
查看配置信息
有时候会看到重复的变量名,那就说明它们来自不同的配置文件(比如 /etc/gitconfig 和~/.gitconfig),不过最终 Git 实际采用的是最后一个。
修改配置信息
在配置中如果不小心配置错了,不能通过重复执行上面的设置昵称命令,来修改昵称,邮件修改也是同理,它会在命令执行后提示你无法重复配置,所以你需要用特定的方式去修改
  1. 命令行修改配置
  1. 修改配置文件
    1. Linux中,通过vim命令编辑~/.gitconfig。windows系统,假设当前用户是administrator,那么对应的配置文件路径应该是c:\Users\administrator\.gitconfig

2. 创建版本库

创建版本库有两种办法:
  1. git init:初始化一个版本库
  1. git clone:克隆一个已有的版本库
使用git init命令可以在本地初始化一个版本库,也就是会在当前目录下创建一个.git的文件夹,我们可以用ls -al进行查看
认识.git
在生成的.git目录中,里面包含了整个版本库的信息
  • HEAD 文件指示目前被检出的分支
  • branches 新版本已经废弃无须理会
  • description 用来显示对仓库的描述信息
  • config 文件包含项目特有的配置选项
  • info 目录包含一个全局性排除文件
  • hooks 目录包含客户端或服务端的钩子脚本
  • index 文件保存暂存区信息
  • objects 目录存储所有数据内容
  • refs 目录存储分支的提交对象的指针

3. Git工作流程

  • 克隆Git资源作为工作目录
  • 在克隆的资源上添加或修改文件
  • 如果其他人修改了,你可以更新资源
  • 在提交前查看修改
  • 提交修改
  • 在修改完成后,如果发现错误,可以撤回提交并再次修改并提交
 
notion image
 
获取远程仓库- HTTP
用上述方式拉取代码,每次都需要输入Git认证信息,我们可以设置永久记住密码
命令执行完后,会在当前用户主目录的.gitconfig文件中新增一项配置
如果没有 --global,则会在当前项目下的.git/config 文件增加配置
获取远程仓库- SSH
直接拉取会失败,因为没有配置公钥和私钥
  1. 在本地创建一个ssh key
    1. ssh-key
      直接回车后可以看到在当前用户目录下生成公钥和私钥,查看生成的公钥cat ~/.ssh/id_rsa.pub
  1. 添加公钥到服务器
更新代码
一个远程仓库可能有多人有权限推送,所以存在远程代码比你本地仓库更新,因此在提交代码之前需要先拉取服务器代码,让本地仓库保持最新的版本记录,这样做的目的是为了防止你提交代码之后 ,推送到远端出现代码冲突问题。
检查改动文件
在Git中文件有下面这几种状态:
  • Untracked:未跟踪的,新增的文件,此文件在文件夹中,但是并没有加入到Git库,不参与版本控制,通过git add后状态变为Staged
  • Modified:文件已修改
  • Deleted:文件已删除,本地删除,服务器上还没删除
  • Renamed:文件名称被改变

4. 回滚变更

如果发现你无意中编辑了一个文件,但是实际上并不想改变它,可以使用git checkout 文件名来撤销更改
将工作区指定文件的内容恢复到暂存区的状态(IDE的回滚操作)
将文件添加到暂存区
提交代码
当你将所需要提交的代码都添加到缓存区后,接下来就可以将代码提交到本地仓库中
推送代码

二、忽略

1. 忽略文件权限

Git会记录文件的权限信息,两个地方的文件权限不一样,很可能会导致代码冲突问题。
解决办法
可以查看.git/config,在配置文件中,可以看到fileMode false

2. 忽略指定文件或目录

很多时候,例如.idea.DS_Store这样的文件夹,并不是我们手动新增加的,而是程序自动产生的,这种文件对项目没有实际上的意义;还可能导致团队协作中让两人的代码冲突,如果删掉这种文件也没有什么用,过不了多久程序又会自动产生,所以最好的办法是让git对他视而不见。
解决方案
Git工作区的根目录下创建一个.gitignore文件,把想忽略的文件名或目录放进去,Git就会自动忽略这些文件
  • 检查忽略,假如设置的忽略规则太宽松或者.gitignore写得有问题,导致某个文件需要被跟踪,但是被忽略,需要找出到底那个规则写错了,可以用git check-ignore命令检查:git check-ignore -v 文件名
  • 除了修改.gitignore文件的规则之外,还可以使用强制添加的方式:git add -f .DS_Store
  • 如果意外将想要忽略的文件添加到缓存中去了,可以使用rm命令将其从中移除(工作目录中还在):

    3. 反向忽略规则

    • 假设已经设置忽略 test 文件夹以及下面的文件, 但是我们希望依然使用test/main.go文件,所以就需要设置反向排除
    • 编辑.gitignore文件,!/test/main.go
    git对于.ignore配置文件是按行从上到下进行规则匹配的,意味着如果前面的规则匹配的范围更大,则后面的规则将不会生效; 如果你不慎在创建.gitignore文件之前就push了项目,那么即使你在.gitignore文件中写入新的过滤规则,这些规则也不会起作用,Git仍然会对所有文件进行版本管理。简单来说出现这种问题的原因就是Git已经开始管理这些文件了,所以你无法再通过过滤规则过滤它们。所以大家一定要养成在项目开始就创建.gitignore文件的习惯,否则一旦push,处理起来会非常麻烦。

    4. 忽略已提交的文件

    假如在之前的提交中没有将 .idea目录添加到 .gitignore文件中,并且把.idea目录提交上去了。那后面再在.gitignore文件中添加.idea目录是不会让提交列表中的.idea目录小时的,我们需要命令删除暂存区的.idea目录
    总结:
    想要忽略某些文件时,可以在git工作目录中编辑.gitignore文件规则,.gitignore文件本身也要放到版本库中,并且对.gitignore做版本管理:
    1. 忽略操作系统自动生成的文件,比如缩略图
    1. 忽略编译生成的中间文件、可执行程序以及编辑器自动生成的文件
    1. 忽略带有敏感信息的配置文件,比如存放口令的配置文件

    三、分支管理

    1. 查看分支

    查看本地分支

    2. 新建分支

    导入远端分支:远端已经有的分支,需要把它在本地也同样创建一份
    • 在执行前,需要确保这个分支在远程或者本地已经存在
    新建本地分支:新建一个远端和本地都不存在的分支
    本地分支第一次提交:本地创建成功后,远端还不存在这个分支。所以你此时如果使用git push是不能直接推送的,需要在第一次推送的时候指定远程分支:
    一般都是在 gitlab 仓库上根据已有分支创建出新的分支,然后在本地拉取创建的新分支

    3. 合并分支

    假设我们现在有三个分支:master生成环境、develop开发环境、test bug修复分支。现在我们在test分支中修复了BUG,需要发布到线上生产服务器上,那么我们可以通过合并分支的方式将test分支的代码合并到master分支上。

    4. 删除分支

    清理远程分支

    我们删除分支实际上只是在本地将分支删除,但远程分支依然会存在,我们可以用以下命令删除远程分支:
    强制删除 极少数情况会遇到普通删除无法将分支删除的情况,这时使用强制删除

    清理本地分支

    5. 实际使用(重要)

    开发合并

    在 gitlab 仓库中根据已有的分支(通常是master)创建出新的分支,假设是venture,本地checkout venture 分支
    然后你在你的个人分支上开发、测试完成后,需要合并master,这时你最好在你本地先合并一下master,直接推送提交PR合并很可能会有冲突

    合并代码保留提交记录:rebase功能使用

    5.1 git merger

    git merge。在 Git 中合并两个分支时会产生一个特殊的提交记录,它有两个 parent 节点。翻译成自然语言相当于:“我要把这两个 parent 节点本身及它们所有的祖先都包含进来。”
     
    notion image
     
    将bugFix分支的提交记录合并到main:git merge bugFix
     
    notion image
     
    把main分支合并到bugFix:git checkout bugFix && git merge main
     
    notion image
     

    5.2 git rebase

    rebase 的意思是变基,你现在dev分支,使用命令 git rebase master,意思就是你要把dev分支上一系列提交记录复制到 master分支上
    • git rebase 实际上就是取出一系列的提交记录,“复制”它们,然后在另外一个地方逐个的放下去。
    • git rebase的优势就是可以创造更线性的提交历史,这听上去有些难以理解。如果只允许使用 git rebase 的话,代码库的提交历史将会变得异常清晰。
     
    notion image
     
     
    notion image
     
    更新main分支:git checkout main && git rebase bugFix
     
    notion image
     
    参考阅读:

    临时保存

    如果你在开发过程中有紧急的线上bug需要修复,可以临时保存一下变更:git stash
    git stash 可以临时保存当前工作目录的修改,以便你可以切换到其他分支或执行其他操作,而不必提交这些更改。以下是 git stash 的基本用法和常见选项:
    基本用法
    1. 保存当前更改
      1. 使用 git stash push 来保存当前的修改(未提交的更改和暂存的更改)。
        或者,可以只使用:
    1. 查看存储的更改
      1. 使用 git stash list 查看所有存储的 stash 条目。
        输出示例:
    1. 应用存储的更改
      1. 使用 git stash apply 来应用最新的 stash 条目,但不会删除它。
        如果想应用特定的 stash,可以指定其名称:
    1. 弹出存储的更改
      1. 使用 git stash pop 来应用最新的 stash 条目,并将其从 stash 列表中删除。
    1. 删除存储的更改
      1. 如果你不再需要某个 stash,可以使用 git stash drop 删除它。
        要清空所有的 stash,可以使用:
    1. 存储未跟踪的文件
      1. 默认情况下,git stash 不会存储未跟踪的文件。要包含这些文件,可以使用 -u--include-untracked
    示例流程
    1. 修改文件并保存到 stash
      1. 检查 stash 列表
        1. 应用最后一次的 stash
          1. 如果需要,删除 stash

            四、撤销提交:reset

            有时候我们用git commit 提交代码后发现这次提交的内容是错误的,需要将代码复原:
            1. 将代码错误内容修改正常,然后重新commit 提交一次;
            1. 使用 git reset命令撤销上一次错误的commit 记录

            1. 覆盖代码

            将错误的代码修改后,重新commit提交一次,这样做可以达到最终修改错误的目的,但是这整个过程是比较繁琐的,并且会多出一些没有意义的 commit 记录。

            2. 回滚记录

            • git reset: 用于回退版本,可以指定退回某一次提交版本
            • -mixed 为默认,可以不用带该参数,用于重置暂存区的文件与上一次的提交(commit)保持一致,工作区文件内容保持不变。
            • -hard 参数撤销工作区中所有未提交的修改内容,将暂存区与工作区都回到上一次版本,并删除之前的所有信息提交

            HEAD说明:

            3. 场景复现

            只在本地提交,还未提交到远程服务器

            错误提交已经push到远端仓库

            不小心把错误代码提交到远程仓库,这时想把错误代码撤销有两种办法:
            1. 代码层覆盖:修改错误代码,重新提交
            1. 记录覆盖:使用reset 命令恢复到上一个版本,然后重新提交,默认情况下 Git 会拒绝你的提交,因为提交的版本号比远程仓库的落后,所以需要用上强制提交
            使用第一种办法会显示错误的提交记录,假如是敏感信息不小心提交上去,第一种办法必然会泄露

            五、远端覆盖本地:fetch

            1. 覆盖本地

            • 首先拉取远端最新的代码,这里不适用 git pull而适用git fetch,因为git pull拉取远程最新分支之后,会自动对本地分支进行合并,而git fetch只会拉取远程分支不进行自动合并
            小结:
            1. 使用 git fetch 拉取远程仓库信息(不会自动进行合并);
            1. 使用 git reset --hard origin/分支名 命令将远程仓库完全覆盖本地仓库。

            六、客户端Hook使用

            有些时候,我们想在提交版本时候触发一些事件,触发事件的这个动作我们称之为钩子(hook)。 在 Git 中有两种类型的钩子,分别是客户端的和服务器端的。 客户端钩子主要是提交和合并这些的操作所调用(代码格式化、代码质量检测),服务器端钩子主要是在接收被推送的提交这样的操作(CICD)。

            1. 认识钩子

            Git 客户端钩子存储在 .git/hooks目录中,在你初始化一个 Git 仓库时这个目录就会产生,同时还会往里面放一些示例脚本,脚本都是以.sample结尾
            钩子只要是命名正确的可执行脚本都可以使用,所以我们可以用shell写脚本,也可以用Python写脚本

            2. 钩子触发

            钩子名字
            触发时间
            pre-commit
            执行 git commit 命令完成前被执行。
            prepare-commit-msg
            在执行完 pre-commit 钩子之后被调用。
            commit-msg
            git commit 执行完成后被调用。
            post-commit
            post-commit 钩子在 commit-msg 钩子之后立即被运行 。
            post-checkout
            post-checkout 钩子在使用 git checkout 命令时候会被调用。
            pre-rebase
            pre-rebase 钩子在使用 git rebase 命令发生更改之前运行
            pre-receive
            pre-receive 钩子在有人用 git push 向仓库推送代码时被执行。
            update
            update 钩子在 pre-receive 之后被调用,分别被每个推送上来的引用分别调用。
            post-receive
            在成功推送后被调用,适合用于发送通知。

            3. 钩子实验

            把一个正确命令且可执行的文件放在 Git 目录下的hooks子目录中即可。
            我们选择 pre-commit 进行测试,它会在 git commit时被触发

            4. 应用场景

            • 代码格式化:多人开发,每个人提交的代码风格可能存在差异,我们可以用Git 钩子作为辅助,当我们提交版本时,都会自动检测我们代码风格

            七、服务端Hook使用

            服务端的Hook同样存放在.git目录下,不过是放在服务端的.git目录下,钩子文件名称也有相对应的文件名,但是不需要记,我们平时使用服务端钩子基本不会通过文件名去找对应的钩子。
            我们使用服务端钩子通常是在web页面中设置。

            1. 设置钩子事件

            需要一个代码仓库,可以是码云,也可以是自己搭建的GitLab
            • 以码云为例,找到仓库的 管理 -> WebHooks -> 增加 页面,然后将我们的URL地址准备好久可以了。
            • 当我们使用git push命令推送代码到码云,码云接收成功后会调用我们此URL地址,并将事件的参数传递到设置的URL。
            • 这个URL地址是可以访问的,后端使用哪种语言都可以,只要能接受参数并执行代码即可,我们的钩子操作在这份代码里实现。

            2. 使用钩子

            准备:
            • Code:写代码的服务器,用于开发代码
            • Gitee:远端代码仓库
            • Hook:钩子服务器,用于验证CI流程的机器
            1. 在Hook服务上clone仓库代码,Hook服务器要有操作Git权限
            1. Code提交代码
            1. Gitee触发WebHook,向订阅的URL发送请求和事件
            1. Hook接收到请求,触发编译脚本,从Gitee拉取最新的代码,编译

            八、服务端Hook使用

            服务端的Hook同样存放在.git目录下,不过是放在服务端的.git目录下,钩子文件名称也有相对应的文件名,但是不需要记,我们平时使用服务端钩子基本不会通过文件名去找对应的钩子。
            我们使用服务端钩子通常是在web页面中设置。

            1. 设置钩子事件

            需要一个代码仓库,可以是码云,也可以是自己搭建的GitLab
            • 以码云为例,找到仓库的 管理 -> WebHooks -> 增加 页面,然后将我们的URL地址准备好久可以了。
            • 当我们使用git push命令推送代码到码云,码云接收成功后会调用我们此URL地址,并将事件的参数传递到设置的URL。
            • 这个URL地址是可以访问的,后端使用哪种语言都可以,只要能接受参数并执行代码即可,我们的钩子操作在这份代码里实现。

            2. 使用钩子

            准备:
            • Code:写代码的服务器,用于开发代码
            • Gitee:远端代码仓库
            • Hook:钩子服务器,用于验证CI流程的机器
            1. 在Hook服务上clone仓库代码,Hook服务器要有操作Git权限
            1. Code提交代码
            1. Gitee触发WebHook,向订阅的URL发送请求和事件
            1. Hook接收到请求,触发编译脚本,从Gitee拉取最新的代码,编译

            九、Git仓库瘦身

            Git 仓库使用久了之后会发现响应会越来越慢,占用的存储空间也会越来越大,出现这些问题的原因是因为 Git 会将我们代码的所有历史版本都会存储起来,当我们代码迭代了上千个版本之后就会占用很大的空间。
            为了让 Git 的响应速度能够快点,我们可以通过一些方式减少 Git 仓库的存储空间,主要有三种方法,分别是:
            • 克隆最后一个版本
            • 清空版本记录
            • 清理大文件

            1. 克隆最后一个版本

            我们在克隆一个使用了很久的 Git 仓库时候可能会发现耗费时间非常长,这是因为 Git 会拉取所有的历史版本导致,我们如果想让 Git 在克隆代码的时候快一些,可以在 git clone 命令行后面加 --depth=1 参数,这样 Git 在克隆代码时候只会克隆最后一个版本的内容,这里我执行命令如下所示:

            2. 清理版本记录

            上面一个例子只能解决本地仓库的占用大小,但是服务端依然保存了所以的版本记录,如果想把远程的仓库也进行清理,可以看看下面的方法。

            3. 清理大文件

            可以通过清理版本库来减少 Git 存储的空间,但有时候我们需要保留历史版本记录,但又想减少 Git 存储空间,这个时候我们就可以考虑清理一些大文件。
            使用 git branch-filter 可以遍历 Git 的版本历史信息,然后从历史版本信息中删除大文件,最终 Git 仓库空间减少,在下面的命令中会涉及到很多 Linux 命令,这些命令我们不用细究,按照步骤执行即可。
             
            注:
            第二和第三都会对远端仓库造成不可逆的修改,慎重
             
             
            💡
            有关Notion安装或者使用上的问题,欢迎您在底部评论区留言,一起交流~
            上一篇
            1、Redis基本特性
            下一篇
            Makefile 学习笔记