为什么我的生活没有做任何事情?

时间:2017-03-05 21:24:47

标签: git rebase git-rebase

这个项目只有一个master分支,所以所有工作都在那里完成。

我错误地犯了一个拼写错误,虽然我可以撤消撤消,但我认为我会尝试完全删除提交。

提交哈希是dbcbf96bded82215是它之前的提交。所以,在these instructions工作,我这样做了:

  1. git rebase -i ded82215
  2. 这会在编辑器中显示“todo”列表,只包含以下内容,如预期的那样:

    pick dbcbf96 Writer update.
    
  3. 大概按照生成文件的注释中的说明,我将该行更改为:

    drop dbcbf96 Writer update.
    
  4. 我保存了文件并关闭了编辑器。然后说:

    Successfully rebased and updated refs/heads/master.
    
  5. 然后我检查了GitLab(我正在使用它来托管这个),期望看到提交消失,但事实并非如此,它仍然存在。

  6. 我做git status看看它推荐了什么动作并且它产生了:

    On branch master
    Your branch is behind 'origin/master' by 1 commit, and can be fast-forwarded.
      (use "git pull" to update your local branch)
    nothing to commit, working tree clean
    
  7. 这有点道理,但就篮板而言,我不确定发生了什么。现在我做git pull来更新本地仓库,但它刚刚回到我开始的地方,回到dbcbf96b,当地文件仍然包含更改,本地仓库更新,GitLab仍在显示修订版。 pull命令产生了:

    Updating ded8221..dbcbf96
    
  8. 所以我的rebase尝试什么也没做。我在这里想念的是什么?

    所以我按照下面的答案建议在第4步和第5步之间尝试git push -f,但它失败了,产生了:

    Total 0 (delta 0), reused 0 (delta 0)
    remote: GitLab: You are not allowed to force push code to a protected branch on this project.
    To https://gitlab.com/...
     ! [remote rejected] master -> master (pre-receive hook declined)
    error: failed to push some refs to 'https://gitlab.com/...'
    

    然后我尝试git push只是因为笑容而且它也失败了,产生了:

    To https://gitlab.com/...
     ! [rejected]        master -> master (non-fast-forward)
    error: failed to push some refs to 'https://gitlab.com/...'
    hint: Updates were rejected because the tip of your current branch is behind
    hint: its remote counterpart. Integrate the remote changes (e.g.
    hint: 'git pull ...') before pushing again.
    hint: See the 'Note about fast-forwards' in 'git push --help' for details.
    

    这也是有道理的,我想这就是-f的用途。第二位中的提示再次推荐git pull,我已经知道这不是正确的操作。

2 个答案:

答案 0 :(得分:4)

  

所以我的rebase尝试什么也没做。我在这里想念的是什么?

这不是真的,它确实做了一些事情。

你重新设置了你的本地仓库,它对GitLab上的远程仓库没有任何作用。所以远程的那个仍然有不需要的提交,当你git pull你获取它并将它合并回你的本地仓库时。

在rebase之后,您需要执行git push -f强制将更改的本地存储推送到GitLab,以删除两个存储库中的错误提交。

答案 1 :(得分:3)

Git是为添加新内容而构建的(其中"东西"意味着"提交")而不是带走东西 。这就是为什么你必须使用强制推动:你的推动会带走东西",即放弃你的提交。

你给了你的rebase一个明确的指示,"放弃这个提交",所以它做了(用一堆安全气囊和安全带让你恢复它,通常至少30天)。常规的git push不会让你放弃提交;只能用力推动。

因为强制推送可能会丢失提交,一些服务器会提供一个受保护的分支"模式,其中一些/许多/所有人都被禁止强迫推动。这就是你现在遇到的。要成功强制推送,您必须将自己设置为允许执行 - 通常是通过暂时取消保护分支,然后在推送后重新保护它。

讨论

确保您不会同时删除任何 else&#39> 提交内容!实际上,分支名称只是提交上的标签。它是提交本身,它们构成了存储库中的提交历史。每个提交本身都有其提交的ID。我们说每次提交都会回到"它的父母:

... <- commit 1234567   <-- branch

要添加新的提交,Git只是推进分支&#34;转发&#34; (即使所有内部Git箭头指向&#34;向后&#34;)到较新的提交。例如,如果我们从:

开始
... <-B <-C   <--branch

我们通过制作指向D的{​​{1}},然后将名称D指向C来添加新提交branch

D

要删除... <- B <- C <- D <--branch ,我们会再次D指向branch,但如果其他人出现并进行了新的提交C,则图片现在看起来像这样:

E

当我们现在强制...--B--C--D--E <-- branch 指向branch时, C D都会丢失:

E

使用...--B--C <-- branch \ D--E [abandoned] ,这几乎是你所能做的。 (有一个安全带可用,称为&#34;强制租赁&#34;,你让Git告诉他们的Git:&#34;我相信你的名字git push指向提交{{1如果是这样,强迫它指向branch。如果没有,请给我一个错误。&#34;但是没有什么比这更好的了,因为它们在你自己的存储库中。在您自己的存储库,D提供了复制所选提交到但能提交不同的提交的功能,以便您可以删除中间产品。 C只有强制选项。)

由于这些原因,Git还提供了“反转”的能力。一个提交:拿一些现有的提交,弄清楚它做了什么,并完全相反 - 放回任何被删除的文件;删除任何已添加的文件;删除添加的行并添加删除的行 - 作为 new 提交。因此,您可以在较新的提交中撤消任何较旧的提交,而这只是添加到历史记录中。例如,如果,在:

git rebase -i

序列,我们发现git push不好,我们可以告诉Git&#34;创建一个与A--B--C--D--E &#34;相反的新提交B,给出:

F

&#34;做同样的事情&#34;好像我们从未在序列中有B A--B--C--D--E--F ,但这样做不必打扰BF。通过添加其反转来回退整个提交的命令是C

考虑所有这些的简单方法

您自己的Git存储库就是:您的。您可以执行任何您想要的操作,包括在链的末尾删除(放弃)提交,或者通过复制过去的所有提交来复制提交(通过E)以删除中间件点。这样,您就可以编辑历史记录&#34;。

但是,每个提交都有一个唯一的ID。这是Git不时向您展示的丑陋哈希ID。唯一ID是进入提交的所有内容的加密校验和,以及#34;编辑历史记录&#34;导致全新的ID。通过 ID 进行交换(推送和提取)提交,因此一旦您将提交提供给另一个 Git实例 - 例如使用git revert - 您就拥有< em>发布这些提交。您可以尝试取消发布&#34;他们,但谁知道什么是成功。这有点像试图删除推文:有人可能已经捕获了它。

这并不代表&#34;永远不会尝试更改已发布的历史记录&#34;只是&#34;请注意,如果您确实尝试更改已发布的历史记录,则可能无效,而且#&#34 39; s开始使用发布的历史可能会烦恼。&#34;