我有 git 存储库 A,它使用 B 作为子模块。
B 的历史记录在 LFS 迁移后已被重写,但如果 A 仍能使其整个历史记录正常运行,我会很高兴。 LFS 迁移后,我确实有子模块 B 的 OldSHA1 > NewSHA1 映射,现在我只想将 OldSHA1 gitlinks 重写到存储库 A 中的 NewSHA1。
我尝试在存储库 A 上运行 filter-repo 命令,并使用完整的 OldSHA1==>NewSHA1 映射作为参数,但它似乎没有获取 gitlinks。
我还尝试了过滤分支,如本线程中详细介绍的重写子模块历史后带有子模块的存储库,这似乎正在寻找我想要完成的确切事情。我尝试使用单个 OldSHA1=>NewSHA1 映射来执行此操作,这是我尝试运行的命令:
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
但我不断收到以下错误:
fatal: reference is not a tree: <NEWSHA1>
不知何故,git checkout似乎没有拾取子模块B的树。我什至尝试使用 git -C AbsolutePathToSubModule checkout 指定路径,但我得到了同样的错误。
那么,有几个问题:
感谢您提供有关如何实现此目标的任何帮助、建议和线索!
编辑1:
在评论中回答后,我将脚本编辑为:
git filter-branch --commit-filter '
if [ "$GIT_COMMIT" = <SpecificCommitID> ];
then
git update-index --add --cacheinfo 160000,<SpecificNewSha1>,<SubmodulePath>;
fi
git commit-tree "$@";
' HEAD
但是没有效果:(
WARNING: Ref 'refs/heads/develop' is unchanged
编辑2:
非常感谢用户@torek!这是一个可以帮助任何人入门的片段:
git filter-branch --index-filter '
if [ "$(git rev-parse --quiet --verify :<SUBMODULEPATH>)" = <OLDSHA1> ];
then
git update-index --cacheinfo 160000,<NEWSHA1>,<SUBMODULEPATH>;
fi' HEAD --all
从那时起,您必须循环所有 OLDSHA1/NEWSHA1 对,或使用 case) 字典,如下面的答案所示
再次非常感谢!
这个:
git filter-branch --commit-filter ' if [ "$GIT_COMMIT" = <SpecificCommitID> ]; then git update-index --add --cacheinfo 160000,<SpecificNewSha1>,<SubmodulePath>; fi git commit-tree "$@"; ' HEAD
不是您想要的,因为它测试 superproject 提交的哈希 ID。您需要在索引条目中测试子模块提交的哈希ID,例如:
if [ "$(git rev-parse --quiet --verify :SubmodulePath)" = oldhash ]; then ...; fi
当然,必须测试所有旧的重写子模块哈希 ID 才能通过映射函数运行它们。
(这在过滤器存储库中肯定会更容易,您可以在其中使用字典查找。)
如果您使用:
sm_hash=$(git rev-parse :submodule-path)
或类似于前缀测试,请记住考虑索引中不存在子模块路径的情况,以便
:submodule-path
无法正确解析。我认为--quiet --verify
会在这里做正确的事情(安静地不产生输出),但值得首先测试。一旦获得哈希值,您就可以执行以下操作:
case $sm_hash in
old1) new=new1;;
old2) new=new2;;
...
oldN) new=newN;;
*) new=$sm_hash
esac
作为默认的穷人字典查找,但如果子模块哈希未更改或为空,您将需要跳过更新子模块哈希。
shamap
文件中,
git filter-branch --setup '
declare -A newsha
while read old new; do newsha[$old]=$new; done <shamap
' --index-filter '
if oldsha=`git rev-parse :submodulepath 2>&-`
then git update-index --cacheinfo 160000,${newsha[$oldsha]-$oldsha},submodulepath
fi
'
如果您使用的是 Mac,则需要 来解决被忽视的 GNU 安装中的问题之一。
declare -A ...
,将不起作用。
git filter-branch
是 Bourne shell 脚本(请参阅https://github.com/git/git/blob/a82fb66fed250e16d3010c75404503bea3f0ab61/git-filter-branch.sh#L1),并且 Bourne shell 没有关联数组。