惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Troy Hunt's Blog
Blog — PlanetScale
Blog — PlanetScale
Engineering at Meta
Engineering at Meta
F
Full Disclosure
Recorded Future
Recorded Future
The GitHub Blog
The GitHub Blog
Microsoft Security Blog
Microsoft Security Blog
GbyAI
GbyAI
博客园_首页
博客园 - 叶小钗
MongoDB | Blog
MongoDB | Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Recent Commits to openclaw:main
Recent Commits to openclaw:main
H
Hacker News: Front Page
人人都是产品经理
人人都是产品经理
The Cloudflare Blog
博客园 - 司徒正美
Webroot Blog
Webroot Blog
Google DeepMind News
Google DeepMind News
Help Net Security
Help Net Security
Cloudbric
Cloudbric
PCI Perspectives
PCI Perspectives
有赞技术团队
有赞技术团队
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
TaoSecurity Blog
TaoSecurity Blog
L
Lohrmann on Cybersecurity
量子位
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Tailwind CSS Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
B
Blog RSS Feed
Apple Machine Learning Research
Apple Machine Learning Research
大猫的无限游戏
大猫的无限游戏
P
Proofpoint News Feed
N
News and Events Feed by Topic
罗磊的独立博客
T
Threat Research - Cisco Blogs
Schneier on Security
Schneier on Security
T
Tor Project blog
IT之家
IT之家
M
MIT News - Artificial intelligence
S
Security @ Cisco Blogs
O
OpenAI News
AI
AI
S
Securelist
Simon Willison's Weblog
Simon Willison's Weblog
The Last Watchdog
The Last Watchdog
月光博客
月光博客
Security Archives - TechRepublic
Security Archives - TechRepublic
L
LINUX DO - 热门话题

Dvel's Blog

Rime 全拼双拼混输 CHD 油猴脚本:每日签到自动答题 Rime 配置:雾凇拼音 Hammerspoon 自动切换输入法 修复 Hugo 本地图片的累计布局偏移(CLS)问题 macOS 利用 Karabiner 修改 Emacs 键位为 Vim 键位 macOS 修改 Emacs 键位为 Vim 键位 Surge 配置 汉字的混乱 Netflix 中英双语字幕的好办法 优化 Rime 英文输入体验 判断字符是否为简体字或繁体字 Cloudflare 转入域名提示「出现了问题。请重试转移此域。尚未向您收费。」 图片压缩:Squoosh、TinyPNG、ImageOptim、WebP macOS grep + sed 批量替换多个文件的内容 在 macOS 根目录创建文件夹 博客图床小妙招 折腾 Hugo & PaperMod 主题 利用 Cloudflare Workers 进行批量 301 重定向 将博客部署在 Cloudflare Pages Alfred File Navigation(文件导航器)详解 在 Hugo Goldmark Markdown 中设置以新标签打开链接 日期与时间(UTC、GMT、时间戳、时区) 让 Alfred 以新标签的方式打开 Finder 用 git filter-branch 给 Git 仓库瘦身 qBittorrent 设置教程 联通光猫破解+桥接记录 配置 Mac 终端走代理 Steam for Mac 中文游戏推荐 我的 Mac 软件/工具列表 《Flask Web 开发》笔记 用 sleepwatcher 让 Mac 在睡眠及唤醒时自动执行一些脚本 解决 pyenv 导致的 brew warning 《SQL 必知必会》笔记 Python 异步 IO 笔记 再见,双点医院! 用 CloudXNS 解决 CNAME 与 MX 记录冲突 你好,Hugo! 为 Mac 打造 zsh command line 环境 新 Mac 新装修 秦皇岛暑期自驾的烦恼 苹果公司开发者账号申请流程 UIScrollView 中使用 Masonry 解决 CocoaPods 的类库 import 没有提示 iOS 使用 CocoaPods 的快速回顾 GitBook 简单生成本地静态 HTML 的方法 你好, Hexo! About
Git 自总结
Dvel · 2019-04-07 · via Dvel's Blog

