Search code examples
gitgit-filter-branchgit-subtreegit-rewrite-history

Remove commits which aren't in subtree nor in original repository


I actually have two repositories:

  • main
  • external

The main repository was merged after some time into external/main directory (as subtree). Now I'd like to migrate the changes made to external/main back to main repository, but only these commits and no other unrelated commits like to external/<anything-else>.

I've actually tried the classical:

git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter main -- --all

but that removes all the commits made to the initial main repository too and only leaves the ones which were made in the external git repository.


So: how to retain only the commits:

a) made to the initial main repository

and

b) made to the subtree of external (external/main)


When I try git pull -s subtree ../external, the commits are all merged, including commits which didn't change anything in the subtree. I'd like to have only the commits which actually changed something in the subtree and there also only the information about files from the subtree.


Solution

  • You should be able to limit the commits rewritten by filter-branch using --not --remotes in the <rev-list options> section of your command:

    git filter-branch --tag-name-filter cat --prune-empty
        --subdirectory-filter main -- --all --not --remotes
    

    This will cause filter-branch not to include commits reachable from your remote branches. If you have multiple remotes, you can use something like --remotes=origin to specify which one to consider.