【问题标题】:Where should .gitignore be placed in a React-Native expo app?.gitignore 应该放在 React-Native expo 应用程序的什么位置?
【发布时间】:2021-08-30 22:41:36
【问题描述】:

enter code here目录如下:

> Repo
    LICENSE
    README.md
    .gitignore
    > App
        'contents of application all in here'
        .gitignore

我们的 .gitignore 文件来自这里 https://github.com/expo/expo/blob/master/.gitignore

虽然不确定将 .gitignore 文件放在哪里,因为在我使用过的所有项目中,它们都直接位于 repo 文件夹中,但是 .gitignore 不需要在所有项目的前面放置 App/_____列出的文件?

谢谢

【问题讨论】:

  • 不是一个真正的博览会问题,而是一个 git 问题。将它放在您想要版本化的整个文件夹空间的根目录中。 Gitignore 并不总是需要路径前缀来匹配文件和文件夹。

标签: git react-native github expo


【解决方案1】:

TL;DR

没有唯一的正确答案。将条目放在最适合的地方。

无论应用程序如何,.gitignore 的规则都是一致的(尽管相当复杂)。您将需要了解排除文件中每个条目的语法和语义,但首先,在您了解这一点之前,您必须了解在 Git 中要跟踪文件的含义 vs untracked,因为排除条目适用于 untracked 文件。

跟踪的文件是 Git 索引中的文件

跟踪文件的定义很简单,但是很微妙。跟踪文件是当前在 Git 的索引中的任何文件。这里的微妙之处在于理解 Git 的索引。这是什么?什么是“指数”?为什么 Git 有 三个 的名字,称它为索引,或者——现在越来越常见——暂存区,或者——越来越少见——缓存?

索引:背景

索引,或暂存区,是 Git 对你隐藏了一段时间的 Git 的一部分——没有简单的方法看到它,不是直接的——但是,然后,将 Git 拟人化,1 Git 随机跳出来用它的索引打你一巴掌,就好像你在this Monty Python sketch 里一样。所以你需要了解它。

索引本身非常很复杂,但使用它的方式非常简单:在其中暂存文件。这就是为什么它现在被更一致地称为暂存区。但这仍然留下了一个明显的问题:暂存文件意味着什么?要回答那个,我们需要考虑一下 Git 提交是。


1不要将计算机拟人化。他们讨厌那样。


提交

一个 Git 提交是:

  • 编号:每个提交都有一个唯一的hash ID,一个看起来很丑的随机数字,几乎总是表示为hexadecimal 数字。这个哈希 ID 实际上是提交的完整内容的加密校验和2,这意味着提交内容字面上不能改变:如果你取出一个提交,进行一些更改,然后将结果放回原处,您将得到一个带有新的唯一哈希 ID 的 new 提交;旧的提交仍然存在,带有旧的哈希 ID。

  • 存储:

    • 每次提交都会以特殊、只读、仅 Git 的格式、压缩和重复数据删除存储您所有源文件的完整快照

    • 每个提交还存储一些元数据,或有关提交本身的信息。这包括制作者和制作时间等内容。

基于散列的编号系统具有已知的加密散列函数,这意味着宇宙中的每个 Git 都同意任何特定提交获得的散列 ID。这就是 Git 如何成为一个 分布式 版本控制系统的方式。两个不同的 Git 存储库可以通过检查哈希 ID 来判断另一个是否具有相同的提交。这不是我们在这里关心的,但它是为什么提交是它们的方式,所以了解它很有用。


2密码学部分让人想起加密货币的区块链,尽管 Git 今天使用的密码学功能太弱了。 Git 仅将其部分用于其Merkle tree 属性;哈希具有良好熵这一事实是最重要的方面。


工作树

在任何情况下,提交中的文件实际上不能被 Git 使用,这意味着要处理 / 提交,我们必须有 Git extract em> 提交。我们让 Git 将此提交提取到我们的工作树

工作树保存从某个提交中提取的文件。如果我们切换到不同的提交,Git 将删除这些文件,并从一些其他提交中提取文件。

好吧,好吧,那又怎样?好吧,假设我们的系统——不管它是什么——需要“编译”或以其他方式处理文件。我们使用常规 JavaScript 或 Typescript 并将这些文件转换为缩小文件,或者使用 Python 代码并将其字节编译为 *.pyc*.pyo 文件,或者使用 C 或 C++ 代码并将其编译为 @987654331 @object 文件,或者其他什么。

