git使用
git使用
1. 安装
windows或Mac前往官方网站下载,可以选择下载GUI Client版本如果安装的磁盘出现故障,使用安装工具再次安装会出现
The drive or UNC share you selected does not exist or is not accessible.,需要删除注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Git_is1文件夹linux使用sudo apt get git安装
2. 配置
- config文件配置
- 配置用户名和邮箱
git config --global user.name "用户名"
git config --global user.email example@163.com
# 查看所有的配置信息
git config --global --list- 配置
ssh秘钥: 通过配置的多个秘钥访问可以方便地向多个代码管理平台获取代码- 推荐使用
git-bash完成,在资源管理器中右键可以看到Open Git Bash选项 ~在windows中没有原生实现,windows只认识%USERPROFILE%,这在git和ssh环境中不可用,万幸的是~在git bash、git和ssh配置文件中可以使用
- 推荐使用
# 生成两个秘钥
# -t 后指定签名算法,推荐使用最新的签名算法 ed25519
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_gitee -C "your_gitee_email@gitee.com"
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_github -C "your_github_email@github.com"
# 让秘钥在传输时使用
# [方法1]编辑~/.ssh/config文件,修改gitee和github的host
# gitee
Host gitee.com
HostName gitee.com
IdentityFile ~/.ssh/id_rsa_gitee
# github
Host github.com
HostName github.com
# 如果 22 端口连不上,可以使用 443 端口
port 443
IdentityFile ~/.ssh/id_rsa_github
# [方法2]Linux可以使用命令添加秘钥到ssh-agent高速缓存中
ssh-add ~/.ssh/id_rsa_gitee
ssh-add ~/.ssh/id_rsa_github
# 将对应公钥.pub文件添加到gitee和github设置(添加新的ssh钥匙)中
# https://gitee.com/profile/sshkeys
# https://github.com/settings/keys- 如果两个提交邮箱地址相同,到此已可以同时提交到两个仓库了
- 如果两个提交邮箱不同
- 可以通过全局配置中的
includeIf设置特殊目录,在特殊目录中的仓库可以配置不同的邮箱 - 也通过编写脚本实现设置邮箱地址并提交,编写完的脚本可以使用别名设置到
git中,脚本可以通过git alias设置别名调用
- 可以通过全局配置中的
[user]
name = "用户名"
# 个人邮箱
email = "your_email@example.com"
# gitdir: 是前缀匹配,最后应该添加/,避免错误的额外匹配
[includeIf "gitdir:D:/projects/"]
# 对应目录使用的另一配置文件
path "~/.gitconfig-work"# 脚本写法
#!/bin/bash
if [ "$1" == "github" ]; then
git config user.email "your_github_email@example.com"
git push github main
git config --unset user.email
elif [ "$1" == "gitee" ]; then
git config user.email "your_gitee_email@example.com"
git push gitee main
git config --unset user.email
else
echo "Usage: ./git-push.sh [github|gitee]"
fi3. git常见命令
3.1 提交代码
3.1.1 git仓库结构
- 在git目录中主要有3个部分:
- 本地库存储区域用于管理本地存储内容,每次提交结果会存储在这里,并通过命令推送到远程储存库管理方
- 暂存区域进行工作区和存储区的比较
- 工作区是本地代码存储区域,在这里可以修改代码

3.1.2 创建/克隆仓库
# 本地创建仓库,根文件夹地址默认为.
git init [根文件夹地址]
# 将仓库添加到远程
# git remote add <remote_name> <url>
git remote add origin 仓库的url地址
# 将远程克隆到本地,根文件夹地址默认为仓库名
git clone 仓库的url地址 [根文件夹地址]
# github加速地址
# git clone https://gitclone.com/github.com/tendermint/tendermint.gitgit remote选项详解

3.1.3 暂存/提交存储
# 查看本地代码信息
git status
# 将代码提交到暂存区,后面可使用正则匹配,如:*.txt
git add .
# 从暂存区移除文件,后面可使用正则匹配
# 默认将从暂存区和工作区移除,误操作请使用git checkout 文件 还原
# 还原将清除修改,如果文件有修改,请先备份文件,再还原,最后使用备份文件覆盖
git rm --cached .
# 如果只是暂时移出暂存区
git restore --staged 文件
# 老版本无restore功能
git reset 文件
# 提交到存储区域
git commit -m "提交信息"
# 还原文件为本地存储区对应版本,默认为最近一次提交
git checkout 指定分支或提交版本号 -- <file>
# 清除工作区未暂存文件修改
git restore <file>
# 将暂存的暂存区文件放入工作区
git restore --staged <file>git add命令详解

