如何取消git add --all后跟多次提交

时间:2017-04-08 06:14:26

标签: git github git-add

我之前意外地使用了git add --all,然后做了几次提交,并且它试图添加几个应该被忽略的大文件。

现在,在任何提交时,它都会显示超过GitHub的文件大小限制为100.00 MB'。我试过git --reset但是它显示你的分支领先于&origin; master&master'由2个提交。如何让git恢复正常?非常感谢。

4 个答案:

答案 0 :(得分:1)

TL; DR:

How to undo last commit(s) in Git?查看各种答案或者,跳到最后一部分,"最后一个例子"。

解释

问题中的错误是您没有正确描述您的情况。您不仅添加了各种文件,还已提交它们。这意味着它们现在永久存储在您的存储库中。

永久这个词在Git中有点奇怪。确实如此,无论你做什么,提交都是固定的,不变的,并且保存在你的存储库中很长一段时间。默认情况是它们永远存在,这是任何人每次提交的历史的一部分。 Git从不删除任何提交:每个 new 提交都保留其先前提交的标识 - 称为 - 这个向后的新旧提交链存储在存储库中的历史记录。

提交本身实际上是通过哈希ID存储的,Git向你显示的那些丑陋的东西(有时缩写)如a9b307c等等。那些哈希ID是"真实的名字"每个提交。它们看似随机,基本上不可能让人记住,所以我们所做的就是让Git将 name 附加到某个特定的提交中,如master。我们将此提交称为分支的提示。该提交本身具有上一个分支提示的哈希ID。

考虑这个只有三次提交的存储库图,所有这些都在master上。我将为每次提交使用单字母名称而不是哈希ID:

A <--B <--C   <--master

名称master存储哈希标识badf00d或其他内容,这是提交C的实际哈希ID。我们说master 指向 C。同时C存储B的哈希ID;我们说C指向B。提交B会存储A的ID,因此B会指向A

由于A是第一次提交,因此它无法指向任何先前的提交。所以它没有。我们将A称为 root 提交。任何Git存储库都必须有第一个提交井,任何Git存储库都有任何提交 - 所以通常总是有一个root提交。根提交是Git可以停止向后遍历的方式。

要添加 new 提交,Git只需写出提交及其所有文件 - 每个提交存储与该提交一起的每个文件 - 并使其指向当前分支&#39 ;小贴士:

A <--B <--C <--D

提交D获取一个新的,唯一的哈希,它基于D中的所有(包括C的哈希ID,以及您的姓名和电子邮件地址和当前时间)。但是 - 这里是Git-Git中分支名称的秘密,现在将新提交的哈希ID写入分支名称,因此名称master现在指向提交D

A <--B <--C <--D   <--master

这就是分支增长的方式。提交后,名称将指向它,并且提交本身将永久存储在您的存储库中。

坏消息

这听起来像坏消息:你已提交这些文件,所以你现在 坚持下去。而且,这是个坏消息,但它并不是致命坏。

好消息

然而,如果你努力工作,最终可能会忘记提交。此外,当您将提交转移到其他人的存储库时 - 即,git push您的新提交 - Git将仅推送可从分支到达的提交或你正在推动分支 1

因此,你需要做的就是忘记&#34;你的一些提交。你通过告诉Git 重新指向分支名称来做到这一点。例如,让我们说提交D本身就是问题,我们只是想摆脱它。假设我们可以告诉Git:&#34;嘿,让master再次指向C&#34; - 就像这样:

A--B--C   <-- master
       \
        D

提交D 仍然存在(它是永久的!)但不再 名称{ {1}},因为Git从master命名的提交哈希ID开始,然后向后工作。这意味着Git没有&#34;看到&#34;提交master:它不再位于分支D上。

1 您可以一次性推送多个分支名称。这曾经是master的默认操作,事实上,尽管事实证明这很容易出错,但现在默认情况下只推送当前分支名称。

在Git中,有时候需要仔细区分名称,例如git pushmaster,以及我称之为&#34; DAGlets& #34;:部分提交图,就像我们上面提到的那样。提交图是 D 竖立的 A 循环 G raph或DAG。 developgit fetch都使用分支名称或任何其他类型的名称。他们在互联网电话的另一端打电话给另一个Git,然后与它交谈:他们互相给出其中一些名字,然后把它们变成适当的哈希ID。然后,他们根据哈希ID和我之前提到的那些父链接决定发送或接收哪些提交(和其他Git对象)。由于散列ID仅基于每个提交的内容,如果您的Git和他们的Git具有相同的 commit ,则这两个提交具有相同的散列ID。 / p>

有关git push

的信息

在Git中移动分支指针的主要方式是使用git reset。不幸的是,git reset是一个复杂的命令。

Git还有另一对重要的功能:当你 make 提交git reset时,你可以从中创建。 &#34;东西&#34;本身实际上是Git的索引。索引主要是,您可以在其中构建下一个提交

当您运行git commit时,Git会从工作树中获取文件 - 您工作的地方,其中包含您可以实际使用它们的表单中的文件 - 以及将它们复制到索引中。当您运行git add时,Git将所有工作树文件 2 并将它们添加到索引中。

