当我签出一个新的分支时,自动删除* .pyc文件和其他空的目录

所以在使用git和python的时候,这里有一个有趣的情况,而且我确定它也发生在其他情况下。

比方说,我做了一个文件夹/ foo /的git回购。 在那个文件夹里我放了/foo/program.py。 我运行program.py并创build了program.pyc。 在.gitignore文件中有* .pyc,所以git不会跟踪它。

现在让我们说我做另一个分支,开发。 在这个开发分支中,我完全删除了/ foo /文件夹。

现在我切换回主分支,/ foo /重新出现。 我运行了program.py并重新显示了program.pyc文件。 一切都很好。

我切换回我的开发分支。 / foo /目录应该消失。 它只存在于主分支,而不是开发分支。 但是,它仍然存在。 为什么? 因为忽略的program.pyc文件会阻止在切换分支时删除该文件夹。

解决这个问题的方法是在切换分支之前recursion地删除所有* .pyc文件。 我可以用这个命令轻松做到这一点。

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

问题是,几乎每次我改变分支时,都要记住这么做是令人讨厌的。 我可以为这个命令做一个别名,但是我每次改变分支时都必须记得input它。 我也可以为git分支做一个别名,但这也不好。 除了改变分支之外,git分支命令还有其他的一些function,我不想每次使用它时都删除所有的pyc文件。 哎呀,我甚至可能用它在一个非python回购,那么是什么?

有没有办法设置一个只有当我更改分支时执行的git钩子? 或者有什么其他的方式来设置所有* .pyc文件擦除每当我切换分支机构?

有一个post-checkout钩子,放在.git / hooks / post-checkout中。 这里可能有一个示例,可能命名为.sample或可能不可执行,取决于你的git版本。 简短描述:它得到三个参数,前面的HEAD,新的HEAD,和一个标志,如果分支改变为1,如果只是一个文件签出,则为0。 请参阅man githooks了解更多信息! 你应该可以写一个shell脚本来做你需要的东西并把它放在那里。

编辑:我知道你正在做这个预结帐,所以结帐自动清理目录变成空的。 虽然没有预先签出钩子,所以您必须使用脚本来删除目录。

另一个注意事项:别名是gitconfig的一部分,它可以是一个仓库的本地(在.git / config中,而不是〜/ .gitconfig)。 如果你select使用别名(对于git-checkout而不是git-branch),你可以很容易地把它们放在python相关的仓库中。 此外,在这种情况下,我会为此专门制作一个别名(例如cc for checkout clean)。 如果你不想清理pyc文件,你仍然可以使用checkout(或其他别名forms)。

只是复制并更新了Apreche的一个很好的解决scheme,它被埋在了评论中:

将这个shell脚本保存到文件/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 

另一个select是不要把它解决为git问题,而是作为一个Python问题。 您可以使用PYTHONDONTWRITEBYTECODE环境variables来防止Python首先编写.pyc文件。 那么当你切换分支时,你将不会有任何东西需要清理。

我的解决scheme与git更兼容 :Git只删除通过结帐删除任何文件的enpty目录。 它不search完整的工作拷贝树。 这对于有大型忽略树的大版本库或存储库很有用,比如tox包的虚拟环境,用于testingPython版本的许多不同的版本等。

我的第一个实现非常清楚地解释了原理:只有与版本控制下的文件相关的 pyc文件才被清除。 这是出于效率和不必要的副作用的原因。

 #!/bin/bash # A hook that removes orphan "*.pyc" files for "*.py" beeing deleted. # It doesn not clean anything eg 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删除,而不需要search整个树。

读完这个问题之后,我把我的钩子代码改写成了Python,并根据你对空目录的要求进行了扩展。

我的完整的短代码 (Python)
https://gist.github.com/hynekcer/476a593a3fc584278b87#file-post-checkout-py

文档string:

 """ 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来说并不重要 ,因为__pycache__ * .pyc文件不能在其父目录中没有相关的* .py *文件的情况下执行。

  • 不需要更改目录,因为每次在存储库的根目录中都会启动挂钩。

  • 已编译代码__pycache__caching目录被完全清理,因为它们从不重要(不参与任何二进制分发),而且效率也很高,因为__pycache__/some_name.*.pyc删除可能会很慢。