99

使用 SVN,我在服务器上保存了一个大型存储库,并在几台机器上签出。这是一个非常好的备份系统,让我可以轻松地在任何机器上工作。我可以签出一个特定的项目,提交并更新“主”项目,或者我可以签出整个项目。

现在,我有一堆 git 存储库,用于各种项目,其中一些在 github 上。我也有我提到的 SVN 存储库,通过 git-svn 命令导入。

基本上,我喜欢将我所有的代码(不仅仅是项目,还有随机片段和脚本,一些东西,比如我的简历、我写的文章、我制作的网站等等)放在一个大存储库中,我可以轻松地克隆到远程机器,或记忆棒/硬盘驱动器作为备份。

问题是,因为它是一个私有存储库,并且 git 不允许签出特定文件夹(我可以将其作为单独的项目推送到 github,但更改会同时出现在主存储库和子存储库中)回购)

可以使用 git 子模块系统,但它也没有按照我想要的方式运行(子模块是指向其他存储库的指针,并且并不真正包含实际代码,因此它对备份毫无用处)

目前我有一个 git-repos 文件夹(例如 ~/code_projects/proj1/.git/ ~/code_projects/proj2/.git/),在对 proj1 进行更改后git push github,我将文件复制到 ~/ Documents/code/python/projects/proj1/ 并执行一次提交(而不是单个存储库中的众多提交)。然后做git push backupdrive1git push mymemorystick

那么,问题来了:您的个人代码和项目如何使用 git 存储库,并让它们保持同步和备份?

4

6 回答 6

75

强烈建议不要将不相关的数据放在给定的 Git 存储库中。创建新存储库的开销非常低,这是一个可以将不同的沿袭完全分开的功能。

反对这个想法意味着以不必要的纠缠历史告终,这使管理变得更加困难,而且——更重要的是——“考古”工具由于由此产生的稀释作用而变得不那么有用。此外,正如您所提到的,Git 假定“克隆单元”是存储库,并且由于其分布式特性而实际上必须这样做。

一种解决方案是保留每个项目/包/等。作为其自己的 存储库(即,没有工作树),位于受祝福的层次结构下,例如:

/repos/a.git
/repos/b.git
/repos/c.git

一旦建立了一些约定,将管理操作(备份、打包、Web 发布)应用到完整的层次结构就变得微不足道了,它的作用与“单片”SVN 存储库并不完全不同。使用这些存储库也变得有点类似于 SVN 工作流,此外还 可以使用本地提交和分支:

svn checkout   --> git clone
svn update     --> git pull
svn commit     --> git push

您可以在每个工作克隆中拥有多个遥控器,以便在多方之间进行同步:

$ cd ~/dev
$ git clone /repos/foo.git       # or the one from github, ...
$ cd foo
$ git remote add github ...
$ git remote add memorystick ...

然后,您可以从每个“源”中获取/拉取,在本地工作和提交,然后在您准备好类似的东西时将其推送(“备份”)到每个远程(注意如何将相同的提交和历史推送到每个遥控器!):

$ for remote in origin github memorystick; do git push $remote; done

将现有的工作存储库~/dev/foo 变成这样的裸存储库的最简单方法可能是:

$ cd ~/dev
$ git clone --bare foo /repos/foo.git
$ mv foo foo.old
$ git clone /repos/foo.git

这几乎等同于svn import-- 但不会丢弃现有的“本地”历史。

注意:子模块是一种包含共享相关 血统的机制,因此我确实不认为它们是您要解决的问题的合适工具。

于 2008-08-31T18:17:07.027 回答
28

我想在他推荐的地方添加Damien 的回答:

$ for remote in origin github memorystick; do git push $remote; done

您可以设置一个特殊的遥控器,用 1 个命令推送到所有单独的真实遥控器;我在http://marc.info/?l=git&m=116231242118202&w=2找到了它:

所以对于“git push”(多次推送相同的分支是有意义的),你实际上可以做我所做的:

  • .git/config 包含:

    [remote "all"]
    url = master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
    url = login.osdl.org:linux-2.6.git
    
  • 现在git push all master将“master”分支推送到这两个
    远程存储库。

您还可以使用以下构造来节省自己键入两次 URL 的时间:

[url "<actual url base>"]
    insteadOf = <other url base>
于 2009-04-23T00:24:42.550 回答
3

,我还没有尝试嵌套 git 存储库,因为我还没有遇到我需要的情况。正如我在#git 频道上读到的, git 似乎对嵌套存储库感到困惑,即您试图在git 存储库中进行git-init。管理嵌套 git 结构的唯一方法是使用git-submodule或 Android 的repo实用程序。

至于您所描述的备份责任,我说委派它......对我来说,我通常将每个项目的“原始”存储库放在工作中的网络驱动器上,由 IT 技术人员通过他们的备份策略定期备份选择。这很简单,我不必担心。;)

于 2008-08-31T15:11:54.320 回答
3

我也对处理此问题的建议方法感到好奇,并将描述我使用的当前设置(使用 SVN)。我基本上创建了一个存储库,其中包含一个迷你文件系统层次结构,包括它自己的 bin 和 lib 目录。这棵树的根目录中有一个脚本,它将设置您的环境以将这些 bin、lib 等...其他目录添加到正确的环境变量中。所以根目录基本上看起来像:

./bin/            # prepended to $PATH
./lib/            # prepended to $LD_LIBRARY_PATH
./lib/python/     # prepended to $PYTHONPATH
./setup_env.bash  # sets up the environment

现在在 /bin 和 /lib 里面有多个项目和它们对应的库。我知道这不是一个标准项目,但我小组中的其他人很容易签出 repo,运行“setup_env.bash”脚本并在他们的本地拥有所有项目的最新版本查看。他们不必担心安装/更新 /usr/bin 或 /usr/lib 并且每次结帐时都可以轻松进行多次结帐和非常本地化的环境。有人也可以只 rm 整个存储库,而不必担心卸载任何程序。

这对我们来说很好,我不确定我们是否会改变它。这样做的问题是在这个大存储库中有很多项目。是否有一种 git/Hg/bzr 标准方式来创建这样的环境并将项目分解到自己的存储库中?

于 2010-04-28T17:54:57.867 回答
2

使用mr一次管理多个 Git 存储库怎么样:

mr(1) 命令可以在一组存储库上签出、更新或执行其他操作,就好像它们是一个组合存储库一样。它支持 subversion、git、cvs、mercurial、bzr、darcs、cvs、vcsh、fossil 和 veracity 存储库的任意组合,并且可以轻松添加对其他版本控制系统的支持。[...]

它通过简单的 shell 脚本非常可配置。它可以做的一些例子包括:

[...]

  • 更新 git 存储库时,从两个不同的上游拉取并将两者合并在一起。
  • 并行运行多个存储库更新,大大加快了更新过程。
  • 记住由于笔记本电脑脱机而失败的操作,以便在它重新联机时重试。
于 2012-10-06T18:09:51.177 回答
1

还有另一种嵌套 git repos 的方法,但它不能解决您所追求的问题。尽管如此,对于正在寻找解决方案的其他人来说,我是:

在顶级 git repo 中,只需隐藏 .gitignore 中包含嵌套 git repo 的文件夹。这使得拥有两个独立(但嵌套!)的 git repos 变得很容易。

于 2010-08-08T19:44:04.587 回答