Git - 如何在本地删除一个提交几个提交?

时间:2016-12-21 01:02:41

标签: git

所以我正在和一些队友一起开展一个项目,我已经改变了他们的变化,但有没有办法删除他们的提交(只是在本地 - 不打算用这种方式推送)并随意添加它?

**编辑:澄清,我不想将提交与我的提交相结合,我只想让它好像从未发生过提交(从提交中删除任何更改等)

Commit A: Commit that both of us got out
Commit B: His commit <- want to locally remove just this commit
Commit C: My commit

我曾考虑过制作一个分支,只是将我的提交放在分支上,而不是将其更改到该分支上,但我想知道是否有更简洁的方法不涉及单独的分支?

提前致谢!

3 个答案:

答案 0 :(得分:4)

不要害怕树枝!特别是分支分支名称,因为the word "branch" is ambiguous in Git - 非常便宜,几乎是免费的。对于Git,创建一个新分支包括将一个提交哈希ID写入一个文件, 1 并删除一个分支包括删除该文件。

虽然价格不那么便宜,但它们本身就是承诺。每个提交都只有一个“真实名称”,即大丑陋的哈希ID,face0ff...cafedad...或其他。每个提交都记录其提交ID,因此您(和Git)可以向后工作,从分支上的 last 提交开始,找到 all < / em>分支上的提交。这些提交是永久性的,不变的。可以更改的不是提交,而是分支名称

你绘制的内容有三次提交,但你没有明确表达彼此之间的关系。通过仅记录父母,在每次提交中记录这种关系,这是一种父/子事物。 2 因此,假设(合理地,我认为)提交A首先出现,然后是B,然后是C,你拥有的是:

A <- B <- C   <-- branch

即,分支名称branch指向您的提交C,您的提交C指向B(“B是我的父母”,说C)和B指向A。这些父指针都不能改变,但分支名称可以改变,并且使新的分支名称如此便宜,它可能也是免费的。

让我们创建一个新的名称并将其指向C

$ git checkout -b temp

现在我们有:

A--B--C   <-- branch, HEAD -> temp

我在此处放置HEAD ->表示当前分支是temp,即使有两个分支名称都指向提交C

现在你可以做的是复制 C到一个新提交,它主要是C,但不完全一样。我们将调用副本C'。在C'中,我们需要这两个主要区别:

  • 我们的新父母应该是A,而不是B
  • 我们应该弄清楚我们从B更改为C的内容,并将这些更改作为修补程序应用到A,而不是B

复制这样的提交,然后移动分支名称的命令是git rebase

$ git rebase --onto HEAD~2 HEAD~1  # we'll explain these later

rebase命令复制每个“rebased”提交,在这种情况下只提交C。然后它将当前分支名称移动到指向副本:

A--B--C   <-- branch
 \
  `---C'  <-- HEAD -> temp

请注意,原始提交C仍然在那里,它仍然位于分支branch的顶端。我们在制作副本时将其从temp放弃,但branch仍然记得它。

现在,您可以孤立地测试更改:C'在没有B的情况下是否正常工作?如果是这样,C可能会引发B中出现的任何问题,因为C' vs AC vs {几乎“相同” {1}}。

1 这是一个实现细节,分支名称也可以存储为多个文件而不是每个文件一个,但它应该让你知道如何廉价的分支真的是。

2 这是必要的,因为在您创建提交时,它具有 no 子项。一旦你创建了提交,它就是永久性的,不变的,所以它不能记录它的子节点。它的孩子还不存在!但是,只要有一个孩子存在,那个孩子就有了它的父母,那个孩子的父母也是永久性的,不变的,所以孩子可以而且确实记录了它的父母。

BHEAD~2

的说明

每当你想在Git中识别特定的提交时,你可以给它原始的SHA-1哈希。例如,您可以从HEAD~1输出中剪切并粘贴这些内容。但您也可以使用符号名称,例如分支或标记名称,或特殊名称git log。这些符号名称只是解析为提交ID:

HEAD

您可以缩写这些内容,以便$ git rev-parse HEAD de2efebf7ce2b308ea77d8b06f971e935238cd2f face0ff可用,如果实际ID以此开头。

您还可以使用 relative 名称,该名称取名为cafebabe。所以~numberHEAD~2都意味着同样的事情。 de2efeb~2后缀表示“返回一些父母”,回访的父母数量是~之后的任何内容。

由于~始终是当前提交,HEAD表示“返回一个父母”,而HEAD~1表示“返回两个父母”。从HEAD~2开始,返回一位家长会获得C,而返回两位则会获得B

因此:

A

表示“复制,以便我们在--onto HEAD~2 之后添加”,同时:

A
在这种情况下,

表示“不要复制提交HEAD~1 或更早” - 只留下提交B

答案 1 :(得分:1)

首先,尝试在存储库中获取所有提交 尝试 - &GT;的 git log 它显示对存储库的所有提交。 您的团队将提供所有不同的提交和参考编号: 例:   - &gt;提交4406fbc67a665a1e78c9ac2698164986b81bed13

让你想改变第一次提交只是引用那个。像这样

git checkout 4406fb(this is the commit reference no)  SplashActivity.java(this will be particular file name) 

答案 2 :(得分:1)

您可以将提交重新绑定到您想要作为父级的提交。

在提交C:

git rebase --onto <a_hash> <b_hash>

这不会“删除”B但它不再是C历史的一部分,这似乎是你的目标。

您可以通过重新贴回B来“添加回来”。

git rebase --onto <b_hash> <a_hash>