Git/Github 笔记

各类操作技巧整理

全局配置(操作一次即可)

1
2
$ git config --global user.email "you@example.com" # 添加全局配置
$ git config --global user.name "Your Name"
1
$ ssh-keygen -t rsa -C "you@example.com" # 生成 ssh 密钥对(公钥和私钥)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Generating public/private rsa key pair.
Enter file in which to save the key (/home/lsy/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/lsy/.ssh/id_rsa.
Your public key has been saved in /home/lsy/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:fovO3yeP8R4GoJLq6R8r6TuyE1W8cZY7NDPjLsTnpRo siyouluo@qq.com
The key's randomart image is:
+---[RSA 2048]----+
| . . |
| + X |
| o B *. |
| . +.=... |
| . .o+S+ . |
| . .Eo+ . |
| ....+. . . o |
| o.+..+ o o.=.. |
| .**=o.+.o o=+ |
+----[SHA256]-----+
1
2
$ cat ~/.ssh/id_rsa.pub # 在 GitHub 网站上个人设置里添加如下公钥
ssh-rsa AAAAB3 ********

局部配置(对单个仓库的操作)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ git init # 初始化仓库 
$ git remote add origin <remote url> # 将本地仓库与远程仓库进行关联(对每个仓库操作一次即可)
$ git add <filename> # 暂存文件
$ git commit -m "commit message" # 提交到本地仓库
$ git branch -M main
$ git push -u origin main # 推送到远程仓库
对象计数中: 3, 完成.
Delta compression using up to 16 threads.
压缩对象中: 100% (2/2), 完成.
写入对象中: 100% (3/3), 3.55 KiB | 3.55 MiB/s, 完成.
Total 3 (delta 0), reused 0 (delta 0)
To <remote url>
* [new branch] main -> main
分支 'main' 设置为跟踪来自 'origin' 的远程分支 'main'

怎么写 Git 提交日志?

规范

在一个团队协作的项目中,开发人员需要经常提交一些代码去修复 bug 或者实现新的 feature。而项目中的文件和实现什么功能、解决什么问题都会渐渐淡忘,最后需要浪费时间去阅读代码。但是好的日志规范 commit messages 编写有帮助到我们,它也反映了一个开发人员是否是良好的协作者。

编写良好的 Commit messages 可以达到 3 个重要的目的

  • 加快代码 review 的流程
  • 帮助开发人员编写良好的版本发布日志
  • 让之后的维护者了解代码里出现特定变化和 feature 被添加的原因

本项目建议使用 Angular 规范 来编写提交日志, 主要由 header, bodyfooter 三部分组成. 其中 header 包括 typesubject, 示例如下.

1
2
3
4
5
<type>: <subject>

<body>

<footer>
  • header: 应当尽量简短, 描述重要更新.

    • type: 本次提交的类型, 可从如下类型中选择一个:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      # 主要 type
      feat: 增加新功能
      fix: 修复 bug

      # 特殊 type
      docs: 只改动了文档相关的内容
      style: 不影响代码含义的改动,例如去掉空格、改变缩进、增删分号
      build: 构造工具的或者外部依赖的改动,例如 webpack,npm
      refactor: 代码重构时使用
      revert: 执行 git revert 打印的 message

      # 暂不使用 type
      test: 添加测试或者修改现有测试
      perf: 提高性能的改动
      ci: 与 CI(持续集成服务)有关的改动
      chore: 不修改 src 或者 test 的其余修改,例如构建过程或辅助工具的变动
    • subject: 简明扼要的阐述下本次 commit 的主旨, 是 commit 目的的简短描述, 建议不超过 50 个字符, 遵循如下规范:
      • 使用祈使句与一般现在时: “change” not “changed” nor “changes”
      • 首字母不要大写
      • 句尾不要标点
  • body: 同样使用祈使句, 一般现在时. 在主体内容中我们需要把本次 commit 详细的描述一下, 比如此次变更的动机, 以及变更的内容.

  • footer: 如果本次提交解决了 Github 上的某个 issue, 可以在这里关闭. 如果本次提交包含不兼容的更新, 则在此处标示并说明, 例如

    1
    BREAKING CHANGE: [the rest commit message]

    或者

    1
    2
    3
    BREAKING CHANGE: 

    [the rest commit message]

提交方式

如果一个 Git 提交日志按照上述规范编写, 就不适宜在命令行中通过 git commit -m "commit message" 的方式进行提交了.

实际上, git 允许我们将提交日志写在一个文件中, 然后指定该文件作为提交日志进行提交: git commit -F COMMIT_EDITMSG.md.

另一种更加简单的方式是在 VS Code 中添加更改后点击提交,将自动打开 COMMIT_EDITMSG 编辑窗口来写入提交日志,写入完毕后保存并关闭该窗口即可完成提交.

更多 git 使用方法可参考

案例

案例一: 压缩 commit 历史

如果在本地修改文件后,进行了多次提交,但实际上每个提交只是小修,算不上一个完整的版本,我希望把多个提交合并为一个提交(即删除中间若干步骤的提交历史),但保留最后版本的文件

1
2
3
4
5
6
7
8
9
10
11
12
lsy@ubuntu1804:~$ git log --oneline
516f335 第二版
6004a9a 小修 3
c53a436 小修 2
178d8c9 小修 1
7f57867 第一版
lsy@ubuntu1804:~$ git reset --soft 7f57867 # 把提交历史回退到第一版,但本地文件仍然是第二版(中间三次小修都被合并到第二版的修改)
lsy@ubuntu1804:~$ git log --oneline
7f57867 第一版
lsy@ubuntu1804:~$ git commit -m " 第二版 " # 重新提交第二版,中间若干次小修的文件内容被合并到最后一次提交
lsy@ubuntu1804:~$ git push origin HEAD --force # 如果中间的提交曾 push 到了 GitHub, 那么执行该命令把本地记录强行同步到 GitHub(即把 GitHub 上的小修版本的提交记录也删除)

注意: 如果是多用户同时维护该代码库,那么本地操作尽量不要影响其他人的工作. 所以请谨慎提交!

案例二: 从文件中读取内容作为 commit message

首先编写 commit_msg.md 文件作为 commit message,然后在 commit 时使用 -F 来指定该文件.

1
$ git commit -F commit_msg.md

案例三:从远端拉取仓库并保持关联

1
git clone git@github.com:<...>/<...>.git

案例四 修改本地分支名,跟踪远程分支

1
2
3
4
git branch -m main <BRANCH> # 将 main 分支更名为 <BRANCH>
git fetch origin
git branch -u origin/<BRANCH> <BRANCH> # 让本地分支 <BRANCH> 跟踪远程分支 origin/<BRANCH>, 二者无需同名
git remote set-head origin -a

案例五 本地创建仓库推送到远端

1
2
3
4
5
6
7
echo "# tools" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main # 这会将当前分支重命名为 main
git remote add origin git@github.com:siyouluo/tools.git
git push -u origin main

案例六 推送本地仓库到远端

1
2
3
git remote add origin git@github.com:siyouluo/tools.git
git branch -M main
git push -u origin main

案例七 权限问题

Windows 系统上安装了Git+TortoiseGit,生成ssh key 并添加到 Github 后无效,在克隆仓库时报错:
Please make sure you have the correct access rights and the repository exists

解决办法:

  1. 删除 C:\Users\SiyouLuo\.ssh 文件夹下的全部文件;
  2. Git Bash 中设置用户名 / 邮箱:
    1. 设置用户名: git config --global user.name "Luo Siyou"
    2. 设置用户名邮箱: git config --global user.email "siyouluo@qq.com"
    3. 查看设置: git config --list
  3. 生成密钥对: ssh-keygen -t rsa -C "siyouluo@qq.com", 密钥直接存放在 C:\Users\SiyouLuo\.ssh 文件夹下即可.
  4. 将公钥添加到 Github 中的 SSH keys 中.
  5. 然后在 Terminal/Git Bash/TortoiseGit 中都可以克隆仓库了.(注意,私有库需使用 git@github.com:xxx 类型的 url )

参考

Git Flow

使用 Git 进行团队协作开发不可避免的涉及分支的创建与合并等操作, 为了维护 Git 分支结构清晰, 让大家有效地合作,必须要有一个规范的工作流程 (Work Flow). 工作流程的设计应该符合团队的规模、协作模式、项目特性等. 前人已经发明了多种基于 Git 协作的工作流, 长期以来被广泛使用.

这里介绍 Vincent Driessen, 2010 提出的 Git Flow.
详细规范以及操作指令主要可以参考如下两个博客文章进行深入学习.

补充:

这里对 Git Flow 的核心部分进行简要介绍. 其分支模型图如下.


Git Flow 的分支模型中包含如下分支:

  • master: 主分支, 代码库应该有且仅有一个主分支. 所有提供给用户使用的正式版本,都在这个主分支上发布. master 分支必须时常保持着软件可以正常运行的状态, 所以不允许开发者直接对 master 分支的代码进行修改和提交. 只有在预发布分支 release 分支经过充分测试后, 被合并到 master 分支; 或者 master 分支的代码在日常运行中出现 bug, 然后创建 hotfix 分支修复 bug 后合并到 master 分支. 每发布一个 master 分支, 都必须打上 tag, 分配版本号并附带相关说明.
    • 语义化版本格式: x.y.z
    • x: 主版本号, 在重大功能变更,或者版本不向下兼容时 +1, 此时 y, z 归零
    • y: 次版本号, 在添加新功能或者删除已有功能时 +1, 此时 z 归零
    • z: 修订号, 只在进行内部问题修改后 +1.
  • develop: 主开发分支, 是开发过程中代码中心分支. 与 master 分支一样,这个分支也不允许开发者直接进行修改和提交. 程序员要以 develop 分支为起点新建 feature 分支, 在 feature 分支中进行新功能的开发或者代码的修正. 也就是说 develop 分支维系着开发过程中的最新代码,以便程序员创建 feature 分支进行自己的工作. 当所有新功能开发完成后, 开发人员自测完成后, 此时从 develop 创建 release 分支, 进行预发布.
  • release: 预发布分支, 在这个分支,我们只处理与发布前准备相关的提交,如果 release 分支存在很小的 bug, 应当就地修正, 该分支绝对不能包含需求变更或者功能变更等重大修正, 这一阶段的提交数应该限制到最低. 当 release 分支准备好真正发布时, 应当合并到 master 分支, 并给 master 分支打上 tag, 然后将 feature 分支合并到 develop 分支, 确保小 bug 的修正也被合并回去.
  • hotfix: 补丁分支, 当 master 分支中出现重大漏洞时, 派生出 hotfix 分支进行修复, 然后合并回 master 分支以及 develop 分支.
  • feature: 功能开发分支, 以 develop 分支为起点, 创建 feature 分支, 进行代码开发, 实现目标功能, 然后合并回到 develop 分支. 与 develop 分支合并后, 已经完成工作的 feature 分支可以在适当的时机删除.
作者

Luo Siyou

发布于

2023-01-01

更新于

2023-04-21

许可协议