为什么for-each-ref和show-ref在裸仓库中的行为不同? [英] Why do for-each-ref and show-ref behave differently in a bare repository?

查看:102
本文介绍了为什么for-each-ref和show-ref在裸仓库中的行为不同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在标准(非裸机)Git存储库中,以下命令都给出基本相同的结果,因为它们列出了所有分支(每个命令后的数字是传递到wc -l的命令输出,以保持事情很简单):

In a standard (non-bare) Git repository the following commands all give essentially the same result, in that they list all the branches (the number after each command is the output of the command piped into wc -l just to keep things brief):

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

但是在裸仓库中,这似乎并不总是正确的:

but in a bare repository the same is not apparently always true:

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

因此,通过查看比此处所示更多的存储库,前三个命令始终给出一致的答案,无论是裸露还是非裸露,但后三个命令给出的结果并不总是与前三个相同,并且也不总是一致的彼此.有人可以解释为什么吗?

So from reviewing a lot more repositories than shown here, the first 3 commands always give consistent answers, bare or non-bare, but the last 3 give results that are not always the same as the first three, and not always consistent with each other. Can someone explain why?

从使用非裸存储库开始,我一直假定像branchshow-reffor-each-ref这样的命令可以在refs/heads目录的实际内容上运行,但是在裸露的情况下,这不可能成立,因为它们显示的结果多于refs/heads目录中的文件.

From working with non-bare repositories I've always assumed commands like branch, show-ref and for-each-ref work on the actual contents of refs/heads directory, but in the bare case this can't be true, because they show more results than there are files in the refs/heads directory.

推荐答案

简短答案:

通过引用参数来抑制shell的通配符处理:

Suppress the shell`s wildcard handling by quoting the arguments :

git for-each-ref "refs/heads/*"

然后再次运行您的命令.

and run your commands again.

由于packed-refsfind不会(或很少)为您提供正确的答案.

Because of packed-refs, find will not (or rarely) give you the correct answer.

详细答案:

您的命令有几个问题:

  1. 最重要的是:Git有两个位置来存储引用(即标签,分支等):.git/refs目录和文件.git/packed-refs.有关详细信息,请参见 git-pack-refs .

  1. The most important first: Git has two places to store refs (i.e. tags, branches, ...): the .git/refs directory AND the file .git/packed-refs. See git-pack-refs for details.

这排除了find ./refs/heads -type f以获得正确答案的可能性.

This rules out find ./refs/heads -type f for getting correct answers.

接下来的两件事:这些命令与您认为的不一样:

The next two things: These command do not what you think they do:

git for-each-ref refs/heads/*
git show-ref refs/heads/*

假定类Unix环境, shell 尝试通过匹配现有文件名来扩展*通配符.所以git实际上看到这样的命令:

Assuming a Unix-like environment the shell tries to expand the * wildcard by matching existing filenames. So git sees actually a command like this:

git for-each-ref refs/heads/master refs/heads/topic1

因此,每当引用仅在packed-refs文件中存储 时,shell都不会将该名称传递给git,因此没有输出.

So whenever a ref is stored only in the packed-refs file then the shell will not pass that name to git and hence there is no output.

与通配符匹配的第二个问题:shell不会将 not 递归到子目录中,因此即使将引用存储在.git/refs/heads/feature/foo中,分支feature/foo也不会显示.

The second issue with wildcard matching: The shell does not recurse into subdirectories, so a branch feature/foo will not show up even when the ref is stored in .git/refs/heads/feature/foo.

您可以通过引用参数来抑制Shell的通配符处理.这样做有几种方法,一种简单的方法是这样:

You could suppress the shell`s wildcard handling by quoting the arguments. There are several ways to do so, a simple way is this:

git for-each-ref "refs/heads/*"

裸仓库和非裸仓库之间的区别并不是真正的区别,而是"shell看到至少一个匹配项"和"shell根本看不到匹配项"之间的区别,因为在后一种情况下,shell照原样转发字符串(包括*)转到命令.在非裸仓库中,是这种情况,因为参数中缺少.git/前缀.

The difference is not really between bare and non-bare repositories but between "shell sees at least one match" and "the shell sees no match at all" because in the later case the shell forwards the string as is (including the *) to the command. In a non-bare repo this is the case because the .git/ prefix is missing in your arguments.

这篇关于为什么for-each-ref和show-ref在裸仓库中的行为不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