前端规范工程-5:Git提交信息规范(commitlint + czg)

news2024/11/27 12:55:09

前面讲的都是在git提交之前的一些检查流程,然而我们git提交信息的时候,也应该是需要规范的。直接进入主题:

目录

    • 需安装插件清单
    • `commitlint` 介绍
    • 安装
    • 配置
    • 配置`commit-msg`钩子
    • 提交填写`commit`信息
    • czg
    • 后续
      • 方式一:push触动build并上传到ftp服务
      • 方案二:push触发CI/CD工作流

需安装插件清单

依赖描述
@commitlint/cligit提交规范检验工具,对提交信息的 message 规范进行校验
@commitlint/config-conventional基于 conventional commits 规范的配置文件
czg交互式命令行工具生成标准化的 git commit message

commitlint 介绍

在使用Git提交代码时,通常都需要填写提交说明,也就是Commit Message

git commit -m '提交测试'

说白了,Commit Message就是我们提交的时候,在-m后面写的提交说明,在小项目中基本是随意去写这个message的,但是当项目到了一定规模,什么东西都需要形成规范,包括这个提交Message,不然协同开发的同事根本不知道你这次提交到底是在干嘛,只能通过点开Git Graph查看明细,或口头阐述给对方。

当然,仅仅只是口头约束并没有实质上的作用,为了禁止不符合规范的Commit Message的提交,我们就需要采用一些工具,只有当开发者编写了符合规范的Commit Message才能够进行commit。而commitlint就是这样一种工具,通过结合husky一起使用,可以在开发者进行commit前就对Commit Message进行检查,只有符合规范,才能够进行commit

上面我们提到过,git最常用的钩子函数有两个,一个是pre-commit,前面我们已经对这个阶段需要做的规范做了介绍,并且还使用了lint-staged工具。另外一个常用的钩子函数就是commit-msg,在这个阶段,用到的工具就是commitlint

安装

需要下载两个依赖包:

pnpm add @commitlint/cli @commitlint/config-conventional -D

注意:现阶段由于stylelint版本的问题,可能会和之前的一些包产生冲突,如果你用的是npm,这里还是直接使用--legacy-peer-deps忽略到依赖冲突,后面的一些安装都有可能造成这个问题,就不再重复了。

通过 npm 安装时添加 --legacy-peer-deps 注意事项

在使用 npm 安装包时,--legacy-peer-deps 参数的作用是告诉 npm 在处理依赖关系时采用旧的(legacy)方式,而不是严格按照 npm 7 及更新版本的新规则来处理对等依赖(peer dependencies)。

从 npm 7 开始,npm 引入了一些更严格的对等依赖解析规则。这些规则要求依赖包必须显式地声明其对其他包的对等依赖,否则 npm 会给出警告或错误,并且可能会拒绝安装或更新这些依赖。

使用 --legacy-peer-deps 参数可以绕过这些新规则,采用更宽松的对等依赖解析方式,允许安装那些在新规则下可能会被拒绝的依赖。

假设你要安装一个依赖包 example-package,并且你知道这个包的依赖可能会与新的 npm 对等依赖规则冲突。你可以这样使用 --legacy-peer-deps

npm install @commitlint/cli @commitlint/config-conventional -D --legacy-peer-deps

这样 npm 将会使用旧的对等依赖解析方式来安装 example-package 及其依赖,而不会严格遵循 npm 7 的新规则。

注意了,使用 --legacy-peer-deps 应谨慎,因为它可能会导致依赖安装时出现不一致或错误的情况。只有在你确信使用旧规则不会影响项目稳定性或安全性时才应该使用这个参数。

依赖说明

依赖描述说明
@commitlint/config-conventional基于 conventional commits 规范的配置文件
@commitlint/clicommitlint 工具的核心

配置

具体的规范配置可以查看: conventional-changelog/commitlint

在项目根目录下创建配置文件 commitlint.config.cjs

# 使用命令行创建文件
echo "module.exports = { extends: ['@commitlint/config-conventional'] };" > commitlint.config.cjs

commitlint.config.cjs 内容:

module.exports = { extends: ['@commitlint/config-conventional'] };

以下是我经常使用的type-enum,这里定义的Commit Message就是继承了@commitlint/config-conventional规则集,这个规则集定义了Git 提交信息定义一致性格式,使得提交信息更易于理解和自动化处理。

