在标准(非裸露)Git存储库中,以下命令都给出基本相同的结果,因为它们列出了所有分支(每个命令后的数字是通过管道传递到wc -l
的命令输出保持简短):
R1) bare: false
pwd .../R1/.git
git branch 8
git for-each-ref refs/heads 8
git show-ref --heads 8
git for-each-ref refs/heads/* 8
git show-ref refs/heads/* 8
find ./refs/heads -type f 8
但是在裸存储库中,似乎并非总是如此:
R2) bare: true
pwd .../R2.git
git branch 24
git for-each-ref refs/heads 24
git show-ref --heads 24
git for-each-ref refs/heads/* 17
git show-ref refs/heads/* 13
find ./refs/heads -type f 14
R3) bare: true
pwd .../R3.git
git branch 15
git for-each-ref refs/heads 15
git show-ref --heads 15
git for-each-ref refs/heads/* 6
git show-ref refs/heads/* 6
find ./refs/heads -type f 6
R4) bare: true
pwd .../R4.git
git branch 36
git for-each-ref refs/heads 36
git show-ref --heads 36
git for-each-ref refs/heads/* 36
git show-ref refs/heads/* 0
find ./refs/heads -type f 0
因此,通过查看比此处所示更多的存储库,前三个命令始终给出一致的答案,无论是裸露还是非裸露,但是后三个命令给出的结果并不总是与前三个相同,并且也不总是一致的彼此。有人可以解释为什么吗?
从使用非裸存储库开始,我一直假设诸如branch
,show-ref
和for-each-ref
之类的命令可以在refs / heads目录的实际内容上使用,但是在裸露的情况下这是不正确的,因为它们显示的结果多于refs / heads目录中的文件。
答案 0 :(得分:3)
简短答案:
通过引用以下参数来抑制shell的通配符处理:
git for-each-ref "refs/heads/*"
然后再次运行命令。
由于packed-refs
,find
不会(或很少)给您正确的答案。
详细答案:
您的命令有几个问题:
最重要的第一件事:Git有两个位置来存储引用(即标签,分支等):.git/refs
目录和文件{{1} }。有关详细信息,请参见git-pack-refs。
这排除了.git/packed-refs
以获得正确的答案。
接下来的两件事:这些命令与您认为的不一样:
find ./refs/heads -type f
假设类似Unix的环境, shell 会尝试通过匹配现有文件名来扩展git for-each-ref refs/heads/*
git show-ref refs/heads/*
通配符。因此*
实际上看到这样的命令:
git
因此,只要将引用仅 存储在git for-each-ref refs/heads/master refs/heads/topic1
文件中,shell便不会将该名称传递给packed-refs
,因此没有输出。
通配符匹配的第二个问题:shell不会递归到子目录,因此即使将引用存储在git
中也不会显示分支feature/foo
。
您可以通过引用参数来抑制Shell的通配符处理。这样做有几种方法,一种简单的方法是:
.git/refs/heads/feature/foo
裸仓库和非裸仓库之间的区别并不是真正的区别,而是“ shell看到至少一个匹配项”和“ shell根本看不到匹配项”之间的区别,因为在后一种情况下,shell照原样转发字符串(包括git for-each-ref "refs/heads/*"
)。在非裸仓库中,是这种情况,因为参数中缺少*
前缀。