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

推荐订阅源

SecWiki News
SecWiki News
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V
Visual Studio Blog
博客园 - 叶小钗
S
SegmentFault 最新的问题
IT之家
IT之家
大猫的无限游戏
大猫的无限游戏
博客园_首页
Apple Machine Learning Research
Apple Machine Learning Research
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
月光博客
月光博客
酷 壳 – CoolShell
酷 壳 – CoolShell
腾讯CDC
D
Darknet – Hacking Tools, Hacker News & Cyber Security
V
V2EX
阮一峰的网络日志
阮一峰的网络日志
L
Lohrmann on Cybersecurity
量子位
C
Cyber Attacks, Cyber Crime and Cyber Security
T
Tor Project blog
J
Java Code Geeks
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
博客园 - 三生石上(FineUI控件)
Attack and Defense Labs
Attack and Defense Labs
AI
AI
The Cloudflare Blog
T
Tailwind CSS Blog
S
Schneier on Security
爱范儿
爱范儿
PCI Perspectives
PCI Perspectives
Stack Overflow Blog
Stack Overflow Blog
S
Secure Thoughts
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
T
The Exploit Database - CXSecurity.com
博客园 - 【当耐特】
V2EX - 技术
V2EX - 技术
S
Securelist
P
Proofpoint News Feed
T
Threat Research - Cisco Blogs
Help Net Security
Help Net Security
C
Cisco Blogs
N
News and Events Feed by Topic
人人都是产品经理
人人都是产品经理
B
Blog RSS Feed
K
Kaspersky official blog
T
The Blog of Author Tim Ferriss
G
Google Developers Blog
S
Security Affairs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Simon Willison's Weblog
Simon Willison's Weblog

一个工匠

AI 发展临界点 - 快上车 流式响应(Chat):HTTP 响应体字节流的读取与解析 iPhone 截屏高效翻译 Flash Open Terminal iPhone 侧载安装 Xcode Symbolic Debug AI 指北 投资风险收益评估 Mac 快速修改系统快捷键 passkey How to pay apple frameworks Mac - Command Line Tools DNS 的 CNAME 是如何工作的 WebRTC 的一些解释 SSE 指南 1.1.1.1、WARP 和 MASQUE 移动端换端方案与场景还原 设备发现 分辨率 - 像素密度 - HiDPI Mac 字体 ESP32 trump - 川普 币圈 - 虚拟货币 【旅游】富士山 【旅游】sakura(樱花) 【旅游】千岛湖 我的 2023 【Swift】中文词语纠错 计算机字符编码与内存编码 - Unicode、UTF8、String 从汇编角度理解 “函数调用栈” 和 “有栈协程” 在 Xcode 中更好的使用 Swift 通过 Swift Package 制作二进制库 Arc 浏览器 - 意外的惊喜 【Swift 三方源码 1】SwiftShell 高效的命令行工具 Swift 脚本开发环境搭建 rime - 小鹤双拼 【旅游】沿海旅游 (威海、青岛) 好记性远远不如烂笔头 高级语言小记 又一年高考 Vision 未来已来 致敬耗子哥 Socket 与 ICMP 对互联网隐私的一些想法 网络代理是如何工作的 (致敬 Surge) 又十年 - 至三十而立 双拼 - 少有的高回报效率技能 Vim 技巧 我的 2022 三年疫情五味杂陈 - 下 老梗 - 浏览器按回车后发生了什么 三年疫情五味杂陈 生活推荐清单 Shell 和进程 有计划的努力 内卷 不确定性 数学可以保障逻辑自洽 这些年我的软件清单 决定做一些改变 函数调用栈之彻底理解 锁 - 共享数据安全指↑ 江苏女有感 碎碎念 - 2022 碎碎念 - 2021 打算记录一些碎碎念 多重性格就是逆天改命 从 Core Foundation 看更大世界 TCP 数据传输过程分析 iOS main 文件中的 @autoreleasepool 的真实用途 多线程的难点在哪里 Objective-C 和 Runtime 早起打卡计划 ing 打比方 IM 和 Socket 的关系及 Heart 的必要性 如果我的人生突然只剩下 8 小时... 胡说八道之雪粉 Array 和 LinkedList 的深刻认知 Swift struct (值类型) 与 class (引用类型) 区别及三种传参机制深刻关系和使用 逃离信用卡和花呗 Swift_let_var_struct_class 网聚人的力量 - 网易 绿皮火车 喝酒十之八九会误事 HKong 胡说八道之云服务 互联网网络传输协议理解坑点 CPU 的制作 我心里一直有一个念想 网络基础协议 为什么 32 位操作系统只能用 4G 内存空间 努力和天赋 洗牙 RAC-Api-Summer iOS 内存原理 Block 闭包简查记录 《白夜行》 谈谈事件驱动 老博新开 祭首
Git Record
海驴 · 2025-05-13 · via 一个工匠

