我该如何调试与git/git-shell相关的问题?

244

我如何获取有关git/git-shell的调试信息?

我的问题是,user1可以无问题地克隆存储库,而user2只能克隆一个空的存储库。我已设置GIT_TRACE=1,但没有提供有用的信息。

最终,在经过漫长的尝试和错误之后,发现这是一个文件权限问题。适当的错误消息可以避免这个问题。


注意:除了GIT_CURL_VERBOSE之外,您还将在Git 2.9.x/2.10中使用GIT_TRACE_CURL。请参见我的答案 - VonC
1
而且(在 2019 年第二季度,在“GIT_TRACE_CURL”三年后),你现在有了“trace2”。例如:git config --global trace2.normalTarget ~/log.normal。请参见我的(新)答案:https://dev59.com/am025IYBdhLWcg3wKSiP#56094711。 - VonC
trace2 可以显示在运行 git 命令期间使用的 git config 值!(Git 2.38,2022 年第三季度 - VonC
10个回答

313

若需要更详细的输出,请使用以下命令:

GIT_CURL_VERBOSE=1 GIT_TRACE=1 git pull origin master


90
除了核心选项外,GIT_TRACE 还有几个选项。以下是超级详细的选项:set -x; GIT_TRACE=2 GIT_CURL_VERBOSE=2 GIT_TRACE_PERFORMANCE=2 GIT_TRACE_PACK_ACCESS=2 GIT_TRACE_PACKET=2 GIT_TRACE_PACKFILE=2 GIT_TRACE_SETUP=2 GIT_TRACE_SHALLOW=2 git pull origin master -v -v; set +x - Paul Irish
这只是一整行代码,您可以将其粘贴到您的终端中。您应该用您想要执行的命令替换 git pull origin master 部分。 - Aeolun
12
在Windows操作系统中,您可以像这样一次设置一个变量(每行一个):set GIT_CURL_VERBOSE=1 set GIT_TRACE=1,然后执行git pull origin master命令。 - cowlinator
7
在PowerShell中,您可以像这样设置它们:$Env:GIT_CURL_VERBOSE=1。该命令会设置名为"GIT_CURL_VERBOSE"的环境变量,并将其值设置为1。 - Jon
@PaulIrish的一行代码被括在括号中(以防止set -x在中止/ Ctrl+c时泄漏到shell中)... 并使底层的ssh调用额外详细...:(set -x; GIT_TRACE=2 GIT_CURL_VERBOSE=2 GIT_TRACE_PERFORMANCE=2 GIT_TRACE_PACK_ACCESS=2 GIT_TRACE_PACKET=2 GIT_TRACE_PACKFILE=2 GIT_TRACE_SETUP=2 GIT_TRACE_SHALLOW=2 GIT_SSH_COMMAND="ssh -vvv" git <command> -vv ) - undefined

146

调试

Git嵌入了一套相当完整的跟踪系统,您可以使用它来调试Git问题。

要打开它们,您可以定义以下变量:

  • GIT_TRACE 用于一般跟踪,
  • GIT_TRACE_PACK_ACCESS 用于跟踪packfile访问,
  • GIT_TRACE_PACKET 用于网络操作的数据包级跟踪,
  • GIT_TRACE_PERFORMANCE 用于记录性能数据,
  • GIT_TRACE_SETUP 可获取与其交互的存储库和环境的信息,
  • GIT_MERGE_VERBOSITY 用于调试递归合并策略(值:0-5),
  • GIT_CURL_VERBOSE 用于记录所有curl消息(相当于curl -v),
  • GIT_TRACE_SHALLOW 用于调试浅克隆/获取存储库。

可能的值包括:

  • true12以将输出写入stderr,
  • /开头的绝对路径以将跟踪输出到指定文件。

有关更多详细信息,请参见:Git内部原理 - 环境变量 - 调试


SSH

对于SSH问题,请尝试以下命令:

echo 'ssh -vvv "$*"' > ssh && chmod +x ssh
GIT_SSH="$PWD/ssh" git pull origin master

或者使用ssh验证您的凭据,例如:

ssh -vvvT git@github.com

或通过 HTTPS 端口:

ssh -vvvT -p 443 git@ssh.github.com

注意:将 -v 的数量减少可降低详细级别。


示例

$ GIT_TRACE=1 git status
20:11:39.565701 git.c:350               trace: built-in: git 'status'

$ GIT_TRACE_PERFORMANCE=$PWD/gc.log git gc
Counting objects: 143760, done.
...
$ head gc.log 
20:12:37.214410 trace.c:420             performance: 0.090286000 s: git command: 'git' 'pack-refs' '--all' '--prune'
20:12:37.378101 trace.c:420             performance: 0.156971000 s: git command: 'git' 'reflog' 'expire' '--all'
...

$ GIT_TRACE_PACKET=true git pull origin master
20:16:53.062183 pkt-line.c:80           packet:        fetch< 93eb028c6b2f8b1d694d1173a4ddf32b48e371ce HEAD\0multi_ack thin-pack side-band side-band-64k ofs-delta shallow no-progress include-tag multi_ack_detailed symref=HEAD:refs/heads/master agent=git/2:2.6.5~update-ref-initial-update-1494-g76b680d
...

4
echo 'ssh -vvv $*' > ssh && chmod +x ssh更改为echo 'ssh -vvv "$@"' > ssh && chmod +x ssh可以在单个参数中包含空格的边缘情况下更加安全。 - Alexander Bird
@AlexanderBird,虽然不是我们所期望的那么安全,因为当ssh在远程运行命令位置给出多个不同的参数时,它只是将它们用空格连接成一个字符串,远程shell eval作为代码。试图正确地执行此操作可能会得到类似于ssh -vvv "${*@Q}"的结果。 - Charles Duffy

55
如果是通过SSH连接,您可以使用以下命令:
要获得更高的调试级别,请针对类型使用-vv或-vvv来分别设置级别2和级别3:
# Debug level 1
GIT_SSH_COMMAND="ssh -v" git clone <repositoryurl>

# Debug level 2
GIT_SSH_COMMAND="ssh -vv" git clone <repositoryurl>

# Debug level 3
GIT_SSH_COMMAND="ssh -vvv" git clone <repositoryurl>

这主要用于处理与服务器的公钥和私钥问题。您可以将此命令用于任何git命令,而不仅仅是'git clone'。


是的,这个工作非常完美。比其他的更好。是的,这个工作非常完美。比其他的更好。 - BMW
这将非常有用,因为我现在必须解决一个关键问题,但它在我的git 1.8.3.1和OpenSSH_6.6.1p1,OpenSSL 1.0.1e-fips 11 Feb 2013上不起作用,CentOS Linux release 7.2.1511 (Core)。:( - Greg Dubicki
@GregDubicki 奇怪。请告诉我什么对您有用,以便我可以更新答案。 - Basil Musa
2
在Windows上使用 set GIT_SSH_COMMAND=ssh -v(不包括引号)。 - jansohn
在PowerShell中,您可以使用$env:GIT_SSH_COMMAND="ssh -v"...上面的评论者并不是指"Windows",而是指Windows上的cmd.exe - 0xC0000022L

51

试试这个:

GIT_TRACE=1 git pull origin master

24
Git 2.9.x/2.10 (Q3 2016) 添加了另一个调试选项:GIT_TRACE_CURL
查看提交 73e57aa提交 74c682d(2016年5月23日)由Elia Pinto(devzero2000
协助者:Torsten Bögershausen(tboegi,Ramsay Jones ramsay@ramsayjones.plus.com,Junio C Hamano(gitsterEric Sunshine(sunshinecoJeff King(peff
(由Junio C Hamano -- gitster --合并于提交 2f84df2,2016年7月6日) 实现`GIT_TRACE_CURL`环境变量,以允许更详细的`GIT_CURL_VERBOSE`,特别是完整的传输头和所有交换的数据负载。如果特定情况需要更彻底的调试分析,这可能会很有用。 文档将说明:
GIT_TRACE_CURL

Enables a curl full trace dump of all incoming and outgoing data, including descriptive information, of the git transport protocol.
This is similar to doing curl --trace-ascii on the command line.

This option overrides setting the GIT_CURL_VERBOSE environment variable.


你可以看到这个新选项在this answer中被使用,还有在Git 2.11(2016年第四季度)的测试中也被使用了。
查看提交14e2411提交81590bf提交4527aa1提交4eee6c6(2016年9月7日)由Elia Pinto(devzero2000提交。
(由Junio C Hamano -- gitster --合并于提交930b67e,2016年9月12日) 使用新的GIT_TRACE_CURL环境变量,而不是已弃用的GIT_CURL_VERBOSE
GIT_TRACE_CURL=true git clone --quiet $HTTPD_URL/smart/repo.git

请注意,并非所有命令都会产生跟踪记录。
例如:在 Git 2.32(2021年第二季度)之前,reflog到期机制尚未被教导产生跟踪事件。

请参阅提交 34c3199(2021年4月23日),作者为Han-Wen Nienhuys(hanwen
(由Junio C Hamano -- gitster --合并于提交 a850356,2021年5月7日) refs/debug:也追踪引用日志的过期时间 Signed-off-by: Han-Wen Nienhuys
从Git 2.39(2022年第四季度)开始,可以在GIT_CURL_VERBOSE和其他地方中,通过cURL的h2h3模块来隐藏头部信息。
查看提交 b637a41(2022年11月11日)由Glen Choo(chooglen完成。
查看提交 73c49a4(2022年11月11日)由Jeff King(peff完成。
(由Junio C Hamano -- gitster --提交 6adf170中合并,2022年11月23日) http:在信息中删除curl h2h3头部 协助者:Jeff King
签署者:Glen Choo
签署者:Taylor Blau

With GIT_TRACE_CURL=1 or GIT_CURL_VERBOSE=1, sensitive headers like "Authorization" and "Cookie" get redacted.
However, since curl/curl commit f8c3724, curl's h2h3 module (invoked when using HTTP/2) also prints headers in its "info", which don't get redacted.
For example,

echo 'github.com  TRUE    /   FALSE   1698960413304   o   foo=bar' >cookiefile &&
GIT_TRACE_CURL=1 GIT_TRACE_CURL_NO_DATA=1 git \
  -c 'http.cookiefile=cookiefile' \
  -c 'http.version=' \
  ls-remote https://github.com/git/git refs/heads/main 2>output &&
grep 'cookie' output

produces output like:

23:04:16.920495 http.c:678              == Info: h2h3 [cookie: o=foo=bar]
23:04:16.920562 http.c:637              => Send header: cookie: o=<redacted>

Teach http.c to check for h2h3 headers in info and redact them using the existing header redaction logic.
This fixes the broken redaction logic that we noted in the previous commit, so mark the redaction tests as passing under HTTP2.


从Git 2.42(2023年第三季度)开始,Git能够处理curl信息行中的"h2"和"h2h3"。
查看 commit fb7d80e(2023年6月24日)由 Junio C Hamano(gitster 提交。
查看 commit db30130(2023年6月17日)由 Jeff King(peff 提交。
(由 Junio C Hamano -- gitster -- 合并于 commit 94486b6,2023年6月24日)

http:在curl信息行中处理"h2"和"h2h3"两种情况 Signed-off-by: Jeff King
在从curl的跟踪输出中删除身份验证令牌时,我们会查找形式为"h2h3 [header: value]"的http/2标头。 这来自于b637a41("http: redact curl h2h3 headers in info",2022-11-11,Git v2.39.0-rc0 -- merge)。
但是,在curl's fc2f1e5 commit(http2: support HTTP/2 to forward proxies, non-tunneling, 2023-04-14)中,"h2h3"前缀更改为"h2"。 这在发布版本curl 8.1.0中;与该版本链接意味着我们将无法正确删除跟踪。 我们的t5559.17会注意到并失败。
我们可以通过匹配任一前缀来修复此问题,这应该处理旧版本和新版本。
从Git 2.43(2023年第四季度)开始,HTTP头部擦除代码已经针对较新版本的cURL库进行了调整,该版本与早期版本显示的痕迹有所不同。
查看提交 0763c3a提交 39fa527(2023年9月15日)由Jeff King (peff)
(由Junio C Hamano -- gitster --合并于提交 7a90d1e,2023年9月22日) http:更新与curl 8.3.0匹配的curl http/2信息 Signed-off-by: Jeff King
为了在http/2 curl跟踪中编辑头部行,我们必须解析掉curl传递给我们的信息行中附加的一些前缀字节。
这已经改变过一次了,我们在db30130(http:处理两者,2023-06-17,Git v2.42.0-rc0 -- merge列在batch #5中)中进行了适应(http:在curl信息行中同时处理"h2"和"h2h3",2023-06-17)。
现在又改变了,在curl的fbacb14提交(http2:清理跟踪消息,2023-08-04)中,这个改变在curl 8.3.0中发布。
使用与该版本链接的git构建将无法编辑跟踪(和以前一样,t5559会注意到并抱怨)。
这里的格式比其他格式稍微复杂一些,因为它现在包括一个"流ID"。
这个ID不是固定的,但总是数字,所以我们可以很容易地解析掉它。
当然,我们将继续匹配旧版本,因为我们希望与许多不同版本的curl一起工作。
我们甚至不能在编译时选择一个格式,因为行为取决于我们使用的curl运行时版本,而不是我们构建的版本。

这个功能很酷!唯一的问题是ASCII输出(其中他们将所有不是(ch >= 0x20) && (ch < 0x80)的内容打印为点“.”),并且没有HTTP数据的十六进制输出方式。 - kinORnirvana
我喜欢它。我正在使用 git version 2.39.1,与文档相反,我发现使用 GIT_CURL_VERBOSE=true GIT_TRACE_CURL=true git push 命令时,GIT_TRACE_CURL 实际上被 GIT_CURL_VERBOSE 覆盖了。 - learning2learn
@learning2learn 很奇怪,可能是一个 bug。这些天,我通常只依赖 TRACE2。从这个搜索来看,GIT_CURL_VERBOSE 看起来已经不再使用了。 - VonC
另请参阅提交 fb7d80e - VonC

15

Git 2.22(2019年第二季度)由Jeff Hostetler引入trace2,其中包含commit ee4512e

trace2:创建新的组合跟踪工具

创建一个新的统一跟踪工具,用于git。
最终目的是用一组统一的git_trace2*例程替换当前的trace_printf*trace_performance*例程。
除了通常的printf风格API外,trace2还提供了带有固定字段的更高级别的事件动词,允许编写结构化数据。
这使得外部工具的后处理和分析更加容易。
Trace2定义了3个输出目标。
这些是使用环境变量"GIT_TR2"、"GIT_TR2_PERF"和"GIT_TR2_EVENT"设置的。
这些可以设置为"1"或绝对路径名(就像当前的GIT_TRACE一样)。
注意:关于环境变量名称,始终使用GIT_TRACExxx而不是GIT_TRxxx
因此实际上是GIT_TRACE2GIT_TRACE2_PERFGIT_TRACE2_EVENT
请参见下面提到的Git 2.22重命名。
以下是关于这个新跟踪功能的初始工作,使用环境变量名称:
  • GIT_TR2旨在替代GIT_TRACE并记录命令摘要数据。

  • GIT_TR2_PERF旨在替代GIT_TRACE_PERFORMANCE
    它通过为命令进程、线程、repo、绝对和相对经过时间添加列来扩展输出。
    它报告子进程启动/停止、线程启动/停止以及每个线程函数嵌套的事件。

  • GIT_TR2_EVENT是一种新的结构化格式。它将事件数据写入一系列JSON记录中。

对trace2函数的调用会记录到任何已启用的3个输出目标中,无需调用不同的trace_printf*trace_performance*例程。

请参见提交记录a4d3a28(2019年3月21日),由Josh Steadmon(steadmon提交。
(由Junio C Hamano -- gitster合并于提交记录1b40314,2019年5月8日)

trace2:写入到目录目标中

当trace2环境变量的值是指向现有目录的绝对路径时,将输出写入给定目录下的文件中(每个进程一个文件)。 文件名将根据trace2 SID的最后一个组成部分命名,后跟计数器以避免潜在的冲突。
这使得通过无条件地将相关的trace2 envvar设置为一个常量目录名来方便地收集每个git调用的跟踪。

另请参见提交f672dee(2019年4月29日),以及提交81567ca提交08881b9提交bad229a提交26c6f25提交bce9db6提交800a7f9提交a7bc01e提交39f4317提交a089724提交1703751(2019年4月15日)由Jeff Hostetler (jeffhostetler)
(由Junio C Hamano -- gitster --提交5b2d1c0中合并,2019年5月13日)

新文档现在包括仅从系统和全局配置文件中读取的配置设置(这意味着不会考虑存储库本地和工作树配置文件以及-c命令行参数。)

示例

$ git config --global trace2.normalTarget ~/log.normal
$ git version
git version 2.20.1.155.g426c96fcdb

产生

$ cat ~/log.normal
12:28:42.620009 common-main.c:38                  version 2.20.1.155.g426c96fcdb
12:28:42.620989 common-main.c:39                  start git version
12:28:42.621101 git.c:432                         cmd_name version (version)
12:28:42.621215 git.c:662                         exit elapsed:0.001227 code:0
12:28:42.621250 trace2/tr2_tgt_normal.c:124 atexit elapsed:0.001265 code:0

而对于性能度量

$ git config --global trace2.perfTarget ~/log.perf
$ git version
git version 2.20.1.155.g426c96fcdb

产生

$ cat ~/log.perf
12:28:42.620675 common-main.c:38                  | d0 | main                     | version      |     |           |           |            | 2.20.1.155.g426c96fcdb
12:28:42.621001 common-main.c:39                  | d0 | main                     | start        |     |  0.001173 |           |            | git version
12:28:42.621111 git.c:432                         | d0 | main                     | cmd_name     |     |           |           |            | version (version)
12:28:42.621225 git.c:662                         | d0 | main                     | exit         |     |  0.001227 |           |            | code:0
12:28:42.621259 trace2/tr2_tgt_perf.c:211         | d0 | main                     | atexit       |     |  0.001265 |           |            | code:0

正如 Git 2.23(2019 年第三季度)所记录的那样,要使用的环境变量是GIT_TRACE2

请查看 commit 6114a40(2019年6月26日)由Carlo Marcelo Arenas Belón (carenas)提交。
请查看 commit 3efa1c6(2019年6月12日)由Ævar Arnfjörð Bjarmason (avar)提交。
(由Junio C Hamano -- gitster --合并于commit e9eaaa4,2019年7月9日)

这是在Git 2.22中完成的工作的后续:提交4e0d3aa提交e4b75d6(2019年5月19日),由SZEDER Gábor (szeder)完成。
(由Junio C Hamano -- gitster --提交463dca6中合并,2019年5月30日)

trace2:将环境变量重命名为GIT_TRACE2*

对于用户应该设置的环境变量,GIT_TR2* 环境变量太不清晰、不一致和难看了。
大多数已经建立的 GIT_* 环境变量没有使用缩写,而在少数几个使用缩写的情况下(GIT_DIRGIT_COMMON_DIRGIT_DIFF_OPTS),很明显这些缩写(DIROPTS)代表什么。
但是 TR 代表什么呢?跟踪、传统、拖车、事务、转移、转换、过渡、翻译、移植、传输、遍历、树、触发器、截断、信任还是其他什么?!
正如其名称中的 '2' 后缀所示,trace2 工具最终将取代 Git 的原始 trace 工具。
可以合理地期望相应的环境变量也会随之更改,在原始的 GIT_TRACE 变量之后,它们被称为 GIT_TRACE2;不存在 'GIT_TR' 这样的东西。
所有特定于 trace2 的配置变量都非常明智地位于 'trace2' 部分,而不是 'tr2'。
另一方面,从这些环境变量的名称中省略 "trace" 的最后三个字符并没有任何好处
因此,在它们进入稳定版本之前,让我们将所有的 GIT_TR2* 环境变量重命名为 GIT_TRACE2*

Git 2.24(2019年第三季度)改进了Git存储库的初始化。

请查看 提交记录22932d9, 提交记录5732f2b, 提交记录58ebccb (2019年8月6日) 由Jeff King (peff)提交。
(在提交记录b4a1eec中由Junio C Hamano -- gitster --合并,于2019年9月9日)

common-main: 延迟 trace2 的初始化

我们在 common main() 函数中初始化 trace2 系统,以便所有程序(即使不是内置程序)都能启用跟踪。 但 trace2 启动相对较耗时,因为我们必须实际读取磁盘上的配置来决定是否跟踪。
这可能会导致与其他 common-main 初始化产生意外的交互。例如,在调用 initialize_the_repository() 之前,我们将进入配置代码,并且通常的不变量 the_repository 永远不会为空将不成立。 让我们把 trace2 的初始化推迟到 common-main 更深处,在执行 cmd_main() 之前再进行初始化。

Git 2.24(2019年第四季度)还确保trace2子系统的输出现在更漂亮地格式化。

请查看 提交 742ed63, 提交 e344305, 提交 c2b890a (2019年8月9日), 提交 ad43e37, 提交 04f10d3, 提交 da4589c (2019年8月8日), 和 提交 371df1b (2019年7月31日) 作者为 Jeff Hostetler (jeffhostetler)
(由Junio C Hamano -- gitster --提交 93fc876合并, 2019年9月30日)

还有,仍然是Git 2.24

请查看提交 87db61a提交 83e57b0(2019年10月4日),以及提交 2254101提交 3d4548e(2019年10月3日),作者为Josh Steadmon (steadmon)
(由Junio C Hamano -- gitster --提交 d0ce4d9合并,2019年10月15日)

trace2:如果目标目录中的文件太多,则丢弃新跟踪

签名作者:Josh Steadmon

trace2 可以将文件写入目标目录。
该目录在大量使用时可能会充满文件,导致跟踪处理系统难以处理。

此修补程序添加了一个配置选项 (trace2.maxFiles),用于设置 trace2 将写入目标目录的文件数量上限。

当将 maxFiles 设置为正整数时,会启用以下行为:

  • trace2 将文件写入目标目录时,首先检查是否应丢弃跟踪。
    如果出现以下情况,则应丢弃跟踪:
    • 有一个标记文件声明文件数量过多
    • 或者,文件数量超过了 trace2.maxFiles。在后一种情况下,我们创建一个名为 git-trace2-discard 的标记文件以加速未来的检查。

假设单独的跟踪处理系统正在处理生成的跟踪;一旦它处理并删除了标记文件,再次生成新的跟踪文件就应安全了。

trace2.maxFiles 的默认值为零,这会禁用文件计数检查。

配置还可以通过新的环境变量 GIT_TRACE2_MAX_FILES 进行覆盖。


Git 2.24(2019年第四季度)教授trace2有关git push阶段的知识。

请参见提交25e4b80提交5fc3118(2019年10月2日),作者为Josh Steadmon(steadmon
(由Junio C Hamano -- gitster --提交3b9ec27中合并,2019年10月15日)

push:添加trace2工具检测

签名作者:Josh Steadmon

transport.cbuiltin/push.c中加入trace2区域,以更好地跟踪推送各个阶段所花费的时间:

  • 列出引用
  • 检查子模块
  • 推送子模块
  • 推送引用

从Git 2.25(2020年第1季度)开始,一些 Documentation/technical 已移动到标题* .h 文件中。
查看提交 6c51cb5, 提交 d95a77d, 提交 bbcfa30, 提交 f1ecbe0, 提交 4c4066d, 提交 7db0305, 提交 f3b9055, 提交 971b1f2, 提交 13aa9c8, 提交 c0be43f, 提交 19ef3dd, 提交 301d595, 提交 3a1b341, 提交 126c1cc, 提交 d27eb35, 提交 405c6b1, 提交 d3d7172, 提交 3f1480b, 提交 266f03e, 提交 13c4d7e (2019年11月17日) 由Heba Waly (HebaWaly)提交。
(由Junio C Hamano -- gitster --合并于提交 26c816a, 2019年12月16日)

trace2:将文档移动到trace2.h

签名作者:Heba Waly

将函数文档从Documentation/technical/api-trace2.txt移动到trace2.h,因为这样开发人员可以更容易地在代码旁边找到使用信息,而不是在另一个文档文件中查找。

仅从Documentation/technical/api-trace2.txt中删除了函数文档部分,因为该文件充满了细节,似乎更适合放在单独的文档文件中,并在trace2.h中添加了指向文档文件的链接。此外,删除函数文档以避免具有冗余信息,这将很难与头文件中的文档保持同步。

尽管这种重组对另一个命令产生了副作用,但在2020年3月的Git 2.25.2中通过commit cc4f2eb(由Jeff King (peff)于2020年2月14日修复)进行了解释和修复。
(由Junio C Hamano -- gitster --合并于commit 1235384,2020年2月17日)


在Git 2.27(2020年第二季度)中:Trace2增强功能,允许记录环境变量。

请参见提交3d3adaa(2020年3月20日),作者为Josh Steadmon(steadmon
(由Junio C Hamano -- gitster --提交810dc64中合并,2020年4月22日)

trace2:教Git记录环境变量

签名作者:Josh Steadmon
确认作者:Jeff Hostetler

通过trace2,Git已经可以记录有趣的配置参数(参见trace2_cmd_list_config()函数)。然而,这可能会给出不完整的图片,因为许多配置参数也允许通过环境变量进行覆盖。

为了允许更完整的日志记录,我们添加了一个新的trace2_cmd_list_env_vars()函数和支持实现,模仿现有的配置参数日志记录实现。


在Git 2.27(2020年第二季度)中,教授代码路径以显示进度条的同时,还要使用start_progress()stop_progress()调用作为“区域”进行跟踪。

请参见提交98a1364(2020年5月12日),作者是Emily Shaffer(nasamuffin
(由Junio C Hamano -- gitster --提交d98abce合并,2020年5月14日)

trace2:记录进度时间和吞吐量

签名作者:Emily Shaffer

与其只教授一个操作,比如 'git fetch',如何将吞吐量写入跟踪中,我们可以通过向进度库本身添加工具来学习各种可能看起来很慢的用户操作

显示进度的操作很可能运行缓慢,而且这也是我们想要监视性能的事情。

通过显示对象计数和数据传输大小,我们应该能够进行一些派生测量,以确保操作按照我们的预期进行扩展。

另外:

使用 Git 2.27(2020 年第二季度),我们对最近更改的最后一分钟修复,允许使用进度 API 作为可跟踪区域。

请查看 提交 3af029c(2020年5月15日),作者为Derrick Stolee (derrickstolee)
(由Junio C Hamano -- gitster --提交 85d6e28中合并,2020年5月20日)

progress:仅在调用_enter()后调用trace2_region_leave()

签名作者:Derrick Stolee

进度API的用户有条件地调用start_progress(),并依赖于display_progress()stop_progress()函数在未调用start_progress()时变为无操作。
由于我们在start_progress()中添加了对trace2_region_enter()的调用,进度API函数中其他trace2 API调用必须确保在进度结构上没有调用start_progress()时跳过这些trace2调用。
具体来说,在未调用进度结构上的start_progress()时,请勿从stop_progress()调用trace2_region_leave(),因为那将调用匹配的trace2_region_enter()

Git 2.29(2020年第4季度)的最后一部分更加强大:

请参见提交ac900fd(2020年8月10日),作者为Martin Ågren (none)
(由Junio C Hamano -- gitster --提交e6ec620中合并,2020年8月17日)

进度:在检查NULL之前不要取消引用

签名作者:Martin Ågren

stop_progress()中,我们小心地检查p_progress是否为非NULL,然而在调用finish_if_sparse(*p_progress)时,我们已经取消引用了它。
而且,值得一提的是,在stop_progress_msg()内部,我们将继续盲目地取消引用它。


随着 Git 2.29(2020 年第四季度)的推出,在 Git 开发环境中有更多的跟踪功能。

请参见 提交 4441f42(由 Han-Wen Nienhuys (hanwen) 于 2020 年 9 月 9 日提交)
(由 Junio C Hamano -- gitster -- 于 2020 年 9 月 22 日合并至 提交 c9a04f0

refs:添加GIT_TRACE_REFS调试机制

签名作者:Han-Wen Nienhuys

When set in the environment, GIT_TRACE_REFS makes git print operations and results as they flow through the ref storage backend. This helps debug discrepancies between different ref backends.

Example:

$ GIT_TRACE_REFS="1" ./git branch
15:42:09.769631 refs/debug.c:26         ref_store for .git
15:42:09.769681 refs/debug.c:249        read_raw_ref: HEAD: 0000000000000000000000000000000000000000 (=> refs/heads/ref-debug) type 1: 0
15:42:09.769695 refs/debug.c:249        read_raw_ref: refs/heads/ref-debug: 3a238e539bcdfe3f9eb5010fd218640c1b499f7a (=> refs/heads/ref-debug) type 0: 0
15:42:09.770282 refs/debug.c:233        ref_iterator_begin: refs/heads/ (0x1)
15:42:09.770290 refs/debug.c:189        iterator_advance: refs/heads/b4 (0)
15:42:09.770295 refs/debug.c:189        iterator_advance: refs/heads/branch3 (0)

git现在在其手册页中新增了以下内容:

GIT_TRACE_REFS

启用对引用数据库操作的跟踪消息。 有关可用的跟踪输出选项,请参见GIT_TRACE


在 Git 2.30(2021 年第一季度)中,与 die()error() 类似,调用 warning() 也会触发 trace2 事件。

请参见 commit 0ee10fd(由 Jonathan Tan (jhowtan) 于 2020 年 11 月 23 日提交)。
(由 Junio C Hamano -- gitster -- 合并于 commit 2aeafbc,2020 年 12 月 8 日)

用法:在warning()时添加trace2条目

署名:Jonathan Tan

每当调用warning()时,发出一个trace2错误事件,就像调用die()error()usage()一样。
这有助于调试会触发警告但不会出现错误的问题。特别是,这可能有助于调试我在$DAYJOB遇到的提交图问题。
在包含潜在相关消息和混乱的跟踪输出之间存在权衡。我认为应该在跟踪中包括warning()消息,因为Git的性质是在多次调用Git工具时使用的,而Git调用中的故障(当前已跟踪)可能是由先前Git调用中的意外交互引起的,而只有警告(当前未跟踪)作为症状 - 就像这里的情况一样。

在 Git 2.35 版本(2022 年第一季度)中,正确追踪了 exit 命令:

参见 提交记录368b584(由 Ævar Arnfjörð Bjarmason (avar) 于 2021 年 12 月 7 日提交)。
(由 Junio C Hamano -- gitster -- 合并至 提交记录67b7017,2021 年 12 月 22 日)

common-main.c: 调用 exit(),不要返回

签名作者:Ævar Arnfjörð Bjarmason

Change the main() function to call "exit()" instead of ending with a "return" statement.
The "exit()" function is our own wrapper that calls trace2_cmd_exit_fl() for us, from git-compat-util.h:

#define exit(code) exit(trace2_cmd_exit_fl(__FILE__, __LINE__, (code)))

That "exit()" wrapper has been in use ever since ee4512e ("trace2: create new combined trace facility", 2019-02-22, Git v2.22.0-rc0 -- merge listed in batch #2).

There is already code immediately downstream of our "main()" which has a hard reliance on that, e.g. the various "exit()" calls downstream of "cmd_main()" in "git.c".


从Git 2.36(2022年第二季度)开始,进展API在追踪方面更加健壮。

请查看 提交 b3118a5, 提交 74900a6, 提交 accf1eb, 提交 1ccad6a, 提交 a02014b, 提交 bbfb1c2, 提交 791afae, 提交 587c3d0, 提交 8266e0c (2022年2月3日) 由 Ævar Arnfjörð Bjarmason (avar) 提交。
(由 Junio C Hamano -- gitster -- 合并于 提交 a47fcfe, 2022年2月25日)

进度 API:统一stop_progress{,_msg}(),修复trace2 bug

签名作者:Ævar Arnfjörð Bjarmason

我们这里出现了一个潜水虫子,是由9d81ecb引入的("progress: add sparse mode to force 100% complete message",2019-03-21,Git v2.22.0-rc0 -- merge listed in batch #5)。
如果进度是以"stop_progress()"而不是"stop_progress_msg()"结束,那么"start_sparse_progress()" API只会做正确的事情。
虽然该API的唯一用户使用"stop_progress()",但我们仍然通过将"stop_progress()"作为"stop_progress_msg()"的简单包装器来解决这个问题,同时也解决了trace2问题。

4

您尝试过在克隆时添加详细模式 (-v) 操作符吗?

git clone -v git://git.kernel.org/pub/scm/.../linux-2.6 my2.6


4

对于旧版本的 git(1.8 及之前版本)

在旧版 git 和 ssh 版本中,我找不到合适的方法来启用 SSH 调试。我使用 ltrace -e getenv ... 查找环境变量,但无法找到任何组合的 GIT_TRACE 或 SSH_DEBUG 变量可用。

相反,以下是一个临时注入 'ssh -v' 到 git->ssh 顺序的方法:

$ echo '/usr/bin/ssh -v ${@}' >/tmp/ssh
$ chmod +x /tmp/ssh
$ PATH=/tmp:${PATH} git clone ...
$ rm -f /tmp/ssh

这是使用git版本1.8.3和ssh版本OpenSSH_5.3p1,OpenSSL 1.0.1e-fips 11 Feb 2013克隆github仓库的输出:

$ (echo '/usr/bin/ssh -v ${@}' >/tmp/ssh; chmod +x /tmp/ssh; PATH=/tmp:${PATH} \
   GIT_TRACE=1 git clone https://github.com/qneill/cliff.git; \
   rm -f /tmp/ssh) 2>&1 | tee log
trace: built-in: git 'clone' 'https://github.com/qneill/cliff.git'
trace: run_command: 'git-remote-https' 'origin' 'https://github.com/qneill/cliff.git'
Cloning into 'cliff'...
OpenSSH_5.3p1, OpenSSL 1.0.1e-fips 11 Feb 2013
debug1: Reading configuration data /home/q.neill/.ssh/config
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Applying options for *
debug1: Connecting to github.com ...
...
Transferred: sent 4120, received 724232 bytes, in 0.2 seconds
Bytes per second: sent 21590.6, received 3795287.2
debug1: Exit status 0
trace: run_command: 'rev-list' '--objects' '--stdin' '--not' '--all'
trace: exec: 'git' 'rev-list' '--objects' '--stdin' '--not' '--all'
trace: built-in: git 'rev-list' '--objects' '--stdin' '--not' '--all'

0
Git 2.39(2022年第四季度)新增了两个新的trace2工具:“timer”和“counter”。

请查看 提交 8107162, 提交 8ad5756, 提交 24a4c45, 提交 3124793, 提交 a70839c, 提交 8e8c5ad, 提交 5bbb925, 提交 545ddca (2022年10月24日) 由 Jeff Hostetler (Jeff-Hostetler) 提交。
(由 Taylor Blau -- ttaylorr -- 合并于 提交 e5be3c6, 2022年10月30日)

trace2:添加秒表计时器

签名作者:Jeff Hostetler

计时器是Trace2区域的替代品。
区域对于测量各种计算阶段所花费的时间非常有用,例如读取索引的时间、扫描未暂存文件的时间、扫描未跟踪文件的时间等。

然而,并不是所有地方都适合使用区域。

例如,在检出期间,使用区域来测量从整个进程的生命周期中从ODB(对象数据库)中膨胀对象所花费的总时间将非常低效;每个unzip()区域会使输出泛滥并显着减慢命令;并且需要某种形式的后处理来计算在unzip()中花费的时间。

计时器可用于测量一系列计时器间隔并发出单个摘要事件(在线程和/或进程退出时)。

technical/api-trace2现在包含在其手册页面中:

"th_timer"

This event logs the amount of time that a stopwatch timer was running in the thread. This event is generated when a thread exits for timers that requested per-thread events.

{
"event":"th_timer",
...
"category":"my_category",
"name":"my_timer",
"intervals":5,         # number of time it was started/stopped
"t_total":0.052741,    # total time in seconds it was running
"t_min":0.010061,      # shortest interval
"t_max":0.011648       # longest interval
}

"timer"

This event logs the amount of time that a stopwatch timer was running aggregated across all threads. This event is generated when the process exits.

{
"event":"timer",
...
"category":"my_category",
"name":"my_timer",
"intervals":5,         # number of time it was started/stopped
"t_total":0.052741,    # total time in seconds it was running
"t_min":0.010061,      # shortest interval
"t_max":0.011648       # longest interval
}

technical/api-trace2现在包含在其手册页面中:

Stopwatch Timer Events

Measure the time spent in a function call or span of code that might be called from many places within the code throughout the life of the process.

static void expensive_function(void)
{
trace2_timer_start(TRACE2_TIMER_ID_TEST1);
...
sleep_millisec(1000); // Do something expensive
...
trace2_timer_stop(TRACE2_TIMER_ID_TEST1);
}

static int ut_100timer(int argc, const char **argv)
{
...

expensive_function();

// Do something else 1...

expensive_function();

// Do something else 2...

expensive_function();

return 0;
}

In this example, we measure the total time spent in expensive_function() regardless of when it is called in the overall flow of the program.

$ export GIT_TRACE2_PERF_BRIEF=1
$ export GIT_TRACE2_PERF=~/log.perf
$ t/helper/test-tool trace2 100timer 3 1000
...
$ cat ~/log.perf
d0 | main                     | version      |     |           |           |              | ...
d0 | main                     | start        |     |  0.001453 |           |              | t/helper/test-tool trace2 100timer 3 1000
d0 | main                     | cmd_name     |     |           |           |              | trace2 (trace2)
d0 | main                     | exit         |     |  3.003667 |           |              | code:0
d0 | main                     | timer        |     |           |           | test         | name:test1 intervals:3 total:3.001686 min:1.000254 max:1.000929
d0 | main                     | atexit       |     |  3.003796 |           |              | code:0

而且,还有 Git 2.39:

trace2:添加全局计数器机制

签名作者:Jeff Hostetler

在Trace2中添加全局计数器机制。
Trace2计数器机制增加了创建一组全局计数器变量和一个API以有效地递增它们的能力。计数器可以选择性地报告每个线程的使用情况,除了所有线程的总和之外。
当线程退出和进程退出时,计数器事件将被发射到Trace2日志中。
计数器是datadata_json事件的替代品。
当您想要测量整个过程中的某些内容时,当您不想因性能原因而进行每次测量事件时,当数据不方便地适合于区域内或者当您的控制流不容易让您编写最终总数时,计数器非常有用。例如,您可以使用此功能报告对unzip()的调用次数或检出期间的去重步骤数。
现在,technical/api-trace2在其手册页面中包含了这些信息。

"th_counter"

This event logs the value of a counter variable in a thread. This event is generated when a thread exits for counters that requested per-thread events.

{
"event":"th_counter",
...
"category":"my_category",
"name":"my_counter",
"count":23
}

"counter"

This event logs the value of a counter variable across all threads. This event is generated when the process exits. The total value reported here is the sum across all threads.

{
"event":"counter",
...
"category":"my_category",
"name":"my_counter",
"count":23
}

0
在 Git 2.37 (Q3 2022) 中,引入了一个新的 bug()BUG_if_bug() API,以便更容易地统一记录“检测多个错误并在最后中止”的模式。
这将成为 trace2 输出的一部分,用于调试与 git-shell 相关的问题。

请查看 提交 6d40f0a, 提交 07b1d8f, 提交 5b2f5d9, 提交 53ca569, 提交 0cc05b0, 提交 19d7594 (2022年6月2日) 由 Ævar Arnfjörð Bjarmason (avar) 提交。
(由 Junio C Hamano -- gitster -- 合并于 提交 4da14b5, 2022年6月10日)

usage.c:添加一个非致命的bug()函数以配合BUG()

签名作者:Ævar Arnfjörð Bjarmason

在编程中添加一个bug()函数,用于在运行时需要指示BUG()的情况下,但由于我们可能正在积累更多的bug()调用者以详尽地指示出错情况,因此希望推迟BUG()调用。
我们已经在代码库的各个部分中有这种设施,只是使用了该新API提供功能的即兴再创造形式。
例如:
这将用于替换parse-options.c中的optbug(),以及builtin/receive-pack.c中循环中执行的'error("BUG:[...]'。
与其所替换的代码不同,我们将记录到trace2中这个新的bug()函数(与其他usage.c函数一样,包括BUG()),我们还能够避免在某些情况下对xstrfmt()的调用,因为bug()函数本身接受可变参数sprintf()-like arguments。
任何对bug()的调用都可以在这些调用之后跟随BUG_if_bug(),如果有任何先前对bug()的调用,则会BUG() out(即abort())。调用者也可以决定不调用BUG_if_bug()并将产生的BUG()调用留到exit()时间。
目前没有不在for-loop之后自己调用BUG_if_bug()的bug() API用户,但允许不调用BUG_if_bug()可以使API更灵活。正如这里的测试和文档所示,我们将在我们的exit()包装器中捕获缺少BUG_if_bug()调用的情况。

technical/api-error-handling现在在其手册页面中包含以下内容:

BUGbugdieusageerrorwarning报告错误。

technical/api-error-handling现在在其手册页面中包含以下内容:

  • bug(小写,不是BUG)应该像BUG一样使用,但会打印一个“BUG”消息而不是调用abort()

调用bug()将导致对BUG()函数的“真实”调用,可以通过在调用bug()之后显式调用BUG_if_bug()或在exit()时隐式调用来实现,在那里我们将检查是否遇到了任何未解决的bug()调用。

如果在调用BUG_if_bug()之前没有调用bug(),则后者是NOOP。 BUG_if_bug()函数接受与BUG()本身相同的参数。显式调用BUG_if_bug()并不是必需的,但可以确保我们尽快死亡。

如果您知道之前调用过bug(),那么调用BUG()本身等效于调用BUG_if_bug(),后者是一个包装器,如果我们设置了指示已调用bug()的标志,则调用BUG()

technical/api-trace2现在在其手册页面中包含以下内容:

当调用BUG()bug()error()die()warning()usage()函数之一时,将触发此事件。


在 Git 2.38 (Q3 2022) 中,您甚至可以在运行时打印命令使用的配置值

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接