Git Quandries

Diverting Fork

I have a fork of a repo that has diverged.

I want to push all changes except for those that involve a particular folder.

To the original repo and rebase the fork on the old repo to ensure version control integrity.

Solution: Pushing Fork Changes to Upstream Without a Folder Using git filter-repo

Prerequisites

Install git-filter-repo if you don't have it:

pip install git-filter-repo

Verify it's available:

git filter-repo --version

Step 1: Create a Working Branch

Create a local copy of your fork's branch to rewrite — never rewrite directly on your main branch:

git checkout -b filtered-changes origin/main

Step 2: Run filter-repo to Remove the Folder

Rewrite the branch, stripping all changes to the excluded folder:

git filter-repo --path path/to/excluded-folder --invert-paths

What this does

  • --path targets the specified folder
  • --invert-paths inverts the selection, meaning everything except that folder is kept
  • Commits that only touched the excluded folder are dropped entirely
  • Commits that touched the excluded folder and other files are kept, but with the folder changes removed
  • Commit hashes will all change since history is being rewritten

Step 3: Verify the Result

Check that the excluded folder doesn't appear in the rewritten history:

# Confirm the folder is absent from the working tree
ls path/to/excluded-folder  # should not exist or be empty

# Scan the entire rewritten history for any trace of the folder
git log --all --full-history -- path/to/excluded-folder
# Should return nothing

Also sanity-check the commit log looks right:

git log --oneline

Step 4: Re-add the Upstream Remote

filter-repo removes remotes as a safety measure during rewriting. Re-add them:

git remote add upstream https://github.com/original/repo.git
git remote add origin https://github.com/your-fork/repo.git

Step 5: Push to Upstream

Push the filtered branch to upstream:

git push upstream filtered-changes

Then open a pull request from filtered-changes into the upstream repo's main branch.

Step 6: Rebase Your Fork onto Upstream

Once upstream merges your PR, sync your fork so history stays clean:

git fetch upstream
git checkout main
git rebase upstream/main

Handling conflicts in the excluded folder

The excluded folder will likely conflict here since your fork still has those changes. Keep your fork's version:

# If conflicts arise:
git checkout --ours path/to/excluded-folder
git add path/to/excluded-folder
git rebase --continue

Step 7: Force Push the Fork

git push origin main --force-with-lease

--force-with-lease is preferred over --force as it will refuse to push if the remote has been updated by someone else since your last fetch, preventing accidental overwrites.

Summary

StepCommandPurpose
Install toolpip install git-filter-repoGet filter-repo
Create branchgit checkout -b filtered-changes origin/mainSafe working copy
Strip foldergit filter-repo --path <folder> --invert-pathsRewrite history
Verifygit log --all --full-history -- <folder>Confirm folder is gone
Re-add remotesgit remote add ...Restore after filter-repo
Pushgit push upstream filtered-changesSend to upstream
Rebase forkgit rebase upstream/mainSync fork
Force push forkgit push origin main --force-with-leaseUpdate fork remote