首页 > 解决方案 > 如何使用 git merge 忽略尾随空格?

问题描述

我期望以下命令在将内容合并到当前分支时忽略对在 branch1 中的行末尾添加或删除空格的行所做的更改:

git merge -Xignore-space-at-eol --no-commit --no-ff branch1

但是以下脚本在执行时演示了对尾随空格进行更改的行仍然被添加。

#!/bin/bash

# Transcribe all commands:
set -x

# Show the version I'm using:
git --version

# Create the repo and add a initial file:
cd /tmp
rm -rf scrap
mkdir scrap
cd scrap
git init
echo "// line 1 " > sample.C
echo "// line 2" >> sample.C
git add sample.C
git diff --cached | sed 's% $%EOLWS%g'
git commit -m "change 1"

# Create a new branch and add changes to it:
git checkout -b branch1
# Change an existing line by changing the whitespace at the end of one line:
sed -i 's%// line 1 %// line 1%g' sample.C
git add sample.C
# Check the whitespace was changed prior to committing:
git diff --cached | sed 's% $%EOLWS%g'
git commit -m "Add trailing whitespace"

# Check out master and merge into it, expecting no lines containing only trailing whitespace to be included:
git checkout master
git merge -Xignore-space-at-eol --no-commit --no-ff branch1
git diff --cached | sed 's% $%EOLWS%g'

以上导致以下输出。我添加了行号以供以后参考:

     1  + git --version
     2  git version 2.20.1
     3  + cd /tmp
     4  + rm -rf scrap
     5  + mkdir scrap
     6  + cd scrap
     7  + git init
     8  Initialized empty Git repository in /tmp/scrap/.git/
     9  + echo '// line 1 '
    10  + echo '// line 2'
    11  + git add sample.C
    12  + git diff --cached
    13  + sed 's% $%EOLWS%g'
    14  diff --git a/sample.C b/sample.C
    15  new file mode 100644
    16  index 0000000..42b5bc0
    17  --- /dev/null
    18  +++ b/sample.C
    19  @@ -0,0 +1,2 @@
    20  +// line 1EOLWS
    21  +// line 2
    22  + git commit -m 'change 1'
    23  [master (root-commit) 07cd37f] change 1
    24   1 file changed, 2 insertions(+)
    25   create mode 100644 sample.C
    26  + git checkout -b branch1
    27  Switched to a new branch 'branch1'
    28  + sed -i 's%// line 1 %// line 1%g' sample.C
    29  + git add sample.C
    30  + git diff --cached
    31  + sed 's% $%EOLWS%g'
    32  diff --git a/sample.C b/sample.C
    33  index 42b5bc0..4b9e635 100644
    34  --- a/sample.C
    35  +++ b/sample.C
    36  @@ -1,2 +1,2 @@
    37  -// line 1EOLWS
    38  +// line 1
    39   // line 2
    40  + git commit -m 'Add trailing whitespace'
    41  [branch1 6144b0c] Add trailing whitespace
    42   1 file changed, 1 insertion(+), 1 deletion(-)
    43  + git checkout master
    44  Switched to branch 'master'
    45  + git merge -Xignore-space-at-eol --no-commit --no-ff branch1
    46  Automatic merge went well; stopped before committing as requested
    47  + git diff --cached
    48  + sed 's% $%EOLWS%g'
    49  diff --git a/sample.C b/sample.C
    50  index 42b5bc0..4b9e635 100644
    51  --- a/sample.C
    52  +++ b/sample.C
    53  @@ -1,2 +1,2 @@
    54  -// line 1EOLWS
    55  +// line 1
    56   // line 2

第 20 行和第 37 行应出现“EOLWS”字样,但第 54 行不会出现。

我在这里做错了什么?

标签: gitmerge

解决方案


我认为您误解了“ignore-space-at-eol”背后的想法(当然,否则您不会问:))。

ignore-space-at-eol是合并策略的合并策略recursive选项。这些选项仅适用于冲突(这是重要的一点!)

您提供的 MWE 正在创建一个分支,其中包含不在 master 上的附加提交,但 master 没有任何其他提交(因此理论上它可以被快速转发,但由于--no-ff已通过,这不会发生)。

因此,在这种情况下,正在进行正常的合并。所有不在 master 中但仅在分支上的更改都合并到 master 中。由于没有冲突,所以-Xignore-space-at-eol不会生效。

如果您在两个分支中将 eol-whitespace-only-changes 更改为同一行,然后尝试合并它,它将生效,即:

$ git init
$ >file echo 'a'
$ git add file
$ git commit -m 'initial'
$ git branch feature # create a branch, but do not switch to it
$ >file echo 'a ' # add one blank
$ git add file ; git commit -m 'add one blank on master'
$ git checkout feature
$ >file echo 'a  ' # add two blank
$ git add file ; git commit -m 'add two blanks branch'
$ git checkout master ; git merge feature # you will get conflicts
$ git merge --abort # let's try that again:
$ git merge -Xignore-space-at-eol feature # no conflicts, hooray!

你看,ignore-space-at-eol是一个策略选项如何处理冲突。这并不意味着这些更改将被完全忽略。

用例:您想要合并一个与您的分支的行尾或空格不匹配的分支(想想 CRLF 与 LF)。使用此策略选项,您可以自动解决此类冲突并干净地合并更改。


推荐阅读