Как мне перебазировать суперпроект git, меняя хеши подмодулей? - PullRequest
0 голосов
/ 03 октября 2019

Фон

Предположим, у нас есть два репозитория git, один подмодуль другого (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

Вопрос

Все это сработало, но мне было интересно, есть ли более простой способ сделать это, так как я предполагаю, что меня назовутчтобы сделать это снова. Этот вопрос состоит из двух частей.

  1. Есть ли простой способ сказать git, что вы хотите, чтобы по умолчанию было edit вместо pick, не зависящее от редактора?
  2. Есть ли более простой способ заставить git делать то, что делает скрипт? Поможет ли мне сделать git lfs migrate import из суперпроекта?

1 Ответ

1 голос
/ 03 октября 2019

Есть ли простой способ сказать 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. Я не уверен, что это на 1020 * проще , но это более прямолинейно. Сам индексный фильтр будет состоять из использования git ls-files --stage аналогично тому, как вы это делаете, но, вероятно, сам по себе использует сгенерированный сценарий sed или awk. Сгенерированный sed, вероятно, будет быстрее, тогда как awk будет проще, особенно если у вас есть современный awk, где вы можете просто читать в хэш-отображении.

...