如何将本地存储库指定为另一个本地存储库的远程存储库?

How to designate a local repository as a remote for another local repository?

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

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

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

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

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

例如,使用:

git clone ../repoA repoB

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

在需要 URL 远程存储库的 Git 命令中阅读有关 ways to specify an URL 的更多信息。

所有 Git 存储库都是 同行 ,就 Git 本身而言。此外,任何存储库至少在逻辑上是完全独立的(您可以使用 "alternate object locations" 做一些棘手的事情,使它们 在物理上 相互依赖,但我们暂时忽略它) .

Suppose I have two Git repositories, A and B, in my local file system. Is it possible to designate A as a remote repository with respect to B, so that, for instance all push commands performed in B will be pushed to A?

暂时支持一下,让我们看看 remote 的定义。该术语有点过载(例如,我们可以谈论 "remote peer" 或 "a Git at some remote host"),但每个 Git 存储库都通过其自己的本地配置文件 (git config) 进行定义, remotes.

的某个数字(可能为零)

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

因此,在存储库 B 中,我们可以定义一个名为 A 的远程,设置其中一些 key/value 对。至少需要一对 key/value(以便创建 [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 需要到达可以读取 and/or 写入其他存储库的 Git。如果 URL 是一个本地文件系统路径,你自己的 Git 扮演这两个角色,但至少在逻辑上,它 假装 与一个单独的 Git 表示另一个存储库。

第二个 remote.A 条目非常重要,如果 B 将永远 运行 git fetch 从 [=18 读取 =].这将提供默认的 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,and/or是否设置,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 这样的命名远程的好处是您可以获得所有这些为您做一些奇特事情的配置条目,例如记住复杂的 URLs 和复杂的默认 refspecs。此外,这使您能够:

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

这意味着无论何时您在分支 evilzorg 上,您的 Git 应该默认连接到远程 A。将其与 url 设置和默认 fetch 设置相结合,以在 refs/remotes/A/ name-space 中设置远程跟踪分支,您将获得一种方便的方式与远程 Git,无论是 "very remote"(完全在另一台机器上)还是 "not at all remote"(在你自己的机器上)——虽然花哨的远程跟踪分支的东西对于一个完全不远程。

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

Is it possible to clone a new local repository C from A using the clone command?

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

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

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

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

... I'd like to inspect the changes that a remote repository undergoes as it interacts with a local repository (via fetch, push, etc.).

真没有"etc":fetch和push就是了。您可以 运行 git ls-remotegit remote show,这两个可以将一个 Git 连接到另一个,但它们不会 交互 要点:这些只是获取 public 引用并将它们打印出来 (git ls-remote) 或将它们与本地存储库中的设置进行比较 (git remote show)。

"obtain public references" 步骤是 git fetchgit push 中的第一步,也许是第二步,因为您的 Git(您是运行ning 或 push) 想要决定 获取什么 推送什么 ,这些往往需要知道哪些引用存在于另一个 Git。 (Push 似乎并不关心 "they" 有什么,但它至少对 matchingsimple 有效。 第一步 ,如果你想称之为第二步,就是建立通用协议功能,这是所有 "smart" 传输所做的事情,因为协议随着时间的推移有所发展。)