黑色,因为pre-commit钩子总是使我的提交失败

55
我正在尝试使用pre-commit来管理Black作为Git预提交钩子,但我可能做错了。
在我的预提交配置文件中,我有:
-   repo: https://github.com/psf/black
    rev: 19.3b0
    hooks:
    -   id: black

我希望发生的是Black只修改暂存文件,提交成功。因为Black的整个重点在于自动强制执行Python代码风格规则,不需要询问。
实际上发生的是:当我暂存一个(非符合Black规范的)文件并尝试提交时,Black会修改该文件以使其符合规范,这正是预期的...但问题是它返回了“失败”。所以提交失败了。然后我必须取消暂存文件,再次暂存,才能再次提交...只有这样才能提交成功。
这是一个巨大的烦恼,不可能是预期的工作流程?
我做错了什么?

3
我认为对于像black这样的工具,它专门用于在无需人类监督的情况下修改文件,即使它已经改变了文件,也应该提交这些文件。我已在“black”代码库上开了一个问题:https://github.com/psf/black/issues/1857 - Anakhand
1
原则上,预提交钩子不应该在没有检查的情况下修改已暂存的文件。听起来你想要的效果更适合通过将git add设置为在暂存之前运行black来实现;这样可以将预提交钩子作为有效性检查而非格式化工具。 - David258
@David258 我希望这个适用于其他团队成员,我无法修改他们的shell别名或图形界面工作流程。 - undefined
6个回答

49

(pre-commit 的作者在这里)

该框架有意不提供自动提交修改的方式。以下是一些要求此类功能的问题:

其中一个问题的评论:

pre-commit 本身永远不会触碰暂存区。这些方法是悄悄地破坏提交的好方法。在我看来,这是 [其他框架做并建议] 的最糟糕的事情之一--钩子非常容易出现问题,神奇地改变正在提交的内容不应该轻率对待。

话虽如此,如果您想要脚辅助输入,您的钩子可以调用 git add -u,而 pre-commit 将不会知道任何更改 :) 这是一个草图(未经测试,不鼓励使用)

  - id: yapf
    entry: bash -c 'yapf "$@"; git add -u' --

(注意:使用 bash 可能会降低可移植性)

另一条评论指出

幸运的是,如果你不介意冒险,git add -u && !! 很容易运行 :)


16
听起来合理。我现在有些困惑的是 black 的预提交钩子应该做什么,或者它应该如何使用。因为 black 的整个意义就是不加询问地修改文件。我猜这是一个问题,需要向那个钩子的作者提问。 - Jean-François Corbett
你应该在哪里添加这个条目?无论是黑色还是 pre-commit-hook 都会说:“yapf” 不在仓库中。是打错字了吗?也许它在更新的版本中被引入了?通常情况下,“pre-commit autoupdate” 可以解决这个问题。 - michel.iamit
@michel.iamit yapf只是一个示例,来自于工单的复制内容。你需要确保你正在配置你想要配置的钩子(例如id: black)。 - anthony sottile
14
我不明白为什么这个答案被采纳了 - 我和@Jean-FrançoisCorbett一样感到困惑。如果预提交挂钩不修改暂存区中的文件,那么格式化代码有什么用处? - mchristos
2
pre-commit钩子的目的是确保格式正确。由个人开发者负责使用相同的代码格式化程序和编辑器设置来确保格式正确。 - Afzal S.H.
https://github.com/psf/black/issues/285 - Linus Fernandes

13

我的一位开发人员提出了一个好的建议,如果由于黑名单(例如由于单引号/双引号)而导致的提交失败,那么可以使用 pre-commit-hook(例如 double-quote-string-fixer)来解决问题。这会让你处于某种“无人之境”的 git 状态中。暂存区里有一个已更改的文件,但是不能通过 pre-commit-hook 提交,git status 不会显示任何更改,但提交失败(在我看来实在是个黑洞)。你只能在提交时失败,但什么也做不了(除了对该文件进行重置)。一旦你处于这种情况下并运行:commit -m 'Resolving pre-commit-hook changes' --no-verify ..... tada!问题解决了。


2
在这种情况下,您的暂存文件仍然具有错误的单引号,因为black只修改了工作文件。为了使git commit成功,首先使用git add暂存black所做的更改,否则您将提交错误的单引号。 - Carl Walsh
@CarlWalsh 您的评论有些含糊不清。“为了让git提交成功”- git commit将会成功,因为答案建议使用--no-verify标志。也许最好重述为“为了避免提交未格式化的代码”。 - Jakub Kukul

6

看黑人的自述文件,你可能想要使用 --check 选项,它根据文件是否符合标准简单地退出成功或失败。这将导致提交失败而不修改文件。


19
我明白你的意思,但那恰恰与我尝试做的相反。我希望黑色只是修改文件,并使提交成功。现在已在问题中澄清。 - Jean-François Corbett

1

我和你一样。据我所知,提交无法在预提交挂钩中进行修改。

就我所了解的情况而言,最好的方法是bk2204提出的。我们请求black防止包括未经过黑色正确格式化的python文件的任何提交。它仍然确保对任何提交进行格式化,但确实很烦人,因为它不会自动为我们格式化文件。

这是有道理的。提交中的任何更改都必须分阶段进行。如果我们可以从git hook中完成这个过程,那么我们的问题就解决了。您通过直接从git hook修改文件已经完成了一半。下一步是对修改后的文件的所有更改进行分阶段。但显然......“您无法在预提交挂钩中修改提交”,这意味着没有分阶段。 https://dev59.com/_G3Xa4cB1Zd3GeqPke8F#14641656

我本来想评论bk2204的答案,但我还没有50个声望。

放弃之前的回答,这个答案(https://dev59.com/QGQn5IYBdhLWcg3wcWzM#16832764)声称可以在预提交钩子中更改提交。在这种情况下,文件正在被添加,所以我敢打赌在我们的情况下文件可以被重新暂存/修改。

有趣的是,基本上“在 pre-commit hook 中更改提交内容是一个坏主意”。解决这个问题的更好方法似乎是拥有一个包装脚本,在运行 git 前运行黑色。 >.> - Carl Walsh

1

根据我的经验,没有必要取消暂存任何文件,只需将黑色或其他预提交钩子修改的文件添加到git add中,再次修改这将覆盖它们在阶段区域中的内容并使用与之前相同的消息commit除非错误是由于提交消息检查。

如果您的提交包括所有更改的文件,则将提交命令从git commit -m“您的提交消息”更改为git commit -am“您的提交消息”即可轻松完成工作。


0
我在VS Code中花了大约一个小时来解决这个问题,我已经安装了pre-commit,并且它作为pre-commit hook的一部分运行了'black'。
这里所解释的,将black作为pre-commit hook的一部分运行将生成一个更新的文件,此时该文件尚未暂存 - 未添加到您的提交中。
因此,您可能会在VS Code中陷入一个无法前进的提交循环。摆脱这个循环的方法是在您的git仓库中打开终端,并执行以下操作:
   % git commit
   % git add .
   % git commit

首次提交将运行黑色并生成带有新缩进等更新文件。然后,您可以像往常一样添加和提交此更改。然后,您就可以回到游戏中并推送您的更改。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接