11.1 简单别名

在 Git 中创建别名有两种方法:

使用 ~/.gitconfig 文件

[alias]
ci = commit
st = status
co = checkout

使用命令行

git config --global alias.ci "commit"
git config --global alias.st "status"
git config --global alias.co "checkout"

别名创建后,你可以使用:

git ci instead of git commit
git st instead of git status
git co instead of git checkout

与常规 Git 命令一样,别名也可以与参数一起使用。例如:

git ci -m "Commit message..."
git co -b feature-42

11.2 列出/搜索现有别名

你可以使用 --get-regexp 列出现有的 Git 别名:

$ git config --get-regexp '^alias\.'

搜索别名

在 .gitconfig 文件中添加以下内容到 [alias] 部分:

aliases = !git config --list | grep ^alias\\. | cut -c 7- | grep -Ei --color "$1" "#"

然后你可以:

git aliases - 显示所有别名
git aliases commit - 只显示包含 "commit" 的别名

11.3 高级别名

Git 允许你在别名中使用非 Git 命令和完整的 shell 语法,只需在别名前添加 !。

在 ~/.gitconfig 文件中

[alias]
temp = !git add -A && git commit -m "Temp"

由于这些前缀别名中可以使用完整的 shell 语法,你还可以使用 shell 函数构建更复杂的别名,例如使用命令行参数的别名:

[alias]
ignore = "!f() { echo $1 >> .gitignore; }; f"

上述别名定义了 f 函数,然后运行该函数,并传递你传递给别名的任何参数。因此,运行 git ignore .tmp/ 会将 .tmp/ 添加到你的 .gitignore 文件中。

实际上,这种模式非常有用,Git 会为你定义 $1、$2 等变量,因此你甚至不需要定义特殊函数。但请注意,Git 也会无论如何附加参数,即使你通过这些变量访问它们,因此你可能需要在末尾添加一个哑命令。

注意:以这种方式前缀的别名是从你的 Git 检出的根目录运行的,即使你的当前目录在树中更深处。这可以是一种从根目录运行命令而无需显式 cd 到那里的有用方式。

[alias]
ignore = "! echo $1 >> .gitignore"

11.4 临时忽略已跟踪文件

要临时将文件标记为被忽略(将文件作为参数传递给别名):

unwatch = update-index --assume-unchanged

要再次开始跟踪文件:

watch = update-index --no-assume-unchanged

要列出所有已被临时忽略的文件:

unwatched = "!git ls-files -v | grep '^[[:lower:]]'"

要清除未跟踪的列表:

watchall = "!git unwatched | xargs -L 1 -I % sh -c 'git watch `echo % | cut -c 2-`'"

使用别名的示例:

git unwatch my_file.txt
git watch my_file.txt
git unwatched
git watchall

11.5 显示带有分支图的漂亮日志

[alias]
logp = log --pretty=format:'%h %ad | %s%d [%an]' --graph --date=short
lg = log --graph --date-order --first-parent \
--pretty=format:'%C(auto)%h%Creset %C(auto)%d%Creset %s %C(green)(%ad) %C(bold cyan)<%an>%Creset'
lgb = log --graph --date-order --branches --first-parent \
--pretty=format:'%C(auto)%h%Creset %C(auto)%d%Creset %s %C(green)(%ad) %C(bold cyan)<%an>%Creset'
lga = log --graph --date-order --all \
--pretty=format:'%C(auto)%h%Creset %C(auto)%d%Creset %s %C(green)(%ad) %C(bold cyan)<%an>%Creset'

以下是 --pretty 格式中使用的选项和占位符的解释(完整的列表可以通过 git help log 查看):

  • --graph - 绘制提交树
  • --date-order - 尽可能使用提交时间戳顺序
  • --first-parent - 在合并节点上仅跟踪第一个父节点
  • --branches - 显示所有本地分支(默认情况下,仅显示当前分支)
  • --all - 显示所有本地和远程分支
  • %h - 提交的哈希值(缩写)
  • %ad - 作者日期戳
  • %an - 作者用户名
  • %cn - 提交者用户名
  • %C(auto) - 使用 [color] 部分中定义的颜色
  • %Creset - 重置颜色
  • %d - --decorate(分支和标签名称)
  • %s - 提交消息
  • %ad - 作者日期(将遵循 --date 指令)(而不是提交者日期)
  • %an - 作者名称(可以使用 %cn 为提交者名称)

11.6 查看 .gitignore 配置忽略的文件

[alias]
ignored = !git ls-files --others --ignored --exclude-standard --directory \
&& git ls-files --others -i --exclude-standard

显示每个文件的一行,因此你可以使用 grep(仅目录):

$ git ignored | grep '/$'
.yardoc/
doc/

或者计数:

$ git ignored | wc -l
199811 # 哎呀,我的主目录太拥挤了

11.7 在保持线性历史的同时更新代码

有时你需要保持代码提交的线性(非分支)历史。如果你在一段时间内工作在一个分支上,这可能会很棘手,因为如果你需要执行常规的 git pull,这将记录与上游的合并。

[alias]
up = pull --rebase

这将更新你的上游源代码,然后将你尚未推送到远程的任何工作重新应用在你拉取的代码之上。

使用方法:

git up

11.8 取消暂存已暂存的文件

通常,要使用 git reset 移除将要提交的已暂存文件,reset 根据提供的参数有许多功能。要完全取消暂存所有已暂存的文件,我们可以使用 Git 别名创建一个新的别名,这样我们就不需要记住为 reset 提供正确的参数。

git config --global alias.unstage "reset --"

现在,每次你想取消暂存已暂存的文件时,只需运行 git unstage 即可。