Is there a git command to add differences within a range of line-numbers to the index?
I want to be able to select lines in my editor and run a macro to add any changes in the selection to the index.
If you can persuade your editor to write a version of the file that you want to be staged, you can use the plumbing-level git commands to add it to the index under the right name. You need to bypass "git add" which will always associate path X in the working tree with path X in the index (as far as I know).
Once you have the content you want to stage written to some temporary file $tempfile, run git hash-object -w $tempfile
- this will write the object to .git/objects and output the blob id. Then feed this blob id to the index using git update-index --cacheinfo 100644 $blobid $path
to associate the path $path with that object.
Here's an example that stages a change to a script called "post_load" in my repo without overwriting the file itself (also demonstrating you can do without a temp file):
git update-index --cacheinfo 100755 $(perl -lne 'print unless (/^#/)' post_load \
| git hash-object -w --stdin) post_load
You don't mention which editor you're planning to do this from, so it's hard to advise you on how to integrate this. As I mentioned, you need to somehow present git with the file as you want it to be staged (remember, git doesn't deal with storing changes). If you can write a macro to just save the file as "$file.tmp", then use something like the above to git update-index --cacheinfo $the_mode $(git hash-object -w $file.tmp) $file
(obtaining $the_mode is left as an exercise :p), delete $file.tmp and revert the editor buffer back to $file that would do basically what you're asking for.
For example, the following script takes three arguments: M N path
. It will update the index content for the file at "path" so that lines M through N (inclusive) are replaced with the content from stdin:
#!/bin/sh
start_line=$1
end_line=$2
path=$3
mode=$(git ls-files -s $path | awk '{print $1}')
blob_id=$(
(
head -n $(expr $start_line - 1) $path
cat
tail -n +$(expr $end_line + 1) $path
) | git hash-object -w --stdin
)
exec git update-index --cacheinfo $mode $blob_id $path
for example echo "HELLO WORLD" | ./stage-part 8 10 post_load
will replace the three lines from 8-10 with just "HELLO WORLD".
The easiest way to do it currently is with git add
in interactive mode:
git add -i path/to/file
It will launch simple UI where you can choose chunks you want to stage and let you edit any chunk to remove lines you don't want to commit.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With