我不小心提交了一个不需要的文件(文件名。Orig而解决合并)到我的仓库几个提交前,没有我注意到它直到现在。我想从存储库历史记录中完全删除该文件。

是否有可能重写更改历史这样的文件名。奥里格从一开始就没有被添加到存储库中?


当前回答

如果这是你想要清理的最新提交,我尝试使用git版本2.14.3 (Apple git -98):

touch empty
git init
git add empty
git commit -m init

# 92K   .git
du -hs .git

dd if=/dev/random of=./random bs=1m count=5
git add random
git commit -m mistake

# 5.1M  .git
du -hs .git

git reset --hard HEAD^
git reflog expire --expire=now --all
git gc --prune=now

# 92K   .git
du -hs .git

其他回答

如果你的情况不是问题中描述的情况,请不要使用这个方法。这个配方是用来修复一个坏的合并,并在一个固定的合并中重新播放你好的提交。

尽管filter-branch会做你想做的事情,但这是一个相当复杂的命令,我可能会选择用git rebase来做这件事。这可能是个人喜好。Filter-branch可以在一个稍微复杂一点的命令中完成,而rebase解决方案则是一次执行一步等效的逻辑操作。

试试下面的食谱:

# create and check out a temporary branch at the location of the bad merge
git checkout -b tmpfix <sha1-of-merge>

# remove the incorrectly added file
git rm somefile.orig

# commit the amended merge
git commit --amend

# go back to the master branch
git checkout master

# replant the master branch onto the corrected merge
git rebase tmpfix

# delete the temporary branch
git branch -d tmpfix

(注意,你实际上不需要一个临时分支,你可以用一个'detached HEAD'来做到这一点,但你需要注意git commit——modify步骤生成的提交id,以提供给git rebase命令,而不是使用临时分支名称。)

重写Git历史记录需要更改所有受影响的提交id,因此每个参与项目的人都需要删除他们的旧回购副本,并在清理历史记录后进行新的克隆。它给人带来的不便越多,你就越需要一个好的理由来这样做——你多余的文件并没有真正造成问题,但如果你只是在做这个项目,你也可以清理Git历史记录,如果你想的话!

为了尽可能简单,我建议使用BFG Repo-Cleaner,这是一个更简单、更快的Git -filter-branch的替代方案,专门用于从Git历史记录中删除文件。它让你的生活更轻松的一种方式是它实际上默认处理所有的引用(所有标签,分支等),但它也快了10 - 50倍。

你应该仔细遵循以下步骤:http://rtyley.github.com/bfg-repo-cleaner/#usage -但核心是:下载BFG jar(需要Java 6或以上)并运行以下命令:

$ java -jar bfg.jar --delete-files filename.orig my-repo.git

您的整个存储库历史将被扫描,任何名为filename的文件。origin(不在最近一次提交中)将被删除。这比使用git-filter-branch做同样的事情要容易得多!

完全披露:我是好心眼巨人回收清理器的作者。

这就是git filter-branch的设计目的。

如果这是你想要清理的最新提交,我尝试使用git版本2.14.3 (Apple git -98):

touch empty
git init
git add empty
git commit -m init

# 92K   .git
du -hs .git

dd if=/dev/random of=./random bs=1m count=5
git add random
git commit -m mistake

# 5.1M  .git
du -hs .git

git reset --hard HEAD^
git reflog expire --expire=now --all
git gc --prune=now

# 92K   .git
du -hs .git

这是最好的方法: http://github.com/guides/completely-remove-a-file-from-all-revisions

一定要先备份文件副本。

EDIT

Neon的编辑在审查过程中不幸被拒绝了。 请看下面的霓虹灯帖子,它可能包含有用的信息!


例如,删除所有不小心提交到git仓库的*.gz文件:

$ du -sh .git ==> e.g. 100M
$ git filter-branch --index-filter 'git rm --cached --ignore-unmatch *.gz' HEAD
$ git push origin master --force
$ rm -rf .git/refs/original/
$ git reflog expire --expire=now --all
$ git gc --prune=now
$ git gc --aggressive --prune=now

还是不管用吗?(我现在的git版本是1.7.6.1)

$ du -sh .git ==> e.g. 100M

不知道为什么,因为我只有一个主分支。无论如何,我终于得到了我的git回购真正清理了推到一个新的空的和裸露的git仓库,例如。

$ git init --bare /path/to/newcleanrepo.git
$ git push /path/to/newcleanrepo.git master
$ du -sh /path/to/newcleanrepo.git ==> e.g. 5M 

(是的!)

然后我把它克隆到一个新目录,并把它的。git文件夹移动到这个目录。如。

$ mv .git ../large_dot_git
$ git clone /path/to/newcleanrepo.git ../tmpdir
$ mv ../tmpdir/.git .
$ du -sh .git ==> e.g. 5M 

(是的!)终于清理干净了!)

在确认一切正常后,您可以删除../large_dot_git和../tmpdir目录(可能在几周或几个月后,以防万一……)