threads / discuss / 42487

git add without whitespace

Subject: git add without whitespace

## tl;dr

8 messages between May 30, 2016 and May 31, 2016.

replies: 7people: 4as markdown or json

Robert Dailey· May 30, 2016, 15:26 UTC · lore

I think it would be useful to have a '-w' option for 'git add' that completely ignores whitespace changes, the same way that 'git diff -w' does.

Real life scenario:

Sometimes developers will use tooling that does not properly strip trailing whitespace in source files. Next time I edit those files for a simple 1-line code change, my tooling will strip whitespace from the whole file. I *do* want these changes, however I want 2 commits: 1 commit with the bugfix, and a supplementary commit with just the whitespace changes.

At the moment, there is no way for me to conveniently add the source file to the index without whitespace. The only way to accomplish this today that I'm aware of is via this command:

$ git diff -U0 -w --no-color | git apply --cached --ignore-whitespace --unidiff-zero

This command explicitly leaves out context because it can sometimes cause the patch to fail to apply, I think due to whitespace being in it, but I'm not completely sure myself.

It would be useful to be able to do this instead:
$ git add -w

This would effectively function the same as my workaround command shown earlier. It should also be valid to use -w with -i and -p. In the -p case, it just won't show hunks containing whitespace changes. For -i, it would assume '-w' as part of any command run during the interactive session.

Does this idea sound good? I have some free time on my hands so I wouldn't mind implementing this. Maybe there isn't a huge audience for this kind of thing, or maybe I'm just going about this the wrong way. Thoughts would be much appreciated.

Junio C Hamano· May 30, 2016, 19:06 UTC · re: Robert Dailey · lore

Re: git add without whitespace

Robert Dailey <rcdailey.lists@gmail.com> writes:
Show 6 quoted lines
> $ git diff -U0 -w --no-color | git apply --cached --ignore-whitespace
> --unidiff-zero
>
> This command explicitly leaves out context because it can sometimes
> cause the patch to fail to apply, I think due to whitespace being in
> it, but I'm not completely sure myself.
I have had this in my ~/.gitconfig for a long time.
[alias]
	wsadd = "!sh -c 'git diff -- \"$@\" | git apply --cached --whitespace=fix;\
		git co -- ${1-.} \"$@\"' -"

That is, "take what's different from the _index_ and the working tree, apply that difference while correcting whitespace errors to the index, and check the result out to the working tree". This would _not_ touch existing whitespace-damaged lines that you are not touching, and honours the customized definition of what is considered whitespace breakage for each paths (which you set up with the attributes system).

Robert Dailey· May 30, 2016, 19:50 UTC · re: Junio C Hamano · lore

Re: git add without whitespace

On Mon, May 30, 2016 at 2:06 PM, Junio C Hamano <gitster@pobox.com> wrote:
Show 14 quoted lines
> I have had this in my ~/.gitconfig for a long time.
>
> [alias]
>         wsadd = "!sh -c 'git diff -- \"$@\" | git apply --cached --whitespace=fix;\
>                 git co -- ${1-.} \"$@\"' -"
>
> That is, "take what's different from the _index_ and the working
> tree, apply that difference while correcting whitespace errors to
> the index, and check the result out to the working tree".  This
> would _not_ touch existing whitespace-damaged lines that you are not
> touching, and honours the customized definition of what is
> considered whitespace breakage for each paths (which you set up with
> the attributes system).
>

I like your solution better than mine because it utilizes the rules defined in .gitattributes. I think that's a really good idea. But other than that, yours is functionally the same as what I'm doing, right? I just want to make sure I understand: What ends up in the index/staging area is the code MINUS the trailing whitespace (e.g. whitespace errors)?

