繁体   English   中英

git 中暂存和未暂存文件的变化性质

[英]The nature of changes in staged and unstaged files in git

太多小时后,我对 git 的概念变得混乱。 有人可以澄清我这种情况。

我有一个存储库并且我在一个特定的提交中,假设一个提交 A

发生了一些变化(由于我应用了补丁,但这也可能是实际手动更改的产物)

所以我做git status并且我有几个“修改过的”暂存文件和一些“新的”未暂存文件。

我添加了我想保留的文件。 但接下来会发生什么?

我的意思是,如果在添加文件后我进行了提交,我处于我还有一次提交的状态,比如说提交 B

但是,未暂存的文件不会“消失”。 他们还在那里。

当然我可以手动删除它们(这会使它们从下一个git status消失)但是已更改的文件呢(我不希望它们更改

即使我不提交它们,更改的文件也在那里,所以如果我构建项目,它们会干扰。 我希望它们保持改变之前的样子

我怎样才能做到这一点?

太多小时后,我对 git 的概念变得混乱。 有人可以澄清我这种情况。

到清晰的路径是这样的:更改不会Git存在。 您可以让 Git 进行计算,然后显示更改(在两个快照之间),或者读取更改(从补丁中)并应用它们(到快照)。 但是,一切都Git是一个快照

这包括 Git 的索引/暂存区——它是一个快照,就像提交一样,除了你可以替换其中的文件——以及在较小程度上,你的工作树。 你的工作树是不是Git,但Git会一目了然了吧; 只要它现在没有主动改变,Git 就会看到一个快照。

我有一个存储库并且我在一个特定的提交中,假设一个提交A

这意味着 commit A是您当前的 commit ,通常是因为(当前)选择了 commit A的某个当前分支名称 (请记住,由某个分支名称选择的提交可以更改。但是,提交A不能更改:任何提交的所有部分都一直处于冻结状态。)

发生了一些变化(由于我应用了补丁,但这也可能是实际手动更改的产物),

由于Git的东西是快照,这些变化必须-一定-发生的Git,例如外,在你的工作树。 例如,您可能会在编辑器中打开某个文件并对其进行更改,然后再将其写回。 或者,您可以使用git apply (不带--index )在某些工作树文件中进行一些更改。

然后你可以——一旦工作树文件被更新——使用git add使 Git 用更新的快照副本替换旧的索引/暂存区快照副本。 此副本已准备好提交:它现在采用特殊的 Git 快照形式,经过压缩和重复数据删除。 它有点像 Git 中的一半(尽管如果它是重复的,则完全在 Git 中,因为它随后已针对已经完全存在的副本进行了重复数据删除)。

所以我做git status并且我有几个“修改过的”暂存文件和一些“新的”未暂存文件。

git status所做的是运行两个git diff ,两者都在内部使用--name-status设置(这会加快速度):

  • 首先,它区分当前提交A与索引/暂存区。 由于 Git 存储去重的文件,这几乎可以立即告诉 Git 在提交A和暂存区中哪些文件是重复的。 这些文件很无趣:Git 对它们一无所知。

    剩余的文件要么只存在于A ,要么只存在于索引/暂存区中,或者存在于两者中但不同。 status命令会说这些文件是为 commit 暂存的 这些是完整的副本! 可以肯定的是,它们已被压缩和重复数据删除; 但它们是整个文件的完整副本。

  • 现在,在提到这些staged for commit文件后,Git 在其索引/暂存区中的文件与工作树中的(常规、普通)文件之间运行差异。 由于您的工作树文件是实际的普通文件,因此这种差异必须更加努力,而不是进行压缩和重复数据删除的特殊 Git 化文件; 但是 Git 仍然有一些可以使用的作弊方法。 1

    同样,Git 索引中的某些文件将与工作树副本完全匹配。 对于这些文件,Git 什么也不会说。 仅对于在某些方面有所不同的文件——例如,仅存在于索引中,或者具有不同的内容——Git 会将这些文件命名为未暂存提交的文件。

然而,不是将仅存在于您的工作树中的文件显示为A dded,而是任何在您的工作树中不在 Git 索引中的文件——根据定义!——一个未跟踪的文件 Git 将这些文件名移动到一个单独的部分,通常首先根据您的.gitignore.git/info/exclude文件过滤此列表。 如果未跟踪的文件也没有忽略,Git 会告诉你它们作为未跟踪的文件存在。 如果它们忽略, git status不会说明它们。 请注意,这使它们与跟踪但未修改的文件无法区分。

我添加了我想保留的文件。 但接下来会发生什么?

没什么特别的: git add path告诉 Git 将文件从工作树中的给定路径复制到 Git 索引/暂存区中的快照中。 现在将暂存副本(以准备提交、Git 化、压缩和重复数据删除形式)与工作树副本之间的比较结果相同,因此第二个git status diff 没有说明文件。 这是否会更改与此特定文件有关的第一个git status diff,取决于更新的重复数据删除索引副本现在是否与 commit- A副本匹配。

当然,我可以手动删除它们(这会使它们从下一个git status消失)但是已更改的文件(我不希望它们更改)呢?

您可以告诉 Git 将提交 - 某个文件A副本复制到其索引中。 现在提交A副本和索引副本匹配。 当然,这假设文件存在提交A 如果没有,您需要完全删除索引副本,以便提交A中的文件缺失与 Git 索引中的文件缺失匹配。 (这里的一个小缺点是文件未被跟踪。通常,这没关系。)

为此,请使用:

git reset HEAD -- path

(在任何版本的 Git 中)或:

git restore --staged -- path

(在 Git 2.23 或更高版本中)。 这些命令意味着从当前提交(这是这种git restore的默认--source复制到Git 的索引中,而不触及工作树副本。

要在不触及工作树副本的情况下从 Git 索引中删除文件,您需要:

git rm --cached -- path

与往常一样, --是可选的,除非path参数类似于其他东西:分支名称、选项等。使用它从来没有坏处,有时foo既是分支名称是文件名并不明显,在在这种情况下,它可以帮助 Git 大量使用它。

(请注意,如果您确实想接触工作树副本,则需要使用一些不同的命令,例如git restore --staged --worktree 。)


1个这些秘籍指数/舞台区/高速缓存方面,当他们不工作,这部分git status可能需要很长的时间。 Git 会注意到这是否进行得很慢,有时会给你一些关于你可以做些什么来加速它的提示。

答案:使用 Stash

git-stash :将更改隐藏在脏工作目录中

你可能会问什么是 stash:

通常,当您一直在处理项目的一部分时,事情处于混乱状态,并且您想暂时切换分支以处理其他事情。 问题是,您不想提交一半的工作,只是为了以后可以回到这一点。 这个问题的答案是 git stash 命令。 存储获取工作目录的脏状态——即修改后的跟踪文件和暂存更改——并将其保存在一堆未完成的更改中,您可以随时重新应用这些更改(即使在不同的分支上)。

根据7.3 Git 工具 - 存储和清理

就我个人而言,我使用git stash 的次数比我想象的有一天会使用的多,但是如上所述使用它是在当前工作未完成时切换工作的好方法

你可以从Git Stash看到完整的手册

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM