跳到主要内容

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 推送。

几点说明

  1. 本地分支 private 与 remote private 同名会触发 refname 'private' is ambiguous 警告——alias 用全限定 ref refs/heads/private 已消除;想根治就把本地分支改名(git branch -m private priv-local)。
  2. 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/,用不到。
  3. commit message 不能泄漏 wip/ 细节:写 feat: add X,不要写 merge wip docs
  4. 两分支需有共同祖先:各自独立 init 的分支首次合并会报 refusing to merge unrelated histories,可加 --allow-unrelated-histories -X theirs 兜底;按上述流程从 master 派生 private 则不会出现。
  5. 每次 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/**(目录必须带尾部 /**)。