如何保持两个检出的git仓库彼此同步?

时间:2020-03-01 07:55:35

标签: git synchronize

我将所有数据都保存在家用计算机的git存储库中。

只能从家用PC所在的本地LAN访问该家用PC(以及git repo)。不能将git repo放在可访问Internet的云服务器上,或将我的家用PC可以在Internet上访问。对于以下问题,必须提及此限制,因为否则,显而易见的解决方案是“将git repo放在云服务器上”。

我有一个随身携带的笔记本电脑,叫做Laptop-A。 在我旅行之前,我使用以下方法从家用PC上查看笔记本电脑A上的存储库: git clone ssh://主PC / ... 在旅行期间,我在笔记本电脑A上进行了本地更改,并在本地进行了更改,但由于无法通过互联网访问家用PC上的主存储库,因此无法推送它们。 我的更改只能在回家后才能推送,并且与我的家用PC位于同一局域网中。

这一切都可以,但是现在我在旅行时添加了Laptop-B。就像Laptop-A一样,此笔记本电脑也克隆了主存储库。实际上,两台笔记本电脑基本相同,但是它们是两台单独的计算机。如果其中一台笔记本电脑出现硬件故障,我会这样做。在那种情况下,我还有另一台笔记本电脑。

但是,现在我遇到的问题是,对于两台笔记本电脑真正是多余的,当我在一台笔记本电脑上对git repo进行本地更改时,该更改未反映在另一台笔记本电脑上的git repo中,因为他们显然是两个分别签出的回购副本。我可以分别在每台笔记本电脑上分别手动进行更改,但这很尴尬,而且我可能会犯一个错误,从而导致不一致。即使我做得正确,这也很烦人,一旦我回家后想从两台笔记本电脑中推出,就会导致合并冲突。

我想做的是在笔记本电脑A上进行更改,然后将其同步到笔记本电脑B,以便我回家后可以从任一笔记本电脑推送(到主存储库)。

我该怎么做?

1 个答案:

答案 0 :(得分:1)

除非您自己如此认为,否则任何Git存储库都不比其他任何Git存储库“特殊”或“重要”。

在笔记本电脑A上git clone ssh://main-PC/...时,您在笔记本电脑A上运行的Git会创建一个Git存储库,该存储库是main-PC上Git的 peer 。您只将PC主版本认为是“ more master-y”,因为这是您使用的方式,实际上,在旅行时,笔记本电脑版本是“ more master-y”,因为它得到了新的提交。

您的笔记本电脑-存储库使用名称origin来记住URL ssh://main-PC/...。名称origin远程。您的笔记本电脑A Git使用origin/*形式的远程跟踪名称来记住其他Git中的分支名称。

在便携式计算机B上,您可以克隆便携式计算机A克隆或主PC克隆。您的笔记本电脑B会记住您在名称origin下在此处使用的任何URL,并使用远程跟踪名称origin/*记住在克隆过程中复制的分支名称。

您可以为任意一台笔记本电脑添加更多的远程名称。例如,假设笔记本电脑A和B都运行git clone ssh://main-PC/...,因此在两者上,origin都表示ssh://main-PC/...,您可能想在笔记本电脑A上执行此操作:

git remote add laptop-b ssh://ip.address/path/to/repo.git
例如

(当然,IP地址可能会随着时间而改变,因此有时您需要删除并重新添加,或者使用git remote set-url进行修复)。现在,笔记本电脑A为笔记本电脑B提供了 name ,您可以从A到B git fetchgit push来获取(获取)或发送(推送)任何提交在B上但不在A(获取)上,或者在A上却不在B(推动)上。同样,在笔记本电脑B上:

git remote add laptop-a ssh://ip.address/path/to/repo.git

将在笔记本电脑B上创建远程名称laptop-a,现在您可以使用该名称git fetchgit push

一台笔记本电脑上的提交现在可以轻松转移到另一台笔记本电脑上。请注意,例如,笔记本电脑A上的远程跟踪名称 laptop-b/master是一台笔记本电脑会记住另一台笔记本电脑有提交内容的方式-因此,您现在想要拥有便携式计算机位于“后面”,更新其本地分支名称以记住新的提交。

关键概念是所有三个存储库都是对等的。除您个人认为某人具有特殊身份外,没有人具有特殊身份。您可以基于提交哈希ID进行决策,而不必像静态决策那样进行决策,该提交哈希ID是在origin/masterlaptop-a/masterlaptop-b/master等远程跟踪名称下记录的。

每个对等存储库中的分支名称不同。 提交哈希ID 是相同的,只要它们都具有相同的提交即可。当一个存储库中缺少某些提交时,git fetch会将它们从需要提交的存储库中拉入(到需要提交的存储库中),和/或git push将它们(从具有提交的存储库,到需要提交的存储库。

这两个操作(取和推)几乎是对称的,除了另一个关键区别。 fetch 操作采用源存储库的分支名称,并对其进行重命名,以便它们以origin/master之类的远程跟踪名称进入。 push 操作发送提交,然后:

  • 询问推送的目标,请设置其某些分支名称(这是礼貌的非强制推送),或者
  • 命令推送目标设置其分支名称之一(强制推送)。

由于推送的目标是设置其分支名称,因此存在一些特殊条件:

  1. 不得将分支检出到工作树中。如果存储库是用--bare制成的存储库,则此方法很好用,因为它从未将任何分支检出到工作树中。
  2. 或者,可以将分支检出到工作树中,但是随后必须告知接受推送的Git允许此类推送操作(并且必须满足其他条件)。例如,参见Git receive.denyCurrentBranch updateInstead fails [编辑:或更好的链接What is this Git warning message when pushing changes to a remote repository?

由于这些原因,使用全取工作流程有时会更好。但是您必须使用第二个Git命令将新提交 combine 组合到本地存储库中。很多人喜欢使用git pull命令,因为它实际上首先运行git fetch,然后运行第二个Git命令来合并获取的提交。