SSH / Personal Access Tokens / GPG Keys / Signing Key / ssh-agent
裸中央仓库 / worktree

Email

通过 ssh key 等方式操作 github 等仓库平台时,只要 ssh 验权通过就可以进行仓库操作。不过对于 git commit 等提交操作,git 会强制要求配置 username 和 email。
不过,email 一定要配置好,和账号的 email 一致。github 虽然不对 email 进行操作验证,但是在显示 verified 等标记的时候,还是会校验 email 的。如果 email 不对,则标记 Unverified

整体来说,虽然不强求,但尽量配置好。

SSH Key

github 这些 git 平台,除了 https 之外,也支持 git 协议的 ssh 操作。
对于公私钥,本机主要使用私钥,公钥在 github 远程平台上设置。

1
2
3
4
5
6
7
8
9
10
tree ~/.ssh/
/Users/example/.ssh/
├── config
├── id_ed25519_personal
├── id_ed25519_personal.pub
├── id_ed25519_work
├── id_ed25519_work.pub
├── known_hosts
├── company-key
└── company-key.pub

当需要在一台主机上管理多个 github 账号的时候,需要在 config 文件中进行如下配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
> cat ~/.ssh/config

Host github-personal
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_personal

Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_work

Host company-github
HostName github.company.com
User git
IdentityFile ~/.ssh/company-key

对应的 git clone 地址也需要做改变:

1
2
3
4
5
git clone [email protected]:octocat/test.git

->

git clone git@github-personal:octocat/test.git

SSH 与 Personal Access Tokens 的关系

一般操作,使用 SSH Key 的情况下,不需要设置 PAT。

核心区别

  • SSH 认证

  • HTTPS 认证

    • 使用 https://github.com/user/repo.git 格式地址
    • 需要配置 PAT 替代密码(GitHub 已禁用密码认证)

协议检查方法

1
2
3
git remote -v


需要 PAT 的场景

  1. 调用 GitHub REST API
  2. 使用 GitHub CLI (gh) 操作敏感资源
  3. 访问 GitHub Packages 服务(npm / Docker 等)
  4. 操作其他 HTTPS 协议的仓库时
  5. 第三方 CI / CD 工具集成
  6. 使用 GitHub Actions 需要访问仓库时
  7. 使用双重认证 (2FA) 的账户通过 HTTPS 协议操作仓库

mac 钥匙串存储 PAT

git 客户端(命令)会在用户输入 PAT 后,将 PAT 存储到 mac 的 keychain 中,并和 github domain 绑定。
这个时候,如果有多个 github 账号,就会发生冲突,导致其中一个 github 账号下面的 pat 验证失败。
所以,需要使用 https://github.company.com/xxx/xx.githttps://alias.github.com/xxx/xx.git 这样的格式,来对不同的 github 账号进行区分。

URL 使用 PAT

URL 协议本身是支持增加 username 和 password 的,即 https://username:[email protected]/xxx/xx.git

