在本地和远程之间显示不同的文件



>我有一个链接到远程git存储库的本地文件夹。

有时,我们有说明来检查本地和远程之间的区别。

但它们的差异可能又大又长。有时,我只想看看哪些文件不同/添加/删除,不需要详细介绍。

有谁知道我怎样才能快速获得这些信息?

编辑 1:

此外,我刚刚意识到我最终需要git add新的本地文件,并在git fetchgit diff之前在本地创建一个新git commit。我说的对吗?

您肯定需要获取远程存储库才能执行此操作。 没有办法避免这种情况。 完成此操作后,您可以进行比较。 有几种方法可以做到这一点。

一种是执行git diff --stat master origin/master并查看统计信息输出:

$ git diff --stat master origin/master
Documentation/RelNotes/2.26.0.txt | 44 +++++++++++++++-----------------------------
1 file changed, 15 insertions(+), 29 deletions(-)

您还可以仅查看带有git diff --name-only的文件的名称。 如果要具体查看已添加或删除的文件,可以使用--diff-filter选项仅列出以给定方式更改的文件。

最后,如果你想要更像git status -s输出的东西,你可以使用git diff --name-status.

您的问题提到了文件夹文件。 Git 不存储文件夹,也不真正处理文件——无论如何,它都不是在与另一台机器上的另一个 Git 通信的级别。 相反,Git 适用于提交。 当你的 Git 调用其他一些 Git 时,在其他机器上,你的 Git 从该 Git 获取他们拥有的任何提交,你没有的,你应该拥有的。 这是一个git fetch操作。 (或者,你的 Git向该Git 提供你拥有的任何提交,他们没有的,你希望他们拥有的提交:这是一个git push操作。 但听起来你在这里关心的是"从他们那里获取",即获取。

因此,在让你的 Git 调用他们的 Git 并从他们那里获得提交之后,你现在的工作是比较这些提交。 每个提交都包含文件。 它只有文件,没有文件夹,但这些文件通常具有可能强制操作系统创建文件夹的名称。 例如,名为dir/sub/file.ext的文件可能要求您的操作系统首先创建文件夹dir,然后在dir内,文件夹sub。 (这是你的操作系统的问题,而不是 Git 的问题:就 Git 而言,它只是一个长名称的文件。 Git 将根据需要解决操作系统对"文件夹"的固定

。每个提交都有该提交文件的完整快照。 因此,例如,如果您将提交C123与提交C456进行比较,您可以看到哪些文件对两者都是通用的,哪些文件对每个文件是唯一的,以及任何两个文件之间的区别。git diff命令就是这样做的,有很多选项:

git diff --name-only <commit#1> <commit#2>

告诉您哪些文件(全名如a/b/c.ext)在两次提交中不同,或者仅在两者之一中。 艺术

git diff --name-status <commit#1> <commit#2>

告诉您哪些文件不同,以及以何种方式不同:例如,可能需要Added 文件才能提交 #1,以便提交 #1 开始接近提交 #2。 另一个文件可能只需要Moded 即可稍微更改其内容。 这里打印git diff实际上是说明:如果你对左侧提交进行这些更改,你将得到右侧提交。git diff的默认设置是提供完整的说明:您必须执行的所有操作。

关于您的编辑

此外,我刚刚意识到我最终需要git add新的本地文件,并在git fetchgit diff之前在本地创建一个新git commit。我说的对吗?

这可能是最明智的,但可能没有必要。

我上面提到了 Git 使用提交,上面显示的差异都使用提交。 提交包含所有(已提交)文件的冻结快照。所有提交都是完全只读的:一旦提交,任何提交的任何部分都无法更改。 存储在提交中的文件采用特殊的只读、仅限 Git 的冻结格式,只有 Git 才能使用。 (这种格式使得比较提交更快、更容易,对于 Git 所做的其他事情也是如此。 它还使提交的存储更加紧凑,因为一旦文件被永久冻结,每个提交都可以重用提交的文件(如果它们匹配)。 更改它们是不可能的,所以如果你进行一个新的提交,并且 100 个文件中的 97 个是相同的,Git 可以重用这 97 个文件。 新提交中的"副本"实际上只是对现有的、共享的、已经冻结的副本的引用。

永远冻结的东西非常适合存档。 但 Git 不仅仅是一个归档器。 它的数据采用这种仅限 Git 的格式:您计算机上的任何其他内容都无法使用这些文件。因此,对于完成任何实际工作是完全没有用的。 这意味着 Git必须让你完成工作,将冻结的文件从某个提交中复制到某种工作区域。 此工作区中的文件(Git 称为工作树或工作树或类似区域)只是普通的日常文件。 它们没有冻结,而且是您的计算机使用的普通日常格式,无论那是什么。 (它们在文件夹和所有内容中!

这个过程,将冻结的文件复制到你的工作树中,也会将冻结的文件复制到 Git 的索引中。 当你git addgit commit时,你所做的是将工作树文件复制回索引(git add),然后从索引中的任何内容(git commit)进行新的提交。

索引可能会变得复杂(在合并期间),但可以非常简单地描述:这是您构建下一次提交的地方。 其中1中的文件采用冻结格式,准备进入新的提交,但与提交不同,不会冻结。 您可以覆盖它们,可以放入全新的文件,还可以从索引中删除文件。 因此,您可以将每个工作树文件复制到索引中,以使其准备好提交。 将工作树文件复制回索引的过程(如果有,则替换旧副本,如果没有,则创建一个全新的文件)称为暂存文件,因此索引也称为暂存区域

所以:要处理文件,你可以将它们从提交复制到索引和工作树。 您可以查看和修改工作树中的文件,并且可以将文件从工作树重新复制回索引,暂存它们以进行提交。


1从技术上讲,索引中的内容是对冻结格式文件的引用,就像在提交中一样。 如果您开始使用git ls-files --stagegit update-index查看索引的内部详细信息,则会显示此内容。 但在大多数情况下,你可以把索引看作是每个文件都有自己的单独副本:在你进入这个低级别之前,这个心智模型工作得很好。


git status

git status命令运行两个git diff:一个将当前提交(冻结,记住)与索引进行比较。 这里有什么不同之处,都是为提交而分阶段的。 也就是说,如果你现在运行git commit,Git 将从索引中的任何内容进行新的提交。 所有与HEAD(当前)提交匹配的文件都不是很有趣:它们是完全相同的。 所以git status对他们一无所知。 但是,对于任何新的、已删除的或不同的文件,git status列出该文件的名称。

这就是git diff --name-only所做的,也是git status在此步骤中所做的:它进行比较,无论有什么不同,都会打印出文件名。 但是,它不是比较两个提交,而是比较一个提交(特别是现在HEAD的提交)和索引。

git status接着跑了第二个git diff。 这一次,它将索引中的文件与工作树中的文件进行比较。 对于所有相同的内容,它什么也没说。 对于所有不同的内容,它会打印文件名。

同样,这与git diff --name-only会做的事情相同,只是它不是比较两个提交,而是比较索引和你的工作树。

由于工作树是一组普通文件夹,因此可以创建不在索引中的文件(和子文件夹)。 这些是您未跟踪的文件。 由于它们不在索引中,因此它们不会在下一次提交中。 如果你对它们运行git add,Git 会将它们从工作树复制到索引中,现在它们索引中,并将在下一次提交中。

如果不将这些文件复制到索引中,它们将保留为未跟踪的文件。 他们不会参加git diff. Git 只会抱怨它们:我发现了这些未跟踪的文件,我该怎么办?.gitignore文件告诉 Git 对未跟踪的文件闭嘴。 它对跟踪的文件(索引中的文件)没有影响,因为这些文件位于索引中。 但是,您可以随时将文件放入索引中,并将它们从索引中删除。

这一切如何与您的原始问题相吻合

如果要比较两个提交,则需要进行提交。 这使您可以根据需要调整索引内容,然后您有两个提交,其中比较很容易:您只需git diff两个哈希ID或两个哈希ID的名称。

但是,如果您愿意使用索引或工作树作为两组文件之一的源,您也可以这样做。 当将工作树用作一组文件时,Git 只会认为索引中的那些文件是该工作树的一部分:其他文件都是未跟踪的,因此不参与git diff。 现在你还有另一个问题:例如,git diff --cached <hash>与右侧的索引和左侧的给定提交进行比较。 但是有一个-R(反转两侧)标志,如果你想让比较走另一条路。

如果在获得差异后,您决定要另一个 Git发送提交,您可能只想进行提交。 提交通常非常便宜:只需打包索引中已有的任何内容,并添加新提交附带的元数据即可。

最新更新