我只是对使用git
有一个愚蠢的问题。
说,我在current_branch
上,并且正在长时间运行program A
,这将连续生成一些日志文件并保存到我的current_branch
中。
此运行大约需要5个小时。 在运行期间,我可以切换到另一个分支(我们称为new_branch
)并做我的工作吗?
我的问题是,如果我在运行中间切换到program A
,在current_branch
上运行的new_branch
生成的文件会怎样?
答案 0 :(得分:2)
我的问题是,如果我在运行中间切换到new_branch,那么在current_branch上运行的程序A生成的文件会如何处理?
这里没有魔术。如果切换到新分支,则工作目录中更改的文件将更改,并且程序将与这些新文件一起继续。 Git将忽略所有被忽略的文件,例如临时文件,日志文件等。接下来会发生什么情况取决于您的程序和操作系统。
您的程序已经加载的任何代码都将保持加载状态。对于许多程序而言,这已足够,但是某些系统会根据需要动态加载文件,并且可能不会全部加载。其他人可能会检测到基础文件已更改,然后重新加载其代码。再说一次,没有魔术。如果您的程序在切换分支后打开了一个已签入的文件,它将获取该文件的新版本。
在Unix操作系统上,如果文件被移动或删除,则任何打开的文件句柄将保持打开状态。这意味着,例如,如果您的程序对日志文件具有打开的文件句柄,并且该日志文件被删除或移动,它将继续写入该文件。这是一种保护临时文件,创建临时文件,将其打开以进行读取和写入,删除文件(实际上只是指向实际数据的指针)并保持文件句柄打开的技术。一旦程序退出并且所有文件句柄关闭,数据将被清除。但是,不太可能将日志文件检入Git。
Windows可以具有强制性的文件锁定功能。这意味着,如果您有打开文件的文件句柄并尝试移动或删除它,则将不允许这样做。因此,如果您使用的是Windows,则意味着您可能无法签出新分支。
最简单,最安全的方法就是不要冒险。在长时间运行的过程中,在新目录中进行新克隆以进行开发。如果很大,您可以克隆现有的存储库,而不必通过网络进行存储。以与您完全相同的方式工作。漫长的过程完成后,您可以将此临时仓库设置为远程仓库并从中撤消其更改,或者可以方便地删除旧仓库并移动新仓库。 Git存储库只是目录,可以自由移动。
将来,请勿在开发结帐时运行真实的代码。而是制作一个新的克隆,并在其中进行长时间运行的过程。无论是在另一个目录中还是专用的工作服务器中,都是由您决定的。
答案 1 :(得分:1)
要了解将发生的情况,请考虑Git的模型以及Git使用计算机文件系统的方式。然后考虑正在运行的程序如何使用计算机的文件系统。一些细节取决于您的操作系统。
首先,让我们看一下Git的模型。在Git存储库中:
我们找到存储库的数据库(DB)。 Git将它们存储在名为.git
的目录中。有多个数据库(以数据库术语来说,主要是键值存储区),但是主要的数据库存储Git的 objects (提交)以及与之协同工作所需的所有支持项目-第二重要的是存储名称。
第二个数据库将名称(例如,分支名称,例如master
转换为Git哈希ID,这些ID是那些丑陋的40个字符的字符串,例如e3331758f12da22f4103eec7efe1b5304a9be5e9
。哈希ID本身是第一个存储区中的密钥:每个密钥使Git能够找到相应的对象。如果该对象是一个提交(例如,它是Git在Git存储库中的提交),则该哈希ID附带的值最终使Git能够查找该提交中快照的所有文件。
已提交的文件被冻结:它们永远无法更改。从现在开始直到永远都可以访问它们,至少只要提交本身保留在主存储库数据库中即可。它们以特殊的压缩格式(通常是高度压缩的格式)存储,如果同一文件出现多次,则该文件的数据只有一个副本。这是可能的,因为它们是只读的!您不能更改已存储的文件(就此而言,也不能更改任何现有的提交)。由于采用这种特殊的仅Git格式,大多数程序根本无法处理这些文件。
接下来,我们有个东西叫Git分别称为 index ,临时区域或缓存。这个东西-基本上只是一个文件.git/index
-内部有点复杂,但是它的基本工作是跟踪(即“索引”)您的工作树。它间接包含当前活动的每个文件的副本。更准确地说,它包含每个跟踪的文件。实际上,这就是跟踪文件的定义:它是索引中的文件。
索引中存储的文件也采用特殊的仅Git格式。但是,与提交的文件不同,它们是不是只读的:您可以随时替换索引副本。这是git add
的作用:它用工作树版本覆盖索引副本。因此,索引始终包含您打算在 next 提交中放入的内容。
运行git commit
时,Git只是将索引文件打包(并冻结)到新的提交中。这就是为什么Git比大多数相关版本控制系统快得多的原因:索引已经非常接近完成的提交。 Git不必花费大量时间重新打包所有工作树文件:它们已经以正确的形式出现在索引中。
最后,我们有一个工作树。在这里,您可以使用计算机的普通格式存储文件。这使您可以与他们一起工作。
Git实际上不需要完成工作的工作树。不是Git,而是需要工作树的是 human (以及不读取Git专用格式文件的各种计算机程序)。
Git允许您(人和/或计算机)将不需要提交的其他文件保留在工作树中。您只需不将这些文件复制到索引中即可。如果它们不在索引中,则它们将被未跟踪,并且不会在您进行的下一次提交中-它们现在不在建议的提交中,因此它们将不在实际提交中除非您先将文件复制到索引中,否则稍后再提交。
git checkout
很容易解释要执行git checkout
,Git需要:
查看当前工作树中的内容。它可以通过扫描索引来快速执行此操作,该索引可以跟踪工作树中的内容(未跟踪的文件除外)。如果尚未使用git add
修改索引,则该索引与当前签出的提交匹配。如果您已经修改了索引,那么Git可以很容易地告诉您您已经拥有索引,因为Git就是在维护索引。
根据您要检出的提交,查看您想要在工作树中包含的内容。许多文件在 current 提交中可能与建议的签出完全相同。 (此时,Git必须小心,因为您可能已经在运行git add
的情况下更改了工作树内容 。)
对于任何不同的文件,新文件或已删除的文件,Git现在必须从要切换到的提交中提取适当的文件,并从工作中替换(或添加或删除)该文件,树。 Git首先可以检查以确保它不会破坏您正在处理的任何内容。 Git 不必检查当前提交和提议的新提交中相同的任何文件。
如果应该继续进行检出,那么Git现在将所需的提交(或至少任何其他文件)复制到索引中,以便索引与提交匹配,并复制到工作树中,以便工作树也匹配提交。现在,所需的提交就是当前的提交,并且如果您要进行更改和提交,则可以更改/更新索引和工作树。
.git
并仅查看工作树除非您使用的是一个能充分理解Git内部工作原理的程序(随着时间的推移,这不是一个好主意),否则程序本身应该只与工作树文件一起工作。这些都是由操作系统以通常的方式进行管理的。
如果您在运行某些程序的同时运行git checkout
,则git checkout
将(尝试)修改工作树,就像我们上面提到的那样。如果这样行得通,那么对Git来说就没问题了:这取决于这个运行时间长的程序来处理更改。您需要咨询该程序以查看其功能。如果修改工作树失败,则签出也会失败,这对于Git来说通常是可以的,这只会使您保持原始提交。
但是这里有一些潜在的极端情况:也许Git已经预先检查了所有内容并认为它将成功,进入结帐的途中,出现了一些步骤失败,并尝试退出所有内容(以恢复原始提交)但是退出也会失败。在这种情况下,索引和工作树可能会变得不同步。这对Git来说不是致命的,但是对您来说,这事后很痛苦,因为您的工作树是neither fish nor fowl。
在大多数情况下,仅使用新鲜的工作树通常更明智(如Schwern answered)。