Запуск фильтра-ветки по целому ряду коммитов
git filter-branch --env-filter '
export GIT_AUTHOR_EMAIL="[email protected]"
export GIT_AUTHOR_NAME="foo"' -- commita..commitb
Результаты в Which ref do you want to rewrite?
Итак, кажется, что filter-branch
не позволяет использовать использование нотации диапазона в диапазоне между двумя произвольными ссылками.
Каков самый прямой способ запуска фильтра по целому ряду последовательных коммитов (где-то в истории ветки), если этот подход невозможен.
Ответы
Ответ 1
Самое чистое решение, которое я нашел, это сделать следующее:
- Создайте временную ветвь в
refb
.
- Примените фильтр ветвления к
refa..temp
.
- Восстановите временную ветку и удалите ее.
е.
git branch temp refb
git filter-branch --env-filter '
export GIT_AUTHOR_EMAIL="[email protected]"' refa..temp
git rebase temp
git branch --delete temp
Ответ 2
Вы не можете применить ответвление фильтра в середине истории, как говорит @kan. Вы должны подать заявку от вашего известного коммита до конца истории
git filter-branch --env-filter '...' SHA1..HEAD
Фильтр-ветвь может проверять автора коммита или другую информацию, выбирать, менять или нет коммит, поэтому есть способы выполнить то, что вы хотите, см. https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History, поищите "Изменение адресов электронной почты глобально"
Помните: если вы отправили коммиты в публичный репозиторий, вы не должны использовать filter-branch пользователя
Ответ 3
git filter-branch
выполняет принятие нотации диапазона, но конец диапазона должен быть ссылкой, а не идентификатором фиксации.
git checkout -b tofilter commitb
git filter-branch .... commita..tofilter
Если заданы только коммиты, он не будет знать, что нужно обновить с фильтрованной веткой.
Ответ 4
Включите команды фильтрации в if-statement, который проверяет этот диапазон. Вы можете проверить, находится ли коммит в заданном диапазоне с помощью этой команды:
git rev-list start..end | grep **fullsha**
Текущая фиксация будет сохранена в $GIT_COMMIT
в вашем фильтре. Таким образом, ваш фильтр будет выглядеть следующим образом:
git filter-branch --env-filter '
if git rev-list commita..commitb | grep $GIT_COMMIT; then
export GIT_AUTHOR_EMAIL="[email protected]"
export GIT_AUTHOR_NAME="foo"
fi' -- ^commita --all
Если вы хотите переписать только текущую ветвь, замените --all
на HEAD
Ответ 5
Вы не можете просто переопределить фиксации в середине истории, потому что sha1 фиксации зависит от родительского. Таким образом, git не знает, где вы хотите указать ссылку HEAD после фильтрации. Итак, вы должны переписать все до HEAD.
Пример:
A---B---C---D---E---F master
\
\--G---H branch
если вы хотите, чтобы фильтр комментирует B и C, вы также должны фильтровать все фиксации после: D, E, F, G, H.
Итак, почему git говорит вам использовать ref в конце диапазона, чтобы он просто не заканчивался отсоединенной головкой.
После того, как вы измените фиксации B и C и остановитесь, это будет выглядеть так:
A---B---C---D---E---F master
\ \
\ \--G---H branch
\-B'--C' (HEAD or a temporary TAG?..)
Итак, master
и branch
будут не затронуты. Я не думаю, что это то, чего ты хочешь.
Это означает, что вы должны переопределить все фиксации. История будет следующей:
A---B---C---D---E---F (loose end, will be garbage collected one day)
\ \
\ \--G---H (loose end, will be garbage collected one day)
\-B'--C'--D'--E'--F' master
\
\--G'--H' branch
Ответ 6
Я делаю это так.
Предположим, вы хотите отфильтровать содержимое ветки с именем branch-you-are-filtering.
Предположим, что в этой ветке есть предок, с ref ref-for-commit-to-stop-at.
git filter-branch --commit-filter 'YOUR_FILTER_COMMANDS' branch-you-are-filtering...ref-for-commit-to-stop-at
После выполнения, фиксация в ref-for-commit-to-stop-at не будет изменена. Все отфильтрованные\измененные фиксации в ветки ветки - вы-фильтрация будут основаны на ref-for-commit-to-stop-at.
Независимо от того, используете ли вы -commit-filter или что-то еще, вы не можете.
Ответ 7
Решение от @Acron мне кажется неправильным. Я бы предложил следующее для переключения между refa и refb, включая оба хэша:
git tag master.bak
git reset --hard refa
git filter-branch --env-filter '
export GIT_AUTHOR_EMAIL="[email protected]"' refa^..master
git cherry-pick refb..master.bak
git tag -d master.bak
Ответ 8
Используйте фильтр-ветвь --setup
parm и немного мощности оболочки:
git filter-branch --setup '
for id in 'git rev-list commitA..commitB'; do
eval filterfor_$id=rewrite
done
rewrite() {
GIT_AUTHOR_NAME="Frederick. O. Oosball"
[email protected]
}
' --env-filter 'eval \$filterfor_$GIT_COMMIT'