如何同步两个Git仓库

35
我有两个存储在不同电脑上的git仓库。每个仓库都有一些本地分支。我不想将这些分支发送到远程服务器,只想保持它们本地。那么,如何在不使用网络的情况下进行同步?我是否可以将一个PC上的仓库打包并移动到另一个PC上呢?这样安全吗?也许我可以以某种方式导出每个分支的最新更改?

1
“服务器”上的Git仓库与其他PC的唯一区别(如果有区别)在于服务器上的仓库可能是裸仓库。将其他电脑视为您看待服务器的方式完全相同。 - William Pursell
4个回答

26

与其制作一个裸克隆,我更喜欢制作一个捆绑包(参见“如何通过电子邮件发送git存储库?”),它会生成一个文件,更容易复制(例如在USB闪存驱动器上)。

好处是它具有一些裸仓库的特性:您可以从中拉取或克隆它,但只需要担心一个文件。

machineB$ git clone /home/me/tmp/file.bundle R2

这将会在结果库中定义一个名为 "origin" 的远程,让你可以从该捆绑包中提取和拉取。在 R2 中的 $GIT_DIR/config 文件将会有如下的条目:
[remote "origin"]
    url = /home/me/tmp/file.bundle
    fetch = refs/heads/*:refs/remotes/origin/*

要更新结果为mine.git的存储库,您可以在用增量更新替换存储在/home/me/tmp/file.bundle中的捆绑包后进行提取或拉取。
在原始存储库中再进行一些工作后,您可以创建一个增量捆绑包来更新其他存储库:
machineA$ cd R1
machineA$ git bundle create file.bundle lastR2bundle..master
machineA$ git tag -f lastR2bundle master

你可以将这个“bundle”文件传输到另一台机器上以替换“/home/me/tmp/file.bundle”,然后从那里拉取。
machineB$ cd R2
machineB$ git pull

23

请查看这篇博客文章"Synchronizing Git repositories without a server "(作者:Victor Costan)。

本文介绍一种在没有连接两个主机的网络服务器的情况下,在两个存储库之间推送更改的方法。

首先在 USB 硬盘上创建一个存储库。

mkdir /path/to/usb/stick/repository.git
git clone --local --bare . /path/to/usb/stick/repository.git

然后将存储库注册为远程存储库到USB存储设备,并将所需的分支推送到该存储库(如果您不想推送主分支,则替换为所需的分支)。

git remote add usb file:///path/to/usb/stick/repository.git
git push usb master

将来,您可以将USB存储库视为任何其他远程存储库。只需确保它已挂载 :) 例如,以下操作将新更改推送到USB存储库。

git push usb

在接收端,挂载USB存储设备,并使用文件URL来访问代码库。

file:///path/to/usb/stick/repository.git

一些方便的命令:
# cloning the repository on the USB stick
git clone file:///path/to/usb/stick/repository.git
# updating a repository cloned from the USB stick using the above command
git pull origin
# adding the USB stick repository as a remote for an existing repository
git remote add usb file:///path/to/usb/stick/repository.git
# updating from a remote repository configured using the above command
git pull usb master

1
永远不要完全依赖外部链接:你不知道它会持续多久。有了http://blog.stackoverflow.com/2009/06/stack-overflow-creative-commons-data-dump/,这些信息将永远可用。 - VonC
第一个“git clone --local”是否最好改为“git clone --no-hardlinks”,以明确需要深度复制? - Dave Amphlett
我相信这会有用。在OSX上,我遇到了Unix链接失败的错误,直到我进行了切换。我也在同样的情况下切换到了--no-local,尽管我不确定是否必要。对我有效的命令是:git clone --no-local --no-hardlinks --bare . /path/to/repository.git/ 。之后,我们两个人就能像任何其他远程一样推送和拉取了。 - XML
@VonC 至少我们希望它能永远存在 - 但不能保证 Stack Overflow 十年后还会存在。 - Snowcrash
在这个阶段,我收到了“致命错误:存储库'.'不存在”的消息:git clone --local --bare . /path/to/usb/stick/repository.git - Snowcrash

5
直接将存储库复制到其他文件系统是裸克隆或打包的替代方法。复制后,您可以直接将已复制的存储库设置为本地远程 - 尽管本地远程可能不太直观 - 以获取并合并到第一个存储库中。
例如,要将来自第二台计算机的repo2合并到~/repo1中,首先将repo2复制到~/repo2的repo1文件系统中(内存棒,网络复制等),然后您可以使用Git pulling changes between two local repositories的答案。
~/repo1 $ git remote add repo2 ~/repo2
~/repo1 $ git fetch repo2
~/repo1 $ git merge repo2/foo

这是因为正如git的维基百科文章所说:“Git仓库(数据和元数据)完全包含在其目录中,因此对整个Git仓库进行常规系统级别的复制(或重命名、删除)是安全的操作。结果副本既独立于原始副本,也不知道原始副本。”

有比我更多知识的人可以确认一下吗?@sage 如果我只想通过复制粘贴到USB存储器来备份我的目录(其中包含我的.git),这样做就足够了吗? - nutty about natty
2
@nutty - 直接复制对于以其确切状态传输存储库是有效的,我经常这样做。但是,对于某些用例,我发现能够从一个磁盘位置拉取/合并到另一个位置更可取(例如,当我编辑了两个存储库位置并且想要将它们同步)。Git在这方面非常包容。 :-) - sage

0

我想为事情添加一点变化。其他帖子中的信息似乎是正确的,但我想提到一些我在实践中做的额外事情。

如果我这样做

git remote -v

我获取的信息是这样的。
USB_F   file:///f/Git_repositories/projectname.git (fetch)
USB_F   file:///f/Git_repositories/projectname.git (push)
USB_G   file:///g/Git_repositories/projectname.git (fetch)
USB_G   file:///g/Git_repositories/projectname.git (push)

基本上,我定义了几个远程设备,使用 USB 名称而不是只使用一个建议的名称,因为分配给我的 USB 设备的驱动器号取决于我将其插入的端口。

然后,我运行一个类似以下内容的脚本:

cd /path/to/projectname

if [ -d /f/Git_repositories/projectname.git ] 
then
    git push USB_F --all
    git push USB_F --tags
fi
if [ -d /g/Git_repositories/projectname.git ] 
then
    git push USB_G --all
    git push USB_G --tags
fi

意图是将所有分支和标签推送到USB存储库,如果存在并且无论在哪里都可以。 (-d标志检查git存储库目录的存在,并且仅在目录存在时执行条件代码。)

原始问题说:每个人都有一些本地分支。 我不想将这些分支发送到远程服务器,只需将它们保留在本地。 如何同步...

push -all和push --tags命令会进行此同步,确保将所有分支和标记推送到USB存储库,即使是USB存储库不知道的新分支和标记。 没有默认为主分支或需要知道分支名称并逐个处理它们。

我出于备份目的运行此操作,因此仅显示了推送方面,并减少了项目和存储库的数量。 实际上,我将多个项目备份到多个位置,但这里只涉及重复的USB项目。

另一个相当明显但我没有看到提到的事情是,为了同步PC A和PC B,您需要

1. sync PC A and the USB device
2. sync PC B and the USB device
3. sync PC A and the USB device again!

或者换个角度,继续

PC A -> USB -> PC B
PC B -> USB -> PC A

这样最终两台机器上的分支和标签才会相同。


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