虽然用了很久的 Git 了,但基本上只是 add、commit、push、pull,这次系统性的学习了一遍。

整体是按照 Github 官方教程,由牛客网翻译的视频 的顺序排下来的。

内容上外加网上的各种博文总结和补充了一些。

Setup

$ brew install git

Config

Git 希望知道每次提交的作者信息,来说明是谁进行的本次提交,这会随着版本迭代永久纳入历史记录中。

$ git config --global user.name "my name"
$ git config --global user.email xxx@example.com

user.email 最好与 github 中的邮件地址相同,否则 push 后在 github 上并不会准确显示出是自己。

配置文件:

~/.gitconfig 中同样可以修改和查看上述配置,或修改 Git 全局忽略的位置信息等。

SSH

配合 SSH Key 在 Github 中可以免去输入密码的环节。

生成密钥:

$ ssh-keygen -t rsa -C "youremail@example.com"

~/.ssh/id_rsa.pub 中取得公钥并上传 GitHub。

Init

创建本地仓库:

$ git init

Github 上创建仓库,可遵循 Github 的提示:

  • create a new repository on the command line:
echo "# test" >> README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin https://github.com/xxx/test.git
git push -u origin master
git remote add origin https://github.com/xxx/test.git
git push -u origin master

status

查看状态:

$ git status

可以查看目前所有文件的状态,改动文件较多时推荐使用更简洁易读的:

$ git status -s
  • ?? 新文件,未跟踪
  • A 新文件,已跟踪
  • M 修改
  • D 删除

接下来是 Git 的提交三部曲:

  • 新建或修改文件
  • 加入到暂存区
  • 提交到仓库

Add

Add:将改动登记到暂存区:

单一文件的新建、修改、删除:

$ git add filename

也可以一次性 add 所有变更:

$ git add .

在简单操作中,add 被理解为把文件添加到暂存区没太大问题,但实际是它暂存的是修改而不是文件。

$ echo aaa > file
$ git add file
$ echo bbb >> file
$ git commit -m "bug fix"

上例中,只有 aaa 这一行的修改被暂存,所以版本库中只有 aaa,现在使用 diff 命令仍然可以看到 bbb 并没有被提交。

关于 git add .

在谷歌前几页几乎所有的博客中都强调了这一点:

git add -A = git add -u + git add . (错误的,见下文)

  • git add . 将文件的修改、新建,登记到暂存区(错误的,见下文)
  • git add -u 将文件的修改、删除,登记到暂存区
  • git add -A 将文件的修改、新建、删除,登记到暂存区

