我不小心提交了一个不需要的文件(文件名。Orig而解决合并)到我的仓库几个提交前,没有我注意到它直到现在。我想从存储库历史记录中完全删除该文件。
是否有可能重写更改历史这样的文件名。奥里格从一开始就没有被添加到存储库中?
我不小心提交了一个不需要的文件(文件名。Orig而解决合并)到我的仓库几个提交前,没有我注意到它直到现在。我想从存储库历史记录中完全删除该文件。
是否有可能重写更改历史这样的文件名。奥里格从一开始就没有被添加到存储库中?
当前回答
我发现的最简单的方法是由leontalbot(作为评论)提出的,这是Anoopjohn发表的一篇文章。我认为有必要用自己的空间来回答:
(我将其转换为bash脚本)
#!/bin/bash
if [[ $1 == "" ]]; then
echo "Usage: $0 FILE_OR_DIR [remote]";
echo "FILE_OR_DIR: the file or directory you want to remove from history"
echo "if 'remote' argument is set, it will also push to remote repository."
exit;
fi
FOLDERNAME_OR_FILENAME=$1;
#The important part starts here: ------------------------
git filter-branch -f --index-filter "git rm -rf --cached --ignore-unmatch $FOLDERNAME_OR_FILENAME" -- --all
rm -rf .git/refs/original/
git reflog expire --expire=now --all
git gc --prune=now
git gc --aggressive --prune=now
if [[ $2 == "remote" ]]; then
git push --all --force
fi
echo "Done."
所有的功劳都归于Annopjohn和leontalbot,感谢他们指出了这一点。
NOTE
请注意,脚本不包括验证,因此请确保不会出错,并有备份以防出现错误。这招对我很管用,但对你可能就不管用了。小心使用它(如果你想知道发生了什么,请点击链接)。
其他回答
为了把它添加到Charles Bailey的解决方案中,我只是使用了git rebase -i来从之前的提交中删除不需要的文件,它就像一个魅力。 的步骤:
# Pick your commit with 'e'
$ git rebase -i
# Perform as many removes as necessary
$ git rm project/code/file.txt
# amend the commit
$ git commit --amend
# continue with rebase
$ git rebase --continue
当然,git filter-branch是正确的选择。
遗憾的是,这将不足以完全删除filename。来源于你的repo,因为它仍然可以被标签、reflog条目、遥控器等引用。
我建议删除所有这些引用,然后调用垃圾回收器。您可以使用本网站的git forget-blob脚本一步完成所有这些。
Git忘记blob filename.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 filter-branch的设计目的。