这有点棘手,直到您意识到 Git 实际上与 文件 无关。 Git 是关于提交。
提交存储文件。在每次提交中,Git 都会存储您文件的所有的完整副本。这不是提交的全部——文件是它的数据,提交也包含 元数据,例如关于谁提交的信息(姓名和电子邮件地址)、何时(日期和时间-stamp),以及为什么(他们在提交时写的日志消息)。还有更多,但我们不会在这个答案中深入探讨。
要记住的是:Git 存储 commits,每个提交都存储 每个 文件。一旦您(或任何人)做出提交,关于该提交的任何内容都无法更改。因此,只要您仍然有任何一个特定的提交,您仍然拥有 所有 文件,就像您提交该提交时的那样。所有提交始终是 100% 完全只读的。大多数提交将永远保留在您的存储库中。
(摆脱一个提交有点困难,但绝对不是不可能的。不要太担心“坏”提交会占用大量空间。每个时间都冻结的快照文件被压缩——通常是高度压缩的——因此通常比原始文件占用更少的空间,和,因为它们被永久冻结,Git 可以并且确实重复使用即,假设您连续进行 100 次提交,每次只更改一个文件。这可以是每次相同的文件,也可以是每次不同的文件,您可以根据需要来回更改——这并不重要。假设这 100 次提交中的每一次都有 500 个文件。由于在您的 next 提交中只有一个文件不同,因此它重用了前一次提交中的 499 个文件!并且, 如果你更改了一个文件back,新文件与旧提交中的旧副本相同,Git 会自动重新使用旧副本。)
每个提交都有一个大而丑陋的哈希 ID,对于那个特定的提交来说是唯一的。这个哈希 ID 的神奇之处在于它不仅对 that 提交是唯一的,而且,宇宙中的每个 Git 都会同意 that commit 获取 that 哈希 ID。没有任何其他提交获得该 ID。1 因此,两个 Git 很容易判断它们是否具有相同的提交:它们只是查看彼此的哈希 ID。 (实际上获取提交需要获取他们拥有的任何文件,而你也没有,但可以快速检查你是否已经拥有它。)
考虑到这一点,答案如下:
首先,我们应该注意这一点:git pull 表示 运行 git fetch,然后——如果可行的话——运行第二个 Git 命令,通常是 git merge。
git fetch 命令让你的 Git 调用其他人的 Git,并询问他们是否有任何提交,而你没有,你的 Git 应该得到。他们给你这些提交,现在你有你的提交加上他们的提交。这对您的任何提交都没有任何影响,因此它始终是完全安全的。
git merge 命令不是很安全,但很安全!它首先检查以确保您已提交您的 工作。如果没有,它会抱怨并让你提交......一旦你拥有了,所有你的文件,就像你提交它们时的状态一样,在你的新文件中一直安全地冻结提交。
git merge 操作通过查找更改来工作。你和你的朋友/同事从一些 common 提交开始——一些提交具有相同的哈希 ID,你和他们之前通过共享获得。然后您对某些文件进行了一些更改并制作了一个新快照以永久保存您的更改(以新的整个文件的形式),他们还进行了一些更改并制作了一个新快照以保存他们的永远改变。 Merge 将 merge base 提交(你们都开始使用的那个)与您自己的最新提交进行比较,并分别与他的最新提交进行比较。
比较任何两个提交可以告诉您这两个提交的不同。所以现在 Git 知道你改变了什么,也知道他们改变了什么。合并操作合并这些更改,并将合并后的更改应用到来自基本版本的快照。
如果您和他们更改了 same 文件的 same 行,您将得到 Git 所说的 合并冲突。在这种情况下,Git 会给您留下一团糟,您必须手动清理它,也许可以借助 merge 工具。但如果 Git 认为它能够自行组合您的更改,Git 将继续提交生成的组合更改快照,作为 合并提交。此合并提交会记住您自己的紧接在前的提交 和 他们最后一次提交的哈希 ID,以便 Git 知道哪两个提交进入了执行合并,并可以向您显示此合并产生的历史记录。
有些人可能会建议您在git pull 之前使用git stash,而不是自己提交。您可以这样做,但我不建议这样做。原因很简单:git stash push2 所做的只是进行一些不在 any 分支上的提交。这使得git pull 更容易,因为现在当git pull 执行其获取和合并步骤时,您没有要合并的提交——它使用分支上的提交进行合并——但之后您需要使用git stash apply 或git stash pop 来撤消隐藏。
您可能会忘记立即执行此操作,并首先进行一些您尚未提交的更改,然后记住git stash apply / git stash pop 步骤。此操作使用git stash push 所做的提交来运行git merge 的更不安全 版本。如果这里的情况很糟糕,则很难恢复您更改但未提交的内容。因此,通过使用git stash,您只是推迟了无论如何都需要进行的合并。
一旦您对合并和其他 Git 操作有很多了解后,您可以更安全地使用 git stash push、git stash apply 和 git stash drop,但如果您是 Git 新手,我建议您避免使用它。
1从技术上讲,两个不同的 Git 存储库可以重复使用哈希 ID,只要您从不将这两个 Git 存储库相互介绍。有关更多信息,请参阅How does the newly found SHA-1 collision affect Git?
2现在拼写为 git stash push 在旧版本的 Git 中拼写为 git stash save。新的拼写,push,修复了选项的一些小问题并允许一些新功能,并且还有助于解释为什么pop 是push 的对应物。我对git stash pop 的问题——好吧,除了我一开始就非常反对使用git stash ?——如果 Git 认为应用步骤去了,Git 将放弃存储好。有时应用步骤会很糟糕,即使 Git 认为它很好,或者你应用了错误的存储,并且 不 已经删除了存储会很好。
(如果你藏了很多东西,你会发现有时它们很难区分。一段时间后你不知道你为了什么原因保留了哪些。诚然commits can have the same problem,但在至少在这里,您以后有更多机会再次解决问题。)