feat:     新增功能
fix:      修复缺陷
docs:     文档变更
style:    代码格式
refactor: 代码重构
perf:     性能优化
test:     添加测试
build:    构建相关
ci:       持续集成修改
revert:   回滚到上一个版本
wip:      开发中
chore:    构建过程或辅助工具的变动

配置commit-msg钩子

上面的commitlint配置好之后,我们还需要commit-msg钩子函数触发

# V9
echo "npx --no-install commitlint --edit $1" > .husky/commit-msg

提交填写commit信息

现在我们提交的时候,就不需要再写git commit -m "提交测试"这种简单的message信息了。我们只需要执行git commit,钩子函数会自动帮我们弹出一个Vim风格的文本输入框。

Vim 是一款经典的文本编辑器,它拥有强大的编辑和操作功能,以下是一些常用的 Vim 风格操作:

  • i 进入插入模式,可以开始编辑文本。
  • Esc 退出插入模式,回到命令模式。
  • :wq 保存并退出编辑器。
  • :q! 放弃修改并退出编辑器。
  • dd 删除当前行。
  • yy 复制当前行。
  • p 粘贴复制的内容。

Vim文本编辑器,需要填写按规范提交。符合规范的Commit Message的提交格式如下,包含了页眉(header), 正文(body)页脚(footer) 三部分。其中,header是必须的,bodyfooter可以忽略。

type([scope]): subject
// 空一行
[body]
// 空一行
[footer]

在这里插入图片描述

需要注意的是,在commitlint.config.cjs配置了哪些类型,Commit Message时候type就只能哪些类型,想要更多的type类型,可以继承extends其他的规范集,或者自己写。

czg

上面Vim模式,这种需要开发者一个个输入commit信息的形式很容易出现问题,因此czg CLI做的事情很简单,就是帮我们提供了一个交互式撰写commit信息的插件。

  • 为什么选择czg CLI

    • 我们先来讲讲他的历史迭代。在czg还没问世之前,他的前身是Commitizen CLI + cz-git。然而cz-git一直以来都是作为Commitizen CLI的适配器,作者Q.Ben就是为了解决这种强依赖关系,所以开发了czg。这里简单的理解就是czg CLI = (Commitizen CLI + cz-git)
  • 特性优点

    • 🤖 OpenAI 支持. 让 AI 来辅助生成你 git commit 的描述信息

    • ⚡️ 轻量级 :零依赖项 (1.31MB)。

    • 🤗 简单且快速 : 无需前置配置,无需适配器,没有额外的步骤,你可以使用 npx | npm 脚本 | 全局下载... 在你的任何项目中快速启动。

    • 😎 高度可定制化 : 内部包含 cz-git 的核心,继承了 cz-git 的所有特性,具有相同的行为,配置加载… 你可以根据自己的需要配置的 CLI 的行为。

  • 在过去

    • 使用cz-git的安装使用流程
      npm install -g commitizen 
      npm install -D cz-git
      
      // package.json
      {
          "scripts": {
              "commit": "git-cz"
          },
          "config": {
              "commitizen": {
              "path": "node_modules/cz-git"
              }
          }
      }
      
  • 而现在

    • 使用 czg CLI 的安装使用流程
      npm install -g czg
      
      // package.json
      {
          {
              "scripts": {
                  "cz": "czg"
              }
          }
      }
      
  • 总结

    • czg 无需任何前置配置
    • 在原有基础上拓展 cz-git 的基础功能
    • 启动速度更快
    • 更轻量化,使用 npx 在项目中启动使用
    • 当然,以上两种方案可以混用: 即 czg CLICommitizen CLI + cz-git
  • 参考

    • 心路历程
    • cz-git配置
    • 配置模板

🚀 安装

pnpm add czg -D

🚀 配置package.json脚本命令

"scripts": {
   //......其他省略
    "commit": "git add -A && czg && git push"
}

上面在scripts脚本中配置了commit命令,用来替代git commit,并且合并了git addgit push命令

📹 效果演示
在这里插入图片描述

根据上gif图演示,1、选择提交类型,2、自定义scope,3、输入commit。完成了一个简易的交互式提交,当然他的亮点并不是单单的提交,它结合了我之前写的规范工程篇章1~4的代码规范检查(检查暂存区文件)。