这个时候,可以把 username 换成 github 账号,password 换成 PAT,就可以在通过 github 授权的情况下操作 xx 仓库了。
原理:

  1. git 客户端会解析 URL,将 username 和 password 提取成 a:b 的格式,进行 base64 编码,放到 “Authorization: Basic ???” 头中。
  2. 服务器端接收到请求后,会进行 base64 解码,获取到 username 和 password,然后进行验证。

不推荐,简单实用一下还是可以的。

Signing Key

github 推出的 commit / tag 等操作的签名认证。被签名的 commit 会在历史记录中显示一个绿色的 verified 标记。
GPG Keys 是专门做这个事情的,其中,github 也推出了自己的 Signing Key,可以复用 SSH Keys 的设置(操作入口在同一个地方)。

具体配置如下,通过在 ~/.gitconfig 中增加 url 分流配置,可以为不同的 host 组设置不同的 signing 规则。

1
2
3
4
5
6
7
8
9
10
// ~/.gitconfig-github-personal

[user]
signingkey = ~/.ssh/id_ed25519_personal
[commit]
gpgsign = true
[gpg]
format = ssh
[tag]
gpgsign = true
1
2
3
4
5
6
7
8
9
10
// ~/.gitconfig-github-work

[user]
signingkey = ~/.ssh/id_ed25519_work
[commit]
gpgsign = true
[gpg]
format = ssh
[tag]
gpgsign = true
1
2
3
4
5
6
7
8
9
10
// ~/.gitconfig

...

[includeIf "hasconfig:remote.*.url:git@github-personal:*/**"]
path = ~/.gitconfig-github-personal
[includeIf "hasconfig:remote.*.url:git@github-work:*/**"]
path = ~/.gitconfig-github-work

...

ssh-agent

ssh 和 ssh-agent 都是 openssh 的一部分。对于 ssh 而言,公私钥中,私钥是可以被加密的,加密后,私钥就无法被直接使用,需要使用 passphrase 进行解密后才能使用。
这个时候操作流程就比较复杂,每次使用 ssh 的时候,ssh 命令通过操作系统弹窗,让用户输入 passphrase,然后对私钥原始内容进行解密获取私钥再使用。

ssh-agent 就是一个内存服务,ssh 拿到解密后的私钥后,直接放到 ssh-agent 中,后续直接从 ssh-agent 中进行读取。

这个时候又会遇到一个问题,就是 macos 系统重启了,ssh-agent 内存数据消失了。所以 ssh 会把 passphrase 存储到 keychain 中,下次启动时,会自动从 keychain 中读取 passphrase。
具体流程是:

  1. macos 重启,ssh-agent 数据清空
  2. 用户操作了 ssh 命令
  3. ssh 客户端,通过 secret api 读取 keychain 中的 passphrase
  4. 对密钥原始数据进行解密后,把密钥放到 ssh-agent 中
  5. 后续直接从 ssh-agent 中读取

配置 ssh-agent 示例 (UseKeychain & AddKeysToAgent):

1
2
3
4
5
6
7
8
9
> cat ~/.ssh/config

Host example.com
HostName example.com
User git
PreferredAuthentications publickey
IdentityFile ~/.ssh/id_ed25519_personal
UseKeychain yes
AddKeysToAgent yes

via https://swiftrocks.com/what-happens-when-you-move-a-file-in-git

裸仓库

【裸仓库】是一个不包含工作区(working tree)的 Git 仓库,只包含 Git 版本库数据(.git 目录中的内容)。在 github 等平台上,我们通过 push、pull 操作的远程仓库,都是【裸仓库】,因为它们只需要存储版本数据,不需要工作区。

