git 尝试推送不存在的文件...清除缓存后

git trying to push non-existent file ... after clearing cache

我的存储库中有许多 shapefile 太大,因此导致我向 GitHub 的推送失败。我最初尝试创建一个 .gitignore 文件,该文件排除了 shapefile 包中的大部分扩展名。它仍然试图推送 shapefile。经过一番搜索,我发现我必须清除缓存:

git rm -rf --cached .
git add .

然而,一旦我尝试提交然后再次推送,我发现这并没有解决问题。同一个 shapefile 正在挂起东西。经过一番折腾,我放弃了这个想法,决定将所有 shapefile 移出存储库。我再次清除了缓存,重新添加、提交并尝试推送到 GitHub。

推送失败。 shapefile(不再在 repo 中)对于推送来说太大了。怎么会这样?我觉得不在提交中的文件,因为它们不在回购中,所以不应该挂断推送。对这里发生的事情有任何想法将不胜感激。

更新:变基选项的当前状态...

noop

# Rebase 133c6ec..133c6ec onto 133c6ec
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

更新: Reflog >> 一切都以 'Adding many images'

开头
133c6ec HEAD@{0}: rebase -i (finish): returning to refs/heads/master
133c6ec HEAD@{1}: rebase -i (start): checkout refs/remotes/origin/master
133c6ec HEAD@{2}: rebase -i (finish): returning to refs/heads/master
133c6ec HEAD@{3}: rebase -i (start): checkout refs/remotes/origin/master
133c6ec HEAD@{4}: rebase -i (finish): returning to refs/heads/master
133c6ec HEAD@{5}: rebase -i (start): checkout refs/remotes/origin/master
133c6ec HEAD@{6}: rebase -i (finish): returning to refs/heads/master
133c6ec HEAD@{7}: rebase -i (pick): still dealing with shp bs
0f81c71 HEAD@{8}: rebase -i (pick): Removing shapefiles
91cb472 HEAD@{9}: rebase -i (pick): Adding comments from Mullins consult - throu
83c1269 HEAD@{10}: rebase -i (pick): Adding comments from Mullins consult - thro
7677b3f HEAD@{11}: rebase -i (pick): Hopefully .gitignore is now working
97aa005 HEAD@{12}: rebase -i (pick): Adjusting gitignore
9e912cb HEAD@{13}: rebase -i (pick): Adjusting gitignore
06647c0 HEAD@{14}: rebase -i (squash): Adding many images
259d73b HEAD@{15}: rebase -i (squash): # This is a combination of 2 commits.
3b2d5e8 HEAD@{16}: rebase -i (start): checkout refs/remotes/origin/master
a585f1d HEAD@{17}: rebase: aborting
7bc98a4 HEAD@{18}: rebase -i (start): checkout refs/remotes/origin/master
a585f1d HEAD@{19}: rebase -i (finish): returning to refs/heads/master
a585f1d HEAD@{20}: rebase -i (start): checkout 9f28970
a585f1d HEAD@{21}: rebase -i (finish): returning to refs/heads/master
a585f1d HEAD@{22}: rebase -i (start): checkout refs/remotes/origin/master
:...skipping...
133c6ec HEAD@{0}: rebase -i (finish): returning to refs/heads/master
133c6ec HEAD@{1}: rebase -i (start): checkout refs/remotes/origin/master
133c6ec HEAD@{2}: rebase -i (finish): returning to refs/heads/master
133c6ec HEAD@{3}: rebase -i (start): checkout refs/remotes/origin/master
133c6ec HEAD@{4}: rebase -i (finish): returning to refs/heads/master
133c6ec HEAD@{5}: rebase -i (start): checkout refs/remotes/origin/master
133c6ec HEAD@{6}: rebase -i (finish): returning to refs/heads/master
133c6ec HEAD@{7}: rebase -i (pick): still dealing with shp bs
0f81c71 HEAD@{8}: rebase -i (pick): Removing shapefiles
91cb472 HEAD@{9}: rebase -i (pick): Adding comments from Mullins consult - throu
83c1269 HEAD@{10}: rebase -i (pick): Adding comments from Mullins consult - thro
7677b3f HEAD@{11}: rebase -i (pick): Hopefully .gitignore is now working
97aa005 HEAD@{12}: rebase -i (pick): Adjusting gitignore
9e912cb HEAD@{13}: rebase -i (pick): Adjusting gitignore
06647c0 HEAD@{14}: rebase -i (squash): Adding many images
259d73b HEAD@{15}: rebase -i (squash): # This is a combination of 2 commits.
3b2d5e8 HEAD@{16}: rebase -i (start): checkout refs/remotes/origin/master
a585f1d HEAD@{17}: rebase: aborting
7bc98a4 HEAD@{18}: rebase -i (start): checkout refs/remotes/origin/master
a585f1d HEAD@{19}: rebase -i (finish): returning to refs/heads/master
a585f1d HEAD@{20}: rebase -i (start): checkout 9f28970
a585f1d HEAD@{21}: rebase -i (finish): returning to refs/heads/master
a585f1d HEAD@{22}: rebase -i (start): checkout refs/remotes/origin/master
a585f1d HEAD@{23}: rebase: aborting
:...skipping...
133c6ec HEAD@{0}: rebase -i (finish): returning to refs/heads/master
133c6ec HEAD@{1}: rebase -i (start): checkout refs/remotes/origin/master
133c6ec HEAD@{2}: rebase -i (finish): returning to refs/heads/master
133c6ec HEAD@{3}: rebase -i (start): checkout refs/remotes/origin/master
133c6ec HEAD@{4}: rebase -i (finish): returning to refs/heads/master
133c6ec HEAD@{5}: rebase -i (start): checkout refs/remotes/origin/master
133c6ec HEAD@{6}: rebase -i (finish): returning to refs/heads/master
133c6ec HEAD@{7}: rebase -i (pick): still dealing with shp bs
0f81c71 HEAD@{8}: rebase -i (pick): Removing shapefiles
91cb472 HEAD@{9}: rebase -i (pick): Adding comments from Mullins consult - through rev chapter
83c1269 HEAD@{10}: rebase -i (pick): Adding comments from Mullins consult - through rev chapter
7677b3f HEAD@{11}: rebase -i (pick): Hopefully .gitignore is now working
97aa005 HEAD@{12}: rebase -i (pick): Adjusting gitignore
9e912cb HEAD@{13}: rebase -i (pick): Adjusting gitignore
06647c0 HEAD@{14}: rebase -i (squash): Adding many images
259d73b HEAD@{15}: rebase -i (squash): # This is a combination of 2 commits.
3b2d5e8 HEAD@{16}: rebase -i (start): checkout refs/remotes/origin/master
a585f1d HEAD@{17}: rebase: aborting
7bc98a4 HEAD@{18}: rebase -i (start): checkout refs/remotes/origin/master
a585f1d HEAD@{19}: rebase -i (finish): returning to refs/heads/master
a585f1d HEAD@{20}: rebase -i (start): checkout 9f28970
a585f1d HEAD@{21}: rebase -i (finish): returning to refs/heads/master
a585f1d HEAD@{22}: rebase -i (start): checkout refs/remotes/origin/master
a585f1d HEAD@{23}: rebase: aborting
eaadebf HEAD@{24}: rebase -i (pick): Adding comments from Mullins consult - through rev chapter
7bc98a4 HEAD@{25}: rebase -i (start): checkout refs/remotes/origin/master
a585f1d HEAD@{26}: commit: still dealing with shp bs
4bef02c HEAD@{27}: commit: Removing shapefiles
cc061ac HEAD@{28}: commit: Adding comments from Mullins consult - through rev chapter
21c5ab7 HEAD@{29}: commit: Adding comments from Mullins consult - through rev chapter
9f28970 HEAD@{30}: commit: Hopefully .gitignore is now working
a2bdbae HEAD@{31}: commit: Adjusting gitignore
c3e5128 HEAD@{32}: commit: Adjusting gitignore
8f8b96e HEAD@{33}: commit: Adding gitignore to avoid tracking shapefiles
0c14e14 HEAD@{34}: commit: Adding gitignore to avoid tracking shapefiles
3b2d5e8 HEAD@{35}: commit: Adding many images

