[git filter-branch ... --all
] фильтрует только главную ветвь, а не orgin / branch ...
Это нормально и желательно, поскольку имена origin/
не являютсяна самом деле ветвь имен вообще.(Git называет их названиями веток для удаленного отслеживания , что, мне кажется, звучит слишком похоже на "имена веток" - в конце концов, там есть фраза "имя ветки"! - поэтому я решил их назвать«имена для удаленного отслеживания», помогающие их различать.)
Имя для удаленного отслеживания - это память вашего Git некоторой другой ветви Git.Когда вы используете git filter-branch
, вы говорите своему Git скопировать коммиты в вашем репозитории, вносить некоторые изменения непосредственно перед фиксацией копий, а затем обновлять ваши имена веток, чтобы они указывали на новые скопированные -предположительно новые и улучшенные - коммиты вместо оригинальных (старых и паршивых?) коммитов.
Ваш последующий git push --force --all
просит ваш Git отправить в Git все имена ваших веток и соответствующий им коммитхэш-идентификаторы, а также любые ваши коммиты, которых нет у origin
, которые необходимы для того, чтобы все это работало.Затем ваши команды Git (--force
) их Git устанавливают свои имена ветвей так же, как ваши, то есть указывают на скопированные, новые и улучшенные коммиты.Если они примут эту команду, ваш Git обновит ваши имена для удаленного отслеживания.
В общем, вы хотите найти все ваши имена для удаленного отслеживания, соответствующие их именам ветвей:
git for-each-ref refs/remotes/origin # add --format options as appropriate
и используйте эти имена, чтобы убедиться, что у вас есть ваши собственные имена ветвей, указывающие на тот же коммит, что и эти имена для удаленного отслеживания.Нижеследующее не проверено, поэтому сначала проверьте его.Он также на самом деле не терпит неудачу , когда что-то не так (потому что prog | while ...
делает это слишком сложно), он просто печатает предупреждения.
git for-each-ref --format='%(refname)' refs/remotes/origin |
while read name; do
shortname=${name#refs/remotes/}
localname=${name#refs/remotes/origin/}
# if we have a branch named $localname, make sure it
# identifies the same commit as $name. If not, create
# one pointing to $name.
fullname=refs/heads/$localname # use full name in case of tags etc
if hash=$(git rev-parse $fullname); then
if test $hash != $(git rev-parse $name); then
echo "WARNING: local branch $localname differs from $shortname"
else
echo "local branch $localname is good (matches $shortname)"
fi
else
echo "creating local branch $localname to match $shortname"
# NB: you can add --track here but that is the default anyway
if ! git branch $localname $name; then
echo "WARNING: failed to create $localname"
fi
fi
done
Теперь у вас есть ветвь на удаленныйотслеживание веток (плюс любые ваши собственные ветки, которые не имеют имен для удаленного отслеживания). Теперь ваш --all
на вашем filter-branch
будет делать то, что вы хотите.
Есть еще одна проблема, возможно незначительная или не относящаяся к делу.Ваша ветвь фильтра говорит:
... --tag-name-filter cat ...
, что говорит вашему git filter-branch
обновить любой из ваших тегов.Но ваш окончательный git push
говорит git push --force --all
, а --all
в git push
означает толкать все ветви , а не толкать все ветви и теги .Если ваш git filter-branch
обновил некоторые теги , вы, вероятно, также должны их подтолкнуть.
Обратите внимание, что изменение тегов в общедоступных репозиториях, как правило, плохая идея, так как сложно убедиться, что вседругие пользователи этих репозиториев, чтобы выбрать новые значения тегов, которые соответствуют существующим именам тегов.Однако, если это уместно, нужно сделать это и просто предупредить всех пользователей из этого публичного хранилища о том, что теги изменились.