将 Git 非分支引用推送到远程

Pushing Git non-branch references to a remote

Git 非分支引用(不是分支、标签、远程和注释)在本地机器上工作得很好,但我有麻烦将它们推送到远程:

$ git update-ref refs/exp/ee01 6a534fb5f9aad615ebeeb9d01ebe558a679a3cd1

创建成功:

$ cat .git/refs/exp/ee01
6a534fb5f9aad615ebeeb9d01ebe558a679a3cd1
$ git for-each-ref refs/exp
6a534fb5f9aad615ebeeb9d01ebe558a679a3cd1 commit refs/exp/ee01

推动它:

$ git push origin exp/ee01
Total 0 (delta 0), reused 0 (delta 0)
To https://github.com/dmpetrov/example-get-started-exp.git
 * [new branch]      refs/exp/ee01 -> refs/exp/ee01

但是,当我克隆这个 repo 时我没有看到它:

$ git clone https://github.com/dmpetrov/example-get-started-exp.git
$ cd example-get-started-exp/
$ git for-each-ref refs/exp  # it returns nothing

如何正确推送非分支引用?

编辑:我可以通过名称将其获取到 FETCH_HEAD。理想情况下,我应该 see\fetch 所有新的参考文献而无需事先知道名称。

$ git fetch origin exp/ee01
From https://github.com/dmpetrov/example-get-started-exp
 * branch            refs/exp/ee01 -> FETCH_HEAD

根据我的经验,如果你想将一些随机的东西推送到远程到一个新的(在远程的)分支中,那么你必须先从你的本地推送一个现有的分支然后你可以推送你的id想要:

git push origin master:new-branch
git push origin the-id-i-really-want:new-branch

Refspecs 作为一个通用概念很棒,但给人一种未完成的感觉。

当您第一次克隆一些现有的存​​储库时,您的 git clone 使用等同于 git remote add 的 built-in 来添加远程名称。如the git remote documentation notes (a bit elliptically - see meaning 2a):

With -t <branch> option, instead of the default glob refspec for the remote to track all branches under the refs/remotes/<name>/ namespace, a refspec to track only <branch> is created. You can give more than one -t <branch> to track multiple branches without grabbing all branches.

这归结为这样一个事实,即在 git clone 之后,新克隆的(单个)默认提取 refspec 是:

+refs/heads/*:refs/remotes/<name>/*

其中 <name> 是来自 -o 选项的名称,如果您没有指定这样的选项,则为 origin1

它没有明确提及且不明显的是 remote.<em>remote</em>.fetch Git 配置文件是累积的。2 这意味着您可以打开现有的 .git/config 文件,一旦 git clone 创建它,并编辑它。你会看到:

[remote "origin"]
    fetch = +refs/heads/*:refs/remotes/origin/*

您可以更改它以添加另一行,以便它显示为:

[remote "origin"]
    fetch = +refs/heads/*:refs/remotes/origin/*
    fetch = +refs/exp/*:refs/exp/*

现在任何 git fetch origin 都会用 origin 上的引用覆盖任何现有的 refs/exp/ 引用。使用 prune = true-p--prune 选项获取将删除任何在 origin.[=58= 上没有相应名称的现有 refs/exp/* 引用]

如果您希望将他们的 refs/exp/* 名字替换为您自己的 refs/rexp/origin/* 名字,请将第二行改为:

    fetch = +refs/exp/*:refs/rexp/origin/*

现在你发明了 exp-tracking 个名字。

(鉴于没有 refs/tags/*:refs/tags/* refspec——有或没有前导 + 符号——你可能想知道标签是如何工作的。这里的答案是“有点神奇,有内部规则这不能通过 refspec 来表达”。这就是我所说的有点未完成的感觉的一部分。在 git clone 期间放入什么也不是很明显,但请注意 git clone -c <em>name=value</em> 让你在 git clone 时间写入配置值。你仍然需要以某种方式知道你正在克隆的远程有 [=不过 34=] 个名字。)


1在即将发布的 Git 版本中,-o 选项可能有一个可配置的默认值,因此省略了 -o不一定意味着 使用 origin,但就目前而言,它始终是这个意思。

2相比之下,user.nameuser.email 等设置仅使用 last 值。也就是说,如果您的配置文件显示:

[user]
    name = fred
    name = flintstone

user.nameflintstone:较早的 fred 值已被丢弃,取而代之的是较晚的 flintstone 值。累积设置只能通过git config --get-allgit config --get-regexp获得;它以每个值一行的形式出现。有关详细信息,请参阅 the git config documentation