设置和配置
获取和创建项目
基本快照
分支和合并
共享和更新项目
检查和比较
补丁
调试
电子邮件
外部系统
服务器管理
指南
管理
底层命令
- 2.46.1 → 2.49.0 没有变更
-
2.46.0
2024-07-29
- 2.34.1 → 2.45.3 没有变更
-
2.34.0
2021-11-15
- 2.29.1 → 2.33.8 没有变更
-
2.29.0
2020-10-19
- 2.27.1 → 2.28.1 没有变更
-
2.27.0
2020-06-01
配置
-
user.name
中应该填写什么? -
您应该填写您的个人姓名,通常是名字和姓氏的形式。例如,Git 的当前维护者使用 "Junio C Hamano"。这将是您所做的每个提交中存储的名称部分。
此配置对远程服务的身份验证没有任何影响;为此,请参阅 git-config[1] 中的
credential.username
。
-
http.postBuffer
实际做什么? -
此选项更改 Git 通过 HTTP 或 HTTPS 将数据推送到远程时使用的缓冲区大小。如果数据大于此大小,libcurl(处理 Git 的 HTTP 支持)将使用分块传输编码,因为它无法提前知道推送数据的大小。
将此值保留为默认大小是可以的,除非您知道远程服务器或中间的代理不支持 HTTP/1.1(引入了分块传输编码)或已知在使用分块数据时会崩溃。这通常(错误地)被建议作为通用推送问题的解决方案,但由于几乎所有服务器和代理都至少支持 HTTP/1.1,因此提高此值通常不能解决大多数推送问题。一个不能正确支持 HTTP/1.1 和分块传输编码的服务器或代理在今天的 Internet 上没有多大用处,因为它会破坏大量的流量。
请注意,增加此值将增加 Git 通过 HTTP 或 HTTPS 执行的每个相关推送上使用的内存,因为无论是否全部使用,都会分配整个缓冲区。因此,最好将其保留为默认值,除非您确定需要不同的值。
- 如何配置不同的编辑器?
-
如果您没有专门为 Git 指定编辑器,默认情况下它将使用您使用
VISUAL
或EDITOR
环境变量配置的编辑器,或者如果两者都未指定,则使用系统默认编辑器(通常是vi
)。由于有些人觉得vi
难以使用或更喜欢不同的编辑器,因此可能需要更改使用的编辑器。如果您想为大多数需要编辑器的程序配置一个通用编辑器,您可以编辑您的 shell 配置(例如,
~/.bashrc
或~/.zshenv
)以包含一行将EDITOR
或VISUAL
环境变量设置为适当值的行。例如,如果您更喜欢编辑器nano
,那么您可以编写以下内容export VISUAL=nano
如果您想专门为 Git 配置编辑器,您可以设置
core.editor
配置值或GIT_EDITOR
环境变量。您可以查看 git-var[1] 以了解有关咨询这些选项的顺序的详细信息。请注意,在所有情况下,编辑器值都将传递给 shell,因此任何包含空格的参数都应适当地用引号引起来。此外,如果您的编辑器通常在调用时与终端分离,您应该使用一个使其不这样做的参数来指定它,否则 Git 将看不到任何更改。一个在 Windows 上解决这两个问题的配置示例是配置
"C:\Program Files\Vim\gvim.exe" --nofork
,它用空格引用文件名并指定--nofork
选项以避免后台运行该进程。
凭据
- 通过 HTTP 推送时如何指定我的凭据?
-
最简单的方法是使用通过
credential.helper
配置的凭据助手。大多数系统都提供一个标准选择来与系统凭据管理器集成。例如,Git for Windows 提供wincred
凭据管理器,macOS 具有osxkeychain
凭据管理器,而具有标准桌面环境的 Unix 系统可以使用libsecret
凭据管理器。所有这些都将凭据存储在加密存储中,以确保您的密码或令牌安全。此外,您可以使用
store
凭据管理器,它存储在您的主目录中的文件中,或者使用cache
凭据管理器,它不会永久存储您的凭据,但会阻止您在一段时间内被提示输入凭据。您也可以在提示时直接输入密码。虽然可以将密码(必须经过百分比编码)放在 URL 中,但这不是很安全,并可能导致凭据意外暴露,因此不建议这样做。
- 如何使用 HTTP 在同一托管提供商上使用多个帐户?
-
通常,区分这些帐户的最简单方法是在 URL 中使用用户名。例如,如果您在
git.example.org
上拥有帐户author
和committer
,则可以使用 URL https://author@git.example.org/org1/project1.git 和 https://committer@git.example.org/org2/project2.git。这样,当您使用凭据助手时,它会自动尝试查找您的帐户的正确凭据。如果您已经设置了远程,您可以使用类似git remote set-url origin https://author@git.example.org/org1/project1.git
的命令更改 URL(有关详细信息,请参阅 git-remote[1])。
- 如何使用 SSH 在同一托管提供商上使用多个帐户?
-
对于大多数支持 SSH 的托管提供商,单个密钥对唯一标识一个用户。因此,要使用多个帐户,必须为每个帐户创建一个密钥对。如果您使用的是相当现代的 OpenSSH 版本,您可以使用类似
ssh-keygen -t ed25519 -f ~/.ssh/id_committer
的命令创建一个新的密钥对。然后,您可以向托管提供商注册公钥(在本例中为~/.ssh/id_committer.pub
;请注意.pub
)。大多数托管提供商使用单个 SSH 帐户进行推送;也就是说,所有用户都推送到
git
帐户(例如,git@git.example.org
)。如果您的提供商是这种情况,您可以在 SSH 中设置多个别名,以明确要使用哪个密钥对。例如,您可以在~/.ssh/config
中编写类似以下内容,替换正确的私钥文件# This is the account for author on git.example.org. Host example_author HostName git.example.org User git # This is the key pair registered for author with git.example.org. IdentityFile ~/.ssh/id_author IdentitiesOnly yes # This is the account for committer on git.example.org. Host example_committer HostName git.example.org User git # This is the key pair registered for committer with git.example.org. IdentityFile ~/.ssh/id_committer IdentitiesOnly yes
然后,您可以调整您的推送 URL 以使用
git@example_author
或git@example_committer
而不是git@example.org
(例如,git remote set-url git@example_author:org1/project1.git
)。
传输
- 如何在系统之间同步工作树?
-
首先,确定您是否要这样做。Git 在您使用典型的
git push
和git fetch
命令推送或拉取您的工作时效果最佳,并且并非设计用于跨系统共享工作树。这具有潜在风险,在某些情况下可能会导致存储库损坏或数据丢失。通常,这样做会导致
git status
需要重新读取工作树中的每个文件。此外,Git 的安全模型不允许跨不受信任的用户共享工作树,因此只有在所有机器上仅由单个用户使用时,同步工作树才是安全的。重要的是不要使用云同步服务来同步 Git 存储库的任何部分,因为这可能会导致损坏,例如缺少对象、更改或添加的文件、损坏的引用以及各种其他问题。这些服务倾向于持续地逐个文件地同步,并且不了解 Git 存储库的结构。如果他们在更新存储库的过程中同步它,情况会更糟糕,因为这很可能导致不完整或部分更新,从而导致数据丢失。
一种可能发生的腐败的例子是关于引用(refs)状态的冲突,导致双方最终在同一个分支上拥有对方没有的不同的提交。这可能会导致重要的对象变为未引用状态,并可能被
git gc
修剪掉,从而导致数据丢失。因此,最好使用正常的推送和拉取机制将你的工作推送到另一个系统或中央服务器。然而,这并不总是能保存重要的数据,比如储藏(stashes),所以有些人更喜欢在不同系统之间共享一个工作树。
如果你这样做,推荐的方法是在仓库的根目录下使用
rsync -a --delete-after
(最好通过加密连接,例如使用ssh
)。当你这样做时,你应该确保以下几点:-
如果你有额外的工作树或单独的 Git 目录,它们必须与主工作树和仓库同时同步。
-
你能够接受目标目录成为源目录的精确副本,删除任何已存在的数据。
-
仓库(包括所有工作树和 Git 目录)在传输期间处于静止状态(也就是说,没有任何操作正在进行,包括后台操作,如
git gc
以及编辑器调用的操作)。请注意,即使有这些建议,以这种方式同步仍然存在一定的风险,因为它绕过了 Git 对仓库的正常完整性检查,所以建议进行备份。你可能还希望在同步后执行
git fsck
来验证目标系统上数据的完整性。
-
常见问题
- 我如何忽略对已跟踪文件的更改?
-
Git 不提供这样做的方法。原因是如果 Git 需要覆盖这个文件,例如在 checkout 期间,它不知道对文件的更改是否是珍贵的并且应该保留,或者它们是否是不相关的并且可以安全地销毁。因此,它必须采取安全的方式并始终保留它们。
尝试使用
git update-index
的某些特性,即 assume-unchanged 和 skip-worktree 位,是很诱人的,但这些特性不能正确地用于此目的,并且不应该这样使用。如果你的目标是修改一个配置文件,那么将一个文件检入到仓库中作为模板或默认设置,然后将其复制到旁边并根据需要进行修改,通常是有帮助的。这个第二个修改过的文件通常会被忽略,以防止意外提交。
- 我要求 Git 忽略各种文件,但它们仍然被跟踪
-
一个
gitignore
文件确保某些未被 Git 跟踪的文件保持未跟踪状态。然而,有时特定的文件可能在将它们添加到.gitignore
之前已经被跟踪,因此它们仍然保持被跟踪状态。要取消跟踪和忽略文件/模式,请使用git rm --cached <file/pattern>
并添加一个与 <file> 匹配的模式到.gitignore
。有关详细信息,请参阅 gitignore[5]。
- 我如何知道我想要执行 fetch 还是 pull?
-
fetch 存储来自远程仓库的最新更改的副本,而不修改工作树或当前分支。然后,你可以随意检查、合并、在上面变基或忽略上游更改。pull 包括一个 fetch,然后立即进行合并或变基。请参阅 git-pull[1]。
- 我可以在 Git 中使用代理吗?
-
是的,Git 支持使用代理。Git 遵循 Unix 上常用的标准
http_proxy
、https_proxy
和no_proxy
环境变量,并且还可以通过http.proxy
和类似的 HTTPS 选项进行配置(请参阅 git-config[1])。http.proxy
和相关选项可以基于每个 URL 模式进行定制。此外,理论上 Git 可以在网络上存在的透明代理正常运行。对于 SSH,Git 可以使用 OpenSSH 的
ProxyCommand
支持代理。常用的工具包括netcat
和socat
。但是,必须将它们配置为在看到标准输入上的 EOF 时不要退出,这通常意味着netcat
将需要-q
,而socat
将需要一个超时,例如-t 10
。这是必需的,因为 Git SSH 服务器知道不再有请求的方式是标准输入上的 EOF,但当发生这种情况时,服务器可能尚未处理最终请求,因此在该点断开连接会中断该请求。一个在
~/.ssh/config
中使用 HTTP 代理的配置条目的示例可能如下所示:Host git.example.org User git ProxyCommand socat -t 10 - PROXY:proxy.example.org:%h:%p,proxyport=8080
请注意,在所有情况下,为了使 Git 正常工作,代理必须是完全透明的。代理不能以任何方式修改、篡改或缓冲连接,否则 Git 几乎肯定会无法工作。请注意,许多代理,包括许多 TLS 中间盒、Windows 防病毒和防火墙程序(Windows Defender 和 Windows Firewall 除外)以及过滤代理,都无法满足此标准,因此最终会破坏 Git。由于有许多关于问题和它们糟糕的安全历史的报告,我们不建议使用这些类型的软件和设备。
合并和变基
- 使用 squash 合并合并长期存在的分支时,可能会出现哪些类型的问题?
-
一般来说,当使用 squash 合并多次合并两个分支时,可能会出现各种问题。这些问题可能包括在
git log
输出、GUI 中或在使用...
符号表示范围时看到额外的提交,以及可能需要一次又一次地重新解决冲突。当 Git 在两个分支之间进行正常的合并时,它会考虑三个点:两个分支和一个称为 *合并基础* 的第三个提交,它通常是提交的公共祖先。合并的结果是合并基础与每个头部之间的更改的总和。当你使用常规合并提交合并两个分支时,这将产生一个新的提交,当再次合并它们时,该提交将最终成为合并基础,因为现在有一个新的公共祖先。Git 不必考虑在合并基础之前发生的更改,因此你不必重新解决之前解决的任何冲突。
当你执行 squash 合并时,不会创建合并提交;相反,来自一侧的更改作为常规提交应用于另一侧。这意味着这些分支的合并基础不会改变,因此当 Git 要执行其下一次合并时,它会考虑它上次考虑的所有更改加上新的更改。这意味着可能需要重新解决任何冲突。类似地,在
git diff
、git log
或 GUI 中使用...
符号的所有内容都会导致显示自原始合并基础以来的所有更改。因此,如果你想重复合并两个长期存在的分支,最好始终使用常规合并提交。
- 如果我在两个分支上都进行了更改,但在一个分支上还原了它,为什么这些分支的合并会包含该更改?
-
默认情况下,当 Git 进行合并时,它会使用一种称为
ort
策略的策略,该策略会进行复杂的三方合并。在这种情况下,当 Git 执行合并时,它会考虑三个点:两个头部和一个称为 *合并基础* 的第三个点,它通常是这些提交的公共祖先。Git 根本不考虑历史记录或这些分支上发生的单个提交。因此,如果双方都有更改并且一方已还原该更改,则结果是包含该更改。这是因为代码在一侧发生了更改,而另一侧没有净更改,在这种情况下,Git 采用了该更改。
如果这对你来说是一个问题,你可以改为进行变基,将带有还原的分支变基到另一个分支上。在这种情况下,变基将还原该更改,因为变基会应用每个单独的提交,包括还原。请注意,变基会重写历史记录,因此你应该避免变基已发布的分支,除非你确定你可以接受这一点。有关更多详细信息,请参阅 git-rebase[1] 中的 NOTES 部分。
钩子
- 我如何使用钩子来防止用户进行某些更改?
-
进行这些更改的唯一安全位置是在远程仓库(即 Git 服务器)上,通常是在
pre-receive
钩子中或在持续集成 (CI) 系统中。这些是策略可以有效实施的位置。通常会尝试使用
pre-commit
钩子(或者,对于提交消息,使用commit-msg
钩子)来检查这些事情,如果你作为一名单独的开发人员工作并且希望工具来帮助你,这很好。但是,在开发人员机器上使用钩子作为策略控制是无效的,因为用户可以在不被注意的情况下使用--no-verify
绕过这些钩子(以及各种其他方式)。Git 假设用户可以控制其本地仓库,并且不会尝试阻止这一点或告发用户。此外,一些高级用户发现
pre-commit
钩子会阻碍使用临时提交来暂存正在进行的工作或创建 fixup 提交的工作流程,因此最好无论如何都将这些类型的检查推送到服务器。
跨平台问题
- 我正在 Windows 上,我的文本文件被检测为二进制文件。
-
Git 在存储文本文件时最好使用 UTF-8 编码。 Windows 上的许多程序都支持 UTF-8,但有些程序不支持,只使用小端 UTF-16 格式,Git 会将其检测为二进制文件。 如果你的程序不能使用 UTF-8,你可以指定一个工作区树编码,指示你的文件应该以哪种编码检出,同时仍然将这些文件以 UTF-8 格式存储在存储库中。 这样,像 git-diff[1] 这样的工具就可以按预期工作,同时仍然允许你的工具工作。
要做到这一点,你可以使用
working-tree-encoding
属性指定一个 gitattributes[5] 模式。 例如,以下模式将所有 C 文件设置为使用 UTF-16LE-BOM,这在 Windows 上是一种常见的编码*.c working-tree-encoding=UTF-16LE-BOM
你需要运行
git add --renormalize
才能使此设置生效。 请注意,如果你正在对一个跨平台使用的项目进行这些更改,你可能希望在每个用户的配置文件或$GIT_DIR/info/attributes
中的配置文件中进行更改,因为在存储库中的.gitattributes
文件中进行更改将应用于存储库的所有用户。有关规范化行尾的信息,请参阅以下条目,有关属性文件的更多信息,请参阅 gitattributes[5]。
- 我在 Windows 上,git diff 显示我的文件末尾有一个
^M
。 -
默认情况下,Git 希望文件以 Unix 行尾符存储。 因此,作为 Windows 行尾符一部分的回车符 (
^M
) 会被显示出来,因为它被认为是尾随空格。 Git 默认只显示新行上的尾随空格,而不是现有行上的。你可以将文件以 Unix 行尾符存储在存储库中,并自动将其转换为你平台的行尾符。 要做到这一点,将配置选项
core.eol
设置为native
,并参阅 关于推荐存储设置的问题,了解如何将文件配置为文本或二进制文件。如果你不想从行尾移除回车符,你也可以使用
core.whitespace
设置来控制此行为。
- 为什么我有一个文件总是被修改?
-
在内部,Git 总是将文件名存储为字节序列,并且不执行任何编码或大小写折叠。 然而,Windows 和 macOS 默认都会对文件名执行大小写折叠。 因此,最终可能会出现多个文件或目录,它们的名称仅在大小写上有所不同。 Git 可以很好地处理这个问题,但是文件系统只能存储其中一个文件,所以当 Git 读取另一个文件以查看其内容时,它看起来像是被修改过的。
最好删除其中一个文件,这样你只有一个文件。 你可以使用如下命令来完成此操作(假设有两个文件
AFile.txt
和afile.txt
),且工作区树是干净的$ git rm --cached AFile.txt $ git commit -m 'Remove files conflicting in case' $ git checkout .
这避免了触碰磁盘,但删除了多余的文件。 你的项目可能更喜欢采用命名约定,例如全部使用小写名称,以避免再次出现此问题;可以使用
pre-receive
hook 或作为持续集成 (CI) 系统的一部分来检查此类约定。如果你的系统正在使用 smudge 或 clean 过滤器,但在先前提交文件时没有运行 smudge 或 clean 过滤器,则也可能在任何平台上发生永久修改的文件。 要解决此问题,请在干净的工作区树上运行以下命令
$ git add --renormalize .
- 推荐使用什么方式在 Git 中存储文件?
-
虽然 Git 可以存储和处理任何类型的任何文件,但有些设置比其他设置更好。 一般来说,我们建议文本文件以不带字节顺序标记 (BOM) 的 UTF-8 编码和 LF (Unix 样式) 行尾符存储。 我们还建议在提交消息中使用 UTF-8(同样,不带 BOM)。 这些设置在跨平台以及与
git diff
和git merge
等工具配合使用时效果最佳。此外,如果可以在基于文本或非基于文本的存储格式之间进行选择,我们建议以文本格式存储文件,并在必要时将其转换为其他格式。 例如,每行一条记录的基于文本的 SQL 转储比实际的数据库文件更适合进行差异和合并。 类似地,诸如 Markdown 和 AsciiDoc 之类的基于文本的格式将比诸如 Microsoft Word 和 PDF 之类的二进制格式更好。
类似地,通常不建议在存储库中存储二进制依赖项(例如,共享库或 JAR 文件)或构建产品。 依赖项和构建产品最好存储在工件或包服务器上,只有引用、URL 和哈希值存储在存储库中。
我们还建议设置一个 gitattributes[5] 文件,以明确标记哪些文件是文本文件,哪些是二进制文件。 如果你希望 Git 进行猜测,你可以设置属性
text=auto
。对于文本文件,Git 通常会确保在存储库中使用 LF 行尾符。
core.autocrlf
和core.eol
配置变量指定在检出任何文本文件时遵循的行尾约定。 你还可以使用eol
属性(例如,eol=crlf
)来覆盖哪些文件获得什么行尾处理。例如,通常 shell 文件必须具有 LF 行尾符,而批处理文件必须具有 CRLF 行尾符,因此以下内容可能适用于某些项目
# By default, guess. * text=auto # Mark all C files as text. *.c text # Ensure all shell files have LF endings and all batch files have CRLF # endings in the working tree and both have LF in the repo. *.sh text eol=lf *.bat text eol=crlf # Mark all JPEG files as binary. *.jpg binary
这些设置有助于工具选择正确的输出格式,例如补丁,并导致文件以适合平台的行尾符检出。
GIT
是 git[1] 套件的一部分