如何使git仓库记住所有远程仓库?

19

我有一个Git存储库,它是另一个存储库的派生版本。通常情况下,我会添加一个名为“upstream”的远程副本,它是我派生自的原始存储库。

$ git remote -v
origin git@github.com:skela/awesomeproject.git (fetch)
origin git@github.com:skela/awesomeproject.git (push)
upstream git://github.com/bob/awesomeproject.git (fetch)
upstream git://github.com/bob/awesomeproject.git (push)

有没有办法让这个额外的远程仓库在克隆时也保留下来呢? 比如我删除了本地仓库,然后执行:

git clone git@github.com:skela/awesomeproject.git

现在我要重新检查我的遥控器:

$ git remote -v
origin git@github.com:skela/awesomeproject.git (fetch)
origin git@github.com:skela/awesomeproject.git (push)

我的上游远程已经消失了!

我该如何确保我的 git 仓库始终保留这两个远程别名?

编辑: 只是为了添加一个主要原因,为了将一些答案引导到可接受的方向 ;)

目标是在我的仓库中有一个分支可以跟踪上游的 master 分支。

[remote "upstream"]
    url = git://github.com/bob/awesomeproject.git
    fetch = +refs/heads/*:refs/remotes/upstream/*
[branch "father"]
    remote = upstream
    merge = refs/heads/master

换句话说,我的repo中名为"father"的分支跟踪了名为upstream的远程主分支。

一旦我设置好了,它就可以很好地工作。但是一旦我再次克隆该repo,"father"分支指向的是origin而不是upstream。


可能是保留git远程的重复问题。 - sschuberth
3个回答

14

那是不可能的。Git只克隆存储库的内容,而不会克隆其设置。如果您想将远程硬编码到存储库中(这是否是一个好主意还有待商榷),请在存储库根目录中创建一个名为repo-setup.sh的脚本,执行以下操作:

git remote rm origin
git remote rm upstream
git remote add origin git@github.com:skela/awesomeproject.git
git remote add upstream git://github.com/bob/awesomeproject.git

在克隆代码库后,运行此文件。


1
子模块信息可以很好地传递,那么为什么远程不能呢?我并不是说应该持久化所有远程内容,但是将上游远程添加到分支库中是如此常见,肯定有一种正确的 Git 方法来实现吧? - Skela
不,绝对不是。子模块信息也没有完全克隆 - 只有 .gitmodules 文件。子模块的真实远程存储在 .git/config 中,这也没有被克隆。 - Chronial
使用子模块后,克隆之后只需要执行2个git命令,那么你知道是否有类似的远程操作吗?貌似没有git remote init和git remote update这样的命令 :P - Skela
1
如果其他人遇到了这个问题,我采用了GoZoner的建议来复制我想要的远程信息。还有Chronial在上面评论中的建议。基本上我最终不得不执行:git clone git@github.com:skela/awesomeproject.git ,cat .gitremotes >> .git/config - Skela
@Michael,听起来你可以在远程仓库中使用git hooks来处理这个问题。 - Chronial
显示剩余2条评论

5
创建一个名为.gitremotes的文件,并将其中与远程相关的内容填充为.git/config中的内容。将.gitremotes添加到仓库中。在克隆之后,将.git/config附加到.gitremotes。注意:如果您想要共享的远程(在.gitremotes中)与'git clone'自动创建的远程('orgin')存在名称冲突,则可能需要手动编辑一些内容。
为了轻松实现这一点,您可以定义一个bash函数:
function git-clone-r ()
{
  src=$1
  tgt=$2
  git clone $src $tgt
  cat ${tgt}/.gitremotes >> ${tgt}/.git/config
}

[以上内容并不高级,但说明了重点并能够发挥作用]

2
我使用这个脚本 https://github.com/juanpabloaj/git-remote-init 来保存和恢复带有 .gitremotes 文件的远程仓库。 - JuanPablo
@juanpablo 不错的脚本。我注意到它假设没有远程存在,并在已经定义了远程的情况下退出。您通常会绕过克隆存储库时设置的默认远程'origin'吗?否则,在克隆后,它将自然存在并且不需要进行任何特殊/非标准操作,您的脚本将默默返回。只是对您的工作流程好奇。 - timblaktu

1
这是GoZoner解决方案的稍作修改版。
您需要捕获关于仓库中所有远程信息的数据,存储到一个文件中,并将该文件存储在git仓库之外。每次添加新的远程信息时,您还需要更新此文件。实际上,这可以添加到您的git仓库中,以便下一次克隆或拉取会带入此文件。
从git 1.7.10+版本开始,git支持包含外部配置文件。
因此,您可以将以下行添加到您的仓库的.git/config中,以包含包含远程信息的外部配置文件:
[include]
    path            = /dir1/dir2/repo-remotes.gitinfo

1
我可以理解将该文件保留在存储库之外的原因,但我认为这有点否定了我在这里尝试实现的目标。本质上,我想添加一个跟踪此上游远程的分支,但当我将其添加到混合中时,问题变得过于复杂。 - Skela
Tuxdude:你知道如果我例如将.gitconfig或.gitremotes文件添加到我的repo中,然后在.git/config中添加[include] path=".gitconfig或.gitremotes",那么这是否会跨克隆持续存在? - Skela
@Skela - 理论上应该可以工作。但是在每次克隆之后,您需要至少更新包含路径以包含此文件。 - Tuxdude
好的,这比GoZoner的解决方案稍微好一些,但仍然不理想。我将检查git的发行说明。也许它已经添加到了更新的版本中? - Skela
好的,我不理解这个...我在.git/config中有两个起点,而且项目被推送到了这两个起点,但是当我从任何一个克隆时,它会以某种方式“失去这个”! - Michael

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接