git commit命令详解

git restore命令详解

3.1.4 上传/回滚版本
# 提交到远程库
# 仓库名需要通过remote设置,如果本地远程使用分支相同,只需要提供一个名称
git push 仓库名 远程分支名:本地分支名
# 默认提交当前分支到origin仓库到对应分支
git push
# 如果是第一次提交需要--set-upstream(-u)来绑定这个分支,使用时有相关提示
# origin是默认的仓库名,可以自己取名
git push --set-upstream origin master
# 从远程获取最新远程信息
# 仓库名需要通过remote设置,如果本地远程使用分支相同,只需要提供一个名称
git pull 仓库名 远程分支名:本地分支名
# 默认获取origin仓库对应分支到到当前分支
git pullgit push命令详解

git pull命令详解

3.1.5 储藏代码
- 将当前未提交的修改(即工作区和暂存区的修改)先暂时储藏起来,保存到一个栈中,并恢复工作目录到干净的
HEAD状态。这样可以在不提交当前更改的情况下,切换到其他分支或进行其他操作
| 命令 | 说明 |
|---|---|
git stash | 将当前工作空间的状态保存,-m可以添加备注,-S只缓存在暂存区的文件 |
git stash pop | 读取stash堆栈中的第一个储藏,并将该储藏从stash堆栈中移除 |
git stash list | 查看当前的所有储藏 |
git stash apply {stashName} | 根据储藏名称读取储藏 |
git stash drop {stashName} | 根据储藏名称删除储藏 |
git stash save "日志信息" | 将当前工作空间的状态保存并指定一个日志信息 |
git stash show [-p] {stashName} | 查看指定储藏与未建立储藏时的差异,-p显示详细差异 |
git stash branch {branchName} [stashName] | 创建并切换到一个新分支来读取指定的储藏 |
其中的
stashName是储藏的名称,默认情况下读取stash堆栈中栈顶的储藏(最后储藏的代码),默认名字为stash@{数字}
3.1.6 还原代码
git中的还原功能主要通过git restore命令实现# 查看某个文件历史,-p 选项查看详细的差异 git log -- src/main.js # 还原到某个提交 git restore --source <版本号> <文件名>
3.2 查询版本号和提交信息
3.2.1 版本号和提交信息
git中的版本号是40位的16进制字符串,每次提交自动生成,可以在.git/object/文件夹中查看到相关信息文件,文件不能通过文本工具查看- 版本号是通过
SHA-1算法生成的,前2位作为文件夹,后38位作为文件名存放在.git/object/中 - 版本号不止在git提交中存在,
.git/object/中存放的信息主要有三类:- 版本号对应的提交信息:每次提交的内容和相关信息通过
tree和parent信息关联tree信息中的版本号对应关联文件信息的版本号parent信息中的版本号是上次提交的版本号
- 关联文件信息:关联文件列表中每个文件都有对应的版本号,通过版本号能够查到对应版本的提交文件内容
- 如果是文件夹在信息中显示是
tree,文件则是blob
- 如果是文件夹在信息中显示是
- 提交的文件内容:每次修改此文件提交才会产生新的版本号,减少不同提交相同文件占用的额外存储
- 版本号对应的提交信息:每次提交的内容和相关信息通过
- 最近的版本号可以通过
HEAD~1获取,表示的是最近的提交

