如何在git中删除第一次提交?

299

我很想知道如何在Git中删除第一个提交。

在提交任何内容之前的版本是什么?这个版本有一个名称或标签吗?


3
作为git的入门,你应该知道版本是没有意义的。你可以谈论提交或它们的相对SHAs。另外,为什么你想这样做?第一个提交是所有东西构建的基础。你可以将几个提交合并在一起,包括第一个提交,这将成为新的第一个提交,但删除第一个提交(或删除除最后一个提交之外的任何提交)意味着什么? - Shahbaz
@Shahbaz 是的,那是最好的方法,可以看这个例子:http://ariejan.net/2011/07/05/git-squash-your-latests-commits-into-one - timaschew
8
你可以使用 git rebase -i --root 命令。详细信息请参考以下 Stack Overflow 回答:https://dev59.com/pXE95IYBdhLWcg3wlu6z - MKroehnert
可能是 Can I remove the initial commit from a Git repo? 的重复问题。 - Gordon Gustafson
这个答案提供了正确的解决方案,可以删除当前分支的根提交:git filter-branch --parent-filter "sed 's/-p <the_commit>//'" HEAD - Jody Bruchon
这个回答解决了你的问题吗?如何撤销初始的git提交? - NBSamar
11个回答

557

对我来说,最安全的方法是使用update-ref命令:

git update-ref -d HEAD

它将删除名为HEAD的引用,因此它将重置(轻松地,您不会失去工作)当前分支上的所有提交

如果您想要将第一个提交与第二个提交合并,可以使用rebase命令:


git rebase -i --root

最后一种方法是创建一个孤立分支(orphan branch),即一个与其他分支相同但没有任何提交历史记录的分支,并在上面提交您的新内容:

git checkout --orphan <new-branch-name>

15
很遗憾这不是被采纳的答案。更遗憾的是,大多数谷歌搜索结果都差不多在说“你无法撤销第一个提交”。但是这个方法对我有效。谢谢! - danielpops
1
感谢@danielpops的支持!很高兴注意到我在3年后回答了这个问题。Git在此期间已经发展了。 - tzi
2
git update-ref -d HEAD是删除所有历史记录的最安全方式,而不仅仅是初始提交。 - user1767316
1
我做了它,它删除了我添加到第一个提交的所有文件。很遗憾。至少不是太多。 - Vyacheslav Tsivina
这并没有帮助到我。我不小心将我的第一个提交推到了主分支而不是特性分支,我想让主分支回到它之前的状态(即没有提交)。运行 git update-ref -d HEAD 后,我再也无法推送任何东西了。 - TanguyP
显示剩余4条评论

47

第一个提交之前没有任何内容,因为每个提交都是指向父提交的。这使得第一个提交很特殊(一个孤儿提交),所以无法引用先前的“状态”。

如果您想修复提交,可以简单地使用git commit --amend:这将修改提交而不创建另一个提交。

如果您想重新开始,请删除.git仓库,并使用git init创建另一个仓库。


9
这个答案是错误的:确实有一种方法可以回到第一次提交之前的状态。请参见下面的 tzi 回答 - David Nelson
3
如果作者初始配置有误,--amend也无法正确更新作者。这就是我需要的,所以我使用了被接受的答案,然后只是创建了一个新的提交。 - Mark Edington
我真的不明白有人根据什么得出“没有答案”的结论,即使显然没有(我在这里放这个短语是因为答案非常古老)。 - nomad

17
# Check out to a temporary branch:
git checkout --orphan TEMP_BRANCH

# Add all the files:
git add -A

# Commit the changes:
git commit -am "Initial commit"

# Delete the old branch:
git branch -D master

# Rename the temporary branch to master:
git branch -m master

# Finally, force update to our repository:
git push -f origin master

8
问题是“如何删除第一次提交”,而不是“如何删除除最后一次提交以外的所有内容”。 - peterh
2
我正好在找这个。谢谢! - Krzysztof Tomaszewski
4
好的,以下是翻译的内容:这个答案是从这里复制的。 - Jason Law
对我来说,我想要在Bitbucket中摆脱.gitignore文件,因为它阻止了我从本地repo推送到Bitbucket的第一次推送。我通过使用git push -f origin master命令来强制解决了这个问题。现在回过头来看,我认为我也可以通过向我的本地repo添加.gitignore文件来解决这个问题。 - luckyguy73

16

我曾试图寻找一种方法来撤销存储库中的所有git提交,就像它们从未发生过一样。

在某种程度上,变基可行。然而,最早(按时间顺序最古老的Git提交)总是会有问题,因为它没有父级,所以会出错。

这些答案都没有完全解决我的问题。但是经过大量搜索和试错,我发现这个方法很有效!

git update-ref -d HEAD
git push origin master -f
希望这能帮到你。祝你有美好的一天。

5
为了让任何人阅读这个答案都能清楚明白:这将删除所有提交记录,但OP只想删除对一个仓库的第一个提交记录;不要运行此命令以删除第一个提交记录,因为它会删除所有提交记录。 - Jody Bruchon
当我运行上述命令时,我也遇到了一个错误:“错误:src refspec Master does not match any error: failed to push some refs to <my repo>”。 - Jeanne vie
@JodyBruchon 我不明白它如何删除本地仓库上的任何提交记录(在运行时)。也许是在推送到远程仓库时。 - Guildenstern