🚀 语法提示

下面我们需要对 commitlint.config.cjs 进一步配置成,在配置之前,我们需要添加 代码提示。添加 @type 到文件中:

/** @type {import('czg').UserConfig} */
module.exports = {
    // 其他代码
}

🚀 英译中

  • commitlint.config.cjs 文件内容:

    不推荐使用纯中文进行commit,因为终端对于中文输入的支持并不是很友好,并且在使用搜索时没有英文交互来得自然。
    推荐使用中英文对照,可以很好给予团队的新人帮助。

    module.exports = {
        // 其他代码
        prompt: {
            messages: {
                type: "Select the type of change that you're committing:",
                scope: "Denote the SCOPE of this change (optional):",
                customScope: "Denote the SCOPE of this change:",
                subject: "Write a SHORT, IMPERATIVE tense description of the change:\n",
                body: 'Provide a LONGER description of the change (optional). Use "|" to break new line:\n',
                breaking: 'List any BREAKING CHANGES (optional). Use "|" to break new line:\n',
                footerPrefixSelect: "Select the ISSUES type of changeList by this change (optional):",
                customFooterPrefix: "Input ISSUES prefix:",
                footer: "List any ISSUES by this change. E.g.: #31, #34:\n",
                confirmCommit: "Are you sure you want to proceed with the commit above?"
    
                // 中文对照
                // type: "选择你要提交的类型 :",
                // scope: "选择一个提交范围(可选):",
                // customScope: "请输入自定义的提交范围 :",
                // subject: "填写简短精炼的变更描述 :\n",
                // body: '填写更加详细的变更描述(可选)。使用 "|" 换行 :\n',
                // breaking: '列举非兼容性重大的变更(可选)。使用 "|" 换行 :\n',
                // footerPrefixSelect: "选择关联issue前缀(可选):",
                // customFooterPrefix: "输入自定义issue前缀 :",
                // footer: "列举关联issue (可选) 例如: #31, #I3244 :\n",
                // confirmCommit: "是否提交或修改commit ?"
            },
            types: {
                {
                    value: "feat",
                    name: "feat:      |  A new feature",
                },
                {
                    value: "fix",
                    name: "fix:       |  A bug fix",
                },
                {
                    value: "docs",
                    name: "docs:      |  Documentation only changes",
                },
                {
                    value: "style",
                    name: "style:     |  Changes that do not affect the meaning of the code",
                },
                {
                    value: "refactor",
                    name: "refactor:  |  A code change that neither fixes a bug nor adds a feature",
                },
                {
                    value: "perf",
                    name: "perf:      |  A code change that improves performance",
                },
                {
                    value: "test",
                    name: "test:      |  Adding missing tests or correcting existing tests",
                },
                {
                    value: "build",
                    name: "build:     |  Changes that affect the build system or external dependencies",
                },
                {
                    value: "ci",
                    name: "ci:        |  Changes to our CI configuration files and scripts",
                },
                {
                    value: "revert",
                    name: "revert:    |  Reverts a previous commit",
                },
                {
                    value: "wip",
                    name: "wip:       |  Work in process",
                },
                {
                    value: "chore",
                    name: "chore:     |  Other changes that don't modify src or test files",
                }
    
                // 中文对照
                // { value: "feat", name: "特性:   |  新增功能" },
                // { value: "fix", name: "修复:   |  修复缺陷" },
                // { value: "docs", name: "文档:   |  文档变更" },
                // { value: "style", name: "格式:   |  代码格式(不影响功能,例如空格、分号等格式修正)" },
                // { value: "refactor", name: "重构:   |  代码重构(不包括 bug 修复、功能新增)" },
                // { value: "perf", name: "性能:    |  性能优化" },
                // { value: "test", name: "测试:   |  添加疏漏测试或已有测试改动" },
                // { value: "build", name: "构建:   |  构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等)" },
                // { value: "ci", name: "集成:   |  修改 CI 配置、脚本" },
                // { value: "revert", name: "回退:   |  回滚 commit" },
                // { value: "wip", name: "开发:   |  正在开发中" },
                // { value: "chore", name: "其他:   |  对构建过程或辅助工具和库的更改(不影响源文件、测试用例)" }
            },
        }
    }
    

