Подтвердить что ты не робот

Автоматически удалять файлы *.pyc и в противном случае - пустые каталоги при проверке новой ветки

Итак, интересная ситуация при использовании git и python, и я уверен, что это происходит и для других ситуаций.

Скажем, я создаю репозиторий git с папкой /foo/. В этой папке я помещаю /foo/program.py. Я запускаю program.py и program.pyc. У меня есть *.pyc в файле .gitignore, поэтому git не отслеживает его.

Теперь позвольте сказать, что я делаю другую ветку, dev. В этой ветки dev я полностью удаляю папку /foo/.

Теперь я переключаюсь обратно на главную ветку и/foo/появляется снова. Я запускаю program.py и снова появляется файл program.pyc. Все хорошо.

Я возвращаюсь обратно в свою ветвь dev. Каталог/foo/должен исчезнуть. Он существует только в ветки мастера, а не в ветки dev. Однако он все еще существует. Зачем? Поскольку проигнорированный файл program.pyc предотвращает удаление папки при переключении ветвей.

Решение этой проблемы - это рекурсивно удалить все *.pyc файлы перед переключением ветвей. Я легко могу сделать это с помощью этой команды.

find . -name "*.pyc" -exec rm '{}' ';'

Проблема заключается в том, что досаждать нужно помнить, чтобы делать это почти каждый раз, когда я меняю ветки. Я мог бы сделать псевдоним для этой команды, но тогда мне все равно придется помнить, чтобы вводить его каждый раз, когда я меняю ветки. Я мог бы также сделать псевдоним для git -branch, но и ничего хорошего. Команда ветвления git выполняет другие действия, кроме изменений ветвей изменений, и я не хочу удалять все файлы pyc каждый раз, когда я их использую. Черт, я бы даже использовал его в нерепитоне, то что?

Есть ли способ установить крюк git, который выполняется только при изменении ветвей? Или есть какой-то другой способ, чтобы все *.pyc файлы удалялись всякий раз, когда я переключаю ветки?

4b9b3361

Ответ 1

Существует крючок post-checkout, который должен быть помещен в .git/hooks/post-checkout. Там, вероятно, есть образец, возможно, названный .sample или, возможно, не исполняемый, в зависимости от вашей версии git. Краткое описание: он получает три параметра: предыдущий HEAD, новый HEAD и флаг, который равен 1, если ветвь изменена, и 0, если это всего лишь проверка файла. См. man githooks для получения дополнительной информации! Вы должны иметь возможность написать оболочку script, чтобы сделать то, что вам нужно, и поместить ее туда.

Изменить: Я понимаю, что вы ищете эту предварительную проверку, так что проверка автоматически очищает каталоги, которые становятся пустыми. Нет никакого крючка предварительной проверки, поэтому вам придется использовать ваш script, чтобы удалить каталоги.

Другое примечание: Псевдонимы являются частью gitconfig, которые могут быть локальными для репозитория (в .git/config, not ~/.gitconfig). Если вы решите сделать это с помощью псевдонимов (для git -checkout, а не git -branch), вы можете легко разместить их только в репозиториях, связанных с python. Также в этом случае я сделал бы псевдоним специально для этой цели (например, cc для проверки очистки). Вы можете использовать checkout (или другую псевдониму), если вы не хотите очищать файлы pyc.

Ответ 2

Просто скопируйте и обновите хорошее решение от Apreche, которое было похоронено в комментариях:

Сохраните эту оболочку script в файл /path/to/repo/.git/hooks/post-checkout и сделайте ее выполнимой.

#! /bin/sh

# Start from the repository root.
cd ./$(git rev-parse --show-cdup)

# Delete .pyc files and empty directories.
find . -name "*.pyc" -delete
find . -type d -empty -delete

Ответ 3

Другой вариант - не решить эту проблему как проблему git вообще, а как проблему Python. Вы можете использовать переменную окружения PYTHONDONTWRITEBYTECODE, чтобы в первую очередь не писать Python файлы .pyc. Тогда вам нечего будет убирать, когда вы переключаете ветки.

Ответ 4

Мое решение более совместимо с git: Git удаляет только каталоги enpty, где какой-либо файл был удален путем проверки. Он не ищет полное дерево обработки. Это полезно для больших репозиториев или репозиториев с очень большим игнорируемым деревом, например виртуальными средами, через tox пакет для тестирования многих разных версий Python и т.д..

Моя первая реализация очень четко объясняет принцип: Очищаются только файлы pyc , связанные с файлами с контролем версий. Это по соображениям эффективности и нежелательных побочных эффектов.

#!/bin/bash
# A hook that removes orphan "*.pyc" files for "*.py" beeing deleted.
# It doesn not clean anything e.g. for .py files deleted manually.
oldrev="$1"
newrev="$2"
# ignored param: branchcheckout="$3"

for x in $(git diff --name-only --diff-filter=DR $oldrev..$newrev | grep "\.py$")
do
    if test -a ${x}c && ! test -a ${x}; then
        rm ${x}c
    fi
done

Крючок post-checkout получает три полезных параметра, которые позволяют точно узнать, какие файлы были удалены с помощью git checkout, без поиска полного дерева.

После прочтения вопроса я переписал код своего крючка на Python и расширил его в соответствии с вашими требованиями о пустых каталогах.

Мой полный короткий исходный код (Python) находится в
https://gist.github.com/hynekcer/476a593a3fc584278b87#file-post-checkout-py

Строка doc:

"""
A hook to git that removes orphan files "*.pyc" and "*.pyo" for "*.py"
beeing deleted or renamed by git checkout. It also removes their empty parent
directories.
Nothing is cleaned for .py files deleted manually or by "git rm" etc.
Place it to "my_local_repository/.git/hooks/post-checkout" and make it executable
"""
  • Проблема с файлами *.pyc не важна для Python 3, потому что файлы *.pyc в __pycache__ не могут быть выполнены без связанного *.py * файла в его родительский каталог.

  • Никакой каталог изменений не требуется, поскольку в корне репозитория каждый раз запускаются крючки.

  • Кэш-каталоги для скомпилированного кода __pycache__ полностью очищаются, потому что они никогда не важны (не участвуют в любом бинарном дистрибутиве), а также для высокой эффективности, поскольку удаление по частям __pycache__/some_name.*.pyc может быть медленным.