如何删除一个文件夹,但将所有子文件夹和文件保留在一个git分支中?

贪婪的

我正在设置一个git分支,该分支需要与其余的目录结构不同。这些文件都是相同的,但是,它们实际上必须全部上移一个级别。有很多文件,我不知道如何使用git将它们一起移动。

当前,它看起来像这样:

Root Directory
    |
    - Main Folder
    |    |
    |     - Sub Folder 1 with a lot of subfolders and files
    |    |
    |     - Sub Folder 2 with a lot of other subfodlers and files
    |
    - A couple of random files

我最终想要得到的是:

Root Directory
    |
    - Sub Folder 1 with a lot of subfolders and files
    |
    - Sub Folder 2 with a lot of other subfodlers and files
    |
    - A couple of random files

但是,此更改应仅在一个分支中。

我该怎么做?

星期二

开始之前,这里有一些有用的背景知识:

  • Git仅存储文件,不存储文件夹。
  • 每个提交的Git存储完整快照所有文件,或者说的,所有的承诺文件。这就是Git所谓的未跟踪文件进入的地方。
  • 快照由存储Git所调用文件的文件制成,这些文件分别是您的索引暂存区(它还有一个旧名称,现在应该将其用于其他名称,但是有时某些内容将引用缓存。这三个名称都是关于同一事物的。)

Git将这些文件存储在commit中Git实际上就是关于提交的。每个提交都进行了编号-但不是以一种很好的简单顺序“提交#1,提交#2,...”的方式进行编号。相反,每个提交都具有唯一的哈希ID,哈希ID看起来完全是随机的,并且与先前的提交无关。这些哈希ID是像83232e38648b51abbcbdb56c94632b6906cc85a6这样的大型丑陋字母和数字字符串git log

由于每个文件都在每个提交中,因此Git以不会立即用完整个磁盘驱动器的方式保存它们非常重要。因此,已保存的文件被压缩,并且进一步在不同的提交之间共享Git之所以能够做到这一点,是因为它使用一种特殊的,仅Git的冻干格式来存储文件。此格式的文件无法更改,但可以共享。这意味着不能更改任何现有的提交存储库中的每个提交都或多或少被永久存档。1认为提交是永久性的(大多数是固定的)并且不可更改。它们历史记录,存储在存储库中。


1可以删除提交,但是有点困难,而且Git通常也不会立即删除它-因此,即使您认为提交已消失并且无法立即找到它,它也可能仍然存在。


完成工作

现在,这对于归档来说一切都很好,但是这些只读的冻干文件对于实际完成任何实际工作完全没有用为此,Git提供了Git所谓的工作树那就是您工作的地方。

Git从工作中提取冻结干燥的文件到工作树中,为文件重新补水,使其具有正常的日常形式。现在,您可以查看和使用这些文件。您只需选择一个提交(通常是某个分支最后一个提交),然后说:让我得到那个commit,然后Git完成。它找到冻结的提交并枚举其中的所有文件:

  • main-folder/sub1/file1啊哈,吉特说,这个工作树没有main-folder,让我们做一个。而且它sub1main-folder我刚刚创建的文档中也没有,我们也要创建它。现在,我可以创建新文件了main-folder/sub1/file1
  • main-folder/sub1/file2,Git说,已经有一个主文件夹/ sub1,我可以在其中创建新文件file2

根据需要重复此过程:Git具有提交中列出的文件,必须重新构造。完成此操作后,如果启动时工作树空,那么现在它具有该提交中每个文件的重新水化版本。没有存储任何文件夹,但是没有必要存储它们。

如果现在从提交切换到其他提交,则Git将删除它仅为该提交创建的所有文件,并用其他不同提交的文件替换它们。如果从中删除所有文件main-folder/sub1,则还将删除目录main-folder/sub1如果最后删除了中的所有内容main-folder,它也将其删除。然后,它开始从您现在想要的提交中提取所有文件,并根据需要创建任何目录/文件夹。

实际上,Git交错了所有这些工作,创建,删除和优化:如果您从commit切换a123456...到commit b789abc...,并且两次提交中文件中有99%是相同的,那么,就不需要对其进行处理了。毕竟工作树在吗?并且,对于git checkoutGit的这种特殊形式,Git在切换提交之前添加了安全检查:对于必须删除或替换的每个文件,工作树中的文件是否“干净”?如果文件“干净”,则可以安全地删除或替换它。如果它是“脏”的(如果自从Git提取它以来就对其进行了更改,并且您可能希望保留所做的更改以免切换会变得笨拙),则Git会就此警告您,并且默认情况下,拒绝切换提交。

索引/暂存区

在此过程中有一个巨大的鸣叫皱纹。通读以上内容,您可能会想到:好的,我们已经提交了冻干文件,而工作树中包含了普通文件。但是Git这两者之间放置了第三个实体这是索引/暂存区域。

就像提交本身一样,索引大部分是不可见的。.git/index在大多数情况下,它实际上只是一个普通文件-最终会变得更加复杂,但它最初只是一个普通文件。从本质上说,文件中的内容是您提取的提交的副本–所有冻干的文件,仅使用哈希ID(例如提交哈希ID)来标识它们。不像在提交实际冻结的文件,不过,这是该指数副本可以被改变。2

这是做什么的git add:它将文件冷冻干燥,并将版本粘贴在索引中。如果文件以前不在索引中,那么现在就可以了。如果以前在索引中,则将踢出先前的版本。无论哪种情况,都可以提交新的冻干文件。运行时git commit,Git只是将索引中所有准备就绪的文件打包到新提交中。这就是为什么 git commit这么快原因:它实际上只剩很少的工作要做。

