使当前提交成为Git存储库中唯一(初始)提交?

我目前有一个本地Git存储库,我将其推送到Github存储库。

本地存储库有大约10次提交,而Github存储库是它的同步副本。

我想做的是从本地Git存储库中删除所有版本历史记录,因此存储库的当前内容显示为唯一的提交(因此存储库中的旧版本文件不会被存储)。

然后我想将这些更改推送到Github。

我已经研究了Git rebase,但这似乎更适合删除特定版本。另一个潜在的解决方案是删除本地存储库,并创建一个新的-尽管这可能会产生很多工作!

ETA:有未跟踪的特定目录/文件-如果可能的话,我想保持这些文件的未跟踪。

304077 次浏览

这是蛮力方法。它还删除了存储库的配置。

说明:如果存储库有子模块,这不起作用!如果您使用子模块,您应该使用例如交互式数据库

步骤1:删除所有历史记录(确保你有备份,这是无法恢复的

cat .git/config  # save your <github-uri> somewhererm -rf .git

第2步:仅使用当前内容重建Git存储库

在步骤2之前,如果您没有设置init.defaultBranch配置,请通过git config --global init.defaultBranch <branch-name>进行,您可以在当前示例中选择main作为<branch-name>

git initgit add .git commit -m "Initial commit"

第3步:推送到GitHub。

git remote add origin <github-uri>git push -u --force origin main

另一个选项,如果你有很多提交,可能会有很多工作,是一个交互式rebase(假设你的git版本>=1.7.12):git rebase --root -i

当在编辑器中显示提交列表时:

  • 将第一次提交的“选择”更改为“reword”
  • 每隔一次提交将“选择”更改为“修复”

保存并关闭。Git将开始重新建立基础。

最后,你会有一个新的根提交,它是它之后的所有提交的组合。

优点是您不必删除您的存储库,如果您有第二个想法,您总是有退路。

如果你真的想去核你的历史,重置主提交并删除所有其他分支。

唯一适合我的解决方案(并保持子模块工作)是

git checkout --orphan newBranchgit add -A  # Add all files and commit themgit commitgit branch -D master  # Deletes the master branchgit branch -m master  # Rename the current branch to mastergit push -f origin master  # Force push master branch to githubgit gc --aggressive --prune=all     # remove the old files

当我有子模块时,删除.git/总是会导致巨大的问题。使用git rebase --root会在某种程度上给我带来冲突(并且需要很长时间,因为我有很多历史)。

下面的方法是完全可重复的,所以如果双方一致,就不需要再次运行clone,只需在另一边运行脚本即可。

git log -n1 --format=%H >.git/info/graftsgit filter-branch -frm .git/info/grafts

如果您想清理它,请尝试此脚本:

我为存储库中的每个分支编写了一个“杀死历史”的脚本:

另见:http://sam.nipl.net/b/confirm

这是我最喜欢的方法:

git branch new_branch_name $(echo "commit message" | git commit-tree HEAD^{tree})

这将创建一个具有一次提交的新分支,添加HEAD中的所有内容。它不会改变任何其他内容,所以它是完全安全的。

要从git中删除最后一次提交,您可以简单地运行

git reset --hard HEAD^

如果要从顶部删除多个提交,则可以运行

git reset --hard HEAD~2

删除最后两个提交。你可以增加数量以删除更多的提交。

更多信息。

这里有管道炎提供了有关如何清除存储库的帮助:

您想从历史记录中删除文件并将其添加到. gitignore以确保它不会意外地重新提交。对于我们的示例,我们将从GitHub gem存储库中删除Rakefile。

git clone https://github.com/defunkt/github-gem.git
cd github-gem
git filter-branch --force --index-filter \'git rm --cached --ignore-unmatch Rakefile' \--prune-empty --tag-name-filter cat -- --all

现在我们已经从历史中删除了该文件,让我们确保我们不要再犯错误了

echo "Rakefile" >> .gitignore
git add .gitignore
git commit -m "Add Rakefile to .gitignore"

如果您对存储库的状态感到满意,则需要强制推送更改以覆盖远程存储库。

git push origin master --force

git filter-branch是大手术工具。

git filter-branch --parent-filter true -- @^!

--parent-filter获取stdin上的父节点,并且应该在stdout上打印重写的父节点;unixtrue成功退出并且没有打印任何内容,所以:没有父节点。@^!git的简写“头部提交,但没有任何父节点”。然后删除所有其他引用并轻松推动。

拉斯曼提议的方法的变体:

保存您的untrackfiles列表:

git ls-files --others --exclude-standard > /tmp/my_untracked_files

保存您的git配置:

mv .git/config /tmp/

然后执行拉斯曼的第一步:

rm -rf .gitgit initgit add .

恢复您的配置:

mv /tmp/config .git/

取消跟踪您未跟踪的文件:

cat /tmp/my_untracked_files | xargs -0 git rm --cached

然后提交:

git commit -m "Initial commit"

最后推送到您的存储库:

git push -u --force origin master

你可以使用浅克隆(git>1.9):

git clone --depth depth remote-url

更多阅读:http://blogs.atlassian.com/2014/05/handle-big-repositories-git/

我想做的是从本地Git存储库中删除所有版本历史记录,因此存储库的当前内容显示为唯一的提交(因此存储库中的旧版本文件不会被存储)。

更概念性的回答:

如果没有标签/分支/引用指向旧提交,git会自动垃圾收集旧提交。因此,您只需删除所有标签/分支并创建一个新的孤儿提交,与任何分支关联-按照约定,您将让分支master指向该提交。

旧的、无法访问的提交将永远不会被任何人看到,除非他们使用低级git命令进行挖掘。如果这对你来说足够了,我就停在那里,让自动GC随时完成它的工作。如果你想马上摆脱它们,你可以使用git gc(可能和--aggressive --prune=all一起)。对于远程git存储库,你没有办法强制执行,除非你有对他们文件系统的shell访问权限。

我通过从项目中删除.git文件夹并通过IntelliJ重新集成版本控制来解决类似的问题。注意:.git文件夹是隐藏的。您可以使用ls -a在终端中查看它,然后使用rm -rf .git将其删除。

使用浅克隆命令git clone--深度1 URL-它将只克隆存储库的当前HEAD

只需删除Github存储库并创建一个新的。迄今为止,最快、最简单和最安全的方法。毕竟,当您想要的只是具有单个提交的主分支时,在已接受的解决方案中执行所有这些命令有什么好处?

以下是根据@Zeelot的回答改编的脚本。它应该删除所有分支的历史记录,而不仅仅是主分支:

for BR in $(git branch); dogit checkout $BRgit checkout --orphan ${BR}_tempgit commit -m "Initial commit"git branch -D $BRgit branch -m $BRdone;git gc --aggressive --prune=all

它适用于我的目的(我不使用子模块)。

在这里你去:

#!/bin/bash## By Zibri (2019)## Usage: gitclean username password giturl#gitclean (){odir=$PWD;if [ "$#" -ne 3 ]; thenecho "Usage: gitclean username password giturl";return 1;fi;temp=$(mktemp -d 2>/dev/null /dev/shm/git.XXX || mktemp -d 2>/dev/null /tmp/git.XXX);cd "$temp";url=$(echo "$3" |sed -e "s/[^/]*\/\/\([^@]*@\)\?\.*/\1/");git clone "https://$1:$2@$url" && {cd *;for BR in "$(git branch|tr " " "\n"|grep -v '*')";doecho working on branch $BR;git checkout $BR;git checkout --orphan $(basename "$temp"|tr -d .);git add -A;git commit -m "Initial Commit" && {git branch -D $BR;git branch -m $BR;git push -f origin $BR;git gc --aggressive --prune=all};done};cd $odir;rm -rf "$temp"}

也在这里:https://gist.github.com/Zibri/76614988478a076bbe105545a16ee743

这将删除master分支上的历史记录(您可能希望在运行命令之前进行备份):

git branch tmp_branch $(echo "commit message" | git commit-tree HEAD^{tree})git checkout tmp_branchgit branch -D mastergit branch -m mastergit push -f --set-upstream origin master

这是基于@dan_waterworth的回答。

以下是清除Github存储库历史记录的步骤

首先,从. git中删除历史记录

rm -rf .git

现在,仅从当前内容重新创建git repos

git initgit add .git commit -m "Initial commit"

推送到Github远程存储库,确保您覆盖历史记录

git remote add origin git@github.com:<YOUR ACCOUNT>/<YOUR REPOS>.gitgit push -u --force origin master