Git ignore & changing the past
I only recently added a .gitignore
file to ignore some specific data files in a subdirectory of mine. I'd really like to go back in time and remove them from previous commits/history as wel开发者_开发知识库l.
Is this easily accomplished? Where/how should I start?
This will be a two-step procedure:
Introduce the .gitignore file
For this to work, the early commits are going to have to have your .gitignore
file. So, you need to:
- Check out the root commit:
git checkout -b temp $(git rev-list HEAD | tail -1)
- Add the
.gitignore
file. git commit --amend
- Rebase all of your existing branches onto "temp". This may or may not work seamlessly, so you might need to fiddle with it if any conflicts spring up.
- Check out your working branch and delete the temp branch.
Rewrite history
Now you can automatically remove these files from all of the branches by this command:
git filter-branch --tree-filter 'git clean -f -X' -- --all
This will rewrite all of your branches to remove ignored files. It may take a while depending on the size of your repository.
I've just done this and some of the other answers/comments nearly got me there, but I had to make some changes.
I've used filter-branch
to introduce my .gitignore
file at the start of history, and apply it to all previous commits.
This is the command:
git filter-branch --tree-filter 'git rm --cached -rf . >/dev/null ; cp ~/Desktop/new-gitignore .gitignore ; git add . ; git clean -d -X -f >/dev/null' -- --all
As you can see, it assumes you have a copy of the wanted .gitignore
file on your Desktop (~/Desktop/new-gitignore
).
I found that only after I've removed and re-added (git rm ...
, git add .
) all the files would git clean
remove all the files that the new .gitignore
is telling it to ignore. Notice its not necessary to add the files again after clean, as tree-filter
will just commit everything as is.
I've included >/dev/null
to reduce the output of the script, but you can safely remove this if you want to see the whole process.
See removing file from every commit section. It is exactly your case.
But be careful, as this feature as every history rewriting one DOES change every commit. So if you have public repository and someone could have based some work on it - it would lead to problems.
Look at something like below using filter-branch
git filter-branch --tree-filter 'rm -f passwords.txt' HEAD
http://progit.org/book/ch6-4.html
git filter-branch is a possible solution. Make sure you understand the implications before you utilize it, as the changes are permanent. You won't be easily able to merge your filtered branch with the old one.
git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' HEAD
Swap filename for the specific file you'd like gone.
精彩评论