3.2.2 查询命令
# 查看提交的信息,版本号支持输入前几个字符,能唯一识别就行
git cat-file -p <版本号>
# tree 99f3ff5f48091413daa6b85f753e516148a6cbd3
# parent 0ae3ce1072470adeb4caf79a5190dfdaca700586
# 作者信息
# 提交者信息
# 提交文本内容
# 查看提交关联文件信息
git cat-file -p 99f3ff5f48091413daa6b85f753e516148a6cbd3
# 100644 blob 52b636fbddd53ee095b139a4bc7beeb92c679c7d .gitignore
# 100644 blob e7cf7113d4627366e9d179feaecc447a8641044c readme.md
# 040000 tree c98a7db8e400685dc64390cbd757dd4348aefb49 java
# 查看提交的文件内容
git cat-file -p 52b636fbddd53ee095b139a4bc7beeb92c679c7d
# .obsidian/
# .crossnote/
# *.pdf
# *.html
# 列出满足条件的提交序列号,从最近开始(时间倒序)
# 常用选项
# -n 1 列出一条结果
# --before\--unit 日期 --after\--since 日期 列出在日期区间内提交的结果
# --author=正则 列出与作者相关的提交
# --parents 列出此序列号的之前的提交序列号 --children 列出结果的之后提交序列号
git rev-list 模糊序列号或--all
# 查询详细的标签或版本号信息
git show 版本号或标签名- 在查询或使用其他的功能时,如果希望指代当前提交指针的位置,可以使用
HEAD,如果希望指代指针之前的几次提交可以使用HAED~i,其中i表示之前第几次提交,当i为1时可省略
^和~的区别
还有一种调用是HEAD^i,表示寻找第i个父提交,二者的区别在于~是向前i次寻找第一个父提交,^是寻找当前指针的第几个父提交,即HEAD^2表示寻找第2个父提交(当合并分支时当次提交有多个父提交)
3.3 分支管理
3.3.1 分支切换
- 分支信息是通过
.git/refs/heads存储的,其中每个文件对应一个分支,文件可直接通过文本工具打开,其中存储的是最近的分支的最新提交版本号 - 在
.git/HEAD中存储的是目前使用的分支,比如使用的是main分支内容为ref: refs/heads/main

管理分支命令
# 查看所有分支
git branch
# 创建分支
git branch 分支名
# 从对应标签创建分支
git branch -b 分支名 版本号或分支名
# 进入分支
git checkout 分支名
# 创建并进入:git checkout -b 分支名
git switch 分支名
# 创建并进入:git switch -c 分支名
# 在不切换分支的情况下修改其他分支指针位置
git branch -f <branch_name> <commit_id>
# 删除本地分支
git branch -d <branch_name>
# 强制删除
git branch -D <branch_name>
# 重命名当前分支
git branch -m new_branch
# 如果已经推送,需要重命名远程仓库分支名
# 可以使用以下命令行或在github等仓库网页上修改分支名称
# 重置本地分支的上游分支,将上游修改存入新分支
git push origin -u <new_branch_name>
# 删除远程分支
git push origin --delete <old_branch_name>git switch命令详解

3.3.2 合并分支
# 将分支1合并到本分支
git merge 分支1
# 如果有冲突,打开文件将所有冲突解决
# 再提交合并
# 默认不删除原有分支
# 如果希望删除本地已合并分支
git branch -d 分支名
# 如果希望删除远程仓库中的已合并分支
git push 远程仓库名 --delete 分支名git merge命令详解

3.4 标签管理
- 标签相当于给版本号起了别名,用于快速查找对应版本
# 添加标签,如果未给出版本号,默认使用最近一次提交的版本号
# 可以用 -m 添加描述
git tag 标签名 版本号
# 删除标签
git tag -d 标签名
# 列出所有标签
git tag -l3.5 修改提交
使用新提交撤销之前的提交
- 使用
git revert命令可以撤销提交,生成一条新的提交来覆盖之前的修改,保留修改历史