🚀 加入emoji

  • 要想实现直观、美观的 git 追踪流,添加 emoji 图标:

    module.exports = {
        // 其他代码
        prompt: {
            types: {
                {
                    value: "feat",
                    name: "feat:      ✨  A new feature",
                    emoji: "✨"
                },
                {
                    value: "fix",
                    name: "fix:       🐛  A bug fix",
                    emoji: "🐛"
                },
                {
                    value: "docs",
                    name: "docs:      📚  Documentation only changes",
                    emoji: "📚"
                },
                {
                    value: "style",
                    name: "style:     🎨  Changes that do not affect the meaning of the code",
                    emoji: "🎨"
                },
                {
                    value: "refactor",
                    name: "refactor:  🌈  A code change that neither fixes a bug nor adds a feature",
                    emoji: "🌈"
                },
                {
                    value: "perf",
                    name: "perf:      ⚡️  A code change that improves performance",
                    emoji: "⚡️"
                },
                {
                    value: "test",
                    name: "test:      🧪  Adding missing tests or correcting existing tests",
                    emoji: "🧪"
                },
                {
                    value: "build",
                    name: "build:     📦  Changes that affect the build system or external dependencies",
                    emoji: "📦"
                },
                {
                    value: "ci",
                    name: "ci:        🎡  Changes to our CI configuration files and scripts",
                    emoji: "🎡"
                },
                {
                    value: "revert",
                    name: "revert:    ⏪️  Reverts a previous commit",
                    emoji: "⏪️"
                },
                {
                    value: "wip",
                    name: "wip:       🕔  Work in process",
                    emoji: "🕔"
                },
                {
                    value: "chore",
                    name: "chore:     🔨  Other changes that don't modify src or test files",
                    emoji: "🔨"
                }
    
                // 中文对照
                // { value: "feat", name: "特性:   ✨  新增功能", emoji: "✨" },
                // { value: "fix", name: "修复:   🐛  修复缺陷", emoji: "🐛" },
                // { value: "docs", name: "文档:   📚  文档变更", emoji: "📚" },
                // { value: "style", name: "格式:   🎨  代码格式(不影响功能,例如空格、分号等格式修正)", emoji: "🎨" },
                // { value: "refactor", name: "重构:   🌈  代码重构(不包括 bug 修复、功能新增)", emoji: "🌈" },
                // { value: "perf", name: "性能:    ⚡️  性能优化", emoji: "⚡️" },
                // { value: "test", name: "测试:   🧪  添加疏漏测试或已有测试改动", emoji: "🧪" },
                // { value: "build", name: "构建:   📦️  构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等)", emoji: "📦️" },
                // { value: "ci", name: "集成:   🎡  修改 CI 配置、脚本", emoji: "🎡" },
                // { value: "revert", name: "回退:   ⏪️  回滚 commit", emoji: "⏪️" },
                // { value: "wip", name: "开发:   🕔  正在开发中", emoji: "🕔" },
                // { value: "chore", name: "其他:   🔨  对构建过程或辅助工具和库的更改(不影响源文件、测试用例)", emoji: "🔨" }
            },
            useEmoji: true,
            emojiAlign: "center",
        }
    }
    

🚀 自定义配置scopes

光有 emoji 还不够!有时候为了其他明了展示你的修改区域范围,或给刚入职的萌新定位,我们还需要加入scopes,就是项目业务区,它能够使Git Graph更明确修改位置,配置:

// commitlint.config.cjs
const fs = require('node:fs')
const path = require('node:path')

const packages = fs.readdirSync(path.resolve(__dirname, "src"), { withFileTypes: true }).filter(dirent => dirent.isDirectory());
module.exports = {
  rules: {
    'scope-enum': [2, 'always', [...packages]]
  }
}

🚀 最终效果展示

结合之前篇章1~4的代码格式化、语法校验等lint通过之后,才会正式提交到远端仓库

在这里插入图片描述

后续

🌈 上面提到,最后一个动作是 git push 命令,将本地代码更新到 远端仓库
那么它实际并未完成整个前端工作流程,那么我们还需要借助husky来处理自动化构建动作,触发它能做些什么呢?如:

方式一:push触动build并上传到ftp服务

  1. 配置husky监听git hooks (push),实现自动 build本地构建。
    • 通过nodejs:fs.readFileSync识别.git/HEAD工作区(即分支名),如果是测试分支或者生产分支,则构建,否则不触发构建动作。
  2. 构建完成通过ftp插件实现文件传输。
    • 配置ftp账号信息,供ftp插件调用;
    • 根据分支规则上传到对应ftp服务;