这些构建工件 进入工作树。但他们不应该进入新的提交。有很多方法可以处理这个问题,但 Git 选择了一种奇怪的方法。

索引,第 2 部分:它作为暂存区的作用

Git 处理关于哪些文件进入新提交,哪些文件进入新提交这一想法的方式是保留一个 每个待提交文件的单独副本在其 index aka staging area 中。这些额外的副本采用 Git 的内部形式,经过压缩和重复数据删除,可以提交。因为它们是去重复,所以从提交出来的文件实际上不占用空间。3

Git 处理这个问题的方式是,当您第一次签出某个提交时,Git 不会只是 填充您的工作树。 Git 填写both 你的工作树 它的索引。所以索引和你的工作树现在匹配了。

在您工作时,您将更改一些工作树文件。正如你所做的那样——并且你选择when——Git 要求你在这些更新的文件上运行git add。这一步读取并压缩工作树文件。 Git 现在检查压缩版本是否是 any 以前版本的 any 文件的副本,如果是,则简单地重新使用旧文件。如果没有,Git 会准备好提交的内容。无论哪种方式,Git 现在更新索引条目以记录新的或重用的内容。

这意味着该索引始终保持您的提议的下一次提交不在索引中的文件不在您提议的下一次提交中。当前提交产生的​​文件,在git checkoutgit switch 时间, 在索引中,除非您已删除或替换它们:这些文件在下一次提交中,除非您已删除或替换它们,但它们将与 当前 提交具有 相同的内容(除非您已删除或替换它们)所以它们不会占用空间。

通过这种方式,索引始终保持您提议的下一次提交。它包含“暂存于提交”、所有文件。

git status 命令将告诉您任何与当前提交中的文件不同的暂存提交文件。不会告诉你关于匹配当前提交的暂存文件,因为这通常并不有趣。因此,如果您有 3000 个文件准备提交,其中两个不同,git status 会告诉您有两个文件staged for commit。你实际上有 3000 个文件;只是其中两个不同,剩下2998个相同

  • 练习:如果git status 告诉你所有 3000 个文件,你会如何找到有趣的两个?

请注意,使用git commit -a 大致表示4

  • 运行git add -u:这会扫描所有现有的索引(暂存)文件以查看是否有任何工作树版本较新,如果是,则在它们上运行git add
  • 然后运行git commit

这种-a 标志可以让您暂时忽略索引。但是,过多地忽略它是错误的。我将在下一节简要介绍这一点。还要注意,它永远不会添加 new 文件:为此,您必须自己创建git add


3从技术上讲,文件的内容不占用空间。索引条目及其缓存数据关于文件显示在您的工作树中,占用一些空间,根据每个文件的许多细节,大约需要 40 到几百个字节。p>

4you 运行 git add 和让 git commit 运行 git add 之间的最大区别在于,如果你的提交失败(例如,由于预提交挂钩,或者您告诉 Git 停止并且毕竟不进行提交)。在这种情况下,由git commit -a 完成的添加得到un-done。如果您自己手动运行git add,则添加将保持添加。


索引的其他用途

索引在冲突合并中起着重要作用。 Git 合并涉及的不是一个而是 三个 提交,为了进行合并,Git 将所有三个提交读入它的索引。这涉及“扩展”索引,以便每个文件获得三个插槽。如果合并顺利,并且 Git 能够自行解决每个冲突,则三个插槽将降级为正常的单插槽,准备提交条目。如果不是,Git 会通过保留所有三个插槽来记住存在冲突。我们不会在这里详细介绍,但索引在合并期间扩展的事实意味着您真的不能忽略它。

此外,Git 有git add -p:这让您可以添加文件的一部分,就像原来的那样。 Git 通过在文件系统某处的常规文件中制作文件的临时副本(如在索引中看到的 in 所示),然后使用更新修补该文件,然后添加 that em> 文件的内容到索引。最终结果是索引中的副本(建议用于下一次提交)与 当前提交 版本您的工作树版本都不同。理解这一点的唯一方法是认识到索引包含文件的待提交副本,该副本可能与任何其他副本不同。

最后,文件中的存在与否决定了文件当前是跟踪还是未跟踪因为会影响文件是否可以忽略,所以你必须了解索引才能理解.gitignore

