【问题标题】:Pushing Git non-branch references to a remote将 Git 非分支引用推送到远程
【发布时间】:2020-12-31 03:37:18
【问题描述】:

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。理想情况下,我应该在不知道名称的情况下看到\获取所有新的引用。

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

【问题讨论】:

  • 如果你将引用推送到原点,当你在新的仓库中克隆它时,它将出现在refs/remotes/origin 下。 git-push 上有很多文档。也许有一些方法可以在推送时保留原始 ref 结构。

标签: git git-branch git-remote


【解决方案1】:

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

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

【讨论】:

  • 你不需要这样做。你可以从一开始就做git push origin the-id-i-really-want:refs/heads/new-branch
【解决方案2】:

Refspecs 作为一个一般概念很棒,但对它们来说有一种未完成的感觉。 ?

当您第一次克隆某个​​现有存储库时,您的 git clone 使用与 git remote add 等效的内置函数来添加远程名称。正如the git remote documentation 注释(有点elliptically - see meaning 2a):

使用 -t <branch> 选项,而不是默认的 glob refspec 用于远程跟踪 refs/remotes/<name>/ 命名空间下的所有分支,而是创建一个仅跟踪 <branch> 的 refspec。您可以提供多个-t <branch> 来跟踪多个分支,而无需抓取所有分支。

这归结为在git clone 之后,新克隆的(单个)默认获取参考规范是:

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

其中&lt;name&gt; 是来自-o 选项的名称,如果您未指定此类选项,则为origin1

它没有明确提及并且不明显的是Git配置文件中的remote.<em>remote</em>.fetch设置是累积的。2这意味着你可以打开现有的@987654337 @ 文件,一旦 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 选项获取将删除您现有的任何refs/exp/* 引用,这些引用在origin 上没有对应名称。

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

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

现在您已经发明了 exp 跟踪名称。

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


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

【讨论】:

  • 感谢您的全面回答!这样可行!我想知道是否有办法让回购消费者(他们可能不知道这个技巧)的这种体验更顺畅:1)回购消费者应该运行什么命令以获得相同的结果; 2)我应该怎么做才能使常规git clone拉出所有结果。
  • 我接受了这个 - 它为这个问题提供了一个可靠的答案。关于我的后续问题 - 我会尝试解决这个问题或创建一个单独的问题。
  • @DmitryPetrov:“如何让这一切变得更顺畅”是一个很好的(但又是独立的)问题,这就是我对 refspecs 的想法的其余部分未完成的意思:没有政策的机​​制。)
猜你喜欢
  • 1970-01-01
  • 2011-09-10
  • 2016-07-08
  • 1970-01-01
  • 2012-07-25
  • 1970-01-01
  • 2016-10-25
  • 2018-12-22
  • 1970-01-01
相关资源
最近更新 更多