裸仓库 一般使用 xx.git 命名文件夹,内部没有工程目录,完全是 git 操作目录,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
tree
.
├── HEAD
├── config
├── description
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-merge-commit.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── prepare-commit-msg.sample
│ ├── push-to-checkout.sample
│ └── update.sample
├── info
│ └── exclude
├── objects
│ ├── info
│ └── pack
└── refs
├── heads
└── tags
  1. 创建 裸仓库:git init --bare example.git
  2. clone:git clone ./path/to/example.git example

worktree

1
2
3
4
5
6
7
8
9
10
11
12
13
NAME
git-worktree - 管理多个工作目录

SYNOPSIS
git worktree add [-f] [--detach] [--checkout] [--lock [--reason <string>]]
[--orphan] [(-b | -B) <new-branch>] <path> [<commit-ish>]
git worktree list [-v | --porcelain [-z]]
git worktree lock [--reason <string>] <worktree>
git worktree move <worktree> <new-path>
git worktree prune [-n] [-v] [--expire <expire>]
git worktree remove [-f] <worktree>
git worktree repair [<path>...]
git worktree unlock <worktree>

git worktree - 管理多个工作目录

核心功能: 允许你从一个 Git 仓库创建多个独立的工作目录,方便同时处理不同分支或任务。

常用命令:

  1. git worktree add <path> [<branch>] - 创建新的工作目录
    • 作用: 在 <path> 创建新的工作目录,并检出 [<branch>] 分支 (默认当前分支)。
    • 常用选项:
      • f: 强制创建,即使目录已存在 (小心数据丢失)。
      • -detach: 创建分离 HEAD 的工作目录 (不关联分支)。
      • b <new-branch>: 创建并检出新分支。
    • 示例:
      • git worktree add -b feature-branch ../feature-branch: 创建新分支 feature-branch 并检出到新工作目录。
      • git worktree add ../working-dir feature-branch: 检出已存在的 feature-branch 分支到新工作目录。
      • git worktree add ../hotfix origin/main: 创建 hotfix 工作目录 (基于 origin/main)。
  2. git worktree list - 列出工作目录
    • 作用: 显示所有已创建的工作目录及其路径和分支信息。
    • 常用选项:
      • v: 显示更详细的信息。
  3. git worktree remove <path> - 删除工作目录
    • 作用: 删除 <path> 指定的工作目录。
    • 常用选项:
      • f: 强制删除,即使工作目录不干净 (小心数据丢失)。
    • 注意: 仅删除工作目录,不影响仓库本身。
  4. git worktree lock <worktree> - 锁定工作目录
    • 作用: 锁定 <worktree>,防止被 git worktree remove 删除。
    • 常用选项:
      • -reason <string>: 添加锁定原因。
  5. git worktree unlock <worktree> - 解锁工作目录
    • 作用: 解锁 <worktree>,使其可以被 git worktree remove 删除。
  6. git worktree move <worktree> <new-path> - 移动工作目录
    • 作用: 将 <worktree> 移动到 <new-path>
  7. git worktree prune - 清理无效信息
    • 作用: 清理已手动删除的工作目录在 Git 仓库中残留的记录。
    • 常用选项:
      • n: 模拟运行,不实际删除。
  8. git worktree repair - 修复工作目录
    • 作用: 修复工作目录的元数据 (通常自动维护,极少手动使用)。

文件夹大小写

Git 对文件夹和文件的大小写,是不敏感的。有些 IDE 会默认做很多事情,让用户无感知。当不通过 IDE 操作 Git 的时候,开发过程中有可能遇到【修改文件夹 / 文件名】无效的场景。

orphan branch

孤儿分支,是指没有父分支的分支。场景:

  • 希望从当前 git 工程独立一份完全没有 git 记录的 new-branch,又需要保留当前 git old-branch 所有的 git 状态
  • 还希望 new-branch 在当前 git 仓库中被管理。
1
2
3
git switch --orphan new-branch
git checkout old-branch -- .

new-branch 将成为独立 commit 节点,没有任何父节点,并且 git 状态和 old-branch 一致。
后面可以新增 remote url,将 new-branch 推送到远程仓库。