索引摘要

除了它在合并、索引或暂存区中的作用之外,如果您现在运行git commit,它只保存将要提交的每个文件的副本。您可以随时更改索引中中的文件:

  • 您可以运行 git checkoutgit switch 来选择一个新的提交,同时填写 Git 的索引和您的工作树。
  • 您可以运行 git rm 从 Git 的索引和工作树中删除文件。
  • 您可以运行git rm --cached(这里是旧的、坏词缓存,而不是暂存区)从Git 的索引中删除文件,而无需触及其中的副本你的工作树。5
  • 您可以使用 --staged 选项运行 git restore 以将文件复制到 Git 的索引中。
  • 你可以使用git reset的各种模式来影响索引文件(这个命令很大,可能太灵活了,这里不再赘述)。

基本上,有很多方法可以随时更改 Git 索引中的内容。索引 not 是只读的,不像提交是只读的。它包含提议的下一次提交,当您运行git commit 时,它会将索引中的所有文件立即打包并永远冻结它们,形成一个新的提交。6 这让我们回到跟踪文件和未跟踪文件:跟踪文件是当前在 Git 索引中的文件。未跟踪的文件是当前不在 Git 索引中的文件。而且,您只能忽略未跟踪的文件。


5请注意,这意味着下一次提交将没有该文件。如果您曾经检查过 old 提交,这会造成一个糟糕的情况,确实 有该文件:现在,当您切换回 em>new 提交,没有文件。

6当然,新的提交只有在它被提交时才会被提交——例如,参见前面关于预提交钩子的评论——并且,虽然新提交永久保留它的新哈希 ID新冻结的文件和元数据集,您可以通过一些工作让 Git 忘记此提交存在。一旦提交,您就无法更改提交,但您可以停止使用它。带有哈希 ID 的新提交永远是只读的,但它只会持续多久。提交是只读的,但只有-永久。


排除文件如.gitignore

在您的工作树中,但不在 Git 的索引中的文件是一个未跟踪的文件。我们可以在这里停下来,因为这就足够了。您运行git commit 并且只有跟踪的 文件被提交。您只需非常小心地git add 只有正确的文件,并且只有那些文件,加上之前提交的文件,才会被提交。

但这种工作方式烦人且效率低下。我们运行 git status,然后,哇,嘿,Git 抱怨大约 3000 个未跟踪的文件。我们的信息在哪里?它隐藏在所有这些“未跟踪文件”的废话之下。

(你之前做过那个练习,关于在大量无用信息中找到好的信息吗?)

那么:如果我们可以让 Git关闭哔哔声关于这些未跟踪文件中的大多数?当我们使用 Git 时,这可能是我们接下来可以做的最重要的事情。这使得git status 只打印有趣 的东西。

当然,我们可以让 Git 闭嘴。我们只需要列出它不应该告诉我们的文件。我们可以将这些文件的名称放在.gitignore.git/info/excludes~/.config/git/ignore 或其他文件中。这些文件统称为排除文件。通俗地说,大多数人只是叫他们.gitignore

.gitignore 文件可以包含:

  • glob 模式,例如 *.pyc
  • 一个简单的文件名,比如debug
  • 带有前导斜杠的路径名,如/tags
  • 带有嵌入斜杠的路径名,例如contrib/buildsystems/out

还有更多。

当其中一个文件列出了一个简单的文件名或模式(如 debug*.pyc)时,此名称与找到 .gitignore 文件的同一目录中的任何文件或目录名匹配, 在该点下的任何目录中。因此,如果我们有一个项目,如您所说:

.gitignore
LICENSE
README.md
App/
    .gitignore
    main.py
    [more files and directories]

然后我们有/.gitignore,一个在顶层,/App/.gitignore,一个在App 子目录中。否则不必要的,有时是误导性的,前导 / 在这里 -/.gitignore - 只是为了告诉我们我们在哪个级别找到了文件。

/.gitignore 中的

简单 条目适用于此处并适用于App/ 中的内容,如果存在则适用于App/sub/ 中的内容,依此类推。但是/.gitignore 文件中有一个条目,其中有一个前导斜杠,例如/README.html 用于我们可能为我们构建一些软件的 HTML 化版本的 markdown 文件,不会匹配App中的README.html,如果有的话。

