跳转到内容

项目

项目 checkout 自动化应该显式且安全。公开的工作站仓库可以描述通用结构,但不应暴露私有工作。

标准布局

本地 checkout 使用 ghq 的目录模型:

text
~/repos/github.com/YunYouJun/workstation

每台机器只需配置一次 ghq

bash
git config --global ghq.root ~/repos

确认当前配置:

bash
git config --global --get ghq.root

尽可能通过 ghq clone 仓库:

bash
ghq get [email protected]:YunYouJun/workstation.git
cd "$(ghq list -p github.com/YunYouJun/workstation)"

这样本地路径会接近远程 URL,也避免 ~/repos/gh/yyj 这类私有简称。

活跃 GitHub 仓库

使用 CLI 拉取并 clone YunYouJun 最近 push 过的仓库:

bash
workstation projects clone-active

该命令默认是 dry-run。确认目标路径后,显式加 --yes 才会写入本机:

bash
workstation projects clone-active --yes

配置最近活跃仓库数量:

bash
workstation projects clone-active --limit 20

更短的写法:

bash
wst p active --limit 20

交互式选择要预览或 clone 的仓库:

bash
wst p active --limit 50 -i

也可以设置脚本默认值,适合写到 shell profile 或机器私有配置里:

bash
WORKSTATION_ACTIVE_PROJECT_LIMIT=20 pnpm projects:clone-active

配置项目根目录:

bash
workstation projects clone-active --root ~/repos

更新已存在的 checkout:

bash
workstation projects clone-active --update --yes

使用 HTTPS clone URL:

bash
workstation projects clone-active --https --yes

包含 forks 和 archived 仓库:

bash
workstation projects clone-active --include-forks --include-archived

如果想用脚本入口:

bash
pnpm projects:clone-active

实现上使用 gh api graphql,按 PUSHED_AT DESC 排序,比按字母或创建时间更接近“最近活跃”。先在本机完成 GitHub CLI 认证:

bash
gh auth login

当已安装 ghq,且主 ghq.root--root 一致时,命令会使用 ghq get。否则回退到显式 git clone 路径:

text
~/repos/github.com/<owner>/<repo>

本地状态巡检

换机或清理旧机器前,检查 ~/repos 下本地 Git 仓库是否还有需要处理的内容:

bash
workstation projects status

短命令和脚本入口:

bash
wst p status
pnpm projects:status

默认只显示需要关注的仓库,包括未提交文件、已提交但未 push、stash、没有 upstream 或 upstream 已消失的分支。显示所有仓库:

bash
workstation projects status --all

默认最多向下扫描 6 层目录。仓库目录嵌套更深时可以调大,想限制扫描范围时也可以调小:

bash
workstation projects status --max-depth 8

用于脚本或离机检查时,如果发现需要关注的仓库就返回非零退出码:

bash
workstation projects status --check

清单模式

清单模式可以 clone 任意 Git 源的常用项目,包括 GitHub、GitHub Enterprise、GitLab、git.example.com 等内部源。命令同样默认 dry-run,确认后再加 --yes

bash
wst p manifest --file projects.local.yaml
wst p manifest --file projects.local.yaml --yes

也可以把常用项目清单放在私有配置仓库里,让 workstation 先读取配置仓库中的 projects.yaml

bash
wst p manifest https://git.example.com/<user>/<config-repo>
wst p manifest https://git.example.com/<user>/<config-repo> --group common --yes

如果清单不在仓库根目录的 projects.yamlprojects.yml,指定内部路径:

bash
wst p manifest --repo https://git.example.com/<user>/<config-repo> --manifest workstation/projects.yaml

私有配置仓库会缓存到 ~/.cache/workstation/project-manifests/。项目本身仍会 clone 到 ~/repos/<host>/<repo-path> 这种接近 ghq 的路径;group 只用于筛选和组织清单,不进入目标路径。当主 ghq.root 与目标 root 一致,且目标路径与 clone URL 推导出的路径一致时使用 ghq get,否则回退到显式 git clone

公开仓库只提交一个示例清单:

text
projects.example.yaml

私有或机器特定项目放在:

text
projects.local.yaml

projects.local.yaml 会被 Git 忽略。

清单格式:

yaml
groups:
  common:
    root: ~/repos
    host: git.example.com
    repositories:
      - name: github.com/YunYouJun/workstation
        url: [email protected]:YunYouJun/workstation.git
      - example/private-service
      - name: local-alias/private-service
        path: example/private-service

