如何删除前N个提交?

时间:2018-06-07 12:43:44

标签: git github

如何删除前N次提交并保持其余的提交不受影响?

换句话说。我想在第n次提交时拆分repo,从第n + 1开始提交提交,从第1次到第n次丢弃提交。

我不知道如何实现这一目标。仅尝试了git rebase,但它无效。

以下是我对git rebase所做的工作。

例如,测试的回购是https://github.com/danistefanovic/build-your-own-x.git

  1. 运行git rebase -i --root

  2. 将前20个提交标记为已删除

    d 4b6d12e Initial commit
    d f81138e Add links to issue form
    d 3530d91 Update README.md
    d 506b834 Update README.md
    d 79f41aa Update README.md
    d f9f9113 Update README.md
    d 9c8f134 Add resource type
    d 133469b Update ISSUE_TEMPLATE
    d 3a47f54 Add tutorials #1
    d 0271577 Add tutorial #2
    d 525953b Add tutorial #3
    d 2796fe5 Update ISSUE_TEMPLATE
    d 4f58667 Updated wrong link language from Go to Node.js
    d 0c525a7 Add tutorial #5
    d 0484fca Add OS: Build a minimal multi-tasking kernel for ARM
    d 457d5bb Add tutorial #9
    d 41ba7fc Add tutorial
    d dfbbf0f Add tutorial #11
    d b76dad5 Add tutorial #12
    d cd3bd26 Add tutorial #13
    pick c5f6c94 readme: Add my tutorial on shell
    pick 1f3c285 Add a minimal interpreter, compiler (x86/Arm) and JIT compiler
    ...
    
  3. 没有运气。我必须手动处理冲突,如show blow。

    $ git rebase -i --root 
    error: could not apply c5f6c94... readme: Add my tutorial on shell
    
    Resolve all conflicts manually, mark them as resolved with
    "git add/rm <conflicted_files>", then run "git rebase --continue".
    You can instead skip this commit: run "git rebase --skip".
    To abort and get back to the state before "git rebase", run "git rebase --abort".
    Could not apply c5f6c94859d852797c26d815e438e6a697c137a9... readme: Add my tutorial on shell
    
  4. 更新

    Remove / cut off Git's revision / commit history

    重复

    但没有办法保留时间戳。

1 个答案:

答案 0 :(得分:2)

首先,您是要尝试删除前20个提交,还是在第一个之后的20个提交?正如您在发布的TODO列表中所注意到的那样,提交4b6d12e并未列出,因此即使操作有效,也不会受到影响。这是因为您将4b6d12e指定为上游。如果你想要包含它(如果它没有父级,因为你说你试图删除第一次 20次提交),你可以使用--root选项,这样您不必将提交指定为upstream

其次,你如何定义&#34;删除提交&#34;?如果commit A添加了file1,并且commit B添加了file2,那么我就会删除&#34;提交A,以便我只留下提交B' - B'是否应包含file1和file2,或仅包含file2?

如果提交B'应仅包含file2 - 这意味着您要删除提交A 并对其进行更改介绍 - 然后使用d选项进行交互式rebase是一种方法。但当然它会导致您必须手动解决的冲突;对于您保留的每个提交,任何修改现在不再创建的文件(因为它最初是由您删除的提交创建的)都是冲突。 git无法推断出您希望它做什么,因此您必须手动解决冲突。您的问题跟踪的方式表明您希望该过程是自动的,但如果您要删除回购的创始提交及其更改,那么这不会是自动的。

请注意,这是历史记录重写。如果repo与其他人共享并且分支甚至被推送(在它包含前20个提交之一的时候),那么

(a)您必须使用push -f更新遥控器,

(b)更新了遥控器后,您将把所有其他用户置于破损状态,不正确的维修程序将撤消您的更改;所以如果你想让它发挥作用,你必须与其他受影响的人协调。

另一方面,如果B'应包含两个文件 - 在这种情况下应该调用类似AB而不是B' {1}} - 然后你想做两件事之一:

一个选项是squash提交,而不是delete他们[1]。这只是在rebase -i TODO列表中为每个提交使用不同的命令。如果您所做的只是压缩提交,那么不应该是任何冲突;但这仍然是历史改写,因此上述说明仍然适用。

另一种选择是创建repo的浅层克隆。这是历史重写;它的主要优点是它保留了提交标识,因此没有人的回购被破坏(作为副作用,如果有需要,你可以在将来重新关联被删除的历史)。请参阅depth的{​​{1}}和shallow-*选项。 https://git-scm.com/docs/git-clone

虽然浅薄并不是你可以通过推拉分享的东西。如果远程需要删除提交,则必须用浅(并且可能是镜像的)克隆替换该远程。这将由具有克隆的每个其他用户更新所述克隆[2]。

[1]我实际上喜欢这个git commit命令的术语,因为它促进了一个误认为提交是由它的补丁定义的水平是完全错误的。但是,这就是rebase使用单词的方式。

[2]最后一点也强调了一个可能的问题:无论你选择什么方法,你都不能强迫其他人放弃他们克隆的提交。因此,如果您要删除它们,因为它们包含敏感数据,那么可能只有猫可以解决问题。例如,您应该将曾被推送到共享仓库的任何凭证视为已泄露。