将其添加到暂存区有什么意义git add .
?git add <filename>
为什么不只是 git commit -m "blabla"
?
我不明白暂存区的价值。
在 Git 中有很多 staging 的用途。下面列出了一些:
staging 帮助您将一个大的更改拆分为多个提交- 假设您进行了一个大的更改,涉及大量文件和相当多的不同子任务。你实际上并没有提交任何这些——正如他们所说,你是“在区域中”,并且你不想考虑以正确的方式拆分提交。(而且你足够聪明,不会把整个事情都放在按喇叭的大承诺上!)。现在更改已全部测试并正常工作,您需要正确提交所有这些,在几个干净的提交中,每个提交都专注于代码更改的一个方面。使用索引,只需暂存每组更改并提交,直到没有更多更改未决。如果您也喜欢 git gui,它确实可以很好地工作,或者您可以使用 git add -p 或者对于较新的 git,使用 git add -e。
分期有助于审查更改- 暂存可帮助您在审核复杂提交时“检查”个别更改,并专注于尚未通过审核的内容。让我解释。在提交之前,您可能会使用 git diff 来查看整个更改。如果您在查看每个更改时对其进行分阶段,您会发现您可以更好地专注于尚未分阶段的更改。git gui 在这里很棒。它的两个左侧窗格分别显示未暂存和暂存更改,您只需单击文件名左侧的图标即可在这两个窗格(暂存/未暂存)之间移动文件。更好的是,您甚至可以暂存文件的部分更改。在 git gui 的右侧窗格中,右键单击您批准的更改并选择“stage hunk”。只是该更改(不是整个文件)现在已上演;事实上,如果有其他的,
当合并发生冲突时,暂存会有所帮助- 当合并发生时,干净合并的更改会在暂存区域和工作树中更新。当您执行 git diff 或 git gui 的左上方窗格时,只会显示未完全合并(即导致冲突)的更改。同样,这使您可以专注于需要您注意的事情——合并冲突。
staging 可帮助您保留额外的本地文件- 通常,不应提交的文件进入 .gitignore 或本地变体 .git/info/exclude。但是,有时您希望对无法排除的文件进行本地更改(这不是好的做法,但有时会发生)。例如,也许您升级了构建环境,现在它需要一个额外的标志或选项以实现兼容性,但如果您将更改提交到 Makefile,其他开发人员就会遇到问题。当然,您必须与您的团队讨论并制定一个更持久的解决方案,但现在,您需要在工作树中进行更改才能完成任何工作!另一种情况可能是您想要一个临时的新本地文件,并且您不想打扰忽略机制。这可能是一些测试数据、日志文件或跟踪文件,或用于自动化某些测试的临时 shell 脚本...... 任何。在 git 中,您所要做的就是永远不要暂存该文件或该更改。而已。
staging 帮助你潜入小改动——假设你正处于一个有点大的改动的中间,并且你被告知一个非常重要的 bug 需要尽快修复。通常的建议是在单独的分支上执行此操作,但假设此修复程序实际上只是一两行,并且可以很容易地进行测试而不会影响您当前的工作。使用 git,您可以快速做出并仅提交该更改,而无需提交您仍在处理的所有其他内容。同样,如果您使用 git gui,左下方窗格中的任何内容都会被提交,因此只需确保只有更改到达那里并提交,然后推送!
值得将 Git 如何处理这个问题(Git 让您了解和使用暂存区)与 Mercurial 如何处理这个问题进行比较。在 Mercurial 中,您完全按照您的建议工作:您只需运行hg commit
,Mercurial 就会找出您更改的内容并提交它。您确实必须hg add
创建一个新文件,但如果您只是更改现有文件,则没有什么特别的事情要做:您更改它们,然后提交,然后就完成了。
Mercurial 的行为似乎(在我的观察中,一直是)对新用户更加友好。Git 实际上可以让你通过使用git commit -a
. 也就是说,您只需添加-a
您将使用的任何其他选项,Git 将做与 Mercurial 几乎相同的事情。但这有点像拐杖,因为最终,除非您了解暂存区,否则您会发现 Git 所做的一些非常莫名其妙的事情。
Hidd3N 的回答显示了您可以使用 Git 暂存区的多种方式。但如果你退后一步,比较一下 Mercurial 和 Git,我认为你可以看到更多真正发生的事情。
请记住,任何版本控制系统 (VCS) 的工作都是让您检索曾经提交的每个版本。(而且,由于 Git 和 Mercurial 都基于整个系统的快照工作,因此在这里很容易比较它们。有一些更老的 VCS 一次只对一个文件进行操作:您必须专门签入/提交每个单独的文件. Git 和 Mercurial 一次性为所有内容创建快照。)这些提交的快照应该永远存在,并且永远不会改变。也就是说,它们是只读的。
但是,只读文件不适合处理。因此,任何 VCS都必须以某种方式/某处具有两个独立的东西:
Git 的对象存储区有一堆只读对象:实际上,每个文件一个,每个提交一个,等等。您可以随时添加新对象,但不能更改任何现有对象。
正如 Mercurial 所展示的,不需要单独的暂存区:VCS 可以使用工作树作为提议的提交。当您运行时hg commit
,Mercurial 会打包工作树并从中进行提交。当您在工作树中进行更改时,您会更改建议的下一次提交。该hg status
命令向您显示您打算提交的内容,即:当前提交和工作树之间的不同之处。
然而,Git 选择在只读提交和读/写工作树之间插入这个中间区域。这个中间区域,暂存区域或索引或缓存,包含建议的下一次提交。
您首先检查一些提交。此时,您拥有每个文件的三个副本:
HEAD
)。这个是只读的;你不能改变它。它是一种特殊的、压缩的(有时非常压缩)、仅限 Git 的形式。HEAD
现在的那个,但它可以改变。这是建议进入下一次提交的那个。这也是特殊的 Git-only 形式。所做的是git add
将文件从工作树复制到暂存区域,覆盖用于匹配HEAD
提交的文件。
运行时git status
,它必须进行两次单独的比较。 将HEAD
提交与索引/暂存区域进行比较,以查看下一次提交会有什么不同。这是什么to be committed
。第二个比较发现索引/暂存区域和工作树之间的不同之处。这是什么not staged for commit
。
当你运行 时git commit -a
,Git 只是根据第二次比较进行复制到暂存区。更准确地说,它运行相当于git add -u
. (它秘密地使用临时暂存区域执行此操作,以防提交由于某种原因失败,以便您的常规暂存区域/索引在提交期间不受干扰。其中一些还取决于其他git commit
参数。通常这往往是不可见的,至少在您开始编写复杂的提交挂钩之前是这样。)
暂存区域就像一个粗略的草稿空间,您可以git add
在其中保存要在下一次提交中保存的文件版本或多个文件(换句话说,在项目的下一个版本中)。
请注意,您可以将文件的版本复制到暂存区域,也可以在提交之前将它们从暂存区域中取出,这就是为什么我将其称为草稿空间的原因。
该git add
命令的实际作用是将文件的该版本从工作目录复制到暂存区。
(这是一个常见的误解,人们可能会在他们的心智模型中认为文件被移动了,但实际上它是被复制的。)
将文件的更新版本添加到您的存储库所需的过程:
git add
然后使用命令将文件添加到暂存区git commit
最后,当您使用该命令时,它会包含在下一次提交中能够选择将哪些文件添加到暂存区域并包含在提交中的好处是您可以通过这种方式更好地组织您的工作。
您可以添加与一项工作相关的所有更新文件,并且当您提交时,您可以添加一条提及该工作的消息。
这样你可以更好地组织你的提交。
该视频以非常简单和直观的方式解释了上述所有内容,因此可能会有所帮助!
另一个小花絮,以防有人好奇暂存区在您的 .git 目录中的真正位置。它由.git 目录中的索引文件表示!
Microsoft Word 具有您建议的方法(假设您没有打开“跟踪更改”)。对文档所做的任何更改都会一起保存。没有暂存区。你别无选择。简单,但不灵活。
但是 Git 给了你更多的力量。您可以选择记录所做更改的时间和方式。复杂,但功能强大。
从根本上说:Git 用户是程序员:我们聪明且能干,我们想要这种灵活性。
弗雷迪写了一些精湛的歌词。在他已经写出它们之后,他如何将它们保存在四个单独的提交中?
妈妈,刚刚杀了一个人
用枪抵着他的头
扣动了扳机,现在他死了
妈妈,生活才刚刚开始
暂存区使他有可能做到这一点。这是一个类似于软件开发的工作流程。
如果您认为 staging 毫无用处,那么您可能也意识到 git 和软件开发的全部功能。Staging 意味着您要将这些文件提交到当前分支。有时,您可能不想提交某些文件,因此不会暂存这些文件以进行提交。
例如:- 一些特定于您的系统的默认配置,因此您可能不想将这些配置文件提交到每个人都在使用它们的分支。我希望它能消除你的疑惑!:-)