将文件添加到最近一次提交
# 暂存文件
git add 需要添加的文件
# 移除文件
# --cached 修改索引将删除,如果此时再添加将视为新添加的文件
# !!! 不添加--cached将删除文件且无法恢复未提交的内容
git rm --cached 需要移除的文件
# 还原文件到某次提交
git checkout 版本号 -- 需要还原的文件
# 修改最近一次提交
git commit --amend
# 不需要修改提交信息的话,直接返回
# 如果本次添加的文件是上次提交时添加的,应该会覆盖之前的版本
# 如果之前已经提交到远程仓库(慎重),如果不希望强制提交就创建新的提交来更新文件吧
git push --force修改最近的部分提交(变基)
- 使用
git rebase命令可以修改提交记录,删除合并修改提交历史而不产生新的提交记录
# 临时储存本分支未提交的修改
git stash
# 修改完成后恢复未提交的修改
git stash pop
# git rebase -i [startpoint] [endpoint]
# 从最近的第3次提交开始修改
git rebase -i HEAD~3
# 还可以添加 --onto 分支名称 参数,将这些提交复制到其他分支上进行修改
# 之后还需要使用git reset重置对应分支HEAD指针
# 打开提交记录文件
# 修改提交记录的前缀
# pick:保留该commit(缩写:p)
# reword:保留该commit,但我需要修改该commit的注释(缩写:r)
# edit:保留该commit, 但我要停下来修改该提交(不仅仅修改注释)(缩写:e)
# squash:将该commit和前一个commit合并(缩写:s)
# fixup:将该commit和前一个commit合并,但我不要保留该提交的注释信息(缩写:f)
# exec:执行shell命令(缩写:x)
# drop:我要丢弃该commit(缩写:d)
# 文件行从上到下将是最终提交次序,可以通过修改文件行的上下关系,修改提交次序
# 关闭窗口,开始修改代码
# 如果需要添加修改文件,使用git add 添加
# 如果需要移除修改文件,使用git reset HEAD^ 将所有提交文件改为未提交状态,重新提交需要提交的文件
# 如果需要将提交应用到其他分支,在对应分支使用git cherry-pick 提交版本号 引入提交
# 修改完成一次提交修改后使用git rebase --continue继续
# 取消rebase修改git rebase --abort
# 结束使用强制提交
git push --forcegit rebase命令详解git rebase 分支名可以将当前分支上从分叉点开始的所有本地提交移动到另一个分支的顶部,另一个分支不变,适合忘记拉取仓库更新的情况git rebase -i 版本号可以交互式修改之前的提交

