停止在git中使用一系列提交

时间:2017-11-03 18:47:10

标签: git

以下是发生的事情:

  1. 写了代码
  2. 提交(commit:a)
  3. 代码有效。很高兴。
  4. 决定添加功能。
  5. 写了更多代码,并创建了提交b,c,d,e和f。这些被推到了主人的回购中。
  6. 意识到这不是最好的方法,我们需要恢复提交,所以,我们做了git checkout a并进行了更改,这些都有效。
  7. 现在,我们需要提交代码 as-is 来掌握,有效地删除,忽略或跳过提交b-f。

    我如何告诉git:"是的,我知道我回去犯了一个,然后做出了改变。我不再需要提交b,c,d,e和f中的任何内容。只需像现在一样完全提交代码。"?

2 个答案:

答案 0 :(得分:2)

如果你可以搞砸使用推送大师的每个人,那么请使用Mureinik的建议,只需git push --force origin

但是,如果你有其他人使用主分支并且你不喜欢他们在睡梦中谋杀你,那么:

首先,创建一个新分支。我们称之为" temp_work":

git checkout -b temp_work

这将保留您当前的提交。

然后,结帐大师:

git checkout master

恢复提交b,c,d,e和f:

git revert f e d c b

(它以相反的顺序以避免潜在的冲突。首先恢复最新的提交应该给你最小的冲突可能性。)

每个提交都会有一个编辑器屏幕可以恢复。

最后,将temp_work合并到master:

git merge temp_work

您现在可以删除temp_work分支:

git branch -d temp_work

但是,下次,请避免签出旧提交并在那里进行更改。恢复您不想要的提交,然后从那里继续正常,因为它可以为您节省一些工作。但除此之外,仍然没有大问题。

答案 1 :(得分:1)

有多种方法可以做到这一点。您应该使用哪种方法取决于(a)您希望历史记录的样子,以及可能(b)历史记录的成本是否重写"有意义的,(c)你对(a)或(b)的回答对你来说是否更重要。那么让我们看看一些选项......

无论您做什么,您都可以从提交新更改开始。这样可以确保不会有任何摆弄会导致您失去它们。

git checkout -b temp
git commit

现在,这些新的更改变为G,而您已

A -- B -- C -- D -- E -- F <--(master)(origin/master)
 \
  G <--(temp)

当您完成后,您将删除temp,如果G不是实际解决方案状态的一部分,那么它最终会被清除,所以作为安全网迈出第一步并没有害处。

现在,如果您知道自己再也不关心BF,那么最简单的解决方案是将master移至G }。这是一个历史重写,因为它从ref的历史中删除了提交。在进行历史记录重写时,您必须与使用回购的其他人协调/可能在删除&#34;删除&#34;承诺是其历史。导致历史重写的事情更难以执行:

  • 已完成其他工作&#34;在&#34;之上F
  • 很多开发人员使用repo
  • 使用回购的一些开发人员沟通有限,可能无法立即意识到发生的事情

如果您有任何这些条件,您可能希望找到不同的解决方案。历史重写的理想情况是,您可以与所有回购用户协调

  • 推送所有更改
  • 弃掉所有本地回购
  • 执行重写
  • 每个人都重新克隆

如果您决定重写历史记录是正确的做法:

首先将指向F的任何引用(例如上例中的master)移至G

git checkout temp
git branch -f master

如果其他分支机构基于F,则需要将其重新定位到G。例如,如果你有

A -- B -- C -- D -- E -- F <--(origin/master)
 \                        \
  G <--(temp)(master)      H <--(feature_b)

然后你可以说

git rebase --onto temp origin/master feature_b

产生

A -- B -- C -- D -- E -- F <--(origin/master)
 \
  G <--(temp)(master)
   \
    H' <--(feature_b)

如果你的工作基于BDE(但不是F),那可能会更具挑战性,但是变基也可能没问题

最后,你强迫推动&#34;您移动或重新分配的任何分支机构。 e.g。

git checkout master
git push -f

此时,所有其他用户需要恢复同步。如果,正如我上面所建议的,每个人都扔掉了他们的本地回购,他们可以重新克隆,他们会重新同步。否则,根据您已更换的任何提交,他们所拥有的任何本地更改都需要重新设置;他们的参考文献必须更新。请参阅&#34;从上游rebase恢复&#34;在git rebase文档中了解更多详情。

请注意,如果所有这些听起来都不错,那么您希望保留原始提交BF&#34;关闭到&#34;为了将来参考,然后在上述过程中移动master之前 ,您可以标记F

git checkout master
git tag old_master

(事实上你可以在移动master之后做到这一点,但此时找到F会更难。)

如果历史记录重写不适合您的情况,那么BF必须保留在历史记录中。然后,您可以添加一个或多个提交到&#34;撤消&#34; BF并申请G。如果没有一组分支都基于F,那么这仍然是最简单的。在最简单的情况下,您可以

git checkout master
git revert HEAD~4..HEAD
git rebase master temp
git checkout master
git merge temp

给你类似的东西

A -- B -- C -- D -- E -- F -- ~F -- ~E -- ~D -- ~C -- ~B -- G' <--(master)

如果您想直接从F跳到G'(没有显式提交以还原更改),您可以改为将G重新加入F (参见git filter-branch docs)。或者做同样事情的另一种方式

git checkout temp
git reset --soft master
git commit
git checkout master
git merge temp

使用这些解决方案中的任何一种,BF仍然会出现在历史记录中(例如git log)。在逐个回购的基础上,如果开发人员想要隐藏它,他们可以提供A作为替换&#34;用于G'之前的提交(即G'^)。有关详细信息,请参阅git replace文档。

另一个选项是将G合并到master(可能是在还原提交之后)。产生类似

的东西
A -- B -- C -- D -- E -- F -- ~FEDCB -- M <--(master)
 \                                     /
  ---------------- G ------------------

这没关系,但是更难以#34;纸张超过&#34;有替代的历史。请注意,在这种情况下,你应该将恢复提交(S)与合并提交相结合,因为这会产生一个&#34;邪恶的合并&#34;并可能导致麻烦。