Git分支是否可能与主分支存在于同一服务器上?

问题描述 投票:0回答:2

我还在学习Git,我知道分支是主存储库的副本,它允许您在不损害主存储库上的内容的情况下进行更改,同时还允许多个人在自己的分支上进行更改。

但是,假设您有一台服务器托管Web应用程序,并在服务器上的另一个目录中提供相同代码的副本以进行测试。是否可以将主存储库连接到实时应用程序,并将测试代码连接到可以通过拉取请求合并到主服务器的特定分支?

在传入的可行性对话中 - 为了在从开发分支创建并合并时部署新的更改,我们将使用Jenkins作业进行部署。

git github
2个回答
2
投票

我为此长度道歉,但你开始时有些误解。 TL; DR是你确实能得到你想要的东西,但你还不太清楚自己想要什么。

我还在学习Git,我知道分支是主存储库的副本,它允许您在不损害主存储库上的内容的情况下进行更改,同时还允许多个人在自己的分支上进行更改。

不幸的是,这种理解并不正确。一般来说,理解Git或分布式版本控制并不容易 - 但首先必须抛弃的是存在一个主存储库的概念! (我们经常在以后重新介绍它,但它有助于从抛出它开始。:-))

使用集中式版本控制系统(CVCS,例如Subversion或ClearCase),确实存在“真正的主人”。无论出于何种原因(通常是速度),可能会有额外的“真正的主人”副本,但是很容易判断你是否正在处理真实的真相来源 - 使用sherriff的明星或总统帽子的存储库,或者无论它是什么区分了真相来源库和其他每一个。 CVCS有一个中央服务器;你把存储库放在那里;并且你已经完成了(除了备份和灾难恢复问题)。

使用真正的分布式(DCVS中的“D”)版本控制,所有存储库都是相同的。嗯,他们是平等的,除非你故意或不小心将一个人视为穿着谢尔夫的明星。也就是说,您可以使用DVCS之类的DVCS,将其中一个服务器指定为“服务器”,但这是您的行为,而不是系统的属性。这改变了很多关于系统内部的内容。

(我注意到你也在询问GitHub。一般来说,当人们使用GitHub时,他们倾向于将GitHub上的副本视为“服务器 - 真相的来源。但是GitHub存储库有它的分支,它们是与你的分支不一样。而且,没有必要声称它们是真理的来源:你可以将它们视为另一个副本。再次,任何存储库的“主人”都是你决定的。所有Git存储库除了你如何选择使用它们之外,它们同样精通!)

在Git中,您通常会克隆存储库,以便拥有所有内容的完整副本。您的存储库就是您的存储库 - 这样您就可以执行任何您想要的操作。无论你做什么都不会影响任何其他克隆。此时您自动拥有自己的分支。在Git中,您没有原始存储库的分支作为分支,但您确实拥有其他形式的所有分支。实际上,你开始时没有自己的分支,但通常会立即生成第一个:git clone的正常最后一步包括创建一(1)个分支名称。这是你的(单个)分支。通常,它是master(虽然你可以控制它)。通常,您将继续创建第二个分支名称,这是您将要进行的分支名称。 (一旦你这样做,你可以自由删除你的master分支,这样你就不需要拖动它来更新它。这取决于你。)

这导致了整个术语问题。 Git是疯狂的混乱。有关此问题的更多信息,请参阅What exactly do we mean by "branch"?。我已经开始使用短语分支名称来引用像mastertesting这样的名称,并使用远程跟踪名称来引用像origin/master这样的名称。当你git clone一个存储库时,你将他们所有的分支名称 - “他们”作为你正在克隆的另一个Git存储库 - 变成远程跟踪名称:他们的master现在是你的origin/master;他们的develop现在是你的origin/develop;等等。

