Git
- “我曾遇到过一些人,他们认为 git 是 GitHub 的前端。他们错了,git 其实是 AUR 的前端。” — Linus T.
Git 是由 Linux 内核创始人 Linus Torvalds 设计和开发的版本控制系统 (VCS)。Git 现在被用于维护 AUR 软件包,以及包括 Linux 内核源码在内的许多其他项目。
安装
安装 git 软件包。如需开发版本,请安装 git-gitAUR 软件包。在使用 git svn、git gui 和 gitk 等工具时,请检查其可选依赖项。
图形前端
另请参阅 Git 图形化客户端。
- Commit — 帮助你编写更优秀的 Git 和 Mercurial 提交信息的编辑器。
- Forge Sparks — 支持 Github、GitLab、Gitea 和 Forgejo 的简单通知应用程序。
- Giggle — Git 的 GTK 前端。
- GitAhead — 包含内置合并工具的图形化 Git 客户端。
- GitButler — 基于 Git 的版本控制客户端,由 Tauri/Rust/Svelte 驱动。
- Git Cola — 使用 Python 编写的精巧且功能强大的 Git 图形用户界面。
- Git Extensions — Git 的图形用户界面,允许你无需使用命令行即可控制 Git。
- gitg — 查看 Git 仓库的 GNOME GUI 客户端。属于 gnome-extra。
- git-gui — 基于 Tcl/Tk 的 Git 便携式图形界面。
- GitHub Desktop — 由 GitHub 团队构建的基于 Electron 的图形用户界面。
- gitk — 基于 Tcl/Tk 的 Git 仓库浏览器。
- Gittyup — 基于 Qt 的 Git 客户端。
- Guitar — Git 图形化客户端。
- gitui — 使用 Rust 编写的快速 Git 终端界面。
- Kommit — 用于 KDE 的 Git 图形化客户端。
- lazygit — 简单的 Git 命令终端界面。
- QGit — 用于浏览修订历史、查看补丁内容和已更改文件的 Git 图形化查看器,可图形化跟踪不同的开发分支。
- RabbitVCS — 一套图形化工具,旨在为你所使用的版本控制系统提供简单直接的访问方式。
- Sublime Merge — 来自 Sublime Text 团队的 Git 客户端。
- Tig — 基于 ncurses 的 Git 文本模式界面。
- ungit — 在不牺牲 Git 多功能性的前提下,为 Git 带来用户友好性。
配置
要使用 Git,你需要至少设置一个名称和电子邮件地址
$ git config --global user.name "John Doe" $ git config --global user.email "johndoe@example.com"
参见 入门 - 首次设置 Git。
有关更多设置,请参阅 #提示与技巧。
用法
Git 仓库包含在 .git 目录中,该目录保存了修订历史记录和其他元数据。由仓库追踪的目录(默认为父目录)被称为工作目录。工作区中的更改在记录(提交)到仓库之前需要先进行暂存。Git 还允许你恢复之前提交过的工作区文件。
参见 入门。
获取 Git 仓库
记录更改
查看变更历史
撤销操作
使用远程仓库
分支管理
基本分支与合并
分支管理
分支工作流
远程分支
变基 (Rebasing)
参见 Git 分支 - 变基
协作
分布式工作流
向项目贡献代码
维护项目
Git 工具
修订选择
交互式暂存
储藏 (Stashing) 与清理
签署你的工作
搜索
参见 Git 工具 - 搜索
重写历史
重置 (Reset) 详解
高级合并
Rerere
使用 Git 调试
子模块 (Submodules)
参见 Git 工具 - 子模块
打包 (Bundling)
参见 Git 工具 - 打包
替换 (Replace)
参见 Git 工具 - 替换
凭据存储
技巧与提示
使用 git-config
Git 从四个 INI 类型的配置文件中读取配置:
/etc/gitconfig:系统范围的默认设置~/.gitconfig和~/.config/git/config(自 1.7.12 起):用户特定的配置.git/config:仓库特定的配置
这些文件可以直接编辑,但通常的做法是使用 git config,如下面的示例所示。
列出当前设置的变量
$ git config list {--local,--global,--system}
$ git config --global core.editor "nano -w"
设置默认推送动作
$ git config --global push.default simple
为 git difftool 设置其他工具(默认为 meld)
$ git config --global diff.tool vimdiff
有关更多信息,请参见 git-config(1) 和 Git 配置。
包含单独的配置文件
自 2012 年的 v1.7.10 起,Git 支持使用 gitconfig 文件内的 include 关键字,将配置文件拆分为多个文件。
--local 或 --global 标志时,默认禁用加载已包含的配置文件。要启用它,请在 git config get 和 git config list 命令中使用 --includes 标志。遵循良好的协作礼仪
- 在考虑向现有项目贡献代码时,请阅读并理解其许可协议,因为它可能会过度限制你修改代码的能力。有些许可协议可能会引发关于代码所有权的争议。
- 思考项目的社区情况以及你如何融入其中。为了了解项目的发展方向,请阅读任何可用的文档,甚至查阅仓库的 日志。
- 当请求拉取提交或提交补丁时,保持提交内容简小且文档齐全;这将有助于维护人员理解你的更改,并决定是合并它们还是要求你进行一些修改。
- 如果贡献被拒绝,不要气馁,毕竟那是他们的项目。如果这件事很重要,请尽可能清楚、耐心地讨论贡献的理由:通过这种方式,最终可能会达成解决方案。
加速身份验证
你可能希望避免每次推送到 Git 服务器时都进行交互式身份验证的麻烦。
- 如果你使用 SSH 密钥进行身份验证,请使用 SSH 代理。另请参阅 OpenSSH#加速 SSH 和 OpenSSH#保持连接。
- 如果你使用用户名和密码进行身份验证,如果服务器支持 SSH,请切换到 SSH 密钥;否则,使用 git-credential-libsecret 凭据助手,或者尝试 git-credential-cache 或 git-credential-store。
使用 git-credential-libsecret 作为凭据助手
Git 可以从 org.freedesktop.secrets 兼容的钥匙圈(如 GNOME Keyring、KeePassXC 或 KDE Wallet)中获取凭据。因此,请设置一个兼容的钥匙圈,并使用以下命令检查钥匙圈是否已注册到 dbus
$ dbus-send --session --print-reply --dest=org.freedesktop.DBus / \
org.freedesktop.DBus.GetConnectionUnixProcessID \
string:org.freedesktop.secrets
然后运行
$ git config --global credential.helper /usr/lib/git-core/git-credential-libsecret
来配置 Git。
使用 git-credential-netrc 作为凭据助手
Git 可以读取 netrc 文件来访问凭据。首先,指引 Git 使用 netrc 助手脚本
$ git config --global credential.helper /usr/share/git/credential/netrc/git-credential-netrc.perl
然后,创建一个 .netrc 文件
~/.netrc
machine git-host login username password password
如果你想安全地保护密码,该凭据助手还支持 gpg 加密文件 (~/.netrc.gpg)。
协议默认设置
如果你像上面那样运行多路复用 SSH 连接,Git over SSH 可能比 HTTPS 更快。此外,某些服务器(如 AUR)只允许通过 SSH 进行推送。例如,以下配置将对托管在 AUR 上的任何仓库设置使用 SSH 协议。
~/.gitconfig
[url "ssh://aur@aur.archlinux.org/"] insteadOf = https://aur.archlinux.org/ insteadOf = http://aur.archlinux.org/ insteadOf = git://aur.archlinux.org/
Bash 自动补全
要启用 Bash 自动补全,请在 Bash 启动文件 中 source /usr/share/git/completion/git-completion.bash。或者,安装 bash-completion。
Git 提示符 (Prompt)
Git 软件包随附了一个提示符脚本。要启用它,请 source /usr/share/git/completion/git-prompt.sh 并使用 %s 参数设置自定义提示符
- 对于 Bash:
PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ ' - 对于 Zsh:
setopt PROMPT_SUBST ; PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ '提示 Zsh 提供了一个可以作为替代方案的vcs_info函数。请参阅 zshcontrib(1) § GATHERING INFORMATION FROM VERSION CONTROL SYSTEMS。
请注意,命令替换必须进行转义,详情请参见 Bash/Prompt 自定义#嵌入命令。有关持久化配置,请参阅 命令行 shell#配置文件。
切换到 Git 仓库目录时,提示符将显示分支名称。可以通过设置相应的环境变量,让提示符显示额外信息:
| Shell 变量 | 信息 |
|---|---|
| GIT_PS1_SHOWDIRTYSTATE | + 表示已暂存,* 表示未暂存。 |
| GIT_PS1_SHOWSTASHSTATE | $ 表示有已储藏的内容。 |
| GIT_PS1_SHOWUNTRACKEDFILES | % 表示存在未追踪的文件。 |
| GIT_PS1_SHOWUPSTREAM | <、>、<> 分别表示落后、领先或与上游分支分叉。 |
| GIT_PS1_STATESEPARATOR | 分支名称与状态符号之间的分隔符 |
| GIT_PS1_DESCRIBE_STYLE | 在分离 HEAD 时,显示相对于标签或分支的提交 |
| GIT_PS1_SHOWCOLORHINTS | 彩色显示 |
环境变量的完整文档可在脚本的注释中找到。
- 如果你发现
$(__git_ps1)返回((unknown)),说明你的当前目录中存在一个不包含任何仓库的.git文件夹,因此 Git 无法识别它。例如,当你将 Git 的配置文件误认为是~/.git/config而非~/.gitconfig时,就可能发生这种情况。 - 如果你的提示符在处理大型仓库时出现延迟,很可能是因为
GIT_PS1_SHOWUNTRACKEDFILES选项,它每次都会触发全目录树扫描以检测新文件,从而导致明显的性能影响。若要针对这些仓库在本地禁用此选项,可以使用命令git config --local bash.showUntrackedFiles false。
或者,你可以使用 AUR 中的 Git shell 提示符自定义软件包,例如 bash-git-promptAUR 或 gittifyAUR。
可视化呈现
为了解已完成的工作量
$ git diff --stat
带有分支结构的 git log
$ git log --graph --oneline --decorate
git log 图形别名(例如 git graph 将显示修饰后的版本)
$ git config --global alias.graph 'log --graph --oneline --decorate'
提交小技巧
重置到上一个提交(非常危险,会将所有受追踪文件擦除回指定提交)
$ git reset --hard HEAD~
如果仓库地址发生更改,则需要更新其远程位置
$ git remote set-url origin git@address:user/repo.git
或者,使用新位置编辑 .git/config。
追加 Signed-off-by 行(某些项目要求在提交中添加名称-电子邮件签名)
$ git commit -s
在补丁中自动追加 Signed-off-by(使用 git format-patch commit 时)
$ git config --local format.signoff true
提交已更改文件的特定部分。如果你进行了大量更改,最好将其拆分为多个提交,这会非常有用。
$ git add -p
签署提交
Git 允许使用 GnuPG 对提交和标签进行签名,请参阅 签署你的工作。
export GPG_TTY=$(tty)(或者使用 pinentry-tty),否则如果 GPG 当前处于锁定状态(因为它无法提示输入 PIN),签名步骤将会失败。配置 Git 自动签署提交:
$ git config --global commit.gpgSign true
使用非 master 分支
有时维护人员会要求在分支上工作。这些分支通常被称为 devel 或 testing。首先克隆仓库:
要进入 master 以外的其他分支(git clone 默认只显示 master 分支,但其他分支依然存在,使用 git branch -a 查看):
$ git checkout -b branch origin/branch
现在可以正常编辑;但是,为了保持仓库树同步,请务必同时使用:
$ git pull --all $ git push --all
直接向邮件列表发送补丁
如果你想直接向邮件列表发送补丁,需要安装以下软件包:perl-authen-sasl 和 perl-io-socket-ssl。
确保你已配置好用户名和电子邮件地址,参见 #配置。
配置你的电子邮件设置
$ git config --global sendemail.smtpserver smtp.example.com $ git config --global sendemail.smtpserverport 465 $ git config --global sendemail.smtpencryption ssl $ git config --global sendemail.smtpuser foobar@example.com
现在你应该可以向邮件列表发送补丁了(另请参阅 OpenEmbedded: 通过电子邮件发送补丁 和 git-send-email.io)
$ git add filename $ git commit -s $ git send-email --to=pacman-contrib@lists.archlinux.org --confirm=always -M -1
处理大型 Git 仓库
在处理大型远程仓库时,必须获取大量数据。以下示例使用 Linux 内核来说明如何处理此类代码库。
获取完整仓库
最简单的解决方案是获取整个仓库
$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
git clone 被中断,则无法恢复。你可以使用 git pull 来更新仓库。
部分获取仓库
为了将本地仓库限制为 origin 的较小部分(例如在 v4.14 之后用于二分查找错误),请使用浅克隆:
$ git clone --shallow-exclude v4.13 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
你将获得 v4.14 及以后的版本,但不会获得 v4.13 及更早的版本。
如果你只需要最新的快照而忽略所有历史记录(如果可用 tarball 且已足够,请选择该方式;从 git 仓库下载需要更多带宽),可以使用以下命令获取:
$ git clone --depth 1 git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
你稍后可以获取更早的提交,如下面两个示例所示:
$ git fetch --tags --shallow-exclude v4.1 $ git fetch --tags --shallow-since 2016-01-01
--tags,标签将不会被获取。使用 Scalar
Scalar(前身为 Virtual File System for Git (VFS for Git))允许在没有本地实例的情况下访问 git 仓库。
参见 scalar(1)。
获取其他分支
在上面的示例中,你的本地仓库仅追踪主线内核(即 进行最新开发的地方)。假设你想要最新的 LTS,例如最新的 4.14 分支。你可以通过以下方式获取:
$ git remote set-branches --add origin linux-4.14.y $ git fetch --shallow-exclude v4.14 $ git branch --track linux-4.14.y origin/linux-4.14.y
最后一行不是强制性的,但通常需要。(没有通用的规则来知道你想要的分支名称。你可以通过查看 gitweb 界面中的 "ref" 链接来猜测一个。)
对于 linux-4.14.y 的快照,请执行:
$ git checkout linux-4.14.y
或者将其解压到另一个目录中:
$ mkdir /path/to/src-4.14; cd /path/to/src-4.14 $ git clone --no-local --depth 1 -b linux-4.14.y ../linux-stable
像往常一样,使用 git pull 来更新你的快照。
过滤敏感信息
有时,软件可能会在配置文件中保留纯文本密码,而不是挂接到钥匙圈。在这种情况下,git clean-filters 可能有助于避免意外提交敏感信息。例如,以下文件为 “some-dotfile” 指定了一个过滤器:
.gitattributes
some-dotfile filter=remove-pass
每当 “some-dotfile” 被签入 git 时,git 都会在签入前对该文件调用 “remove-pass” 过滤器。该过滤器必须在 git 配置文件中定义,例如:
.git/config
[filter "remove-pass"] clean = "sed -e 's/^password=.*/#password=TODO/'"
HTML 帮助文件
通过安装 git-htmldocsAUR,也可以以 HTML 形式获取 git help 文档。安装后,可以通过传递 -w 标志访问 HTML 文档。例如:
$ git help -w merge
可以通过设置 git config 选项将 HTML 文档设置为默认加载:
$ git config --global help.format html
扩展
辅助工具
- git-extras — Git 实用程序集合(仓库摘要、repl、更新日志、作者提交等)
- https://github.com/tj/git-extras || git-extrasAUR - 如果你正在使用 oh-my-zsh,你也可以启用 git-extras 插件
- gitflow-cjs — 使用 Vincent Driessen 的分支模型 扩展 Git。CJS 版本是一个积极维护的分支。
- gitmoji-cli — 一个 gitmoji 交互式 NodeJS 客户端,用于在提交信息中使用 gitmojis。
大文件同步支持
- git-annex — 用 Haskell 编写的分布式文件同步系统,允许使用 Git 管理大量数据。
管理多个 Git 仓库
- garden — 使用 Rust 编写的用于管理多个 Git 仓库的命令行工具。
- gita — 使用 Python 编写的用于管理多个 Git 仓库的命令行工具。
- git-bulk — 使用 Bash 编写的用于管理多个 Git 仓库的命令行工具。
- mani — 使用 Go 编写的用于管理多个 Git 仓库的命令行工具和 TUI。
- mu-repo — 使用 Python 编写的用于管理多个 Git 仓库的命令行工具。
- myrepos (mr) — 使用 Perl 编写的用于管理多个 Git 仓库的命令行工具。
参见
- Git 手册页,参见 git(1)
- 《Pro Git》书籍
- Git 参考手册(由 GitHub 提供)
- Git 工作流:Forks、远程仓库和 Pull Requests
- VideoLAN Wiki 文章
- Git 协议 - 服务器上的 Git
- 如何使用 GitHub