167

git merge行末の違いを無視することは可能ですか?

多分私は間違った質問をしている...しかし:

使用してみましたが、特に事後config.crlf inputに適用したときに、物事が少し乱雑になり、制御不能になりました。

1 つには、事後にこの構成を適用しても、このオプションを適用する前にリポジトリにコミットされたファイルには影響しないようです。もう 1 つのことは、突然、すべてのコミットで、CRLF が LF に変換されているという迷惑な警告メッセージが大量に表示されるようになったことです。

正直なところ、どの行末が使用されているかはあまり気にしません。個人的には Unix スタイル\nの方が好きですが、何でも構いません。私が気にかけているのはgit merge、少し賢くなり、改行の違いを無視することだけです。

2 つの同一のファイルがある場合もありますが、異なる行末文字を使用しているという理由だけで、git はそれらを競合しているとマークします (競合はファイル全体です)。

アップデート:

git diffがオプションを受け入れることがわかりました。このオプションも使用--ignore-space-at-eolできるようにすることはできますか?git merge

4

10 に答える 10

127

更新 2013:

最近の git バージョンは、戦略recursiveと戦略オプション( -X)を使用してマージを使用して承認します。

ただし、「-Xignore-space-change」を使用することも可能です

  • Fab-Vは次のように述べています
    git merge master -s recursive -X renormalize
    

jakub.gはまた、この戦略はチェリーピッキングでも機能するとコメントしています。

git cherry-pick abcd123456 --strategy=recursive --strategy-option=renormalize 

これは よりもはるかにうまく機能しますignore-all-space


Git 2.29 (2020 年第 4 四半期) より前では、マージ再帰機構を内部で使用するすべての「マージ」操作はmerge.renormalize構成を尊重する必要がありますが、それらの多くはそうではありませんでした。

commit 00906d6commit 8d55225commit 6f6e7cfcommit fe48efb (2020 年 8 月 3 日) by Elijah Newren ( newren)を参照してください。
( 2020 年 8 月 10 日、コミット 4339259Junio C Hamanoによってマージされました)gitster

merge:merge.renormalizeマージ機構のすべての用途に対応するようにします

署名者: Elijah Newren

マージを行うのは' merge' コマンドだけではありません。checkout -mまたは rebaseのような他のコマンドも同様です。

merge.renormalize残念ながら、" " 構成設定をチェックするコードの領域は " " だけでした。つまり、" " コマンドbuiltin/merge.cによって実行されるマージにしか影響しませんでした。merge

この構成設定の処理を に移動しmerge_recursive_config()て、他のコマンドも同様に恩恵を受けることができるようにします。


元の回答 (2009 年 5 月)

eol スタイルを無視するためのパッチが2007 年 6 月に提案されましたが、これは関係があるだけであり、関係git diff --ignore-space-at-eolありませんgit merge

その際、次のような質問がありました。

--ignore-space-at-eolのオプションにする必要がありますgit-mergeか?
マージは、この機能が重要な場所です。
これらのオプションが有効な場合の自動解決マージのセマンティクスは何ですか? それらは名前変更の検出にのみ使用されますか? または、たとえば、空白の変更のみで競合にフラグを立てませんか? そうでない場合、どのバージョンが自動的に受け入れられますか?

Julio C Hamano はまったく熱狂的ではありませんでした。

これは確かに魅力的ですが、後のラウンドに任せるべきだと思います。
1つは機械的に処理され(つまり、「git-merge-recursive」とのマージで使用され、「git-am」で適用されます)、もう1つはによって検査されます。人間が理解する。
変更された入力ファイルの比較からの出力が機械的なアプリケーションにすぐに使用できない場合でも、後者の場合には入力を変更することが役立つことがよくあります。

に関して言えば、一般的な考え方はgit merge、サードパーティのマージ ツールに依存することです。

たとえば、Git マージ用のツールとしてDiffMergeをセットアップし、そのマージ ツールが特定の種類のファイルの eol を無視できるようにするルールセットを設定しました。


MSysGit1.6.3 を使用した Windows でのセットアップ、DOS または Git bash セッションのいずれか、DiffMerge または KDiff3 を使用:

  • ディレクトリを PATH に設定します (ここでは: c:\HOMEWARE\cmd)。
  • そのディレクトリにスクリプト merge.sh (お気に入りのマージ ツールのラッパー) を追加します。