这里首先要记住的是 git push 推送 提交 。如果碰巧包含任何文件,那纯粹是被推送的 提交 所需要的问题。

要记住的第二件事是,当您执行 git push 时,您的 git 和 "their" git(git 命令 运行 在 github 上,在这种情况下)通常会互相交谈,形式为:

  • "I have commit <SHA-1> I'd like to give you, and then I'd like you to set your branch master (or whatever other branch) to point to that SHA-1."

  • "Well, I have <different SHA-1> for that branch. Tell me what SHA-1s I need to fill in any holes between what I have and what you have."(除此之外还有更多内容,顺序不同,但本质是交换谁拥有什么提交和其他对象 ID。)

一旦他们知道彼此的 ID,发件人打包 "whatever is needed":这是一系列提交(可能是空的)和任何实体——主要是(但不限于)文件——去对于这些提交,接收者也还没有。在这种情况下,发件人是您的 git,收件人是他们的 git,包裹中包含一些大文件。

您决定发送大文件。这意味着您必须用您要求 git 发送的一些新提交替换您要求 git 发送的提交。如果新提交 引用大文件,那么当您的 git 发送提交时,他们的 git 将不会要求文件,您的 git 不会发送它们。

Pro Git book has a section on "rewriting history" 很好地涵盖了这一点。缺少的(至少如果你只阅读了其中的一个部分,还有其他部分涵盖了这一点)是 rebase 真正作用的图表。

