如何在不跟踪 png 文件的情况下将其保存在 git 中?

How do I keep png files in git without tracking them?

我的 bitbucket 存储库中有我的自述文件需要的 png 文件。但由于这些是二进制文件,当声纳 bitbucket 插件对它们运行 diff 时我会收到错误消息。

如何在不跟踪文件的情况下保留文件?

I 运行 git update-index --skip-worktree filename 然后 git status 但标志没有反射。它说-

Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean

不确定是否需要从存储库中删除文件然后添加跳过工作树标志。有人可以告诉我我做错了什么,或者是否有更好的方法来保存没有 运行 diff 的图像文件?谢谢。

在主题行中对您问题的字面回答:

How do I keep png files in git without tracking them?

只是“你不知道”。那是因为在Git中,一个跟踪文件是一个存在于Git的index.[=38中的文件=]

Git 的索引是您必须了解的重要数据结构(否则 Git 的行为将无法解释)。它的名字太普通了,太糟糕了,以至于它还有两个其他名字:它也被称为 staging area,或者有时——现在很少见——cache。现在,您经常会在某些命令的某些标志中看到术语“缓存”,例如 git rm --cachedgit diff --cached。但是这三个术语实际上指的是同一件事。

索引的功能复杂且数量众多,但实际上您需要了解的只有少数几个。最主要的——这也是为什么人们称它为 暂存区——是因为它始终保存着将进入你的下一个[的文件的副本。 =135=]提交。

“副本”一词在这里或许应该用引号引起来,因为索引中真正的内容 将进入下一次提交的内容。提交确实存储文件,但它们以冻结、压缩、Git-ified 和 de-duplicated-content 形式存储它们。这允许 Git 在 每个提交 中存储 每个 文件。事实上,新的提交主要存储与前一次提交相同的文件,并且 Git de-duplicates 每个文件的内容,意味着文件的新“副本”不带 space.索引中的“副本”也是如此:它们是 pre-de-duplicated,所以只要它们匹配 current 提交,它们就不会 space.1 但除此之外,它们确实像每个文件的副本一样。

换句话说,Git 始终拥有您正在处理或使用的每个(提交的)文件的 三个 副本:

  • 当前提交中有一个冻结的,永久保存。你不能改变这个,它不是你可以用于任何东西的格式,但是 Git 可以阅读它。

  • Git 的索引中有一个“副本”,准备进入下一个 提交。此副本开始与提交的副本匹配(好吧,无论如何通常)。

    此索引副本采用冻结格式,但实际上并未冻结。如果修改work-tree副本,则必须运行git add才能更新index副本。2

  • 最后,当然是文件的普通 read/write 副本。此副本位于您的 工作树 work-tree 中。这是您可以看到、使用和更改的,但实际上 根本不在 Git 中 。它不是提交中的副本,也不是准备好进入 next 提交的副本——这就是为什么如果你改变了你必须 git add 文件此 work-tree 副本。

当您 运行 git commit 时,Git 从索引中的任何内容创建 new 快照。在你 运行 git checkout 和你 运行 git commit 之间, 可以控制 Git 中的内容' s 索引,使用 git add and/or git rm。因此 Git 索引中的文件副本可能会更改,甚至会被完全删除。这会影响 next 提交,一旦你真正到达 运行ning git commit。在那之前,它只是“暂存”更新的文件。

(git status命令通过运行宁两个比较起作用:

  • 第一个比较告诉您当前提交和索引之间不同为提交.
  • 准备了任何不同之处
  • 第二次比较告诉您索引和您的 work-tree 之间 不同 。有什么不同的是 not staged for commit

因为有三个副本,这就是一个文件可以同时被暂存和 not-staged 的方式:提交版本、索引版本和 work-tree 版本都是不同的版本。)

无论如何,我们回到跟踪文件的定义:一个跟踪文件是您work-tree中的任何文件现在在Git的索引中。 未跟踪的文件 是现在在您的 work-tree 中,但现在不在 Git 的索引中的文件。 它进入Git 的索引,因为 (a) 它来自提交,and/or (b) 你 运行 git add 在上面。如果要在新提交中,它必须在 Git 的索引中 be。如果它现在不在 Git 的索引中,例如,因为你在它上面使用了 git rm,它就不会在 next 提交中。如果您不想在该提交中使用它,那很好;但是如果你确实想要在那个提交中使用它,你需要把它放回Git的索引中。

I ran git update-index --skip-worktree filename ...

这个及其相关的 --assume-unchanged 变体,只是在文件的索引条目中设置一个特殊位(必须是 in Git的索引,以便为要设置的位留出空间)。当该位被设置时,Git 将经常——不总是,但经常——假装文件的 work-tree 副本与文件的索引副本相匹配。然后它将单独保留索引副本。因此,如果索引副本当前与 current-commit 副本匹配,则设置该位可确保未来 git add 不会 使用 work-tree 副本(或缺少)更新索引副本。索引副本就保留在那里,在索引中,仍然匹配当前提交。

(当你使用git checkoutgit switch切换到一个新的不同的提交时,Git不得不更新各种文件的索引副本,Git 不会服从 assume-unchanged 或 skip-worktree 位,如果更改索引副本会破坏 work-tree 中任何未提交的工作,通常会抱怨并停止 commit-changing。但是这个至少有点危险,因为在 .gitignore 中列出文件可以让 Git 有权销毁 work-tree 副本。)


1他们需要一点 space 来保存文件 names、缓存数据和其他任何东西 Git 发现在使 Git 工作和快速运行方面很有用。它们还使用一些字节(目前每个文件 20 个字节)来保存内容哈希 ID,这与 Git 的内部存储格式有关。这意味着列出几千个文件的索引需要几千 KiB 来存储。例如,在 Git 的 Git 存储库中,我们发现:

$ git ls-files | wc -l

表示索引中有 3865 个文件,.git/index 上的 ls -l 显示索引大小为 366964(字节)。该索引还存储 headers 和预告片以及其他项目,因此这里没有保证 运行 直接相关性,但它通常会像这样平均。

2从技术上讲,这个 git add 会立即压缩和 de-duplicates 文件的内容,然后更新 blob 哈希 ID 在索引中。如果内容已经在其他地方的存储库中,则新的 ready-to-commit 文件是 de-duplicated。如果内容是 new,它现在是第一次在存储库中,准备提交。

请注意,如果您 git add 从工作树中 删除 文件后,Git 将在此时删除索引副本。 git add 命令实际上意味着 使索引副本匹配 work-tree 副本 ,如果 work-tree 副本消失,则意味着 Git 应该删除索引副本以匹配。

当然,如果根本没有索引副本,Git 将创建一个新的索引条目,像往常一样压缩和de-duplicating work-tree 内容。索引现在包含文件名、blob 哈希 ID 和缓存数据,索引副本现在与 work-tree 副本匹配。