6

您可能只想编辑第一个提交(因为 git 存储库中总是有第一个提交)。考虑使用 git commit --amend --reset-author 而不是通常的 git commit --amend


1
“不是答案:问题想要删除第一个提交,而不是修改最后一个的属性。” - peterh
@peterh-ReinstateMonica 为了澄清:在交互式变基期间,可以修改提交以完全更改其内容,但是还需要提供 --reset-author 选项以更改作者。有了这个选项,您可以完全替换第一个提交以符合您的需求。也请参阅 CharlesB 的答案。 - Max Beikirch

3
你可以采取另一种方法:
  1. 切换到你想要保留的分支(比如 dev) git checkout dev
  2. 现在,删除你想要重置的分支 git branch -D master
  3. 接着,创建一个同名的空分支 git checkout --orphan master
当然,所有这些都取决于你的使用情况,但如果你有多个分支,删除 .git 目录就没有意义了。

3
完成此操作后,您必须在推送之前删除远程分支。否则,在尝试推送时,您将遇到以下错误:![拒绝]主->主(非快进)-错误:无法将某些引用推送到'git@github.com:r1/r2.git'-提示:更新被拒绝,因为您当前分支的末端滞后于其远程对应项。在再次推送之前集成远程更改(例如,提示:'git pull ...')- 如果执行git pull,则所有提交都会返回。 - dxvargas
@dxvargas 只需执行 git push -f 命令来强制更新远程分支。 - Radon8472

2
如果您想保留其他分支,但是例如使master分支重新开始而不与其他分支共享历史记录,则实现此目的的一种安全方法是创建一个新存储库,并将其内容推送到旧存储库中:
cd ..
git init newrepo
cd newrepo
# make some initial commits
git push ../oldrepo master:newmaster

这将在旧仓库中创建一个名为newmaster的新分支,其历史记录与任何其他分支都不相同。当然,您也可以使用git push -f覆盖master
如果您想销毁所有分支和所有现有内容,只需运行
rm -rf .git/

2
“不是答案:” OP想要删除第一个提交,而不是以当前工作树作为初始提交开始新的git repo。 - peterh
@peterh 我同意 git rebase --root 可能是 OP 想要的,但考虑到这个回答已经有两个赞,我会避免删除它,以防某人仍然认为它相关。 - user1338062
我认为这个答案非常相关 - 如果您想要删除某个分支中的第一个提交,并且那里只有一个提交!(但您还想保留其他分支中的其他提交;并且您还想以使更改最终出现在Bitbucket或Github中,而不仅仅是本地。)我相信这个答案是实现此目的的一种方式,我认为这可能是这里唯一的方法。(这是因为-就我所看到的情况而言-没有办法强制推送没有提交的本地分支到具有某些提交的远程分支上。) - MikeBeaton

1
如果您刚刚提交了代码但还没有推送,那么只需删除.git目录并再次运行git init即可...

@peterh 是的,它可以。你假设(我想)OP的问题是想要删除第一个提交,但保留后续提交。另一个可能性(我认为完全符合OP的问题 - 这个答案也是一个答案)是想要从分支中删除第一个且唯一的提交,将其恢复为空状态。 - MikeBeaton
@MikeBeaton 你说得对。我撤回了我的评论,但是接下来我需要投票将这个问题标记为不清楚。请注意,尽管只有我发表了这个评论,但在我身后有着40000位访问者,其中很大一部分是通过Google找到这个问题的,他们没有得到他们想要的答案。 - peterh
那似乎有些极端。删除问题?难道不能(非常好地)认为对一个完全合理的问题给出完整的答案需要采取两种不同的方法,具体取决于是否...等等?(我的意思是,就我个人而言,我知道如何在不仅仅是唯一提交时删除第一个提交,以及如何在只有一个提交时删除第一个提交。这当然不是显而易见的,肯定取决于实现特定的细节,事实上每种情况都需要采用截然不同的方法。) - MikeBeaton

1

这里的所有答案都没有做到我从问题中隐含理解的事情(也是我个人需要做的),即如何删除第一个提交但保留其余历史记录。

以下是我是如何做到的(受@Mega Sahu答案的启发):

  1. 创建整个repo的备份。

  2. 使用switch切换到临时分支,使其完全为空:

    git switch --orphan TMP_BRANCH
  1. 添加一个临时文件以进行初始提交:
    touch tmp
    git add tmp
    git commit -m "initial "

第四步:最重要的一步是挑选你想要的所有提交,除了那些你不想要的(初始提交和其他任何东西)。最好使用图形用户界面来完成此操作。
    gitk
  1. 为了保险起见,在挑选完提交后,请与您创建的备份进行比较,以确保一切就位。

  2. 删除旧分支:

    git branch -D master
  1. 将临时分支重命名为主分支:
    git branch -m master

0
如果这是第一个且唯一的提交,可以使用git commit --amend来合并暂存的更改并修改最近的提交,即第一个提交。修改后的提交将成为一个新的提交,并拥有自己的引用。
# stage the new changes which will replace previous commit
git add my_file.py
# commit and change message
git commit --amend -m "Updating first and only commit"
# or commit without changing the message
git commit --amend --no-edit

如果没有新的内容被提交,那么它只是编辑之前提交的信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接