如何在独立的git存储库之间同步分支?

时间:2017-02-24 17:07:21

标签: git

我有两个独立的git存储库;一个用于保存我的数据分析项目的代码,另一个用于保存运行代码的输出。所以,它看起来像这样:

.
|-- project_output
|   |-- .git
|   |-- output_sample1
|   |-- output_sample2
|   `-- output_sample3
`-- project_code
    |-- .git
    |-- code
    |   `-- all_my_scripts.sh
    `-- output -> ../project_output

输出数据由非常大的基于文本的文件组成,我将其保存在project_output中。该项目本身在GitHub上是开源的,并在project_code上进行跟踪。我使用git来跟踪两者的变化。

当我想向project_code添加新功能,或调试或更改旧功能时,我会创建一个分支:

project_code$ git checkout -b fix-some-bug
project_code$ # make some changes, run the new code
project_code$ # save output in output -> ../project_output

现在,我可以查看project_output中输出的更改:

project_output$ git status
project_output$ git diff

如果我想保留新输出,我会提交:

project_output$ git add -u; git add .
project_output$ git commit -m "Update results from project_code/fix-some-bug branch"

然而,跟踪project_codeproject_output的不同分支的输出是相当繁琐和困难的。我认为,如果有一个系统可以创建&更改project_code中的分支将在project_output中进行镜像。例如:

project_code$ git checkout -b fix-some-bug # project_output/fix-some-bug is created
project_code$ git checkout master # project_output switches to master branch as well
project_code$ git merge fix-some-bug # project_output merges fix-some-bug to master as well

我想这听起来很像我希望拥有一个存储库的好处,同时保持保持敏感数据不会触及我的公共存储库的安全性。

1 个答案:

答案 0 :(得分:1)

总而言之,您有点想拥有一个只有代码的 public 存储库,以及第二个私有存储库,它可以从中获取代码。公共存储库,但随后添加数据。事实证明这非常容易(尽管如果你不小心的话, >

Git非常像星际迷航Borg collective:它喜欢采用另一个存储库的技术独特性 - 即新提交 - 并将其添加到自己的。实际上,这正是git fetch所做的。

要使用git fetch,您可以告诉您的Git通常通过某个网址的互联网电话调用其他Git。然后,你的Git主要获取所有引用 - 分支和标记名称的列表,还有其他内容。 (更准确地说,你的Git会得到他们的Git愿意显示你的任何东西,但默认情况下,他们会向你显示所有内容。)这些引用名称指向特定的提交。 1 然后你的Git会询问你还没有提交的任何提交,以及完成它们所需的任何其他对象。

由于git fetch的方向是"从他们,到我们",所有的转移都是这样的。 (最接近git fetch的是git push,我们指示我们的Git调用另一个Git并发送给他们我们的技术独特性。显然你不想从你的私人存储库中做到这一点。)一旦我们的Git拥有了所有对象,它就可以停在那里,或者设置名称来记住对象

如果我们告诉我们的Git保存名称,我们得到的名称是我们的名称,而不是他们的名字。但是,当我们使用分支名称作为起点来复制提交来查找提交时,我们通常会让我们的Git通过我们自己的存储库中的远程跟踪分支名称保存它们。例如,如果他们的master提交了我们没有的deadbee,我们会将他们的deadbee复制到我们的存储库中,然后让我们的origin/master记住这个哈希ID {{ 1}}。 2 (如果deadbee的父提交是deadbee,我们的Git也会使用ac0ffee,除非我们已经拥有它,等等。)

如果我们让我们的Git选择标记 -named提交(和/或脚注1中的标记对象),我们让Git将这些标记名称存储在我们的中标记名称,而不是"远程标记",因此,如果他们添加了名为ac0ffee的标记,我们为自己设置了一个名为v2.3的新标记。默认情况下,花式重命名仅适用于分支。但这是由您自己控制的:它是您的存储库,因此您可以控制所有内容。

在任何情况下,您都可以指示您的Git根本不设置自己的名字。如果你这样做,你就依赖v2.3在昏暗时间做过的事情,即它总是保存git fetch中得到的每个名称。正常.git/FETCH_HEAD 会覆盖上一个git fetch,因此您必须从该文件中提取提交ID,并在再次运行FETCH_HEAD之前做一些事情来记住它们

与此同时,无论您是否为其提交设置了自己的名称,您都拥有了所有提交(以及您指示git fetch复制的所有提交)。你的Git已经像博格一样,为你自己的添加了技术独特性。

因此,您所要做的就是将 public 存储库设置为私有存储库中的命名远程存储库,然后运行git fetch

git fetch

或:

~/repos/private$ git remote add public https://github.com/...

或您喜欢的任何网址。之后,运行:

~/repos/private$ git remote add public file://~me/repos/public

将让您的Git使用保存的URL调用另一个Git(可能在您自己的机器上! 3 ),并下载到您的私人存储库中,在"他们的&中找到任何新的唯一提交#34; (你的另一个)存储库。它将命名"他们的"分支~/repos/private$ git fetch public 等等,即将其分支从 X 重命名为public/master,因为我们与public/X一起使用的名称来创建此代码" remote",是git add

请注意不要将私有提交推送到公共存储库。像Borg一样,Git非常乐意添加的东西,但会让你对删除事情感到沮丧。好吧,也许不是死亡。 :-)但是一旦数据像这样逃脱,任何人都可以克隆它,即使你设法迅速将其从公共存储库中删除,它可能已被复制并广泛分发。

1 标记名称可以指向四种对象类型中的任何一种。通常它们将指向带注释的标记对象,然后标记对象指向提交,但有时标记名称只是直接指向提交。分支名称只能指向提交。

2 这是publicfetch不同的地方:当我们从push发送提交时,我们通常会要求他们设置他们的 master。他们没有"推送跟踪分支"为了我们。但是,如果我们使用拉取请求,我们会这样做"请设置您的主人"以更加迂回的方式,通过将我们的主人发送到他们可以识别为&#34的名称,请查看这个,然后决定你是否喜欢它"而不是更自动的"只要它很容易适应,请自动接受#34;。

换句话说,拉取请求相当于远程跟踪分支:一个安全的地方"存储您尚未完全信任的内容,以便您可以在合并这些新对象之前查看并决定这些新对象。因为他们的名字往往很糟糕 - 拉请求通常是编号的,并且" PR#1234"之间没有明显的联系。并且,例如,"我希望你把它加入到feature / california-bear"中,有些人会这样做。他们推送到他们自己的公共存储库,然后通过电子邮件宣布:"我在我的功能/甲虫中为你准备了新东西,为什么你不去{ {1}}来自我的公共存储库。"这有着完全相同的目的:您可以通过某个名称在某个URL处提交您的提交master。然后使用相同的网址或不同的网址来检索您的提交,这可能是因为他们已经在某个奇怪的名称(如git fetch下)或您的网址上的该网址名称为cafedad

3 将文件从您自己计算机上的一个存储库复制到您自己计算机上的另一个存储库时 - 即使用路径网址或pull/1234/head网址 - 您的Git可能会同时播放"你的Git"和他们的Git"在获取和推送对话中。但是,从高级视图来看,效果与两个单独的Gits相同,在两个独立的存储库中工作,通过相对较窄的通道交换数据,就像通过Internet连接一样。 / p>