在没有父母提交的情况下,Git责备被打破了

时间:2012-09-21 12:21:39

标签: git

我做了一些不好的事情......我不知道我做了什么,但我现在有两个提交没有父母。据我所知,我只应该有一个,这是最初的提交。

每当我责怪时, funky 提交之前的所有更改都指向提交2139f47。

这是我的reflog的 funky 部分:

...
49d0d22 HEAD@{313}: commit (merge): unused questions widget removed
2139f47 HEAD@{314}: commit: unused questions widget removed
e548c10 HEAD@{315}: commit: unused questions widget removed
e7d174b HEAD@{316}: pull: Fast-forward
...

内部链接看起来像这样:

  HEAD
   |
  ...         e548c10
   |             |
49d0d22 -----+   |
   |         |   |
2139f47     e7d174b
   |           |
  nil         ...
               |
            initial

合并提交对象(49d0d22)的内容是:

tree c3989e79c49df4b141b080502192bf0be0f67195
parent 2139f479dac242ad2ef757519aef77f3003ca996
parent e7d174bef4ab7e89b96f8c3de3551d0b760c80f8
author Michael Andersen <***> 1345190024 +0200
committer Michael Andersen <***> 1345190024 +0200

unused questions widget removed

没有父母(2139f47)的 funky 提交的内容是:

tree 4cfebc6b5a2a525bc255e4e095008b6aa8b106cc
author Michael Andersen <***> 1345189769 +0200
committer Michael Andersen <***> 1345189918 +0200

unused questions widget removed

没有对象似乎指向的提交内容(e548c10)是:

tree 0ae0960fccee7faec86ce7a82dd30af70f9c225a
parent e7d174bef4ab7e89b96f8c3de3551d0b760c80f8
author Michael Andersen <***> 1345189769 +0200
committer Michael Andersen <***> 1345189769 +0200

unused questions widget removed

所以我的问题是:

我可以删除时髦的提交吗?这个效应是如何产生的以及我的同伴编写的本地回购?

---编辑---

我不关心丢失一些提交对象。在我看来,我需要切掉2139f47和e548c10。我该怎么做?

2 个答案:

答案 0 :(得分:2)

您可以执行以下操作:

  1. 使用与49d0d22相同但具有单个父级e7d174b的树创建提交。这是需要每天不使用的“管道”命令的步骤。

  2. 49d0d22的后代重新引用到此新提交中。这使您的HEAD可以再次使用。

  3. 警告您的同事即将执行非快进推送。 (如果自定义回购以拒绝非快进推送,请与回购管理员联系以暂时启用它。)执行推送。

  4. 确保您的同事使用git pull --rebase更新其树,因此他们永远不会尝试与旧HEAD合并。要验证这一点,请让他们在拉动后运行git merge-base HEAD 49d0d22 - 它应该是空的。

  5. 实现这些步骤的命令应如下所示:

    # 0.
    git checkout master # or whatever your working branch is called
    
    # 1.
    commit=$(git commit-tree -m "unused questions widget removed" -p e7d174b 49d0d22:)
    
    # $commit should now identify the new commit; you should be able to see it
    # with git log $commit or any other git inspection tool.
    
    # 2.
    git rebase 49d0d22 --onto $commit
    # now your HEAD should be in a valid state.
    # git merge-base HEAD 49d0d22 should output nothing
    
    # 3.
    git push origin master
    
    git checkout master # or whatever your main branch is called
    

    至于提交e548c10 - 请忽略它。删除引用它的本地和远程分支,并告诉其他分支也忽略它。因为此提交不以任何方式引用2139f47,所以此步骤完全独立于上述手术。

答案 1 :(得分:1)

使用一些移植物或替换物为您提供正确的外观(链接),然后使用过滤器分支使其永久化。

这假设那些时髦的部分还没有与其他部分一起发布。


编辑前一阵子我问how-do-git-grafts-and-replace-differ, are-grafts-now-deprecated?这两种技术。

在实践中,我发现移植物更容易设置。它只是一个你想要被尊重的提交 - 父对的列表,而不是提交中列出的现有父对象。

这意味着,例如,您可以使用绕过错误提交的对来中断提交链(请记住所有提交只是快照; - )。

在这种情况下,您可以通过向grafts文件中添加必要的链接,使任何提交看起来都在提交链中的任何位置。你甚至可以用贪婪创造'假'合并(两个父母在线)。

因此,创建列表(移植文件),列出您想要更改的链接,然后它将显示(看起来像)你想要的方式。此时您可能希望将其永久化,因此只需运行git filter-branch即可重写这些部分。只要确保任何同事知道会发生什么,这样他们就不会“感到惊讶”。