Git Alias 别名
Git Alias 类似于 Linux 的 alias,将常用的命令或复杂的命令串绑定到一个简短名称上,减少重复输入。
基础用法
# 配置到当前仓库(写入 .git/config)
git config alias.<name> '<command>'
# 配置到全局(写入 ~/.gitconfig)
git config --global alias.<name> '<command>'
命令以 ! 开头时,作为 shell 命令执行,可以串联多条命令:
git config --global alias.<name> '!command1 && command2'
配置 后直接使用:
git <name>
查看与管理
# 查看所有已配置的 alias
git config --get-regexp alias
# 删除某个 alias
git config --global --unset alias.<name>
也可以直接写入 ~/.gitconfig
[alias]
<name> = <command>
Alias 收录
lg — 美化 Git Log
详见 Git Log 优化
sync-from-private — 合并时排除 wip/ 目录
场景:本地 master 对应公开仓 origin,本地 private 对应私有仓 private。日常在 private 上开发(代码 + wip/ 私有文档),同步到 master 推往公开仓时,wip/ 既不能出现在公开仓的文件树,也不能在 commit history 里留下痕迹(含 commit message)。
alias:用 --squash 而非普通 merge,避免 private 的 commit chain 被链接到 master 的祖先里(用 merge --no-ff 时 public 仓 git log 能看到 add wip docs 这类 message,目录藏住、history 藏不住)。alias 故意只到 staged 状态,commit 由你自己写 message:
git config alias.sync-from-private \
'!git merge --squash refs/heads/private && git reset HEAD -- wip/ && git clean -fd wip/ && git status'
| 片段 | 作用 |
|---|---|
merge --squash refs/heads/private | 把 private 改动作为 staged 应用到 master,不建立 merge link,private 的 commit history 不进入 master |
reset HEAD -- wip/ | 把 wip/ 从暂存区撤出(变 untracked) |
clean -fd wip/ | 删 untracked 的 wip/(文件、目录都兼容) |
git status | 显示 staged,提醒手动 commit |
日常工作流:
git checkout private # 改代码、改 wip/ → commit → git push private
git checkout master
git sync-from-private # squash 私有改动到 staged 区,排除 wip/
git diff --cached # 复查 staged 内容
git commit -m "feat: add /healthz endpoint" # 自己写 message,不要泄漏 wip/ 细节
git push origin
# 同步后把 private rebase 到 master,前移公共祖先(见说明 5)
git checkout private
git rebase master
git push private --force-with-lease
完整配置流程(从零起一个仓库,先 master 再从它派生 private,保证两分支共享 root commit):
mkdir myrepo && cd myrepo
git init -b master
# 放可公开的代码(不含 wip/)
git add . && git commit -m "init"
# origin = 公开仓
git remote add origin https://github.com/<you>/<repo>.git
git config --add remote.origin.push refs/heads/master:refs/heads/master
git push -u origin
# 从 master 派生 private,加 wip/
git checkout -b private
mkdir wip && echo "..." > wip/draft.md
git add wip && git commit -m "add wip"
# private = 私有仓(跨名映射:本地 private → 远程 master)
git remote add private https://git.example.com/<you>/<repo>.git
git config --add remote.private.push refs/heads/private:refs/heads/master
git push -u private
# alias(仓库本地,不污染全局)
git config alias.sync-from-private \
'!git merge --squash refs/heads/private && git reset HEAD -- wip/ && git clean -fd wip/ && git status'
之后 git push origin / git push private 自动按各自 refspec 推送。
几点说明
- 本地分支 private 与 remote private 同名会触发
refname 'private' is ambiguous警告——alias 用全限定 refrefs/heads/private已消除;想根治就把本地分支改名(git branch -m private priv-local)。 - wip/ 曾被合并进 master 的边界情形下,squash 带进来的是 modified(tracked),
clean -fd不处理,需git checkout HEAD -- wip/还原。兼容两种情况的写法:git reset HEAD -- wip/ && (git checkout HEAD -- wip/ 2>/dev/null || true) && git clean -fd wip/。按推荐流程 master 不含 wip/,用不到。 - commit message 不能泄漏 wip/ 细节:写
feat: add X,不要写merge wip docs。 - 两分支需有共同祖先:各自独立 init 的分支首次合并会报
refusing to merge unrelated histories,可加--allow-unrelated-histories -X theirs兜底;按上述流程从 master 派生 private 则不会出现。 - 每次 sync 后必须 rebase:squash commit 不在 private 的历史里,公共祖先不会前移。若 private 继续开发而不 rebase,下次 sync 的合并基点仍是老祖先,已同步过的差量会被重复带入 master。rebase 时有两个预期现象:
- 输出
skipped previously applied commit:git 按 patch-id 识别出该提交内容已在 master(上次 squash 带入),自动跳过; - 普通 push 被拒(non-fast-forward):rebase 重写了提交 SHA,用
git push private --force-with-lease强推。不要按提示执行git pull,否则旧历史会被合并回来。
- 输出
忘记 rebase 后的救援
若已经在旧 private 上继续开发,下次 sync-from-private 可能出现大量 add/add 或重复内容冲突。先完成本次 squash 同步并在公开分支提交,确认除私有目录外的最终代码正确;然后以公开分支为新基线重建 private:
# master 已完成本次 squash commit,且工作区干净
git branch private-backup refs/heads/private # 先保留旧 private 作为退路
git checkout private
git reset --hard master # private 以最新 master 为基线
git checkout private-backup -- wip/ # 恢复私有目录的最终内容
git add wip/
git commit -m "docs: restore private files"
git push private --force-with-lease
master 替换为实际接收同步的目标分支(如 dev),wip/ 替换为 alias 实际排除的目录(如 temp/)。这是救援流程,会重写 private 历史,因此必须先建备份分支,并使用 --force-with-lease 而不是 --force。恢复后可验证:
git merge-base --is-ancestor master refs/heads/private
git diff --quiet master refs/heads/private -- . ':(exclude)wip/**'
两条命令均返回 0,表示 private 已基于最新 master,且除私有目录外与 master 一致。
每次 commit 前可快速验证:
ls wip 2>&1 # 工作区无 wip/
git diff --cached --stat | grep wip || echo OK # staged 不含 wip/
git log master --oneline | grep -i wip || echo OK # history 无 private commit
忽略多个路径(目录/文件都行,多个路径用空格分隔,可用变量减少重复):
git config alias.sync-from-private \
'!IGNORE="docs/ secrets.env scripts/"; git merge --squash refs/heads/private && git reset HEAD -- $IGNORE && git clean -fd $IGNORE && git status'
$IGNORE不加引号——让 shell 按空格 word splitting。若目标在.gitignore内(如.env),对它单独用-fdx(-x才会清 ignored 文件,作用域只限指定 path)。路径默认是精确匹配(相对仓库根目录):
secrets.env只匹配根目录那一个,子目录同名文件不 受影响。要匹配任意层级,文件写:(glob)**/secrets.env,目录写:(glob)**/temp/**(目录必须带尾部/**)。