如何获取给定目录名称的树哈希?
How to get the tree hash for a given directory name?
我想在树对象上附加一条注释。然而,为了这样做,我首先需要知道树对象的散列。对于作为我的存储库一部分的给定目录名称,我如何获取其所属树对象的哈希值以便为其附加注释?
通过阅读 this answer 我知道我可以使用
git cat-file -p master^{tree}
列出根树的内容,但我仍然需要 grep 目录名称的输出,并递归地跟踪嵌套的树对象以获得层次结构中更深目录的树对象的哈希值。
基本上,我正在寻找一个虚构的 get-tree-hash.sh
脚本的实现。如果这样调用
get-tree-hash.sh path/to/directory/in/my/git/repo
它应该输出
The hash for the "repo" tree inside "path/to/directory/in/my/git" is:
92a68a2f5560fa7080393b633e2afd1d5271deef
我自己想出来的,
git ls-tree HEAD -- path/to/directory/in/my/git | cut -d' ' -f3 | cut -f1
做我想做的。
你可以这样做:
git rev-parse HEAD:path/to/directory/in/my/git
只打印散列。所以你不需要 cut
或 awk
来提取它。
而不是
git ls-tree HEAD -- path/to/directory/in/my/git | cut -d' ' -f3 | cut -f1
您可以使用新的格式选项(Git 仅限 2.36+,2022 年第 2 季度):
git ls-tree <tree-ish> --format='%x09'
随着 Git 2.36(2022 年第 2 季度),“git ls-tree
"(man) learns --oid-only
option, similar to "--name-only
", and more generalized "--format
" option。
参见 commit 22184af (23 Mar 2022) by Johannes Schindelin (dscho
)。
参见 commit 9c4d58f, commit 0f88783, commit 455923e, commit e815171, commit 132ceda, commit 26f6d4d, commit 82e69b0, commit 4e4566f, commit a53343e (23 Mar 2022) by Ævar Arnfjörð Bjarmason (avar
)。
参见 commit cab851c, commit 315f22c, commit f6b224d, commit 87af0dd, commit 889f783 (23 Mar 2022) by Teng Long (dyrone
)。
(由 Junio C Hamano -- gitster
-- in commit 1041d58 合并,2022 年 4 月 4 日)
ls-tree
: introduce "--format
" option
Signed-off-by: Ævar Arnfjörð Bjarmason
Signed-off-by: Teng Long
Add a --format
option to ls-tree
.
It has an existing default output, and then --long
and --name-only
options to emit the default output along with the objectsize and, or to only emit object paths.
Rather than add --type-only
, --object-only
etc.
we can just support a --format
using a strbuf_expand()
similar to "for-each-ref --format".
We might still add such options in the future for convenience.
The --format
implementation is slower than the existing code, but this change does not cause any performance regressions.
We'll leave the existing show_tree()
unchanged, and only run show_tree_fmt()
in if a --format
different than the hardcoded built-in ones corresponding to the existing modes is provided.
I.e.
something like the "--long" output would be much slower with this, mainly due to how we need to allocate various things to do with quote.c
instead of spewing the output directly to stdout.
The new option of '--format' comes from Ævar Arnfjörð Bjarmasonn's idea and suggestion, this commit makes modifications in terms of the original discussion on community.
In that thread, there was a "GIT_TEST_LS_TREE_FORMAT_BACKEND"
variable to ensure that we had test coverage for passing tests that would otherwise use show_tree()
through show_tree_fmt()
, and thus that the formatting mechanism could handle all the same cases as the non-formatting options.
Somewhere in subsequent re-rolls of that we seem to have drifted away from what the goal of these tests should be.
We're trying to ensure correctness of show_tree_fmt()
.
We can't tell if we "hit [the] fast-path" here, and instead of having an explicit test for that, we can just add it to something our "test_ls_tree_format"
tests for.
Here is the statistics about performance tests:
Default format (hitten the builtin formats):
"git ls-tree <tree-ish>" vs "--format='%(mode) %(type) %(object)%x09%(file)'"
$hyperfine --warmup=10 "/opt/git/master/bin/git ls-tree -r HEAD"
Benchmark 1: /opt/git/master/bin/git ls-tree -r HEAD
Time (mean ± σ): 105.2 ms ± 3.3 ms [User: 84.3 ms, System: 20.8 ms]
Range (min … max): 99.2 ms … 113.2 ms 28 runs
$hyperfine --warmup=10 "/opt/git/ls-tree-oid-only/bin/git ls-tree -r --format='%(mode) %(type) %(object)%x09%(file)' HEAD"
Benchmark 1: /opt/git/ls-tree-oid-only/bin/git ls-tree -r --format='%(mode) %(type) %(object)%x09%(file)' HEAD
Time (mean ± σ): 106.4 ms ± 2.7 ms [User: 86.1 ms, System: 20.2 ms]
Range (min … max): 100.2 ms … 110.5 ms 29 runs
Default format includes object size (hitten the builtin formats):
"git ls-tree -l <tree-ish>" vs "--format='%(mode) %(type) %(object) %(size:padded)%x09%(file)'"
$hyperfine --warmup=10 "/opt/git/master/bin/git ls-tree -r -l HEAD"
Benchmark 1: /opt/git/master/bin/git ls-tree -r -l HEAD
Time (mean ± σ): 335.1 ms ± 6.5 ms [User: 304.6 ms, System: 30.4 ms]
Range (min … max): 327.5 ms … 348.4 ms 10 runs
$hyperfine --warmup=10 "/opt/git/ls-tree-oid-only/bin/git ls-tree -r --format='%(mode) %(type) %(object) %(size:padded)%x09%(file)' HEAD"
Benchmark 1: /opt/git/ls-tree-oid-only/bin/git ls-tree -r --format='%(mode) %(type) %(object) %(size:padded)%x09%(file)' HEAD
Time (mean ± σ): 337.2 ms ± 8.2 ms [User: 309.2 ms, System: 27.9 ms]
Range (min … max): 328.8 ms … 349.4 ms 10 runs
git ls-tree
现在包含在其 man page 中:
--format=<format>
A string that interpolates %(fieldname)
from the result
being shown.
It also interpolates %%
to %
, and
%xx
where xx
are hex digits interpolates to character
with hex code xx
; for example %00
interpolates to
[=53=]
(NUL), %09
to \t
(TAB) and %0a
to \n
(LF).
When specified, --format
cannot be combined with other
format-altering options, including --long
, --name-only
and --object-only
.
git ls-tree
现在包含在其 man page 中:
The output format of ls-tree
is determined by either the --format
option, or other format-altering options such as --name-only
etc.
(see --format
above).
The use of certain --format
directives is equivalent to using those
options, but invoking the full formatting machinery can be slower than
using an appropriate formatting option.
In cases where the --format
would exactly map to an existing option
ls-tree
will use the appropriate faster path. Thus the default format
is equivalent to:
%(objectmode) %(objecttype) %(objectname)%x09%(path)
git ls-tree
现在包含在其 man page 中:
Customized format:
It is possible to print in a custom format by using the --format
option,
which is able to interpolate different fields using a %(fieldname)
notation.
For example, if you only care about the "objectname
" and "path
" fields, you
can execute with a specific "--format
" like
git ls-tree --format='%(objectname) %(path)' <tree-ish>
FIELD NAMES
Various values from structured fields can be used to interpolate
into the resulting output. For each outputing line, the following
names can be used:
objectmode
The mode of the object.
objecttype
The type of the object (blob
or tree
).
objectname
The name of the object.
objectsize[:padded]
The size of the object ("-
" if it's a tree).
It also supports a padded format of size with "%(size:padded)".
path
The pathname of the object.
我想在树对象上附加一条注释。然而,为了这样做,我首先需要知道树对象的散列。对于作为我的存储库一部分的给定目录名称,我如何获取其所属树对象的哈希值以便为其附加注释?
通过阅读 this answer 我知道我可以使用
git cat-file -p master^{tree}
列出根树的内容,但我仍然需要 grep 目录名称的输出,并递归地跟踪嵌套的树对象以获得层次结构中更深目录的树对象的哈希值。
基本上,我正在寻找一个虚构的 get-tree-hash.sh
脚本的实现。如果这样调用
get-tree-hash.sh path/to/directory/in/my/git/repo
它应该输出
The hash for the "repo" tree inside "path/to/directory/in/my/git" is:
92a68a2f5560fa7080393b633e2afd1d5271deef
我自己想出来的,
git ls-tree HEAD -- path/to/directory/in/my/git | cut -d' ' -f3 | cut -f1
做我想做的。
你可以这样做:
git rev-parse HEAD:path/to/directory/in/my/git
只打印散列。所以你不需要 cut
或 awk
来提取它。
而不是
git ls-tree HEAD -- path/to/directory/in/my/git | cut -d' ' -f3 | cut -f1
您可以使用新的格式选项(Git 仅限 2.36+,2022 年第 2 季度):
git ls-tree <tree-ish> --format='%x09'
随着 Git 2.36(2022 年第 2 季度),“git ls-tree
"(man) learns --oid-only
option, similar to "--name-only
", and more generalized "--format
" option。
参见 commit 22184af (23 Mar 2022) by Johannes Schindelin (dscho
)。
参见 commit 9c4d58f, commit 0f88783, commit 455923e, commit e815171, commit 132ceda, commit 26f6d4d, commit 82e69b0, commit 4e4566f, commit a53343e (23 Mar 2022) by Ævar Arnfjörð Bjarmason (avar
)。
参见 commit cab851c, commit 315f22c, commit f6b224d, commit 87af0dd, commit 889f783 (23 Mar 2022) by Teng Long (dyrone
)。
(由 Junio C Hamano -- gitster
-- in commit 1041d58 合并,2022 年 4 月 4 日)
ls-tree
: introduce "--format
" optionSigned-off-by: Ævar Arnfjörð Bjarmason
Signed-off-by: Teng Long
Add a
--format
option tols-tree
.
It has an existing default output, and then--long
and--name-only
options to emit the default output along with the objectsize and, or to only emit object paths.Rather than add
--type-only
,--object-only
etc.
we can just support a--format
using astrbuf_expand()
similar to "for-each-ref --format".
We might still add such options in the future for convenience.The
--format
implementation is slower than the existing code, but this change does not cause any performance regressions.
We'll leave the existingshow_tree()
unchanged, and only runshow_tree_fmt()
in if a--format
different than the hardcoded built-in ones corresponding to the existing modes is provided.I.e.
something like the "--long" output would be much slower with this, mainly due to how we need to allocate various things to do withquote.c
instead of spewing the output directly to stdout.The new option of '--format' comes from Ævar Arnfjörð Bjarmasonn's idea and suggestion, this commit makes modifications in terms of the original discussion on community.
In that thread, there was a
"GIT_TEST_LS_TREE_FORMAT_BACKEND"
variable to ensure that we had test coverage for passing tests that would otherwise useshow_tree()
throughshow_tree_fmt()
, and thus that the formatting mechanism could handle all the same cases as the non-formatting options.Somewhere in subsequent re-rolls of that we seem to have drifted away from what the goal of these tests should be.
We're trying to ensure correctness ofshow_tree_fmt()
.
We can't tell if we "hit [the] fast-path" here, and instead of having an explicit test for that, we can just add it to something our"test_ls_tree_format"
tests for.Here is the statistics about performance tests:
Default format (hitten the builtin formats):
"git ls-tree <tree-ish>" vs "--format='%(mode) %(type) %(object)%x09%(file)'" $hyperfine --warmup=10 "/opt/git/master/bin/git ls-tree -r HEAD" Benchmark 1: /opt/git/master/bin/git ls-tree -r HEAD Time (mean ± σ): 105.2 ms ± 3.3 ms [User: 84.3 ms, System: 20.8 ms] Range (min … max): 99.2 ms … 113.2 ms 28 runs $hyperfine --warmup=10 "/opt/git/ls-tree-oid-only/bin/git ls-tree -r --format='%(mode) %(type) %(object)%x09%(file)' HEAD" Benchmark 1: /opt/git/ls-tree-oid-only/bin/git ls-tree -r --format='%(mode) %(type) %(object)%x09%(file)' HEAD Time (mean ± σ): 106.4 ms ± 2.7 ms [User: 86.1 ms, System: 20.2 ms] Range (min … max): 100.2 ms … 110.5 ms 29 runs
Default format includes object size (hitten the builtin formats):
"git ls-tree -l <tree-ish>" vs "--format='%(mode) %(type) %(object) %(size:padded)%x09%(file)'" $hyperfine --warmup=10 "/opt/git/master/bin/git ls-tree -r -l HEAD" Benchmark 1: /opt/git/master/bin/git ls-tree -r -l HEAD Time (mean ± σ): 335.1 ms ± 6.5 ms [User: 304.6 ms, System: 30.4 ms] Range (min … max): 327.5 ms … 348.4 ms 10 runs $hyperfine --warmup=10 "/opt/git/ls-tree-oid-only/bin/git ls-tree -r --format='%(mode) %(type) %(object) %(size:padded)%x09%(file)' HEAD" Benchmark 1: /opt/git/ls-tree-oid-only/bin/git ls-tree -r --format='%(mode) %(type) %(object) %(size:padded)%x09%(file)' HEAD Time (mean ± σ): 337.2 ms ± 8.2 ms [User: 309.2 ms, System: 27.9 ms] Range (min … max): 328.8 ms … 349.4 ms 10 runs
git ls-tree
现在包含在其 man page 中:
--format=<format>
A string that interpolates
%(fieldname)
from the result being shown.It also interpolates
%%
to%
, and%xx
wherexx
are hex digits interpolates to character with hex codexx
; for example%00
interpolates to[=53=]
(NUL),%09
to\t
(TAB) and%0a
to\n
(LF).When specified,
--format
cannot be combined with other format-altering options, including--long
,--name-only
and--object-only
.
git ls-tree
现在包含在其 man page 中:
The output format of
ls-tree
is determined by either the--format
option, or other format-altering options such as--name-only
etc. (see--format
above).The use of certain
--format
directives is equivalent to using those options, but invoking the full formatting machinery can be slower than using an appropriate formatting option.In cases where the
--format
would exactly map to an existing optionls-tree
will use the appropriate faster path. Thus the default format is equivalent to:%(objectmode) %(objecttype) %(objectname)%x09%(path)
git ls-tree
现在包含在其 man page 中:
Customized format:
It is possible to print in a custom format by using the
--format
option, which is able to interpolate different fields using a%(fieldname)
notation. For example, if you only care about the "objectname
" and "path
" fields, you can execute with a specific "--format
" likegit ls-tree --format='%(objectname) %(path)' <tree-ish>
FIELD NAMES
Various values from structured fields can be used to interpolate into the resulting output. For each outputing line, the following names can be used:
objectmode
The mode of the object.
objecttype
The type of the object (
blob
ortree
).
objectname
The name of the object.
objectsize[:padded]
The size of the object ("
-
" if it's a tree). It also supports a padded format of size with "%(size:padded)".
path
The pathname of the object.