Make the current commit the only (initial) commit in a Git repository?
我目前有一个本地Git存储库,我将其推送到GitHub存储库。
本地存储库有大约10个提交,而Github存储库是这个的同步副本。
我要做的是从本地Git存储库中删除所有版本历史记录,因此存储库的当前内容将显示为唯一提交(因此存储库中的旧版本文件不会存储)。
然后我想把这些更改推到Github。
我研究过Git-Rebase,但这似乎更适合于删除特定版本。另一个可能的解决方案是删除本地回购,并创建一个新的回购-尽管这可能会产生大量的工作!
ETA:有一些特定的目录/文件是未跟踪的-如果可能的话,我想维护这些文件的未跟踪。
这是蛮力的方法。它还删除了存储库的配置。
注意:如果存储库具有子模块,则此操作不起作用!如果您使用子模块,则应使用例如Interactive Rebase
步骤1:删除所有历史记录(确保您有备份,此操作无法还原)
1 2 | cat .git/config # note <github-uri> rm -rf .git |
步骤2:仅使用当前内容重建git repo
1 2 3 | git init git add . git commit -m"Initial commit" |
第三步:推到Github。
1 2 | git remote add origin <github-uri> git push -u --force origin master |
唯一适合我的解决方案(并保持子模块工作)是
1 2 3 4 5 6 7 | git checkout --orphan newBranch git add -A # Add all files and commit them git commit git branch -D master # Deletes the master branch git branch -m master # Rename the current branch to master git push -f origin master # Force push master branch to github git gc --aggressive --prune=all # remove the old files |
当我有子模块的时候,删除
这是我最喜欢的方法:
1 | git branch new_branch_name $(echo"commit message" | git commit-tree HEAD^{tree}) |
这将创建一个新的分支,其中有一个提交将所有内容添加到头中。它不会改变任何其他东西,所以它是完全安全的。
另一个选择是一个交互式数据库(假设您的Git版本大于等于1.7.12):
在编辑器中显示提交列表时:
- 第一次提交时将"pick"更改为"rework"
- 每隔一次提交时将"pick"更改为"fixup"
保存并关闭。Git将开始重新平衡。
最后,您将得到一个新的根提交,它是在它之后出现的所有根提交的组合。
好处是,你不必删除你的存储库,如果你有第二个想法,你总是有一个回退。
如果您真的想创建历史记录,请将master重置为此commit并删除所有其他分支。
拉尔斯曼建议方法的变体:
保存您的未跟踪文件列表:
1 | git ls-files --others --exclude-standard > /tmp/my_untracked_files |
保存Git配置:
1 | mv .git/config /tmp/ |
然后执行拉尔曼的第一步:
1 2 3 | rm -rf .git git init git add . |
恢复配置:
1 | mv /tmp/config .git/ |
取消跟踪未跟踪的文件:
1 | cat /tmp/my_untracked_files | xargs -0 git rm --cached |
然后提交:
1 | git commit -m"Initial commit" |
最后推送到您的存储库:
1 | git push -u --force origin master |
您可以使用浅克隆(Git>1.9):
1 | git clone --depth depth remote-url |
进一步阅读:http://blogs.atlassian.com/2014/05/handle-big-stores-git/
1 | git filter-branch --parent-filter true -- @^! |
下面的方法是完全可复制的,所以如果两边都一致,就不需要再次运行clone,只需在另一边运行脚本即可。
1 2 3 | git log -n1 --format=%H >.git/info/grafts git filter-branch -f rm .git/info/grafts |
如果要清除它,请尝试以下脚本:
网址:http://sam.nipl.net/b/git-gc-all-ferocious
我为存储库中的每个分支编写了一个"杀死历史"的脚本:
网址:http://sam.nipl.net/b/git-kill-history
另请参阅:http://sam.nipl.net/b/confirm
下面是改编自@zeelot答案的脚本。它应该从所有分支中删除历史记录,而不仅仅是主分支:
1 2 3 4 5 6 7 8 | for BR in $(git branch); do git checkout $BR git checkout --orphan ${BR}_temp git commit -m"Initial commit" git branch -D $BR git branch -m $BR done; git gc --aggressive --prune=all |
它适用于我的目的(我不使用子模块)。
只需删除github repo并创建一个新的。到目前为止,这是最快、最简单、最安全的方法。毕竟,当您只需要一个提交的主分支时,在接受的解决方案中执行所有这些命令有什么好处?
What I'd like to do is remove ALL the version history from the local Git repository, so the current contents of the repository appear as the only commit (and therefore older versions of files within the repository are not stored).
一个更概念化的答案:
如果没有标记/分支/refs指向旧提交,Git会自动垃圾收集它们。因此,您只需删除所有标记/分支并创建一个新的孤立提交,与任何分支相关联—按约定,您可以让分支
旧的、无法实现的提交将不再被任何人看到,除非他们用低级的git命令挖掘。如果这对你足够了,我就停在那里,让自动GC在它想做的任何时候做它的工作。如果你想马上摆脱他们,你可以使用
为此,请使用shallow clone命令git clone—深度1 URL—它将只克隆存储库的当前头
我解决了类似的问题,只需从我的项目中删除
To remove the last commit from git, you can simply run
1 | git reset --hard HEAD^ |
If you are removing multiple commits from the top, you can run
1 | git reset --hard HEAD~2 |
to remove the last two commits. You
can increase the number to remove even more commits.
更多信息在这里。
这里的git tutourial提供了有关如何清除存储库的帮助:
you want to remove the file from history and add it to the .gitignore
to ensure it is not accidentally re-committed. For our examples, we're
going to remove Rakefile from the GitHub gem repository.
1 2 3 4 5 6 7 | 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 |
Now that we've erased the file from history, let's ensure that we
don't accidentally commit it again.
1 2 3 4 5 | echo"Rakefile">> .gitignore git add .gitignore git commit -m"Add Rakefile to .gitignore" |
If you're happy with the state of the repository, you need to
force-push the changes to overwrite the remote repository.
1 | git push origin master --force |