git推送git diff不显示的文件

时间:2017-12-25 11:55:21

标签: git github

当我在本地存储库中运行git diff --stat --cached origin/master时,我看到已准备好推送某些已提交的文件。但是,当我尝试git push时,它会尝试推送使用diff未出现但对我的远程存储库来说太大的不同文件。

这里发生了什么?溶液

1 个答案:

答案 0 :(得分:0)

TL; DR:您需要git reset

您可能需要git reset --soft origin/master后跟git commit。但请注意,这种git reset是更危险的Git命令之一,因为它可以删除提交。 Git是围绕添加新提交而构建的,它永远不会导致任何旧提交消失,因此意味着以前没有任何承诺的工作会丢失。由于git reset 删除了提交 - 或者至少可以删除它们 - 它可能会以这种方式丢失已提交的工作。

描述

git push推送提交,而非文件。

git diff --cached origin/master将名称origin/master选择的提交与索引的当前内容进行比较。索引不是提交,因此这不会告诉您git push会推送什么。

有关索引和提交的知识

索引 - 它有几个额外的名称:它也称为临时区域,有时也称为缓存 -is在哪里你有Git构建将在 next 提交中的所有文件。最初,索引包含与当前提交中的所有文件相同的文件。当前提交是您在运行git checkout master时检出的提交(请注意,我假设您根据问题中的名称git checkout master运行origin/master。)< / p>

现在,您在存储库中的每个提交都包含文件,可能包含很多文件。每次提交都充当了所有该提交中文件的完整,大部分独立的快照。

如果您提交了某些内容,然后删除文件并再次提交,则新提交就像旧提交一样,只是文件少了一个。

如果您提交了某些内容,然后更改文件并git add将更改复制到索引和git commit中,新提交就像旧提交一样,除了您更改的文件不同之外新提交。

换句话说,无论何时运行git commit,您的Git都会将索引中的任何内容打包到,并将其转换为新的提交。通常,这些新提交只需添加到您现有的提交。如果每个提交都有一个单字母的名称,而不是像a123456...这样的丑陋名称,我们可能会这样画出来:

...--F--G--H   <-- master (HEAD)

添加新提交会选择下一个字母,将其添加到提交链中,并使master指向刚刚添加的新提交:

...--F--G--H--I   <-- master (HEAD)

以这种方式使用时,Git只会添加新的提交

了解git push

的事项

当你运行git push时,你的Git会调用其他一些Git。你的Git和他们的Git进行了一次对话,找出你不想做的贡献,你想要给他们。然后你的Git会说:以下是我没有的这些提交。当您查看它们时,请设置您自己的master分支以记录提交#a123456 ...作为您自己master上的最后一次提交,就像它自己的master一样我的git push上次提交,好吗?

您获得的错误是因为当您发送这些提交和该请求时,他们的 Git查看这些提交并确定某些提交中的某些文件也是如此大。

这意味着为了让您的origin/master成功,您必须停止向提交那些提交,即具有大文件的提交。

这意味着您必须以某种方式删除提交

现在,假设他们的F在提交链中的提交...--F <-- origin/master \ G--H <-- master (HEAD) 结束:

G

进一步假设他们所抱怨的大文件在提交H和/或提交git commit中。如果您从索引中删除这些大文件,并运行I,您将获得新的提交...--F <-- origin/master \ G--H--I <-- master (HEAD) ,不再包含这些大文件:

git push origin master

但现在您运行G-H-I,即向其发送提交master,然后让他们将I设置为指向提交G。他们检查提交HI,并发现其中有大文件。在提交G-H-I中,大文件消失并不重要;重要的是,您让Git发送整个链G-H,并且大文件位于之前的提交中。

你需要做的是以某种方式使一个新的提交 连接回 J <-- master (HEAD) / ...--F <-- origin/master \ G--H--I <-- ??? 序列,例如,以某种方式做出一个可能看起来像这样的提交:

I

(我在这里假设你继续前进并提交J - 如果没有,只是假装它不在图中。)一旦你这个 sequence,你可以让你的Git调用他们的Git,发送他们F - 它连接回F但他们已经有master - 然后要求他们将J设置为指向提交J。由于J 没有拥有大文件,这样就可以了,幸运的是,它会通过他们施加的任何其他要求,并且他们会采取git reset --soft origin/master并将其放入存储库中。

如果您HEAD附加到master这样的master 1 ,您的Git会将您的origin/master更改为指向同一次提交...--F <-- master (HEAD), origin/master \ G--H--I [abandoned]

一样
origin/master

此时,整个提交链&#34;&#34; master不再使用--soft这个名称让您找到它们。这就是为什么现在可以删除它们。 2 这个命令的I部分告诉Git:不要触摸索引或工作树。因此,您的索引和工作树仍然按照提交git commit的方式设置。

如果您现在运行I,您将获得一个新提交,其快照来自索引,我们刚才记录的设置与提交J匹配。这是创建新提交F的原因。 Git使用当前提交(J)作为新提交的父级,以便F连接回 J <-- master (HEAD) / ...--F <-- origin/master

git push origin master

这正是我们想要的。

所以,现在我们可以运行J,让我们的Git调用他们的Git,将提交master转移给他们,然后让他们设置他们的{{1}指向我们刚刚发送的新提交J。其他提交 - 所有 - 永远不会离开我们自己的存储库。我们最好还是停止使用它们,因为它们有那些我们不想承诺的大文件,所以这一切都可能是正确的。

1 Git有两种模式:一种是HEAD是&#34;附加到&#34;一些分支如master,另一个分支HEAD 分离。分离的HEAD模式对于构建一些提交然后将分支名称附加到它们非常有用,并且由git rebase之类的内部使用。不过,附带HEAD的情况更为常见。 : - )

2 默认情况下,Git会将它们保留至少30天,如果你搞砸了,但是现在他们很难找到他们没有方便分支名称。