Это следует за этим июньским потоком 2018 года , где оно сообщается как "git rm bug
"
TLDR;это не ошибка.
Никакая команда Git не должна вести себя так, чтобы при переходе от коммита X
к Y
дерево оставалось в таком состоянии, чтобы вы не получили тот же Y
если вы клонировали.
В теме:
ОБЗОР
"git rm
" удалит больше файлов, чем указано.Это либо ошибка, либо недокументированное поведение (не на страницах руководства).
SETUP
В репозитории git создайте пустой каталог ИЛИ цепочку пустых каталогов
$ mkdir -p path / to / some /
Создайте файл в самом глубоком каталоге и добавьте его в список отслеживания
$ touch path /в / some / file $ git add path / в / some / file $ git commit -m 'add path / to / some / file'
THE BUG
Запустите 'git rm
' для отслеживаемого файла.
ОЖИДАЕМОЕ ПОВЕДЕНИЕ
$ git rm path/to/some/file
rm 'path/to/some/file'
$ ls path
to/
$ ls path/to
some/
Обратите внимание, что path/
, path/to/
и path/to/some/
все еще существуют.
АКТУАЛЬНОЕ ПОВЕДЕНИЕ
$ git rm path/to/some/file
rm 'path/to/some/file'
$ ls path
ls: cannot access 'path': No such file or directory
Вся цепочка пустых каталогов удаляется, несмотря на то, что git выводит только "rm 'path/to/some/file'
".
Это ТОЛЬКО происходит, когда все каталоги в цепочке пусты после удаления отслеживаемого файла.
Это поведение НЕ задокументировано на страницах руководства.
Я предлагаю добавить операторы 'rmdir' в вывод 'git rm' или обновить страницы руководства, чтобы отразить это поведение.
Общий принцип таков:
Git не может отслеживать пустые каталоги.
Так как это было only содержимым во всей этой иерархии, всяиерархия должна была быть удалена.
Похоже, что это поведение было в течение многих лет, так как d9b814cc97 ("Добавить встроенную" команду git rm "", 2006-05-19,Git v1.4.0-rc1).
Интересно, что Линус отметил в сообщении коммита, чтоудаление ведущих каталогов отличалось от того, когда git-rm
был сценарием оболочки.
И он задался вопросом, может быть, стоит иметь возможность контролировать это поведение.
Я полагаю, что большинство пользователей либо хотят текущийповедение или они редко сталкиваются с этим и удивляются, учитывая, как долго git rm
работал таким образом.
Это также согласуется с другими частями Git, которые удаляют файлы.Например, «git checkout
» до состояния, в котором нет файла, удалит ведущие каталоги (если они, конечно, пусты).
В более общем случае:
Я собираюсь быть противоречивым и упрямым и предположить, что текущее поведение в порядке, поскольку нет никаких убедительных причин для любого другого поведения.
Неизменно, каждая защита для подвешиванияопустошение каталогов сводится к тому, что «в будущем я могу сделать что-то, что ожидает, что эти каталоги будут существовать».
Ну, если это так, то создавайте их тогда, когда они вам нужны - ничего, что вы должны делать, просто не нужно предположим, существование необходимых каталогов.
Кроме того, "отслеживая" эти каталоги, вы предлагаете Git спокойно делать то, что обычно следует делать с помощью "git rm --cached
".
Если мне нужно такое поведение, я бы предпочел набрать его сам.
Например, чтобы проиллюстрировать, почему не удаление пустой папки было бы проблематичным:
Другие говорили, почему, но вот крайний случай, о котором вы, вероятно, не задумывались:
(
rm -rf /tmp/repo &&
git init /tmp/repo &&
cd /tmp/repo &&
mkdir -p foo/bar/baz &&
git status
)
Если у вас просто пустые каталоги, "git status
" ничего не сообщит, хотя "git clean -dxfn
"покажет, что будет очищено.
Так что, если это сработает, как вы предлагаете, тогда кто-нибудь может git rm
какой-то файл, тогда все сообщат, что они находятся на коммите XYZ
,но если бы они клонировали этот коммит, то получили бы дерево, которое выглядело бы иначе.
Никакая команда Git не должна вести себя так, чтобы при переходе из коммита * оставить дерево в состоянии, при котором вы не получите тот же Y
, если будете клонировать.
Примечание: официальный git rm
тест (git/git/t/t3600-rm.sh
) самого репозитория Git совершенно ясен относительно того, что он ожидает:
test_expect_success 'rm removes subdirectories recursively' '
mkdir -p dir/subdir/subsubdir &&
echo content >dir/subdir/subsubdir/file &&
git add dir/subdir/subsubdir/file &&
git rm -f dir/subdir/subsubdir/file &&
! test -d dir