此时,他们在索引中,但未提交,因此他们不是永久性的。您可以git add --all他们回复 out 索引。这是git reset的工作之一:重新设置索引。

但是那些文件也在你的工作树中。工作树版本也未提交,因此它们不是永久性的。你也可以git reset 他们,这是{em> git reset个{/ p>的工作。

当然,git reset可以移动分支名称,这是我们对此特定情况所需要的,因为 提交文件,所以现在它们作为新提交的一部分永久存储。移动分支机构名称是git reset三个主要职位中的第三个。 3 这三个职位具有一定的重要性:

  1. git reset 始终移动(重新设置)分支名称;
  2. git reset 有时会重置索引;和
  3. git reset 偶尔重置工作树。
  4. 您可以使用git reset(仅执行作业#1),--soft(执行作业#1和#2)和--mixed(执行所有三项作业)来控制这些

    当您执行移动分支的--hard时,您必须选择是保留索引和/或工作树。如果你使用git reset,Git会做所有三个事情。只要你准备丢失索引和工作树中的临时内容就可以了。

    提交是永久性的,但是一旦忘记了他们的哈希ID,就很难找到它们。所以可以重置它们:你可以让它们重新回来。此外,您可以使用新名称保存哈希ID,例如 new 分支名称,然后您可以非常轻松地将它们全部取回。让我们看一个最后的例子。

    2 全部,即除了(a)在索引中已经的文件和(b)列在git reset --hard或类似的文件中&#34;不要自动添加&#34;文件。

    3 .gitignore命令也可以做几个更具体的事情,在这种情况下它可以停止做一些主要的工作,但我们在这里不会提到它们

    最后的例子

    让我们说你在git reset并且已经做了许多提交,而不只是一个,其中包含太多文件。您希望记住(保存)您的工作,但也要抛弃索引和工作树,让master与您的&#34;上游&#34;同步。存储库,您克隆的存储库,您正在使用Git调用master

    你的提交图中有一些内容如下:

    origin

    您在...--o--o--o <-- origin/master \ X--o--o--o--Y <-- master (HEAD) 分支机构,它上面有所有的底行提交,以及您和master处的另一个Git共享的所有顶行提交。

    你在第一次提交中犯了一个错误,标记为origin。因此,您希望将X一直重置为指向与master相同的提交,并抛弃当前的索引和工作树,因为它们已经&#34;清理&# 34; (已提交并匹配origin/master的提示,即提交master)。您可以运行Y来执行此操作,但是您将忘记git reset --hardX的所有哈希ID。

    因此,您只需创建指向提交Y new 分支:

    Y

    现在你的照片看起来像这样:

    git branch save-my-mistake
    

    现在是运行的时间:

    ...--o--o--o   <-- origin/master
                \
                 X--o--o--o--Y   <-- master (HEAD), save-my-mistake
    

    将当前分支 - git reset --hard origin/master - 移动到指向与<{1}}相同的相同提交,并重新设置索引和工作树以匹配该提交:

    master

    现在,您可以随时从origin/master分支中获取任何内容,因为 分支名称会记住您的提交。

    最终,完成后,您只需删除该分支即可。这些提交迟早会 4 &#34;垃圾收集&#34;并真正从您的存储库中消失。在那段时间之前,你再也不会看到,因为你(和Git)可以找到难以理解的哈希ID的名称已经消失。

    4 过期时间相当棘手。它部分取决于 reflog条目,,它们在90天后到期,并且可以到达&#34;提交和30天无法访问&#34;提交,根据引用的当前值定义可达和不可达。一旦reflog条目本身到期,如果基础Git对象全局无法访问,即无法从任何名称访问,则它们就有资格获得此垃圾回收。从创建时起,他们仍然可以获得14天的宽限期,尽管在大多数情况下,如果30天或90天的时间段已经过期,那么14天就已经很久了。但是,删除分支名称将删除其所有的reflog条目,这可能会暴露更年轻的提交,然后获得其14天期间剩余的任何内容。

    在任何情况下,所有这些都是从...--o--o--o <-- master (HEAD), origin/master \ X--o--o--o--Y <-- save-my-mistake 驱动的,当其他Git命令认为有一些很好的理由时,它会运行。因此,直到其中一个那些 Git命令运行save-my-mistake,这些过期的对象可能会一直存在。这与Git的非正式名称非常吻合,&#34;版本控制的Borg&#34;它将一切都集中在它的集体中,但它可能会摧毁你的世界。 : - )

答案 1 :(得分:0)

如果您已提交,则可以选择删除文件夹并再次克隆。新的变化将会丢失!只有这样做,如果你在这个回购单独工作并且没有改变太多。

答案 2 :(得分:0)

您可以通过$params = array('q'=>'#producers OR Beatstars OR #Beatstars OR Instrumentals OR #Instrumentals OR #beattape OR Beattape OR Instrumental OR #Instrumental OR #myflashstore OR #soundclick OR Soundclick OR Send beats OR #beats OR FI Studio OR Hip hop beats OR Send beats to OR Pop beats OR Trap beats OR Beat store','lang'=>'en'); $reply = (array) $cb->search_tweets($params);

git reset返回2次提交

答案 3 :(得分:0)

如果您尚未提交,请运行:

  

git stash -u