版本管理与合作¶
Pending Review
Git 使用技巧¶
本地配置¶
配置文件
Git 的配置文件一般存放于 ~/.gitconfig
或 ~/.config/git/config
中, 可以使用 git config --global --edit
快速打开配置文件, 你可以直接拷贝下面的内容。
下文中会讲解部分配置的作用及注意事项。
缩进问题
下面的文档中,.gitconfig
的配置文件均使用 4 个空格而不是 Tab 进行缩进。
常用别名¶
[alias]
aliases = !git config --get-regexp alias | sed -re 's/alias\\.(\\S*)\\s(.*)$/\\1 = \\2/g'
ci = commit
co = checkout
st = status
lg = log --graph --date=relative --pretty=tformat:'%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%an %ad)%Creset'
oops = commit --amend --no-edit
reword = commit --amend
push-with-lease = push --force-with-lease
uncommit = reset --soft HEAD~1
常用配置¶
[color]
ui = auto
[color "branch"]
upstream = green
remote = red
[core]
editor = nvim
excludesfile = ~/.gitignore_global
[commit]
template = ~/.gitmessage
[pull]
ff = only
[push]
default = upstream
followTags = true
[tag]
sort = version:refname
我们也将上述的 .gitconfig
正确使用 Tab 缩进的版本放在 这里. 使用如下命令可以快速将我们提供的模板放入你的配置文件中:
gitignore¶
GitHub 在 这里 提供了一些常见的 .gitignore
文件,对于较为复杂的项目,也可以使用gitignore.io 生成。
.env
文件与 .gitignore
有些项目在开发的途中,可能引入.env
用于存放测试环境的配置,这类文件通常包含敏感信息,因此应该被加入到.gitignore
中。
请注意,回退时 .env
会被忽略,如果此时 .gitignore
不含 .env
, .env
会被视作 untracked files。
classDiagram
direction LR
CommitA --|> CommitB : "Add .env to .gitignore"
CommitB --|> CommitA_revert : reset --hard
CommitA: .gitignore (without .env)
CommitB: .gitignore (including .env)
CommitB: .env
CommitA_revert: .env (untracked)
CommitA_revert: .gitignore (without .env)
此时需手动将.env
移除版本控制,例如 mv ./.env ../.env.bk
以防止.env
被提交。
仅本地的 gitignore
本地的 .git/info/exclude
起到与 .gitignore
相同的作用,但是不会被提交到版本库中,适用于以下的情况:
- 项目不允许修改
.gitignore
- 目录名称本身包含敏感信息
- 不希望
.gitignore
参与到版本控制中
详细的文档可以参考这里。
Global gitignore¶
对于一些常见的文件类型,可以在全局配置文件中指定:
Git Hook¶
对于一些重复性的工作(例如格式化代码、检查代码风格等),可以使用 Git Hook 来自动化。
一个叫较为成熟的框架是 pre-commit,它支持多种语言和工具,例如 black
、flake8
、eslint
等,这里 提供了一些常用的 hook.
如果只需要在 commit 后运行一段脚本
可以按照如下方法进行配置:
Git Submodule¶
Submodule 可以用来添加外部项目,例如向一个 C++ 项目中添加 Eigen:
如果已经 clone 到了子目录 src/eigen
下,可以通过如下方法添加:
git rm --cached -f src/eigen # if you've already added it to the index
git submodule add <url_of_eigen> src/eigen
Rebase 与 Merge¶
一般来说,我们希望保持项目有线性的提交历史,这样可以更容易地追溯问题,因此推荐使用 rebase
来合并分支。
git checkout -b feature
git commit -a --alow-empty -m "feat: aaaaaa"
git checkout master
git commit -a --alow-empty -m "feat: bbbbbb"
git checkout feature
git rebase master
通过如下设置,可以使得 rebase
成为默认行为:
Commit Message Convention¶
对于多人协作的项目,良好的 commit message 是非常重要的。胡乱使用诸如 update
、fix
、change
等无意义的 Commit Message,会使得项目的历史记录变得难以理解,也会给后续的维护带来困难。
Conventional Commits
一种常见的 Commit Message 格式是 Conventional Commits,它的格式是:
其中:
type
是 commit 的类型,可以是feat
、fix
、docs
、style
、refactor
、perf
、test
、build
、ci
、chore
等。scope
是 commit 的作用域description
是 commit 的简要描述body
是 commit 的详细描述,通常会引用 issue、解释修改的原因等footer
通常用于引用 issue、关闭 issue 等,例如Closes #123
,也可以用于指定 breaking change 等
值得注意的是,以上规范仅仅只是推荐,实际使用时可以根据项目的实际情况进行调整,例如本文档所存放的仓库是一个文档类的项目,一般情况下可以直接省略掉type
.
Commit Message 模板
即便不严格遵循上述规范,设置一个 commit message 模板也是非常有用的,例如,可以将 这里的例子 添加到 ~/.gitmessage
:
添加后不要忘记在首行添加空行,这样 git commit
时无需新建一行。
GitHub 使用技巧¶
GitHub CLI¶
GitHub CLI 是 GitHub 官方提供的命令行工具,可以用于管理 GitHub 仓库、Issue、Pull Request 等。
例如,给 ustclug/Linux201-docs
修 bug 的流程可以简化为:
GPG 签名¶
SSH Key 只用来验证 push 环节的身份,而 GPG Key 则用来验证 Commit 的真实性。
GitHub 对 GPG Key 的文档描述很详细,我们将其列在这里:
Issue¶
下面关于 Markdown 的特性并不限于 Issue,也适用于 Pull Request 等。
GitHub 链接¶
我们以 ustclug/mirrorrequest#213 为例:
- 在 Issue 中,可以使用
#
来引用其他 Issue / PR,例如#133
-
可以通过
user/repo#issue_number
的方式引用其他仓库的 Issue / PR,例如tuna/issues#341
-
当一个 PR 包含如下关键字,并且按照上述方法连接到一个 Issue 时,合并这个 PR 会关闭对应的 issue:
-
-
可以通过 GitHub Web 上 Copy permalink 的方式获取代码的链接,例如打开 ustclug/mirrorrequest/README.md 后,可以选择某一行,点击左侧的菜单,选择 Copy permalink, 即可获得诸如 https://github.com/ustclug/mirrorrequest/blob/f23dd1f1cbe81f01e4f878ac11ee064b6c7d70ec/README.md?plain=1#L1 这样的链接。
- 这样的链接可以在 Issue 中直接粘贴,会被以代码框的形式渲染到 Issue 中,方便其他人迅速了解问题。
- 点击后也可以直接复制地址栏中的 URL,这样的链接总是指向某个 branch 或者 tag 的,而不是特定 commit,但这样的作法可能会导致链接失效。
GitHub Flavor Markdown¶
正如其他编辑器对 Markdown 的支持一样,GitHub 支持一个 Markdown 方言(超集)的写法,称为 GitHub Flavor Markdown。
我们在这里介绍一些你可能感兴趣的 feature:
-
Mermaid 是一种简单且强大的关系图/流程图语法,例如可以通过如下方式创建一个简单的关系图:
graph LR; A-->B; A-->C; B-->D; C-->D;
-
GitHub 通过 MathJax 支持 LaTeX 公式,可以通过
$ \frac 12 $
的形式创建行内公式,$$ \frac 12 $$
的形式创建块级公式。 -
在 Issue 正文中创建一个任务列表,例如:
此时可以将这个 Issue 转化为一个任务列表,方便追踪任务的进度,同时
#123
会被标记为Tracked by #xxx
。
Issue 模板¶
对于大型项目,使用 Issue template 可以使得 Issue 更加规范化,例如,可以在 .github/ISSUE_TEMPLATE/bug_report.yml
中添加如下内容:
name: Bug Report
about: Create a report to help us improve
labels:
- bug
body:
- type: textarea
id: bug-description
attributes:
label: Describe the bug
description: A clear and concise description of what the bug is.
placeholder: I'm always frustrated when...
validations:
required: true
可以参考 ustclug/mirrorrequest/.../01-mirror-request.yml, GitHub 文档.
Pull Request¶
对于 Maintainer 来说,Pull Request 更像是 Merge Request, 他们会检查代码、测试代码、review 代码,然后将代码合并到主分支中。
GitHub 在 这里 介绍了合并 PR 的方式,简单来说跟本地 merge / rebase 没有太大区别。
- PR 中仅有一个 commit 时,推荐使用 Rebase 合并 PR
- 当 PR 中包含多次 commit,但实际上应当合并为一个时(例如经过 Review 后),推荐使用 Squash 合并 PR
- 多次 commit 来提交新 feature 时,推荐使用 Merge 合并 PR
GitHub Actions¶
GitHub Actions 是 GitHub 提供的 CI/CD 服务,可以用于自动化构建、测试、部署等。
GitHub Actions Pricing
对于 Public 仓库,GitHub 提供了免费的服务,对于 Private 仓库,GitHub 提供了 2000 分钟的免费服务。
关于计费问题,可以参考这里。
对于 GitHub Actions 的写法,只需要关心如下几件事情:
- 何时应当触发 Action:例如
on: push, pull_request
- 如何在 GitHub Actions 上搭建环境(例如安装依赖、配置环境变量等)
- 产物的存放位置:例如
artifacts
、release
如果涉及到 Secret Key,还应当注意安全问题(限制触发条件、产物等)。
GitHub 在 这里 提供了详细的文档。
Other CI/CD systems¶
以下是一些其他常用的 CI/CD 提供商,它们提供了类似的服务:
考虑到 GitHub Actions 的免费额度,以及与 GitHub 的无缝集成等,已经足够满足大多数项目的需求,因此我们在这里不再详细介绍其他 CI/CD 系统。