マージ.sh:

#!/bin/sh

# Passing the following parameters to mergetool:
#  local base remote merge_result

alocal=$1
base=$2
remote=$3
result=$4

if [ -f $base ]
then
    #"C:/Program Files/SourceGear/DiffMerge/DiffMerge.exe" "$alocal" "$base" "$remote" -m --result="$result" --title1="Mine" --title2="Merging to: $result" --title3="Theirs"

    # for merge respecting eol, KDiff3 is better than DiffMerge (which will always convert LF into CRLF)
    # KDiff3 will display eol choices (if Windows: CRLF, if Unix LF)
    "C:/Program Files/KDiff3/kdiff3.exe" -m "$base" "$alocal" "$remote" -o "$result"
else
    #there is not always a common ancestor: DiffMerge needing 3 files, BASE will be the result
    #"C:/Program Files/SourceGear/DiffMerge/DiffMerge.exe" "$alocal" "$result" "$remote" -m --result="$result" --title1="Mine" --title2="Merging to: $result" --title3="Theirs"
    
    # KDiff3 however does know how to merge based on 2 files (not just 3)
    "C:/Program Files/KDiff3/kdiff3.exe" -m "$base" "$remote" -o "$result"
fi
  • Git のマージ ラッパーを宣言する

Git 構成コマンド:

git config --global merge.tool diffmerge
git config --global mergetool.diffmerge.cmd "merge.sh \"$PWD/$LOCAL\" \"$PWD/$BASE\" \"$PWD/$REMOTE\" \"$PWD/$MERGED\"
git config --global mergetool.diffmerge.trustExitCode false
git config --global mergetool.diffmerge.keepBackup false
  • autoCRLF が false であることを確認する

システムレベルでの git config:

git config ---system core.autoCRLF=false
  • 2 つの行が同一である (ただし eol 文字が異なる) 場合、マージ中に DiffMerge または KDiff3 の両方がそれらの行を無視することをテストします。

DOS スクリプト (注: dos2unix コマンドは here から来ており、Unix eol スタイルをシミュレートするために使用されます。そのコマンドは、この回答の冒頭に記載されているディレクトリにコピーされています。):

C:\HOMEWARE\git\test>mkdir test_merge
C:\HOMEWARE\git\test>cd test_merge
C:\HOMEWARE\git\test\test_merge>git init
C:\HOMEWARE\git\test\test_merge>echo a1 > a.txt & echo a2 >> a.txt
C:\HOMEWARE\git\test\test_merge>git add a.txt
C:\HOMEWARE\git\test\test_merge>git commit -m "a.txt, windows eol style"
C:\HOMEWARE\git\test\test_merge>git checkout -b windows
Switched to a new branch 'windows'
C:\HOMEWARE\git\test\test_merge>echo a3 >> a.txt & echo a4 >> a.txt
C:\HOMEWARE\git\test\test_merge>git add a.txt
C:\HOMEWARE\git\test\test_merge>git commit -m "add two lines, windows eol style"
C:\HOMEWARE\git\test\test_merge>git checkout master
C:\HOMEWARE\git\test\test_merge>git checkout -b unix
Switched to a new branch 'unix'
C:\HOMEWARE\git\test\test_merge>echo au3 >> a.txt & echo au4 >> a.txt && echo au5 >> a.txt
C:\HOMEWARE\git\test\test_merge>dos2unix a.txt
Dos2Unix: Processing file a.txt ...
C:\HOMEWARE\git\test\test_merge>git add a.txt
C:\HOMEWARE\git\test\test_merge>git commit -m "add 3 lines, all file unix eol style"
[unix c433a63] add 3 lines, all file unix eol style

C:\HOMEWARE\git\test\test_merge>git merge windows
Auto-merging a.txt
CONFLICT (content): Merge conflict in a.txt
Automatic merge failed; fix conflicts and then commit the result.

C:\HOMEWARE\git\test\test_merge>git ls-files -u
100644 39b4c894078a02afb9b1dfeda6f1127c138e38df 1       a.txt
100644 28b3d018872c08b0696764118b76dd3d0b448fca 2       a.txt
100644 3994da66530b4df80189bb198dcfac9b8f2a7b33 3       a.txt

C:\HOMEWARE\git\test\test_merge>git mergetool
Merging the files: a.txt

