A
将是超级项目,B
将是子模块)。项目A
本身不是源代码,而是一个收集和跟踪有关其子模块的信息的项目。 A
存储库很少(如果有的话)在本地计算机上存在,而是一堆脚本来对其进行更新。[一天,有人意识到回购B
应该更好地使用LFS,并使用git lfs migrate import
清理了回购。我有B
的旧哈希和新哈希的列表。
我做了什么
A
发生线性变化(无分支),所以我能够执行git rebase --root -i
,将所有提交更改为edit
,然后运行一个简单的bash脚本,将子模块重置为新的哈希值。这是脚本的示例:#!/bin/bash
#set the submodule path and input files
submodulePath=foo
newHashesFile=NewHashes.txt
originalHashesFile=OriginalHashes.txt
while [ (test -d "$(git rev-parse --git-path rebase-merge)" || test -d "$(git rev-parse --git-path rebase-apply)" ) ]; do
numLines=`git ls-files --stage | grep $submodulePath | wc -l`
if [ $numLines = 1 ];
then
oldHash=`git ls-files --stage | grep $submodulePath | sed -e 's/^160000 \([^ ]*\) 0.*$/\1/g'`
echo oldHash: $oldHash
else
echo merge conflict
oldHash=`git ls-files --stage | grep $submodulePath | grep '^160000 \([^ ]*\) 3.*' | sed -e 's/^160000 \([^ ]*\) 3.*$/\1/g'`
echo oldHash: $oldHash
fi
lineNumber=`grep -n $oldHash $originalHashesFile | sed -e 's/^\([^:]*\):.*/\1/g'`
newHash=`head -n $lineNumber $newHashesFile | tail -n 1`
if [ ! $lineNumber ];
then
echo Hash not changed
else
cd $submodulePath
git reset --hard $newHash
cd ../
fi
git add $submodulePath/
git commit --amend
git rebase --continue
done
问题所有这些都有效,但是我想知道是否有一种更简单的方法,因为我想我会被要求再次进行此操作。这个问题有两个部分。
是否有一种简单的方法告诉git您希望默认值为
edit
而不是pick
,而不依赖于编辑器?- 是否有一种更简单的方法告诉git执行脚本的作用?如果我在超级项目中执行了
git lfs migrate import
,会有所帮助吗?
是否有一种简单的方法告诉git您希望编辑默认值而不是选择内容,而不依赖于编辑器?
否。但是,有一种方法可以将命令序列编辑器设置为与其他编辑器不同的编辑器:设置环境变量GIT_SEQUENCE_EDITOR
。因此,例如,您可以执行:
GIT_SEQUENCE_EDITOR="sed -i '' s/^pick/edit/" git rebase -i ...
(假设您的sed
具有以这种方式工作的-i
,依此类推。]是否有一种更简单的方法告诉git来执行脚本的工作?鉴于您要更新每个gitlink哈希,我将使用
git filter-branch
(而不是git rebase
)来进行此操作,并使用--index-filter
进行gitlink哈希更新。我不确定这是否是simpler,但更直接。索引过滤器本身将使用与您执行此操作类似的方法来使用
git ls-files --stage
,但可能本身也会使用生成的sed
脚本或awk
脚本。 Generated-sed可能会更快,而awk可能会更简单,尤其是如果您有一个现代的awk,您可以在其中读取哈希映射。