Search code examples
pythonbashgitgit-filter-repo

git-filter-repo loses the remotes


I previously got this rewrite of history commit messages to work:

#!/bin/bash

# Create a temporary file to store the commit messages
temp_file=$(mktemp)

main_head_hash=$(git rev-parse main)
suffix="⚠️ rebased since!"
# Use git log to retrieve the commit messages and store them in the temporary file
git log --pretty=format:%s $main_head_hash.. | grep '📌 build version' | grep -v "$suffix" > $temp_file

# Create a file to store the replacements
echo > replacements.txt

# Iterate over the commit messages in the temporary file
while read commit_message; do
  # Print the replacement message to the replacements.txt file
  echo "$commit_message==>$commit_message $suffix" >> replacements.txt
done < $temp_file

# # ⚠️⚠️ Rewriting history ⚠️⚠️
git filter-repo --replace-message replacements.txt --force

# # Remove the temporary files
rm $temp_file
rm replacements.txt

but I have no began to notice that it causes my git repo to lose the remotes setup. Af first I thought it was some other git tool I was using, but now I have this script being the suspect 🕵️

How do I avoid losing the remotes?


Solution

  • Removing the remote is by design. Quote from the author:

    filter-repo defaults to rewriting the whole repository and as such it creates history incompatible with the original. There are lots of things that can go wrong with pushing a rewritten history back up to the original location, something that other tools did not discuss or warn about in detail and which will trip up many people. Removing the origin remote helps avoid these errors; it is encouragement for folks to stop and read the docs to make sure they are prepared and understand the ramifications (and take appropriate preventative steps) before they do something that may bite them. (They can still push to the remote by just setting it back up, can just re-fetch, etc., so it's easy to circumvent, but I want them to at least notice something is different).

    Note it's easy to add the remote back:

    git remote add <repo-url-here>
    

    Or, you can also use the --refs or --partial options to avoid removing it during the filter. Note these options do more than just "not removing the remote", so you should decide whether they are acceptable to you:

    --partial

    Do a partial history rewrite, resulting in the mixture of old and new history. This implies a default of update-no-add for --replace-refs, disables rewriting refs/remotes/origin/* to refs/heads/*, disables removing of the origin remote, disables removing unexported refs, disables expiring the reflog, and disables the automatic post-filter gc. Also, this modifies --tag-rename and --refname-callback options such that instead of replacing old refs with new refnames, it will instead create new refs and keep the old ones around. Use with caution.

    --refs <refs+>

    Limit history rewriting to the specified refs. Implies --partial. In addition to the normal caveats of --partial (mixing old and new history, no automatic remapping of refs/remotes/origin/* to refs/heads/*, etc.), this also may cause problems for pruning of degenerate empty merge commits when negative revisions are specified.