macOS 自带的 git 默认都是 2.20 版本了,在 stackoverflow 中的评论中看到,2.0 版本后 git add . 已经和 git add -A 效果相同。(https://stackoverflow.com/questions/15011311/whats-the-difference-between-git-add-u-and-git-add-a/27854048)

所以在大部分情况,只需要记住 git add . 这一个命令就足够了。


Commit

commit: 将暂存区提交到版本库:

$ git commit -m "message..."

如果不使用 -m 参数填写提交信息,git 会打开一个文本编辑器让你输入


工作区、暂存区、仓库区

diff 在 GUI 中观察更为舒适,但下一章 diff 的三种比较模式可以让新手深入了解三大区的变更状态。

工作区(Workspace)

即你肉眼可见的项目目录。

暂存区(Index/Stage)

一般存放在 “.git目录下” 下的index文件(.git/index)中,所以我们把暂存区有时也叫作索引(index)。它保存了下次将提交的文件列表信息,Git 对暂存区在命名和命令上有多个名字,包括Index,Stage,Cache。

本地仓库(Repository)

版本库即 .git 这个隐藏目录,真正存储各版本代码库的地方。

远程仓库(Remote)

协作开发时或个人备份用,存储在 GitHub 等平台或自建 git 的远端仓库,可用于多方共同开发。

Git

Git

日常操作与几大区的关系:

-> 修改代码、新建文件等操作,工作区发生改动

-> add:将改动内容"登记"到暂存区

-> commit:将暂存区的所有内容提交到本地仓库。

只有 commit 了,我们的代码才真正的进入到 git 仓库了。

-> push: 将本地仓库推送到远程仓库

Diff

三种比较模式

$ git diff

比较对象:工作区 与 暂存区(此时暂存区的内容是上一次提交的内容)

使用情景:日常命令,看看这次改动了什么。


$ git diff --staged
$ git diff --cached # 效果同上

比较对象:暂存区 与 版本库(上一次提交的内容)

使用情景: add 所有改动后,git diff 将不会显示任何东西了,在 commit 之前,仍可以使用 --staged 进行对比。


$ git diff HEAD

比较对象:工作区 与 版本库(上一次提交的内容)

使用情景:比如 add 后,又对这个文件进行了修改,在再次 add 之前,想看看在上一次提交之前都做了哪些改动。

经过自己动手测试,通过 Diff 章节应该能基本掌握工作区、暂存区、版本库之间的关系了。

diff 修饰命令

diff 默认是按行显示区别的,这两个命令会获得一种对长行小改动而言更易读的报告:

$ git diff --color-words
$ git diff --word-diff

不输出代码改动,仅仅告诉你哪些文件遭遇了改动:

$ git diff --stat

Log

了解仓库的提交历史:

$ git log

关于 40 位的 16 进制字符:(Git 保证完整性)

Git 中所有数据在存储前都计算校验和,然后以校验和来引用。 这意味着不可能在 Git 不知情时更改任何文件内容或目录内容。 这个功能建构在 Git 底层,是构成 Git 哲学不可或缺的部分。 若你在传送过程中丢失信息或损坏文件,Git 就能发现。

Git 用以计算校验和的机制叫做 SHA-1 散列(hash,哈希)。 这是一个由 40 个十六进制字符(0-9 和 a-f)组成的字符串,基于 Git 中文件的内容或目录结构计算出来。 SHA-1 哈希看起来是这样:

24b9da6552252987aa493b52f8696cd6d3b00373

Git 中使用这种哈希值的情况很多,你将经常看到这种哈希值。 实际上,Git 数据库中保存的信息都是以文件内容的哈希值来索引,而不是文件名。


$ git log --oneline

每行一个简短的概要:标识符+提交信息


$ git log --patch

在原始 log 显示内容的基础上,增加每次提交的代码改动情况。


$ git log --stat

在原始 log 显示内容的基础上,增加每次提交的代码改动情况。(不输出代码改动,仅仅告诉你哪些文件遭遇了改动,类似 diff 中的 --stat 效果)


$ git log -- directory/filename.ext

后接 -- 再接文件名,可以查看仅针对此文件的 log 记录。

常用组合命令

$ git log --graph --all --decorate --oneline

支持分支、标签的查看,快速了解整个项目的发展历程。

Remove

$ git rm

可以不用学习的命令,增删改都可以用 add 命令登记。

$ git rm xxx

该命令完成两件事:

  1. 删除文件
  2. 将删除文件这个操作’‘登记’‘到暂存区

如果你在本次变更中只进行了此次操作,可以直接 commit,不用再 add 登记了。

如果你通过终端执行了 rm 操作 / 在编辑器或 IDE 中执行了删除操作 / 在电脑上直接删除文件:

则只完成了第一步的内容,仍然可以通过 git rm xxx 命令将删除文件这个改动登记到暂存区。

$ git rm --cached

这个命令将删除一个文件,但并不是从系统中真正的删除。只是告诉 git 请不要再跟踪这个文件,这个文件将仍然保留在我的工作区中。

情景说明:当我使用 JetBrains 全家桶时,项目下面会有一个 .idea/ 的目录,里面也许会包含一些个人信息或无用信息,这个目录已经被纳入 git 管理了。

目的:并不在本地删除 .idea/ 目录及其中文件,只是取消被 git 追踪。

需配合 .gitignore 文件使用。

  1. 创建 .gitignore 文件,写入一行内容:.idea/ 即可。
  2. $ git rm -r --cached .idea/ (-r 是递归目录,如果只是单个文件可取消这个参数)
  3. add 与 commit 完成本次修改

以后即使 .idea/ 目录里面发生了文件的增删改,git 也不会理会。

Move

$ git mv file.ext xxx/file.ext

rm 类似,同时完成移动与 add。

基本很少用到,一般都用系统自带的文件管理器或 IDE、编辑器来移动文件,然后 add 即可。

建议使用情景:在同一次提交前,既修改了超过 50% 的代码,又想修改文件名。(参考忒修斯之船)


$ git log --stat -M --follow directory/file.ext

加上 -M —follow 参数,可以 log 出文件的移动。

Ship of Theseus (忒修斯之船)

忒修斯悖论来比喻代码修改:

  • 某些 CVS:当移动文件后,它认为只是一个完全不同的东西,无法追踪文件的移动过程。
  • 某些企业版 CVS:每个文件都有标识,有个数据库来记录,可以轻易的追踪文件的移动。
  • Git:当一个文件至少有 50% 相似度时,这是同一个文件,小于 50% 时,这是一个新文件。

在移动并修改文件后 commit,Git 会反馈出一个百分比:

[master 48f02f2] 本次提交信息
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename xxx => xxx/xxx (100%)

100% 即代表是纯移动,未做修改。

默认为 50%,低于这个阈值时,Git 会直接显示创建与删除:

[master 9a28f41] 本次提交信息
 2 files changed, 3 insertions(+), 1 deletion(-)
 create mode 100644 xxx
 delete mode 100644 xxx/xxx

50% 这个默认数值是可以修改的,视频只是简单打了个示例代码并未详细说明,我觉得这可能是个几乎永远不会用到的功能。

Ignore

创建 .gitignore 文件并写入规则,来使 Git 去忽略哪些你不想纳入版本控制的文件与文件夹。

在被 gitignore 之前已经被 Git 追踪的文件不受 gitignore 规则的影响。

比如 Python 生成的 __pycache__ 文件夹,JB 全家桶的 .idea 文件夹,macOS 的 .DS_Store 文件,都属于无用文件。或者存储了数据库密码的配置文件,是绝对不能纳入版本控制的。

.gitignore 书写规则

# 注释行以 # 开头
# 文件名中有 # 怎么办 -> 加一个反斜杠转义
# 文件名中有 ! 怎么办 -> 加一个反斜杠转义
# 文件名最后有空格怎么办 -> 加一个反斜杠转义

# 忽略文件,直接书写文件名
.DS_Store

# 忽略目录,以 / 结尾
# foo/ 会忽略 foo 目录及此目录下所有内容(但不忽略同名的 foo 文件)
foo/

# 支持通配符 *,忽略所有以 .log 结尾的文件
*.log

# 此文件除外
!a.log
# 如果 a.log 父级目录被忽略,Git 并不会递归这个目录来寻找 a.log
# 即如果 a.log 在 foo/ 中(foo/ 目录已被忽略),写这条规则也没用

# 忽略 bar/ 目录内除了 abc.txt 的文件
bar/*
!abc.txt

# 递归忽略所有 foo 文件和目录
**/foo

# 递归忽略所有 foo 目录及其子目录下的 bar.txt 文件
foo/**/bar.txt

全局忽略

~/.gitconfig 中查看全局忽略文件的配置(默认即可):

...
[core]
	excludesfile = /Users/xxx/.gitignore_global
...

如果没有配置,可以复制粘贴上面的,或者:

$ git config --global core.excludesfile ~/.gitignore_global

编辑 ~/.gitignore_global 文件,规则相同。

在 macOS 中安装完 Git,默认的 .gitignore_global 应该是这样的:

*~
.DS_Store

忽略了所有以 ~ 结尾的文件,忽略了所有 .DS_Store 文件。

全局忽略适用于那些无论使用任何语言或 IDE 都需要忽略的文件,但是此文件只对自己有效,如果想让忽略规则对协作开发的所有成员有效,需要在项目目录正常建立 .gitignore 文件并纳入版本控制。

查看当前已被忽略的所有内容

$ git ls-files --others --ignored --exclude-standard

强制 add 被 gitignore 忽略的文件

$ git add -f filename

检测 gitignore 规则

在日常 git add . 时发现某一文件并不想忽略,但是已经被忽略了,检测命令:

$ git check-ignore -v filename

Branch

查看分支

$ git branch

显示分支一览表,当前所在分支前面有 * 表示。

创建分支

$ git branch 新分支名

删除分支

$ git branch -d 分支名

如果分支没有完全合并,Git 会抛出一个 error,提示你需要将 -d 改成 -D

切换分支

$ git checkout 分支名

Checkout

切换分支

$ git checkout 分支名

创建并切换分支

$ git checkout -b 分支名

相当于同时执行了 git branch 分支名git checkout 分支名

Detached head (头指针分离)

先通过 log 查找到某一时刻的 commit 16 进制标识码。

这个命令会让你的工作区会改变为这次提交时的状态:

$ git checkout 12563de6382baaaaf78c58085b4b9abbe5b26608

Git 会提示:

注意:正在检出 '12563de6382baaaaf78c58085b4b9abbe5b26608'。

您正处于分离头指针状态。您可以查看、做试验性的修改及提交,并且您可以通过另外
的检出分支操作丢弃在这个状态下所做的任何提交。

如果您想要通过创建分支来保留在此状态下所做的提交,您可以通过在检出命令添加
参数 -b 来实现(现在或稍后)。例如:

  git checkout -b <新分支名>

HEAD 目前位于 12563de 本次的commit message

这时 checkout 命令相当于一个时光穿梭机,你可以检出任意一次提交时的状态。

注意这不是版本回退。如果你强行修改 + add + commit,Git 会自动帮你创建一个分支。

退出时光穿梭机:

$ git checkout 分支名

Discarding edits (撤销修改)

见下面章节

Merge

合并分支

$ git merge dev

将 dev 分支合并到当前分支,dev 分支会仍然存在。

Fast-forward

  1. 假设当前只有 master 分支
  2. 创建并切换到 dev 分支
  3. 进行了一次或 N 次的修改,但是 master 分支根本没人动
  4. 切换到 master 分支,合并 dev 分支

即便会导致冲突的地方,也会被 dev 分支的内容覆盖。

这就是 Fast-forward (快进)合并模式,关键点在于 master 分支无人推进。

缺点:历史记录是一条冗长的直线,删除分支后会丢失分支信息。

解决冲突

当 master 和 dev 两条分支都并行推进的时候,在 master 分支合并 dev 分支时,如果同一行都被修改了,就会产生冲突。

自动合并 xxx
冲突(内容):合并冲突于 xxx
自动合并失败,修正冲突然后提交修正的结果。

冲突以 <<<<<<< ======= >>>>>>> 隔开,分别展示两个分支的不同内容。

<<<<<<< HEAD
master!!!
=======
dev!!!
>>>>>>> dev

取其一或将这一整体变成你想要的内容即可。

--abort

$ git merge dev
... (发现冲突)
$ git merge --abort

--abort 选项会尝试恢复到你运行合并前的状态,相当于你没有进行本次合并。

--suqash

$ git merge --squash dev
$ git commit -m "提交信息"

与直接合并结果相同,但是不提交、不移动 HEAD,因此需要一条额外的 commit 命令。

合并后 master 分支很干净,只保留一条记录。

删除 dev 分支后,dev 分支信息消失。

--no-ff

$ git merge --no-ff dev -m "提交信息"

禁用 Fast-forward 模式,这样在删除分支后也会保留分支信息。

我觉得这个命令记录的提交内容比较全面且容易理解,但分支多的时候会让历史记录看起来比较混乱。

删除 dev 分支后,dev 分支信息仍然保留。

Network

Remotes

$ git remote add 远端名称 远端地址
# 例如:
$ git remote add origin https://github.com/aaa/bbb

# 修改 URL
$ git remote set-url origin https://github.com/aaa/ccc

# 删除远端链接
$ git remote rm 远端名称
# 例如:
$ git remote rm origin

# 查看所有远端链接
$ git remote -v

# 查看所有远端分支名
$ git branch -r
# 所有远端的分支前都加上了远端名称,例如 origin/master、origin/dev

终于知道 origin 到底是什么意思了。

其实没什么意思,就是约定俗成的,如果你只有一个远端,比如这份代码只放在 Github 上,或只放在 码云 或 Coding 上,那就把远端起名叫 origin,这样大家看到了都懂。

如果你这份代码在本地修改后,既要 push 到 Github,又要 push 到其它某平台,那两个远端名称就可以自己定制。

Fetch, Pull, Push

$ git fetch origin master # 先拉取更新,fetch 不会更改本地工作区内容
$ git merge origin/master master # 将远程内容与本地内容合并
$ git pull origin master # 拉取并合并
$ git push origin master # 将本地内容推送到远程仓库

只有单个远程主机时,一般都命名为 origin。

在任何分支第一次 push 时,Git 会提示:

fatal: 当前分支 xxx 没有对应的上游分支。
为推送当前分支并建立与远程上游的跟踪,使用

    git push --set-upstream origin xxx

你可以输入这个命令让本地分支与远程分支建立连接。

也可以在每个分支的第一次 push 时使用 -u 参数:

$ git push -u origin xxx

以后就可以使用简化命令 git push 了。

Push 所有分支到远端:

$ git push --all

有多个远程主机时,比如 Hexo、Hugo 博客可能同时会部署到 GitHub 和 Coding,也会起不同的远程主机名,这时 -u 参数可以指定一个默认主机,不带参数时就默认 push 到这个远程主机。

GitHub 相关章节

GUI:主要是 GitHub Desktop 的介绍,我个人日常操作更喜欢用命令行,但是 GUI 在查看历史进度和 Diff 时更方便快捷。

GitHub:GitHub 的相关介绍

Forking:GitHub 的 Fork 功能相关介绍。

Pull Requests:GitHub 的 Pull Requests 功能相关介绍。

Reset

见下面章节

撤销修改与版本回退

必须理解的概念:

三个区:工作区、暂存区、版本库,或三棵树:Working Directory、Index、HEAD。

→ 改动代码,工作区改动

→ add,将改动登记到暂存区

→ commit,将暂存区提交到版本库,HEAD 指向当前分支的最后一次提交

→ …

→ 又一次 commit,将暂存区提交到版本库,HEAD 依然指向当前分支的最后一次提交

HEAD 是当前分支引用的指针,它总是指向该分支上的最后一次提交。 这表示 HEAD 将是下一次提交的父结点。 通常,理解 HEAD 的最简方式,就是将它看做 你的上一次提交 的快照。

撤销修改

当你对修改不太满意,想恢复初始状态:

# 单个文件撤销
$ git checkout -- 文件名
# 所有文件撤销
$ git checkout . 

如果 add 进暂存区了,先撤销暂存区,再撤销工作区:

# 单个文件:
$ git reset HEAD 文件名
$ git checkout -- 文件名
# 多个文件:
$ git reset HEAD
$ git checkout .

如果 commit 进版本库了,那就用 reset 进行版本回退。

Reset

reset 分为三种模式:

  • --soft 保持本地所有改动(工作区、暂存区不变)
  • --mixed 默认,保持工作副本但重置索引(工作区不变)
  • --hard 丢弃所有改动

它们的主要区别在于作用覆盖的区域(工作区、暂存区)不一样,HEAD 的指向是必变的,在敲完命令后可以用 diff 的三种比较模式去验证。

以一个例子来讲,这是目前的状况。

$ git log --oneline
4a9dabc (HEAD -> master) 3
e285589 2
116eee9 1
$ git reset --soft e285589
  • 工作区:无变化
  • 暂存区:无变化
  • 版本库:HEAD 指向此版本
$ git reset e285589
$ git reset --mixed e285589 # 同上
  • 工作区:无变化
  • 暂存区:变成此版本
  • 版本库:HEAD 指向此版本
$ git reset --hard e285589
  • 工作区:变成此版本
  • 暂存区:变成此版本
  • 版本库:HEAD 指向此版本

压缩提交 / 合并提交

例子:

$ git log --oneline
900db85 (HEAD -> master) 修复刚才修复刚才修复错误导致的错误导致的错误
656915e 修复刚才修复错误导致的错误
2d7e668 修复错误
57335f5 5
ed32739 4
6a15af1 3
e285589 2
116eee9 1

我认为最后三次这种 commit message 应该合并成一个。

$ git reset --soft 57335f5

HEAD 指向了"版本5",但是工作区和暂存区都是目前的状态,直接 commit 即可。

$ git commit -m "fixed a big bug"

再 log 查看:

$ git log --oneline
5827469 (HEAD -> master) fixed a big bug
57335f5 5
ed32739 4
6a15af1 3
e285589 2
116eee9 1

除了用 reset,在图形化工具 GitHub Desktop 中,选中多个 commit 后点击“Squash n(选中的个数) Commit”,就可以将选中的 n 个提交合并成一个。

Tag

比起混乱的 commit id,标签可以更方便的标记出重要的版本。

狗书《Flask Web 开发》作者配合使用 Tag 功能做了一个相当方便的时光穿梭机,比如第一章第一部分代码使用 1a 作为标签,第二章第三部分代码使用 2c 作为标签,读者只需执行 git checkout 2c 即可查看此次代码。

查看所有标签:

$ git tag

打标签:

# 给最新的 commit 打标签:
$ git tag 标签内容

# 给指定 commit ID 打标签,如:
$ git tag 标签内容 116eee9

# 创建带有说明的标签,用-a指定标签名,-m指定说明文字,可用`git show 标签内容`查看:
$ git tag -a v0.1 -m "version 0.1 released" 1094adb

删除标签:

$ git tag -d 标签内容

删除远端标签:

如果已经 push 到了 GitHub 上,想删除 GitHub 上的标签:

$ git push --delete <远端名成> <标签名称>

例如:

$ git push --delete origin v1.0

默认 push 时不推送标签,推送标签命令:

# 推送单个标签
$ git push 标签内容

# 推送所有标签
$ git push --tags

Rebase (变基)

https://www.git-tower.com/learn/git/ebook/cn/command-line/advanced-topics/rebase

推荐看一些文章后用 https://learngitbranching.js.org/ 这个教程试一试。

一个简洁的工作流教程:https://www.bilibili.com/video/BV19e4y1q7JJ

补充

命令行显示 utf-8 字符

git status 等命令下使 Git 使用 utf-8 编码显示中文等字符,而不是\123\123\123\123 这样的格式。

参考:https://stackoverflow.com/questions/22827239/how-to-make-git-properly-display-utf-8-encoded-pathnames-in-the-console-window

$ git config core.quotepath off

全局:

$ git config --global core.quotepath off

还原:off 改成 on

bisect

看到一个 git bisect 命令挺好玩的,用类似二分法去快速定位是哪次提交引起了当前的错误:

git bisect 命令教程 - 阮一峰的网络日志

提交时关闭 issue

参考:https://stackoverflow.com/questions/60027222/github-how-can-i-close-the-two-issues-with-commit-message

可以使用 close, closes, closed, fix, fixes, fixed, resolve, resolves, resolved 等单词,如:

$ git commit -m "巴啦巴啦; close #233"

可以同时关闭多个 issue:

$ git commit -m "closes #1, closes #2, closes #3; YOUR COMMIT MESSAGE"