在处理Git时,你还必须在头脑中保留一堆看似矛盾的想法:

  • 提交是快照:永久(大部分),不腐败(完全),不变。它们由哈希ID唯一标识。这些哈希ID很大,很丑陋,对人类来说难以理解,但它们在Git中很重要。
  • 提交是历史。提交相互链接以形成(有向,非循环)图形。进行新提交是一个创建快照的过程,添加元数据,例如谁提交了提交和原因,并将新提交链接回其父提交。作为进行新提交的最后一步......好吧,让我们等待另一个要点。
  • 虽然提交包含文件,但提交不是文件。没有文件历史记录,只有提交历史记录。但Git可以向您显示文件历史记录。它通过使用提交历史记录动态实现它。要查看提交中的更改,Git将简单地将父级快照与子级快照进行比较。不管是什么,都不会改变。无论有什么不同,那就是改变了。
  • 总有一个当前的提交(称为HEAD)。
  • HEAD通常“附加”到分支名称。因此,HEAD只识别名称,而不是提交。 (有一个“分离的HEAD”模式,其中HEAD直接识别提交本身,但它主要用于浏览历史记录和特殊情况工作 - 通常你想要“在一个分支上”,你可以通过附加你的HEAD。 )
  • 每个分支名称(以及其他名称,如标记)标识一个且仅一个提交。 Git称之为该分支的提示。
  • 但是提交已经或者可能更好地描述为“包含在” - 分支中。
  • 在Git中,一些提交同时在许多分支上。包含提交的分支集合通过从分支名称开始并在历史记录中向后工作来确定。具有两个或更多父项的合并提交往往导致提交在多个分支上。根提交(通常只有一个)通常在所有分支上。
  • 进行新提交会创建新提交,并将当前提交作为其父提交。这也会创建新提交的真实名称:它的哈希ID,它是提交内容的密码校验和。根据定义,这个新ID与每个现有ID不同,几乎无法预测,但也完全可预测,因为它只是提交内容的哈希。 (内容包括一个时间戳,因此,由于时间总是在增加,我们不确切地知道何时提交,直到它被提出,这是使得难以预测的部分。)然后,以便新的提交是在当前分支上,Git所做的是将新的哈希ID写入当前分支名称。新提交现在是提示提交,这就是分支增长的方式。

这都是关于提交的。提交内容 - 以快照文件形式存储的数据(间接存储和压缩存储) - 存储库内部。我们还需要有一个区域,其中某些文件以正常形式可用。在几乎所有版本控制系统(集中式或分布式)中,这称为工作树或工作树或此主题的一些变体。使用集中式VCS,工作树可能就是您所拥有的一切。但是,在像Git这样的DVCS中,您通常会在本地拥有整个VCS数据库以及工作树。在Git中,还有另一个关键数据结构,Git强迫您了解,称为索引。 (它实际上有三个名称,以反映其三个不同的方面或角色。用户友好的名称是临时区域,因为您在制作快照之前使用它来暂存文件的内容。第三个名称是缓存。)

但这与所有背景相关,重要,但背景 - 你真正的问题:

但是,假设您有一台服务器托管Web应用程序,并在服务器上的另一个目录中提供相同代码的副本以进行测试。是否可以将主存储库连接到实时应用程序,并将测试代码连接到可以通过拉取请求合并到主服务器的特定分支?

在这里,因为Git是分布式的,所以您可以选择许多不同的方法来执行此操作。

要充当Web应用程序或Web服务器,您将需要以正常的日常形式存储文件,而不是高度压缩的全历史记录Git-ized表单。所以你需要一个工作树 - 或者至少看起来像一个工作树 - 而不是存储库或者除了存储库之外。如果这台机器上有某个存储库,你可以在这里没有存储库的情况下离开。

对于第二个测试变体,您还需要第二个工作树。第二个工作树可以与一个完全独立的第二个存储库相关联 - 由于Git是分布式的,因此第二个存储库可以独立于第一个存储库存在(如果存在第一个存储库)。

如果您有两个单独的存储库,则它们具有各自的分支名称。没有要求这些以任何方式协调。但是,为了理智,您可能希望第一个存储库和工作树对在其自己的master上运行。每个存储库都可以并且通常会有自己的master,但是只要你保持它们同步,它们的masters就会匹配,这很容易记住。 (哈希ID是不可能记住的!)

如果您只有一个存储库,则情况会有所不同。 Git存储库通常带有一个(计数,1)工作树和相关索引。你需要两个,或者至少两个看起来像工作树的东西。因此,两个存储库是一种简单的方法。

但是从Git 2.5版本开始,Git已经内置了额外的工作树。你通过git worktree命令获得这些。每个存储库都以一个基本工作树(和索引)开始。使用git worktree add <arguments>将指导您的Git创建一个新的附加工作树(它带有自己的索引)。但是,每个添加的工作树都带有约束:它必须位于与其他所有工作树和主要原始工作树不同的分支上。分支都是存储库本身的属性,而工作树是独立的 - 并且通过强制它们在不同的分支上,Git确保它们保持独立。

