我只想用一个 shell 命令从文件中git add
特定范围的行。我正在成像类似的东西:
git add -c myfile.go@123..204
我不想使用git add -i
、git add -p
或git -e
(交互式 git 工具),因为我的文件很大并且有很多变化,而且我已经确切地知道我想要哪几行。为了论证(明白吗?),假设我想在 2000 行文件myfile.go
123-204
包含
行。我也不想使用 GUI。要么我的电脑太旧,无法运行它们,要么屏幕太小......无论什么。以上所有。Github GUI,Sourcetree,一个(Atom|IntelliJ|VSC|.*
插件,KDiff,Kaleidescope...他们都出去了。
能做到吗?
奖励点:可以一次对多个文件完成吗?
供参考:
两个相关但不重复的问题。两者都不符合我的需求:
- 将文件的特定行提交到 git
- 在 Git 中仅提交文件的一部分
- 这个评论让我觉得可以做到...在 Git 中仅提交文件的一部分
Git 文档很接近,但没有雪茄:
- https://git-scm.com/book/en/v2/Git-Tools-Interactive-Staging
从注释中,不清楚您是否担心执行添加操作的效率,需要执行哪些类型来指示工具要做什么,或者两者兼而有之。
我不会担心前者;如果你担心它,你也无能为力。 步骤比您认为合理的要多,它们涉及处理整个文件;但实际上,这并不重要,因为我从未见过单文件暂存操作需要足够的时间来担心它。
至于涉及的键入量,您列出的add
选项是最接近git
提供的内置支持。 因此,您可以编写一些脚本来增强它们。 但要确保它总是"做对"并不容易。
特别是,定义"此行范围的更改"比您意识到的要棘手。 看似明显的问题是,行添加和删除会更改它们之后出现的行的行号;但是您可以通过根据文件的当前工作版本定义行号范围来解决这个问题(因为这是最近在确定行号范围时可能会看到的内容)......
但更大的问题是检测一个范围中的所有行都被编辑的情况,并且该范围与要暂存更改的行范围的末尾重叠。 例如,假设您有文件
1
2
3
4
5
在索引中,您的工作副本显示
1
2
3 THREE
4 FOUR
5 FIVE
现在,您指定要暂存第 2-4 行的更改。
补丁将看起来像
@@ -1,5 +1,5 @@
1
2
-3
-4
-5
+3 THREE
+4 FOUR
+5 FIVE
很明显,在这种情况下,直观的结果是
1
2
3 THREE
4 FOUR
5
但是,编写代码来获得这种"正确"而不使其他情况"错误"(相对于同样直观的解释)并不是那么容易。 有时它真的可以解释。 "这一次操作改变了三条线吗? 或者一个操作删除了三行,然后是三个操作,每个操作增加了一行? 或者...">
git 中的自动化工具避免了做出这些解释性决策,首先通过查看大量更改的代码(而不是任意行范围),并在您想要不同的东西时手动干预(即通过使用补丁编辑模式);然后插入冲突标记(再次需要手动干预)当似乎仍然需要解释时。
因此,您基本上必须做出简化的假设来构建工具,并确保这些假设在使用该工具时有效。
然后,我们的想法是创建一个脚本,该脚本从由其第一个参数命名的文件中读取补丁并就地编辑补丁;并在运行git add -e
时将该脚本设置为编辑器(即通过设置GIT_EDITOR
环境变量)。 您将使用@@ -#,# +#,# @@
形式的行来确定更改的受影响行号,使用该信息(以及您的假设)来决定是要保留还是放弃给定的更改行,以及是否要丢弃它
- 如果该行以
-
开头,则将-
更改为
- 如果该行以
git add -p
开头,则删除该行
我已经对此进行了研究,但不是很广泛。我的理解是,git diff
的工作方式是生成补丁,提供一个直观的界面来编辑它们,然后应用它们。
您可以自己执行此过程。
工作树中的更改由git apply
提供。这些更改可以使用git add .
作为修补程序应用于索引
所以你可以跑git diff . | git apply - --cached
而不是
git add -e
即,在当前目录中获取工作树中的所有差异,并将其全部应用于索引。
因此,您可以做的是自己修改差异的输出,并在应用之前使用脚本或任何方法生成不同的补丁。
使用脚本修改此过程的过程可能比选择git add -p
或$EDITOR
解决方案更棘手,但据我所知,如果您想以不同的方式解决问题,这是解决问题的方法。
补遗:
这基本上正是交互式 git 命令使用 perl 脚本所做的。它创建分块的差异文件,然后在++ XYZ / -- zyx
中打开它们。重要的是,它会在您完成修改后自动修复差异格式(自己做很烦人),因为差异git appy foo.diff --cached && git restore --staged foo.diff && git add -p
顶部的行摘要内容需要正确才能应用补丁。
我不记得perl脚本运行什么命令来对差异进行分块,但它在源代码的某个地方。
如果我今天必须解决这个问题,我可能会生成分块差异。删除行外的那些。然后CC_26.