索引中的文件根本不存储在文件夹中。只有一个巨大的清单:文件path/to/file1包含这些冻干的内容,文件path/to/file2包含这些其他冻干的内容,依此类推。但这种或那种方式,该文件存在索引,随着冻干即食提交内容是什么使在工作树的水化文件跟踪一个跟踪文件是一个是在索引中,这样一个未经跟踪的文件就是在工作树中的任何文件,而不是在索引中。由于git commit存档的是索引中的内容,而不是工作树中的内容,因此只能进行跟踪 文件被提交。


2这里最棘手的部分是,将一个新文件实际放入索引中进行冷冻干燥,然后将其存储在存储库中;如果确实是新内容,则创建一个新的哈希ID;如果冻结,则共享一些现有的哈希ID,干燥的内容与任何现有文件匹配。现在,假定是新文件已被简化为哈希ID,它就可以与旧文件占用的索引位于同一插槽中!


有了这种方式,答案现在很容易

要进行新的提交,即在该提交中存储某些文件,只需进行设置,以使索引中仅包含那些文件。为此,请从索引中删除所有完全不需要的文件,这也将删除工作树副本:

git rm ...

由于索引通过它们相对于工作树顶部的路径来存储它们,因此您需要将所有要保留的文件保存在某个位置。最简单的方法是在工作树索引中重命名它们

git mv main-folder/sub1 sub1

sub1如果需要的话,它将在您的工作树中创建(在这种情况下,通过重命名)文件夹,然后从它们的目录等中重命名索引中的所有跟踪文件(记住git mv必须与索引以及工作树一起使用)main-folder/sub1/file1具有sub1/file1etc路径的路径。git mv命令与git rm命令一样,然后将其与工作树文件一起拖动。

(方便地或有时不是有时,当git mv就地重命名文件夹时,它还会重命名其中的所有未跟踪文件。由于Git的其余部分对未跟踪文件并不真正感兴趣,因此以后git checkout不会将它们移回!)

因为在所有内容的下方,Git都使用冻结的文件的哈希ID按内容存储文件,因此所有重命名都是免费的。Git需要一点空间来存储更新后的名称-承诺必须将全名和哈希ID一起存储,并且名称在这里不容易共享,因为它们不同3-但是实际内容与在其他提交中具有不同名称的文件。

请注意,当您在具有这些sub1/file1类型名称的提交之间来回切换至具有类型名称的任何提交时main-folder/sub1/file1,Git可能必须在工作树上进行大量修改,首先删除所有sub1/file1名称,然后创建新的空名称main-foldermain-folder/sub1目录,以保存以前位于其中的(最后是相同的!)文件,sub1/file1依此类推。如果Git足够聪明地意识到它可以重命名工作树中的那些文件,那么Git可以做到这一点,但是Git通常用的简单而愚蠢的方式就是删除并重新创建。他们。这将显示在操作系统级别的文件时间戳中:如果Git删除了一个文件并重新创建它,则它将作为磁盘上的工作树文件时间戳获得“ now”。


3内部提交(但不在索引中)Git可以追溯到树结构的命名方案。因此,如果sub1在这个新的顶层承诺是100%相同的sub1,这是在main-folder/sub1其他一些承诺,Git会真正共享底层为对象sub1的新的提交根树子树。根树当然会有所不同,因为它将被命名sub1为其子树之一,而不是被命名main-folder为其子树之一。但是所有这些仅是实现细节:没有一个显示在索引和工作树中。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

JGit:我想在一个特定的分支中的所有文件和文件夹

如何删除Android上一个文件夹中的所有文件和文件夹

如何将一个文件夹及其所有子文件夹和文件复制到另一个文件夹

git忽略除一个扩展名和文件夹结构以外的所有文件

我如何git添加一个文件夹,但没有文件夹的内容?

如何将文件从文件夹和子文件夹复制到R中的另一个文件夹?

批处理文件:复制除一个文件夹外的所有文件和文件夹

Java / IntelliJ将类保留在另一个文件夹中,但在同一包中

文件夹中除一个命名文件夹外的所有文件夹的glob

如何用一些简短的方法将所有文件和文件夹从一个文件夹移到php中S3存储桶的另一个文件夹?

Bash脚本将文件夹及其子文件夹中的所有png文件移动到另一个目录?

如何将一个文件夹中的所有文件复制到另一个文件夹并更改扩展名?

如何删除所有文件/文件夹,但将根文件夹保留在C#中

如何将一个文件复制到所有子文件夹

如何仅在一个分支文件夹或子文件夹中显示分支?

如何将所有同级文件夹移动到一个文件夹中?

如何将分散在文件系统中的所有同名文件移动到一个文件夹中?

从一个文件夹中复制所有文件和文件夹

如何使用git subtree将子文件夹的多个分支迁移到另一个仓库

将所有文件夹和子文件夹中的每个文件压缩为一个单独的zip文件

如何将GIT中的2个分支合并到一个带有2个文件夹的分支中

创建一个新链接以访问所有文件和文件夹

删除给定文件夹中的文件,但将文件保留在子文件夹中

如何删除当前目录中的所有文件,但将文件保留在子文件夹中

将除一个子文件夹外的所有子文件夹移动到该子文件夹中

如何将子文件夹和文件的创建限制在一个位置?

递归删除除一个子文件夹之外的所有子文件夹

在给定文件夹的所有子文件夹中递归创建一个php文件

删除给定文件夹中的文件,但将文件保留在子文件夹中