如何将Git仓库回滚到第一次提交并删除所有历史记录

42

我最近在学习如何使用Git,但是我经常遇到试错的情况。因此我需要删除并重新创建我的远程和本地仓库。有没有一种方法可以回滚到仓库的第一个提交,并删除其后的所有历史记录?基本上是为了得到一个全新的状态来进行实验。

我正在学习如何使用git,我做了很多尝试,所以需要删除并重新创建远程和本地仓库。是否有一种方法可以回滚到仓库的第一次提交,并删除该提交之后的所有历史记录?这样就可以获得一个干净的状态以进行实验。

6
Git又把一个简单的任务搞得复杂了。Git的开发人员应该将Stack Overflow作为他们SDLC循环中的反馈。18K人应该表明Git的工作流出现了严重问题。他们需要聘请一个用户体验专家,因为他们显然无法自己解决这个问题。 - jww
哈哈,现在是64k了。 - Eskay Amadeus
7个回答

56
我不知道有什么方法可以完全满足你的要求(可以回滚到第一个提交,但无法删除所有历史记录,因为历史记录至少会包含初始提交)。
如果我是你,我会直接删除远程仓库和本地仓库的.git目录,并使用git init重新开始。
我能做到最接近你要求的是回滚除了第一个提交之外的所有提交。要做到这一点,首先要找到第一个提交的SHA1值,例如:
% git rev-list --max-parents=0 --abbrev-commit HEAD
aa8119f

...然后运行其中之一
% git reset aa8119f

...或者

% git reset --hard aa8119f

...根据您是否想保留或丢弃自初始提交以来所做的所有更改。(上述假设您只有一个分支。如果不是这样,您还需要删除任何其他分支,可以使用 git branch -d <BRANCHNAME>命令。)

最后,您将运行

% git push -f

希望你明白,每当你向与他人共享的存储库推送时,git push -f 是不可取的。
不幸的是,正如已经解释过的那样,这种方法并不能删除所有的历史记录。
如果你经常需要这样做,我建议在git init之后立即运行类似以下的命令:
% git commit --allow-empty --allow-empty-message -m ''
% git tag -a -m '' ROOT

这将在您的历史记录中放置一个空提交,并使用名为ROOT的标签进行标记。然后您可以执行类似以下操作的操作
% git reset ROOT

或者

% git reset --hard ROOT

带你回到第一个空提交。
为了更好地理解git reset的作用,我建议阅读this

2
关于“这种方法无法删除所有历史记录”的问题,确实无法摆脱最初的提交,但是在重置到第一个提交之后,您可以使用git rm *来清理文件(如果您修改了文件,请小心),然后使用git commit --amend --allow-empty --reset-author --date= -m "Erased history"来清除第一个提交的信息。 - TWiStErRob
1
又是一个被Git搞得复杂化的简单任务。Git开发人员应该将Stack Overflow作为他们SDLC循环中的反馈。18K人应该表明Git的工作流程存在严重问题。他们需要聘请一个UX专家,因为显然他们自己无法做到正确的git。 - jww
这个链接对我有帮助:https://dev59.com/umw15IYBdhLWcg3wZ68Y#6637891 如果你需要删除所有的历史记录 - 在执行答案中链接中的步骤后运行 git reset --hard - Eduard

14

你可以重置到第一个提交:

"如何在 'git log' 中显示第一个提交?"描述了如何找到第一个提交:

git log --pretty=format:%H | tail -1

(仅在没有多个根分支的情况下起作用)

git reset --hard yourFirstCommitSHA1

请注意,在重置后,如果要真正地开始一个全新的仓库,你可以简单地初始化一个新的git仓库并复制刚刚重置的第一次提交的内容(然后在这个新仓库中添加、提交)。


出于好奇:如何获得多个根分支? - kjo
太好了,知道了。谢谢!!!(我从来没有发现过这个功能,因为我期望这样的功能由git branch提供并记录,而不是由git checkout提供;我觉得这有点反常规,因为你必须要检出这样一个分支才能创建它。) - kjo
1
又是一个被Git搞得复杂化的简单任务。Git开发人员应该将Stack Overflow作为他们SDLC循环中的反馈。18K人应该表明Git的工作流程存在严重问题。他们需要聘请一个UX专家,因为显然他们自己无法做到正确的git。 - jww

12
一旦你完成了第一次提交并检出后,只需将.git目录删除即可。如下所示:
git checkout <first-commit-sha>
rm -rf .git
git init
git add -A
git commit -m 'Initial Commit'

比我的好多了。也许可以给出查找主根提交的SHA命令? - jthill
请注意,这个操作会 1) 删除你的配置文件(.git/config),并且 2) 完全清除子模块(它们的提交和配置)。因此,请确保备份你关心的配置文件设置,并确保你没有未推送的子模块提交。还有可能存在其他问题,所以总的来说,我不赞同这种解决方案。 - void.pointer

5

切换至主分支:

$ git checkout master

显示日志:

$ git log

回退到首次提交:

$ git reset --hard <you first commit number>

然后,将更改推送到远程:

$ git push --force origin

4
要进行一次干净的重置,你需要清除日志、配置更改和其他所有内容。我会通过将主根目录提取到一个新的仓库来实现这一点。
git tag master-root $(git rev-list --topo-order master|sed '$!d')
git init ../reset-my-repo
cd ../reset-my-repo
git fetch $OLDPWD master-root
git checkout -B master FETCH_HEAD

(即基本上就是VonC所说的
(添加--topo-order以防止错误的时间戳)

这似乎是我下面回答的更详细版本,所以点赞。 - VonC
@VonC 我现在明白了,我只关注了命令的效果。我还是很新,不是故意挑战你的权威,我的回答作为你的编辑是否更好呢? - jthill
不完全正确。我认为你的回答更详细,如果对提问者有用,它应该被采纳为最佳答案 :) - VonC

1
您可以使用以下方法删除当前分支中的所有历史记录:
git reset --hard <commit_id>

commit_id 是某个历史提交的 SHA1。

然而,如果您是在学习和进行实验,则很少需要使用它。

相反,您可以为您的实验创建新分支,例如:

git branch experiment <commit_id>
git checkout experiment
...

这基本上与第一种变体相同,但如果需要,您可以切换回去。

您还可以重新命名分支,使您的实验具有原始分支名称,例如:

git branch -m master backup
git branch master
git checkout master

如果你想销毁 backup 分支,只需执行以下操作:

git branch -D backup

0

或者通过Shell脚本 :)

#!/bin/bash

variable=`git rev-list --max-parents=0 --abbrev-commit HEAD`

git reset --hard $variable
git push -f

如果您将此发送给其他人,请不要忘记添加。
echo "Ja pie***** cos Ty odje***..."

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