gpt4 book ai didi

git - 如何在多分支项目中格式化代码?

转载 作者:太空狗 更新时间:2023-10-29 13:19:10 26 4
gpt4 key购买 nike

因此,我们拥有数十万行的代码git存储库,自从我两年前加入该项目以来,格式化就困扰了我。这不仅使我感到困扰,而且当开发人员随机“修复” fomratting时, merge 仅在一侧应用代码格式时会令人头疼。现在,重新格式化代码是一个两分钟的任务,但是也会导致 merge 冲突。我最近将master merge 到了一个长期存在的功能分支中,并尝试了以下操作:

master中的

  • 格式代码, merge 到功能分支:3路 merge 工具融合给了我上面提到的一团糟。不检测功能边界。 merge 真的没有乐趣。
  • master中的
  • 格式代码,功能分支中的格式代码, merge master:现在,我仍然获得30个带有冲突的文件,这些文件更易于整理

  • 现在,我想知道是否值得 merge ,因为还有15个分支都需要完全相同的代码审查,并且手动 merge 容易出错,所以我想知道是否有某种方法可以避免这些 merge 冲突。

    最佳答案

    假设配方

    (注意:我没有测试过任何一个)

    我们假设重新格式化程序位于~/Downloads/android-studio/bin/format.sh中,并且[注意:显然,这是一个错误的假设!]它会读取stdin并写入stdout,并且一次处理一个文件。 (有可能,但是非常困难,一次要处理多个文件,这是很困难的。但是,在这种情况下,您不能使用此配方。Git的基本过滤机制要求每个过滤器仅读取stdin和写入stdout。默认情况下,即使它以失败状态退出,Git也会假定过滤器正常工作。)

    选择在哪里运行过滤器;在这里,我仅将其设置为“干净”过滤器。

    ~/.gitconfig.git/config中,添加过滤器的定义:

    [filter "my-xyz-language-formatter"]
    clean = ~/Downloads/android-studio/bin/format.sh
    smudge = cat

    (这假定运行 cat运行的过滤器会将其未更改的输入写入其stdout;在任何类似Unix的系统上都是如此)。

    然后,根据需要创建 .gitattributes文件。它将应用于您在其中创建目录的目录以及所有子目录,除非在这些子目录中被覆盖,因此将其放置在最高明智的位置(通常是存储库的根目录),但有时会在 source/src/或任何下方目录。通过格式化程序将行添加到与某些模式匹配的直接文件中。我们在这里假设所有名为 *.xyz的文件都应进行格式化:
    *.xyz   filter=my-xyz-language-formatter

    现在,此过滤器将应用于 *.xyz文件的所有提取和插入。 The gitattributes documentation讨论了在退房和入住时应用的这些内容,但这并不是完全正确的。取而代之的是,每当Git从工作树复制到索引时(本质上是 git add-早于 git commit,除非您使用 git commit -a或类似的标志),都会应用一个干净的过滤器。每当Git从索引复制到工作树时(基本上是 git checkout,但还有一些其他情况,例如 git reset --hard),都会应用一个模糊过滤器。

    请注意,为每个文件分配一个过滤器可能会很慢。如果对过滤器有很多控制权,则可以使用“长期运行的过滤器过程”协议(protocol),这样可以加快速度(特别是在Windows上)。但是,这超出了此答案的范围。

    运行 git merge通常不使用过滤器(它适用于索引中已经存在的副本,这在过滤步骤之外)。但是,将 -X renormalize添加到标准 merge 中将使 git merge进行如下所述的“虚拟 checkin 和 checkout ”,因此它将应用过滤器。对于 merge 中涉及的所有三个提交,都会发生这种情况(并且在两个方向(干净和弄脏),因此,比一次提交要慢大约6倍)。

    说明(见下文)

    Git本身在这里仅部分有用。

    从根本上讲,问题在于Git是愚蠢且面向行的:它从 merge 基础提交到每个提示提交运行 git diff。如果这两个 git diff中的一个或两个都看到了很多格式更改,则认为这些重要且值得应用于基础。它不具有输入代码的语义知识。

    (由于您可以接管整个 merge 过程,因此您可以编写一个使用语义分析的更聪明的 merge 。但是,这非常困难。我所知道的唯一可以做到这一点或实现这一目标的系统就是Ira Baxter的商业软件,而我从未真正使用过它;我只是了解其背后的理论。)

    有一种解决方案不依赖于使Git更智能。如果您有一个语义分析器来输出一致格式的代码,而不管输入形式如何,则可以将所有三个版本(B表示基,L表示左或本地或 --ours以及R表示右或远程或其他或 --theirs的代码)格式化程序:
    reformat < B > B.formatted
    reformat < L > L.formatted
    reformat < R > R.formatted

    现在,您可以让Git merge 所有三个格式化的版本,而不是 merge 原始的可能尚未格式化(但可能已经格式化)的版本。

    当然, merge 的结果将被重新格式化。但是想必这就是您想要的。

    使用Git的内置工具实现此目的的方法是使用所谓的污迹和清洁过滤器。当文件从存储库中提取到工作树中时,会将污迹过滤器应用于文件。每当文件从工作树进入存储库时,都会对其应用干净的过滤器。

    在这种情况下,污迹过滤器可以“不对数据执行任何操作”,从而完全保留已提交的内容。干净的过滤器可以是重整器。或者,如果您愿意,污迹过滤器可以是重整器,清洁过滤器可以是重整器,也可以是无操作过滤器。一旦到位,就可以在 .gitattributes中进行设置,方法是通过路径名定义特定文件的过滤器,并在 .git/config或主(用户或系统范围内) .gitconfig中定义过滤器驱动程序。

    完成所有设置后,即可运行 git merge -X renormalize。 Git将照常提取B,L和R版本,然后通过“虚拟 check out 和检入”步骤运行它们,进行三个临时提交,1 B格式化等等。然后,它使用三个临时提交(而不是原始三个提交)进行 merge 。

    困难的部分是找到一种可以满足您的需求的重新格式化器。一些现代系统具有它们,例如 gofmtclang-format。如果有一个可以满足您的需求,那么将所有这些整合在一起,并从团队中的其他成员那里买进就可以了,这种重新格式化是个好主意。

    1从技术上讲,它只是制作树对象;不需要实际的提交。

    关于git - 如何在多分支项目中格式化代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47023081/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com