What does the checkout at the end do? That part confuses me (granted I'm not well-versed with bash script).

Thanks for the feedback. Looks like this is niche enough that an alias/script is probably the best solution.

Junio C Hamano· May 30, 2016, 22:00 UTC · re: Robert Dailey · lore

Re: git add without whitespace

Robert Dailey <rcdailey.lists@gmail.com> writes:
> I like your solution better than mine because it utilizes the rules
> defined in .gitattributes.

A difference that may be more important is that I do not do generation of a patch or application of it without ignoring whitespaces with things like -w and --ignore-whitespace. That way, if my edit is a correction of existing whitespace breakage (e.g. I noticed a line that is indented by 8 spaces, and I corrected it by replacing them with one tab), that is shown as a change by "diff" and kept in the result. I suspect that your "diff -w | apply --ignore" will ignore that manual fix?

> What does the checkout at the end do? That part confuses me (granted
> I'm not well-versed with bash script).

I correct whitespace-broken updates the user (i.e. I) made in her working tree file by adding a corrected version to the index, and then I checkout the result out of the index to the working tree.

That corrects the breakage in both the index and the working tree, so that my further edit to the file will start from a ws-corrected version.

Robert Dailey· May 31, 2016, 15:03 UTC · re: Junio C Hamano · lore

Re: git add without whitespace

On Mon, May 30, 2016 at 5:00 PM, Junio C Hamano <gitster@pobox.com> wrote:
Show 24 quoted lines
> Robert Dailey <rcdailey.lists@gmail.com> writes:
>
>> I like your solution better than mine because it utilizes the rules
>> defined in .gitattributes.
>
> A difference that may be more important is that I do not do
> generation of a patch or application of it without ignoring
> whitespaces with things like -w and --ignore-whitespace.  That way,
> if my edit is a correction of existing whitespace breakage (e.g. I
> noticed a line that is indented by 8 spaces, and I corrected it by
> replacing them with one tab), that is shown as a change by "diff"
> and kept in the result.  I suspect that your "diff -w | apply --ignore"
> will ignore that manual fix?
>
>> What does the checkout at the end do? That part confuses me (granted
>> I'm not well-versed with bash script).
>
> I correct whitespace-broken updates the user (i.e. I) made in her
> working tree file by adding a corrected version to the index, and
> then I checkout the result out of the index to the working tree.
>
> That corrects the breakage in both the index and the working tree,
> so that my further edit to the file will start from a ws-corrected
> version.

Ah, I think I get it now. I was confused, you and I are apparently trying to accomplish two different things.

My alias stages changes EXCEPT whitespace fixes. In this case, I've already made the whitespace corrections (by hand) in the working tree. I want to stage the changes EXCEPT whitespace. This will allow me to do 1 commit without whitespace, and another with just the whitespace. So yes, my patch is deliberately ignoring whitespace because I do not want it in the index for the first commit.

Yours seems to take exactly what is in the working tree and make further modifications to it as it is added to the index. That is, to correct whitespace errors as defined by the gitattributes file.

When I tested your alias, all changes in my working tree were added to the index, where I expected the index to contain everything except whitespace modifications.

But honestly your solution is a little better, even if it requires me
to change my process, because:
- You don't depend on external tooling to correct whitespace
- Splitting whitespace & real changes to two commits is probably
superfluous; my original goal was to make diffing the actual changes
easier, but since 'git diff -w' exists this is moot.

So I guess it's not bad practice to mix whitespace changes in with real diffs, given the flexibility of Git (in previous VCS such as Git and perforce I didn't do it this way). I have a similar habitual carry-over from SVN where I do file moves/renames in separate commits before I modify file contents. Again with Git, probably not as necessary to do this.

Junio C Hamano· May 31, 2016, 16:16 UTC · re: Robert Dailey · lore

Re: git add without whitespace

Robert Dailey <rcdailey.lists@gmail.com> writes:
> - Splitting whitespace & real changes to two commits is probably
> superfluous; my original goal was to make diffing the actual changes
> easier, but since 'git diff -w' exists this is moot.

Doing "whitespace clean-up" in a separate preparatory patch _is_ a good practice. I do not think either approach makes it harder to do. After all, if you had a real change on the same line that you dropped a broken whitespace, e.g. (end-of-line shown with '$')

    -	if  (i==1) {  $
    +   if (j == 2) {$
both approaches would add the updated line.

The wsadd is about protecting _me_ from introducing new whitespace breakages, not about helping me when fixing existing whitespace breakages. So from that point of view, that may not fit well to what you are trying to do.

Christian Neukirchen· May 31, 2016, 15:59 UTC · re: Junio C Hamano · lore

Re: git add without whitespace

Junio C Hamano <gitster@pobox.com> writes:
Show 14 quoted lines
> Robert Dailey <rcdailey.lists@gmail.com> writes:
>
>> $ git diff -U0 -w --no-color | git apply --cached --ignore-whitespace
>> --unidiff-zero
>>
>> This command explicitly leaves out context because it can sometimes
>> cause the patch to fail to apply, I think due to whitespace being in
>> it, but I'm not completely sure myself.
>
> I have had this in my ~/.gitconfig for a long time.
>
> [alias]
> 	wsadd = "!sh -c 'git diff -- \"$@\" | git apply --cached --whitespace=fix;\
> 		git co -- ${1-.} \"$@\"' -"
Very useful, thanks for sharing!
I wonder which other gems are in your .gitconfig, is it public?
-- 
Christian Neukirchen  <chneukirchen@gmail.com>  http://chneukirchen.org
demerphq· May 31, 2016, 16:27 UTC · re: Junio C Hamano · lore

Re: git add without whitespace

On 30 May 2016 at 21:06, Junio C Hamano <gitster@pobox.com> wrote:
Show 22 quoted lines
> Robert Dailey <rcdailey.lists@gmail.com> writes:
>
>> $ git diff -U0 -w --no-color | git apply --cached --ignore-whitespace
>> --unidiff-zero
>>
>> This command explicitly leaves out context because it can sometimes
>> cause the patch to fail to apply, I think due to whitespace being in
>> it, but I'm not completely sure myself.
>
> I have had this in my ~/.gitconfig for a long time.
>
> [alias]
>         wsadd = "!sh -c 'git diff -- \"$@\" | git apply --cached --whitespace=fix;\
>                 git co -- ${1-.} \"$@\"' -"
>
> That is, "take what's different from the _index_ and the working
> tree, apply that difference while correcting whitespace errors to
> the index, and check the result out to the working tree".  This
> would _not_ touch existing whitespace-damaged lines that you are not
> touching, and honours the customized definition of what is
> considered whitespace breakage for each paths (which you set up with
> the attributes system).

That is very very cool. I have a perl script that does the same thing from git-blame output. This is MUCH nicer.

cheers, Yves

-- 
perl -Mre=debug -e "/just|another|perl|hacker/"

← back to recent threads