TL; DR
Если они действительно есть, вы можете просто запустить вторую бездействующую ветвь фильтра с --prune-empty
, чтобы отбросить их.
Long, с экспериментом
После этого у меня все еще есть некоторые коммиты, которые имеют отношение только к теперь удаленным файлам.
Это должно быть редко, потому что вы включили:
--prune-empty
, который предписывает filter-branch
пропустить любой простой (не объединяющий) коммит, соответствующий его родителю.
Возможно, у вас есть некоторые слияния, которые объединяют две ветви, которые в остальном идентичныв их входных точках, но эти коммиты не могут быть удалены, потому что они объединяют ветви, которые в остальном идентичны.
Предположим, например, что у нас есть следующая структура ветвей до фильтрации:
B--C
/ \
...--o--A M--o--...
\ /
D--E
Commit M
является слиянием и должен быть сохранен (так оно и есть), но предположим, что A
-vs- B
сворачивается, потому что после фильтрации B
соответствует A
и C
-vs-B
(или vs- A
) также разрушается в течениеПо той же причине:
...--o--A'-----M'-o--...
\ /
D'-E'
(отметки или простые символы после букв указывают на то, что это копии оригинальных коммитов - возможно A'
- A
, если ничего не изменилось ранее, но это охватывает более общий случай).Здесь M
действительно все еще требуется для поддержания логической структуры, даже если бы было возможно выполнить ускоренную перемотку вперед, если бы коммиты были сделаны без изначально удаленных файлов.
Более интересный случайкогда D
и E
сами исчезают, потому что теперь M
все еще существует в качестве входных данных для процесса ответвления фильтра, и у него все еще есть два родителя, но оба родителя отображают для принятия A'
самого себя .Я не уверен, не глядя, что здесь происходит: может ли filter-branch сделать коммит слияния с A'
, указанным дважды как два родителя для M'
?Если это попытается сделать это, git commit-tree
записывает коммит M'
как обычный коммит без слияния?Тестирование говорит «нет»:
$ mkdir mtest
$ cd mtest
$ git init
Initialized empty Git repository in ...
$ echo test commit-tree > README
$ git add README
$ git commit -m initial
[master (root-commit) 1db1f76] initial
1 file changed, 1 insertion(+)
create mode 100644 README
$ echo log msg | git commit-tree -p HEAD -p HEAD HEAD^{tree}
error: duplicate parent 1db1f76a4e7217d5198c0f178464b7a087e94078 ignored
44f91061b7bd08c39a4dc9e8ebb1f4f7c588ea9e
Таким образом, получается, что наивный filter-branch
попытается сделать M'
и сделает это как однопользовательский коммит:
...--o--A'-M'-o--...
гдеM'
и A'
не имеют различий.Код ветки фильтра имеет проверку для этого:
for parent in $parents; do
for reparent in $(map "$parent"); do
case "$parentstr " in
*" -p $reparent "*)
;;
*)
parentstr="$parentstr -p $reparent"
;;
esac
done
done
(Если вы предоставите свой собственный родительский фильтр, это произойдет после проверки, и вам потребуется ваша собственная повторная проверка.)
Так что, если вы получаете такой результат ...--A'-M'-...
, вторая ветвь фильтра с --prune-empty
отбросит их.