如果只写 name: git.example.com/<group>/<repo>,CLI 会默认推断 SSH clone URL;加 --https 时会推断 HTTPS clone URL。也可以在 manifest 或 group 上配置 host,随后用 example/private-service 这类短路径。需要同时支持两种协议时,也可以写 sshUrlhttpsUrl,命令会按 --https 选择。

当本地目标路径需要和远端路径不同,使用对象格式的 name + pathname 是本地路径,path 是远端仓库路径。这种情况会自动避开 ghq get,用显式 git clone <url> <target>,避免 ghq 按远端 URL 放到另一个目录。

Git 多账号与来源隔离

同一台机器访问 GitHub、GitHub Enterprise、公司 GitLab 或其他内部 Git 源时,把“提交身份”和“远端认证账号”分开配置:

  • 提交身份用 Git 的 includeIf 按 checkout 目录选择。
  • 认证账号用 SSH Host / IdentityFile 或 HTTPS credential helper 选择。
  • 全局开启 user.useConfigOnly,避免 Git 自动猜测错误邮箱。
  • 同一个 host 上有多个账号时,使用 SSH Host alias,并把仓库 remote 指向 alias。

全局 Git 配置只负责路由,不直接写默认身份:

ini
[user]
  useConfigOnly = true

[includeIf "gitdir:~/repos/github.com/"]
  path = ~/.gitconfig-github

[includeIf "gitdir:~/repos/git.example.com/"]
  path = ~/.gitconfig-work

不同来源的身份放在独立文件里:

ini
# ~/.gitconfig-github
[user]
  name = Your Name
  email = [email protected]
ini
# ~/.gitconfig-work
[user]
  name = Your Name
  email = [email protected]

SSH 认证账号通过 host 配置决定:

text
Host github.com
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519_github
  IdentitiesOnly yes

Host git.example.com-work
  HostName git.example.com
  User git
  IdentityFile ~/.ssh/id_ed25519_work
  IdentitiesOnly yes

同一 host 多账号时,仓库 remote 使用 alias:

bash
git remote set-url origin [email protected]:team/repo.git

检查当前仓库最终生效的身份与认证入口:

bash
git config --show-origin --get user.name
git config --show-origin --get user.email
git remote -v
ssh -G git.example.com-work | grep identityfile

不建议默认依赖 includeIf "hasconfig:remote.*.url:..." 根据 remote URL 自动切换身份。新 clone、fork + upstream、多 remote 仓库都可能让规则变得含糊;按 ~/repos/<host>/... 目录切换身份更容易预测和审计。

CLI 中对应的初始化任务是 git.include-if。先查看任务和预览写入内容:

bash
wst init --list
wst init git.include-if --git-profile 'id=github;host=github.com;name=Your Name;[email protected]'

确认后再应用:

bash
wst init git.include-if --git-profile 'id=github;host=github.com;name=Your Name;[email protected]' --yes

如果本机已经有 ~/.gitconfig-github 且其中包含 user.name / user.email,也可以直接让 CLI 推断默认 GitHub profile:

bash
wst init git.include-if --yes

需要手动选择初始化任务和输入身份信息时,使用交互模式:

bash
wst init -i

最佳实践

  • 普通项目 checkout 优先使用 ghq
  • Git 提交身份按 ~/repos/<host>/... 目录切换,远端认证账号按 SSH host 或 credential helper 切换。
  • 开启 user.useConfigOnly,让未匹配身份的仓库无法提交。
  • 按用途分组项目,而不是按历史偶然性分组;分组不应改变 clone 目标路径。
  • 公开示例保持通用。
  • 对需要主动 push 的仓库优先使用 SSH URL。
  • Clone 脚本默认使用 dry-run。
  • 仓库已存在时跳过,除非显式请求更新模式。
  • 目标目录应可配置,默认根目录为 ~/repos
  • GitHub 特定的列表和认证流程使用 gh
  • “活跃仓库”发现使用 PUSHED_AT 排序。

清单模式可以继续扩展更多分组,同时不需要把私有仓库名放进公开 Git。对于普通 Git 仓库,它会生成与 ghq 一致的目标路径。

迁移旧路径

如果此仓库已经存在于旧的简称路径,可以移动一次,并只在旧编辑器窗口或脚本还引用旧路径时保留兼容 symlink:

bash
mkdir -p ~/repos/github.com/YunYouJun
mv ~/repos/gh/yyj/workstation ~/repos/github.com/YunYouJun/workstation

mkdir -p ~/repos/gh/yyj
ln -s ~/repos/github.com/YunYouJun/workstation ~/repos/gh/yyj/workstation

当 shell 历史、编辑器工作区和本地脚本都使用新路径后,就可以移除兼容 symlink。

个人工作站笔记、脚本与 dotfiles。