(顺便说一下,您的 git 存储库仍将 包含 大文件,并将继续这样做,直到 全部 对这些文件的引用都消失了,包括在历史重写操作后在 git 的 "reflogs" 中徘徊的幽灵引用。正是这些挥之不去的幽灵允许您在操作过程中犯错时复活文件历史记录重写。Reflog 条目默认保留 30 天,对于这些条目至少 - "more active" reflog 条目默认保留 90 天 - 但除非你正在做一些不寻常的事情,否则你通常可以让它们过期拥有。)


git rebase documentation有一些图表,比如这张:

                 A---B---C topic
                /
           D---E---F---G master

[becoming]

                         A'--B'--C' topic
                        /
           D---E---F---G master

单个字母代表提交,这里有 A' 而不是 A 的原因,等等,在变基之后,是变基没有—不能——实际上移动一个提交,它只能做一个复制。原始提交仍然在那里,它们只是没有像 topic 这样的标签来保持它们可见。如果副本不同——它们确实不同——那么它们就有一个新的、不同的 SHA-1。真正重要的是 SHA-1,至少在推送(和获取)期间是这样。

在你的情况下,当变基时你想要做的是制作 "deliberately flawed copies",其中原件有大文件,而 "flawed" 副本没有。 (其实当然是"having the large file"的瑕疵,所以不是很完美的复制品才是正确的,是原件是错误的!)

Interactive rebase 具有额外的能力 "squash" 将新提交添加到现有提交中,即获取将要制作的副本并根据 next[=145] 进行修改=] 按顺序提交。

你想做的和上图中的另一个大区别是你希望新的提交从与原始提交相同的点开始:

        H - I   <-- master [in your repo]
       /
... - G     <-- origin/master [i.e., what's on github as master]

此处的提交 H 可能是带有额外文件的有缺陷的提交,而 I 可能是删除额外文件的提交。如果你要求将你的 master 推送到 github 并让 github 将其设置为它的 master,你的 git 和他们的 git 将聊天并决定 github 需要 HI 以及一些文件——包括,因为 H,大文件。

如果您重写自己的历史记录,以便在 HI 的位置有一个新的 H'I' 提交——为简单起见,我们将其称为 J ——那么你会得到这个图表:

        H - I   [abandoned ghosts]
       /
... - G     <-- origin/master [i.e., what's on github as master]
       \
        J   <-- master

现在您可以让您的 git 调用 git 集线器的 git 并建议只发送 J,其中没有大文件。

请注意,所有这些有两个关键:

  • Commit G(如 origin/master 所指)没有大文件,但是 github 上的存储库和存储库。这是 push 的共享起点:这是第一个提交,你的一方 在推送时离开 ,因为他们一方已经有了它。

  • 提交J(and/or您将推送的任何其他提交)必须没有大文件。这样,当您的 git 与他们的 git 交谈时,您的 git 将决定它需要发送的内容不包括大文件。

最后,您一方将在推送中发送多少次提交并不重要,重要的是 那些特定提交中的内容。您可以根据自己的喜好经常(或很少)重写 "only you have" 的内容。一旦你成功地将这些提交移交给另一个存储库,如果你 "rewrite" 他们到新的略有不同的副本,另一个存储库 仍然有原件 并且其他用户可能有也得到了它们(如果其他存储库通常可以访问)。

(你 可以 仍然 "rewrite history" 并使用 --force 推送请求其他仓库丢弃一些提交,包括你决定是不好的。这也没有本质上的错误,只是与您合作的任何人都可能选择了这些 "wrong originals" 并且他们可能正在使用它们,因此您也在为这些人做更多的工作。 )


最后一点,关于 git rebase -i 显示空列表的事实:这表明您实际上已经删除了所有您拥有但它们没有的提交。也就是说,而不是从:

        H - I  <-- master
       /
... - G      <-- origin/master

至:

        J    <-- master
       /
... - G      <-- origin/master

你以某种方式简单地完全丢弃了 HI,所以你的 master 也指向提交 G

如果你做了一个 rebase -i 并告诉 git 到 squash IH,它就会发生,结果是与提交 G 中的文件完全相同。 (例如,如果从 GH 的唯一区别是 "add big-file",从 HI 的唯一区别是 "remove big-file",则两者的组合与 G 没有 区别。) Git 确实允许 "empty" 提交——带有作者、消息等的提交,像往常一样,但是 same 树和之前的提交一样——但是默认情况下,rebase 假设你不想要那个:它只是完全去除取消的提交.

如果您确实有其他提交消失了,那么我之前提到的那些 "ghost commits" 正是您所需要的。要找到它们,请查看 "reflogs":

$ git reflog

和:

$ git reflog master

这些 reflogs 保留了 HEADmaster(或任何其他分支)在过去 90 天内指向的位置的历史记录:两者的原始 SHA-1 ID提交,无论它们是将永远存在的常规提交,还是仅由 reflog 条目保留的挥之不去的幽灵提交。