但这正是你想要的。所以你可以使用这个方法,前提是你的Git至少是2.5版本。如果没有,你可以使用两个单独的存储库,它们将有两个独立的工作树,当然还有单独的分支 - masterteststaging或者一个存储库中的任何东西都不需要与masterteststaging相关或者其他存储库中的任何内容,因为分支名称属于存储库。如果您有两个存储库,则有两组独立的分支名称。如果您只有一个存储库,则只有一组分支名称。

(即使你有一个旧版本的Git,你仍然可以使用这个“一个存储库,两个签出”的方法,只要你没有意图在至少一个分支中实际工作。这种方法更复杂,我赢了因为这个答案已经太长了,所以请进入这里。)

请注意,无论您走哪条路,您在GitHub上保留的存储库(假设您选择保留一个存储库)仍然是另一个单独的Git存储库。它有自己的分支,独立于任何其他Git存储库。这是事情变得特别棘手的地方。

在某些时候,一旦您进行了新的提交,您将希望将这些新提交发送到其他存储库。请注意,执行此操作时,会有一个发送存储库和一个接收存储库。它们各自独立,除了它们将彼此共享提交(通过这些哈希ID),并且......好吧,暂时坚持这个想法。

要发送提交,您将使用git push:您的Git调用另一个Git并发送提交。要接收提交,你将使用git fetch:你的Git调用另一个Git并接收提交。这两个命令将您运行它们时的Git连接到另一个Git存储库,并在两个存储库之间传输提交。这部分非常简单,除了哈希ID对人类来说难以理解的事实。

但是,在发送或收到提交后,你的Git和其他Git现在需要做最后一招:

  • 如果您正在接收提交(git fetch),则根据其分支提示ID获取提交。你的Git也知道他们的Git用来保存那个ID的分支名称 - 以容纳难以理解的东西。您的Git将通过将其分支(例如master)重命名为远程跟踪名称origin/master来保存该ID。这与您进行初始克隆时发生的情况相同。 请注意,此处的存储库没有任何反应。您只需将新提交添加到存储库,然后在您自己的控制下执行此操作,并通过远程跟踪名称调用其分支。所以这对你自己的分支根本没有影响。
  • 如果你正在发送提交(git push),你必须要求另一个Git设置他们的一个分支名称,以便将你已经发送的(或者你已经拥有的)提交到他们的一个分支提示中。与fetch如何不接触您的分支相反,这确实会影响他们的分支。你真的在改变他们的分支 - 要求他们改变哪个提交是他们的分支名称的提示 - 当你git push。 因此,他们可以选择接受此请求或拒绝此请求。通常,如果您只是向其分支添加新提交,它们将接受此请求,而不是如果您的请求将从其分支中删除提交。如果他们不接受礼貌请求,您可以发送更有力的命令,但他们也不必遵守该命令。 他们接受的请求或命令以及拒绝的内容都基于您可以设置的控件。像GitHub这样的Web服务为此提供了精美的Web界面。如果您不使用花哨的服务,则必须编写自己的访问控制。

git fetch之后,它只添加了他们的提交并更新了你的远程跟踪名称,你通常需要做一些事情 - 通常是git mergegit rebase-将他们的提交纳入你的分支。 Git带有一个方便的命令git pull,结合了git fetch和第二步。当你开始时避免使用git pull!在你理解git fetch之前,第二个命令-git mergegit rebase似乎在做不可能的事情。同时,git pull便利命令使用的语法与Git的其余部分不相符。如果你打破它的两个单独的命令,一切都更好。起初它仍然会令人困惑,但至少它(大部分)是一致的。

如果您打算使用GitHub的“拉取请求”机制,您可能需要使用GitHub调用的分支来设置更多的存储库副本。 Forks本质上是克隆,但直接在GitHub服务器上创建,具有隐藏的链接,以便GitHub可以记住哪些Git存储库是其他Git存储库的分支(我猜,在幕后秘密共享磁盘空间和内部Git对象) 。这些是更多的存储库,所有这些存储库都可以彼此不同步,并且所有存储库都可以通过git fetchgit push操作重新同步。


0
投票

是。您只需要在服务器上有两个本地存储库(并且希望其他地方存储服务器爆炸)。假设我有目录结构

           /----------live-app
          /
--home---/------------testing

“live-app”和“testing”都是独立的git目录。他们每个人都有自己的.git文件。你可以在'live-app'里面做checkout master,把它放在那里,然后定期拉。你会在测试中的其他任何分支上工作。当您准备好将测试分支合并到master中时,您只需要处理“live-app”之外的所有内容。

只需让'live-app'留在主人身上。詹金斯唯一应该做的就是git pull

© www.soinside.com 2019 - 2024. All rights reserved.