方案二:push触发CI/CD工作流

  1. 创建CI/CD流(gitlab、github)
    • 指定触发工作流的分支,如master
    • 定义每个阶段的任务、需要的镜像依赖等
  2. 触发动机
    • 手动push
    • CR分支合并;

以上两种方案
第一种学习成本相对较低,主要是在开发者本地运行;
第二种学习成本相对高,自定义方面强。包括设置任务延时发布(比如你可以选择在半夜更新)、重试机制和报警(邮件通知)等等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2187129.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

行为设计模式 -观察者模式- JAVA

观察者模式 一.简介二. 案例2.1 抽象主题(Subject)2.2 具体主题(Concrete Subject)2.3 抽象观察者(Observer)2.4 具体观察者(Concrete Observer)2.5 测试 三. 结论3.1 优缺点3.2 使用…

从零开始讲PCIe(0)——外设与外设总线

一、外设 计算机外设(Peripheral)是指连接到计算机主机以扩展其功能的外部设备。这些设备可以是输入设备、输出设备、存储设备或通信设备等,外设(外围设备)通过输入、输出、存储和通信等方式帮助计算机与用户和其他设备…

用Arduino单片机读取PCF8591模数转换器的模拟量并转化为数字输出

PCF8591是一款单芯片,单电源和低功耗8位CMOS数据采集设备。博文[1]对该产品已有介绍,此处不再赘述。但该博文是使用NVIDIA Jetson nano运行python读取输入PCF8591的模拟量的,读取的结果显示在屏幕上,或输出模拟量点亮灯。NVIDIA J…

可解释聚类又“炸出圈”啦!把准3个切入点一路开挂!创新思路一学就会~

可解释聚类是机器学习领域一个非常重要的研究方向,它通过引入解释性强的特征和模型,让我们更直观地理解聚类结果,从而提升聚类分析的准确性和可靠性。 这种方法在一些敏感领域如医疗、金融等非常适用,因为它与传统方法不同&#…

工具模块及项目整体模块框架

文章目录 工具模块logger.hpphelper.hppthreadpool.hpp 核心概念核心API交换机类型持久化⽹络通信消息应答持久化数据管理中心模块虚拟机管理模块交换路由模块消费者管理模块信道管理模块连接管理模块Broker服务器模块消费者管理信道请求模块通信连接模块项⽬模块关系图 工具模…

Oracle SQL语句没有过滤条件,究竟是否会走索引??

