I would like to replace the content of a file in all branches with the current visible version of that file. I have been trying something like this, but it does not work:
FILE_PATH="$1"
cp "$FILE_PATH" "/tmp/file_to_replace_in_git_history"
git filter-repo --path "$FILE_PATH" --force --blob-callback "
if filepath == b'$FILE_PATH':
with open('/tmp/file_to_replace_in_git_history', 'rb') as f:
blob.data = f.read()
"
rm "/tmp/file_to_replace_in_git_history"
I wondering, but I could not find any ready to use solution. Probably you have a better idea.
I want to remove encrypted files which could contain passwords etc, which should not be there. So the files are binary and should be replaced complete.
Replacing entire file content seems to be the area where git filter-repo
has problems. Blob callback doesn't know filename, --replace-text
can only replace line by line AFAIU.
I can solve your task with git filter-branch
. Yes, I know it's outdated and not recommended. It works on one branch at a time. I use --tree-filter
which is extra slow because it checks out every commit, updates it and commits it back. But still here is the working solution:
FILE_PATH="$1"
cp "$FILE_PATH" "/tmp/file_to_replace_in_git_history"
FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch --tree-filter "
cp '/tmp/file_to_replace_in_git_history' '$FILE_PATH'
" HEAD
rm "/tmp/file_to_replace_in_git_history"
After that run git log -- "$FILE_PATH"
— the log should contain only one commit, the initial commit.
Upd. Process all branches and copy tags:
FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch --tree-filter "
cp '/tmp/file_to_replace_in_git_history' '$FILE_PATH'
" --tag-name-filter cat -- --all