【问题标题】:How to designate a local repository as a remote for another local repository?如何将本地存储库指定为另一个本地存储库的远程?
【发布时间】:2017-09-09 07:07:52
【问题描述】:

为了更好地了解 Git 的工作原理,我想检查远程存储库在与本地存储库交互(通过获取、推送等)时所经历的更改。

  1. 假设我的本地文件系统中有两个 Git 存储库 A 和 B。是否可以将 A 指定为相对于 B 的远程存储库,以便例如在 B 中执行的所有 push 命令都将推送到 A?

  2. 是否可以使用clone 命令从 A 克隆一个新的本地存储库 C?

【问题讨论】:

  • 为什么要在本地创建一个 repo 主机,因为它可以使用 github 轻松完成而无需任何费用。
  • @AmitK:例如,当远程存储库托管在 GitHub 上时,我如何检查 HEAD 的值?
  • @AmitK OP 问题的第一句话描述了您的问题的答案:“为了更好地理解 Git 的工作原理”

标签: git git-push git-clone git-remote git-fetch


【解决方案1】:

就 Git 本身而言,所有 Git 存储库都是 peers。此外,任何存储库至少在逻辑上是完全自包含的(您可以使用“备用对象位置”做一些棘手的事情,使它们在物理上相互依赖,但现在让我们忽略它)。

假设我的本地文件系统中有两个 Git 存储库 A 和 B。是否可以将 A 指定为相对于 B 的远程存储库,以便例如在 B 中执行的所有推送命令都将推送到 A?

暂时支持一下,让我们看看remote的定义。这个术语有些过分(例如,我们可以谈论“远程对等点”或“某个远程主机上的 Git”),但每个 Git 存储库通过其自己的本地配置文件 (git config) 定义了一些数字——可能为零——遥控器

遥控器只是一个名称,例如 origin 或在我们的例子中为 A。该名称成为用作键/值对的稍长名称的一部分:remote.A.key1 = some-valueremote.A.key2 = another value 等等。

因此,在存储库 B 中,我们可以定义一个名为 A 的远程,设置其中一些键/值对。至少需要一个键/值对(以便创建[remote "A"] 部分),此处适合设置url

cd B
git config remote.A.url <some url here>

Repo B 现在有一个名为 A 的遥控器。 URL 可以只是一个简单的路径,或ssh://host.name/path/to/repo.git,或以git://http://https://file:// 开头的东西。

URL 需要到达可以读取和/或写入其他存储库的 Git。如果 URL 是本地文件系统路径,则您自己的 Git 扮演这两个角色,但至少在逻辑上,它假装与代表另一个存储库的单独 Git 对话。

如果B 将运行git fetch读取 A,第二个remote.A 条目非常重要。这将提供默认的 refspec,通常是:

git config --add remote.A.fetch '+refs/heads/*:refs/remotes/A/*'

请注意,可能有多个fetch refspecs 以这种方式定义(这是在此处使用--add 的原因)。当您在存储库B 中时,如果您现在运行git fetch git push 并使用名称A 作为远程,您的Git 将调用另一个将发送对象的Git来自A(如果您正在获取)或接收发往A(如果您正在推送)的对象。

请注意,默认的 fetch refspec 或 refspecs 来自 git config --get-all remote.A.url,但默认的 push refspec 或 refspecs 更复杂(取决于 push.default,和/或者如果它们已设置,remote.A.pushremote.A.mirror 设置)。

还有一个可选的remote.A.pushurl 设置。如果设置了此项,git push A 将不连接到 remote.A.url 地址,而是连接到 remote.A.pushurl 地址。

(还有remote.pushDefault:如果你运行git push而没有指定remoteremote.pushDefault会覆盖当前分支的branch.<em>branch</em>.remote设置,但不会覆盖它的branch.<em>branch</em>.pushRemote设置。这一切都非常复杂,唯一的方法是咨询the git config documentation。)

请注意,您根本没有 在这里使用命名遥控器!你可以:

git fetch <url> <refspec>

和:

git push <url> <refspec>

使用像A 这样的命名远程的好处是您可以获得所有这些为您做一些花哨的事情的配置条目,例如记住复杂的 URL 和复杂的默认 refspecs。此外,这使您能够:

git config branch.evil.remote A
git config branch.zorg.remote A

这意味着无论何时你在分支evilzorg 上,你的Git 应该默认连接到远程A。将此与url 设置和默认fetch 设置结合起来,在refs/remotes/A/ 命名空间中设置远程跟踪分支,您将获得一种与远程Git 交谈的便捷方式,无论它是“非常远程”(完全在另一台机器上)或“一点也不远程”(在你自己的机器上)——尽管花哨的远程跟踪分支的东西对于一个根本不远程的远程来说显然不那么重要。

(配置branch.<em>name</em>.remote 设置是为该分支配置上游 工作的一半。另一半通过配置branch.<em>name</em>.merge 完成。使用git branch --set-upstream-to=A/zorg,您可能会这样做在您的分支zorg 上,同时设置两者。)

是否可以使用 clone 命令从 A 克隆一个新的本地仓库 C?

是的:git clone 的语法是 git clone [ <em>options</em> ] <em>url</em> [ <em>directory</em> ]。 URL 可以像以前一样只是一个简单的路径名。如果是,则默认启用--local 选项。

克隆存储库会自动在新的 Git 存储库中创建一个远程。这个遥控器默认命名为origin,有两个默认设置:

remote.origin.url = <url>
remote.origin.fetch = +refs/heads/*:refs/remotes/origin/*

这当然是任何遥控器的推荐设置。请注意,fetch 设置的 refspec 值的右侧嵌入了遥控器的名称:这里是 origin,而对于 remote.A.fetch,它是 A

...我想检查远程存储库在与本地存储库交互时所经历的更改(通过获取、推送等)。

真的没有“等”:就是获取和推送。您可以运行 git ls-remotegit remote show,这两个可以将一个 Git 连接到另一个 Git,但此时它们不会交互:它们只是获取公共引用并将它们打印出来 (@987654392 @) 或将它们与本地存储库中的设置进行比较 (git remote show)。

“获取公共引用”步骤是第一步——嗯,也许是第二步——git fetchgit push 也是如此,因为你的 Git(你是运行或推送的人)想要决定 要获取什么要推送什么,这些往往需要知道其他 Git 中存在哪些引用。 (推送似乎可能不在乎“他们”有什么,但它至少对matchingsimple 有用。第一步,如果你想称之为第二步,正在建立通用协议功能,这是所有“智能”传输所做的事情,因为协议随着时间的推移而有所发展。)

【讨论】:

    【解决方案2】:

    这两个问题的答案都是:是的!

    像往常一样使用 Git 命令,并将另一个存储库的完整路径或相对路径作为参数 &lt;repository&gt; 传递。

    例如,使用:

    git clone ../repoA repoB
    

    将仓库../repoA克隆到当前目录的子目录repoB中。

    详细了解需要远程存储库 URL 的 Git 命令中的 ways to specify an URL

    【讨论】:

      猜你喜欢
      • 2014-05-08
      • 2020-01-09
      • 2011-07-23
      • 2014-09-06
      • 2011-09-16
      • 1970-01-01
      • 2014-10-20
      • 1970-01-01
      相关资源
      最近更新 更多