Normal merge conflict for 'a.txt':
  {local}: modified
  {remote}: modified
Hit return to start merge resolution tool (diffmerge):

この時点で (「戻る」を押すと)、DiffMerge または KDiff3 が開き、実際にマージされる行と無視される行が表示されます。

警告: 結果ファイルは、常に DiffMerge を使用した Windows eol モード (CRLF) になります...
KDiff3 は何らかの方法で保存することを提案します。

于 2009-05-14T11:57:44.853 に答える
107

同じ答えを探していて、これを見つけまし

チェックイン/チェックアウト属性が異なるブランチのマージ

clean/smudge フィルターや text/eol/ident 属性を追加するなど、そのファイルの正規リポジトリ形式を変更する属性をファイルに追加した場合、属性が配置されていない場所で何かをマージすると、通常はマージの競合が発生します。 .

これらの不必要なマージの競合を防ぐために、3 方向のマージを解決するときに、merge.renormalize 構成変数を設定して、ファイルの 3 つのステージすべての仮想チェックアウトとチェックインを実行するように git に指示できます。これにより、変換されたファイルが変換されていないファイルとマージされるときに、チェックイン変換によって引き起こされた変更によって誤ったマージ競合が発生するのを防ぐことができます。

「smudge→clean」の結果が、すでに汚れているファイルであっても「clean」と同じ出力になる限り、この戦略はすべてのフィルター関連の競合を自動的に解決します。このように動作しないフィルターは、手動で解決する必要がある追加のマージ競合を引き起こす可能性があります。

したがって、任意のリポジトリでこのコマンドを実行すると、トリックが実行されます。

git config merge.renormalize true
于 2012-08-30T10:25:38.720 に答える
7

この回答のように: https://stackoverflow.com/a/5262473/943928

あなたは試すことができます:git merge -s recursive -Xignore-space-at-eol

于 2013-01-07T11:44:22.940 に答える
4

私がしたことは、すべてをデフォルトのままにし(つまり、autocrlf = true)、すべてのファイルに触れ(find . -exec touch {} \;)、gitにそれらを「変更済み」と見なさせてコミットし直して、それで完了です。そうしないと、煩わしいメッセージや驚くべき違いに常に悩まされるか、git のすべての空白機能を無効にする必要があります。

非難情報を失うことになりますが、遅かれ早かれそれを行う方が良いです:)

于 2009-05-14T08:10:40.983 に答える
0

マージする前に、両方のブランチの行末を正規化 (およびコミット) するのが最善の方法のように思えます。

「crlfをlfに変換」をグーグルで検索したところ、最初の結果としてこれが見つかりました:
http://stahlforce.com/dev/index.php?tool=remcrlf

私はそれをダウンロードして使用しましたが、素晴らしいツールのようです。

>sfk remcr . .py

ただし、ディレクトリとファイルの種類 (.py など) を必ず指定してください。そうしないと、.gitディレクトリの内容を台無しにしようとする可能性があります。

于 2009-05-16T03:12:15.397 に答える
0

AFAICT、(試したことはありません) を使用git diffして、マージするブランチを共通の祖先と比較し、結果をgit apply. どちらのコマンドにも --ignore-whitespace、行末と空白のエラーを無視するオプションがあります。

残念ながら、パッチが完全に適用されない場合、操作全体が中止されます。マージの競合を修正することはできません。--rejectパッチを適用できないハンクをファイルに残すオプションがあり.rejますが、これは役に立ちますが、1 つのファイルにマージの競合が表示されるのと同じではありません。

于 2010-08-23T09:49:27.900 に答える
-1

ただし、sed などのツールを使用して正しい行末を作成し、次に diff ファイルを使用することをお勧めします。私は、さまざまな行末でプロジェクトを比較するのに数時間を費やしました。

最良の方法は次のとおりです。

  1. プロジェクトファイルのみをコピーし(.gitディレクトリを省略)、別のディレクトリにリポジトリを作成し、ファイルを追加してコミットします(新しいリポジトリのマスターブランチにある必要があります)。
  2. 2 番目のプロジェクトから同じフォルダーにファイルをコピーしますが、たとえば別のブランチdev( git checkout -b dev)、このブランチでファイルをコミットして実行します (最初のプロジェクトがマスターにある場合): git diff master..dev --names-only 変更されたファイルの名前のみを表示するには
于 2015-03-18T19:33:18.137 に答える