答案是:可能走索引也可能不走索引,具体要看列的值可不可为null,Oracle不会为所有列的nullable属性都为Y的sql语句走索引。 例子: create table t as select * from dba_objects; CREATE INDEX ix_t_name ON t(object_id, objec…

MySQL 中的 GTID 复制详解

MySQL 中的 GTID 复制详解 在 MySQL 的复制架构中,GTID(Global Transaction Identifier)复制是一种重要的技术,它为数据库的复制提供了更强大的功能和更高的可靠性。本文将深入探讨 MySQL 中的 GTID 复制是什么,以及它…

OpenCV计算机视觉库

计算机视觉和图像处理 Tensorflow入门深度神经网络图像分类目标检测图像分割OpenCVPytorchNLP自然语言处理 OpenCV 一、OpenCV简介1.1 简介1.2 OpenCV部署1.3 OpenCV模块 二、OpenCV基本操作2.1 图像的基本操作2.1.1 图像的IO操作2.1.2 绘制几何图像2.1.3 获取并修改图像的像素…

时间相关数据的统计分析(笔记更新中)

对事件相关数据的统计思路做一个笔记 可以用作肿瘤生长曲线(Tumor Growth Curve)/某一个药物处理后不同时间点表型的获取类型的数据。 总体来说合适的有两类,一类是以ANOVA为基础的方差分析,重复测量资料的方差分析;…

D - Connect the Dots Codeforces Round 976 (Div. 2)

原题 D - Connect the Dots 思路 直接去做的话会超时, 因此用差分去优化 代码 #include <bits/stdc.h> using namespace std;int f[200020]; int z; int b[11][200020];// 并查集的 find 函数 int find(int x) {return f[x] ! x ? f[x] find(f[x]) : x; }// 检查是…

食品饮料小程序搭建私域会员管理

食品饮料是商超主要经营类目之一&#xff0c;多样化的品牌/厂商/渠道/经销商&#xff0c;客户在消费方面购物渠道和选择范围广&#xff0c;无论厂商还是线下门店/线上电商都需要围绕流量/会员开展生意获得更多营收。 小程序开店基于微信平台生态分享宣传、用户店铺方便购物及提…

Flutter与原生代码通信

文章目录 1. 知识回顾2. 示例代码3. 经验总结我们在上一章回中介绍了通道相关的内容,本章回中将介绍其中的一种通道:MethodChannnel.闲话休提,让我们一起Talk Flutter吧。 1. 知识回顾 我们在上一章回中介绍了通道的概念和作用,并且提到了通道有不同的类型,本章回将其中一…

【C++】类与对象基础概念解析

恭喜你学习完C语言与数据结构的有关内容&#xff0c;现在让我们开始进行对C的学习吧~ &#x1f49d;&#x1f49d;&#x1f49d;如果你对C语言或数据结构还存在疑惑&#xff0c;欢迎观看我之前的作品 &#x1f449;【数据结构】 &#x1f449;【C语言】 目录 一、引言 二、类…

【2024年最新】基于springboot+mysql就业信息管理系统

技术摘要 技术框架&#xff1a;以springboot作为框架&#xff0c;业务模式&#xff1a;B/S模式数据库&#xff1a;MySql作为后台运行的数据库服务器&#xff1a;使用Tomcat用为系统的服务器 系统展示 系统实现功能 本次实现一个就业信息管理系统&#xff0c;通过这个系统能够…

vscode安装及c++配置编译

1、VScode下载 VS Code官网下载地址&#xff1a;Visual Studio Code - Code Editing. Redefined。 2、安装中文插件 搜索chinese&#xff0c;点击install下载安装中文插件。 3、VS Code配置C/C开发环境 3.1、MinGW-w64下载 VS Code是一个高级的编辑器&#xff0c;只能用来写代…

嵌入式系统中qt开发 Qdebug输出中文的时候变成了问号 ??? bulideroot制作的根文件系统

嵌入式系统中qt开发 Qdebug输出&#xff1f;&#xff1f;&#xff1f; bulideroot制作的根文件系统 这个问题我找了三四天了&#xff0c;因为的字符也配置了 /etc/profile中qt的环境变量我也配置了 我的/usr/share/fonts也是有字库的&#xff0c;但是qt输出的中文全是&#…

windows 11 LTSC 26100.1742 官方简体中文版

系统简介 Windows 11 LTSC&#xff08;长期服务通道&#xff09;是一个专为长期稳定性和可靠性设计的Windows 11变体&#xff0c;适合于需要最小更新和更改的关键任务系统和设备。与常规版本相比&#xff0c;LTSC版本的特点是更新频率较低&#xff0c;目的是为了保持系统的稳定…

从零开始掌握YOLOv11:揭秘三大损失函数的理想值(源码+实战)

相关文章&#xff1a; YOLOv1–v11: 版本演进及其关键技术解析-CSDN博客 YOLOv11&#xff1a;重新定义实时目标检测的未来-CSDN博客 Yolo v11目标检测实战1&#xff1a;对象分割和人流跟踪&#xff08;附源码&#xff09;-CSDN博客 YOLOv11目标检测实战2&#xff1a;人流统计…

win10下cuda12.1 +troch2.4.1+vs2022环境下编译安装flash-attn

步骤一 下载项目 先下载 https://github.com/Dao-AILab/flash-attention&#xff0c;然后在conda环境中进入项目目录 步骤二 安装依赖项 执行以下命令&#xff0c;安装cutlass库&#xff0c;该库为编译flash-attn的必须依赖 conda update --force conda conda install conda…

Linux文件重定向文件缓冲区

目录 一、C文件接口 二、系统文件I/O 2.1认识系统文件I/O 2.2系统文件I/O 2.3系统调用和库函数 2.4open( )的返回值--文件描述符 2.5访问文件的本质 三、文件重定向 3.1认识文件重定向 3.2文件重定向的本质 3.3在shell中添加重定向功能 3.4stdout和stderr 3.5如何理…