开发者

How can you combine git add patch -p mode with diff's ignore-all-space

How can I do git add with patch mode but ignoring whitespace changes.

The use case is for when you've reformatted a file and also made changes to it. I want to commit the real code changes separately first (as shown by git diff -w path开发者_StackOverflow) and then commit the reformatting as a separate commit.


Here's an adaptation from a related question.

git diff -w --no-color | git apply --cached --ignore-whitespace

It has the benefit that you don't need to use stash, temporary files, or perform a reset --hard on your working folders.

Addendum

The solution above only stages changes except whitespace-only edits. This did not address patch, though using --patch to stage isn't straight forward in this situation.

Patch Option 1: Edit the diff in a text editor

There are many ways to implement this using a text editor. Vim is especially suited to this.

In the root directory of your repository, start Vim.

In normal mode, load the diff into an empty buffer with...

:r !git diff -w --no-color
:set ft=diff  # if you want syntax highlighting

Edit the diff and remove the parts you don't want to stage.

To stage the contents of the vim buffer, run the vim ex command...

:w !git apply --cached --ignore-whitespace

If you're a Vim afficionado, you could use visual mode to stage, too!

:<',>'w !git apply --cached --ignore-whitespace

You can commit the staged changes with the ex command...

:!git commit -m "message"
# or
:!git commit

Clear the buffer, read the unstaged changes, and repeat

:bd! | set ft=diff | r !git diff -w --no-color

Eventually, you'll be left with only whitespace changes to commit.

If you don't use Vim, you could also dump git diff into a file, edit the file, save, then feed the file into git apply. Commit and repeat until done. It's a bit tedious, but functional.

Patch Option 2: Patch reset

It's backwards from git add --patch, but once you've staged non-whitespace changes with...

git diff -w --no-color | git apply --cached --ignore-whitespace

...you can unstage chunks in patch mode with...

git reset --patch .

Keep in mind you're removing the changes that you want to keep staged. Repeat and commit as necessary until you only have whitespace changes left.


If you want to do git add --patch but ignore all whitespace like the asker is asking, you can do this in one command:

git diff -w --no-color | git apply --cached --ignore-whitespace && git checkout -- . && git reset && git add -p

git diff -w --no-color creates a diff

git apply --cached --ignore-whitespace applies the diff ignoring whitepace, and indexes it

git checkout -- . removes the unindexed “whitespace” changes

git reset resets the index to just the non-whitespace changes

git add -p adds the non-whitespace changes in patch mode

Wrap this up in an alias, like so:

alias gwap=“git diff -U0 -w --no-color | git apply --cached --ignore-whitespace --unidiff-zero && git checkout -- . && git reset && git add -p”

Or if you're on a unix based system like I am:

gwap= !git diff -U0 -w --no-color | git apply --cached --ignore-whitespace --unidiff-zero && git checkout -- . && git reset && git add -p 

(Notice I added options -U0, and --unidiff-zero respectively to workaround context matching issues, according to this comment.)

Source: https://til.hashrocket.com/posts/696df00135-remove-whitespace-changes-then-git-add-p


Note: This answer is old. 6 years down the road, the other answer by Justin is much better. Prefer to use git apply --cached

I suggest simply roundtripping a diff

Idea:

git diff --ignore-all-space | (git reset --hard && git apply)

Warning: this is fraught with danger because of the git reset there (it will not preserve changes to binary files as written). Perhaps you'd want a bash function similar to

function cleanup_patch()
{
    if [ $# -lt 1 ]; then 
        echo 'Must provide explicit paths (wildcards allowed)'; 
    else
        git diff --ignore-all-space -- "$@" |
            (git checkout HEAD -- "$@" &&
             git apply)
    fi
}

Afaict the seemingly useful --binary option to diff doesn't honour the whitespace ignore flags


A more robust and versatile version of @"Justin C"s answer is:

anw = !git diff -U0 -w --no-color -- \"$@\" | git apply --cached --ignore-whitespace --unidiff-zero "#"
  • With no argument - adds all tracked files' non-whitespace changes
  • Given files/directories - only adds non-whitespace changes in those locations

See this answer for more.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