I have git repository A that uses B as a submodule.
B's history has been rewritten after an LFS migration, but I would love it if A could still have its entire history functional. After the LFS migration, I do have a mapping OldSHA1 > NewSHA1 for submodule B, and now I just want to rewrite OldSHA1 gitlinks to NewSHA1 in repo A.
I have tried to run a filter-repo command on the repo A with a full OldSHA1==>NewSHA1 mapping as parameter but it doesn't seem to pick up gitlinks.
I also tried filter-branch as detailed in this thread Repository with submodules after rewriting history of submodule that seems to be looking for the exact thing I am trying to accomplish. I tried doing this with a single OldSHA1=>NewSHA1 mapping, and here's the command I am trying to run:
git filter-branch --commit-filter '
if [ "$GIT_COMMIT" = <OLDSHA1> ];
then
cd <SUBMODULE_ABSOLUTE_PATH>;
git checkout <NEWSHA1>;
cd ..;
git add -u;
git commit -m "updated gitlink";
else
git commit-tree "$@";
fi' HEAD
But I keep getting the following error:
fatal: reference is not a tree: <NEWSHA1>
Somehow, git checkout doesn't seem to pick up the tree of submodule B. I even tried to specify a path with git -C AbsolutePathToSubModule checkout but I get the same error.
So, a few questions:
- Is there something obvious I'm doing wrong here?
- Is there a better way of accomplishing this? It seems like I "simply" want to replace a string with another somewhere in the object database, but I can't find a simple way to do that
- Is there a way to do this on the entire repo like filter-repo does? Or should I run this on every single branch.
Thanks for any help, advice, clue about how to accomplish this!
Edit 1:
After an answer in the comments, I edited my script to this:
git filter-branch --commit-filter '
if [ "$GIT_COMMIT" = <SpecificCommitID> ];
then
git update-index --add --cacheinfo 160000,<SpecificNewSha1>,<SubmodulePath>;
fi
git commit-tree "$@";
' HEAD
But it has no effect :(
WARNING: Ref 'refs/heads/develop' is unchanged
Edit 2:
Thanks a lot to user @torek! This is a snippet to help anyone get started:
git filter-branch --index-filter '
if [ "$(git rev-parse --quiet --verify :<SUBMODULEPATH>)" = <OLDSHA1> ];
then
git update-index --cacheinfo 160000,<NEWSHA1>,<SUBMODULEPATH>;
fi' HEAD --all
From then, you have to loop over all OLDSHA1/NEWSHA1 pairs, or use a case) dictionary as depicted in their answer below
Thanks again a lot!
git filter-branch, remember that you don't have the submodule at all, all you have is the gitlink. You must inspect the hash ID of the gitlink (stored in Git's index in the given path name: usegit rev-parseto retrieve it from the index) and if it's one of the ones to replace, usegit update-indexto shove the corrected gitlink into position. The rest, thegit filter-branchcode will handle on its own.git update-index --cacheinfo 160000,<NewSha1>,<SubmodulePath>but i'm gettinggit update-index: --cacheinfo cannot add <SubmodulePath> ; cannot add to the index - missing --add option?when I do it in my script. And that still triggers with ---add