From comments, it's unclear whether you're concerned about the efficiency of executing the add operation, the typing that needs to be done to instruct the tools what to do, or both.
I wouldn't worry about the former; and if you are worried about it, there's not much you can do anyway. There are more steps than you might think sound reasonable, and they involve processing the whole file; but really, it doesn't matter, in that I've never seen a single-file staging operation take enough time to worry about it.
As for the amount of typing involved, the add
options you listed are the closest built-in support git
offers. So you can do a little scripting to augment them. But it won't be easy to ensure that it always "gets it right".
In particular, it's trickier than you might realize to define "the changes to this range of lines". The seemingly-obvious issue is that line additions and deletions change the line numbers of lines that occur after them; but you can probably resolve that by defining your line number range in terms of the current working version of the file (since that's what one would likely be looking at most recently when determining the line number range)...
But the bigger problem is detecting the case where all lines in a range were edited, and that range overlaps the end of the range of lines for which you're staging changes. For example, suppose you have the file
1
2
3
4
5
in the index, and your working copy says
1
2
3 THREE
4 FOUR
5 FIVE
Now you specify that you want to stage the changes from lines 2-4.
The patch will look like
@@ -1,5 +1,5 @@
1
2
-3
-4
-5
+3 THREE
+4 FOUR
+5 FIVE
And it's pretty clear that in this case the intuitive result is
1
2
3 THREE
4 FOUR
5
But writing code that gets this "right" without getting other cases "wrong" (relative to equally intuitive interpretation) is not so easy. Sometimes it really is open to interpretation. "Was this one operation that changed three lines? Or one operation that deleted three lines, followed by three operations that each added a line? Or..."
The automated tooling in git avoids making those interpretive decisions, first by looking at code in hunks of change (rather than arbitrary line ranges) and making you intervene manually if you want something different (i.e. by using patch-edit mode); and then by inserting conflict markers (and again requiring manual intervention) when interpretation still seems to be required.
So you basically have to make simplifying assumptions to build a tool, and make sure those assumptions are valid when using the tool.
The idea, then, would be to create a script that reads the patch from the file named by its first argument and edits the patch in place; and set that script as the editor (i.e. by setting the GIT_EDITOR
environment variable) when running git add -e
. You would use lines of the form @@ -#,# +#,# @@
to figure out the affected line numbers for a change, use that information (and your assumptions) to decide if you want to keep or discard a given change line, and if you want to discard it
- if the line starts with
-
, change the -
to a
- if the line starts with
+
, delete the line