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

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

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


这是我最喜欢的方法:

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

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


另一个选择是一个交互式数据库(假设您的Git版本大于等于1.7.12):git rebase --root -i,如果您有很多提交,这可能会是一个很大的工作。

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

  • 第一次提交时将"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/


git filter-branch是主要的手术工具。

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

--parent-filter得到stdin上的父级,应该在stdout上打印重写的父级;unix true成功退出,不打印任何内容,所以:没有父级。@^!是git的缩写,表示"头犯,而不是其父母"。然后删除所有其他参考并在空闲时推送。


下面的方法是完全可复制的,所以如果两边都一致,就不需要再次运行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会自动垃圾收集它们。因此,您只需删除所有标记/分支并创建一个新的孤立提交,与任何分支相关联—按约定,您可以让分支master指向该提交。

旧的、无法实现的提交将不再被任何人看到,除非他们用低级的git命令挖掘。如果这对你足够了,我就停在那里,让自动GC在它想做的任何时候做它的工作。如果你想马上摆脱他们,你可以使用git gc(可能与--aggressive --prune=all)。对于远程Git存储库,除非您有shell对其文件系统的访问权,否则无法强制执行该操作。


为此,请使用shallow clone命令git clone—深度1 URL—它将只克隆存储库的当前头


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


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