【问题标题】:How can you combine git add patch -p mode with diff's ignore-all-space如何将 git add patch -p 模式与 diff 的 ignore-all-space 结合使用
【发布时间】:2011-07-04 12:40:49
【问题描述】:

如何使用补丁模式执行 git add 但忽略空格更改。

该用例适用于您重新格式化文件并对其进行更改的情况。我想先单独提交真正的代码更改(如 git diff -w path 所示),然后将重新格式化作为单独的提交提交。

【问题讨论】:

  • git add --patch 的“g”选项会有所帮助;空白更改将在可供选择的大块列表中显示为空。
  • 哪个版本的git添加了g选项?
  • 它在 1.6.1-rc1-37 中,所以第一个正式版本应该是 1.6.2。 (它实际上不是一个“选项”,而是在显示大块时使用的导航菜单选择。)
  • 请注意,g 不会像我想的那样做:我将“空白更改”解释为“插入或删除空白行”。 'g' 将为这些类型的更改显示空白标题,但不用于插入/删除空格。

标签: git whitespace patch


【解决方案1】:

这是对related question 的改编。

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

它的好处是您不需要使用stash、临时文件或对您的工作文件夹执行reset --hard

附录

上述解决方案仅阶段更改,仅空白编辑除外。虽然在这种情况下使用--patch 暂存并不直接,但这并没有解决补丁问题。

补丁选项 1:在文本编辑器中编辑差异

有很多方法可以使用文本编辑器来实现这一点。 Vim 尤其适合这个。

在存储库的根目录中,启动 Vim。

在正常模式下,将差异加载到一个空缓冲区中...

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

编辑差异并删除您不想暂存的部分。

要暂存 vim 缓冲区的内容,请运行 vim ex 命令...

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

如果您是 Vim 爱好者,您也可以使用视觉模式进行演示!

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

您可以使用 ex 命令提交分阶段的更改...

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

清除缓冲区,读取未暂存的更改,然后重复

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

最终,您将只剩下要提交的空白更改。

如果您不使用 Vim,您也可以将 git diff 转储到文件中,编辑文件,保存,然后将文件输入到 git apply。提交并重复直到完成。这有点乏味,但很实用。

补丁选项 2:补丁重置

它从 git add --patch 倒退,但是一旦你使用...进行非空白更改...

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

...您可以使用...在补丁模式下取消暂存块

git reset --patch .

请记住,您正在删除要保留暂存的更改。根据需要重复并提交,直到只剩下空白更改。

【讨论】:

  • 那真是太棒了。在 Visual Studio 在 web.config 上大便之后非常有用。
  • 怎么会有这么多赞。它完全没有包含 git add --patch,允许用户通过他们的所有更改,但忽略空格更改?
  • 我完全忽略了“补丁”,Chucky。更新了您的解决方案的一些替代方案。谢谢!
  • 当上下文包含被 git diff 忽略的空白错误时,这可能会在一些复杂的情况下失败。 diff 和 apply 上的 unidiff-zero 选项可以通过删除所有上下文来提供帮助:stackoverflow.com/a/63904526/5520728
【解决方案2】:

注意:这个答案是旧的。 6年后,贾斯汀的另一个答案要好得多。更喜欢使用git apply --cached

我建议简单地往返一个差异

想法:

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

警告:这充满了危险,因为那里有git reset(它不会保留对二进制文件的更改)。也许你想要一个类似于

的bash函数
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
}

似乎有用的--binary diff 选项不支持空格忽略标志

【讨论】:

  • 我通过将 diff 的输出重定向到一个文件来做到这一点。然后使用结帐路径,最后使用 --ignore-whitespace 应用。如果你想编辑你的答案,我可以接受。
  • @Sam:如果我的回答对您有所帮助,那就足够了。为什么使用临时文件要好得多?您所描述的似乎正是 cleanup_patch 函数所做的,只是增加了乏味。我可能错过了什么
  • 当您不经常使用差异和补丁时,输出到文件只是安全轮。您可以检查补丁是否正常,如果您在重置/检查后搞砸了,您至少可以手动应用补丁更改。 Iow我是一个n00b。无论如何,您至少不认为检查特定路径比重置整个工作目录更安全吗?哦,现在我看到你的 shell 函数确实做到了 X_X 我会继续大声思考。你不应该在 apply 中使用 --ignore-whitespace 标志吗?
  • @Sam:在应用时忽略空格是多余的。很高兴您注意到 bash 函数中的 checkout。如果需要,请务必使用临时文件。我的偏好是commit/reset HEAD^ 或使用git stash,如果我怀疑的话。不过,我通常还是手动清理补丁
  • @AnkurLoriya 这是故意的,但我同意它使单班轮方法有风险。另一个答案应该是公认的答案。几分钟后将在顶部添加注释
【解决方案3】:

@"Justin C" 答案的一个更健壮和通用的版本是:

anw = !git diff -U0 -w --no-color -- \"$@\" | git apply --cached --ignore-whitespace --unidiff-zero "#"
  • 不带参数 - 添加所有跟踪文件的非空白更改
  • 给定文件/目录 - 仅在这些位置添加非空白更改

请参阅this answer 了解更多信息。

【讨论】:

    【解决方案4】:

    如果您想执行 git add --patch 但忽略询问者要求的所有空格,您可以在一个命令中执行此操作:

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

    git diff -w --no-color 创建一个差异

    git apply --cached --ignore-whitespace 应用差异忽略空白,并将其编入索引

    git checkout -- . 删除未索引的“空白”更改

    git reset 将索引重置为仅非空白更改

    git add -p 在补丁模式下添加非空白更改

    用别名把它包起来,像这样:

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

    或者,如果您像我一样使用基于 unix 的系统:

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

    (请注意,根据this comment.,我分别添加了选项-U0--unidiff-zero 来解决上下文匹配问题)

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

    【讨论】:

    • 为了安全起见,隐藏空白更改然后在此命令之后弹出它们也可能很有用。如果不将所有内容都存储在索引中,我不确定如何做到这一点。有人知道吗?
    • 我不知道有选择地隐藏,我已经广泛寻找这种能力。但是,如果您的仅空格更改是由格式化工具(例如 gofmtrustfmt)引起的,则此解决方案非常有效。我只是在提交恢复空白更改后重新运行格式化工具。
    • git diff | git apply 之后,git stash --keep-index 可能会保存空白更改。它将存储所有更改,但不理会索引。 git reset &amp;&amp; git add -p,提交直到完成,然后git stash pop 应该恢复空白更改。灵感来自this answer
    • 我试了一下,贾斯汀。但是在弹出存储时会发生合并冲突。
    • 我也很害怕。 :/我想一个临时文件就足够了。在git checkout -- . 之前,git diff -U0 --no-color &gt; some-temp-file,然后在末尾,&lt;some-temp-file git apply --cached --unidiff-zero &amp;&amp; rm some-temp-file
    猜你喜欢
    • 1970-01-01
    • 2018-08-10
    • 2011-11-10
    • 2016-02-14
    • 1970-01-01
    • 2016-06-23
    • 2017-10-28
    • 2012-06-08
    相关资源
    最近更新 更多