gitrebasegit-rebasegit-rewrite-historygit-branch-sculpting

Git interactive-rebase across multiple branches


I have a git repo that has a source file containing some sensitive content which I wish to remove (I don't want to delete the file, just amend its contents). The commit was pretty early on in the project development (when we only had a single branch), but now finds its self in n other branches.

Is there any git-fu I can run to clean it in all branches? An interactive rebase only works one Head at a time.

I did find this command over at github:

git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch DotNet/src/ExternalLibs/GemBox/' \
--prune-empty --tag-name-filter cat -- --all

but it only works for deletions, not amendments.

A-B-C-**STUPID**-D-E-F
                    \
                     \-G-H-I
                          \-J-K

Solution

  • Assuming that the amended content is not also sensitive, then this might work: checkout a new branch at the commit that you want to amend, amend the file, then use a non-interactive rebase that preserves merges of everything after the previously un-amended commit back onto the new amended commit:

    # Checkout a branch "fix" at the commit STUPID
    git checkout -b fix STUPID
    
    # Make your file changes...
    
    # Amend STUPID
    git add .
    git commit --amend -m "REDACTED MWA-HA-HA!"
    
    # Do the BIGGEST rebase that you'll probably ever do in your entire life!
    git rebase --preserve-merges --onto fix STUPID master
    # or `-p` for short
    git rebase -p --onto fix STUPID master
    
    # Verify that the only difference between master and master@{1}
    # is the amended content:
    git diff master@{1} master
    

    Once you've verified that the only difference between master before and after the rebase is the amended content, you'll probably want to purge your local and remote repos of the old commits by expiring your reflog and running git gc:

    git reflog expire --expire=now --all
    git gc --prune=now
    

    You can read about any other cleanup steps that you might need to do at the following:

    1. Remove sensitive files and their commits from Git history.
    2. GitHub: Remove sensitive data.

    By the way, please test the rebase on another local clone first before you try this on the only copy of your repo that you have...in case something goes wrong.

    Oh yeah, I almost forgot, if your amendment at STUPID causes conflicts with the commits that are being rebased on top of it, you'll need to fix those conflicts during the rebase.

    This 1337 git-fu brought to you courtesy of Cupcake: Performing open-heart surgeries on git repos since 2012 ;)