9

The git add -p command allows interactive staging of hunks or parts of a file ( https://git-scm.com/book/en/v2/Git-Tools-Interactive-Staging).

Is there a way to stage a hunk non-interactively? Say, I have these hunks:

$ git diff diff --git a/test.txt b/test.txt index 77e67ac..34eabb1 100644 --- a/test.txt +++ b/test.txt @@ -1,4 +1,4 @@ -this is the first change +this is the first change, don't stage it! @@ -6,5 +6,5 @@ this is the first change -this is the first change +this is the second change, stage it! 

It would be nice to run a single command like git add -p 2 to stage the second hunk without going through the interactive menu.

NOTE: One solution is mentioned here (How to stage chunks non-interactively in git?), but it involves multiple commands and an additional step of editing a patch file.

When would this be useful? Say I was editing a long and repetitive JSON file, and after running git diff, I know I want to stage every other hunk. I don't want to go through each hunk individually; I just want to tell git "stage the 2nd, 4th, 6th, 8th, etc. hunks".

This can also be useful when trying to interact with Sourcetree (which enables working with hunks), using self-defined scripts.

3
  • 1
    Staging hunks (as opposed to whole files) only makes sense in an interactive setting. How would you know, programmatically, that it is indeed the second hunk that you want to stage? Commented Aug 13, 2015 at 15:57
  • 1
    @Jubobs, Well say I was editing a long and repetitive JSON file or something, and I know I want to stage every other hunk after viewing the output of git diff. So, I have "interacted" by running git diff, but now I just want to stage a bunch of hunks all at once without going through them one-by-one. Commented Aug 13, 2015 at 16:03
  • Ok, that makes more sense. You should edit your question and add this explanation. Commented Aug 13, 2015 at 16:04

2 Answers 2

3

In case you are able to manually or automatically (say, thanks to sed) edit your patch (the one produced thanks to git diff), you can stage hunks non-interactively thanks to the following command:

git apply --cached patchfile 

PS: I could actually find the answer to your question here: https://stackoverflow.com/a/31498768/7009806

Sign up to request clarification or add additional context in comments.

Comments

1

This answer is more for the exercise's sake and for the fun side of finding a solution for it. I am not too sure if that can really be applied in a real world case. It also shows a solution about how to use git add -p given a list of desired choices.

git add --patch reads from stdin, so you could prepare your interactive actions, say, in a file (called for the example's sake /tmp/foo), with each line the hunk action you would want and then do:

git add -p < /tmp/foo 

Here is a full example:

I made a file with a number per line from 0 to 100, committed it and remplaced the 0's by a. The beginning of the diff looks like it:

diff --git a/my-file b/my-file index 3b53b00..8f9a65c 100644 --- a/my-file +++ b/my-file @@ -1,4 +1,4 @@ -0 +a 1 2 3 @@ -8,7 +8,7 @@ 7 8 9 -10 +1a 11 12 13 @@ -18,7 +18,7 @@ 17 18 19 -20 +2a 21 22 23 @@ -28,7 +28,7 @@ 27 28 29 -30 +3a 31 32 33 @@ -38,7 +38,7 @@ 37 38 39 -40 +4a 41 42 43 

Now, I want to stage only one change out of two, then I create my foo file:

echo `y n y n y n y n y n y' > /tmp/foo 

The creation of this file can be automated or not.

Then I run it:

git add -p < /tmp/foo 

and I get staged:

> git diff --cached diff --git a/my-file b/my-file index 3b53b00..00010f9 100644 --- a/my-file +++ b/my-file @@ -1,4 +1,4 @@ -0 +a 1 2 3 @@ -18,7 +18,7 @@ 17 18 19 -20 +2a 21 22 23 @@ -38,7 +38,7 @@ 37 38 39 -40 +4a 41 42 43 [.....] 

and unstaged:

> git diff diff --git a/my-file b/my-file index 3b53b00..00010f9 100644 --- a/my-file +++ b/my-file @@ -1,4 +1,4 @@ -0 +a 1 2 3 @@ -18,7 +18,7 @@ 17 18 19 -20 +2a 21 22 23 @@ -38,7 +38,7 @@ 37 38 39 -40 +4a 41 42 43 [...] 

Another way to do the same without a file would be:

echo 'y n y n y n y n y n y' | git add --patch 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.