重置代码(多人公共分支慎重使用)
- 使用
git reset命令可以将本地代码重置,将对应区域的代码恢复到对应版本
# 重置代码为某次提交
# git reset 仓库名/分支名
# git reset 提交版本号
# 可选参数
# -soft:重置分支的指针,之前的修改将被保留在暂存区中,你的修改回到了未提交状态 --- 回退本地库存储区域
# -mixed(默认选项):重置分支的指针,并清除暂存区的内容。之前的修改将保留在工作区中 --- 回退本地库存储区域和暂存区
# -hard:重置分支的指针,并清除暂存区和工作区的内容 --- 全部回退
# 用于命令默认对齐的是HEAD也就是当前,因此需要配合版本号使用,否则无效
# 用途清除暂存区存储,将改动转为未添加状态,实际上省略了--mixed HEAD^
git reset
# 重置提交,将提交的改动存储在暂存区中
git reset --soft HEAD^
# 回滚代码,将所有改动还原,还原提交、暂存区和工作区
git reset --head HEAD^- 取消
git reset,如果内容已被垃圾回收机制gc清理,无法恢复
# 查看分支指针变动信息,查看之前的版本号
git reflog
# 回到git reset之前
git reset 版本号
# 如果reflog已被清除,可以寻找仓库的悬空提交记录
# 查看悬空提交记录
git fsck --lost-found
# 查看某个提交具体内容
git show 版本号
# 恢复
git merge 版本号- 将其他提交添加到本分支
git cherry-pick
# 如果不希望自动生成提交记录,使用--no-commit选项
# 如果提交是空的,默认报错,可以使用--skip跳过对应提交
git cherry-pick 需要添加的提交版本号列表
# 如果出现冲突,解决冲突后使用
git cherry-pick --continue
# 如果希望放弃处理当前冲突,取消命令
git cherry-pick --abort3.5.1 修改仓库历史
在大型项目维护过程中,可能错误地将某些不需要上传的文件上传到远程仓库,并且错误的上传深入多次提交和大量文件夹
这些命令使用时需要提供对文件历史的操作命令,避免
windows等系统操作不便和不同,使用git bash可使用unix/linux命令git filter-branch是一个官方自带工具,能够深度修改仓库的历史- 使用
需要注意的是这里使用了
--来提示后面的--all是一个版本号的引用,而不是命令选项# 关于限制需要修改的提交范围 # --all表示对所有提交做操作,可以替换成版本提交范围如:HEAD~5..HEAD # 也允许使用排除选项,比如排除修改ab1234提交,HEAD~5..HEAD ^ab234 # 提交范围也可以使用abc1234^!指定修改某个版本 # 对tree做操作,--tree-filter # 将对需要提交的文件本身做操作,涉及对应版本号的文件解压修改压缩 # 耗时长,但可进行复杂操作,如对文件内容修改 git filter-branch --tree-filter '对文件命令名' -- --all # 对index做操作,--index-filter # 将只修改提交历史索引中的信息,无法修改文件内容,但可以快速移除提交文件 git filter-branch --tree-filter '对文件命令名' -- --all # 对某些提交做操作,--commit-filter # 比如对某些提交修改提交者信息,甚至跳过提交 git filter-branch --commit-filter '命令名' -- --all # 对提交信息做操作,--msg-filter # 修改提交信息中的部分文本描述 git filter-branch --msg-filter 'sed "s/old message/new message/g"' -- --all # 修改提交的环境变量,--env-filter # 比如提交者名字,邮箱 git filter-branch --env-filter '命令名' -- --all- 还原执行
git filter-branch带来的错误修改,每次执行此命令都会自动备份当前结果到refs/original/中(例如refs/original/refs/heads/main)
# 直接重置指针恢复 git reset --hard refs/original/refs/heads/main # 通过reflog恢复 git reflog # 看见如下结果 # a1b2c3d HEAD@{0}: filter-branch: rewrite finished in refs/heads/main # 9e8f7g6 HEAD@{1}: commit: Some commit message git reset --hard 9e8f7g6- 删除备份分支
git update-ref -d refs/original/refs/heads/main # 彻底删除所有备份和已移除的历史文件及相关版本号信息 # 删除创建的备份分支 rm -rf .git/refs/original/ # 删除所有不可达的提交 git reflog expire --expire-unreachable=now --updateref # 还可以添加--aggressive,进行更彻底的长时间回收 git gc --prune=nowgit filter-repo是社区中修改仓库历史的工具,高效易用现代化,仓库地址在github- 安装
# 需要添加python安装文件夹中的script文件夹到环境变量 pip install git-filter-repo- 使用,每次操作包括重置到最新提交、删除指针跳转记录、执行垃圾回收,使用前备份仓库,因为无法恢复
# 分析仓库情况 git filter-repo --analyze # 从提交历史中删除文件,--invert-paths表示反选(删除) # 如果希望只保留文件名的提交历史,删除其他文件提交历史则不添加反选选项 # 如果希望使用正则表达式,可以使用--path-glob '正则表达式' # 可以使用在末尾--refs选项限制修改的提交范围,--refs HEAD~5..HEAD ^ab234 git filter-repo --path <文件名> --invert-paths # 删除大小大于10M的文件提交历史 git filter-repo --strip-blobs-bigger-than 10M # 替换文件内容,使用fnmatch格式的替换文件expression.txt进行替换 # fnmatch:https://docs.python.org/3/library/fnmatch.html git filter-repo --replace-text expressions.txt如果提交过远程仓库需要再覆盖提交
部分常见操作可以查看从filter-branch转换到filter-repo包含两种工具的使用和对比
3.6 查看仓库相关信息
# 查看缓存区情况
git status
# 查看提交情况
# 添加--oneline一个提交只显示一行
git log
# 查看此提交和之前提交情况
# 可以使用 git log 标签名或版本号 获取对应提交情况
# 可以使用 git log -1 来获取最近一次提交情况
git log 标签名或版本号
# 查看某文件的提交记录
git log --pretty=oneline --stat -- 文件名
# 查看所有引用,包括标签,分支,远程分支
git show-ref
# 查看标签
git tag
# 查看分支
git branch
# 查看远程仓库
git remote
# 查看分支对比
git diff 分支名 远程仓库名/分支名
# 查看仓库大小
git count-objects -vH3.7 设置命令别名
- 在
git中允许通过命令别名的方式将常用命令保存下来,方便下次调用
# 创建别名
git config --global alias.p 'push'
# 如果希望是bash直接执行,此脚本如果希望能全局使用请添加到有环境变量的目录下
# 如果是linux还应该使用chmod +x git-push.sh修改权限
# !表明这是外部命令,不是git的子命令
git config --global alias.push-github '!bash git-push.sh github'
# 使用
git p
# 删除
git config –unset alias.p
# 如果希望查询所有别名
git config --global -l3.8 子仓库管理
- 存在两种子仓库管理方法,
submodule和subtree,这两种仓库代码存放位置和关系有所不同submodule子仓库部分在父仓库不会频繁更新,每次更新也只是指向一个版本号,子仓库的历史记录也不会在父仓库中出现,更新需要手动更新subtree子仓库部分直接集成到父仓库,使用简单,但历史记录会和父仓库混合,父仓库和子仓库需要分别推送,保证内容相同
submodule
# 添加子仓库
git submodule add <子仓库的URL> <本地子文件夹路径>
# 克隆主仓库之后,需要再克隆子仓库
git submodule init
git submodule update
# 使用一条命令代替
git submodule update --init
# 或在克隆时使用--recurse-submodules参数递归更新子仓库
git clone --recurse-submodules <主仓库的URL>
# 子仓库需要更新在子文件夹更新即可
cd 子仓库文件夹
git fetch
git merge
# 子仓库有外部更新,在主仓库需要拉取最新提交
# 希望一次性更新全部子仓库
git submodule update --init --recursive
# 如果git>=2.14可以直接在主仓库拉取时添加参数
git pull --recurse-submodules
# 更新特定子仓库,不添加名称会更新所有子仓库
git submodule update --remote 子仓库名
# 然后必须在主仓库提交一次,因为子仓库版本号发生了变化
# 建议主仓库提交时添加check参数,检查子仓库是否提交
# 避免子仓库未提交,主仓库中使用的子仓库版本号指向错误
# git config push.recurseSubmodules check设置成默认行为
# 还存在参数为--recurse-submodules=on-demand会自动提交未提交的子仓库
git push --recurse-submodules=check
# 如果子仓库地址发生改变,需要将新的 URL 复制到本地配置中,补救
git submodule sync --recursive
# 从新 URL 更新子仓
git submodule update --init --recursive
# 对所有子仓执行相同命令
git submodule foreach '命令名'
# 如果希望删除子仓库
# 删除仓库文件夹
rm -rf 子仓库文件夹
# 删除主仓库中的.gitmodule文件中关于子仓库的内容、.git/config中关于子仓库的条目
vi .gitmodule
vi .git/config
# 删除.git/module/下的对应子仓库文件夹
rm -rf ./git/module/子仓库名称subtree
# 添加子树,--squash表示不拉取子树历史记录
git subtree add --prefix <文件夹名称> <项目URL> <分支名> --squash
# 在主仓库修改提交后希望更改子仓库
git subtree push --prefix <文件夹名称> <项目URL> <分支名>
# 移除子项目或切换子分支
git rm <文件夹名称>
git commit
git subtree add --prefix=<文件夹名称> <项目URL> <分支名>
# 为了避免每次都需要输入项目URL,就可使用URL名称代替地址
git remote add URL名称 <项目URL>4. git hook
5 github action
5.1 action介绍
github action是github提供的仓库自动化、自定义开发工作流程,能够执行各种操作,github action文档
5.2 github PAT
GITHUB_TOKEN是github默认提供的用户凭证,能够完成基本的操作,是github默认使用的token,如果需要在github action中操作除本仓库外的私有仓库或进行账号的操作,需要申请PTA秘钥github Personal Access Token(PAT)是github的个人秘钥,可以获取到更高的秘钥权限- 添加方法:在Personal access tokens页面添加新的秘钥,选择需要的权限并记下秘钥的内容
- 如果需要
action对私有仓库进行拉取等操作,添加对repo的完整权限
- 如果需要
- 将秘钥添加到仓库:秘钥需要添加到对应的仓库中才能在仓库的
action中调用,在action秘钥与变量页面将秘钥内容添加,此处设置的名字是在action中需要使用的名称,比如设置为:TEST_TOKEN - 在action中使用:可以使用
token: ${{ secrets.TEST_TOKEN }}修改使用个人秘钥,代替默认的秘钥
# 比如 checkout 操作 - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 # 引入私有仓库作为子模块,需要使用有私有仓库访问权限的个人秘钥 submodules: true token: ${{ secrets.TEST_TOKEN }}- 添加方法:在Personal access tokens页面添加新的秘钥,选择需要的权限并记下秘钥的内容
6. 破坏性问题
6.1 某个提交版本号索引文件被破坏
- 错误信息如下:
error: object file .git/objects/fb/80ec1aeaa085f6269d9aa0a81c8e833f96723d is empty
error: object file .git/objects/fb/80ec1aeaa085f6269d9aa0a81c8e833f96723d is empty
fatal: loose object fb80ec1aeaa085f6269d9aa0a81c8e833f96723d (stored in .git/objects/fb/80ec1aeaa085f6269d9aa0a81c8e833f96723d) is corrupt原因:错误可能来自在执行
add、commit、push和rebase操作时终端被异常关闭- 如果系统或电源不稳定,可以考虑
git config core.fsync true,通过文件同步配置,降低损坏风险(极大增加性能开销) - 尽可能在提交完成后立刻上传,减轻影响
- 如果系统或电源不稳定,可以考虑
挽救策略:此错误会导致对应的文件和提交消失,极有可能会因此丢失对应文件的修改和对应的提交信息,并且无法通过
git还原,尝试解决之前先备份文件夹下的文件- 如果还未提交,可以取消
git add,然后删除对应索引文件,再使用add添加 - 如果已经提交,尝试使用
git插件,比如vscode的git graph,定位损坏的提交,结合git cat-file -p命令查看提交中包含的文件索引,然后挨个查看对应的文件夹或文件的索引内容,找到损坏的索引部分,之后将对应的损坏索引文件删除,尝试使用以下方法恢复tree内容损坏,对应所有的本文件夹下的本次提交内容都无法索引,如果能够恢复文件夹下的所有内容,使用git add添加需要提交的文件,然后在此文件夹执行git write-tree,文件夹索引与文件夹中的内容都有关系,因此文件夹中的所有内容和权限都应该和之前提交时一致(可能很困难)blob内容损坏,对应文件内容无法索引,可以还原文件,然后使用git hash-object -w 文件路径重新生成索引(容易恢复)commit损坏,可以尝试使用echo "还原的提交消息" | git commit-tree tree索引 -p 父提交索引,前提是能够知道对应的tree索引(如果不知道tree索引,非常困难,可以尝试查看git reflog),如果是最近一次提交,可以应该就是当前的tree索引,git write-tree会输出索引版本号
- 如果过于困难,还是在找回修改之后,重新拉取项目,重新进行提交操作
- 如果还未提交,可以取消
对于使用现代
IDE编写的项目,可以通过编辑器中的历史记录恢复最近的文件内容,然后重新提交- 如果使用的工具没有历史记录,且之前没有上传远程服务器或进行其他形式备份,相关内容无法恢复
如果是在原项目更改指针为破坏之前重新进行提交操作,而不是重新拉取项目操作,接下来需要删除之前提交带来的悬空指针
# 移除所有空文件 cd .git find . -type f -empty -delete -print # 清理 git gc --prune=now git repack -a -d # 检查,如果有悬空指针会显示位置 git fsck --full
7. 提交规范
conventional commit是被广泛使用的提交规范,要求提交信息如下格式
<type>[optional scope]: <description> [optional body] [optional footer(s)]类型
type,可选在类型后添加!表示破坏变更,类型实际上允许自己添加,仓库中保持一致即可fix: 表示在代码库中修复了一个bugfeat: 表示在代码库中新增了一个功能build: 用于修改项目构建系统,例如修改依赖库、外部接口或者升级Node版本等chore: 用于对非业务性代码进行修改,例如修改构建流程或者工具配置等ci: 用于修改持续集成流程,例如修改Travis、Jenkins等工作流配置docs: 用于修改文档,例如修改README文件、API文档等style: 用于修改代码的样式,例如调整缩进、空格、空行等refactor: 用于重构代码,例如修改代码结构、变量名、函数名等但不修改功能逻辑perf: 用于优化性能,例如提升代码的性能、减少内存占用等test: 用于修改测试用例,例如添加、删除、修改代码的测试用例等
影响的模块
scope大致描述
description修改内容
body脚注
footer:- 使用
git trailer格式,也就是key: name emaile格式,定义了很多的key,比如Signed-off-by提交者签名、Reviewed-by代码检查、Tested-by测试者签名等 - 使用
Breaking change:来描述是否破坏了兼容性
- 使用
