java - Git:查找仅更改了 serialVersionUID 的文件
问题描述
我有一组自动生成的 java 文件,它们被检入到 git 中。每个文件包含该行
final static long serialVersionUID = -4268385597939353497L;
其中 serialVersionUID 之后的部分在每次重新生成时更改为随机数。
注意:这是一成不变的,我知道“没有将生成的代码检查到版本控制等中”。
如何识别仅更改了 serialVersionUID 的所有文件? 已更改意味着文件在工作副本中已被修改,但尚未提交。
我的目标是通过预提交挂钩还原这些文件。
我已经到了
git diff -U10000 --raw MyFile.java
这给了我整个文件的差异或
git diff -U0 --raw --word-diff=porcelain MyFile.java
这给了我一个“差异标题”加上一个更改列表。
解决方案
注意:这个特定的 StackOverflow 答案并不能解决您的问题(我实际上无法正确解决它,因为我没有 Java 解析器)。这完全是关于您将遇到的所有其他绊脚石,以及如何避免它们,以便您的任务实际上只是与 Java 相关的部分。
需要注意的是,这里的每个文件都有三个副本:
- 您当前提交中的那个,
HEAD:MyFile.java
(git show HEAD:MyFile.java
用来查看这个); - 您提议的下一次提交中的那个,
:MyFile.java
(再次,用于git show
查看它);和 - 工作树中的那个,
MyFile.java
您可以直接查看和编辑。
该git diff
命令通常会选择三个中的两个进行比较。
git diff
不带参数运行,或只选择文件(不是提交)的参数运行,将文件的索引副本与工作树副本进行比较。它不会提取当前提交的文件。索引副本是git commit
将写入新提交的副本,因此它实际上是您现在提议提交的内容。
Usinggit diff --cached
告诉 Git 将文件中HEAD
的文件与索引中的文件进行比较。Usinggit diff HEAD
告诉 Git 将文件HEAD
与工作树中的文件进行比较。因此,这些是您选择比较哪些文件对的方式。但无论如何,如果让 Git 比较所有文件,每个文件git diff
只选择一对文件,或者一组对。
如果你运行git commit -a
——我建议你不要,在这里——这大致相当于git add -u && git commit
,除了它用更新的文件建立一个临时索引。在这里的各种提交钩子中事情变得特别棘手,因为现在有多个不同的索引文件具有不同的建议下一个提交。这就是为什么我建议避免git commit -a
在这里。处理和推理一个文件的三个副本已经足够困难,并且使用棘手的提交选项,例如-a
或--only
或--include
抛出第四个甚至有时是第五个副本。
(Git 一次只能处理一个索引文件。标准git commit
只有一个标准索引文件。标准索引文件具有将或将进入下一次提交的文件的副本。1 选项导致 Git 创建额外的临时索引文件,它在其中构建提议的新提交,然后在环境中使用 set 运行其余操作(包括您的挂钩),$GIT_INDEX_FILE
以使这些子命令查看要使用的临时索引。如果一切顺利最后git commit
进行新的提交,这些临时索引文件中的一个,根据选项和参数具有适当的内容,成为新索引,之后你回到正常情况,每个只有三个副本文件。)
由于您的计划是在预提交挂钩中工作,因此您可能应该将HEAD
文件与索引中的建议提交文件进行比较,即,您可能应该git diff --cached
在此处使用。但是,如果您打算通过计算机程序来执行此操作,而不是作为人类闲暇时阅读的东西,那么您根本不应该使用git diff
。前端git diff
命令是供人类使用的,这就是为什么它对输出进行分页和着色,并执行所有那些只会惹恼计算机程序的事情。Git 将这些花哨的前端称为瓷器命令。
每种git diff
都由后端管道命令实现。将提交(技术上是一棵树)与索引进行比较的管道命令是git diff-index
,它仍然需要--cached
告诉它进行所需的比较:git diff-index --cached HEAD
产生可预测的输出,不依赖于每个用户的首选寻呼机、颜色样式等.
(如果你写这个钩子专门为你自己使用,你可以使用git diff
或者git diff-index
因为你可以补偿你自己的个人git diff
设置。但从某种意义上说,最好还是使用管道命令——那么就没有必要补偿为了任何东西。)
无论您在这里选择什么,您仍然必须编写自己的代码来解释差异输出。:MyFile.java
相反,您可能会选择编写一个程序,该程序仅从当前提交和索引中提取两个感兴趣的文件 - <code>HEAD:MyFile.java 和,并在您自己的程序中比较它们,而不是使用git diff
一点也不。您可以使用 提取文件git show
,但这有一个小缺陷,即它是另一个瓷器命令。您可以使用git cat-file -p
底层管道命令直接提取文件,而无需通过git show
.
实际上解析 Java 代码将是最可靠的方法,这样您就不会被某种愚蠢的格式更改所绊倒。一种更hacky的方法,例如假设除了某一特定形式的一行之外的所有内容都必须匹配,这在 awk 中并不太困难(一次读取两个文件一行,检查两个文件中只有一行不同文件并且它具有预期的形式)。所有这些似乎都比尝试解析 diff 输出更简单,但如果你想解析 diff 输出,非 Git 非上下文 diff 可能更简单。
最后,关于:
我的目标是通过预提交挂钩还原这些文件。
这样做是可以的(Git 会正确处理它,对于“正确”的一些定义),但对于许多 Git 用户来说,这也有点令人惊讶。像这样的 Git 钩子不应该改变事情。编写 Git 的人的目的是让像这样的 Git 挂钩仅用于验证事物。如果验证步骤失败,钩子应该退出非零,这将导致git commit
停止。任何修复都应该通过一些非挂钩操作来完成。
请注意,它完全git commit --no-verify
跳过了预提交挂钩。
1从技术上讲,索引引用了每个文件的只读副本。因为这些副本是只读的,所以它们可以共享。所以“复制”一个索引很便宜,因为它实际上只是复制了所有的引用。此外,提议的新提交中的每个文件与某个现有提交中已经存在的文件 100% 逐位相同,实际上只是对该文件的引用,因为存储在每个提交中的每个文件本身都是完全读取的-只要。
推荐阅读
- python - 如何将所有已安装在 Python 轮中的依赖项包含在内?
- python - 如何重塑数据以修复“RuntimeError:内核大小不能大于实际输入大小”
- python - 我试图用标题垂直打印 csv 数据,但它总是以水平线打印。有人可以看看我的代码吗
- symfony - Twig 变量在块外的扩展页面上不可用?
- django - 我们如何才能在 django-simple-history 中只保留删除操作
- python - dvc.api.read() 引发“UnicodeDecodeError”
- symfony - 使用 Symfony DateType 禁用未来日期
- ffmpeg - 有没有办法在ffmpeg中设置视频文件的整体比特率?
- python - Python 基类可以是没有 __mro_entries__ 的对象
- javascript - 如何获取对象中存在的对象?