因此,.gitignore 文件中条目中的前导斜杠具有锚定条目的效果:它仅在此特定级别匹配。如果/App/.gitignore 包含/LICENSE,这将忽略/App/LICENSE,但不会忽略顶层的/LICENSE

.gitignore 文件中的锚定有点奇怪,因为任何嵌入的斜线 也会有这种锚定效果。因此,如果您想忽略 contrib/buildsystems/out,就像 Git 的 Git 存储库所做的那样,您可以编写:

contrib/buildsystems/out

或:

/contrib/buildsystems/out

在顶级.gitignore 文件中:两者的含义相同。 Git 的人选择使用后者,也许是因为它更清晰(我认为它是,稍微)。

我们可以在.gitignore 文件中使用更多的模式和规则,但现在这可能已经足够了。详细信息在the gitignore documentation 中进行了描述。我们真正需要在这里讨论的是.gitignore 条目的其他效果。

我们已经知道,针对某些未跟踪的文件列出某些模式会导致git status 对此闭嘴。这很重要:它使git status 可用。但它还有两个效果:

  • 它使git add 更易于使用。
  • 它有一个不幸的“破坏许可”副作用。

让我们现在解决第一个问题。

全体git add

为了使git add 易于使用,我们可以在.gitignore 文件中列出那些不应添加的文件(如果它们尚未被跟踪)。例如,如果.gitignore 文件包含*.pyc*.pyo__pycache__,那么无论我们使用的是Python 2 还是Python 3,我们都可以运行:

git add .

不用担心我们的字节码编译的 Python 文件会被提交。这是因为扫描当前目录的全体git add .不会将任何未被跟踪和被忽略的文件添加为跟踪文件。

请注意,如果一个文件已经被跟踪,git add . 会添加它。也就是说,如果某个匹配 .gitignore 模式的文件已经在 Git 的 索引,并且您使用 git add 命令添加它,如果它没有被列为被忽略,Git 就像它没有被列为被忽略一样。它现在在索引中的事实覆盖了其他所有内容:它没有被忽略,因此它不会被忽略。

您还可以使用git add -f 强制覆盖忽略规则。例如,请参阅How to use .gitignore to ignore everything in a directory except one file?。这使您可以“第一次”将一个被忽略的文件放入索引中,之后它的存在 in 索引确保了它在索引中的持续存在(和更新)。我个人不喜欢这种技术,因为这意味着如果你曾经在文件上运行git rm稍后 git add 不会注意到它应该被添加回来:一旦它是 超出索引,它保持在外面!

破坏许可

这个很棘手。它也不会经常发生。触发它的主要方法是拥有一个被跟踪和提交的文件,然后决定您不希望它被跟踪,但希望将其作为典型工作树中的未跟踪文件保留。因此,您使用git rm --cached 将其从 Git 的索引中删除,然后提交,然后仔细更新此存储库克隆的所有用户。

但是,有一天,你决定检查一些 old 提交,看看情况如何。这会覆盖文件的工作树副本。 Git 需要一种方式来说明某些文件不应该被提交,但也不应该被破坏。它没有一个。详情请见Git checkout has deleted untracked files unintentionally

结论

如果你做到了这一步,恭喜! ? 您现在比大多数普通 Git 用户了解的多得多,了解 Git 索引和 .gitignore 文件之间的交互,以及这些排除文件中可以包含哪些内容。

最终的答案是你应该做适合的事情。毕竟,Git 是一组工具,而不是解决方案。任何一个给定的问题都没有一个正确的答案(尽管一些简单的问题确实有一个简单的答案,因此可能是可以使用的答案)。如果您遇到不寻常的情况,您可能需要一个不寻常的解决方案。 Git 或许可以提供。

记住排除文件条目是如何匹配的(请参阅我在How to use .gitignore to ignore everything in a directory except one file? 中的详细描述)。根据需要使用git check-ignore -v 来查看是否匹配了某个文件名,如果匹配,则根据哪个规则。请记住,~/.gitignore~/.config/git/ignore 中的 个人 排除文件可用于防止 Git 像 *.swp 或 @987654427 那样批量添加 临时编辑器 @ (vim)、*.~ (emacs 备份) 等等。如果您不想在您的个人排除文件或本地.gitignore 被提交到这个存储库中。

你有很多工具。其中一些有锋利的边缘(比如可能破坏文件),所以要使用它们,但要小心使用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-03
    相关资源
    最近更新 更多