如果它是分支中唯一的提交,我如何删除第一个也是唯一的提交?

时间:2016-05-03 15:54:57

标签: git build-process git-rebase git-commit git-config

我写了作者信息。在第一次提交。

但是,似乎大多数rebase或树修改操作都依赖于已经存在的其他提交。

即使我运行Git的交互式rebase命令,我在我的小提交列表中看到的只是一行,&#34; noop&#34;。 :/(通过使用root对Git树git rebase -i --root运行我的rebase来解决这个问题,但删除我做的第一次提交的行实际上并没有将它从树中删除。)< / p>

root或第一次提交之上重新定位不起作用。

[vagrant@localhost vagrant]$ git rebase -i HEAD~1
fatal: Needed a single revision
invalid upstream HEAD~1
[vagrant@localhost vagrant]$ git rebase -i HEAD
Unknown command: rnoop
Please fix this using 'git rebase --edit-todo'.
[vagrant@localhost vagrant]$ git rebase --edit-todo
[vagrant@localhost vagrant]$ git rebase --abort

以下内容看起来像是一个相关的可能的替代答案,但我认为更多,或者至少更具体一些,值得为这个特例解答:

Delete commits from a branch in Git

另一个答案(How do you undo the last commit?)导致以下结果:

[vagrant@localhost vagrant]$ git reset --soft HEAD~
fatal: ambiguous argument 'HEAD~': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
[vagrant@localhost vagrant]$ git reset --soft HEAD

在这里,对于那些仍在阅读本文的人来说,是我前面提到过的noop的vim缓冲区:

noop

# Rebase 3d1c632..3d1c632 onto 3d1c632 (1 command(s))
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

对于那些想知道我为什么不编辑文件并将它们重新添加到提交或其他内容的人,我的作者信息不正确,我在运行&#34; git commit&#后才更正了34;,当我打开提交消息进行编辑时,我更改了作者信息。

也许我可以尝试删除整个.git文件夹或其他内容,但我更喜欢更优雅的方式。

另外,如果我不删除整个.git文件夹,我会保留我的钩子和东西,我觉得这类问题的答案将与Git中的基本设计原则有关。我可能还不明白。

2 个答案:

答案 0 :(得分:3)

您可以在--root

之上进行折扣
git rebase -i --root

要在最后一次提交时更改作者,请使用:

git commit --amend --no-edit --author="The Name <email@domain>"

答案 1 :(得分:2)

我看到你已经解决了修复一个特定问题的机制。

但我会尝试解决您更普遍的问题:

  

......我有一种感觉,这类问题的答案将与Git的基本设计原则有关,我可能还不了解。

以下是此特定流程中涉及的所有棘手问题。

  1. 分支名称(如master)是指向一个特定提交的可移动指针。
  2. 每个提交都指向其父提交。根据定义, root 提交没有父级。 (这里不相关,但有用的知道: merge 提交只是定义为至少有两个父母的任何提交。)
  3. 要创建任何提交,我们需要在分支 1 上,但要创建 root 提交,它没有父级,我们需要让分支没有提交 - 但是请看第1点:分支名称指向提交。
  4. Rebase通过在git cherry-pick目标增长的匿名分支上执行重复--onto操作来工作。 (一旦完成重复的挑选,新的匿名分支提示将替换原始分支提示,即我们将分支重新指向新的提示。)
  5. 单个git cherry-pick的工作原理是将提交与其父级进行区分。例如,如果父项有三个文件,并且正在挑选的提交有四个,则提交添加了一个新文件。如果三个结转文件中只有一个是不同的,那么那个文件中的任何改变都构成了该提交的其余部分(好吧,提交的作者和其他元数据也是如此:这些也被带来了在樱桃挑选)。将原始提交转换为一组更改后,Git会将相同的更改应用于某些其他(已存在的)提交,并从中进行新的提交。新提交的父级是另一个提交。
  6. 这些原则创建了Gordian knot that --root slices through。值得注意的是--root在Git版本1.6.2中是新的,并且在1.7.12中进行了大量修改(我模糊地回忆起在此之前使用rebase并遇到一些问题)。

    Git总是必须解决#1和#3之间的紧张关系(当git checkout增加--orphan选项时,解决方案本身得到了改进并且在某些时候正确地形式化了。这里的诀窍在于,当所谓的&#34;未出生的分支&#34;时,Git像往常一样记录HEAD中的当前分支名称,但保留分支名称本身未发布的。

    (这里有助于了解 - 虽然这是一个你不应该担心的实现细节 - 分支指针当前存储在两个地方中的一个或两个地方.Git存储这些名称到ID的映射.git/refs/中的小型单个文件和/或单个平面文本文件.git/packed-refs。如果分支名称既不在某个位置,但在<{1}}中是,则Git认为这是一个未出生的分支&#34;。)

    在进行新提交时,如果当前状态为&#34;在未出现的分支&#34;上,Git进行根提交。新的提交ID成为现在创建的分支的ID,现在我们已经脱离了在分支上的自相矛盾的状态,但却没有提交。

    我们仍然遇到HEAD通过比较提交到其父级的问题。这就是为什么,如果您希望选择合并提交,您必须指定哪个父级:合并是一个具有两个或更多父级的提交,因此不清楚要对哪个进行区分。但是根提交,它的所有零计数 - &#39; em-zero父母呢?

    Git通过比较樱桃挑选的根提交与the empty tree来解决这个特殊问题。由于空树是空的,所以每个文件都是新添加的,这是樱桃选择的正确结果。

    因此,要使用git cherry-pick进行变基,我们希望创建一个孤立分支,然后像往常一样挑选根提交,然后是所有其他提交。但--root使用匿名分支。创建孤立分支的唯一正常方法是 name ,但是rebase使用&#34;分离的HEAD&#34;模式。此外,每个包含第一个的挑选都需要对现有提交应用更改,但是要创建新的根提交,我们必须避免使用某个现有的父提交。

    这个棘手的内部结构(间接地)在this answer from VonC中找到,它链接到this commit to the Git code。 rebase脚本创建一个真正空的根提交(使用空树和git rebase内部&#34; plumbing&#34;命令创建一个具有用户指定父ID的提交对象),然后生成一个内部& #34;壁球&#34;樱桃挑选现有的根提交(对同一个空树进行樱桃挑选)并将其与虚拟空根提交相结合。

    (这里也有助于注意到&#34;压缩&#34;在rebase期间的操作意味着&#34;修改先前的提交&#34;,la git commit-treegit commit --amend操作告诉--amend进行新的提交 - 现有的提交无法更改 - 但要使新提交的父级与现有提交的父级匹配。这具有推迟旧提交的效果另外:分支现在指向新的提交,它指向&#34;修改&#34;提交的父级。修改后的提交仍然在存储库中,但除非有其他方法找到它,它不再是可见。)

    (这个两步技巧意味着专门处理作者信息。)

    1 出于此声明的目的,至少处于分离的HEAD模式(例如,在git commitgit checkout hash之后)被视为特殊匿名branch,其提示是当前提交的哈希值。